2

In this answer, there is a macro that allows one to have a precise control of the page lengths of a document.

This macro is too complicated for me and I have found a problem with it. It behaves strangely with itemize environments. I am looking for help to improve the macro so that it behaves normally with itemize.

The goal of the macro

The goal of the macro is to produce a PDF document from a LaTeX source with the following constraints:

  • the default height of the pages is a parameter defaultLength
  • there is another parameter: initialVerticalInset
  • the height of the first page should be defaultLength - initialVerticalInset
  • the height of the last page equals the "height of its content", i.e. "the last page is but" after the end of its content
  • all the other pages have an height equal to defaultLength

Other constraints that were added after experiments:

  • if any of these pages are put next to another one, the baselines should be aligned
  • the macro should be compatible, if possible, with mdframed

The macro

Here is the macro:

[...]
\flushbottom
\setlength{\maxdepth}{0pt}% to address the "third bug"
\setlength{\topskip}{0pt}% no space above the first line

% assuming the page number is the absolute page number
\usepackage{zref-totpages,zref-savepos}
\usepackage{atbegshi}

\makeatletter
\providecommand*{\zsaveposy}{\zsavepos}% for older zref-savepos
\def\@oddhead{\PosFirstHead\PosLastHead\hss}%
\def\@evenhead{\PosLastHead\hss}%
\newcommand*{\PosFirstHead}{%
  \ifnum\value{page}=1 %
    \zsaveposy{PosFirstHead}%
    \global\let\PosFirstHead\@empty
  \fi
}
\newcommand*{\PosLastHead}{%
  \ifnum\value{page}=\ztotpages
    \zsaveposy{PosLastHead}%
    \global\let\PosLastHead\@empty
  \fi
}
\AtBeginShipout{%
  \ifnum\value{page}=1 %
    \dimen@=\dimexpr
      \zposy{PosFirstHead}sp-\headsep
      -\zposy{PosFirst}sp%
    \relax
    \setbox\AtBeginShipoutBox=\vbox{%
      \kern-\dimen@ %
      \copy\AtBeginShipoutBox
    }%
    \advance\pdfpageheight by -\dimen@
  \else
    \ifnum\value{page}=\ztotpages
      \advance\pdfpageheight by%
        -\dimexpr
          \textheight
          -\zposy{PosLastHead}sp+\headsep
          +\zposy{PosLast}sp%
        \relax
    \fi
  \fi
}
\AtEndDocument{%
  \par
  \nobreak
  \dimen@=\prevdepth
  \ifdim\dimen@>\maxdepth
    \kern-\maxdepth
  \else
    \ifdim\dimen@>0pt %
      \kern-\dimen@
    \fi
  \fi
  \zsaveposy{PosLast}%
}
\makeatother

\usepackage{lipsum}% provides dummy text

\interlinepenalty=-100

\begin{document}
\vspace*{\dimexpr5cm-\topskip plus 1fill}% first page should not be larger than 15cm
\zsaveposy{PosFirst}
\nointerlineskip
[...]

A MWE that fails

Here is a MWE showing the issue. The first page should have a normal height. But, it is shorter.

\documentclass{article}

\usepackage%
[paperwidth=10.000000cm,
paperheight=8cm,
hmargin=1.000000mm,
top=1.000000mm,
bottom=1.000000mm]
{geometry}


\pagestyle{empty}

\flushbottom
\setlength{\maxdepth}{0pt}% to address the "third bug"
\setlength{\topskip}{0pt}% no space above the first line

% assuming the page number is the absolute page number
\usepackage{zref-totpages,zref-savepos}
\usepackage{atbegshi}

\makeatletter
\providecommand*{\zsaveposy}{\zsavepos}% for older zref-savepos
\def\@oddhead{\PosFirstHead\PosLastHead\hss}%
\def\@evenhead{\PosLastHead\hss}%
\newcommand*{\PosFirstHead}{%
  \ifnum\value{page}=1 %
    \zsaveposy{PosFirstHead}%
    \global\let\PosFirstHead\@empty
  \fi
}
\newcommand*{\PosLastHead}{%
  \ifnum\value{page}=\ztotpages
    \zsaveposy{PosLastHead}%
    \global\let\PosLastHead\@empty
  \fi
}
\AtBeginShipout{%
  \ifnum\value{page}=1 %
    \dimen@=\dimexpr
      \zposy{PosFirstHead}sp-\headsep
      -\zposy{PosFirst}sp%
    \relax
    \setbox\AtBeginShipoutBox=\vbox{%
      \kern-\dimen@ %
      \copy\AtBeginShipoutBox
    }%
    \advance\pdfpageheight by -\dimen@
  \else
    \ifnum\value{page}=\ztotpages
      \advance\pdfpageheight by%
        -\dimexpr
          \textheight
          -\zposy{PosLastHead}sp+\headsep
          +\zposy{PosLast}sp%
        \relax
    \fi
  \fi
}
\AtEndDocument{%
  \par
  \nobreak
  \dimen@=\prevdepth
  \ifdim\dimen@>\maxdepth
    \kern-\maxdepth
  \else
    \ifdim\dimen@>0pt %
      \kern-\dimen@
    \fi
  \fi
  \zsaveposy{PosLast}%
}
\makeatother

