Problem with setting correct custom page size with 'geometry' in xelatex
Well, finally I think I got somewhere with switching between custom page sizes and page layouts with geometry
in mid-document (the MWE is below (see also previous post on geometry
's pass
); click on image for full size):
First of all, a couple of words about geometry:
- You can call
\geometry
only in preamble, and there multiple commands have simply the effect of replacing previously set values of parameters geometry
first calculates a layout (margins etc) after\begin{document}
, which the manual calls layout L1- The command
\restoregeometry
can only restore L1! - The command
\newgeometry
can only be called after\begin{document}
(and thus, after L1 is created) - Layouts created with
\newgeometry
can be\save
/\loadgeometry
-ied \newgeometry
does NOT care about\paperwidth
/height
! In fact, if you thought you could cheat with:\setlength{\paperwidth}{100mm} \setlength{\paperheight}{100mm} \newgeometry{twoside,...}
,geometry
will care not a bit, and will in fact reset paperwidth/height back to the documentclass setting (or I guess, the last named page size setting ingeometry
, if any).- However,
geometry
does take into account parameters calledlayoutwidth
andlayoutheight
, which serve the purpose of page size limits.
Thus, how geometry
calculates margins, is independent of the actual page setting in \paperwidth
/\pdfpagewidth
. Having all this in mind, the following checklist can be submitted for managing custom page sizes and layouts:
- Prepare in preamble custom page sizes as new lengths
- Prepare in preamble commands
\generatePageLayouts
,\switchToLayoutPageA
and\switchToLayoutPageB
- After
\begin{document}
, call first\generatePageLayouts
, not doing any actual page size switching with\paperwidth
/\pdfpagewidth
- it will call
\newgeometry
withlayoutwidth
/height
set to respective custom pagesize newlengths, and then\savegeometry
- it will call
- Then
\switchToLayoutPageA
and typeset content- it will do actual page switching with
\paperwidth
/\pdfpagewidth
, and call respectiveloadgeometry
- it will do actual page switching with
- Then
\switchToLayoutPageB
and typeset content- it will -- || --
Note that even \loadgeometry
resets \paperwidth
/height
- which can be seen on the image, in the table produced by layouts
: there it is reported, on both pages, that: \paperwidth = 614.295pt
- even if neither of the pages is of that size:
$ pdfinfo -box -f 1 -l 2 test.pdf | grep Page
Pages: 2
Page 1 size: 300 x 400 pts
Page 2 size: 400 x 500 pts
In any case, here is the MWE, compiled with xelatex test.tex
:
\documentclass{article}
% reminder: US letter: 596pt x 795pt
\newlength{\pagewidthA}
\newlength{\pageheightA}
\setlength{\pagewidthA}{300bp}
\setlength{\pageheightA}{400bp}
\newlength{\pagewidthB}
\newlength{\pageheightB}
\setlength{\pagewidthB}{400bp}
\setlength{\pageheightB}{500bp}
\newlength{\stockwidth}
\newlength{\stockheight}
\usepackage{geometry}
% these seem to have NO effect in preamble!
% geometry first has effect after begin{document}!
\pdfpagewidth=\pagewidthA \pdfpageheight=\pageheightA % to enforce?
\paperwidth=\pagewidthA \paperheight=\pageheightA % for TikZ
\stockwidth=\pagewidthA \stockheight=\pageheightA % hyperref (memoir)?!
% this command will take effect into L1 layout just after \begin{document}
\geometry{twoside,inner=50bp,outer=30bp,top=50bp,bottom=50bp}
\usepackage{tikz,enumitem}
\usepackage{fix-cm}
\usepackage{fontspec}
\defaultfontfeatures{Ligatures=TeX}
\setmainfont{Junicode}
\usepackage{layouts}
\usepackage{etoolbox}
\patchcmd{\drawpage}{\ifdrawparameters}{\iftrue}%
{\typeout{^^J*******\string\drawpage fixed*******^^J}}%
{\typeout{^^J*******\string\drawpage not fixed*******^^J}}
\usepackage{lipsum}
\makeatletter
\newcommand{\printpagevalues}{%
% from geometry.sty:
* paper: \ifx\Gm@paper\@undefined<default>\else\Gm@paper\fi \\%
* layout: \ifGm@layout<custom>\else<same size as paper>\fi \\%
\@ifundefined{ifGm@layout}{}{%
\ifGm@layout
* layout(width,height): (\the\Gm@layoutwidth,\the\Gm@layoutheight) \\%
\fi
* layoutoffset:(h,v)=(\the\Gm@layouthoffset,\the\Gm@layoutvoffset) \\%
}%
\pagevalues % from package layouts
}
\makeatother
\newcommand{\generatePageLayouts}{%
% this command must be called after \begin{document}!
% geometry needs layoutwidth - cause it ignores the above paper sizes!
% layoutwidth=148mm ok, layoutwidth=\paperwidth NOT ok
% paperwidth gets reset again internally in newgeometry: in log: *geometry* verbose mode: * layout(width,height): (614.295pt,794.96999pt)
% but by using \stockwidth, which here is just a custom length: * layout(width,height): (421.10078pt,597.50787pt)
\newgeometry{layoutwidth=\pagewidthA,layoutheight=\pageheightA,left=1mm,right=5mm,bottom=1mm,top=1mm}
\savegeometry{LayoutPageA}
\newgeometry{layoutwidth=\pagewidthB,layoutheight=\pageheightB,twoside,inner=2.5cm,outer=0.5cm,top=1.5cm,bottom=1.5cm}
\savegeometry{LayoutPageB}
}
\newcommand{\switchToLayoutPageA}{%
% doesn't include page sizes; so page size too:
\pdfpagewidth=\pagewidthA \pdfpageheight=\pageheightA % for PDF output
\paperwidth=\pagewidthA \paperheight=\pageheightA % for TikZ
\stockwidth=\pagewidthA \stockheight=\pageheightA % hyperref (memoir)?!
\loadgeometry{LayoutPageA} % note; \loadgeometry may reset paperwidth/h!
}
\newcommand{\switchToLayoutPageB}{%
% doesn't include page sizes; so page size too:
\pdfpagewidth=\pagewidthB \pdfpageheight=\pageheightB % for PDF output
\paperwidth=\pagewidthB \paperheight=\pageheightB % for TikZ
\stockwidth=\pagewidthB \stockheight=\pageheightB % hyperref (memoir)?!
\loadgeometry{LayoutPageB} % note; \loadgeometry may reset paperwidth/h!
}
\fontspec[Scale=1.0]{Junicode}
\begin{document}
% here geometry layout L1 is instantiated;
% without anything else, paper size defaults to US letter!
% \restoregeometry command restores L1!!
\fontsize{8}{9}\selectfont % this nowork in preamble!
% generate page layouts first based on layoutwidth as page size;
% don't switch actual page sizes yet:
\generatePageLayouts{}
%%% start with content
% start with LayoutPageA (includes switching page size)
\switchToLayoutPageA{}
\pagestyle{empty} % no page numbers here
\\
\the\paperwidth
\lipsum[1]
\printpagevalues{}
\clearpage
% switch to LayoutPageB (includes switching page size)
\switchToLayoutPageB{}
% start page numbering here ("this will reset the page number"):
\pagenumbering{arabic}
% make page numbers visible
\pagestyle{plain}
\the\paperwidth
\lipsum[1]
Trying
some
text
\printpagevalues{}
\end{document}
And finally - here is how the above image was generated:
convert -density 150 -bordercolor LimeGreen -border 2 test.pdf[0] test1.png
convert -density 150 -bordercolor LimeGreen -border 2 test.pdf[1] test2.png
montage test1.png test2.png -geometry +2+2 -tile 2x1 test.png
Well, hope this helps someone,
Cheers!