Problem with setting correct custom page size with 'geometry' in xelatex

I'm trying to set the page size using the geometry package as shown in the following MWE, compiled with xelatex test.tex:

\documentclass[12pt]{article}

\usepackage[b5paper,pass]{geometry}
\geometry{b5paper}
\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}

\begin{document}

\lipsum[1]

\end{document}


If I then try to check the page size using pdfinfo (on Ubuntu), I get size of US letter (?!):

$pdfinfo -box -f 1 -l 1 test.pdf | grep Page Pages: 1 Page 1 size: 612 x 792 pts (letter) Page 1 MediaBox: 0.00 0.00 612.00 792.00 Page 1 CropBox: 0.00 0.00 612.00 792.00 Page 1 BleedBox: 0.00 0.00 612.00 792.00 Page 1 TrimBox: 0.00 0.00 612.00 792.00 Page 1 ArtBox: 0.00 0.00 612.00 792.00  However, if I enter b5paper in \documentclass[b5paper,12pt]{article} - then I can just as well delete all the other references to geometry using b5paper - because when I compile with that change, I get: $ pdfinfo -box -f 1 -l 1 test.pdf | grep Page
Pages:          1
Page    1 size: 498.9 x 708.66 pts
Page    1 MediaBox:     0.00     0.00   498.90   708.66
Page    1 CropBox:      0.00     0.00   498.90   708.66
Page    1 BleedBox:     0.00     0.00   498.90   708.66
Page    1 TrimBox:      0.00     0.00   498.90   708.66
Page    1 ArtBox:       0.00     0.00   498.90   708.66


... which (I guess) corresponds to correct B5 measures.

Now, as far as I had believed until now - one should be able to change the paper size with geometry - as long as those changes are issued before \begin{document}, is that correct? If so, why doesn't it work here?

I'm wandering, because I wanted to set some custom page sizes with geometry in this way (and which thus I couldn't propagate to the \documentclass command).

Many thanks in advance for any suggestions on how to set a custom page size in this example,
Cheers!

-
You have to pass b5paper as an option to \documentclass rather than to geometry. –  egreg May 13 '12 at 20:21
Thanks for that, @egreg - but I wanted a solution outside of \documentclass, since I want to set custom page sizes.. I came up with a sort of a hack below, but I'm not sure if that is the way custom page sizes should be handled.. Thanks again - cheers! –  sdaau May 13 '12 at 20:31

EDIT2: Ok, I think I finally realized the culprit, which is the pass option of the geometry package. It turns out, whenever the pass option is present in a geometry call - regardless if it is in the options of \usepackage[...]{geometry}, or if it is a \geometry{pass} call right before \begin{document} - it will simply "kill" whatever settings for margins you may have set there, and revert to whatever the documentclass was set to, apparently (so, apparently including the b5paper option set below in \usepackage[b5paper,pass]{geometry} was made irrelecant by the subsequent pass).

For instance, I tried setting margins (in code below) with:

\usepackage[pass,paperwidth=\classpagewidth,paperheight=\classpageheight,twoside,inner=1cm,outer=2cm,top=1cm,bottom=1cm]{geometry}


... and nothing worked - because pass was there!

Knowing that, now I can just replace the geometry related commands in the code below with:

\usepackage{geometry}
\geometry{pass,twoside,inner=1cm,outer=2cm,top=1cm,bottom=1cm}


... and all seems to work fine.

Note finally, that while we cannot use \geometry{pass} after \begin{document} - we can use \newgeometry{pass} there; and in that case, pass doesn't seem to revert all page lengths so drastically.

(Btw, using pass there was because of a fix to Centering full-page Tikz image on page without margins with xelatex?)

OK, I think I finally arrived at some sort of a hack/solution/understanding; basically, it seems that settings for the page size in the above example are ignored as part of the geometry package, and one has to explicitly set page sizes (as per hack seen in Change paper size in mid-document and elsewhere).

In the example below - note that the explicit setting of page sizes, even if it occurs before geometry is loaded, seems to be unaffected by loading of geometry's options:

\documentclass[12pt]{article}

\newlength{\classpageheight}
\newlength{\classpagewidth}
\newlength{\stockwidth}\newlength{\stockheight}

% since here page size stuff may get ignored,
% set explicitly custom page size
\setlength{\classpagewidth}{290pt}
\setlength{\classpageheight}{360pt}
\pdfpagewidth=\classpagewidth \pdfpageheight=\classpageheight % to enforce?
\paperwidth=\classpagewidth \paperheight=\classpageheight     % for TikZ
\stockwidth=\classpagewidth \stockheight=\classpageheight % hyperref (memoir)?!

\usepackage[b5paper,pass]{geometry}
\geometry{b5paper}

\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}

\begin{document}

\lipsum[1]

\end{document}


Note that in the example, I've defined \stockwidth only because layouts defines it (otherwise for purposes in memoir) - which then causes a hyperref "Package hyperref Warning: Height of page (\stockheight) is invalid (0.0pt), ( hyperref) using 11in."

If I build this with xelatex test.tex, and then check the page size, I get:

$pdfinfo -box -f 1 -l 1 test.pdf | grep Page | grep size Page 1 size: 288.92 x 358.66 pts  Notably, I thought I asked for 290 x 360 pts page; but pdfinfo says the size is actually 288.92 x 358.66 pts. Turns out, what I need is the 'big points' (bp) LaTeX length units - so if I rewrite: \setlength{\classpagewidth}{290bp} \setlength{\classpageheight}{360bp}  ... then indeed pdfinfo reports the requested size: $ pdfinfo -box -f 1 -l 1 test.pdf | grep Page | grep size
Page    1 size: 290 x 360 pts


Still not sure if this is the way things are supposed to be done, though ... Cheers!

-

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 in geometry, if any).
• However, geometry does take into account parameters called layoutwidth and layoutheight, 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 with layoutwidth/height set to respective custom pagesize newlengths, and then \savegeometry
• Then \switchToLayoutPageA and typeset content
• it will do actual page switching with \paperwidth/\pdfpagewidth, and call respective loadgeometry
• 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)?!
}

\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)?!
}

\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{}

\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!

-