I would like to fit text (potentially several paragraphs) into a box of given size. This should be done by adjusting the fontsize of the contained text.
Clarification edit: The given dimensions are the maximum space the result should occupy. There is no need to fill the box fully, but under no circumstances should the dimensions be exceeded.
Something like
\fitbox{<width>}{<height}{Some text to be squeezed into a box \par With paragraphs}
or
\begin{fitbox}{<width>}{<height>}
Some text to be squeezed into a box
With paragraphs
\end{fitbox}
There are a number of questions here that ask the same in the title, but then only target to constrain the width or the height. I want to constrain both. Also, I would like the text only the be adjusted in the fontsize, not scaled disproportionally in one direction.
@TH solves this for another question by fitting text on a page. Unfortunately, my TeX knowledge is too limited to adapt that to a box. See here: Fitting and centering text (both!) in a constrained area For a page-fitting, his solution looks great to me. Maybe that's a starting point.
Edit: comparing the solutions from Werner and Martin
I've used XeLaTeX from TeXLive 2011 to compare the solutions from Werner and Martin below. The font is a TrueType Times New Roman vector font. The fitbox
es are contained in a framebox
to help comparison.
Case 1 is a box of 2cm x 2cm. Case 2 is the same text in a box of 8cm x 2cm.
Both boxes can be stacked next to each other horizontally and only consume the space they should. However, in Case 1 the box with Martin's approach is too high, while Werner's box fits the content correctly.
Edit 2: some more tests show: both suggestions can fail
After some more tests, the case illustrated below fails for both suggestions from Werner and Martin. That means, the question is still open.
As Werner points out in a comment to his answer, the reason is that TeX cannot hyphenate the pattern. At the same time, it finds it acceptable to set it into the box and run over the edge.
After some research I believe that the algorithm after each line would have to check for \badness
and if that exceeds 10000 reduce the font size further. At least the TeX pearl from Paweł Jackowski points in that direction.
Has anyone the insights and experience to put these pieces and the excellent work from Werner and Martin together into something that works and really stays inside the given box?
Edit 3: Another idea that might help to solve this
Another approach that might help would be a way to measure the width of the longest word (or box) of the paragraph, let's say it is wl. The associated font size is f. The maximum desired box width as given by the user is wmax.
Then, the upper bound for the font size could be calculated by
fmax = f * wmax / wl
This, of course, assumes that everything works out proportionally, which probably isn't entirely true considering inter word and inter character spacing. But it should be sufficiently good to keep the text in the fitbox
horizontally.
Since this can only shrink the fontsize (it's an upper bound), the vertical condition if met before would still be met afterwards. That means, this could be applied after the suggestion of @Werner as a check and adjustment if required.
Does anyone have the TeX experience to stick that in?
Best Answer
Using the suggestion in Fitting and centering text (both!) in a constrained area, together with Martin's answer that uses the
environ
package, the following provides the environmentwhich typesets
<stuff>
using a form of binary search to fit the text within the given height<height>
while under a fixed width<width>
constraint set by aminipage
. This is required in order to maintain a proportionate scaling of the font and leading (\baselineskip
).In the figure below, two pages are typeset, each starting with
\lipsum[1]
and ending with\lipsum[2]
to provide some frame of reference. The left page has afitbox
of dimension.5\textwidth x .5\textwidth
while the page on the right is set at300pt x 300pt
(square).Interestingly enough, I'm having trouble compiling this under TeXLive 2011. Although, there is no problem compiling it using the online LaTeX compiler ScribTeX, which runs TeXLive 2009. I don't know what the cause behind this is...This has been fixed by the replacement of\protected@edef\stuff{\BODY}
with\def\stuff{\BODY}
. The original code used this form since it provided two macros - one for parsing the content (called\fillthepage{<stuff>}
) and another for updating a resized version of the content (called\buildbox
). I assume the coding structure required this. However, with everything contained in a singleenviron
mentfitbox
above, this is not needed anymore.