Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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)

share|improve this question
    
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
1  
    
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
1  

3 Answers 3

up vote 5 down vote accepted

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

share|improve this answer
    
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}

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}
share|improve this answer
    
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.

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.

share|improve this answer
    
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
1  
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

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.