5

I am trying to create an environment where a user gives a suggestion, via the \suggestion macro, and includes some pictures, via the \picutres macro, then it formats the suggestion with the picutres formatted underneath. I'm having a problem where passing the contents of \suggestion into a macro makes the pictures render differently than if I pass the contents directly to the environment. More specifically when LINE 1 of the MWE is uncommented the output appears on a single page, but when LINE 2 is uncommented the output is split across two pages. I would like to pass the contents to a macro inside the enviroment to do some text formatting but cannot figure out how to do that while still keeping the output on a single page.

\documentclass{article}
\usepackage[bottom=1in, showframe]{geometry}
\usepackage{lipsum}
\usepackage{etoolbox}
\usepackage{tikz}
\usepackage{calc}

\newcounter{imagecount}%
\newsavebox\picturesbox%
\newlength\heightleft%
\setlength{\parindent}{0pt}

\makeatletter

\def\@pictures{}

\NewDocumentCommand{\pictures}{sm}{%
    \def\@pictures{}%
    \setcounter{imagecount}{0}%
    #2%
    \setlength\heightleft{\dimexpr\textheight - \pagetotal - 2em\relax}%
    \edef\widthleft{\dimexpr\textwidth/\theimagecount\relax}%
    \savebox\picturesbox[\textwidth]{%
        \parbox[b][\dimexpr\textheight - \pagetotal - 2em\relax][s]{\textwidth}{%
            \@pictures%
        }%
    }%
}

\NewDocumentCommand\image{m}{%
    \stepcounter{imagecount}%
    \g@addto@macro\@pictures{%
        \includegraphics[keepaspectratio, height=\heightleft, width=\widthleft]{#1}%
    }%
}

\NewDocumentCommand{\suggestion}{+m}{%
    \g@addto@macro\@suggestion{%
        #1%
    }%
}

\NewDocumentEnvironment{recipe}{m}{%
    \def\@suggestion{}%
    \def\@pictures{}%
}{
    \@suggestion\par%
    \vfill%
    \usebox{\picturesbox}%
    \newpage%
}


\makeatother

\begin{document}

\begin{recipe}{Test!}
    \lipsum[1-3]                 % LINE 1
    % \suggestion{\lipsum[1-3]}  % LINE 2
    
    \pictures{
        \image{example-image-16x10}
        \image{example-image-9x16}
    }
    
\end{recipe}

\end{document}
2
  • 3
    \suggestion only collects the text to be printed, but it does not output it, so it does not change \pagetotal. Therefore the size of the pictures is different. You can see this adding \showthe\pagegoal before and after the two lines. So you would, e.g., need to use \@suggestion before the first \pictures does the \heightleft calculation. Commented 22 hours ago
  • @cabohah thanks, I just moved the computation of \heightleft from \pictures to the end of the recipe environment and that solved it. Commented 15 hours ago

1 Answer 1

3

We use the following approach: measure the height of the text from \@suggestion without immediately typesetting it, and then use this information when calculating \heightleft. Finally, both the text and the images are output in the correct order. This is apparently what cabohah meant in their comment.

\documentclass{article}
\usepackage[bottom=1in, showframe]{geometry}
\usepackage{lipsum}
\usepackage{graphicx}
\usepackage{calc}

\newcounter{imagecount}
\newsavebox\picturesbox
\newsavebox\suggestionbox
\newlength\heightleft
\setlength{\parindent}{0pt}

\makeatletter

\NewDocumentCommand{\suggestion}{+m}{%
    \savebox\suggestionbox{\parbox{\textwidth}{#1}}%
}

\NewDocumentCommand{\pictures}{sm}{%
    \def\@pictures{}%
    \setcounter{imagecount}{0}%
    #2%
    \setlength\heightleft{%
        \dimexpr\textheight - \ht\suggestionbox - \dp\suggestionbox - 2em\relax
    }%
    \ifdim\heightleft<0pt
        \setlength\heightleft{0pt}
    \fi
    \ifnum\theimagecount>0
        \edef\widthleft{\dimexpr\textwidth/\theimagecount\relax}%
    \else
        \def\widthleft{\textwidth}
    \fi
    \savebox\picturesbox[\textwidth]{%
        \parbox[b][\heightleft][s]{\textwidth}{%
            \@pictures%
        }%
    }%
}

\NewDocumentCommand\image{m}{%
    \stepcounter{imagecount}%
    \g@addto@macro\@pictures{%
        \includegraphics[keepaspectratio, height=\heightleft, width=\widthleft]{#1}%
    }%
}

\NewDocumentEnvironment{recipe}{m}{%
    \setbox\suggestionbox=\vbox{}%
    \def\@pictures{}%
}{%
    \usebox\suggestionbox
    \par
    \vfill
    \usebox\picturesbox
    \newpage
}

\makeatother

\begin{document}

% === Case 1: short text ===
\begin{recipe}{Short text}   
    \suggestion{\lipsum[1][1-6]}
    \pictures{
        \image{example-image-16x10}
        \image{example-image-9x16}
    }
\end{recipe}

% === Case 2: medium text ===
\begin{recipe}{Medium text}
    \suggestion{\lipsum[1-2]}
    \pictures{
        \image{example-image-16x10}
        \image{example-image-9x16}
    }
\end{recipe}

% === Case 3: long text ===
\begin{recipe}{Long text}
    \suggestion{\lipsum[1-4]}
    \pictures{
        \image{example-image-16x10}
        \image{example-image-9x16}
    }
\end{recipe}

\end{document} 

enter image description here

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.