# Insert text into a fixed size box

Is there a way to create a box which has fixed width and height? I tried \parbox and some similar things, but sometimes the text overflows.

If the text inserted would overflow: it should be resized to fit or it should be clipped (with a warning). Is any of these possible?

We can assume, that the inserted text is one continous paragraph.

-
Can you show us an example of \parbox when the text overflows? You should get an overfull hbox message in that case. –  Qrrbrbirlbel Nov 10 '13 at 22:52
–  egreg Nov 10 '13 at 23:24
There is always \resizebox –  John Kormylo Nov 11 '13 at 0:47
@Qrrbrbirlbel the overflow is vertical: \parbox[t][2cm][t]{2cm}{\lipsum[1]} - and there is no warning here. –  masu Nov 11 '13 at 8:48
–  Steven B. Segletes Nov 13 '13 at 17:18

You can use the fitting library of the tcolorbox package. It provides a macro called \tcboxfit which fits the font size of the content to the dimensions of the box. Alternatively, the option fit for tcolorbox does the same trick.

Note that the used font has to be resizable to all dimensions (vector font) to achieve the correct resizing.

The first example shows a framed box (can be adapted in many ways), the second one a box without a frame (the red border is just for displaying the size), the third example displays a box with title and fixed height.

\documentclass[a4paper]{article}
\usepackage[many]{tcolorbox}
\usepackage{lmodern}% or any other vector / postscript font
\usepackage{lipsum}
\begin{document}

\tcboxfit[width=6cm,height=6cm,nobeforeafter,
before=\noindent]{\lipsum[1]}
%
%
\begin{tcolorbox}[fit,width=6cm,height=6cm,blank,
borderline={0.4pt}{0pt}{red!20!white},
watermark text={6cm $\times$ 6cm},nobeforeafter]
\lipsum[1]
\end{tcolorbox}

\bigskip

\tcboxfit[height=6cm,title={This box has a height of 6cm},
colback=blue!5!white,colframe=blue!30!black,
before=\noindent]{\lipsum[1]}

\end{document}


-
Do you happen to know anything about the algorithm? Execution seems to quite slow with a number of bad boxes... :( I think I might have to implement my own fitting algorithm. –  masu Nov 12 '13 at 1:57
Hm... I have to quote my doctor father: 'There is no free lunch'. You have to pay for the automatic sizing with compilation time. The algorithm is a bisection method which (by experiment) usally does not need more than a dozen steps. The option fix maxstep allows to control the maximal step number (20 by default). Since the objective function is not smooth (because of line breaks) I doubt that some kind of Newton method will give stable and faster results. But, maybe, for your special application there is a faster algorithm (?). –  Thomas F. Sturm Nov 12 '13 at 9:18
I'd hoped for free breakfast only, and I've been served. :) I have my plans, but the implementation has to wait for a while... Thanks for this answer again anyway, it's a good-to-know-about feature. –  masu Nov 12 '13 at 9:30
I've got around fitting iterations with the use of a calculation and a resize. Posted it as an answer. –  masu Nov 12 '13 at 21:19

Using tikz or pstricks you can clip a portion of a graphics.

Here's an example using tikz:

\documentclass{article}
\usepackage[margin=0.5in]{geometry}
\usepackage{tikz}
\usetikzlibrary{calc}
\pagestyle{empty}
\usepackage{lipsum}
\begin{document}

\fbox{\begin{minipage}[t][4in]{3in}
\lipsum[1-3]
\end{minipage}}
%%
\hspace*{\fill}vs.\hspace*{\fill}
%%
\begin{tikzpicture}[baseline=(myparbox.base)]
\node (A) at (0,0)      {};
\node (B) at (3in,4in)  {};

%\draw ($(A)-(2pt,2pt)$) rectangle ($(B)+(2pt,2pt)$);
\clip ($(A)-(2pt,2pt)$) rectangle ($(B)+(2pt,2pt)$);

\node[below right,
inner sep=0pt,
outer sep=0pt,
text width=+3in,
align=justify] (myparbox) at (A|-B)
{\lipsum[1-3]};
\end{tikzpicture}

\end{document}


Here's a similar example using pstricks:

\documentclass{article}
\usepackage[margin=0.5in]{geometry}
\usepackage{pstricks,pst-node}
\usepackage{lipsum}
\begin{document}

\fbox{\begin{minipage}[t][4in]{3in}
\lipsum[1-3]
\end{minipage}}
%%
\hspace*{\fill}vs.\hspace*{\fill}
%%
\begin{psclip}{\psline[linestyle=none](0,3ex)(3in,3ex)(3in,-\dimexpr4in-1ex\relax)(0,-\dimexpr4in-1ex\relax)}
\begin{minipage}[t]{3in}
\lipsum[1-3]
\end{minipage}
\end{psclip}

\end{document}

-
The text width options does install a minipage on its own. So you can just do \node[below right, text width=+3in] at (A|-B) {\lipsum[1-3]};. –  Qrrbrbirlbel Nov 10 '13 at 22:55
@Qrrbrbirlbel Thanks for your comment, but when I try text width=+3in, the linebreaks are not consistent with that produced using a minipage set to the same width. Do you know why? –  A.Ellett Nov 10 '13 at 23:02
If I add align=justify, they are the same. –  Qrrbrbirlbel Nov 10 '13 at 23:17
Thanks. For the record: clipping warning can be generated by measuring the size using this answer. –  masu Nov 11 '13 at 8:57

I've made my own solution, without iterations. Can still be improved with some iterations or similar. epsilon is for tweaking, and \fitfuzz defines the warning threshold.

\documentclass{article}

\usepackage[latin]{babel} % demo only: for hyphenation in lipsum
\usepackage{lipsum} % demo only
\usepackage[demo]{graphicx}
\usepackage{lmodern}
\usepackage[nomessages]{fp}

\newsavebox{\mybox}
\newlength{\actheight}
\newlength{\prefwidth}
\newlength{\prefheight}

\def\fitfuzz{1000} % hundredth of a percent

\newlength{\scaleepsilon}
\setlength{\scaleepsilon}{0pt}

\makeatletter
\def\fitbox#1#2#3{%
\setlength{\prefwidth@fitbox}{#1}%
\setlength{\prefheight@fitbox}{#2}%
\setlength{\actheight@fitbox}{\the\dimexpr\ht\mybox@fitbox+\dp\mybox@fitbox}%
\edef\valueA{\strip@pt\prefwidth@fitbox}%
\edef\valueB{\strip@pt\prefheight@fitbox}%
\edef\valueBx{\strip@pt\actheight@fitbox}%
\edef\valueE{\strip@pt\scaleepsilon@fitbox}%
\FPeval\valueAx{pow(0.5,\valueBx*\valueA*\valueA/\valueB)+\valueE}%
\setlength{\actheight@fitbox}{\the\dimexpr\ht\mybox@fitbox+\dp\mybox@fitbox}%
\edef\valueBx{\strip@pt\actheight@fitbox}%
\fi%
\resizebox{\prefwidth@fitbox}{\prefheight@fitbox}{\parbox[b]{\valueAx pt}{#3}}%
}
\makeatother

\begin{document}

\fitbox{3cm}{5cm}{\lipsum[1]}\includegraphics[width=3cm, height=5cm]{}

\includegraphics[width=3cm, height=5cm]{}

\fitbox{4cm}{3cm}{\lipsum[2]}\includegraphics[width=4cm, height=3cm]{}

\includegraphics[width=4cm, height=3cm]{}

\end{document}


Thanks to the answer of egreg.

-
Just to do some nitpicking: I would count this solution as 3 iterations since 3 parboxes are constructed, plus a resizebox which may be cheaper(?). But, of course, it is faster than doing more iterations (8 or 10) without resizebox :-) –  Thomas F. Sturm Nov 13 '13 at 8:54
@ThomasF.Sturm agreed. And I like the that there are no Underfull and Overfull \hbox messages when it's unnecessary. –  masu Nov 13 '13 at 8:57
Yes, you are right. The unnecessary messages are removed with tcolorbox version 2.60 (2013/12/17) ... :-). –  Thomas F. Sturm Dec 18 '13 at 8:37
@ThomasF.Sturm thanks for the info. I haven't noticed until now that you are the package maintainer. :) –  masu Dec 18 '13 at 9:10