10

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.

Related: Package for game/playing cards (not only poker)

6

3 Answers 3

10

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}

enter image description here

4
  • 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
    Commented Nov 12, 2013 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 (?). Commented Nov 12, 2013 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
    Commented Nov 12, 2013 at 9:30
  • I've got around fitting iterations with the use of a calculation and a resize. Posted it as an answer.
    – masu
    Commented Nov 12, 2013 at 21:19
3

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}

enter image description here

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}
4
  • 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]};. Commented Nov 10, 2013 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
    Commented Nov 10, 2013 at 23:02
  • If I add align=justify, they are the same. Commented Nov 10, 2013 at 23:17
  • Thanks. For the record: clipping warning can be generated by measuring the size using this answer.
    – masu
    Commented Nov 11, 2013 at 8:57
2

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.

enter image description here

\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}%
\sbox{\mybox@fitbox}{\hbadness=10000\parbox[b]{\prefwidth@fitbox}{#3}}%
\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}%
\sbox{\mybox@fitbox}{\hbadness=10000\parbox{\valueAx pt}{#3}}%
\setlength{\actheight@fitbox}{\the\dimexpr\ht\mybox@fitbox+\dp\mybox@fitbox}%
\edef\valueBx{\strip@pt\actheight@fitbox}%
\FPeval\badness{round(10000*abs(1-\valueBx/\valueAx/\valueB*\valueA):0)}%
\FPifgt{\badness}{\fitfuzz}%
    \@latex@warning{Notably inaccurate fitting (badness \badness)}%
\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.

4
  • 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 :-) Commented Nov 13, 2013 at 8:54
  • @ThomasF.Sturm agreed. And I like the that there are no Underfull and Overfull \hbox messages when it's unnecessary.
    – masu
    Commented Nov 13, 2013 at 8:57
  • 1
    Yes, you are right. The unnecessary messages are removed with tcolorbox version 2.60 (2013/12/17) ... :-). Commented Dec 18, 2013 at 8:37
  • @ThomasF.Sturm thanks for the info. I haven't noticed until now that you are the package maintainer. :)
    – masu
    Commented Dec 18, 2013 at 9:10

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .