目標:
在 ConTeXt 中排版簡約的書籍封面,標題採用盡可能最大的字體大小,同時保留在框框中。
問題:
長單字或行不符合框的右側並繼續離開頁面。
最小範例:
我發現這段程式碼來自沃夫岡在郵件列表中,感謝這個答案來自@aditya。 (抱歉這個愚蠢的標題,但我想要一個我知道會在頁面之外繼續出現的單字!)
\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
編譯為:
筆記:
在上下文中(沒有雙關語的意思!)對於書籍封面,我更關心水平方向的最大文字大小而不是填充垂直空間。理想的情況是設定文字的最大高度和絕對寬度,並將文字放入內部,與頂部對齊。如果文字不佔據最大垂直空間,那也沒關係。
答案1
在這種情況下,設定有點複雜,因為我們必須在這裡提出一個全新的演算法。您發布的內容將排版在一個框中,並循環字體大小(增加),直到達到一定的高度。這裡我們想要在一個盒子裡排版東西,檢查它是否太寬並且減少字體大小。這意味著我們從一個大得離譜的字體開始(我選擇了 100pt)。
現在的問題是,我們在 vbox 中以固定寬度設定內容(\textwidth
為了簡單起見)。我們如何知道一條線是否太寬? Victor Eijkhout 在他的書中提出了一個方法TeX 按主題他稱之為\eatlines
。我調整它來測量線的寬度,並根據寬度是否滿足設定一個布林值。剩下要做的唯一一件事就是循環遍歷字體大小(這裡以 1pt 為步長,遞減)。我還處理字體大小減小到 0pt 以下的情況,在這種情況下,內容永遠無法放入框中(這不應該發生),但忽略這種情況將導致無限循環。
\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
輸出(含\showboxes
):
ConTeXt 讓在其中添加全面的鍵值介面變得非常容易,因此您可以使用諸如
\startcover[width=2in]
Mary Poppins Sings Supercalifragilisticexpialidocious
\stopcover
\definecover[whatever][maxsize=200pt]
\setupcover[whatever][stepsize=5pt]
\startwhatever[width=4in]
Mary Poppins Sings Supercalifragilisticexpialidocious
\stopwhatever
這可能看起來有點誇張,但我們甚至可以更進一步,將這些東西放入一個模組中,所以您只需要這樣做就可以了\usemodule[cover]
。將以下內容儲存t-cover.mkiv
在您的工作目錄中。
\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
然後你的主文件將讀取
\usemodule[cover]
\starttext
\startcover
Mary Poppins Sings Supercalifragilisticexpialidocious
\stopcover
\stoptext
答案2
如果您不介意手動換行(對於封面來說應該不是什麼大問題),並且如果您不介意使用錯誤的光學尺寸(很少有字體根據字體大小改變字形),您可以簡單地排版框並適當縮放它。例如:
\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