\usepackage{lipsum}% provides dummy text

\interlinepenalty=-100

\begin{document}
\vspace*{\dimexpr0.000cm-\topskip plus 1fill}
\zsaveposy{PosFirst}
\nointerlineskip

This is a test. This is a longer sentence with some more words, isn't it? This is a test. This is a longer sentence with some more words, isn't it? This is a test. This is a longer sentence with some more words, isn't it? This is a test. This is a longer sentence with some more words, isn't it?

This is a test:
\begin{itemize}
\item Hello

\item This is a test. This is a longer sentence with some more words, isn't it? This is a test. This is a longer sentence with some more words, isn't it? This is a test.

\item Good Bye

\item Hello

\item This is a test. This is a longer sentence with some more words, isn't it? This is a test. This is a longer sentence with some more words, isn't it? This is a test.
\end{itemize}

This is a test. This is a longer sentence with some more words, isn't it? This is a test. This is a longer sentence with some more words, isn't it? This is a test. This is a longer sentence with some more words, isn't it? This is a test. This is a longer sentence with some more words, isn't it? This is a test. This is a longer sentence with some more words, isn't it? This is a test. This is a longer sentence with some more words, isn't it? This is a test. This is a longer sentence with some more words, isn't it? This is a test. This is a longer sentence with some more words, isn't it? This is a test. This is a longer sentence with some more words, isn't it? This is a test. This is a longer sentence with some more words, isn't it? This is a test. This is a longer sentence with some more words, isn't it? This is a test. This is a longer sentence with some more words, isn't it?

This is a test. This is a longer sentence with some more words, isn't it? This is a test. This is a longer sentence with some more words, isn't it? This is a test. This is a longer sentence with some more words, isn't it? This is a test. This is a longer sentence with some more words, isn't it?

This is a test. This is a longer sentence with some more words, isn't it? This is a test. This is a longer sentence with some more words, isn't it? This is a test. This is a longer sentence with some more words, isn't it? This is a test. This is a longer sentence with some more words, isn't it?
\end{document}

enter image description here

Colas
  • 6,772
  • 4
  • 46
  • 96
  • \setlength{\topskip}{0pt}% no space above the first line doesn't say no space above the first line it says to try to put the baseline of the first line at the top (which it won't do so will give inconsistent line positions for the page depending on the height of the characters in the first line, seting \maxdepth=0pt is similarly bizarre are you sure you want to that: it means if the last line of text has a g the line will not fit so tex will have to leave the page short and take the line over to the next page. – David Carlisle Oct 22 '14 at 16:34
  • These commands were intended for having no top and bottom margin BUT, if two such pages are next one to another, the baselines are aligned. – Colas Oct 22 '14 at 16:39
  • No chance of baseline alignment if topskip is 0 – David Carlisle Oct 22 '14 at 16:39
  • do you consider space for descenders like g to be "margin" setting maxdepth to zero prevents the bottom line from having any such character – David Carlisle Oct 22 '14 at 16:41
  • OK, thanks! Do you see, apart from that, why the macro is behaving like that with itemize environments... This macro is really complicated! – Colas Oct 22 '14 at 16:43
  • why do you want to do this? The whole thing seems exceedingly strange??? – David Carlisle Oct 22 '14 at 16:47
  • I want to to generate a PDF document from a LaTeX document with the following constraints: 1) the first page should have a given height (for instance, 2cm less than normal) 2) the other pages have all the same height 3) the last page has the same height as its content (it is "cut" after the end of the content) – Colas Oct 22 '14 at 16:52

1 Answers1

1

The lines

%\setlength{\maxdepth}{0pt}% to address the "third bug"
%\setlength{\topskip}{0pt}% no space above the first line

%\vspace*{\dimexpr0.000cm-\topskip plus 1fill}

Can't ever do anything very helpful to the document and if I remove them the first page is the expected size.

David Carlisle
  • 757,742
  • The line \vspace*{\dimexpr0.000cm-\topskip plus 1fill} is very important because in other situations, I want to specify instead: \vspace*{\dimexpr2.000cm-\topskip plus 1fill}. The goal is to say: the height of the first page should be 2cm less that normal. – Colas Oct 22 '14 at 16:48
  • @Colas the goal seems rather unrelated to the setting (why are 2.000cm rather than 2cm by the way it means the same but just looks odd) The setting does not change the default height of the page, since topskip is zero it is just a complicated way of saying \vspace*{\fill} which adds stretchy white space at the top which balances with other glue on the page allowing it to be arbitrarily short, then your macro clips the page to the shortened text. – David Carlisle Oct 22 '14 at 16:51
  • @Colas \vspace*{2cm} would shrink the first page by 2cm – David Carlisle Oct 22 '14 at 16:57
  • I have edited the question to explain the goal of the macro. – Colas Oct 22 '14 at 17:00
  • @Colas so this seems to answer it, so long as you used fixed length when you shorten the first page as in my comment above. – David Carlisle Oct 22 '14 at 17:03
  • OK, yes it seems to work. Do you have a guess why @Heiko (who wrote this macro) put this command (\vspace*{\dimexpr0.000cm-\topskip plus 1fill})? – Colas Oct 22 '14 at 17:22