0

Can Latex fill an area of a certain aspect ratio (e.g. 3:1) with centered text using a ttf font so that it can be export to a specific pixel size image (600x200, probably using convert)?

Word- or letter-spacing should not be changed (as seen in \Shapepar attempt below).

Imagemagick's convert can do it:

convert -size 600x200 -font Montserrat-Regular -gravity center \
        caption:"I am curious about area-filling text rendering options" test.png

filling area with text using imagemagick

\Shapepar modifies word-spacing, which affects readability:

\documentclass[preview]{standalone}
\usepackage{fontspec}
\setmainfont{Montserrat-Regular}
\usepackage{shapepar}
\begin{document}
\Shapepar{\rectangleshape{200}{600}}I am curious about area-filling text rendering options\par
\end{document}

Shapepar rectangle fill

I also tried increasing point size and restricting the page size using \geometry but this causes errors

Can \Shapepar center text rather than modify word-spacing? Or is there another way of filling a specific rectangle with text in Latex?

1

Thankfully, very similar problems have been solved. Here is an adaptation:

\documentclass[preview]{standalone}
\usepackage{fontspec}
\setmainfont{Montserrat-Regular}
\sloppypar

\usepackage{environ}% http://ctan.org/pkg/environ
\newdimen\fontdim
\newdimen\upperfontdim
\newdimen\lowerfontdim
\newif\ifmoreiterations
\fontdim12pt

\newbox\trialbox
\newbox\linebox
\global\newcount\maxbad
\newcount\linebad
\newcount\currenthbadness

\makeatletter
\NewEnviron{fitbox}[2]{% \begin{fitbox}{<width>}{<height>} stuff \end{fitbox}
    % Store environment body
    \def\stuff{%
        \BODY%
    }%
    % prepare badness box
    \def\badnessbox{%
        \global\maxbad=0\relax%
        \currenthbadness=\hbadness% save old \hbadness
        \hbadness=10000000\relax% make sure, TeX reports overfull boxes
        \message{Starting measureline recursion with width #1^^J}%
        \setbox\trialbox=\vbox{%
            \hsize#1\relax%
            \fontsize{\fontdim}{1.2\fontdim}%
            \selectfont%
            \stuff\par%
            \measurelines% start recursion
        }%
%       \noindent\usebox\trialbox\par
        \hbadness=\currenthbadness% restore old \hbadness
    }
    % prepare recursion to measure line badness
    \def\measurelines{%
        \message{Iteration of measurelines^^J}%
        \begingroup%
            \setbox\linebox=\lastbox% get the last line
            \setbox0=\hbox to \hsize{\unhcopy\linebox}% put the last line into box0 to provoke badness calculation
            \linebad=\the\badness\relax% \badness now reflects the last typeset box, i.e. box0
            \message{Badness: \the\badness\space\the\linebad\space with max \the\maxbad\space at Fontsize: \the\fontdim\space^^J}%
            \ifnum\linebad>\maxbad% store the maximum badness
                \global\maxbad=\linebad% Uncomment this line to ignore overfull hboxes!
            \fi%
            \ifvoid% end of recursion
                \linebox%
            \else%
                \unskip\unpenalty\measurelines% do the recursion
                \ifhmode%
                    \newline%
                \fi%
                \noindent\box\linebox% do the output
            \fi%
        \endgroup%
    }%
    % Prepare measurement box
    \def\buildbox{%
        \badnessbox% measure badness
        \setbox0\vbox{% measure height
            \hbox{%
                \fontsize{\fontdim}{1.2\fontdim}%
                \selectfont%
                \minipage{#1}%
                    \vbox{%                     
                        \stuff\par%
                    }%
                \endminipage%
            }%
        }%
        \message{Measured badness: \the\maxbad\space at Fontsize: \the\fontdim\space^^J}%
        \dimen@\ht0
        \advance\dimen@\dp0
        \message{Measured box height: \the\dimen@\space^^J}%
    }%
    \def\shrinkheight{%
        \loop
            \fontdim.5\fontdim % Reduce font size by half
            \buildbox
            \message{Shrinking, new box height: \the\dimen@\space at Fontsize: \the\fontdim\space^^J}%
        \ifdim\dimen@>#2 \repeat
        \lowerfontdim\fontdim
        \upperfontdim2\fontdim
        \fontdim1.5\fontdim
    }%
    \def\shrinkwidth{%
        \loop
            \fontdim.5\fontdim % Reduce font size by half
            \buildbox
        \ifnum\maxbad>10000 \repeat
        \lowerfontdim\fontdim
        \upperfontdim2\fontdim
        \fontdim1.5\fontdim
    }%
    \def\growheight{%
        \loop
            \fontdim2\fontdim % Double font size
            \buildbox
            \message{Growing, new box height: \the\dimen@\space at Fontsize: \the\fontdim\space^^J}%
        \ifdim\dimen@<#2 \repeat
        \upperfontdim\fontdim
        \lowerfontdim.5\fontdim
        \fontdim.75\fontdim
    }%
    \buildbox
    % Compute upper and lower bounds
    \ifdim\dimen@>#2
        \message{Need to shrink box height: \the\dimen@\space^^J}%
        \shrinkheight
    \else
        \message{Need to grow box height: \the\dimen@\space to target: #2^^J}%
        \growheight
    \fi
    \message{Max font: \the\upperfontdim\space^^J}%
    \message{Min font: \the\lowerfontdim\space^^J}%
    % Potentially further reduce bounds for overfull box
    \ifnum\maxbad>10000
        \shrinkwidth
    \fi 
    \message{Max font adjusted: \the\upperfontdim\space^^J}%
    \message{Min font adjusted: \the\lowerfontdim\space^^J}%
    % Now try to find the optimum height and width
    \loop
        \buildbox
        \message{Height: \the\dimen@\space^^J}%
        \ifdim\dimen@>#2
            \moreiterationstrue
            \upperfontdim\fontdim
            \advance\fontdim\lowerfontdim
            \fontdim.5\fontdim
        \else
            \ifnum\maxbad>10000
                \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
        \fi
    \ifmoreiterations \repeat
    \message{Selected font: \the\fontdim\space^^J}%
    \vbox to #2{\box0\hbox{}}% Typeset content
}%
\makeatother

\usepackage{parskip}

\setlength\fboxsep{0pt}
\begin{document}

\begin{fitbox}{600px}{200px}%
\center{I am curious about area-filling text rendering options}
\end{fitbox}

\end{document}

lualatex solution

This was processed with lualatex.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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