Passen Sie die Schriftgröße an, damit lange Wörter in die Vbox passen

Passen Sie die Schriftgröße an, damit lange Wörter in die Vbox passen

Ziel:
Satz minimalistischer Buchcover in ConTeXt, wobei der Titel in der größtmöglichen Schriftgröße verwendet wird, aber dennoch im Rahmen bleibt.

Problem:
Lange Wörter oder Zeilen respektieren die rechte Seite des Felds nicht und gehen über die Seite hinaus.

Minimales Beispiel:
ich fanddieser Code von Wolfgangauf der Mailingliste, danke andiese Antwortvon @aditya. (Entschuldigen Sie den albernen Titel, aber ich wollte ein Wort, von dem ich wusste, dass es auch über die Seite hinaus Bestand haben würde!)

\newbox\cover
\newdimen\coverheight \coverheight= 4in
\newdimen\coverwidth  \coverwidth = 7in
\newdimen\coverfont   \coverfont  = 12pt
\newdimen\fontstep    \fontstep   = 1pt

\def\startcover
  {\dostartbuffer[cover][startcover][stopcover]}

\def\stopcover
  {\setups[cover:place]}

\def\boxsize
  {\setbox\cover\vbox
     {\hsize\coverwidth
      \definedfont[Serif at \the\coverfont]\setupinterlinespace
      \setupalign[nothyphenated]
      \emergencystretch\maxdimen
      \getbuffer[cover]}}

\def\covertext
  {\boxsize\doloop
     {\boxsize
      \ifdim\ht\cover>\coverheight
        \global\advance\coverfont-\fontstep
        \exitloop
      \else
        \global\advance\coverfont\fontstep
      \fi}}

\startsetups[cover:place]
  \covertext
  \boxsize
  \vbox to\coverheight{\box\cover}
\stopsetups

\starttext

\startcover
\strut Mary Poppins Sings Supercalifragilisticexpialidocious
\stopcover

\stoptext

Kompiliert zu:
Bildbeschreibung hier eingeben Anmerkungen:
Im Kontext(kein Wortspiel beabsichtigt!)Bei Buchumschlägen ist mir die horizontale maximale Textgröße wichtiger als das Ausfüllen des vertikalen Raums. Ideal wäre es, eine maximale Höhe und absolute Breite für den Text festzulegen und den Text oben ausgerichtet darin einzufügen. Wenn der Text nicht den maximalen vertikalen Raum einnimmt, ist das in Ordnung.

Antwort1

Das Setup ist in diesem Fall etwas komplizierter, da wir uns hier einen völlig neuen Algorithmus ausdenken müssen. Der von Ihnen gepostete Algorithmus setzt Dinge in eine Box und durchläuft die Schriftgröße (zunehmend), bis eine bestimmte Höhe erreicht ist. Hier wollen wir Dinge in eine Box setzen, prüfen, ob sie zu breit ist undverringerndie Schriftgröße. Das bedeutet, dass wir von einer lächerlich großen Schriftgröße ausgehen (ich habe 100pt gewählt).

Das Problem ist nun, dass wir die Inhalte in einer Vbox auf eine feste Breite einstellen ( \textwidthder Einfachheit halber). Woher wissen wir, ob eine Zeile zu breit ist? Victor Eijkhout hat in seinem Buch eine Methode dafür vorgestellt.TeX nach Themadie er nannte \eatlines. Ich habe dies angepasst, um die Breite der Linie zu messen und einen booleschen Wert festzulegen, je nachdem, ob die Breite erreicht wird oder nicht. Das einzige, was noch zu tun bleibt, ist, die Schriftgröße zu durchlaufen (hier in Schritten von 1pt, abnehmend). Ich behandle auch den Fall, dass die Schriftgröße unter 0pt abnimmt, in welchem ​​Fall der Inhalt niemals in das Feld passen kann (was nicht passieren sollte), aber diesen Fall wegzulassen würde dann zu einer Endlosschleife führen.

\newdimen\coverwidth  \coverwidth = \textwidth
\newdimen\coverfont   \coverfont  = 100pt
\newdimen\fontstep    \fontstep   = 1pt
\newconditional\widthmet

\def\startcover
  {\dostartbuffer[cover][startcover][stopcover]}

\def\stopcover
  {\setups[cover:place]}

\def\eatlines{%
  \global\settrue\widthmet
  \setbox\scratchboxone=\lastbox
  \ifvoid\scratchboxone\else
    \unskip\unpenalty
    {\eatlines}%
    \copy\scratchboxone
    \setbox\scratchboxtwo=\hbox{\unhbox\scratchboxone}%
    \ifdim\wd\scratchboxtwo>\coverwidth
      \global\setfalse\widthmet
    \fi
  \fi
}

\startsetups cover:place
  \start\dontcomplain
  \doloop{%
    \setbox\scratchbox=\vbox{\hsize=\coverwidth
      \definedfont[Serif at \the\coverfont]\setupinterlinespace
      \setupalign[nothyphenated]\emergencystretch\maxdimen
      \getbuffer[cover]%
      \par\eatlines
    }%
    \ifconditional\widthmet
      \box\scratchbox
      \exitloop
    \else
      \global\advance\coverfont by -\fontstep
    \fi
    \ifdim\coverfont<0pt
      \exitloop
    \fi
  }
  \stop
\stopsetups

\starttext

\startcover
Mary Poppins Sings Supercalifragilisticexpialidocious
\stopcover

\stoptext

Ausgabe (mit \showboxes):

Bildbeschreibung hier eingeben

ConTeXt macht es ganz einfach, eine umfassende Schlüssel-Wert-Schnittstelle hinzuzufügen, so dass Sie Dinge wie

\startcover[width=2in]
  Mary Poppins Sings Supercalifragilisticexpialidocious
\stopcover

\definecover[whatever][maxsize=200pt]
\setupcover[whatever][stepsize=5pt]
\startwhatever[width=4in]
  Mary Poppins Sings Supercalifragilisticexpialidocious
\stopwhatever

Das mag etwas übertrieben erscheinen, aber man könnte sogar noch weiter gehen und das Zeug in ein Modul packen, dann müsste man nur noch tun \usemodule[cover]und schon wäre man fertig. Speichern Sie das Folgende als t-cover.mkivin Ihrem Arbeitsverzeichnis.

\startmodule[cover]
\unprotect

\installcorenamespace{cover}
\installcommandhandler \??cover {cover} \??cover

\startinterface all
  \setinterfaceconstant {maxsize}  {maxsize}
  \setinterfaceconstant {stepsize} {stepsize}
\stopinterface

\appendtoks
  \setuevalue{\e!start\currentcover}{\cover_start[\currentcover]}%
  \setuvalue {\e!stop\currentcover}{\cover_process}%
\to \everydefinecover

\setupcover[
  \c!width=\textwidth,
  \c!maxsize=100pt,
  \c!stepsize=1pt,
]

\unexpanded\def\cover_start
  {\bgroup\obeylines\dodoubleargument\cover_start_indeed}

\starttexdefinition cover_start_indeed [#1][#2]
  \egroup
  \edef\currentcover{#1}
  \setupcover[#1][#2]
  \grabbufferdata[coverbuffer][start#1][stop#1]
\stoptexdefinition

\unexpanded\def\cover_process{%
  \start\dontcomplain
  \scratchdimen=\coverparameter\c!maxsize
  \doloop{%
    \setbox\scratchbox=\vbox{\hsize=\coverparameter\c!width
      \definedfont[Serif at \the\scratchdimen]\setupinterlinespace
      \setupalign[nothyphenated]\emergencystretch\maxdimen
      \getbuffer[coverbuffer]%
      \par\eatlines
    }%
    \ifconditional\scratchcounter
      \box\scratchbox
      \exitloop
    \else
      \global\advance\scratchdimen by -\coverparameter\c!stepsize
    \fi
    \ifdim\scratchdimen<0pt
      \exitloop
    \fi
  }%
  \stop
}

\def\eatlines{%
  \global\settrue\scratchcounter
  \setbox\scratchboxone=\lastbox
  \ifvoid\scratchboxone\else
    \unskip\unpenalty
    {\eatlines}%
    \copy\scratchboxone
    \setbox\scratchboxtwo=\hbox{\unhbox\scratchboxone}%
    \ifdim\wd\scratchboxtwo>\coverparameter\c!width
      \global\setfalse\scratchcounter
    \fi
  \fi
}

\definecover[cover]

\protect
\stopmodule

Dann würde Ihre Hauptdatei lauten

\usemodule[cover]

\starttext

\startcover
  Mary Poppins Sings Supercalifragilisticexpialidocious
\stopcover

\stoptext

Antwort2

Wenn es Ihnen nichts ausmacht, Zeilenumbrüche manuell vorzunehmen (was bei Titelseiten kein großes Problem sein sollte) und wenn es Ihnen nichts ausmacht, dass die falsche optische Größe verwendet wird (nur sehr wenige Schriftarten ändern die Glyphen entsprechend der Schriftgröße), können Sie das Feld einfach setzen und entsprechend skalieren. Beispiel:

\define[1]\FitBox
    {\scale[width=10cm,height=5cm,factor=max]{\framed[align=normal]{#1}}}


\starttext
\FitBox{Mary \\ Poppins Sings \\ Supercalifragilisticexpialidocious}

\FitBox{A \\ B \\ C \\ D \\ E \\ F \\ G \\ H \\ I \\ J \\ K \\ L \\ M \\ N}

\stoptext

verwandte Informationen