Meta:
Composição de capas de livros minimalistas em ConTeXt, com o título no maior tamanho de fonte possível, permanecendo na caixa.
Problema:
Palavras ou linhas longas não respeitam o lado direito da caixa e continuam fora da página.
Exemplo mínimo:
eu encontreieste código de Wolfgangna lista de discussão, graças aesta respostade @aditya. (Desculpe pelo título bobo, mas queria uma palavra que soubesse que continuaria fora da página!)
\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
Compila para:
Notas:
No contexto(sem trocadilhos!)de capas de livros, estou mais preocupado em obter o tamanho máximo do texto horizontalmente do que em preencher o espaço vertical. O ideal seria definir uma altura máxima que o texto poderia ter e largura absoluta, e encaixar o texto dentro, alinhado ao topo. Se o texto não ocupar o espaço vertical máximo, tudo bem.
Responder1
A configuração é um pouco mais complicada neste caso porque temos que criar um algoritmo completamente novo aqui. Aquele que você postou compõe o material em uma caixa e percorre o tamanho da fonte (aumentando) até atingir uma certa altura. Aqui queremos compor coisas em uma caixa, examinar se ela é muito larga ediminuiro tamanho da fonte. Isso significa que começamos com um tamanho de fonte ridiculamente grande (escolhi 100pt).
Agora o problema é que definimos coisas em um vbox com largura fixa ( \textwidth
para simplificar). Como sabemos se uma linha é muito larga? Victor Eijkhout apresentou um método para isso em seu livroTeX por tópicoque ele chamou \eatlines
. Adaptei isso para medir a largura da linha e definir um valor booleano dependendo se a largura foi atendida ou não. A única coisa que resta a fazer é percorrer o tamanho da fonte (aqui em passos de 1 ponto, diminuindo). Eu também trato do caso de o tamanho da fonte diminuir abaixo de 0pt, caso em que o conteúdo nunca caberá na caixa (o que não deveria acontecer), mas deixar de fora esse caso resultaria em um loop infinito.
\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
Saída (com \showboxes
):
O ConTeXt torna muito fácil adicionar uma interface abrangente de valores-chave para que você possa usar coisas como
\startcover[width=2in]
Mary Poppins Sings Supercalifragilisticexpialidocious
\stopcover
\definecover[whatever][maxsize=200pt]
\setupcover[whatever][stepsize=5pt]
\startwhatever[width=4in]
Mary Poppins Sings Supercalifragilisticexpialidocious
\stopwhatever
Isso pode parecer um pouco exagerado, mas pode-se ir além e colocar o material em um módulo, então você só precisa fazer isso \usemodule[cover]
e está pronto. Salve o seguinte como t-cover.mkiv
em seu diretório de trabalho.
\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
Então seu arquivo principal seria lido
\usemodule[cover]
\starttext
\startcover
Mary Poppins Sings Supercalifragilisticexpialidocious
\stopcover
\stoptext
Responder2
Se você não se importa em quebrar linhas manualmente (não deve ser um grande problema para páginas de rosto) e se você não se importa com o uso do tamanho óptico errado (muito poucas fontes alteram os glifos de acordo com o tamanho da fonte), você pode simplesmente compor a caixa e dimensioná-la adequadamente. Por exemplo:
\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