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 environment
\begin{fitbox}{<width>}{<height>}
<stuff>
\end{fitbox}
which 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 a minipage
. This is required in order to maintain a proportionate scaling of the font and leading (\baselineskip
).
\documentclass{article}
\usepackage{lmodern}
\usepackage{environ}% http://ctan.org/pkg/environ
\usepackage{lipsum}% http://ctan.org/pkg/lipsum
\newdimen\fontdim
\newdimen\upperfontdim
\newdimen\lowerfontdim
\newif\ifmoreiterations
\fontdim12pt
\makeatletter
\NewEnviron{fitbox}[2]{% \begin{fitbox}{<width>}{<height>} stuff \end{fitbox}
\def\buildbox{%
\setbox0\vbox{\hbox{\minipage{#1}%
\fontsize{\fontdim}{1.2\fontdim}%
\selectfont%
\stuff%
\endminipage}}%
\dimen@\ht0
\advance\dimen@\dp0
}
\def\stuff{\BODY}% Store environment body
\buildbox
% Compute upper and lower bounds
\ifdim\dimen@>#2
\loop
\fontdim.5\fontdim % Reduce font size by half
\buildbox
\ifdim\dimen@>#2 \repeat
\lowerfontdim\fontdim
\upperfontdim2\fontdim
\fontdim1.5\fontdim
\else
\loop
\fontdim2\fontdim % Double font size
\buildbox
\ifdim\dimen@<#2 \repeat
\upperfontdim\fontdim
\lowerfontdim.5\fontdim
\fontdim.75\fontdim
\fi
% Now try to find the optimum size
\loop
%\message{Bounds: \the\lowerfontdim\space
% \the\fontdim\space \the\upperfontdim^^J}
\buildbox
\ifdim\dimen@>#2
\moreiterationstrue
\upperfontdim\fontdim
\advance\fontdim\lowerfontdim
\fontdim.5\fontdim
\else
\advance\dimen@-#2
\ifdim\dimen@<10pt
\lowerfontdim\fontdim
\advance\fontdim\upperfontdim
\fontdim.5\fontdim
\dimen@\upperfontdim
\advance\dimen@-\lowerfontdim
\ifdim\dimen@<.2pt
\moreiterationsfalse
\else
\moreiterationstrue
\fi
\else
\moreiterationsfalse
\fi
\fi
\ifmoreiterations \repeat
\box0% Typeset content
}
\makeatother
\begin{document}
\lipsum[1]
\begin{fitbox}{.5\textwidth}{0.5\textheight}
\lipsum[1-2]
\end{fitbox}
\lipsum[2]
\clearpage
\lipsum[1]
\begin{fitbox}{300pt}{300pt}
\lipsum[1-2]
\end{fitbox}
\lipsum[2]
\end{document}
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 a fitbox
of dimension .5\textwidth x .5\textwidth
while the page on the right is set at 300pt 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 single environ
ment fitbox
above, this is not needed anymore.
For the sizes, you can use the current bounding box
together with \pgfgetlastxy
:
\documentclass{standalone}
\usepackage{tikz}
\newcommand*{\ExtractCoordinate}[3]{\path (#1); \pgfgetlastxy{#2}{#3};}%
\newdimen\tlx
\newdimen\tlx
\newdimen\brx
\newdimen\bry
\begin{document}
\begin{tikzpicture}
\draw (-3,-1) rectangle (3,1) (-2,-2) rectangle (2,2);
\foreach \x in {north west,south west,south east,north east}
{ \fill[red] (current bounding box.\x) circle (0.01);
}
\ExtractCoordinate{current bounding box.north west}{\tlx}{\tly}
\ExtractCoordinate{current bounding box.south east}{\brx}{\bry}
\pgfmathsetmacro{\myheight}{(+\tly-\bry)/28.452755}
\pgfmathsetmacro{\mywidth}{(-\tlx+\brx)/28.452755}
\node[below right] at (-2,1) {height: \myheight\ cm};
\node[above left] at (2,-1) {width: \mywidth\ cm};
\end{tikzpicture}
\end{document}
Edit 1: Ah, now I get it. Here is a still not automatic version. You set two commands in each tikzpicture
:
\maximumdimensions{4}{3}
, which is the desired width and height, at the beginning of the picture.
\getscalingfactors
which will draw nodes with a recommended scaling factor in the middle of your picture if the image if to high/wide:
\documentclass{scrartcl}
\usepackage{tikz}
\usepackage{lipsum}
\usepackage{xifthen}
\newcommand*{\ExtractCoordinate}[3]{\path (#1); \pgfgetlastxy{#2}{#3};}%
\newdimen\tlx
\newdimen\tlx
\newdimen\brx
\newdimen\bry
\def\xscalefactor{}
\def\yscalefactor{}
\parindent0mm
\newcommand{\getscalingfactors}{%
\ExtractCoordinate{current bounding box.north west}{\tlx}{\tly}
\ExtractCoordinate{current bounding box.south east}{\brx}{\bry}
\pgfmathsetmacro{\myheight}{(+\tly-\bry)/28.452755}
\pgfmathsetmacro{\mywidth}{(-\tlx+\brx)/28.452755}
\pgfmathsetmacro{\xsf}{\maxwidth/\mywidth}
\pgfmathsetmacro{\ysf}{\maxheight/\myheight}
\global\edef\xscalefactor{\xsf}
\global\edef\yscalefactor{\ysf}
\pgfmathtruncatemacro{\xsfc}{\xsf*10000}
\pgfmathtruncatemacro{\ysfc}{\ysf*10000}
\ifthenelse{\xsfc > 10000}{}{\node[fill=white,above] at (current bounding box.center) {x-s: \xsf};}
\ifthenelse{\ysfc > 10000}{}{\node[fill=white,below] at (current bounding box.center) {y-s: \ysf};}
}
\newcommand{\maximumdimensions}[2]{% width, height
\global\edef\maxwidth{#1} % in cm
\global\edef\maxheight{#2} % in cm
}
\begin{document}
\begin{tikzpicture}[scale=1]
\maximumdimensions{4}{3}
\draw[fill=orange] (-3,-1) rectangle (3,1) (-2,-2) rectangle (2,2);
\getscalingfactors
\end{tikzpicture}
\lipsum[1]
\begin{tikzpicture}[scale=1]
\maximumdimensions{4}{3}
\draw[fill=orange!50!gray] (0,0) circle (3);
\draw[fill=red!50!gray] (3,1) circle (1);
\draw[fill=blue!50!gray] (-2,2) circle (1);
\draw[fill=green!50!gray] (-3,-2) circle (1);
\draw[fill=yellow!50!gray] (2,-1) circle (1);
\getscalingfactors
\end{tikzpicture}
\end{document}
If you scale the picture down enough, the nodes inside the picture vanish:
\begin{tikzpicture}[scale=0.66]
and \begin{tikzpicture}[scale=0.497]
Best Answer
You need to end the paragraph before you close the group. While the fontsize is updated when you issue
\selectfont
the new leading only is updated when the paragraph is ended. In your case the group ends (with}
) before the paragraph ends (the empty line after the line end). Either writeor use
\par
at the end: