How to fit text in a box of given size?

To duplicate the answer I gave on the LaTeX Community site...

You could try \resizebox from the graphicx package. See its documentation, page 7:

\resizebox{1in}{!}{Some text}

This will give "Some text" which is exactly 1 inch long. The ! for the second argument means to vary the height by whatever it needs to in order to maintain the aspect ratio. If you did {!}{1in} it would be 1 inch tall instead. If you specify both parameters, it'll be stretched disproportionally so that it is exactly a rectangle of that size, and so on.


That's a lot of questions at once. I'll answer some of the easy ones, leaving the trickier aspects to others.

To typeset text in a box of a given width, use either

\makebox[width][s]{lorem ipsum dolor} % latex, or
\hbox to width{lorem ipsum dolor} % plain tex

where width is to be replaced by the desired width, of course. It will only stretch interword spaces, though, and not interglyph spacing. The latter is impossible in standard TeX without some macro trickery (which might involve taking the text apart and sticking stretchable spaces between the glyphs before putting it back together).

The answer from frabjous (just in) is good if you run a TeX engine such as pdftex where such resizing is supported by the graphics package. Otherwise, a possibility would be to measure the text when set in a standard box, then computing the appropriate font size for the box you want to fit it in, then typeset it using the font at that size. But again, standard TeX won't let you scale the font differently in the horizontal and vertical directions. The computation requires dividing one length by another: The only way I know of to do this requires a bit of plain TeX: Assign both lengths to count registers (which will receive the length in scaled points (sp)) and divide one by the other. But this produces an integer, so you need to rescale if you wish more accuracy. It gets involved rather quickly, especially since the rescaling can result in an overflow if overdone.Here is a quick hack, using some of latex's built-in temporary registers:

\documentclass{article}
\makeatletter
\newcommand{\scalehelper}[4][64]{%
  \@tempdima=#3\relax
  \multiply\@tempdima by #1
  \@tempcnta=\@tempdima
  \@tempdimb=#4\relax
  \@tempcntb=\@tempdimb
  \divide\@tempcnta by \@tempcntb
  \multiply#2 by \@tempcnta
  \divide#2 by #1
}
\makeatother
\begin{document}
\newlength{\foo}
\setlength{\foo}{12pt}
\scalehelper[128]{\foo}{80pt}{30pt}
\showthe\foo
\end{document}

Ideally, the new value of \foo should be 32pt; in reality, it is 31.96875pt. If you crank the optional argument of \scalehelper up, you increase the accuracy. Scale it up too much, and you get arithmetic overflow. But an accuracy on the order of a percent should be good enough for selecting a suitable fontsize. (You get the rest of the way by typesetting in a box of specified width, letting the interword spaces compensate for any inaccuracy.)

This is just an idea. Some assembly required. Batteries not included.


Couple of ConTeXt solutions:

  • If you are willing to break lines manually, you can just say

    \hbox to 7cm {\stretched{Some Text}}
    

    and play around with the settings

    \def\stretchedspacefactor{4}
    \def\stretchedspaceamount{.25em}
    \def\stretchedbreaktokens{.@/}
    

    to change the amount of intercharacter and interword separation.

  • If you want line breaks, and are only interested in rectangular boxes, Wolfgang Schuster posted a solution on the ConTeXt mailing list that loops over the value of the font size until the height equals to the desired height

  • If you also want line breaks to occur at any location (and not just interword boundaries), ConTeXt wiki has a solution.

  • And if you want non-rectangular shapes with line breaks, Hans Hagen posted a solution as a This Way magazine.