texlive[64404] Master: photobook (15sep22)

commits+karl at tug.org commits+karl at tug.org
Thu Sep 15 21:57:32 CEST 2022


Revision: 64404
          http://tug.org/svn/texlive?view=revision&revision=64404
Author:   karl
Date:     2022-09-15 21:57:32 +0200 (Thu, 15 Sep 2022)
Log Message:
-----------
photobook (15sep22)

Modified Paths:
--------------
    trunk/Master/tlpkg/bin/tlpkg-ctan-check
    trunk/Master/tlpkg/libexec/ctan2tds
    trunk/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc

Added Paths:
-----------
    trunk/Master/texmf-dist/doc/latex/photobook/
    trunk/Master/texmf-dist/doc/latex/photobook/LICENSE
    trunk/Master/texmf-dist/doc/latex/photobook/Makefile
    trunk/Master/texmf-dist/doc/latex/photobook/README.md
    trunk/Master/texmf-dist/doc/latex/photobook/photobook.pdf
    trunk/Master/texmf-dist/doc/latex/photobook/scripts/
    trunk/Master/texmf-dist/doc/latex/photobook/scripts/cls2tex.sh
    trunk/Master/texmf-dist/doc/latex/photobook/scripts/make-images.sh
    trunk/Master/texmf-dist/tex/latex/photobook/
    trunk/Master/texmf-dist/tex/latex/photobook/photobook.cls
    trunk/Master/tlpkg/tlpsrc/photobook.tlpsrc

Added: trunk/Master/texmf-dist/doc/latex/photobook/LICENSE
===================================================================
--- trunk/Master/texmf-dist/doc/latex/photobook/LICENSE	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/photobook/LICENSE	2022-09-15 19:57:32 UTC (rev 64404)
@@ -0,0 +1,29 @@
+BSD 3-Clause License
+
+Copyright (c) 2021, Alex A. Naanou
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Added: trunk/Master/texmf-dist/doc/latex/photobook/Makefile
===================================================================
--- trunk/Master/texmf-dist/doc/latex/photobook/Makefile	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/photobook/Makefile	2022-09-15 19:57:32 UTC (rev 64404)
@@ -0,0 +1,375 @@
+#----------------------------------------------------------------------
+#
+#
+#
+# Main targets:
+# 	pdf				- build class pdf documentation...
+# 	md				- build class markdown documentation (XXX EXPERIMENTAL)...
+#
+# Distribution and install:
+# 	dist			- build a distributable zip
+# 	install			- install to user home latex path
+#	uninstall		- uninstall/remove from user home latex path
+# 	install-local	- install to local latex path 
+# 						(may require elevated privileges)
+# 	uninstall-local	- uninstall/remove from local latex path
+# 						(may require elevated privileges)
+# 	install-devel	- XXX
+# 	uninstall-devel	- XXX
+#
+# Other targets:
+# 	sweep			- cleanup auxiliary generated files
+# 	clean			- cleanup repo
+#
+#
+# Variables:
+# 	CODE_INSTALL	- set how we handle the installing code/source.
+# 						this can be:
+# 							strip		- strip the docs from code (default)
+# 							copy		- copy the code/doc file
+# 							link		- link the code/doc files
+# 						(affects install and install-local targets)
+# 	INSTALL_PATH	- install path
+# 						(only affects install target)
+#
+#
+# Examples:
+#
+# 	$ INSTALL_PATH=./test CODE_INSTALL=link make install
+# 		install to "./test" and do not strip docs.
+#
+#
+#
+#----------------------------------------------------------------------
+# Config...
+
+.EXPORT_ALL_VARIABLES:
+
+# NOTE: this makes things run consistently on different systems including 
+# 		things like Android...
+SHELL := bash
+
+MODULE := photobook
+
+
+# metadata...
+#
+# NOTE: the code version is in the code...
+VERSION = $(strip $(shell \
+	cat $(MODULE).cls \
+		| grep 'VERSION{' \
+	 	| sed 's/.*{\(.*\)}.*/\1/'))
+DATE = $(strip $(shell date "+%Y%m%d%H%M"))
+COMMIT = $(strip $(shell git rev-parse HEAD))
+
+
+# installing code...
+#
+# this can be:
+# 	- strip
+# 	- copy
+# 	- link
+#
+# NOTE: we are doing things in different ways for different modes:
+# 		- copy vs. strip
+# 			- simply change the target name and let make figure it out...
+# 		- link vs. copy/strip
+# 			- $(LN) vs. $(INSTALL) in the install target...
+CODE_INSTALL ?= strip
+ifeq ($(CODE_INSTALL),strip)
+	MODULE_CODE := $(MODULE)-stripped
+else
+	MODULE_CODE := $(MODULE)
+endif
+
+
+# markdown dialect...
+#
+# XXX still needs some tweaking...
+MD_FORMAT ?= markdown_github
+
+
+# debug output...
+#
+# $DEBUG can either be empty or anything else...
+DEBUG ?=
+ifeq ($(DEBUG),)
+	STDERR := > /dev/null
+else
+	STDERR :=
+endif
+
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Paths and files...
+
+# LaTeX...
+TEX_LOCAL = $(shell kpsewhich --var-value TEXMFLOCAL)
+TEX_HOME = $(shell kpsewhich --var-value TEXMFHOME)
+
+# default install target...
+INSTALL_PATH ?= $(TEX_HOME)
+
+# build...
+BUILD_DIR := build
+
+# distribution...
+#DIST_NAME := $(MODULE)-$(VERSION)
+DIST_NAME := $(MODULE)-$(VERSION)-$(DATE)
+DIST_DIR := dist
+DIST_FILES = \
+	README.md \
+	LICENSE \
+	Makefile \
+	$(wildcard scripts/*) \
+	$(MODULE).cls \
+	$(MODULE).pdf
+# Add these when ready...
+#	$(wildcard examples/*) \
+#	$(wildcard manual/*) \
+#	$(wildcard workflow/*) \
+#
+
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Software...
+
+# NOTE: need to run latex two+ times to build index, the simpler way to 
+# 		go is to use latexmk...
+#TEX := lualatex
+TEX := latexmk -lualatex
+
+# Doc generator...
+DOC := ./scripts/cls2tex.sh
+
+MD := mkdir -p
+# XXX cp/install, technically this is only used in install* targets so 
+# 		renaming CP -> INSTALL would seem logical...
+#INSTALL := cp
+INSTALL := install
+# copy preserving relative paths...
+RCP := cp -r --parents
+LN := cp -l
+
+
+
+#----------------------------------------------------------------------
+# Rules...
+
+# docs (pdf)...
+#
+%.pdf: %.tex
+	$(TEX) $< $(STDERR)
+
+# docs (markdown)...
+#
+# XXX this still needs some tweaking...
+# 			- |..|	- verbatim does not work...
+# 			- ||	- parts of doc omitted...
+#			- verbatim blocks get merged sometimes...
+#			- ...
+#		...not sure if this can be tweaked...
+#%.md: %.tex
+#	pandoc -t $(MD_FORMAT) -s $< -o $@
+
+# XXX EXPERIMENTAL...
+# XXX revise:
+#		...for this to work we need to replace:
+#			\documentclass{ltxdoc}
+#		to:
+#			\documentclass[markdownextra]{internet}
+# XXX install the internet class...
+#			https://github.com/loopspace/latex-to-internet
+#		...needs testing...
+%.md: %.tex
+	cat $< \
+		| sed 's/documentclass{ltxdoc}/documentclass[markdownextra]{internet}/' \
+		> $<.tmp
+	mv $<{.tmp,}
+	$(TEX) $< $(STDERR)
+
+
+# meta-section...
+#
+# NOTE: .sty and .cls are essentially the same in terms of documentation 
+# 		generation...
+# XXX might be a good idea to place a link/footnote where metadocs were 
+#		originally located...
+#		...not sure yet manually or automatically...
+%.tex: %.sty %-meta.tex
+	$(DOC) $< > $@
+
+%.tex: %.cls %-meta.tex
+	$(DOC) $< > $@
+
+
+# meta docs...
+#
+# NOTE: this is a bit ugly, but allot less so than trying to push \verb
+# 		into a LaTeX macro/env and then getting it out again in one pice...
+%-meta.tex: %.sty
+	$(DOC) --prefix M $< > $@
+
+%-meta.tex: %.cls
+	$(DOC) --prefix M $< > $@
+
+
+# strip docs out...
+#
+# XXX can we unify these???
+%-stripped.tex: %.tex
+	$(DOC) --strip $< \
+		$(DOC) --prefix M --strip \
+		> $@
+
+%-stripped.sty: %.sty
+	$(DOC) --strip $< \
+		| $(DOC) --prefix M --strip \
+		> $@
+
+%-stripped.cls: %.cls
+	$(DOC) --strip $< \
+		| $(DOC) --prefix M --strip \
+		> $@
+
+
+
+#----------------------------------------------------------------------
+# Info targets...
+
+.PHONY: version
+version:
+	@echo $(VERSION)
+
+
+
+#----------------------------------------------------------------------
+# Main targets...
+
+.PHONY: pdf
+pdf: $(MODULE).pdf
+
+
+.PHONY: md
+md: $(MODULE).md
+
+
+# XXX STUB -- not sure how to approach this yet...
+# 		on one hand the manual should be a self-contained example in 
+# 		itself on the other hand we already have a working Makefile 
+# 		building the docs...
+.PHONY: manual
+manual:
+	$(MAKE) -C manual all
+	mv manual/*.pdf .
+
+
+%.zipnote: %.zip
+	zipnote $< > $@
+
+
+.PHONY: dist
+dist: $(DIST_FILES)
+	$(MD) $(DIST_DIR)
+	zip -Drq $(DIST_DIR)/$(DIST_NAME).zip $(DIST_FILES)
+	# Place everything in the module dir as per CTAN spec...
+	zipnote $(DIST_DIR)/$(DIST_NAME).zip \
+		| sed 's/^\@ \([^(].*\)$$/@ \1\n@=$(MODULE)\/\1/' \
+		| zipnote -w $(DIST_DIR)/$(DIST_NAME).zip
+
+CTAN: dist
+	$(MD) $(DIST_DIR)/CTAN
+	cp $(DIST_DIR)/$(DIST_NAME).zip $(DIST_DIR)/CTAN/$(MODULE).zip
+
+
+.PHONY: all
+all: pdf
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Install/uninstall targets...
+
+# NOTE: keep the dir clean unless this is explicitly built...
+.INTERMEDIATE: \
+		$(MODULE)-stripped.cls \
+		$(MODULE)-stripped.sty \
+		$(MODULE)-stripped.tex
+
+
+# user install...
+.PHONY: install
+install: pdf $(MODULE_CODE).cls
+	$(MD) $(INSTALL_PATH)/{tex,source,doc}/latex/$(MODULE)
+	$(INSTALL) "$(MODULE).pdf" $(INSTALL_PATH)/doc/latex/$(MODULE)
+	$(INSTALL) "$(MODULE_CODE).cls" $(INSTALL_PATH)/tex/latex/$(MODULE)/$(MODULE).cls
+#	# NOTE: we are printing only the stuff we are doing...
+	@run(){ echo "$$@" ;  "$$@" ; } ;\
+	if [[ $${CODE_INSTALL} == "link" ]] ; then \
+		run $(LN) \
+			"$(INSTALL_PATH)/tex/latex/$(MODULE)/$(MODULE).cls" \
+			"$(INSTALL_PATH)/source/latex/$(MODULE)/" ;\
+	else \
+		run $(INSTALL) "$(MODULE).cls" "$(INSTALL_PATH)/source/latex/$(MODULE)" ;\
+	fi
+
+.PHONY: uninstall
+uninstall:
+	rm -rf $(INSTALL_PATH)/{tex,source,doc}/latex/$(MODULE)
+	@echo "###"
+	@echo "### NOTE: this can leave the following dirs empty:"
+	@echo "###         $(INSTALL_PATH)/{tex,source,doc}/latex/"
+	@echo "###"
+
+
+# local/system install...
+# NOTE: this should be run with sudo, i.e.:
+# 			$ sudo make install-local
+.PHONY: install-local
+install-local: INSTALL_PATH := $(TEX_LOCAL)
+install-local: install
+
+.PHONY: uninstall-local
+uninstall-local: INSTALL_PATH := $(TEX_LOCAL)
+uninstall-local: uninstall
+
+
+# XXX need to make this work for windows...
+# 		...this must depend not on the OS but rather on in what context 
+# 		(cygwin/wsl/windows), latex is running...
+# 		...this seems to work:
+# 			> mkling TO FROM
+# 		but like ln, it's args are in the wrong order...
+# 		...cp -s creates links usable from cygwin but not usable from 
+# 		windows...
+.PHONY: install-devel
+install-devel: CODE_INSTALL := copy
+install-devel: INSTALL := cp -s
+install-devel: install
+
+.PHONY: uninstall-devel
+uninstall-devel: uninstall
+
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# Cleanup targets...
+
+.PHONY: sweep
+sweep:
+	rm -f \
+		*.{aux,fls,glo,gls,hd,idx,ilg,ind,ins,log,out,toc,fdb_latexmk} \
+		*-stripped.{tex,sty,cls} \
+		*-meta.{tex,sty,cls} \
+		${MODULE}.tex
+
+
+.PHONY: clean
+clean: sweep
+	rm -rf $(DIST_DIR) $(BUILD_DIR) $(MODULE).md *.pdf
+
+
+
+#----------------------------------------------------------------------
+#                                                   vim:set ts=4 sw=4 :


Property changes on: trunk/Master/texmf-dist/doc/latex/photobook/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/photobook/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/latex/photobook/README.md	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/photobook/README.md	2022-09-15 19:57:32 UTC (rev 64404)
@@ -0,0 +1,52 @@
+# photobook
+
+[LaTeX](https://www.latex-project.org/) document class for making photo books.
+
+
+## Build requirements for docs
+
+- LaTeX tool chain (including: `lualatex`, `latexmk`, ..)  
+  The simplest way to get started is [TeX Live](https://www.tug.org/texlive/), 
+  either a full install or for specific modules see the _Packages_ section 
+  in [photobook.cls](./photobook.cls),
+- Un\*x-like environment (`bash`, GNU Make, coreutils, ...),  
+  on Windows systems, either [Cygwin](https://www.cygwin.com/) or 
+  [WSL/WSL2](https://en.wikipedia.org/wiki/Windows_Subsystem_for_Linux) 
+  should work fine.
+
+
+
+## Build / Install
+
+```shell
+# get the source...
+$ git clone https://github.com/flynx/photobook.git
+
+# if desired, install in the user context...
+$ cd ./photobook
+$ make install
+```
+
+If only building the docs is required without installing:
+```shell
+$ make pdf 
+```
+
+For more info on `make` targets see the: [./Makefile](./Makefile)
+
+
+
+## Authors
+
+[Alex A. Naanou](https://github.com/flynx)
+
+
+
+## License
+
+[BSD 3-Clause License](./LICENSE)
+
+Copyright (c) 2021-2022, Alex A. Naanou,
+All rights reserved.
+
+


Property changes on: trunk/Master/texmf-dist/doc/latex/photobook/README.md
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/photobook/photobook.pdf
===================================================================
(Binary files differ)

Index: trunk/Master/texmf-dist/doc/latex/photobook/photobook.pdf
===================================================================
--- trunk/Master/texmf-dist/doc/latex/photobook/photobook.pdf	2022-09-15 19:55:43 UTC (rev 64403)
+++ trunk/Master/texmf-dist/doc/latex/photobook/photobook.pdf	2022-09-15 19:57:32 UTC (rev 64404)

Property changes on: trunk/Master/texmf-dist/doc/latex/photobook/photobook.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/photobook/scripts/cls2tex.sh
===================================================================
--- trunk/Master/texmf-dist/doc/latex/photobook/scripts/cls2tex.sh	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/photobook/scripts/cls2tex.sh	2022-09-15 19:57:32 UTC (rev 64404)
@@ -0,0 +1,156 @@
+#!/usr/bin/env bash
+#----------------------------------------------------------------------
+
+CMD="$0 $@"
+
+SCRIPT_NAME=$(basename $0)
+
+printusage(){
+	echo "Usage:"
+	echo "  $SCRIPT_NAME [OPTIONS] [[INPUT] OUTPUT]"
+}
+
+printhelp(){
+	echo "Generate docs from latex package/class"
+	echo
+	printusage
+	echo
+	echo "Options:"
+	echo "  -h | --help         Show this message and exit"
+	echo "  -p | --prefix PREFIX"
+	echo "                      Set the doc comment PREFIX (default: \"%\")"
+	echo "  -s | --strip        Strip docs out"
+	echo "  -n | --no-msg       Don't add the \"generated with\" message to output"
+	echo
+	echo "This will:"
+	echo "  - read the INPUT"
+	echo "  - keep lines starting with \\def\\<module-name>@[A-Z]\\+"
+	echo "  - keep lines starting with '%%'"
+	echo "  - %%%%% Text -> \\subsection(Text)"
+	echo "  - %%%% Text -> \\section(Text)"
+	echo "  - %% >> code -> \\begin{verbatim}code\\end{verbatim}"
+	echo "  - write the result to OUTPUT"
+	echo
+	echo "If no OUTPUT is given $SCRIPT_NAME will read stdout. If no INPUT"
+	echo "is given $SCRIPT_NAME will read stdin."
+	echo
+	echo "PREFIX can replace the second \"%\" in the above patterns to make it"
+	echo "possible to integrate multiple layers of documentation in one file"
+	echo "and to integrate them in various ways, for example, in the photobook"
+	echo "document class documentation \"M\" prefix is used to indicate"
+	echo "meta-command docs, this enables us to document them in the relevant"
+	echo "location (i.e. at the implementation) in source but move the docs to"
+	echo "a unified location in docs, effectively decoupling the source and doc"
+	echo "structure when needed."
+	echo
+	echo "Strip mode is the reverse of of the default, it will strip out docs"
+	echo "and empty lines, keeping only the actual code and code comments."
+	echo
+	echo "NOTE: stripping will not remove non-doc comments."
+	echo "NOTE: the idea of keeping latex docs in a latex file is far simpler"
+	echo "      than all the stuff crammed into .dtx, at least for my needs:"
+	echo "          - keep the code readable"
+	echo "          - keep the docs readable"
+	echo "      in both the repo and in installed form, so .dtx is not used."
+}
+
+# Usage: printerror MESSAGE...
+printerror(){
+	echo Error: $@
+	echo
+	printusage
+}
+
+# Usage: printmsg TEXT
+printmsg(){
+	# print message...
+	if [ -z $NO_MSG ] ; then 
+		echo "%----------------------------------------------------------------------"
+		echo "% $1 file generated by:" 
+		echo "%    $CMD"
+		echo "% NOTE: multiple messages indicate multiple runs."
+		echo "%----------------------------------------------------------------------"
+	fi
+}
+
+
+
+#----------------------------------------------------------------------
+# Args and defaults...
+
+PREFIX=%
+
+while true ; do
+	case $1 in
+		-h|--help)
+			printhelp
+			exit
+			;;
+		-p|--prefix)
+			PREFIX=$2
+			shift
+			shift
+			;;
+		-s|--strip)
+			STRIP_DOC=1
+			shift
+			;;
+		-n|--no-msg)
+			NO_MSG=1
+			shift
+			;;
+
+		# handle unknown options...
+		-*|--*)
+			printerror "unknown option \"$1\""
+			exit
+			;;
+
+		# non-flag, option parsing done...
+		*)
+			break
+			;;
+	esac
+done
+
+INPUT=${1:-/dev/stdin}
+
+OUTPUT=${2:-/dev/stdout}
+
+
+# generate the module name...
+MODULE=$(basename "$INPUT")
+MODULE=${MODULE/.*/}
+
+
+#----------------------------------------------------------------------
+# do the work...
+
+# make docs...
+if [ -z $STRIP_DOC ] ; then
+	printmsg "Documentation" \
+		> "$OUTPUT"
+	cat "$INPUT" \
+		| egrep '(^%'$PREFIX'|^\\edef\\'$MODULE'@[A-Z][A-Z]+)' \
+		| sed 's/^\(\\edef\\\)'$MODULE'@/%'$PREFIX'\1/' \
+		| sed 's/%'$PREFIX'%%%% \(.*\)/%'$PREFIX'\\subsubsection{\1}\\label{subsubsec:\1}/' \
+		| sed 's/%'$PREFIX'%%% \(.*\)/%'$PREFIX'\\subsection{\1}\\label{subsec:\1}/' \
+		| sed 's/%'$PREFIX'%% \(.*\)/%'$PREFIX'\\section{\1}\\label{sec:\1}/' \
+		| sed 's/%'$PREFIX'\s\+>>\s\+\(.*\)/%'$PREFIX'\\begin{verbatim} \1 \\end{verbatim}/' \
+		| cut -c 3- - \
+		>> "$OUTPUT"
+
+# make stripped code...
+else
+	printmsg "Stripped code" \
+		> "$OUTPUT"
+	cat "$INPUT" \
+		| egrep -v '%'$PREFIX'' \
+		| egrep -v '^(\s*%)?\s*$' \
+		>> "$OUTPUT"
+fi
+
+
+
+#----------------------------------------------------------------------
+#                                           vim:set ts=4 sw=4 nowrap :


Property changes on: trunk/Master/texmf-dist/doc/latex/photobook/scripts/cls2tex.sh
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+LF
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/doc/latex/photobook/scripts/make-images.sh
===================================================================
--- trunk/Master/texmf-dist/doc/latex/photobook/scripts/make-images.sh	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/latex/photobook/scripts/make-images.sh	2022-09-15 19:57:32 UTC (rev 64404)
@@ -0,0 +1,449 @@
+#!/bin/bash
+shopt -s nullglob extglob
+
+#----------------------------------------------------------------------
+#
+# Template structure:
+#	templates/
+#		imagepage.tex
+#		textpage.tex
+#		...
+#	$IMAGE_DIR/
+#		$spread/
+#			tweaks.tex
+#				template tweaks.
+#				loaded before the templates are handled.
+#			layout.tex
+#				manual layout of spread.
+#				if given rest of directory contents are 
+#				ignored.
+#				fields:
+#					${IMAGE0}
+#					${CAPTION0}
+#					${IMAGE1}
+#					${CAPTION1}
+#				NOTE: if images are included, hi-res source
+#					substitution is not done here.
+#			<spread-template-name>.tpl
+#				indicates the spread template to use.
+#				if given the rest of the .tex files in 
+#				directory are ignored.
+#				resolves to:
+#					templates/<spread-template-name>.tex
+#				fields:
+#					${IMAGE0}
+#					${CAPTION0}
+#					${IMAGE1}
+#					${CAPTION1}
+#			imagepage.tex
+#				image page template.
+#				fields:
+#					${IMAGE}
+#					${CAPTION}
+#			textpage.tex
+#				text page template.
+#				fields:
+#					${TEXT}
+#			<spread-template-name>-imagepage.tpl
+#			<spread-template-name>-textpage.tpl
+#				indicates the image/text page template to use.
+#				ignored if explicit templates are given.
+#				image fields:
+#					${IMAGE}
+#					${CAPTION}
+#				text fields:
+#					${TEXT}
+#			00-<image>.png
+#				image.
+#				if $IMAGE_HIRES_DIR is set then this will 
+#				resolve to:
+#					$IMAGE_HIRES_DIR/<image>
+#				XXX hi-res substitution currently disabled.
+#			01-<text>.txt
+#				text.
+#			...
+#		...
+#
+#
+#
+# Env variables:
+#	IMAGE_HIRES_DIR=<path>
+#		sets the path to which the hi-res images are resolved.
+#
+#
+#
+#
+# XXX TODO:
+#		- revise printed comments...
+#		- add real arg handling...
+#		- add abbility to apply template to a specific page in spread...
+#			...something like:
+#				<template-name>-left.tpl
+#				<template-name>-right.tpl
+#
+#
+#
+#----------------------------------------------------------------------
+
+# defaults...
+
+CFG_FILE=`basename $0`.cfg
+
+TEMPLATE_PATH=templates/
+
+IMAGE_DIR=pages/
+
+#IMAGE_HIRES_DIR=
+
+
+# Default timplates
+#SINGLE_IMAGE=blank-image
+SINGLE_IMAGE=imagebleedleft
+DOUBLE_IMAGE=image-image
+
+
+# load config...
+[ -e $CFG_FILE ] && source $CFG_FILE
+
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+printhelp(){
+	echo "Usage: `basename $0` [ARGUMENTS] [PATH]"
+	echo "       `basename $0` [ARGUMENTS] PATH FROM [COUNT]"
+	echo
+	echo "Generate LaTeX layout from directory structure."
+	echo
+	echo "Arguments:"
+	echo "  -h --help   - print this help and exit."
+	echo "  --templates=PATH"
+	echo "              - path to search for templates (default: $TEMPLATE_PATH)."
+	echo "  --single-image-tpl=NAME"
+	echo "              - single image default template (default: $SINGLE_IMAGE)."
+	echo "  --double-image-tpl=NAME"
+	echo "              - double image default template (default: $DOUBLE_IMAGE)."
+	echo
+	echo "Parameters:"
+	echo "  PATH        - path to root pages directory (default: $IMAGE_DIR)"
+	echo "  FROM        - spread to start from (default: 0)"
+	echo "  COUNT       - number of spreads to generate (default: 1)"
+	echo
+	echo "Environment:"
+	echo "  \$IMAGE_HIRES_DIR "
+	echo "              - source directory for replacement hi-res images."
+	echo "  \$ANOTATE_IMAGE_PATHS "
+	echo "              - if true add image paths in anotations."
+	echo
+	echo "Configuration defaults can be stored in a config file: $CFG_FILE"
+	echo
+	echo "NOTE: COUNT is relevant iff FROM is given, otherwise all available "
+	echo "        spreads are generated."
+	echo
+	echo "Examples:"
+	echo "  $ `basename $0` ./pages > pages.tex"
+	echo "              - generate a layout fron the contents of ./pages"
+	echo
+	echo "  $ IMAGE_HIRES_DIR=images/hi-res `basename $0` ./pages"
+	echo "              - generate a layout fron the contents of ./pages and "
+	echo "                replaceing local images with images in ./images/hi-res"
+	echo
+}
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# handle arguments...
+
+while true ; do
+	case $1 in
+		-h|--help)
+			printhelp
+			exit
+			;;
+
+		--templates)
+			TEMPLATE_PATH=$2
+			shift
+			shift
+			;;
+		--single-image-tpl)
+			SINGLE_IMAGE=$2
+			shift
+			shift
+			;;
+		--double-image-tpl)
+			DOUBLE_IMAGE=$2
+			shift
+			shift
+			;;
+
+		# handle unknown options...
+		-*|--*)
+			echo "Error: unknown option \"$1\""
+			exit
+			;;
+
+		*)
+			break
+			;;
+	esac
+done
+
+
+if [ -z $1 ] ; then
+	IMAGE_DIR=pages/
+else
+	IMAGE_DIR=$1/
+fi
+
+
+# calculate spread index range...
+# XXX add support for negative indexing...
+FROM=$2
+COUNT=$( [ -z $3 ] && echo 1 || echo $3 )
+STOP=$(( FROM + COUNT ))
+
+
+
+#----------------------------------------------------------------------
+
+# XXX should we report images w/o captions???
+getCaption(){
+	local C=`basename "${1%.*}"`
+	#C="${C/[0-9]-}"
+	C="captions/${C}.txt"
+
+	if [ -e "${C}" ] ; then
+		C=`cat "${C}" | sed 's/\\\/\\\\\\\/g'`
+	else
+		C=""
+	fi
+
+	echo ${C[*]}
+}
+
+getTemplate(){
+	local SPREAD=$1
+	local TYPE=$2
+	local TEMPLATE=($SPREAD/*-$TYPE.tex)
+	if [ -z $TEMPLATE ] ; then
+		TEMPLATE=($SPREAD/*-$TYPE.tpl)
+		if ! [ -z $TEMPLATE ] ; then
+			TEMPLATE=${TEMPLATE/$SPREAD\//}
+			TEMPLATE=${TEMPLATE/[0-9]-/}
+			TEMPLATE="$TEMPLATE_PATH/${TEMPLATE[0]%-${TYPE}.*}.tex"
+		fi
+	fi
+	if [ -z $TEMPLATE ] ; then
+		 TEMPLATE="$TEMPLATE_PATH/${TYPE}.tex"
+	fi
+	echo $TEMPLATE
+}
+
+anotatePath(){
+	if [ -z "$1" ] || [ -z "$ANOTATE_IMAGE_PATHS" ] ; then
+		return
+	fi
+	path=$(basename ${1%.*})
+	# NOTE: did not figure out how to make a verbatim comment in latex 
+	#		so here we are, doing it in shell...
+	path=${path//_/\\_}
+	#echo "\\pdfmargincomment{Image: $path}%"
+	echo "\\pdfcommentcell{Image: $path}%"
+}
+
+
+#----------------------------------------------------------------------
+
+
+echo %----------------------------------------------------------------------
+echo %
+echo % WARNING: This file is auto-generated by make-images.sh and will be 
+echo "%          overwritten on next run..."
+echo %
+echo "% Image source (preview): \"$IMAGE_DIR\""
+echo "% Image source (hi-res): \"$IMAGE_HIRES_DIR\""
+echo %
+echo %----------------------------------------------------------------------
+echo %
+#echo % set image source directory...
+#echo "\\graphicspath{{${IMAGE_DIR}}}"
+#echo %
+#echo %----------------------------------------------------------------------
+#echo %
+#
+#cd ${IMAGE_DIR}
+
+l=$(ls "$IMAGE_DIR/" | wc -l)
+c=0
+
+for spread in "${IMAGE_DIR}"/* ; do
+	# skip non-spreads...
+	if ! [ -d "$spread" ] ; then
+		continue
+	fi
+
+	c=$(( c + 1 ))
+
+	# if $FROM is given print only stuff in range...
+	[ -z $FROM ] \
+		|| if (( $(( c - 1 )) < $FROM )) || (( $c > $STOP )) ; then
+			continue
+		fi
+
+	# if we are building only a specific spread...
+	##if ! [ -z $SPREAD ] && [[ "$spread" != "$IMAGE_DIR/$SPREAD" ]]; then
+	##	continue
+	##fi
+
+	if ! [ -z $SKIP_FIRST ] ; then
+		echo %
+		echo %
+		echo % - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+	fi
+	SKIP_FIRST=1
+	# skip temporarily disabled...
+	if [ -z ${spread/-*/} ] ; then
+		echo "% spread: ${spread/-/}: skipped..." | tee >(cat >&2)
+		echo %
+		continue
+	else
+		printf "Spread ($c/$l): ${spread/-/}                         \r" >&2
+		echo "% spread: ${spread/-/}"
+	fi
+
+
+	# auto layout / templates...
+	# NOTE: to use a specific template just `touch <template-name>.tpl`
+	#	in the spread directory...
+
+	# layout tweaks...
+	tweaks=($spread/*tweak.tex)
+	if ! [ -z ${tweaks} ] ; then
+		echo "% tweaks: ${tweaks[0]}"
+		cat ${tweaks[0]}
+	fi
+
+
+	# NOTE: we also get *.txt files here...
+	items=($spread/*.!(tex|tpl|bak))
+
+	# get hi-res image paths...
+	if ! [ -z $IMAGE_HIRES_DIR ] ; then
+		C=0
+		for img in "${items[@]}" ; do
+			# skip non-images...
+			if [[ "$img" == "${img/.txt/}" ]] ; then
+				#new="../$IMAGE_HIRES_DIR/`basename ${img/[0-9]-/}`"
+				new="$IMAGE_HIRES_DIR/`basename ${img/[0-9]-/}`"
+				# ignore file ext for availability test...
+				# NOTE: the first match may be an unsupported format...
+				new="${new%.*}"
+				new=($new.*)
+				if [ -e "${new[0]}" ] ; then
+					items[$C]=${new[0]}
+				else
+					echo %
+					echo "% WARNING: hi-res image not found for: \"${img}\" -> \"${new}\"" | tee >(cat >&2)
+					echo %
+				fi
+			fi
+			C=$(( C + 1 ))
+		done
+	fi
+
+
+	# manual layout...
+	layout=($spread/*layout.tex)
+	if ! [ -z $layout ] ; then
+		TEMPLATE=${layout[0]}
+
+	# templates and partial templates...
+	else
+		# spread template...
+		TEMPLATE=($spread/*.tpl)
+		# skip page template refs: *-imagepage.tpl / *-textpage.tpl
+		# XXX this will also eat 0-imagepage.tpl / 20-textpage.tpl -- do a better pattern...
+		if ! [ -z $TEMPLATE ] ; then
+			TEMPLATE=(`ls "$spread/"*.tpl | egrep -v '.*-(imagepage|textpage)\.tpl'`)
+		fi
+		# no template explicitly defined -> match auto-template...
+		AUTO=
+		if [ -z $layout ] && [ -z $TEMPLATE ] ; then
+			AUTO=" (auto)"
+			if [ ${#items[@]} == 1 ] ; then
+				TEMPLATE=$SINGLE_IMAGE
+
+			# multiple items...
+			else 
+				C=0
+				for img in "${items[@]}" ; do
+					C=$(( C + 1 ))
+					P=`[ $C == 1 ] && echo "left" || echo "right"`
+
+					# image...
+					if [ "${img/.txt/}" == "${img}" ] ; then
+						echo %
+						echo "% $P page (image)..."
+						TEMPLATE=`getTemplate "$spread" "imagepage"`
+						echo % page template: $TEMPLATE
+						anotatePath "${img}"
+						CAPTION=`getCaption "${img}"`
+						cat "${TEMPLATE}" \
+							| sed "s%\${IMAGE0\?}%${img%.*}%" \
+							| sed "s%\${CAPTION0\?}%${CAPTION}%"
+
+					# text...
+					else
+						echo %
+						echo "% $P page (text)..."
+						TEMPLATE=`getTemplate "$spread" "textpage"`
+						echo % page template: $TEMPLATE
+						cat "${TEMPLATE}" \
+							| sed "s%\${TEXT}%${img}%"
+					fi
+
+					# reset for next page...
+					TEMPLATE=
+					# only two pages at a time...
+					[ $C == 2 ] && break
+				done
+			fi
+		fi
+		# formatting done...
+		[ -z $TEMPLATE ] && continue
+
+		# format...
+		TEMPLATE=${TEMPLATE/$spread\//}
+		TEMPLATE=${TEMPLATE/[0-9]-/}
+		# get...
+		TEMPLATE="$TEMPLATE_PATH/${TEMPLATE[0]%.*}.tex"
+	fi
+
+	# captions...
+	CAPTION0=`getCaption "${items[0]}"`
+	CAPTION1=`getCaption "${items[1]}"`
+
+	echo "% template: (template${AUTO}: $TEMPLATE)"
+	anotatePath "${items[0]}"
+
+	# fill the template...
+	cat "${TEMPLATE}" \
+		| sed "s%\${IMAGE0\?}%${items[0]%.*}%" \
+		| sed "s%\${CAPTION0\?}%${CAPTION0}%" \
+		| sed "s%\${IMAGE1}%${items[1]%.*}%" \
+		| sed "s%\${CAPTION1}%${CAPTION1}%"
+done
+
+echo %
+echo %
+echo %
+echo %----------------------------------------------------------------------
+echo
+
+echo "Spread created: $c of $l                                         " >&2
+
+
+
+#----------------------------------------------------------------------
+# vim:set ts=4 sw=4 :


Property changes on: trunk/Master/texmf-dist/doc/latex/photobook/scripts/make-images.sh
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+LF
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/latex/photobook/photobook.cls
===================================================================
--- trunk/Master/texmf-dist/tex/latex/photobook/photobook.cls	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/latex/photobook/photobook.cls	2022-09-15 19:57:32 UTC (rev 64404)
@@ -0,0 +1,5058 @@
+%----------------------------------------------------------------------
+%
+%
+% This does the following:
+%	- sets up the document/pdf for viewing as a book
+%	- adds support for page bleeds
+%	- adds basic templates for image pages
+%
+%
+% This file contains both the code and the reference, but in a slightly 
+% more readable format than the traditional LaTeX .dtx format. In general
+% there are two main sections:
+%	- code
+%	- reference
+%		lines starting with "%%" or "%X" where X is a section id
+% Sections are parts of the reference that are logically ordered differently 
+% than the code, e.g. main user tools should have priority in the reference 
+% while meta code (identified by "%M") can be described later, while in code
+% we strictly need to define macros before they are used thus meta-macros
+% and other building blocks and components come before the user tools.
+%
+% Docs are build by the Makefile, so reference it for more info.
+%
+%	$ make doc
+%
+%
+% NOTE: in a stripped code install this file may contain only code and 
+%		code comments, in this case, to see the docs refer to either the 
+%		source or the actual documentation/pdf.
+% NOTE: the stripped code file is auto-generated, it is not recommended 
+%		to edit it directly, edit the source instead.
+%
+%
+% XXX Q: do we add the pdf to the repo and if so, should it be 
+%		compressed (diff-able) or uncompressed (blob)??
+% XXX revise \clearcaption / \captionclearpage...
+% XXX unify API -- see CellContent env...
+% XXX make this loadable both as a class and as a package...
+%		\@ifclassloaded{photobook}{<true>}{<false>}
+% XXX revise command naming -- should be obvious from name what is what:
+%		- meta commands -- ??? (currently same as templates)
+%		- general macros -- \usecell{..}
+%		- templates --  \ImagePage{..}
+% XXX see where we need to \ignorespaces...
+% XXX might be a good idea to add a spine calculator...
+% XXX add list of dependencies to docs...
+% XXX manual / book:
+%		- basic usage
+%			- setup
+%			- templates (copyright, front matter, back matter, acknowledgements, ...)
+%			- using templates
+%			- pre-print
+%		- customizing
+%		- extending
+%
+%
+%----------------------------------------------------------------------
+
+%%% NOTE: \def\<module-name>@[A-Z]+ macros will be visible to both the 
+%%%		code and the generated docs...
+\edef\photobook at FILEVERSION{v0.1}
+\edef\photobook at FILEDATE{2021-07-28}
+
+
+%% \documentclass{ltxdoc}
+%%
+%%% \usepackage{iftex}
+%%% \ifluatex
+%%% 	\edef\pdfcompresslevel{\pdfvariable compresslevel} 
+%%% 	\edef\pdfobjcompresslevel{\pdfvariable objcompresslevel}
+%%% \fi
+%%% \pdfcompresslevel 0
+%%% \pdfobjcompresslevel 0
+%% 
+%% \usepackage[a4paper,margin=25mm,left=55mm,nohead]{geometry}
+%%
+%% % NOTE: this needs to load before hyperref or bookmarks will break...
+%% % NOTE: loading hyperref here will break it loading later in one of 
+%% %		the packages...
+%% \usepackage{titlesec}
+%%
+%% \usepackage[numbered]{hypdoc}
+%% \usepackage{doctools}
+%% \usepackage{needspace}
+%%
+%% \usepackage[toc]{multitoc}
+%% \renewcommand*{\multicolumntoc}{2}
+%% \setlength{\columnseprule}{0.5pt}
+%%
+%% \usepackage{imakeidx}
+%% \makeindex[
+%%		columns=1, 
+%%		title=Alphabetical Index, 
+%%		intoc,
+%%		options= -s photobook.ist ]
+%%
+%%% \newcommand\DescribeGlobal[1]{%
+%%%	\DescribeMacro{#1}}
+%%
+%% \newcommand\LEGACY[1][]{\fbox{LEGACY #1}}
+%% \newcommand\EXPERIMENTAL[1][]{\fbox{EXPERIMENTAL #1}}
+%%
+%%% sections to new pages...
+%% \newcommand\sectionbreak{\Needspace{5\baselineskip}}
+%%
+%% % remove section numbering...
+%% \setcounter{secnumdepth}{0}
+%%
+%% % paragraph configuration...
+%% \setlength\parindent{0pt}
+%% \setlength\parskip{0.5em}
+%% 
+%% \newcommand\blankfootnote[1]{%
+%% 	\begingroup
+%% 		\renewcommand\thefootnote{}%
+%% 		\footnote{#1}%
+%% 		\addtocounter{footnote}{-1}%
+%% 	\endgroup}
+%%
+%%
+%% \begin{document}
+%%
+%% \title{\textsf{photobook} --- Document class for building photo-books
+%%		\thanks{This file describes version \FILEVERSION, 
+%%			last revised \FILEDATE.}}
+%%
+%% \author{Alex A. Naanou\thanks{E-mail: alex.nanou at gmail.com}}
+%%
+%% \date{Released \FILEDATE}
+%%
+%%
+%% \maketitle
+%%
+%% \begin{abstract}
+%%	The |photobook| \LaTeX\space document class extends the |book| class 
+%%	defining a set of parameters, meta-macros, macros and environments 
+%%	with reasonable defaults to help typeset, build and print books mainly 
+%%	based on visual/image content.
+%% \end{abstract}
+%%
+%% \tableofcontents
+%%
+%
+%%%% Introduction
+%
+%% \LaTeX\ is great with textual and text-primary content with figures
+%% peppered in, as long as pictures/figures flow within, with or as part
+%% of text, vanilla \LaTeX\ is fantastic.
+%% 
+%% One can relatively easily stretch the flow concept to more complex
+%% layouts introducing {\it even} and {\it odd} pages (the |book| class is 
+%% one example) and flow rules based on them, but the next step, {\it bleeds}, 
+%% combining page pairs into {\it spreads} as is often needed when designing 
+%% image-oriented books is lacking. Full-bleed images/pages can be implemented 
+%% manually, some more effort is needed to split something horizontally 
+%% into a page spread, but doing so for whole book's worth of content is 
+%% not practical -- automating and experimenting with this process is 
+%% how |photobook| began.
+%% 
+%% |photobook| extends the |book| class adding page layout types, bleeds
+%% and other global geometry configuration, introduces the {\it page} and
+%% {\it spread} as first-class elements into the document flow. These concepts
+%% are generalized as |cell|s. A |cell| is similar to a figure, it can
+%% be placed within the document flow, but unlike a figure a |cell| can
+%% be aligned relative to a page, it can fill a page, a cell can even be
+%% horizontally split to fill several pages (how spreads are implemented).
+%% 
+%% On top of the |cell|, {\it page}, and {\it spread} concepts, |photobook| 
+%% also builds a set of configurable high level macros and templates for 
+%% common use cases like full bleed image spreads, foldouts, ... etc.
+%
+%
+%%%% Usage
+%
+%%	>> \documentclass[<options>]{photobook}
+%%
+%
+%----------------------------------------------------------------------
+
+\NeedsTeXFormat{LaTeX2e}
+
+\ProvidesClass{photobook}
+	[\photobook at FILEDATE \space \photobook at FILEVERSION Photo book document class]
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%%%% Options
+%%
+
+\edef\photobook at options{\@classoptionslist}
+
+\RequirePackage{kvoptions}
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Helpers...
+
+\newcommand\@DeclareLiteralOptionTo[2]{%
+	\DeclareVoidOption{#2}{%
+		\expandafter\edef\csname photobook@#1\endcsname{#2}}}
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%%%%% Page geometry
+%
+%% \DescribeMacro{blockwidth=<len>}
+%% \DescribeMacro{blockheight=<len>}
+%% \DescribeMacro{bindingoffset=<len>}
+%% \DescribeMacro{bleed=<len>}
+%
+%% This is similar to what |geometry| does, but adds bleed support.
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%   <---> bleed                                 <---> bleed
+%%
+%%   + - - - - - - - - - - - - - - - - - - - - - + - +   ^
+%%   .                                           .   .   | bleed
+%%   .   +---------------------------------------+-----  v   .   .  ---
+%%   .   |                           ^       .   =   .
+%%   .   |   .   .   .   .   .   .   |   .   .   =   .               ^
+%%   .   |<-- blockwidth ----------------------->=   .               |
+%%   .   |   .                       |   .   .   =   .               |
+%%   .   |                           |       .   =   .       textheight
+%%   .   |   .             Page      |   .   .   =   .               |
+%%   .   |                      blockheight  .   =   .               |
+%%   .   |   .                       |   .   .   =   .               |
+%%   .   |                           |       <---> bindingoffset     |
+%%   .   |   .   .   .   .   .   .   |   .   .   =   .               v
+%%   .   |                           v       .   =   .
+%%   .   +---------------------------------------+-----  ^   .   .  ---
+%%   .   .                                       .   .   | bleed
+%%   + - - - - - - - - - - - - - - - - - - - - - + - +   v
+%%       .                                       .
+%%       |   <-- textwidth -------------->   .   |
+%%                                               ^ binding line
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+% NOTE: if blockwidth/blockheight are set they will force recalculations 
+%		and overriding of the paperwidth/paperheight if they were changed
+%		by the user code anywhere between \documentclass[..]{photobook}
+%		and \begin{document}...
+\DeclareStringOption{blockwidth}
+\DeclareStringOption{blockheight}
+\DeclareStringOption[0pt]{bindingoffset}[10mm]
+\DeclareStringOption[5mm]{bleed}[5mm]
+
+%% \DescribeMacro{flatfold=<len>}
+%
+%% Sets the clearance set aside for a flat fold, used for foldouts 
+%% (see: \nameref{subsec:Foldout page cells} section).
+%%
+\DeclareStringOption[0pt]{flatfold}[0.2mm]
+
+%% \DescribeMacro{pagefold=<fold>}
+%
+%% Sets the default fold type.
+%%
+%% Can be |in| or |out|.
+%%
+% XXX check values...
+\DeclareStringOption{pagefold}
+
+%% \DescribeMacro{foldout=<fold-spec>}
+%
+%% Sets the default fold specification (i.e. sets |\defaultfoldout|).
+%%
+%% For more information see: \nameref{subsec:Foldout page cells} section.
+%%
+\DeclareStringOption[2]{foldout}[2]
+
+
+
+%%%%% layout
+%
+%% \DescribeMacro{layoutmode=<layout>}
+%% \DescribeMacro{block}
+%% \DescribeMacro{endpaper}
+%% \DescribeMacro{cover}
+%% \DescribeMacro{jacket}
+%
+%% Sat page layout mode.
+%
+%%	>> layoutmode=<option>
+%%
+%% |block| (default)
+%%
+%%	Basic page layout.
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%       blockwidth
+%%   <--------------->
+%%
+%%   +---------------+
+%%   |               |
+%%   |               |
+%%   |     page      |
+%%   |               |
+%%   |               |
+%%   +---------------+
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%%
+%% |endpaper|:
+%%
+%%	Endpaper layout.
+%%
+% XXX should this use \flatfold???
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%       blockwidth 2x
+%%   <------------------------------->
+%%
+%%   +---------------+---------------+
+%%   |               .               |
+%%   |               .               |
+%%   |           endpaper            |
+%%   |               .               |
+%%   |               .               |
+%%   +---------------+---------------+
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%	
+%%
+%% |cover|
+%%
+%%	Book cover layout
+%%
+%% \DescribeMacro{coverboardgrow=<len>}
+%% \DescribeMacro{coverflap=<len>}
+%% \DescribeMacro{spinewidth=<len>}
+%% \DescribeMacro{spinewidth=<len>}
+%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%          blockwidth            blockwidth
+%%       <--------------->     <--------------->
+%%     <-> coverboardgrow                      <-> coverboardgrow
+%%   <-> coverflap                             . <-> coverflap
+%%   . . .                                     . . .
+%%   +-------------------++---++-------------------+    ---
+%%   | + - - - - - - - - ++ - ++ - - - - - - - - + |    --^ coverflap                
+%%   | . + - - - - - - - ++ - ++ - - - - - - - + . |    --^ coverboardgrow  
+%%   | . .               ..   ..               . . |     ^                  
+%%   | . .               ..   ..               . . |     | blockheight      
+%%   | . .     Back      ..   ..     Front     . . |     |                  
+%%   | . .               ..   ..               . . |     |                  
+%%   | . .               ..   ..               . . |     v                  
+%%   | . + - - - - - - - ++ - ++ - - - - - - - + . |    --v coverboardgrow  
+%%   | + - - - - - - - - ++ - ++ - - - - - - - - + |    --v coverflap                 
+%%   +-------------------++---++-------------------+    ---
+%%                        .   .
+%%                       ^.   .^ spinefold
+%%                        .   .
+%%                        <---> spinewidth
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%%
+%% |jacket|
+%%
+%%	Dust jacket layout
+%%
+%% \DescribeMacro{jacketwrap=<len>}
+%% \DescribeMacro{jacketflap=<len>}
+%% \DescribeMacro{jacketflapfront=<len>}
+%% \DescribeMacro{jacketflapback=<len>}
+%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%   <---> jaketflap/jacketflapback                  <---> jaketflap/jacketflapfront
+%%   .   .                                           .   .
+%%   .   .     blockwidth            blockwidth      .   .
+%%   .   .  <--------------->     <--------------->  .   .
+%%   .   .<-> coverboardgrow                      <-> coverboardgrow
+%%   .   .  .                                     .  .   .
+%%   +---++-----------------++---++-----------------++---+    ---
+%%   |   .. + - - - - - - - ++ - ++ - - - - - - - + ..   |    --^ coverboardgrow
+%%   |   .. .               ..   ..               . ..   |     ^
+%%   |   .. .               ..   ..               . ..   |     | blockheight
+%%   |   .. .     Back      ..   ..     Front     . ..   |     |
+%%   |   .. .               ..   ..               . ..   |     |
+%%   |   .. .               ..   ..               . ..   |     v
+%%   |   .. + - - - - - - - ++ - ++ - - - - - - - + ..   |    --v coverboardgrow
+%%   +---++-----------------++---++-----------------++---+    --- 
+%%       ..                  .   .                  ..
+%%       ^ jacketwrap        .   .                  ^ jacketwrap
+%%                          ^.   .^ spinefold
+%%                           .   .
+%%                           <---> spinewidth
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%
+% XXX in cover layout setup pdf boxes in a way to use \bleed as foldover...
+% 		...see hyperref docs to set pdf view/print area (???)
+%		.....should also set \bleed default to something like 17mm
+% XXX do we need to implement cover fold over???
+% XXX fold/cut marks???
+\DeclareStringOption[block]{layoutmode}[block]
+\@DeclareLiteralOptionTo{layoutmode}{block}
+%\@DeclareLiteralOptionTo{layoutmode}{web}
+\@DeclareLiteralOptionTo{layoutmode}{endpaper}
+% XXX add overhang...
+% XXX minght be a good idea to add cover types as separate values and 
+%		preset defeaults per type, e.g:
+%			layoutmode=		hardcover	softcover
+%		should also set: 
+%			spinefold=		5mm			5mm
+%			coverflap=		17mm		0mm
+%			bleed=			0mm			5mm
+\@DeclareLiteralOptionTo{layoutmode}{cover}
+%\@DeclareLiteralOptionTo{layoutmode}{hardcover}
+%\@DeclareLiteralOptionTo{layoutmode}{softcover}
+\@DeclareLiteralOptionTo{layoutmode}{jacket}
+
+
+% NOTE: this is only used when layoutmode=cover
+% NOTE: these are documented inline with layoutmode=.. docs...
+\DeclareStringOption[0pt]{spinewidth}[0pt]
+\DeclareStringOption[0pt]{spinefold}[7mm]
+\DeclareStringOption[0pt]{coverboardgrow}[3mm]
+\DeclareStringOption[0pt]{coverflap}[17mm]
+\DeclareStringOption[0pt]{jacketwrap}[2mm]
+\DeclareStringOption[0pt]{jacketflap}[50mm]
+\DeclareStringOption[0pt]{jacketflapfront}[50mm]
+\DeclareStringOption[0pt]{jacketflapback}[50mm]
+
+
+
+%%%%% Image clearance
+%
+%% \DescribeMacro{clearimage=<len>}
+%
+%% Distance from image to paper border (clearance) for full-page images.
+%%
+%% this can be:
+%% - negative value set image bleed, 
+%% - positive value set distance from paper edge to image.
+%%
+\DeclareStringOption{clearimage}[10mm]
+
+
+%%%%% Image block layout
+%
+%% \DescribeMacro{imageblockwidth=<len>}
+%% \DescribeMacro{imageblockheight=<len>}
+%% \DescribeMacro{imageblockoffsettop=<len>}
+%
+%% Image block size relative to text block.
+%%
+\DeclareStringOption[0.85]{imageblockwidth}[1]
+\DeclareStringOption[0.85]{imageblockheight}[1]
+\DeclareStringOption[-0.05]{imageblockoffsettop}[0]
+
+%%%%% PDF Viewer layout
+%
+%% \DescribeMacro{pdfpagelayout=<mode>}
+%% \DescribeMacro{SinglePage}
+%% \DescribeMacro{OneColumn}
+%% \DescribeMacro{TwoColumnLeft}
+%% \DescribeMacro{TwoColumnRight}
+%% \DescribeMacro{TwoPageLeft}
+%% \DescribeMacro{TwoPageRight}
+%
+%% Sets PDF page display mode.
+%%
+%% Defaults to |TwoColumnLeft| for |layoutmode=block| and |SinglePage| for
+%% other modes.
+%%
+%% See: 
+%% \href{https://ctan.altspu.ru/macros/latex/contrib/hyperref/doc/hyperref-doc.pdf}{hyperref}'s 
+%% |pdfpagelayout| for more options.
+%%
+\DeclareStringOption{pdfpagelayout}
+\@DeclareLiteralOptionTo{pdfpagelayout}{SinglePage}
+\@DeclareLiteralOptionTo{pdfpagelayout}{OneColumn}
+\@DeclareLiteralOptionTo{pdfpagelayout}{TwoColumnRight}
+\@DeclareLiteralOptionTo{pdfpagelayout}{TwoColumnLeft}
+\@DeclareLiteralOptionTo{pdfpagelayout}{TwoPageRight}
+\@DeclareLiteralOptionTo{pdfpagelayout}{TwoPageLeft}
+
+
+%%%%% Other options
+%
+%% \DescribeMacro{nofoldmarks}
+%
+%% If given disable fold marks.
+%%
+%% This sets |\iffoldmarks| to false, otherwise it is set to true.
+%%
+\DeclareBoolOption{nofoldmarks}
+
+%% \DescribeMacro{foldmarksize=<len>}
+%
+%% Sets the fold mark size (default: 6mm).
+%%
+\DeclareStringOption[6mm]{foldmarksize}
+
+%% \DescribeMacro{geometrynodefaults}
+%
+%% let the user set geometry defaults.
+%%
+%%	If this is not set |photobook| will override some user settings when
+%%	initializing geometry.
+%%
+%%	If set |photobook| will only set override:
+%%	\begin{verbatim}
+%%		paperwidth=\bleedblockwidth
+%%		paperheight=\bleedblockheight
+%%		bindingoffset=\bindingoffset
+%%	\end{verbatim}
+%%
+\DeclareBoolOption{geometrynodefaults}
+
+%% \DescribeMacro{roundprintedlengthsto=<num>}
+%
+%% Number of digits to round printed lengths to (default: 1).
+%%
+%% This is a shorthand to |numprint|'s |\nprounddigits{..}|, us it to 
+%% change values mid-document if needed.
+%%
+%% This is mostly used for |\GenerateTemplate|.
+%%
+\DeclareStringOption[1]{roundprintedlengthsto}[1]
+
+
+\DeclareDefaultOption{\PassOptionsToClass{\CurrentOption}{book}}
+\ProcessKeyvalOptions*
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Parent class...
+%
+\LoadClass[9pt, final, openany]{book}
+
+
+
+%----------------------------------------------------------------------
+% Packages...
+%
+% NOTE: imports are after \LoadClass{ .. } to avoid figting over macro
+%		names...
+
+\RequirePackage{calc}
+\RequirePackage{xargs}
+\RequirePackage{ifthen}
+\RequirePackage{iftex}
+\RequirePackage{pgffor}
+\RequirePackage{xint}
+\RequirePackage{xinttools}
+\RequirePackage{listofitems}
+\RequirePackage{xkeyval} 
+\RequirePackage{etoolbox}
+\RequirePackage{atbegshi}
+%\RequirePackage{afterpage}
+%\RequirePackage{changepage}
+\RequirePackage[unicode]{hyperref}
+%\RequirePackage{pdfcomment}
+\RequirePackage{eso-pic}
+\RequirePackage{environ}
+\RequirePackage{numprint}
+\RequirePackage{trimclip}
+\RequirePackage{xcolor}
+\RequirePackage{colorspace}
+\RequirePackage{graphicx}
+\RequirePackage{adjustbox}
+\RequirePackage[absolute]{textpos}
+\RequirePackage{fancyvrb}
+\RequirePackage{tikz}
+%\RequirePackage[linewidth=1pt]{mdframed}
+% XXX flow text frames...
+% XXX this messes with geometry....
+%\RequirePackage{flowfram}
+\RequirePackage{rotating}
+\RequirePackage{fancyhdr}
+\RequirePackage{pdfpages}
+
+
+
+%----------------------------------------------------------------------
+%%%% Globals
+% XXX move these out to relevant sections + add a separate globals glossary...
+%
+% NOTE: most of these are setup in \InitPages...
+
+%%% \DescribeGlobal{layoutmode}
+%% \DescribeMacro{\layoutmode=<mode>}
+%
+%%	Layout mode
+%%
+\edef\layoutmode{\photobook at layoutmode}
+
+% layout mode tests...
+\newif\ifcoverlayout
+\newif\ifhardcoverlayout
+\newif\ifsoftcoverlayout
+\newif\ifendpaperlayout
+\newif\ifjacketlayout
+% aggregates...
+\newif\ifcoverlikelayout
+\newif\ifblocklayout
+
+%% \DescribeMacro{\pdfpagelayout=<mode>}
+%
+%%	Controls the default layout in the pdf viewer.
+%%
+\edef\pdfpagelayout{\photobook at pdfpagelayout}
+
+%% \DescribeMacro{\spinewidth=<len>}
+%
+%%	Spine width
+%%
+\newlength\spinewidth
+\setlength\spinewidth{\photobook at spinewidth}
+
+%% \DescribeMacro{\spinefold=<len>}
+%
+%%	Spine fold width
+%%
+\newlength\spinefold
+\setlength\spinefold{\photobook at spinefold}
+
+%% \DescribeMacro{\coverboardgrow=<len>}
+%
+%%	Controls how much biger the cover board is than the page block
+%%
+\newlength\coverboardgrow
+\setlength\coverboardgrow{\photobook at coverboardgrow}
+
+%% \DescribeMacro{\coverflap=<len>}
+%
+%%	Cover flap
+%%
+\newlength\coverflap
+
+%% \DescribeMacro{\jacketwrap=<len>}
+%% \DescribeMacro{\jacketflap=<len>}
+%% \DescribeMacro{\jacketflapfront=<len>}
+%% \DescribeMacro{\jacketflapback=<len>}
+%
+%%	Jacker configuration
+%%
+\newlength\jacketwrap
+\newlength\jacketflap
+\newlength\jacketflapfront
+\newlength\jacketflapback
+
+%% \DescribeMacro{\blockwidth=<len>}
+%% \DescribeMacro{\blockheight=<len>}
+%
+%%	Page block size
+%%
+% NOTE: page and bleed block sizes are set via \InitPages
+\newlength\blockwidth
+\newlength\blockheight
+
+%% \DescribeMacro{\bleedblockwidth=<len>}
+%% \DescribeMacro{\bleedblockheight=<len>}
+%
+%%	Page block size with bleeds
+%%
+%%	These are equivalent to |\paperwidth| and |\paperheight| but are 
+%%	independent of them...
+%%
+\newlength\bleedblockwidth
+\newlength\bleedblockheight
+
+%% \DescribeMacro{\pageblockwidth=<len>}
+%% \DescribeMacro{\pageblockheight=<len>}
+%
+%% Original page block size
+%%
+%% for the block layout these are the same as |\blockwidth| and |\blockheight|
+%% for other layouts these are the original page layout size while the 
+%% |\blockwidth| are set tho the current layout visible size.
+%%
+\newlength\pageblockwidth
+\newlength\pageblockheight
+
+%% \DescribeMacro{\bleed=<len>}
+%
+%% Page bleed size
+%%
+\newlength\bleed
+\setlength\bleed{\photobook at bleed}
+
+%% \DescribeMacro{\bindingoffset=<len>}
+%
+%% Binding offset
+%%
+\newlength\bindingoffset
+\setlength\bindingoffset{\photobook at bindingoffset}
+
+%% \DescribeMacro{\defaultfoldout=<fold-spec>}
+%
+%% Set the default fold specification.
+%%
+%% This can be set via the |foldout| class option.
+%%
+%% For more information see: \nameref{subsec:Foldout page cells} section.
+%%
+\edef\defaultfoldout{\photobook at foldout}
+
+%% \DescribeMacro{\flatfold=<len>}
+%
+%% Sets the amount of paper to account for a flat fold.
+%%
+\newlength\flatfold
+\setlength\flatfold{\photobook at flatfold}
+
+%% \DescribeMacro{\pagefold=<fold>}
+%
+%% Default fold type.
+%%
+%% This defaults to |out| for |jacket| and |cover| and to |in| for other
+%% layouts.
+%%
+\newcommand\photobook at setpagefold[1]{%
+	\edef\pagefold{
+		\ifx \photobook at pagefold \empty%
+			#1%
+		\else%
+			\photobook at pagefold\fi}}
+\photobook at setpagefold{in}
+
+%% \DescribeMacro{\foldmarkoffset=<len>}
+%
+%% Sets the offset of fold marks from outside of page edge (default: |0.5\bleed|).
+%%
+%% Note that this can either be a command or a dimension.
+%%
+%\def\foldmarkoffset{0.5\bleed}
+\def\foldmarkoffset{2mm}
+
+%% \DescribeMacro{\foldmarksize=<len>}
+%
+%% Sets fold marker size (vertical).
+%%
+\newlength\photobook at foldmarklen
+\setlength\photobook at foldmarklen{\photobook at foldmarksize}
+
+%% \DescribeMacro{\iffoldmarks}
+%
+%% Disable/enable fold marks.
+%%
+%% The default is true, to toggle on/off use |\foldmarkstrue| / |\foldmarksfalse|.
+%%
+%% This can be set globally via the |nofoldmarks| class option.
+%%
+\newif\iffoldmarks
+\ifphotobook at nofoldmarks%
+	\foldmarksfalse%
+\else%
+	\foldmarkstrue\fi%
+
+%% \DescribeMacro{\clearimage=<len>}
+%
+%%	Image clearance
+%%
+% NOTE: since this can be any number but we need to detect if it was set 
+%		manually we'll set it to \maxdimen and hope noe will print 
+%		something big enough and dare to use it as image clearance...
+\newlength{\clearimage}
+\setlength\clearimage{\maxdimen}
+
+%% \DescribeMacro{\imageblockwidth=<ratio>}
+%% \DescribeMacro{\imageblockheight=<ratio>}
+%
+%%	Image block width relative to |\textwidth|
+%%
+\edef\imageblockwidth{\photobook at imageblockwidth}
+\edef\imageblockheight{\photobook at imageblockheight}
+
+%% \DescribeMacro{\pagetextwidth=<len>}
+%% \DescribeMacro{\pagetextheight=<len>}
+%
+%% Root page text width/height.
+%%
+\newlength\pagetextwidth
+\setlength\pagetextwidth{\textwidth}
+\newlength\pagetextheight
+\setlength\pagetextheight{\textheight}
+
+%% \DescribeMacro{\imageblockoffsettop=<ratio>}
+%
+%% The ration by which the image is raised in |\ImagePage{..}| and 
+%% derived templates.
+%%
+\edef\imageblockoffsettop{\photobook at imageblockoffsettop}
+
+%% \DescribeMacro{\clearcaption=<len>}
+%
+%% Block caption clearance from edge of parent cell.
+%%
+%% Used as default by |\captionblockcell{..}|
+%%
+% XXX do we need this???
+\newlength\clearcaption
+\setlength\clearcaption{0pt}
+
+%% \DescribeMacro{\captioncellspacing=<len>}
+%
+%% Block caption spacing from parent cell.
+%%
+%% Used as default by |\captionblockcell{..}|
+%%
+% XXX should this be used in other caption cells???
+\newlength\captioncellspacing
+\setlength\captioncellspacing{5pt}
+
+
+%% \DescribeMacro{\captionclearpage=<len>}
+%
+%% The distance between a caption block on a template page and page 
+%% borders (defaults to: |\clearimage|).
+%%
+%% This is relevant only in page/spread templates.
+%%
+\def\captionclearpage{\clearimage}
+
+
+%% \DescribeMacro{\cellparentwidth=<len>}
+%% \DescribeMacro{\cellparentheight=<len>}
+%% \DescribeMacro{\cellwidth=<len>}
+%% \DescribeMacro{\cellheight=<len>}
+%% \DescribeMacro{\celloffsetleft=<len>}
+%% \DescribeMacro{\celloffsettop=<len>}
+%% \DescribeMacro{\clearance=<len>}
+%
+%% Cell geometry. 
+%%
+%% These are set automatically by cells, thus it is not recommended to 
+%% edit them manually.
+%%
+%% For more details see the \nameref{subsec:Cells} section.
+%%
+\newlength\cellparentwidth
+\setlength\cellparentwidth{\paperwidth}
+\newlength\cellparentheight
+\setlength\cellparentheight{\paperheight}
+\newlength\cellwidth
+\setlength\cellwidth{\cellparentwidth}
+\newlength\cellheight
+\setlength\cellheight{\cellparentheight}
+\newlength\celloffsetleft
+\setlength\celloffsetleft{0pt}
+\newlength\celloffsettop
+\setlength\celloffsettop{0pt}
+\newlength\clearance
+\setlength\clearance{0pt}
+
+
+%% \DescribeMacro{\clearfoldoutbinding=<len>}
+%% \DescribeMacro{\clearfoldoutfold=<len>}
+%% \DescribeMacro{\clearfoldoutedge=<len>}
+%
+%% Foldout geometry.
+%%
+%% For more info see \nameref{subsec:Foldout page cells} section.
+%%
+\newlength\clearfoldoutbinding
+\setlength\clearfoldoutbinding{8mm}
+\newlength\clearfoldoutfold
+\setlength\clearfoldoutfold{5mm}
+\newlength\clearfoldoutedge
+\setlength\clearfoldoutedge{1mm}
+
+
+
+%----------------------------------------------------------------------
+%%%% Initialization
+%%
+%% \DescribeMacro{\InitPages}
+%
+%% Initialize page dimensions.
+%%
+%% This is not intended for direct use.
+%%
+% XXX do we need to document this??
+%		...is there a usecase for calling this manually?
+\newcommand\InitPages{
+	% layout bools/tests...
+	\coverlayoutfalse
+	\hardcoverlayoutfalse
+	\softcoverlayoutfalse
+	\endpaperlayoutfalse
+	\jacketlayoutfalse
+	\coverlikelayoutfalse
+	\blocklayoutfalse
+	\ifdefstring{\layoutmode}{block}{
+		\blocklayouttrue }{}
+	\ifdefstring{\layoutmode}{cover}{ 
+		\coverlayouttrue
+		\coverlikelayouttrue }{}
+	\ifdefstring{\layoutmode}{hardcover}{ 
+		\hardcoverlayouttrue
+		\coverlikelayouttrue }{}
+	\ifdefstring{\layoutmode}{softcover}{ 
+		\softcoverlayouttrue
+		\coverlikelayouttrue }{}
+	\ifdefstring{\layoutmode}{jacket}{%
+		\jacketlayouttrue
+		\coverlikelayouttrue }{}
+	\ifdefstring{\layoutmode}{endpaper}{ 
+		\endpaperlayouttrue }{}
+	% pdf layout...
+	\ifx\photobook at pdfpagelayout\empty
+		\ifblocklayout
+			\def\pdfpagelayout{TwoPageRight}
+		\else
+			\def\pdfpagelayout{SinglePage}\fi
+	\else
+		\def\pdfpagelayout{\photobook at pdfpagelayout}\fi
+	% items to ignore in different layouts...
+	% XXX is this the correct way to go???
+	\ifcoverlayout
+		\setlength\coverflap{\photobook at coverflap}
+	\else
+		\setlength\coverflap{0pt}\fi
+	\ifjacketlayout
+		\setlength\jacketwrap{\photobook at jacketwrap}
+		\setlength\jacketflap{\photobook at jacketflap}
+	\else
+		\setlength\jacketwrap{0pt}
+		\setlength\jacketflap{0pt}\fi
+	% flaps...
+	\ifdim\jacketflapfront=0pt
+		\setlength\jacketflapfront{\jacketflap}\fi
+	\ifdim\jacketflapback=0pt
+		\setlength\jacketflapback{\jacketflap}\fi
+	% block size...
+	\ifdim\blockwidth=0pt
+		% layout: block...
+		\setlength\blockwidth{
+			\ifx\photobook at blockwidth\empty
+				\dimexpr 
+					\paperwidth 
+					- 2\bleed \relax
+			\else
+				\photobook at blockwidth \fi} 
+		\setlength\pageblockwidth{\blockwidth}
+		% layout: cover...
+		\ifcoverlayout
+			\setsepchar{,}%
+			\readlist*\pagefoldpanels{%
+				\the\coverflap,
+				% board thickness is ignored...
+				\the\dimexpr
+					\coverboardgrow
+					+ \pageblockwidth \relax,
+				\the\spinefold,
+				\the\spinewidth,
+				\the\spinefold,
+				\the\dimexpr
+					\coverboardgrow
+					+ \pageblockwidth \relax,
+				% board thickness is ignored...
+				\the\coverflap}%
+			\photobook at setpagefold{out}
+			\setlength\blockwidth{
+				\dimexpr 
+					2\blockwidth 
+					+ \spinewidth 
+					+ 2\spinefold
+					+ 2\coverboardgrow
+					+ 2\coverflap \relax}\fi
+		% layout: jacket...
+		% XXX this seems to be about 6mm off -- what are we missing here???
+		\ifjacketlayout
+			\setsepchar{,}%
+			\readlist*\pagefoldpanels{%
+				\the\jacketflapback,
+				\the\jacketwrap,
+				\the\dimexpr
+					\coverboardgrow
+					+ \pageblockwidth \relax,
+				\the\spinefold,
+				\the\spinewidth,
+				\the\spinefold,
+				\the\dimexpr
+					\coverboardgrow
+					+ \pageblockwidth \relax,
+				\the\jacketwrap,
+				\the\jacketflapfront}%
+			\photobook at setpagefold{out}
+			\setlength\blockwidth{
+				\dimexpr 
+					2\blockwidth 
+					+ 2\coverboardgrow
+					+ \spinewidth
+					+ 2\spinefold
+					+ 2\jacketwrap
+					+ \jacketflapfront
+					+ \jacketflapback \relax}\fi
+		% layout: endpaper...
+		\ifendpaperlayout
+			\readlist*\pagefoldpanels{%
+				\the\pageblockwidth,
+				\the\pageblockwidth}%
+			\photobook at setpagefold{in}
+			\setlength\blockwidth{2\blockwidth}\fi\fi
+	\ifdim\blockheight=0pt
+		% layout: block / endpaper...
+		\setlength\blockheight{
+			\ifx\photobook at blockheight\empty
+				\dimexpr \paperheight - 2\bleed \relax
+			\else
+				\photobook at blockheight\fi} 
+		\setlength\pageblockheight{\blockheight}
+		% layout: cover...
+		\ifcoverlayout
+			\setlength\blockheight{
+				\dimexpr 
+					\blockheight
+					+ 2\coverboardgrow
+					+ 2\coverflap
+				\relax}\fi
+		% layout: jacket...
+		\ifjacketlayout
+			\setlength\blockheight{
+				\dimexpr 
+					\blockheight
+					+ 2\coverboardgrow
+				\relax}\fi\fi
+	% default image clearance...
+	\ifdim \clearimage = \maxdimen
+		\ifx\photobook at clearimage\empty
+			%\setlength\clearimage{-\bleed}
+			\setlength\clearimage{10mm}
+		\else
+			\setlength\clearimage{\photobook at clearimage}\fi\fi
+	% page with bleeds...
+	% NOTE: this is essentially \paperwidth and \paperheight but we do 
+	%		not rely on them being defined -- photobook settings take 
+	%		priority over \paperwidth and \paperwidth...
+	\setlength\bleedblockwidth{\dimexpr 
+			2\bleed 
+			+ \blockwidth \relax}
+	\setlength\bleedblockheight{\dimexpr 
+			2\bleed 
+			+ \blockheight \relax} 
+	% cells...
+	\global\setlength\cellparentwidth{\blockwidth}
+	\global\setlength\cellparentheight{\blockheight}
+	\global\setlength\cellwidth{\cellparentwidth}
+	\global\setlength\cellheight{\cellparentheight}
+	% misc...
+	\nprounddigits{\photobook at roundprintedlengthsto}}
+
+
+%% \DescribeMacro{\ReInitPages}
+%
+%%	Reset and re-initialize page dimentions.
+%%
+\newcommand\ReInitPages{%
+	\setlength\blockwidth{0mm}%
+	\setlength\blockheight{0mm}%
+	\edef\pdfpagelayout{}%
+	%
+	\InitPages%
+	\ResetFoldMarks}
+
+
+
+%----------------------------------------------------------------------
+% Setup...
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% on-import...
+
+% init/update lengths...
+\InitPages
+
+% minimal geometry setup...
+\RequirePackage[
+	% paper size (incl. bleeds)...
+	paperwidth=\bleedblockwidth, paperheight=\bleedblockheight,
+]{geometry}
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% pre-document...
+
+\AtEndPreamble{
+
+	% Metadata...
+	\hypersetup{
+		pdfinfo={
+			Title={\@title},
+			Subject={\@subject},
+			Author={\@author},
+			Keywords={\@keywords},
+		},
+		pdfpagelayout=\pdfpagelayout,
+	}
+
+	% Geometry...
+	\InitPages
+	% no-defaults -- the user is expected to set things up...
+	\ifphotobook at geometrynodefaults
+		\geometry{
+			% paper size (incl. bleeds)...
+			paperwidth=\bleedblockwidth, paperheight=\bleedblockheight,
+			bindingoffset=\bindingoffset}
+	% normal mode...
+	\else
+		\geometry{
+			% paper size (incl. bleeds)...
+			paperwidth=\bleedblockwidth, paperheight=\bleedblockheight,
+			bindingoffset=\bindingoffset,
+			% include header/footer/margin notes in printed area
+			twoside, includeall, nomarginpar,
+			ignorehead=false, ignorefoot=false, ignoremp=false,
+			% center printed area on page
+			vcentering, hcentering}\fi
+
+	\setlength\pagetextwidth{\textwidth}
+	\setlength\pagetextheight{\textheight}
+
+	% PDF boxes...
+	\pdfboxesset[\bleed]{\bleedblockwidth}{\bleedblockheight}}
+
+
+
+%----------------------------------------------------------------------
+%%%% Generic commands
+%%
+
+
+%% \DescribeMacro{\keywords\{..\}}
+%
+%%	Set pdf metadata keywords
+%%
+%%	>>	\keywords{<keywords>}
+%%
+\def\@keywords{}
+
+\newcommand\keywords[1]{%
+	\def\@keywords{#1}}
+
+
+%% \DescribeMacro{\subject\{..\}}
+%
+%%	Set pdf metadata subject
+%%
+%%	>>	\subject{<subject>}
+%%
+\def\@subject{}
+
+\newcommand\subject[1]{%
+	\def\@subject{#1}}
+
+
+%% \DescribeMacro{\mindim\{..\}}
+%% \DescribeMacro{\maxdim\{..\}}
+%
+%% Get min/max dimension.
+%
+%%	>> \mindim{A}{B}
+%
+%%	>> \maxdim{A}{B}
+%%
+% XXX do we actually need these??
+%		...should be simple to replace with calc's: 
+%			0pt + \minof{..}
+%			0pt + \maxof{..}
+\newcommand\mindim[2]{
+	\ifdim \dimexpr #1 \relax < \dimexpr #2 \relax%
+		\dimexpr #1 \relax%
+	\else%
+		\dimexpr #2 \relax\fi}
+
+\newcommand\maxdim[2]{
+	\ifdim \dimexpr #1 \relax > \dimexpr #2 \relax%
+		\dimexpr #1 \relax%
+	\else%
+		\dimexpr #2 \relax\fi}
+
+
+%% \DescribeMacro{\emptypage\{..\}}
+%
+%% Create an empty page.
+%
+%%	>> \emptypage
+%%	>> \emptypage[<style>]
+% 
+%% |<style>| is the style name as defined via |fancyhdr| (default: |empty|).
+%% 
+\newcommand\emptypage[1][empty]{%
+	\begin{page}%
+		\ifthenelse{\equal{#1}{}}{}{%
+			\thispagestyle{#1}}%
+	\end{page}}
+
+
+%% \DescribeMacro{\cleartoleftpage}
+%
+%% Forces content to left page.
+%%
+%% This is a companion to |\cleardoublepage|.
+%%
+\newcommand*{\cleartoleftpage}{%
+	\clearpage
+	\if at twoside
+		\ifodd\c at page
+			\hbox{}\newpage
+			\if at twocolumn
+				\hbox{}\newpage \fi\fi\fi }
+
+
+%M \DescribeMacro{\ResettableMacro\{..\}}
+%
+%M Create a resettable command.
+%
+%M	>> \ResettableMacro{<name>}{<code>}
+%M	>> \ResettableMacro{<name>}[<arg-count>]{<code>}
+%M	>> \ResettableMacro{<name>}[<arg-count>][<default>]{<code>}
+%
+%M This is similar to |\newcommand{..}| but will define two commands:
+%M
+%M	>> \<name>{..}
+%M
+%M	>> \reset<name>
+%M
+%M |\<name>{..}| can be freely redefined or undefined by user.
+%M
+%M |\reset<name>| will reset |\<name>{..}| to its original state.
+%M
+% parse args...
+\def\ResettableMacro#1{%
+	\@ifnextchar[{%
+		\photobook at ResettableMacro@pre{#1}%
+	}{%
+		\photobook at ResettableMacro{#1}}}
+\def\photobook at ResettableMacro@pre#1[#2]{%
+	\@ifnextchar[{%
+		\photobook at ResettableMacro@args at dfl{#1}[#2]%
+	}{%
+		\photobook at ResettableMacro@args{#1}[#2]}}
+% pre -- main command definition...
+\def\photobook at ResettableMacro#1#2{%
+	\expandafter\newcommand\csname photobook at ResettableMacro@#1\endcsname{#2}%
+	\photobook at ResettableMacro@tail{#1}}
+\def\photobook at ResettableMacro@args#1[#2]#3{%
+	\expandafter\newcommand\csname photobook at ResettableMacro@#1\endcsname[#2]{#3}%
+	\photobook at ResettableMacro@tail{#1}}
+\def\photobook at ResettableMacro@args at dfl#1[#2][#3]#4{%
+	\expandafter\newcommand\csname photobook at ResettableMacro@#1\endcsname[#2][#3]{#4}%
+	\photobook at ResettableMacro@tail{#1}}
+% post...
+\def\photobook at ResettableMacro@tail#1{%
+	% \reset<name>
+	\expandafter\newcommand\csname reset#1\endcsname{%
+		\expandafter\let\csname #1\expandafter\endcsname\csname photobook at ResettableMacro@#1\endcsname}
+	% initialize...
+	\csname reset#1\endcsname}
+
+
+% XXX EXPERIMENTAL
+%	>> \resizedpage[<bleed>]{<width>}{<height>}{<code>}
+\newenvironment{resizedpages}[3][\bleed]{
+	\begingroup%
+		% setup page...
+		\setlength\bleed{#1}%
+		\setlength\blockwidth{#2}%
+		\setlength\blockheight{#3}%
+		\setlength\pageblockwidth{\blockwidth}%
+		\setlength\pageblockheight{\blockheight}%
+		\edef\pdfpagelayout{}%
+		%
+		\InitPages%
+		%
+		\setlength\paperwidth{\bleedblockwidth}%
+		\setlength\paperheight{\bleedblockheight}%
+		%
+		\pdfboxesset[\bleed]{\bleedblockwidth}{\bleedblockheight}%
+		%
+		% NOTE: this prevents some issues with macros racing to place 
+		%		stuff at ship-out (possibly)...
+		%		...also see cell env...
+		%		XXX needs more digging...
+		%		XXX do this at beginshipout/beginpage... (???)
+		%\null%
+		%\hbox{}%
+}{%
+	\endgroup%
+	% reset...
+	\pdfboxesset[\bleed]{\bleedblockwidth}{\bleedblockheight}}
+
+
+
+
+%----------------------------------------------------------------------
+%%%% Environments and Cells
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%%%%% Generic
+
+%% \DescribeEnv{page}
+%
+%% Page environment.
+%%
+%% This is mainly designed to wrap other cell environment described later.
+%%
+%% Note that this may span more than one page if there is enough stuff 
+%% packed in.
+%%
+\newenvironment{page}{%
+	\null%
+	\ignorespaces%
+}{%
+	\clearpage}
+
+
+%% \DescribeEnv{leftpage}
+%
+%% \EXPERIMENTAL
+%%
+% XXX not sure about this...
+\newenvironment{leftpage}{%
+	\begin{page}%
+		\cleartoleftpage%
+}{%
+	\end{page}}
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%%%%% Cells
+
+% meta helpers...
+
+%M \DescribeMacro{\CellContentOptions\{..\}}
+%
+%M \EXPERIMENTAL
+%M
+%M Define standard cell options.
+%M
+% XXX figure out how to align and pad without messing with geometry...
+\newcommand\CellContentOptions[1]{%
+	%% align...
+	%\expandafter\def\csname photobook@#1 at align\endcsname{flushleft}%
+	%\define at key{#1 at args}{align}{%
+	%	\expandafter\edef\csname photobook@#1 at align\endcsname{##1}}%
+	% valign...
+	\expandafter\def\csname photobook@#1 at valign\endcsname{t}%
+	\define at key{#1 at args}{valign}{%
+		\expandafter\edef\csname photobook@#1 at valign\endcsname{##1}}%
+	%% margin...
+	%\expandafter\def\csname photobook@#1 at margin\endcsname{0pt}%
+	%\define at key{#1 at args}{margin}{%
+	%	\expandafter\edef\csname photobook@#1 at margin\endcsname{##1}}%
+	%% padding...
+	%\expandafter\def\csname photobook@#1 at padding\endcsname{0pt}%
+	%\define at key{#1 at args}{padding}{%
+	%	\expandafter\edef\csname photobook@#1 at padding\endcsname{##1}}%
+}
+
+%M \DescribeEnv{CellContent}
+%M \DescribeEnv{CellContent*}
+%
+%M \EXPERIMENTAL
+%M
+%M Standard cell content wrapper, used by |inlinecell|.
+%
+%M	>> \begin{CellContent}[<parent-align>]{<name>} ... \end{CellContent}
+%M	>> \begin{CellContent*}[<parent-align>]{<name>}{<width>}{<height>} ... \end{CellContent}
+%
+%M The star version requires width/height to be manually passed while the
+%M non-star version will get the values from |\cellwidth| and |\cellheight|
+%M respectively.
+%
+% XXX TEST params...
+\newenvironment{CellContent}[2][t]{%
+	\begin{CellContent*}[#1]{#2}{\cellwidth}{\cellheight}%
+}{%
+	\end{CellContent*}}
+
+\newenvironment{CellContent*}[4][t]{%
+	\begin{adjustbox}{
+			minipage=[#1][#4][\csname photobook@#2 at valign\endcsname]{#3},
+			valign=#1}%
+		\ignorespaces%
+}{%
+		% NOTE: prevent empty "minipage" from collapsing...
+		\hspace{\fill}%
+	\end{adjustbox}}
+
+
+%M \DescribeEnv{CellContent}
+%M \DescribeEnv{CellContent*}
+%
+%M \EXPERIMENTAL
+%M
+%M Like |CellContent| / |CellContent*| but will use |minipage| as the wrapper.
+%
+%M	>> \begin{MinipageCellContent}[<parent-align>]{<name>} ... \end{MinipageCellContent}
+%M	>> \begin{MinipageCellContent*}[<parent-align>]{<name>}{<width>}{<height>} ... \end{MinipageCellContent}
+%
+% XXX TEST...
+% XXX doc...
+\newenvironment{MinipageCellContent}[2][t]{%
+	\begin{MinipageCellContent*}[#1]{#2}{\cellwidth}{\cellheight}%
+}{%
+	\end{MinipageCellContent*}}
+
+\newenvironment{MinipageCellContent*}[4][t]{%
+	\begin{minipage}[#1][#4][\csname photobook@#2 at valign\endcsname]{#3}%
+}{%
+	\end{minipage}}
+
+
+%% A cell environment is a box of specified size.
+%%
+%% Cells can be both placed inline relative to other content or in an 
+%% absolute location.
+%%
+%% Note that absolute cells are placed relative to the page and currently 
+%% can not be placed relative to other absolute cells (this might change
+%% in the future).
+%%
+%% \DescribeMacro{\cellwidth=<len>}
+%% \DescribeMacro{\cellheight=<len>}
+%% \DescribeMacro{\cellparentwidth=<len>}
+%% \DescribeMacro{\cellparentheight=<len>}
+%% \DescribeMacro{\celloffsettop=<len>}
+%% \DescribeMacro{\celloffsetleft=<len>}
+%% \DescribeMacro{\clearance=<len>}
+%%
+%% A cell defines a set of contextual lengths:
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%   <--> celloffsetleft
+%%   .   <--------------> cellwidth
+%%   <----------------------> cellparentwidth
+%%   .   .              .   .
+%%   +----------------------+ . . . . . . .
+%%   |   .              .   |     ^       ^ celloffsettop
+%%   |   .              .   |     |       |
+%%   |   +--------------+ . | . . | . . . v 
+%%   |   |              |   |     |   ^
+%%   |   |              |   |     |   | cellheight
+%%   |   |     cell     |   |     |   |
+%%   |   |              |   |     |   |
+%%   |   |              |   |     |   |
+%%   |   +--------------+ . | . . | . v
+%%   |                      |     |
+%%   |                      |     | cellparentheight
+%%   +----------------------+ . . v
+%%                              
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%% For absolutely positioned cells these define the cell offset from 
+%% parent.
+%%
+%% The bare page can be reasonably treated as a cell.
+%%
+%% Initally, outside of any cells |\cellwidth|, |\cellparentwidth| and 
+%% |\cellheight|, |\cellparentheight| are equal to |\paperwidth| and 
+%% |\paperheight| respectively, and |\celloffsettop| and |\celloffsetleft|
+%% are set to |0pt|.
+%%
+%% Changing these is not recommended, it likely will not affect the 
+%% current cell but can mess up nested cells.
+%%
+%% \DescribeEnv{inlinecell}
+%% \DescribeEnv{inlinecell*}
+%
+%% Create a basic inline cell.
+%
+%%	>> \begin{inlinecell}{<width>}{<height>} ... \end{inlinecell}
+%%	>> \begin{inlinecell}[<valign>]{<width>}{<height>} ... \end{inlinecell}
+%
+%% This will clip oversized content.
+%%
+%% |inlinecell*| is like |inlinecell| but will not clip.
+%
+%%	>> \begin{inlinecell*}{<width>}{<height>} ... \end{inlinecell*}
+%%	>> \begin{inlinecell*}[<valign>]{<width>}{<height>} ... \end{inlinecell*}
+%
+%% |<valign>| can be one of |t| (default) for top, |c| for center or |b| for bottom.
+%%
+%% These are just like |minipage| but provide cell mechanics.
+%%
+% XXX EXPERIMENTAL
+\CellContentOptions{inlinecell}
+
+\def\photobook at inlinecell@parentvalign{t}
+\define at boolkey{inlinecell at args}{t}[true]{%
+	\def\photobook at inlinecell@parentvalign{t}}
+\define at boolkey{inlinecell at args}{c}[true]{%
+	\def\photobook at inlinecell@parentvalign{c}}
+\define at boolkey{inlinecell at args}{b}[true]{%
+	\def\photobook at inlinecell@parentvalign{b}}
+
+\newenvironment{inlinecell*}[3][]{%
+	\begingroup%
+		\setkeys{inlinecell at args}{
+			t,
+			#1}%
+		%
+		% get args by value...
+		\edef\photobook at protect@w{\the\dimexpr #2 \relax}%
+		\edef\photobook at protect@h{\the\dimexpr #3 \relax}%
+		%
+		\setlength\cellparentwidth{\cellwidth}%
+		\setlength\cellparentheight{\cellheight}%
+		\setlength\cellwidth{\photobook at protect@w}%
+		\setlength\cellheight{\photobook at protect@h}%
+		\setlength\celloffsettop{0pt}%
+		\setlength\celloffsetleft{0pt}%
+		%
+		\begin{CellContent}[\photobook at inlinecell@parentvalign]{inlinecell}%
+}{%
+		\end{CellContent}%
+	\endgroup}
+
+\newenvironment{inlinecell}[3][t]{%
+	\begin{inlinecell*}[#1]{#2}{#3}%
+	\begin{cliptocell}%
+}{%
+	\end{cliptocell}%
+	\end{inlinecell*}}
+
+
+% XXX EXPERIMENTAL
+%% \DescribeEnv{minipagecell}
+%% \DescribeEnv{minipagecell*}
+%
+%% \EXPERIMENTAL
+%%
+\CellContentOptions{minipagecell}
+
+\def\photobook at minipagecell@parentvalign{t}
+\define at boolkey{minipagecell at args}{t}[true]{%
+	\def\photobook at minipagecell@parentvalign{t}}
+\define at boolkey{minipagecell at args}{c}[true]{%
+	\def\photobook at minipagecell@parentvalign{c}}
+\define at boolkey{minipagecell at args}{b}[true]{%
+	\def\photobook at minipagecell@parentvalign{b}}
+
+\newenvironment{minipagecell*}[3][]{%
+	\begingroup%
+		\setkeys{minipagecell at args}{
+			t,
+			#1}%
+		% get args by value...
+		\edef\photobook at protect@w{\the\dimexpr #2 \relax}%
+		\edef\photobook at protect@h{\the\dimexpr #3 \relax}%
+		%
+		\setlength\cellparentwidth{\cellwidth}%
+		\setlength\cellparentheight{\cellheight}%
+		\setlength\cellwidth{\photobook at protect@w}%
+		\setlength\cellheight{\photobook at protect@h}%
+		\setlength\celloffsettop{0pt}%
+		\setlength\celloffsetleft{0pt}%
+		\setlength\clearance{0pt}%
+		%
+		\begin{MinipageCellContent}[\photobook at minipagecell@parentvalign]{minipagecell}%
+}{%
+		\end{MinipageCellContent}%
+	\endgroup}
+
+\newenvironment{minipagecell}[3][t]{%
+	\begin{minipagecell*}[#1]{#2}{#3}%
+	\begin{cliptocell}%
+}{%
+	\end{cliptocell}%
+	\end{minipagecell*}}
+
+
+% XXX EXPERIMENTAL
+%% \DescribeEnv{zinlinecell}
+%% \DescribeEnv{zinlinecell*}
+%
+%% \EXPERIMENTAL
+%%
+%% Like |inlinecell| / |inlinecell*| but will take up zero space.
+%%
+%%	>> \begin{zinlinecell}{<width>}{<height>} ... \end{zinlinecell}
+%%	>> \begin{zinlinecell}[<valign>]{<width>}{<height>} ... \end{zinlinecell}
+%%
+% XXX need to get rid of the raisebox here...
+\NewEnviron{zinlinecell*}[1][]{%
+	\smash{\makebox[0pt][l]{%
+		% XXX HACK: RAISEBOX -- feels hackish...
+		\raisebox{0pt - \totalheightof{O}}{%
+			\begin{inlinecell*}[#1]{\cellwidth}{\cellheight}%
+				\BODY%
+			\end{inlinecell*}}}}}
+
+\NewEnviron{zinlinecell}[1][]{%
+	\smash{\makebox[0pt][l]{%
+		% XXX HACK: RAISEBOX -- feels hackish...
+		\raisebox{0pt - \totalheightof{O}}{%
+			\begin{inlinecell}[#1]{\cellwidth}{\cellheight}%
+				\BODY%
+			\end{inlinecell}}}}}
+
+
+%% \DescribeEnv{cell}
+%% \DescribeEnv{cell*}
+%
+%% Create a basic absolutely positioned cell.
+%
+%%	>> \begin{cell}{<left>, <top>}{<width>}{<height>} ... \end{cell}
+%
+%% Oversized content will be clipped.
+%%
+%% |cell*| is just like |cell| but will not clip its content.
+%
+%%	>> \begin{cell*}{<left>, <top>}{<width>}{<height>} ... \end{cell*}
+%%
+% XXX SYNTAX: place the second arg in braces...
+%		\begin{cell*}(<left>, <top>){<width>}{<height>}
+\newenvironment{cell*}[3]{%
+	\begingroup%
+		\setsepchar{,}%
+		\readlist*\photobook at cell@offset{#1}%
+		%
+		% NOTE: if there is no \null before textblock then it can reset the 
+		%		non-standard page boxes... 
+		%		...not sure yet if this is an issue with how/when foldout env
+		%		updates the boxes or with textblock internals, needs 
+		%		investigating...
+		%		XXX report this as a bug if issue is in textblock...
+		%		XXX another place where this is relevant is in the resizedpages
+		%			env...
+		\null%
+		\begin{textblock*}{#2}(#1)%
+		\begin{inlinecell*}{#2}{#3}%
+			\setlength\celloffsettop{\photobook at cell@offset[1]}%
+			\setlength\celloffsetleft{\photobook at cell@offset[2]}%
+			\ignorespaces%
+}{%
+		\end{inlinecell*}%
+		\end{textblock*}%
+	\endgroup%
+	\ignorespaces}
+
+\newenvironment{cell}[3]{%
+	\begin{cell*}{#1}{#2}{#3}%
+	\begin{cliptocell}%
+		\ignorespaces%
+}{%
+	\end{cliptocell}%
+	\end{cell*}%
+	\ignorespaces}
+
+
+% XXX EXPERIMENTAL
+%% \DescribeEnv{adjustcell}
+%% \DescribeEnv{adjustcell*}
+%
+%% \EXPERIMENTAL
+%%
+\newenvironment{adjustcell*}[4][t]{%
+	\begin{adjustbox}{#2}%
+		\vspace{0pt}%
+		\begin{minipagecell*}[#1]{#3}{#4}%
+}{%
+		\end{minipagecell*}%
+	\end{adjustbox}}
+
+\newenvironment{adjustcell}[4][t]{%
+	\begin{adjustbox}{#2}%
+		\vspace{0pt}%
+		\begin{minipagecell}[#1]{#3}{#4}%
+}{%
+		\end{minipagecell}%
+	\end{adjustbox}}
+
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%%%%% Save cells
+
+%% \DescribeMacro{\savecell\{..\}}
+%% \DescribeMacro{\gsavecell\{..\}}
+%
+%% Create a saved cell.
+%
+%%	>> \savecell{<name>}{<width>}{<height>}{ .. }
+%
+%% This is similar to |\newsavebox{..}| and |\sbox{..}| but adds 
+%% cell functionality.
+%%
+%% |\gsavecell{..}| is the same as |\savecell{..}| but greates a global 
+%% cell.
+%%
+% XXX can/should we make this an env???
+% XXX should this be split into \newsavecell{..} and \scell{..} ???
+% XXX can we use root cells inside this???
+%		...i.e. things using textbox*...
+\newcommand\savecell[5][]{%
+	% only define a savebox once...
+	\@ifundefined{#2}{%
+		\expandafter\newsavebox\csname #2\endcsname}{}
+	\expandafter\sbox\csname #2\endcsname{%
+		\begin{inlinecell*}[#1]{#3}{#4}%
+			#5%
+		\end{inlinecell*}}%
+	\ignorespaces}
+
+\newcommand\gsavecell[5][]{%
+	% only define a savebox once...
+	\@ifundefined{#2}{%
+		\expandafter\newsavebox\csname #2\endcsname}{}
+	\global\expandafter\sbox\csname #2\endcsname{%
+		\begin{inlinecell*}[#1]{#3}{#4}%
+			#5%
+		\end{inlinecell*}}%
+	\ignorespaces}
+
+
+%% \DescribeMacro{\usecell\{..\}}
+%% \DescribeMacro{\usecell*\{..\}}
+%
+%% Use part of a saved cell.
+%%
+%%	>> \usecell{<name>}(<top>, <left>){<width>}{<height>}
+%%
+%% This will clip the content to cell.
+%%
+%% |\usecell*{..}| is similar to |\usecell{..}| but will not clip the 
+%% cell content.
+%%
+%%	>> \usecell*{<name>}(<top>, <left>){<width>}{<height>}
+%%
+%% These are similar to |\usebox{..}|.
+%%
+\def\usecell{\@ifstar{%
+	\photobook at usecell%
+}{%
+	\photobook at usecell@star}}
+
+% cell content...
+% NOTE: this is not intended for direct use -- depends closure/context...
+\def\photobook at usecell@placecell#1(#2){%
+	\setsepchar{,}%
+	\readlist*\photobook at usecell@offset{#2}%
+	% XXX how we align things feels a bit odd...
+	\vspace{-\dimexpr \photobook at usecell@offset[1] \relax}%
+	\adjustbox{margin={-\dimexpr \photobook at usecell@offset[2] \relax} 0pt 0pt 0pt}{%
+		\expandafter\usebox\csname #1\endcsname}}
+
+% XXX add option to rotate saved cell...
+\def\photobook at usecell@star#1(#2)#3#4{
+	\begin{inlinecell}{#3}{#4}%
+		\photobook at usecell@placecell{#1}(#2)%
+	\end{inlinecell}}
+
+% XXX add option to rotate saved cell...
+\def\photobook at usecell#1(#2)#3#4{
+	\begin{inlinecell*}{#3}{#4}%
+		\photobook at usecell@placecell{#1}(#2)%
+	\end{inlinecell*}}
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%%%%% Cell macros
+%
+%% Cell macros require a cell environment to function correctly.
+%%
+
+%% \DescribeEnv{topdown}
+%% \DescribeEnv{bottomup}
+%
+%% Rotate cell content vertically, orienting it top-down or bottom-up.
+%
+%%	>> \begin{topdown} ... \end{topdown}
+%%	>> \begin{bottomup} ... \end{bottomup}
+%%
+\newenvironment{topdown}[1][t]{%
+	\begin{flushright}%
+	\begin{turn}{270}%
+	\begin{inlinecell*}[#1]{\cellheight}{\cellwidth}%
+}{%
+	\end{inlinecell*}%
+	\end{turn}%
+	\end{flushright}}
+
+\newenvironment{bottomup}[1][t]{%
+	\begin{turn}{90}%
+	\begin{inlinecell*}[#1]{\cellheight}{\cellwidth}%
+}{%
+	\end{inlinecell*}%
+	\end{turn}}
+
+
+%% \DescribeEnv{cliptocell}
+%
+%% Clip content to parent cell.
+%%
+\newenvironment{cliptocell}{%
+	\begin{clipbox*}{0cm {\height - \cellheight} {\cellwidth} {\height}}%
+	\begin{minipage}[t][\cellheight][t]{\cellwidth}% 
+		\ignorespaces%
+}{%
+	\end{minipage}%
+	\end{clipbox*}}
+
+
+
+%% \DescribeMacro{\imagecell\{..\}}
+%
+%% Place image in cell.
+%
+%%	>> \imagecell{<caption-cell>}{<image>}
+%%	>> \imagecell[<key>=<value>, ..]{<caption-cell>}{<image>}
+%%
+%%	>> \imagecell[fit]{}{<image>}
+%%	>> \imagecell[fill]{}{<image>}
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%   fit (default)                fill
+%%   +-----------------+    . . . +-----------------+ . . .
+%%   |                 |    .  .  |                 |  .  .
+%%   +-----------------+    .     |                 |     .
+%%   | .             . |    .     |  .           .  |     .
+%%   |    .       .    |    .     |     .     .     |     .
+%%   |      image      |    .     |      image      |     .
+%%   |    .       .    |    .     |     .     .     |     .
+%%   | .             . |    .     |  .           .  |     .
+%%   +-----------------+    .     |                 |     .
+%%   |                 |    .  .  |                 |  .  .
+%%   +-----------------+    . . . +-----------------+ . . .
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%% Centering. The image will be centered by default.
+%%
+%%	>> \imagecell{}{<image>}
+%%	>> \imagecell[center]{}{<image>}
+%%
+%% Vertical alignment
+%%
+%%	>> \imagecell[top]{}{<image>}
+%%	>> \imagecell[bottom]{}{<image>}
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%   top                    center (default)       bottom
+%%   +-----------------+    +-----------------+    +-----------------+ 
+%%   | .             . |    |                 |    |                 |
+%%   |    .       .    |    +-----------------+    |                 |
+%%   |      image      |    | .             . |    |                 |
+%%   |    .       .    |    |    .       .    |    +-----------------+ 
+%%   | .             . |    |      image      |    | .             . | 
+%%   +-----------------+    |    .       .    |    |    .       .    | 
+%%   |                 |    | .             . |    |      image      | 
+%%   |                 |    +-----------------+    |    .       .    | 
+%%   |                 |    |                 |    | .             . | 
+%%   +-----------------+    +-----------------+    +-----------------+ 
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%% Horizontal alignment
+%%
+%%	>> \imagecell[left]{}{<image>}
+%%	>> \imagecell[right]{}{<image>}
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%   left                   center (default)       right
+%%   +-------------+---+    +-+-------------+-+    +---+-------------+
+%%   | .         . |   |    | | .         . | |    |   | .         . |
+%%   |  .       .  |   |    | |  .       .  | |    |   |  .       .  |
+%%   |   .     .   |   |    | |   .     .   | |    |   |   .     .   |
+%%   |    .   .    |   |    | |    .   .    | |    |   |    .   .    |
+%%   |    image    |   |    | |    image    | |    |   |    image    |
+%%   |    .   .    |   |    | |    .   .    | |    |   |    .   .    |
+%%   |   .     .   |   |    | |   .     .   | |    |   |   .     .   |
+%%   |  .       .  |   |    | |  .       .  | |    |   |  .       .  |
+%%   | .         . |   |    | | .         . | |    |   | .         . |
+%%   +-------------+---+    +-+-------------+-+    +---+-------------+
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%% Horizontal and vertical alignment can be combined to control alignment 
+%% of both vertical and horizontal images at the same time.
+%%
+%% Image |clearance|. This sets the amount of clearance around an image 
+%% (default: |0pt|).
+%%
+%%	>> \imagecell[clearance=-4mm]{}{<image>}
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%   clearance > 0pt        clearance = 0pt          clearance < 0pt
+%%                                  (default)     
+%%   +--------v--------+    +-----------------+    +--------^--------+    
+%%   |                 |    |                 |    |                 |    
+%%   |+---------------+|    +-----------------+  ..+-----------------+..  
+%%   || .           . ||    | .             . |  . |.               .| .  
+%%   ||   .       .   ||    |    .       .    |  . |    .       .    | .  
+%%   |>     image     <|    |      image      |  < |      image      | >  
+%%   ||   .       .   ||    |    .       .    |  . |    .       .    | .  
+%%   || .           . ||    | .             . |  . |.               .| .  
+%%   |+---------------+|    +-----------------+  ..+-----------------+..  
+%%   |                 |    |                 |    |                 |    
+%%   +--------^--------+    +-----------------+    +--------v--------+    
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%% Note that if |clearance| is less than 0, the image will take up more
+%% space than the containing cell, |\imagecell{..}| will not clip 
+%% its content and the whole image surface will be shown. If clipping is 
+%% needed then use |clipcell| environment as a container.
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%   +-----------------+ - - caption cell size
+%%   .                 .       .
+%%   +-----------------+       .
+%%   |                 |       . 
+%% ..+-----------------+..  .  +
+%% . |.caption cell   .| .     |
+%% . |    .       .    | .     |
+%% . |        .        | .     | 
+%% . |    .       .    | .     |
+%% . |.               .| .     |
+%% ..+-----------------+..  .  +
+%%   |                 |    
+%%   +-----------------+    
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%% |<caption-cell>| occupies the same space as the image clipped by the 
+%% containing cell and provides all the cell functionality.
+%%
+%% If |captionclearparent| is set, the |<caption-cell>| will fit into an 
+%% intersection between the image area and the parent cell padded by 
+%% |captionclearparent|.
+%%
+%% This will write image path, page and size to |\jobname|.image-list, 
+%% this is useful for final image pre-press. 
+%%
+%% To disable image list set:
+%
+%%	>> \writeimagelistfalse
+%%
+% XXX do we need captionclearparent to be directional (a-la margin in adjustbox)???
+% XXX might be a good idea to split this into two parts:
+%		- \aligncell{..}
+%		- \imagecell{caption}{image}
+%			-> size image
+%			-> \aligncell{
+%					image
+%					caption}
+% XXX document scale/offsettop/offsetleft...
+
+% helpers...
+
+% image size logging...
+\newif\ifwriteimagelist
+\writeimagelisttrue
+
+\newwrite\photobook at imagelist
+\def\photobook at logimagesize@setup{%
+	\immediate\openout\photobook at imagelist=\jobname.image-list%
+	\AfterEndDocument{%
+		\immediate\closeout\photobook at imagelist}%
+	% setup only once per job...
+	\global\def\photobook at logimagesize@setup{}}
+
+%	>> \photobook at logimagesize{<path>}{<page>}{<imagebox>}
+% XXX for some reason can't use \lenprint[mm]{..} in \write{..}...
+\newcommand\photobook at logimagesize[3]{%
+	\ifwriteimagelist%
+		% first setup...
+		\photobook at logimagesize@setup%
+		% write...
+		\immediate\write\photobook at imagelist{%
+			#1: p#2: \the\wd#3\space x \the\ht#3}\fi}%
+
+
+% NOTE: these are macros and not lengths as we need to "resolve" these 
+%		as late as possible, i.e. after all the arguments have been 
+%		processed.
+\def\photobook at imagecell@top{0pt}
+\def\photobook at imagecell@left{0pt}
+\def\photobook at imagecell@captiontop{0pt}
+\def\photobook at imagecell@captionleft{0pt}
+
+\newlength\photobook at imagecell@clearance
+\setlength\photobook at imagecell@clearance{0pt}
+
+% NOTE: these feel like a hack...
+\newlength\photobook at imagecell@imgratio
+\newlength\photobook at imagecell@cellratio
+
+% fit/fill...
+\define at boolkey{imagecell at args}{fit}[true]{%
+	\KV at imagecell@args at fillfalse}
+\define at boolkey{imagecell at args}{fill}[true]{%
+	\KV at imagecell@args at fitfalse}
+% center...
+\define at boolkey{imagecell at args}{center}[true]{%
+	\def\photobook at imagecell@top{\dimexpr 
+		+0.5\cellheight 
+		-0.5\ht\photobook at imagebox \relax}%
+	\def\photobook at imagecell@left{\dimexpr 
+		+0.5\cellwidth 
+		-0.5\wd\photobook at imagebox \relax}}%
+% left/right...
+% shortdands...
+\newcommand\photobook at imagecell@LEFT{%
+	\def\photobook at imagecell@left{\dimexpr%
+		+\photobook at imagecell@clearance \relax}%
+	\def\photobook at imagecell@captionleft{
+		% XXX not sure why this branch is needed...
+		\ifKV at imagecell@args at fit
+			0pt
+		\else%
+			\dimexpr%
+				+\cellwidth 
+				-\photobook at imagecell@clearance
+				-\wd\photobook at imagebox \relax\fi}}%
+\newcommand\photobook at imagecell@RIGHT{%
+	\def\photobook at imagecell@left{\dimexpr 
+		+\cellwidth 
+		-\photobook at imagecell@clearance
+		-\wd\photobook at imagebox \relax}
+	% XXX not sure why 0.5 but it seems to work...
+	\def\photobook at imagecell@captionleft{%
+		-0.5\photobook at imagecell@left}}%
+% args...
+\define at boolkey{imagecell at args}{left}[true]{%
+	\photobook at imagecell@LEFT}
+\define at boolkey{imagecell at args}{right}[true]{%
+	\photobook at imagecell@RIGHT}
+% inside/outside...
+\define at boolkey{imagecell at args}{inside}[true]{%
+	\ifthenelse{\isodd{\thepage}}{%
+		\photobook at imagecell@LEFT%
+	}{%
+		\photobook at imagecell@RIGHT}}%
+\define at boolkey{imagecell at args}{outside}[true]{%
+	\ifthenelse{\isodd{\thepage}}{%
+		\photobook at imagecell@RIGHT%
+	}{%
+		\photobook at imagecell@LEFT}}%
+% top/bottom...
+\define at boolkey{imagecell at args}{top}[true]{%
+	\def\photobook at imagecell@top{%
+		\photobook at imagecell@clearance}%
+	\def\photobook at imagecell@captiontop{%
+		-\dimexpr 
+			+\cellheight 
+			-\ht\photobook at imagebox \relax}}%
+\define at boolkey{imagecell at args}{bottom}[true]{%
+	\def\photobook at imagecell@top{%
+		\dimexpr 
+			+\cellheight 
+			-\photobook at imagecell@clearance
+			-\ht\photobook at imagebox \relax}%
+	\def\photobook at imagecell@captiontop{%
+		\dimexpr
+			\photobook at imagecell@top 
+			+\photobook at imagecell@clearance \relax}}%
+% clearance=<len>...
+\define at key{imagecell at args}{clearance}{%
+	\setlength\photobook at imagecell@clearance{#1}}%
+
+% offsettop=<len> / offsetleft=<len>...
+% XXX DOC!!!
+\newlength\photobook at imagecell@offsettop%
+\setlength\photobook at imagecell@offsettop{0pt}%
+\define at key{imagecell at args}{offsettop}[0pt]{%
+	\setlength\photobook at imagecell@offsettop{#1}}%
+\newlength\photobook at imagecell@offsetleft%
+\setlength\photobook at imagecell@offsetleft{0pt}%
+\define at key{imagecell at args}{offsetleft}[0pt]{%
+	\setlength\photobook at imagecell@offsetleft{#1}}%
+
+% scale=<num>...
+\edef\photobook at imagecell@scale{1}%
+\define at key{imagecell at args}{scale}[1]{%
+	\edef\photobook at imagecell@scale{#1}}%
+
+% captionalign=t|c|b...
+\def\photobook at imagecell@captionalign{t}
+\define at choicekey{imagecell at args}{captionalign}{t,c,b}[t]{%
+	\def\photobook at imagecell@captionalign{#1}}
+
+% captionclearparent=<len>...
+% XXX DOC!!!
+\newif\ifphotobook at imagecell@captionclearparent
+\newlength\photobook at imagecell@captionclearparent
+\define at key{imagecell at args}{captionclearparent}[0pt]{%
+	\setlength\photobook at imagecell@captionclearparent{#1}%
+	\photobook at imagecell@captionclearparenttrue}
+
+% XXX can we make this an env???
+\newcommand\imagecell[3][]{%
+	\begingroup%
+		% args...
+		\setkeys{imagecell at args}{%
+			fit,
+			center,
+			clearance=0pt,
+			#1}%
+		% preload image...
+		% fit...
+		\ifKV at imagecell@args at fit%
+			\sbox{\photobook at imagebox}{%
+				\includegraphics[%
+					keepaspectratio, 
+					width=\photobook at imagecell@scale\dimexpr 
+						\cellwidth 
+						- ((\photobook at imagecell@clearance) * 2) \relax,
+					height=\photobook at imagecell@scale\dimexpr 
+						\cellheight 
+						- ((\photobook at imagecell@clearance) * 2) \relax]{#3}}%
+		% fill...
+		\else\ifKV at imagecell@args at fill%
+			% preload image to get its proportions...
+			\sbox{\photobook at imagebox}{\includegraphics{#3}}%
+			% constrain minimal dimension of image...
+			% NOTE: here we calculate image/cell eccentricity to decide 
+			%		to fit to width or heigh of cell...
+			% NOTE: did I say that I "love" how LaTeX does basic math??
+			\setlength\photobook at imagecell@imgratio{%
+				1pt * \ratio{\wd\photobook at imagebox}{\ht\photobook at imagebox}}%
+			\setlength\photobook at imagecell@cellratio{%
+				1pt * \ratio{\cellwidth}{\cellheight}}%
+			\ifdim \photobook at imagecell@imgratio < \photobook at imagecell@cellratio%
+				\sbox{\photobook at imagebox}{%
+					\includegraphics[%
+						keepaspectratio, 
+						width=\photobook at imagecell@scale\dimexpr 
+							+ \cellwidth
+							- ((\photobook at imagecell@clearance) * 2) \relax]{#3}}%
+			\else%
+				\sbox{\photobook at imagebox}{%
+					\includegraphics[%
+						keepaspectratio, 
+						height=\photobook at imagecell@scale\dimexpr 
+							+ \cellheight 
+							- ((\photobook at imagecell@clearance) * 2) \relax]{#3}}%
+		\fi\fi\fi%
+		%
+		\setlength\celloffsetleft{%
+			\dimexpr 
+				\photobook at imagecell@offsetleft 
+				+ \photobook at imagecell@left \relax}%
+		\setlength\celloffsettop{%
+			\dimexpr 
+				\photobook at imagecell@offsettop
+				+ \photobook at imagecell@top \relax}%
+		%
+		%
+		% place image box...
+		% XXX for some odd reason without this the alignment completely breaks...
+		\vspace{0pt}%
+		\smash{\makebox[0pt][l]{%
+			\adjustbox{%
+					margin={\celloffsetleft} 0pt 0pt {\celloffsettop},
+					valign=T}{%
+				\photobook at logimagesize{#3}{\thepage}{\photobook at imagebox}%
+				\usebox\photobook at imagebox}}}%
+		% 
+		%
+		% prepare for caption cell...
+		\setlength\cellparentwidth{\cellwidth}%
+		\setlength\cellparentheight{\cellheight}%
+		\setlength\cellwidth{%
+			\mindim{
+				\wd\photobook at imagebox
+				+ \mindim{\celloffsetleft}{0pt}
+			}{
+				\cellwidth}}%
+		\setlength\cellheight{%
+			\mindim{
+				\ht\photobook at imagebox
+				+ \mindim{\celloffsettop}{0pt}
+			}{
+				\cellheight}}% 
+		\setlength\celloffsetleft{%
+			\maxdim{\celloffsetleft}{0pt}}%
+		\setlength\celloffsettop{%
+			\maxdim{\celloffsettop}{0pt}}%
+		\setlength\clearance{\photobook at imagecell@clearance}%
+		% clear parent...
+		% XXX might be a good idea to put this into a special reusable cell...
+		\ifphotobook at imagecell@captionclearparent%
+			% trim vertical...
+			% XXX this seems overcomplicated...
+			\setlength\cellheight{%
+				\mindim{
+					\cellheight
+				% trim from both sides....
+				}{\mindim{
+					\cellparentheight
+					- 2\photobook at imagecell@captionclearparent
+				% trim from bottom...
+				}{\mindim{
+					\cellheight
+					+ \celloffsettop
+					- \photobook at imagecell@captionclearparent
+				% trim from top...
+				}{
+					\cellparentheight
+					- \photobook at imagecell@captionclearparent 
+					- \celloffsettop}}}}%
+			% offset top...
+			\setlength\celloffsettop{
+				\maxdim{
+					\celloffsettop
+						+ (\photobook at imagecell@captionclearparent - \celloffsettop)
+				}{
+					\celloffsettop}}%
+			% trim horizontal...
+			% XXX this seems overcomplicated...
+			\setlength\cellwidth{%
+				\mindim{
+					\cellwidth
+				% trim from both sides....
+				}{\mindim{
+					\cellparentwidth
+					- 2\photobook at imagecell@captionclearparent
+				% trim from right...
+				}{\mindim{
+					\cellwidth
+					+ \celloffsetleft
+					- \photobook at imagecell@captionclearparent
+				% trim from left...
+				}{
+					\cellparentwidth
+					- \photobook at imagecell@captionclearparent 
+					- \celloffsetleft}}}}%
+			% offset left...
+			\setlength\celloffsetleft{
+				\maxdim{
+					\celloffsetleft
+						+ (\photobook at imagecell@captionclearparent - \celloffsetleft)
+				}{
+					\celloffsetleft}}\fi%
+		%
+		%
+		% place caption box...
+		\smash{\makebox[0pt][l]{%
+			\adjustbox{%
+					%cfbox=gray 0.5pt 0pt 0pt,
+					margin={\celloffsetleft} 0pt 0pt {\celloffsettop},
+					minipage=[b][\cellheight][\photobook at imagecell@captionalign]{\cellwidth},
+					valign=T}{%
+				\ignorespaces%
+				#2}}}%
+	\endgroup}
+
+
+%% \DescribeMacro{\captioncell\{..\}}
+%
+%% Caption cell
+%%
+%% Placement:
+%
+%%	>> \captioncell[<position>]{<caption>}
+%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%     over            
+%%   +-----------------+
+%%   | top             |
+%%   |                 |
+%%   |                 |
+%%   |                 |
+%%   | center          |
+%%   |                 |
+%%   |                 |
+%%   |                 |
+%%   | bottom          |
+%%   +-----------------+
+%%     under           
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%% Default:
+%%	>> \captioncell{<caption>}
+%%	>> \captioncell[top]{<caption>}
+%%
+%%	>> \captioncell[center]{<caption>}
+%%	>> \captioncell[bottom]{<caption>}
+%%
+%%	>> \captioncell[over]{<caption>}
+%%	>> \captioncell[under]{<caption>}
+%%
+%% Horizontal alignment
+%
+%%	>> \captioncell[align=<mode>]{<caption>}
+%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%   +-----------------+    +-----------------+    +-----------------+
+%%   |flushleft        |    |     center      |    |       flushright|
+%%   |                 |    |                 |    |                 |
+%%   |                 |    |                 |    |                 |
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%% Default:
+%%	>> \captioncell{<caption>}
+%%	>> \captioncell[align=flushleft]{<caption>}
+%%
+%%	>> \captioncell[align=center]{<caption>}
+%%	>> \captioncell[align=flushright]{<caption>}
+%%
+%% Note that a caption cell does not take up any space in the parent cell
+%% so multiple captions can be used in combination with other elements.
+%%
+%% Note that caption cells currently do not play well with other content
+%% in the same cell that takes up space, e.g. text, pictures, ...etc.
+%% Captions are mainly suited to play well with image cells.
+%%
+
+% over / top / center / bottom / under...
+\define at boolkey{captioncell at args}{over}[true]{%
+	\def\photobook at captioncell@format##1{%
+		\photobook at captioncell@formatalign[-\cellheight]{b}{##1}}}
+\define at boolkey{captioncell at args}{top}[true]{%
+	\def\photobook at captioncell@format##1{%
+		\photobook at captioncell@formatalign{t}{##1}}}
+\define at boolkey{captioncell at args}{center}[true]{%
+	\def\photobook at captioncell@format##1{%
+		\smash{\makebox[0pt][l]{%
+			\begin{minipage}[t][\cellheight][c]{\cellwidth}%
+			\begin{\photobook at captioncell@align}%
+				\ignorespaces%
+				##1%
+			\end{\photobook at captioncell@align}%
+			\end{minipage}}}}}
+\define at boolkey{captioncell at args}{bottom}[true]{%
+	\def\photobook at captioncell@format##1{%
+		\photobook at captioncell@formatalign{b}{##1}}}
+\define at boolkey{captioncell at args}{under}[true]{%
+	\def\photobook at captioncell@format##1{%
+		\photobook at captioncell@formatalign[\cellheight]{t}{##1}}}
+% align=<len>...
+\def\photobook at captioncell@align{}
+% XXX for some reason \define at choicekey{..} does not expand macros...
+%\define at choicekey{captioncell at args}{align}{flushleft,center,flushright}{%
+\define at key{captioncell at args}{align}{%
+	\def\photobook at captioncell@align{#1}}
+% margin=<len>...
+\def\photobook at captioncell@margin{0pt}
+\define at key{captioncell at args}{margin}{%
+	\def\photobook at captioncell@margin{#1}}
+
+% helpers...
+% XXX set minipage height to available cell height (???)
+\newcommand\photobook at captioncell@formatalign[3][0pt]{%
+	\smash{\makebox[0pt][l]{%
+		\begin{minipage}[t][\cellheight][t]{\cellwidth}%
+			% XXX for some reason without this things get misaligned...
+			\vspace{#1}%
+			% XXX HACK: for some magical reason setting the above minipage to 'b' 
+			%		will make \vspace{..} above break...
+			%		...adding another nested minipage seems to fix the issue...
+			\begin{minipage}[t][\cellheight][#2]{\cellwidth}%
+				\begin{\photobook at captioncell@align}%
+					\ignorespaces%
+					#3%
+				\end{\photobook at captioncell@align}%
+			\end{minipage}
+		\end{minipage}}}}
+% format...
+\def\photobook at captioncell@format#1{%
+	\photobook at captioncell@formatalign{t}{#1}}
+
+\newcommand\captioncell[2][]{%
+	\setkeys{captioncell at args}{
+		top, 
+		align=flushright, 
+		margin=1pt, 
+		#1}%
+	\photobook at captioncell@format{%
+		\adjustbox{margin=\photobook at captioncell@margin}{#2}}%
+	\ignorespaces}
+
+
+%% \DescribeMacro{\vcaptioncell\{..\}}
+%
+%% Vertical caption cell
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%   (topdown)                   (bottomup)
+%%     +-----------------+         +-----------------+
+%%   b | l      c      r | a       |                 |
+%%   e | e      e      i | f       |                 |
+%%   f | f      n      g | t       |                 |
+%%   o | t      t      h | e     e |        r        |
+%%   r |        e      t | r     r |        e      t | r
+%%   e |        r        |       o | t      t      h | e
+%%     |                 |       f | f      n      g | t
+%%     |                 |       e | e      e      i | f
+%%     |                 |       b | l      c      r | a
+%%     +-----------------+         +-----------------+
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%% See samples for better illustration.
+%%
+
+% bottomup / topdown...
+\def\photobook at vcaptioncell@orientation{bottomup}
+\define at boolkey{vcaptioncell at args}{bottomup}[true]{%
+	\KV at vcaptioncell@args at topdownfalse%
+	\def\photobook at vcaptioncell@orientation{bottomup}}
+\define at boolkey{vcaptioncell at args}{topdown}[true]{%
+	\KV at vcaptioncell@args at bottomupfalse%
+	\def\photobook at vcaptioncell@orientation{topdown}}
+
+% before / left / center / right / after...
+\def\photobook at vcaptioncell@position{top}
+\define at boolkey{vcaptioncell at args}{before}[true]{%
+	\def\photobook at vcaptioncell@position{%
+		\ifKV at vcaptioncell@args at bottomup%
+			over%
+		\else%
+			under\fi}}
+\define at boolkey{vcaptioncell at args}{left}[true]{%
+	\def\photobook at vcaptioncell@position{%
+		\ifKV at vcaptioncell@args at bottomup%
+			top%
+		\else%
+			bottom\fi}}
+\define at boolkey{vcaptioncell at args}{center}[true]{%
+	\def\photobook at vcaptioncell@position{center}}
+\define at boolkey{vcaptioncell at args}{right}[true]{%
+	\def\photobook at vcaptioncell@position{%
+		\ifKV at vcaptioncell@args at bottomup%
+			bottom%
+		\else%
+			top\fi}}
+\define at boolkey{vcaptioncell at args}{after}[true]{%
+	\def\photobook at vcaptioncell@position{%
+		\ifKV at vcaptioncell@args at bottomup%
+			under%
+		\else%
+			over\fi}}
+% align...
+\def\photobook at vcaptioncell@align{}
+% XXX for some reason \define at choicekey{..} does not expand macros...
+%\define at choicekey{vcaptioncell at args}{align}{flushleft,center,flushright}{%
+\define at key{vcaptioncell at args}{align}{%
+	\def\photobook at vcaptioncell@align{#1}}
+% margin...
+\def\photobook at vcaptioncell@margin{0pt}
+\define at key{vcaptioncell at args}{margin}{%
+	\def\photobook at vcaptioncell@margin{#1}}
+
+% valign
+\def\photobook at vcaptioncell@valign{%
+	\ifKV at vcaptioncell@args at bottomup%
+		b%
+	\else%
+		t\fi}
+
+\newcommand\vcaptioncell[2][]{%
+	\setkeys{vcaptioncell at args}{
+		left, 
+		bottomup, 
+		align=flushleft, 
+		margin=1pt, 
+		#1}%
+	%
+	\smash{\makebox[0pt][l]{%
+		\begin{minipage}[t][\cellheight][\photobook at vcaptioncell@valign]{\cellwidth}%
+		\begin{\photobook at vcaptioncell@orientation}%
+			\captioncell[%
+					\photobook at vcaptioncell@position,
+					align=\photobook at vcaptioncell@align,
+					margin=\photobook at vcaptioncell@margin]{#2}%
+		\end{\photobook at vcaptioncell@orientation}%
+		\end{minipage}}}%
+	\ignorespaces}
+
+
+%% \DescribeMacro{\rcaptioncell\{..\}}
+%
+%% \EXPERIMENTAL
+%%
+%% Upside-down caption cell.
+%%
+% XXX a bit off...
+\newcommand\rcaptioncell[2][]{%
+		\captioncell[align=flushleft, #1]{%
+			\begin{turn}{180}%
+				% XXX HACK: RAISEBOX -- need to shift by x-height...
+				%		...currently this is set to 1/(golden ratio) would
+				%		be nice to make this parametric / font-derived...
+				\raisebox{1ex * \real{-0.618033988749855}}{#2}%
+			\end{turn}}%
+	\ignorespaces}
+
+
+%% \DescribeMacro{\captionblockcell\{..\}}
+%
+%% Add caption into a box left/right of current cell.
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%    celloffsetleft                celloffsetleft
+%%   <------->                     v 
+%%   .        <-------------->     .<-------------> cellwidth
+%%   <------------------------>    <------------------------> cellparentwidth
+%%   .       ..              ..    ..             .         .
+%%   +------------------------+    +------------------------+ 
+%%   |                        |    |                        | 
+%%   |                        |    |                        | 
+%%   |+-------++ - - - - - - +|    |+ - - - - - - ++-------+| 
+%%   ||       |.             .|    |.             .|       || 
+%%   ||       |.             .|    |.             .|       || 
+%%   ||  cap. |.     cell    .|    |.    cell     .|  cap. || 
+%%   ||       |.             .|    |.             .|       || 
+%%   ||       |.             .|    |.             .|       || 
+%%   |+-------++ - - - - - - +|    |+ - - - - - - ++-------+| 
+%%   |                        |    |                        | 
+%%   |                        |    |                        | 
+%%   +------------------------+    +------------------------+ 
+%%   <> clearcaption                              ..       <> clearcaption
+%%            <> spacing                          <> spacing
+%%                              
+%% \end{verbatim}
+%% \end{minipage}
+%%                              
+% XXX make captions clear top/bottom of page...
+% XXX need to do a caption block -- a cell to one side of an image to the 
+% 		end of the page...
+% XXX can we use the normal caption and simply insert a minipage of the 
+%		appropriate width???
+
+\newlength\photobook at captionblockcell@tmplen
+
+% left / right
+\define at boolkey{captionblockcell at args}{left}[true]{%
+	\KV at captionblockcell@args at rightfalse}
+\define at boolkey{captionblockcell at args}{right}[true]{%
+	\KV at captionblockcell@args at leftfalse}
+
+% align=flushright|center|flushright
+% XXX this should depend on left/right...
+\def\photobook at captionblockcell@align{%
+	\ifKV at captionblockcell@args at left%
+		flushright%
+	\else%
+		flushleft\fi}
+\define at key{captionblockcell at args}{align}{%
+	\def\photobook at captionblockcell@align{#1}}
+
+% valign=t|c|b
+% XXX should be a boolkey -- t|c|b???
+\edef\photobook at captionblockcell@valign{b}
+\define at key{captionblockcell at args}{valign}{%
+	\edef\photobook at captionblockcell@valign{#1}}
+
+% clearance=<len> (defaults: \clearcaption)
+\newlength\photobook at captionblockcell@clearance
+\define at key{captionblockcell at args}{clearance}{%
+	\setlength\photobook at captionblockcell@clearance{#1}}
+
+% XXX should this clear only top/bottom or all sides???
+% XXX doc!!
+% XXX do we need this here???
+\define at boolkey{captionblockcell at args}{constraintoparent}[true]{}
+\newlength\photobook at captionblockcell@clearparent
+\setlength\photobook at captionblockcell@clearparent{0pt}
+\define at key{captionblockcell at args}{clearparent}{%
+	\setlength\photobook at captionblockcell@clearparent{#1}%
+	\KV at captionblockcell@args at constraintoparenttrue}
+
+% spacing=<len>
+\newlength\photobook at captionblockcell@spacing
+\setlength\photobook at captionblockcell@spacing{0pt}
+\define at key{captionblockcell at args}{spacing}{%
+	\setlength\photobook at captionblockcell@spacing{#1}}
+
+% width=<len>
+\newlength\photobook at captionblockcell@width
+\setlength\photobook at captionblockcell@width{0pt}
+\define at key{captionblockcell at args}{width}{%
+	\setlength\photobook at captionblockcell@width{#1}}
+
+% showbox
+\define at boolkey{captionblockcell at args}{showbox}[true]{}
+
+\newcommand\photobook at captionblockcell@content[2][0pt]{%
+	\hspace{\celloffsetleft}{%
+		\begin{adjustbox}{
+				% NOTE: we need to draw the border before we set margins 
+				%		to show the original box...
+				fbox=#1 0pt 0pt,
+				margin=0pt 0pt 0pt \celloffsettop,
+				minipage=[t][\cellheight][\photobook at captionblockcell@valign]{\cellwidth},
+				valign=T}%
+		\begin{\photobook at captionblockcell@align}%
+			\ignorespaces%
+			#2%
+		\end{\photobook at captionblockcell@align}%
+		\end{adjustbox}}}
+
+% XXX revise how \clearance is handled...
+% XXX do we need top/bottom boxes???
+%		...if yes do we need lop/left, top/right, bottom/left and bottom/right???
+% XXX should we keep within parent cell if imagecell has negative clearance???
+% XXX need to auto-place within images via \offsetleft...
+% XXX add tweak support...
+\newcommand\captionblockcell[2][]{%
+	% XXX should this be within the group???
+	\setkeys{captionblockcell at args}{%
+		left, 
+		valign=b,
+		clearance=\clearcaption, 
+		spacing=\captioncellspacing,
+		#1}%
+	%
+	\smash{\makebox[0pt][l]{%
+		\begingroup%
+			% setup cell context...
+			\setlength\clearcaption{%
+				\photobook at captionblockcell@clearance}%
+			\setlength\photobook at captionblockcell@tmplen{\cellwidth}%
+			\setlength\cellwidth{%
+				\ifnum \photobook at captionblockcell@width = 0%
+					\dimexpr 
+						\cellparentwidth 
+						- \photobook at captionblockcell@spacing
+						- \cellwidth 
+						- \clearcaption 
+						% XXX this is only present in images...
+						- \clearance \relax%
+				\else%
+					\photobook at captionblockcell@width\fi}%
+			\setlength\cellparentwidth{%
+				\photobook at captionblockcell@tmplen}%
+			\setlength\celloffsetleft{%
+				\ifKV at captionblockcell@args at left%
+					\dimexpr
+						- \cellwidth%
+						- \photobook at captionblockcell@spacing \relax%
+				\else%
+					\dimexpr
+						\cellparentwidth
+						+ \photobook at captionblockcell@spacing \relax%
+					\fi}%
+			% clear parent...
+			% XXX do we need this here???
+			\ifKV at captionblockcell@args at constraintoparent%
+				% offset top...
+				\setlength\celloffsettop{%
+					\mindim{
+						\photobook at captionblockcell@clearparent - \celloffsettop
+					}{
+						\photobook at captionblockcell@clearparent}}%
+				% trim cell top... 
+				\ifdim \celloffsettop > 0pt%
+					\setlength\cellheight{%
+						\cellheight - \celloffsettop}\fi%
+				% trim cell bottom...
+				\ifdim \dimexpr 
+							\cellheight 
+							+ \celloffsettop \relax%
+						> \dimexpr 
+							\cellparentheight 
+							- \photobook at captionblockcell@clearparent \relax%
+					\setlength\cellheight{%
+						\dimexpr
+							\cellparentheight 
+								- \mindim{
+									\cellheight - \cellparentheight
+								}{
+									2\photobook at captionblockcell@clearparent} \relax}\fi%
+			% do not clear parent...
+			\else%
+				\setlength\celloffsettop{0pt}\fi%
+			%
+			% place...
+			\ifKV at captionblockcell@args at showbox%
+				\photobook at captionblockcell@content[0.1pt]{#2}%
+			\else%
+				\photobook at captionblockcell@content{#2}\fi%
+		\endgroup}}%
+	\ignorespaces}
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%%%%% Paper cells
+%
+%% Paper and page cells are very similar but differ in one aspect -- paper
+%% cells represent the paper as indicated by |layoutmode=<layout>| while
+%% page cells are always the size of the page block, i.e. |layoutmode=block|.
+%%
+
+%% \DescribeEnv{papercell}
+%
+%% Paper cell.
+%%
+%% This does not include bleeds.
+%%
+\newenvironment{papercell}{%
+	\begin{cell*}{\bleed, \bleed}{\blockwidth}{\blockheight}%
+}{%
+	\end{cell*}}
+
+
+%% \DescribeEnv{paperbleedcell}
+%
+%% Paper bleed cell.
+%%
+%% Like |papercell| but includes bleeds.
+%%
+\newenvironment{paperbleedcell}{%
+	\begin{cell*}{0pt, 0pt}{\bleedblockwidth}{\bleedblockheight}%
+}{%
+	\end{cell*}}
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%%%%% Page cells
+%
+%% Page cells always correspond to the page block size, i.e. |layoutmode=block| 
+%% regardless of the actual |layoutmode| set currently.
+%%
+
+%% \DescribeEnv{pagecell}
+%% \DescribeEnv{pagecell*}
+%
+%% Page cell. 
+%%
+%% This corresponds to the visible page in the |layoutmode=block| and 
+%% does not include bleeds.
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%   <-> bleed         <-> bleed
+%%
+%%   + - - - - - - - - - +    + bleed
+%%   . +---------------+ .    v
+%%   . |               | .   
+%%   . |               | .   
+%%   . |   pagecell    | .   
+%%   . |               | .   
+%%   . |               | .   
+%%   . +---------------+ .    + bleed
+%%   + - - - - - - - - - +    v
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%% The star version accounts for |\bindingoffset|. 
+%%
+%% Note that |layoutmode|'s other than block will change the paper size 
+%% but will not affect this either in size (block size) or in position 
+%% (top-left).
+%%
+\newenvironment{pagecell}{%
+	\begin{cell*}{\bleed,\bleed}{\pageblockwidth}{\pageblockheight}%
+}{%
+	\end{cell*}}
+
+\newenvironment{pagecell*}{%
+	\begin{cell*}{%
+			\bleed + \ifnumodd{\thepage}{\bindingoffset}{0pt},%
+			\bleed}%
+		{\pageblockwidth - \bindingoffset}%
+		{\pageblockheight}%
+}{%
+	\end{cell*}}
+
+
+%% \DescribeEnv{pagebleedcell}
+%
+%% Like |page| but includes bleeds.
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%   <-> bleed         <-> bleed
+%%
+%%   +-------------------+    + bleed  
+%%   | + - - - - - - - + |    v        
+%%   | .               . |             
+%%   | .               . |             
+%%   | . pagebleedcell . |             
+%%   | .               . |             
+%%   | .               . |             
+%%   | + - - - - - - - + |    + bleed  
+%%   +-------------------+    v        
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%% Note that as with |pagecell| this is not affected by |layoutmode|.
+%%
+\newenvironment{pagebleedcell}{%
+	\begin{cell*}{0pt, 0pt}{\bleedblockwidth}{\bleedblockheight}%
+}{%
+	\end{cell*}}
+
+
+
+% XXX EXPERIMENTAL / TEST...
+\NewEnviron{shipoutbgcell}{%
+	\AddToShipoutPictureBG*{%
+		\begin{pagecell}%
+			\BODY%
+		\end{pagecell}}%
+	\ignorespaces}
+
+
+
+% XXX EXPERIMENTAL / TEST...
+%% \DescribeEnv{textcell}
+%
+%% \EXPERIMENTAL
+%%
+%% A cell taking up the page text block.
+%
+%%	>> \begin{textcell}{<width>}{<height>} ... \end{textcell}
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%      <-----------> \textwidth
+%%                          
+%%   <-----------------> \pageblockwidth
+%%
+%%   +-----------------+   ^ \pageblockheight
+%%   |                 |   |
+%%   |  +-----------+  |   |  ^ \textheight
+%%   |  |           |  |   |  |
+%%   |  |           |  |   |  |
+%%   |  | textcell  |  |   |  |
+%%   |  |           |  |   |  |
+%%   |  |           |  |   |  |
+%%   |  +-----------+  |   |  v
+%%   |                 |   | 
+%%   +-----------------+   v 
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%% Note that this is an inline cell and if something is on the page it 
+%% may not be centered properly.
+%%
+\newenvironment{textcell}{%
+	\begin{inlinecell*}{\textwidth}{\textheight}%
+}{%
+	\end{inlinecell*}}
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%%%%% Foldout page cells
+%
+%% \EXPERIMENTAL
+%%
+%% A foldout is a special case cell that changes the page format. 
+%%
+%% In addition to cell lengths a foldout defines a set of additional 
+%% lengths and lists within its context.
+%%
+%% \DescribeMacro{\pagefoldpanels=<list>}
+%% \DescribeMacro{\pagefoldpanelfolds=<list>}
+%
+%% Lists page folded panel widths and fold types respectively.
+%%
+%% |pagefoldpanels| is set automatically for layouts other than |block| 
+%% and for foldout pages, changing this can mess up fold markers and 
+%% page cell placement.
+%%
+%% |pagefoldpanelfolds| is generated when creating a foldout.
+%%
+%% See:
+%% \href{https://ctan.altspu.ru/macros/generic/listofitems/listofitems-en.pdf}{listofitems}
+%% for list API.
+%%
+% XXX add a generic panel constructor..
+%		\foldedcell[<height>]{<index>}
+% NOTE: these are wrapped in \@ifundefined{..} to prevent overwriting when
+%		values are defined in \InitPages...
+\@ifundefined{pagefoldpanels}{%
+	\def\pagefoldpanels{}}{}
+\@ifundefined{pagefoldpanelfolds}{%
+	\def\pagefoldpanelfolds{}}{}
+
+%% \DescribeMacro{\foldoutwidth=<len>}
+%
+%% Total foldout page width, calculated when a foldout page is created.
+%%
+\newlength\foldoutwidth
+\setlength\foldoutwidth{\blockwidth}
+
+
+%% \DescribeEnv{foldout}
+%
+%% Create 2 or more pages in foldout mode.
+%
+%%	>> \begin{foldout}[<fold-spec>] ... \end{foldout}
+%
+%% |<fold-spec>| can be a number of folds, or contain one or more fold 
+%% types (|in| or |out|), two or more panel widths (dimensions) or a
+%% sequence of both (i.e. dim fold dim ...) where missing widths are 
+%% automatically calculated and missing folds are the same as the previous
+%% fold or the default if no folds are specified.
+%%
+%% If not |<fold-spec>| is given, then the value of |\defaultfoldout| is
+%% used (default: |2|).
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%                            v    \flatfold    v
+%%          
+%%       - --=----------------++---------------++--------------+
+%%           =                ..               ..              |
+%%           =                ..               ..              |
+%%           =                ..               ..              |
+%%           =                ..               ..              |
+%%           =                ..               ..              |
+%%           =                ..               ..              |
+%%           =                ..               ..              |
+%%           =                ..               ..              |
+%%           =                ..               ..              |
+%%           =            (1) ..           (2) ..          (3) |
+%%       - --=----------------++---------------++--------------+
+%%          
+%%  +--------------++---------------++----------------=-- -
+%%  |              ..               ..                =
+%%  |              ..               ..                =
+%%  |              ..               ..                =
+%%  |              ..               ..                =
+%%  |              ..               ..                =
+%%  |              ..               ..                =
+%%  |              ..               ..                =
+%%  |              ..               ..                =
+%%  |              ..               ..                =
+%%  |          (1) ..           (2) ..            (3) =
+%%  +--------------++---------------++----------------=-- -
+%%
+%%                 ^    \flatfold    ^
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%%
+%% A foldout always starts on the right/odd page and will always end on 
+%% the left/even page. 
+%%
+%% If |\foldoutpages{..}| is called on an even page, an empty normal 
+%% page will be created pushing the foldout to the right page of the 
+%% spread. If an odd number of pages is created the set will be padded 
+%% with an empty page before |\foldoutpages{..}| exits.
+%%
+%%
+%% Foldout panel numbering
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%                 right page
+%%           - --=-------+-------+-    --+-------+-------+
+%%               =       |       |       |       |       |
+%%               =  (1)  |  (2)  |  ...  | (n-1) |  (n)  |
+%%               =       |       |       |       |       |
+%%           - --=-------+-------+--    -+-------+-------+
+%%
+%%                                 left page
+%%   +-------+-------+-    --+-------+-------=-- -
+%%   |       |       |       |       |       =
+%%   |  (1)  |  (2)  |  ...  | (n-1) |  (n)  =
+%%   |       |       |       |       |       =
+%%   +-------+-------+--    -+-------+-------=-- -
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%% Formal |<fold-spec>| grammar:
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%   <fold-spec> ::
+%%       <count>
+%%       | <fold>
+%%       | <panels>
+%%   <panels> ::=
+%%       <panel>
+%%       | <panel> <panels>
+%%   <panel> ::=
+%%       <width> <fold>
+%%       | <width>
+%%       | <fold>
+%%   <fold> ::= 
+%%      in | out
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%
+%% \DescribeMacro{\clearfoldoutbinding=<len>}
+%% \DescribeMacro{\clearfoldoutedge=<len>}
+%% \DescribeMacro{\clearfoldoutfold=<len>}
+%
+%% Fold panel sizing for similar fold sequence:
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%                       \clearfoldoutedge <->
+%%                    \clearfoldoutfold <->  
+%%   <--> \clearfoldoutbinding
+%%                                                    (3)  /\  (2)  
+%%      +---------------------------------+               /  \     
+%%      +-------------------------------  |                  /     
+%%   -------------------------------------+                 /  (1) 
+%%   ========================================         =====+=====  
+%%   ========================================        
+%%                                                 
+%% \end{verbatim}                                  
+%% \end{minipage}                                  
+%%
+%% Note that |in in| fold sequence is drawn, |out out| is identical in 
+%% sizing but reflectd.
+%%
+%%
+%% Fold panel sizing for dissimilar fold sequence:
+%%
+%% \begin{minipage}{\textwidth}                    
+%% \begin{verbatim}                                
+%%                                                 
+%%                      \clearfoldoutedge <->                /      
+%%   <--> \clearfoldoutbinding                         (3)  /       
+%%                                                          \       
+%%      +----------------------------------                  \  (2) 
+%%      +---------------------------------+                  /      
+%%   -------------------------------------+                 /  (1)  
+%%   ========================================         =====+=====   
+%%   ========================================
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%% |in out| is drawn, |out it| is the same but reflected.
+%%
+%% The size of the paper fold is set by |\flatfold|.
+%%
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% Fold marks...
+
+% draw in/out fold mark...
+%
+%	>> \foldinmark[<baseline>]
+%	>> \foldoutmark[<baseline>]
+%
+% NOTE: these should be used in a box.
+% NOTE: these are centered in origin.
+%
+% XXX these can affect the items after -- need to encapsulate better + test...
+% XXX do we need to make centering block size dependant on \foldmarksize 
+%		or are the two independent??? (test)
+% XXX MARKOFFSET for some reason splitting the \vspace{..} into a 
+%		arg-dependant and a foldmarklen-dependant parts below yields 
+%		wrong results...
+%		...not that simply splitting the original into two \vspace{..} 
+%		calls works fine...
+\newsavebox\photobook at foldinmark
+\newsavebox\photobook at foldoutmark
+\newcommand\ResetFoldMarks{%
+	\sbox{\photobook at foldinmark}{%
+		% XXX MARKOFFSET
+		%\vspace{0.5\photobook at foldmarklen}%
+		\smash{\makebox[0pt][l]{%
+			% size-agnostic centering...
+			\hspace{-5mm}{\makebox[1cm][c]{%
+				\begin{tikzpicture}%
+					\draw[white, ultra thick] 
+						(-0.3333\photobook at foldmarklen,0.3333\photobook at foldmarklen) 
+						-- (0,0) 
+						-- (0.3333\photobook at foldmarklen,0.3333\photobook at foldmarklen);
+					\draw[white, ultra thick] 
+						(0,0.6666\photobook at foldmarklen) 
+						-- (0,-0.3333\photobook at foldmarklen);
+					\draw[black, thin] 
+						(-0.3333\photobook at foldmarklen,0.3333\photobook at foldmarklen) 
+						-- (0,0) 
+						-- (0.3333\photobook at foldmarklen,0.3333\photobook at foldmarklen);
+					\draw[black, thin] 
+						(0,0.6666\photobook at foldmarklen) 
+						-- (0,-0.3333\photobook at foldmarklen);
+				\end{tikzpicture}}}}}}
+	\sbox{\photobook at foldoutmark}{%
+		% XXX MARKOFFSET
+		%\vspace{0.5\photobook at foldmarklen}%
+		\smash{\makebox[0pt][l]{%
+			% size-agnostic centering...
+			\hspace{-5mm}{\makebox[1cm][c]{%
+				\begin{tikzpicture}%
+					\draw[white, ultra thick] 
+						(-0.3333\photobook at foldmarklen,0) 
+						-- (0,0.3333\photobook at foldmarklen) 
+						-- (0.3333\photobook at foldmarklen,0);
+					\draw[white, ultra thick] 
+						(0,0.6666\photobook at foldmarklen) 
+						-- (0,-0.3333\photobook at foldmarklen);
+					\draw[black, thin] 
+						(-0.3333\photobook at foldmarklen,0) 
+						-- (0,0.3333\photobook at foldmarklen) 
+						-- (0.3333\photobook at foldmarklen,0);
+					\draw[black, thin] 
+						(0,0.6666\photobook at foldmarklen) 
+						-- (0,-0.3333\photobook at foldmarklen);
+				\end{tikzpicture}}}}}}}
+\ResetFoldMarks
+
+% XXX EXPERIMENTAL...
+% XXX not sure if this should ever be needed...
+%\newcommand\setfoldmarksize[1][6mm]{%
+%	\setlength\photobook at foldmarklen{#1}%
+%	%\edef\photobook at foldmarklen{#1}%
+%	\ResetFoldMarks}
+
+%	>> \foldinmark[<baseline>]
+\newcommand\foldinmark[1][0pt]{%
+	% XXX MARKOFFSET
+	%\vspace{#1}%
+	\vspace{\dimexpr 0.5\photobook at foldmarklen + #1 \relax}%
+	\usebox\photobook at foldinmark}
+%	>> \foldoutmark[<baseline>]
+\newcommand\foldoutmark[1][0pt]{
+	% XXX MARKOFFSET 
+	%\vspace{#1}%
+	\vspace{\dimexpr 0.5\photobook at foldmarklen + #1 \relax}%
+	\usebox\photobook at foldoutmark}
+
+%	>> \photobook at foldmark[<baseline>]{<type>}{<left>, <top>}
+\newif\ifphotobook at foldmark@in
+\newcommand\photobook at foldmark[3][0pt]{%
+	\begingroup%
+		\ifnumodd{\thepage}{%
+			\ifthenelse{\equal{#2}{in}}{%
+				\photobook at foldmark@intrue}{%
+				\photobook at foldmark@infalse}}{%
+			\ifthenelse{\equal{#2}{in}}{%
+				\photobook at foldmark@infalse}{%
+				\photobook at foldmark@intrue}}%
+		\begin{textblock*}{0pt}(#3)%
+			\ifphotobook at foldmark@in%
+				\foldinmark[#1]%
+			\else%
+				\foldoutmark[#1]\fi%
+		\end{textblock*}%
+	\endgroup}
+\newcommand\photobook at topfoldmark[2][in]{%
+	\photobook at foldmark[-0.5\photobook at foldmarklen]{#1}{#2}}
+\newcommand\photobook at bottomfoldmark[2][in]{%
+	\photobook at foldmark[0.5\photobook at foldmarklen]{#1}{#2}}
+%	>> \photobook at markfold[<fold>]{<offset>}
+\newcommand\photobook at markfold[2][in]{%
+	\photobook at topfoldmark[#1]{
+		#2,
+		\bleed 
+			- \foldmarkoffset}%
+	\photobook at bottomfoldmark[#1]{
+		#2,
+		\blockheight 
+			+ \bleed 
+			+ \foldmarkoffset}}
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\newlength\photobook at foldout@panelwidth
+\setlength\photobook at foldout@panelwidth{0pt}
+\newlength\photobook at foldout@maxpanelwidth
+\setlength\photobook at foldout@maxpanelwidth{0pt}
+\edef\photobook at foldout@count{}
+\edef\photobook at foldout@prevfold{in}
+
+%	>> \photobook at foldout@pushpanel{<width>}{<fold>}
+%
+% XXX should we set maxpanelwidth when manually setting panel widths???
+% XXX might be good to warn the user if the manual fold will not work...
+%		after two folds in same direction panels must be strictly smaller...
+%		...would be nice to maintain maxpanelwidth and warn if explicit 
+%		width is larger...
+\newcommand\photobook at foldout@pushpanel[2]{%
+	% initial max panel size...
+	\ifnum \thephotobook at foldoutpanel = 1%
+		\setlength\photobook at foldout@maxpanelwidth{%
+			\blockwidth
+			- \clearfoldoutedge}\fi%
+	% panel #2 -- clear binding...
+	\ifnum \thephotobook at foldoutpanel = 2%
+		\setlength\photobook at foldout@maxpanelwidth{%
+			\photobook at foldout@maxpanelwidth
+			- \clearfoldoutbinding}\fi%
+	% calculate widths...
+	\ifdim #1 = 0pt%
+		% first two panels do not need fold compensation...
+		\ifnum \thephotobook at foldoutpanel < 3%
+			\setlength\photobook at foldout@panelwidth{%
+				\photobook at foldout@maxpanelwidth
+				+ \flatfold}%
+		\else%
+			% double fold twice in same direction...
+			\ifthenelse{\equal{#2}{\photobook at foldout@prevfold}}{%
+				\setlength\photobook at foldout@panelwidth{%
+					\photobook at foldout@maxpanelwidth 
+					+ \flatfold
+					- \clearfoldoutfold}%
+			% different fold directions -- no resizing needed here...
+			}{%
+				\setlength\photobook at foldout@panelwidth{%
+					\photobook at foldout@maxpanelwidth
+					+ \flatfold}}\fi%
+		\setlength\photobook at foldout@maxpanelwidth{%
+			\photobook at foldout@panelwidth}%
+	% explicit width...
+	\else%
+		% XXX should we set the maxpanelwidth here too???
+		%		...if yes, should we be more thorough and size it to the 
+		%		available space (accounting for last two folds)??
+		%\setlength\photobook at foldout@maxpanelwidth{#1}%
+		\setlength\photobook at foldout@panelwidth{#1}\fi%
+	% accumulate width...
+	\setlength\foldoutwidth{
+		\foldoutwidth
+		+ \photobook at foldout@panelwidth}%
+	% panel spec lists...
+	\edef\pagefoldpanelfolds{%
+		\pagefoldpanelfolds,#2}%
+	\edef\pagefoldpanels{%
+		\pagefoldpanels,\the\photobook at foldout@panelwidth}%
+	\stepcounter{photobook at foldoutpanel}}
+
+% XXX also add this to jacket/cover/endpaper...
+\newlength\photobook at showmarks@offset
+\setlength\photobook at showmarks@offset{0pt}
+\newcommand\photobook at showmarks{%
+	% XXX make this a list-length check...
+	\ifx \pagefoldpanels \empty \else%
+		\begingroup%
+			\setlength\photobook at showmarks@offset{\bleed}%
+			% NOTE: we need to iterate left/right pages in reverse order...
+			% NOTE: the below branches are similar but not identical...
+			\ifnumodd{\thepage}{%
+				\xintFor* ##1 in {\xintSeq{1}{\pagefoldpanelslen - 1}} \do {%
+					\setlength\photobook at showmarks@offset{
+						\photobook at showmarks@offset
+						+ \pagefoldpanels[##1]}%
+					% XXX HACK: it appears that we can't expand \pagefoldpanelfolds[##1] in [..]...
+					\edef\photobook at showmarks@tmp{\pagefoldpanelfolds[##1]}%
+					\photobook at markfold[\photobook at showmarks@tmp]{\photobook at showmarks@offset}}%
+			}{
+				\xintFor* ##1 in {\xintSeq{\pagefoldpanelslen}{2}} \do {%
+					\setlength\photobook at showmarks@offset{
+						\photobook at showmarks@offset
+						+ \pagefoldpanels[##1]}%
+					% XXX HACK: it appears that we can't expand \pagefoldpanelfolds[##1] in [..]...
+					\edef\photobook at showmarks@tmp{\pagefoldpanelfolds[##1 - 1]}%
+					\photobook at markfold[\photobook at showmarks@tmp]{\photobook at showmarks@offset}}}%
+		\endgroup\fi}
+\AtBeginShipout{%
+	\iffoldmarks%
+		\photobook at showmarks\fi}
+
+\newcounter{photobook at foldoutpanel}
+\setcounter{photobook at foldoutpanel}{1}
+
+\newenvironment{foldout}[1][\defaultfoldout]{%
+	\begingroup%
+		\setsepchar{ }%
+		\readlist*\photobook at foldout@args{#1}%
+		%
+		% defaults...
+		\setcounter{photobook at foldoutpanel}{1}
+		\setlength\foldoutwidth{0pt}%
+		\edef\photobook at foldout@prevfold{\pagefold}%
+		%
+		% panel count...
+		\ifnum \photobook at foldout@argslen = 1%
+			% in/out...
+			\ifthenelse{
+					\equal{#1}{in} 
+						\OR \equal{#1}{out}}{%
+				\edef\photobook at foldout@count{2}%
+				\edef\photobook at foldout@prevfold{#1}%
+			% count...
+			}{%
+				\edef\photobook at foldout@count{#1}}%
+			%
+			% build the panels...
+			\xintFor* ##1 in {\xintSeq{1}{\photobook at foldout@count}} \do {%
+				\photobook at foldout@pushpanel{%
+					0pt}{\photobook at foldout@prevfold}}%
+		% fold spec...
+		\else%
+			\foreachitem \photobook at foldout@opt \in \photobook at foldout@args{%
+				% in/out...
+				\ifthenelse{
+						\equal{\photobook at foldout@opt}{in} 
+							\OR \equal{\photobook at foldout@opt}{out}}{%
+					\photobook at foldout@pushpanel{%
+						\photobook at foldout@panelwidth}{\photobook at foldout@opt}%
+					% prep for next panel...
+					\edef\photobook at foldout@prevfold{%
+						\photobook at foldout@opt}%
+					\setlength\photobook at foldout@panelwidth{0pt}%
+				% explicit size...
+				}{%
+					% finalize prev panel...
+					\ifdim \photobook at foldout@panelwidth > 0pt%
+						\photobook at foldout@pushpanel{%
+							\photobook at foldout@panelwidth}{\photobook at foldout@prevfold}\fi%
+					%
+					\setlength\photobook at foldout@panelwidth{\photobook at foldout@opt}}}%
+			% add trailing panel... 
+			\photobook at foldout@pushpanel{%
+				\photobook at foldout@panelwidth}{\photobook at foldout@prevfold}%
+		\fi%
+		% prepare data for cells...
+		\setsepchar{,}%
+		% NOTE: the first element is empty due to how we create these 
+		%		i.e. ('' + ',<value>')...
+		\ignoreemptyitems%
+		\readlist*\pagefoldpanelfolds{\pagefoldpanelfolds}%
+		\readlist*\pagefoldpanels{\pagefoldpanels}%
+		%
+		% pages...
+		% NOTE: we'll keep the start of the foldout set at the right page
+		%		and end it on the left page.
+		\cleardoublepage%
+		\begin{resizedpages}{\foldoutwidth}{\blockheight}%
+			\ignorespaces%
+}{%
+			\cleardoublepage%
+		\end{resizedpages}%
+	\endgroup}
+
+
+%% \DescribeEnv{foldoutcell}
+%% \DescribeEnv{foldoutcell*}
+%
+%% Create a cell spanning one or more foldout panels.
+%
+%%	>> \begin{foldoutcell}[<num>] ... \end{foldoutcell}
+%%	>> \begin{foldoutcell}[<from>-<to>] ... \end{foldoutcell}
+%
+%% If no arguments are given this will create a panel at |foldoutpanel| 
+%% counter and increment it by one. 
+%
+%%	>> \begin{foldoutcell} ... \end{foldoutcell}
+%
+%% This will also auto-advance the page when all panels are filled.
+%% 
+%% Note that manual panel placement has no effect on the panel counter 
+%% thus care must be taken when mixing manual and auto-advanced panels.
+%% Also note that |foldoutpanel|'s value is not maintained within manually 
+%% placed panels and should be treated as undefined.
+%%
+%% |foldoutcell*| is the same as the non-star version but creates cells
+%% including bleeds.
+%%
+%% Neither version clips its content, to explicitly clip use the |cliptocell| 
+%% environment.
+%%
+%% These can only be used from within a |foldout| cell.
+%%
+% XXX should we be able to turn clipping on/off???
+
+\newlength\photobook at foldoutcell@left
+\setlength\photobook at foldoutcell@left{0pt}
+\newlength\photobook at foldoutcell@width
+\setlength\photobook at foldoutcell@width{0pt}
+
+% calculate offset via \pagefoldpanels and write to dimension <name>...
+%	>> \photobook at foldoutcell@setfoldoutoffset{<name>}{<from>}{<to>}
+%
+% NOTE: [<from>, <to>[ -- i.e. <to> is not included...
+\newcommand\photobook at foldoutcell@setfoldoutoffset[3]{%
+	\expandafter\setlength\csname #1\endcsname{0pt}%
+	\ifnum \numexpr #2 \relax < \numexpr #3 \relax%
+		\xintFor* ##1 in {%
+				\xintSeq{#2}{\xintiiMin{#3}{\pagefoldpanelslen + 1} - 1}} \do {%
+			\ifnumodd{\thepage}{%
+				\expandafter\setlength\csname #1\endcsname{%
+					\csname #1\endcsname%
+					+ \pagefoldpanels[##1]}
+			}{%
+				\expandafter\setlength\csname #1\endcsname{%
+					\csname #1\endcsname%
+					+ \pagefoldpanels[-\numexpr ##1 \relax]}}}\fi}
+
+% foldout panel auto-advance counter...
+\newcounter{foldoutpanel}
+\setcounter{foldoutpanel}{0}
+\edef\photobook at foldoutcell@from{0}
+% reset panel count on each page...
+\AtBeginShipout{%
+	\setcounter{foldoutpanel}{0}
+	\edef\photobook at foldoutcell@from{%
+		\thefoldoutpanel}}
+
+% set panel left/width dimensions (helper)...
+%	>> \photobook at foldoutcell@setdimensions[<panel-spec>]
+%
+% NOTE: for <panel-spec> see docs for foldoutcell/foldoutcell*...
+\newcommand\photobook at foldoutcell@setdimensions[1][0]{
+	% parse args...
+	\setsepchar{-}%
+	\readlist*\photobook at foldoutcell@panels{#1}%
+	%
+	% auto advance panel...
+	\ifnum \photobook at foldoutcell@panels[1] = 0%
+		% auto advance page...
+		\ifnum \value{foldoutpanel} = \pagefoldpanelslen%
+			% NOTE: this will reset the counter...
+			\newpage\fi%
+		\stepcounter{foldoutpanel}%
+		\global\edef\photobook at foldoutcell@from{%
+			\thefoldoutpanel}%
+	% explicit panels...
+	\else%
+		\global\edef\photobook at foldoutcell@from{
+			\photobook at foldoutcell@panels[1]}\fi%
+	% left offset...
+	\photobook at foldoutcell@setfoldoutoffset{photobook at foldoutcell@left}{%
+			1
+		}{%
+			\photobook at foldoutcell@from}%
+	% panel from-to width...
+	\ifnum \photobook at foldoutcell@panelslen > 1%
+		\photobook at foldoutcell@setfoldoutoffset{photobook at foldoutcell@width}{%
+				\photobook at foldoutcell@from%
+			}{%
+				\photobook at foldoutcell@panels[2] + 1}%
+	% panel N width...
+	\else%
+		\ifnumodd{\thepage}{%
+			\setlength\photobook at foldoutcell@width{%
+				\pagefoldpanels[{\photobook at foldoutcell@from}]}
+		}{%
+			\setlength\photobook at foldoutcell@width{%
+				\pagefoldpanels[-\numexpr \photobook at foldoutcell@from \relax]}}\fi}
+
+\newenvironment{foldoutcell}[1][0]{%
+	% XXX check if outside of foldout -> warn...
+	\begingroup%
+		\photobook at foldoutcell@setdimensions[#1]%
+		\begin{cell*}{%
+					\bleed 
+						+ \photobook at foldoutcell@left,%
+					\bleed}%
+				{\photobook at foldoutcell@width}%
+				{\pageblockheight}%
+}{%
+		\end{cell*}%
+	\endgroup}
+
+\newenvironment{foldoutcell*}[1][0]{%
+	% XXX check if outside of foldout -> warn...
+	\begingroup%
+		\photobook at foldoutcell@setdimensions[#1]%
+		% add bleed to first/last panel...
+		\ifnum \photobook at foldoutcell@from = 1%
+			\setlength\photobook at foldoutcell@width{%
+				\bleed
+				+ \photobook at foldoutcell@width}
+		\else%
+			\setlength\photobook at foldoutcell@left{%
+				\bleed
+				+ \photobook at foldoutcell@left}\fi%
+		\ifnum \photobook at foldoutcell@from = \pagefoldpanelslen%
+			\setlength\photobook at foldoutcell@width{%
+				\bleed
+				+ \photobook at foldoutcell@width}\fi%
+		\begin{cell*}{%
+					\photobook at foldoutcell@left,%
+					0pt}%
+				{\photobook at foldoutcell@width}%
+				{\pageblockheight + 2\bleed}%
+}{%
+		\end{cell*}%
+	\endgroup}
+
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%%%%% Multi-page cells
+%
+%% \DescribeEnv{spreadtopages}
+%% \DescribeEnv{spreadtopages*}
+%% \DescribeMacro{\usespreadpage\{..\}}
+%% \DescribeMacro{\usespreadpage*\{..\}}
+%
+%% Spread cell into pages.
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%   +----------------------------------- -                 
+%%   |                                                      <-- input cell
+%%   |          .          .          .                     
+%%   |     Oversized content cell...                        
+%%   |          .          .          .                     
+%%   |                                                      
+%%   +----------.----------.----------.-- -                 
+%%   .          . .         . .         .  .
+%%   .          .   .         .   .         .    .         
+%%   +----------+    +----------+    +----------+    +-- -  
+%%   |          |    |          |    |          |    |      <-- output pages
+%%   |          |    |          |    |          |    |      
+%%   |     Overs|    |ized conte|    |nt cell...|    |      
+%%   |          |    |          |    |          |    |      
+%%   |          |    |          |    |          |    |    
+%%   +----------+    +----------+    +----------+    +-- -
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%% |spreadtopages| creates a cell and spreads it into pages right away.
+%%
+%%	>> \begin{spreadtopages} .. \end{spreadtopages}
+%%	>> \begin{spreadtopages}[<page-count>] .. \end{spreadtopages}
+%%
+%% |spreadtopages*| creates a named save cell only allowing the pages 
+%% to be placed manually via |\usespreadpage{..}|.
+%%
+%%	>> \begin{spreadtopages*}{<name>} .. \end{spreadtopages*}
+%%	>> \begin{spreadtopages*}[<page-count>]{<name>} .. \end{spreadtopages*}
+%%
+%% |\usespreadpage{..}| places a page from a saved cell.
+%%
+%%	>> \usespreadpage{<name>}
+%%	>> \usespreadpage[<page-num>]{<name>}
+%%
+%% |\usespreadpage*{..}| is the same as the non-star version but will 
+%%	not use a |page| environment, enabling the user to populate the page
+%%	with other elements.
+%%
+%% Page numbers are 1-based.
+%%
+%% Note that the cell created by |spreadtopages*| env is a normal save 
+%% cell and can be manipulated via |\usecell{..}| and |\usecell*{..}|.
+%%
+% XXX add nudge/grow support...
+
+\NewEnviron{spreadtopages*}[2][2]{%
+	% setup page count...
+	\@ifundefined{thespreadtopages#2page}{%
+		\newcounter{spreadtopages#2page}}{}
+	\setcounter{spreadtopages#2page}{1}
+	%
+	\begingroup%
+		% create the actual cell...
+		\setlength\cellparentwidth{\cellwidth}%
+		\setlength\cellparentheight{\cellheight}%
+		\setlength\cellwidth{#1\pageblockwidth}%
+		\setlength\cellheight{\pageblockheight}%
+		%
+		\gsavecell{#2}{\cellwidth}{\cellheight}{\BODY}%
+	\endgroup%
+	\ignorespaces}
+
+% NOTE: this essentially counts pages, \usecell{..} / \usecell*{..} are 
+%		better suited for custom stuff...
+% NOTE: page is a 1 based offset in pages and can be fractional...
+% NOTE: \usecell*{..} takes care of all the bleed calculations...
+\def\usespreadpage{\@ifstar{%
+		\photobook at usespreadpage@star%
+	}{%
+		\photobook at usespreadpage}}
+\newcommand\photobook at usespreadpage@star[2][]{%
+	\begin{pagecell}%
+		% auto advance pages...
+		\ifthenelse{\equal{#1}{}}{%
+			\usecell*{#2}%
+				(0pt, \numexpr \value{spreadtopages#2page} - 1 \relax\cellwidth)%
+				{\cellwidth}{\cellheight}%
+			\stepcounter{spreadtopages#2page}%
+		% manual page selected...
+		}{%
+			\usecell*{#2}%
+				(0pt, \numexpr #1 - 1 \relax\cellwidth)%
+				{\cellwidth}{\cellheight}}%
+	\end{pagecell}}
+\newcommand\photobook at usespreadpage[2][]{%
+	\begin{page}%
+		\usespreadpage*[#1]{#2}%
+	\end{page}}
+
+\NewEnviron{spreadtopages}[1][2]{%
+	\begingroup%
+		% create the actual cell...
+		\setlength\cellparentwidth{\cellwidth}%
+		\setlength\cellparentheight{\cellheight}%
+		\setlength\cellwidth{#1\pageblockwidth}%
+		\setlength\cellheight{\pageblockheight}%
+		%
+		\savecell{photobook at spreadtopages}{\cellwidth}{\cellheight}{\BODY}%
+		%
+		% place the pages...
+		\foreach \photobook at spreadtopages@page in {1, ..., #1}{%
+			\usespreadpage[\photobook at spreadtopages@page]{photobook at spreadtopages}}%
+	\endgroup%
+	\ignorespaces}
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%%%%% Endpaper cells
+%
+%% \DescribeEnv{leftside}
+%% \DescribeEnv{rightside}
+%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%   +---------------+---------------+
+%%   |               |               |
+%%   |               |               |
+%%   |   leftside    |   rightside   |
+%%   |               |               |
+%%   |               |               |
+%%   +---------------+---------------+
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+
+% XXX for some reason naming these anything starting with endpaper will
+%		make LaTeX complain that that is already defined...
+%		...collision with bools???
+\newenvironment{leftside}{%
+	\begin{pagecell}%
+}{%
+	\end{pagecell}}
+
+\newenvironment{rightside}{%
+	\begin{cell*}%
+			{\bleed + \pageblockwidth, \bleed}%
+			{\pageblockwidth}{\pageblockheight}%
+}{%
+	\end{cell*}}
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%%%%% Cover and dust jacket cells
+%
+%% \DescribeEnv{frontcover}
+%% \DescribeEnv{backcover}
+%
+%% \DescribeEnv{spine}
+%% \DescribeEnv{vspine}
+%
+%% \DescribeEnv{frontflap}
+%% \DescribeEnv{backflap}
+%
+%% Covers and dust jackets differ only in that covers do not {usually} 
+%% have flaps.
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%   backflap        spline/vspine           frontflap
+%%     .    backcover      .   frontcover      .
+%%     v     v             v     v             v
+%%   +---+---------------+---+---------------+---+               
+%%   |   |               |   |               |   |
+%%   |   |               |   |               |   |
+%%   |   |     Back      |   |     Front     |   |
+%%   |   |               |   |               |   |
+%%   |   |               |   |               |   |
+%%   +---+---------------+---+---------------+---+               
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+\newenvironment{frontcover}{%
+	\begin{cell*}{
+				\bleed 
+					+ \jacketflapback 
+					+ \coverflap 
+					+ \jacketwrap 
+					+ \coverboardgrow 
+					+ \pageblockwidth 
+					+ 2\spinefold 
+					+ \spinewidth,
+				\bleed 
+					+ \coverflap }%
+			{ \pageblockwidth + \coverboardgrow }%
+			{ \pageblockheight + 2\coverboardgrow }%
+}{%
+	\end{cell*}}
+
+\newenvironment{backcover}{%
+	\begin{cell*}{
+				\bleed 
+					+ \jacketflapback 
+					+ \coverflap 
+					+ \jacketwrap,
+				\bleed 
+					+ \coverflap }%
+			{ \pageblockwidth + \coverboardgrow }%
+			{ \pageblockheight + 2\coverboardgrow }%
+}{%
+	\end{cell*}}
+
+
+% spines...
+%
+\newenvironment{spine}{%
+	\begin{cell*}{
+				\bleed 
+					+ \jacketflapback 
+					+ \coverflap 
+					+ \jacketwrap 
+					+ \coverboardgrow 
+					+ \pageblockwidth 
+					+ \spinefold,
+				\bleed 
+					+ \coverflap }%
+			{ \spinewidth }%
+			{ \pageblockheight + 2\coverboardgrow }%
+}{%
+	\end{cell*}}
+
+\newenvironment{vspine}[1][topdown]{%
+	\def\photobook at vspine@orientation{#1}%
+	%
+	\begin{spine}%
+	\begin{\photobook at vspine@orientation}%
+}{%
+	\end{\photobook at vspine@orientation}%
+	\end{spine}}
+
+
+% jackets flaps...
+%
+\newenvironment{frontflap}{%
+	\begin{cell*}{
+				\bleed 
+					+ \jacketflapback 
+					+ 2\jacketwrap 
+					+ 2\coverboardgrow 
+					+ 2\pageblockwidth 
+					+ 2\spinefold 
+					+ \spinewidth,
+				\bleed 
+					+ \coverflap }% 
+			{ \jacketflapfront }%
+			{ \pageblockheight + 2\coverboardgrow }%
+}{%
+	\end{cell*}}
+
+\newenvironment{backflap}{%
+	\begin{cell*}{
+				\bleed,
+				\bleed 
+					+ \coverflap }%
+			{ \jacketflapback }%
+			{ \pageblockheight + 2\coverboardgrow }%
+}{%
+	\end{cell*}}
+
+
+
+%----------------------------------------------------------------------
+%%%% Caption Templates
+% XXX need to be able to configure/pass/override:
+%		- size / \captionsize...
+%		- color...
+
+%% \DescribeMacro{\captionsize\{..\}}
+%
+%% Defines the caption font.
+%%
+%% Can be redefined to control caption font/style.
+%%
+\ResettableMacro{captionsize}{%
+	\fontsize{6.5pt}{8pt}\selectfont}
+
+
+%% \DescribeMacro{\captionformat\{..\}}
+%
+%% General caption format.
+%
+%%	>> \captionformat{<code>}
+%
+%% This can be redefined to control the image caption.
+%%
+\ResettableMacro{captionformat}[1]{%
+	\adjustbox{
+			margin=0.1em 0.2em, 
+			varwidth=\cellwidth}{%
+		\captionsize #1}}
+
+
+
+%----------------------------------------------------------------------
+%%%% Page Templates
+%
+%% This section contains a set of predefined configurable single-page
+%% templates.
+%%
+% XXX PRECLEAR this may lead to pages collapsing on each other, test...
+%
+%% Note that most page templates do not |\clearpage| before expanding, 
+%% this enables one to prepend elements (like pdf comments), if clearing 
+%% a page is required add |\clearpage| manually before the template.
+%%
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%%%%% Tweaking
+%
+%% Most page/spread templates provide an ability to externally "tweak" 
+%% some image proportions.
+%%
+%% This is an alternative means to setting template properties, e.g:
+%
+%% \begin{verbatim}
+%%		\tweakimagescale{0.8}
+%%		\ImagePage{image}
+%% \end{verbatim}
+%
+%% Is equivalent to:
+%
+%%	>> \ImagePage[scale=0.8]{image}
+%
+%% Tweaks get reset after each template.
+%%
+
+
+%% \DescribeMacro{\imagescale=<num>}
+%% \DescribeMacro{\imageoffsettop=<len>}
+%% \DescribeMacro{\imageoffsetleft=<len>}
+%
+%% Tweak next image templates scale/offsettop/offsetleft
+%%
+%% Note that |\imagescale| is not a length.
+%
+%%	>> \edef\imagescale{<scale>}
+%%	>> \setlength\imageoffsettop{<len>}
+%%	>> \setlength\imageoffsetleft{<len>}
+%%
+\edef\imagescale{1}
+% NOTE: these are initialized later by \resetimagetweaks...
+\newlength\imageoffsettop
+\newlength\imageoffsetleft
+
+%% \DescribeMacro{\tweakimagescale\{..\}}
+%% \DescribeMacro{\tweakimageoffsettop\{..\}}
+%% \DescribeMacro{\tweakimageoffsetleft\{..\}}
+%
+%% Convenience commands
+%%
+%% These provide a uniform interface for tweaking.
+%
+%%	>> \tweakimagescale{<scale>}
+%%	>> \tweakimageoffsettop{<len>}
+%%	>> \tweakimageoffsetleft{<len>}
+%%
+\newcommand\tweakimagescale[1]{%
+	\edef\imagescale{#1}}
+
+\newcommand\tweakimageoffsettop[1]{%
+	\setlength\imageoffsettop{#1}}
+
+\newcommand\tweakimageoffsetleft[1]{%
+	\setlength\imageoffsetleft{#1}}
+
+
+%% \DescribeMacro{\resetimagetweaks\{..\}}
+%
+%% Reset tweaked values.
+%%
+\newcommand\resetimagetweaks{%
+	\edef\imagescale{1}%
+	\setlength\imageoffsettop{0pt}%
+	\setlength\imageoffsetleft{0pt}}
+
+% setup initial state...
+\resetimagetweaks
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+% meta-commands...
+
+%M \DescribeMacro{\ImagePageTemplate\{..\}}
+%
+%M	>> \ImagePageTemplate{<name>}{<code>}
+%
+%M This will define two commands:
+%
+%M	>> \<name>[<options>]{<caption>}{<code>}
+%M	>> \<name>*[<options>]{<caption>}{<code>}
+%
+%M |\<name>{..}| will use |\<name>Caption{..}| template command to typeset 
+%M the image caption while |\<name>*{..}| will show the caption as-is.
+%M
+\def\ImagePageTemplate#1#2{%
+	% handle <macro>* version...
+	\expandafter\def\csname #1\endcsname{\@ifstar{%
+		\csname photobook at ImagePageTemplate@#1 at star\endcsname%
+	}{%
+		\csname photobook at ImagePageTemplate@#1\endcsname}}%
+	% main implementation (raw caption)...
+	\expandafter\newcommand\csname photobook at ImagePageTemplate@#1 at star\endcsname[3][]{%
+		#2%
+		\resetimagetweaks}%
+	% main implementation with caption template...
+	\expandafter\newcommand\csname photobook at ImagePageTemplate@#1\endcsname[3][]{%
+		\csname photobook at ImagePageTemplate@#1 at star\endcsname[##1]{%
+			\@ifundefined{#1Caption}{%
+				##2%
+			}{%
+				\csname #1Caption\endcsname{##2}}}{##3}}}
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+\newsavebox\photobook at imagebox
+
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%%%%% General interface
+%
+%% A templates provide a uniform interface consisting of several commands:
+%%
+%% Base template command:
+%
+%%	>> \<template-name>{<caption>}{<image>}
+%%	>> \<template-name>[<options>]{<caption>}{<image>}
+%
+%% |<options>| is the same as for |\imagecell{..}|.
+%%
+%% Template-specific caption command:
+%
+%%	>> \<template-name>Caption{<caption>}
+%
+%% This can be redefined to control typesetting the caption for all 
+%% consecutive templates.
+%%
+%% Reset template caption to default:
+%
+%%	>> \reset<template-name>Caption
+%
+%% An equivalent to the non-star version but use the caption as-is:
+%
+%%	>> \<template-name>*{<caption>}{<image>}
+%%	>> \<template-name>*[<options>]{<caption>}{<image>}
+%
+%% Note that thogh some template versions differ only in |<options>| 
+%% defaults passed to |\imagecell{..}|, they are split to provide ability 
+%% to configure the template defaults separately.
+%%
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%%%%% No bleed
+
+%% \DescribeMacro{\ImagePage\{..\}}
+%% \DescribeMacro{\ImagePageCaption\{..\}}
+%% \DescribeMacro{\resetImagePageCaption}
+%% \DescribeMacro{\ImagePage*\{..\}}
+%
+%%	Basic image page
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%   +-----------------+
+%%   |                 |
+%%   | +-------------+ |
+%%   | | .         . | |
+%%   | |   .     .   | |
+%%   | |    image    | |
+%%   | |   .     .   | |
+%%   | | .         . | |
+%%   | +-------------+ |
+%%   |               c |
+%%   |                 |
+%%   +-----------------+
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%% Create an image page:
+%%
+%% Note that |\ImagePage{..}| only supports tweaking |scale|, this is 
+%% intentional ad tweaking offset will mess up page alignment relative 
+%% to other pages in a book.
+%%
+\ResettableMacro{ImagePageCaption}[1]{%
+	\captioncell[under, align=flushright]{%
+		\captionformat{#1}}}
+\ImagePageTemplate{ImagePage}{%
+	% XXX PRECLEAR do we need clear page here???
+	%\clearpage%
+	\begin{page}%
+	\begin{pagecell*}%
+	\begin{minipage}[t][\cellheight][c]{\cellwidth}%
+		\vspace{\imageblockoffsettop\pagetextheight}%
+		\begin{center}%
+			\begin{inlinecell*}%
+					{\imageblockwidth\pagetextwidth}%
+					{\imageblockheight\pagetextheight}%
+				\imagecell[fit,
+					scale=\imagescale,
+					%captionclearparent=\captionclearpage,
+					#1]{#2}{#3}%
+			\end{inlinecell*}%
+		\end{center}%
+	\end{minipage}%
+	\end{pagecell*}%
+	\end{page}}
+
+
+%% \DescribeMacro{\ImagePageClear\{..\}}
+%% \DescribeMacro{\ImagePageClearCaption\{..\}}
+%% \DescribeMacro{\resetImagePageClearCaption}
+%% \DescribeMacro{\ImagePageClear*\{..\}}
+%
+%%	>> \ImagePageClear[<options>]{<caption>}{<image>}
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%    \clearimage      \clearimage
+%%    v                v
+%%   +-----------------+      +-----------------+  < \clearimage
+%%   |                 |      |  +-----------+  |   
+%%   |+---------------+|      |  | .       . |  |
+%%   || .           . ||      |  |  .     .  |  |
+%%   ||    .     .    ||      |  |   .   .   |  |
+%%   ||     image     ||      |  |   image   |  |
+%%   ||    .     .    ||      |  |   .   .   |  |
+%%   || .           . ||      |  |  .     .  |  |
+%%   |+---------------+|      |  | .       . |  |
+%%   |               c |      |  +-----------+  |
+%%   +-----------------+      +-----------------+  < \clearimage
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%% Default image clearance is set by |\clearimage| global length.
+%%
+%% This respects |\bindingoffset|.
+%%
+% XXX make captions adaptive??? 
+\ResettableMacro{ImagePageClearCaption}[1]{%
+	\captioncell[under, align=flushright]{%
+		\captionformat{#1}}}
+\ImagePageTemplate{ImagePageClear}{%
+	% XXX PRECLEAR do we need clear page here???
+	%\clearpage%
+	\begin{page}%
+	% NOTE: this accounts for \bindingoffset...
+	\begin{pagecell*}%
+		\imagecell[%
+			center, 
+			clearance=\clearimage, 
+			scale=\imagescale,
+			offsettop=\imageoffsettop,
+			offsetleft=\imageoffsetleft,
+			captionclearparent=\captionclearpage,
+			#1]{#2}{#3}%
+	\end{pagecell*}%
+	\end{page}}
+
+
+%% \DescribeMacro{\ImagePageClear<D>\{..\}}
+%% \DescribeMacro{\ImagePageClear<D>Caption\{..\}}
+%% \DescribeMacro{\resetImagePageClear<D>Caption}
+%% \DescribeMacro{\ImagePageClear<D>*\{..\}}
+%
+%% |<D>| can be one of T, B, L or R, for top, bottom, left and right 
+%% respectively.
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%   +-----------------+    +-----------------+ 
+%%   | +-------------+ |    |                 |   
+%%   | | .         . | |    | c               | 
+%%   | |   .     .   | |    | +-------------+ | 
+%%   | |    image    | |    | | .         . | | 
+%%   | |   . (T) .   | |    | |   .     .   | | 
+%%   | | .         . | |    | |    image    | | 
+%%   | +-------------+ |    | |   . (B) .   | | 
+%%   |               c |    | | .         . | | 
+%%   |                 |    | +-------------+ | 
+%%   +-----------------+    +-----------------+ 
+%%
+%%   +-----------------+    +-----------------+ 
+%%   | +---------+     |    |     +---------+ | 
+%%   | |.       .|     |    |     |.       .| | 
+%%   | | .     . |     |    |     | .     . | | 
+%%   | |  .   .  |     |    |     |  .   .  | | 
+%%   | |  image  |     |    |     |  image  | | 
+%%   | |  .(L).  |     |    |     |  .(R).  | | 
+%%   | | .     . |     |    |     | .     . | | 
+%%   | |.       .|     |    |     |.       .| | 
+%%   | +---------+ c   |    |   c +---------+ | 
+%%   +-----------------+    +-----------------+ 
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+% XXX TEST...
+\ResettableMacro{ImagePageClearTCaption}[1]{%
+	\captioncell[under]{%
+		\captionformat{#1}}}
+% XXX the image seems to be a line too low...
+\ImagePageTemplate{ImagePageClearT}{%
+	\ImagePageClear*[%
+		top,
+		#1]{#2}{#3}}
+
+\ResettableMacro{ImagePageClearBCaption}[1]{%
+	\captioncell[over]{%
+		\captionformat{#1}}}
+\ImagePageTemplate{ImagePageClearB}{%
+	\ImagePageClear*[%
+		bottom,
+		#1]{#2}{#3}}
+
+\ResettableMacro{ImagePageClearLCaption}[1]{%
+	\captionblockcell[right, clearance=\captionclearpage]{%
+		\captionformat{#1}}}
+\ImagePageTemplate{ImagePageClearL}{%
+	\ImagePageClear*[%
+		left,
+		#1]{#2}{#3}}
+
+\ResettableMacro{ImagePageClearRCaption}[1]{%
+	\captionblockcell[left, clearance=\captionclearpage]{%
+		\captionformat{#1}}}
+\ImagePageTemplate{ImagePageClearR}{%
+	\ImagePageClear*[%
+		right,
+		#1]{#2}{#3}}
+
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%%%%% Partial bleed
+
+%% \DescribeMacro{\ImagePageFit\{..\}}
+%% \DescribeMacro{\ImagePageFitCaption\{..\}}
+%% \DescribeMacro{\resetImagePageFitCaption}
+%% \DescribeMacro{\ImagePageFit*\{..\}}
+%
+%% Fit image into page...
+%
+%%	>> \ImagePageFit[<options>]{<caption>}{<image>}
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%                               . . . . . . .
+%%   +-----------------+      +-----------------+
+%%   |                 |      |  |.         .|  |
+%% . +-----------------+ .    |  | .       . |  |
+%% . | .             . | .    |  |  .     .  |  |
+%% . |    .       .    | .    |  |   .   .   |  |
+%% . |      image      | .    |  |   image   |  |
+%% . |    .       .    | .    |  |   .   .   |  |
+%% . | .             . | .    |  |  .     .  |  |
+%% . +-----------------+ .    |  | .       . |  |
+%%   |               c |      |  |.        c.|  |
+%%   +-----------------+      +-----------------+
+%%                               . . . . . . .
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%% Default image clearance is set by |\bleed| global length.
+%%
+%% If centered image fits vertically this will account for |\bindingoffset|.
+%%
+% XXX make captions adaptive??? 
+\ResettableMacro{ImagePageFitCaption}[1]{%
+	\captioncell[under, align=flushright]{%
+		\captionformat{#1}}}
+
+\newif\ifphotobook at ImagePageFit@centered
+\photobook at ImagePageFit@centeredfalse
+
+\newlength\photobook at ImagePageFit@imgratio
+\newlength\photobook at ImagePageFit@cellratio
+\def\photobook at ImagePageFit@opt{}
+\def\photobook at ImagePageFit@args{}
+
+\ImagePageTemplate{ImagePageFit}{%
+	\begingroup%
+		% see if default alignment is overridden...
+		\setsepchar{,}%
+		\ignoreemptyitems%
+		\readlist*\photobook at ImagePageFit@args{moo, #1}%
+		\foreachitem\photobook at ImagePageFit@opt\in\photobook at ImagePageFit@args{%
+			\ifthenelse{\equal{\photobook at ImagePageFit@opt}{fill}}{%
+				\photobook at ImagePageFit@centeredtrue}{}%
+			\ifthenelse{\equal{\photobook at ImagePageFit@opt}{inner}}{%
+				\photobook at ImagePageFit@centeredtrue}{}%
+			\ifthenelse{\equal{\photobook at ImagePageFit@opt}{outer}}{%
+				\photobook at ImagePageFit@centeredtrue}{}%
+			\ifthenelse{\equal{\photobook at ImagePageFit@opt}{top}}{%
+				\photobook at ImagePageFit@centeredtrue}{}%
+			\ifthenelse{\equal{\photobook at ImagePageFit@opt}{left}}{%
+				\photobook at ImagePageFit@centeredtrue}{}%
+			\ifthenelse{\equal{\photobook at ImagePageFit@opt}{bottom}}{%
+				\photobook at ImagePageFit@centeredtrue}{}%
+			\ifthenelse{\equal{\photobook at ImagePageFit@opt}{right}}{%
+				\photobook at ImagePageFit@centeredtrue}{}}%
+		% align center -> check if image fits vertically...
+		\ifphotobook at ImagePageFit@centered\else%
+			\sbox{\photobook at imagebox}{\includegraphics{#3}}%
+			\setlength\photobook at ImagePageFit@imgratio{%
+				1pt * \ratio{\wd\photobook at imagebox}{\ht\photobook at imagebox}}%
+			% NOTE: subtracting \bindingoffset from \cellwidth here makes sure that
+			%		we avoid offsetting images close enough in ratio to the page and
+			%		messing up bleeds...
+			\setlength\photobook at ImagePageFit@cellratio{%
+				1pt * \ratio{\cellwidth - \bindingoffset}{\cellheight}}%
+			\ifdim \photobook at ImagePageFit@imgratio > \photobook at ImagePageFit@cellratio%
+				\photobook at ImagePageFit@centeredtrue\fi\fi%
+		%
+		% ignore \bindingoffset -> center the image...
+		\ifphotobook at ImagePageFit@centered%
+			% XXX PRECLEAR do we need clear page here???
+			%\clearpage%
+			\begin{page}%
+			% NOTE: this does not account for \bindingoffset...
+			\begin{pagecell}%
+				\imagecell[%
+					center, 
+					clearance=-\bleed, 
+					scale=\imagescale,
+					offsettop=\imageoffsettop,
+					offsetleft=\imageoffsetleft,
+					captionclearparent=\captionclearpage,
+					#1]{#2}{#3}%
+			\end{pagecell}%
+			\end{page}%
+		% special case: centered vertical image -> account for \bindingoffset...
+		\else%
+			\ImagePageClear*[%
+				clearance=-\bleed, 
+				#1]{#2}{#3}\fi%
+	\endgroup}
+
+
+%% \DescribeMacro{\ImagePageFit<D>\{..\}}
+%% \DescribeMacro{\ImagePageFit<D>Caption\{..\}}
+%% \DescribeMacro{\resetImagePageFit<D>Caption}
+%% \DescribeMacro{\ImagePageFit<D>*\{..\}}
+%
+%% |<D>| can be one of T, B, L or R, for top, bottom, left and right 
+%% respectively.
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%   . . . . . . . . . . . .  
+%%   . +-----------------+ .    +-----------------+
+%%   . |  .           .  | .    |                 |
+%%   . |     .     .     | .    |                 |
+%%   . |      image      | .    |                 |
+%%   . |     . (T) .     | .  . |-----------------| .
+%%   . |  .           .  | .  . |  .           .  | .
+%%   . |-----------------| .  . |     .     .     | .
+%%     |                 |    . |      image      | .
+%%     |                 |    . |     . (B) .     | .
+%%     |                 |    . |  .           .  | .
+%%     +-----------------+    . +-----------------+ .
+%%                            . . . . . . . . . . . .
+%%   
+%%   . . . . . . . .                  . . . . . . . .
+%%   . +-----------------+      +-----------------+ .
+%%   . |.         .|     |      |     |.         .| .
+%%   . | .       . |     |      |     | .       . | .
+%%   . |  .     .  |     |      |     |  .     .  | .
+%%   . |   .   .   |     |      |     |   .   .   | .
+%%   . |   image   |     |      |     |   image   | .
+%%   . |   .(L).   |     |      |     |   .(R).   | .
+%%   . |  .     .  |     |      |     |  .     .  | .
+%%   . | .       . |     |      |     | .       . | .
+%%   . |.         .| c   |      |   c |.         .| .
+%%   . +-----------------+      +-----------------+ .
+%%   . . . . . . . .                  . . . . . . . .
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+\ResettableMacro{ImagePageFitTCaption}[1]{%
+	\captioncell[under]{%
+		\captionformat{#1}}}
+\ImagePageTemplate{ImagePageFitT}{%
+	\ImagePageFit*[%
+		top, 
+		#1]{#2}{#3}}
+
+\ResettableMacro{ImagePageFitBCaption}[1]{%
+	\captioncell[over]{%
+		\captionformat{#1}}}
+% XXX the image seems a bit too low...
+\ImagePageTemplate{ImagePageFitB}{%
+	\ImagePageFit*[%
+		bottom, 
+		#1]{#2}{#3}}
+
+\ResettableMacro{ImagePageFitLCaption}[1]{%
+	\captionblockcell[right, clearance=\captionclearpage]{%
+		\captionformat{#1}}}
+\ImagePageTemplate{ImagePageFitL}{%
+	\ImagePageFit*[%
+		left, 
+		#1]{#2}{#3}}
+
+\ResettableMacro{ImagePageFitRCaption}[1]{%
+	\captionblockcell[left, clearance=\captionclearpage]{%
+		\captionformat{#1}}}
+\ImagePageTemplate{ImagePageFitR}{%
+	\ImagePageFit*[%
+		right, 
+		#1]{#2}{#3}}
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%%%%% Full bleed
+
+%% \DescribeMacro{\ImagePageFill\{..\}}
+%% \DescribeMacro{\ImagePageFillCaption\{..\}}
+%% \DescribeMacro{\resetImagePageFillCaption}
+%% \DescribeMacro{\ImagePageFill*\{..\}}
+%
+%%	Like |\ImagePage| but will fill page with image.
+%
+%%	>> \ImagePageFill[<options>]{<caption>}{<image>}
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%   . . . . . . . . . . . . . . . . . . .
+%%   . .      +-----------------+      . .
+%%   .    .   |              c  |   .    .
+%%   .       .|                 |.       .
+%%   .        | .             . |        .
+%%   .        |    .       .    |        .
+%%   .        |      image      |        .
+%%   .        |    .       .    |        .
+%%   .        | .             . |        .
+%%   .       .|                 |.       .
+%%   .    .   |                 |   .    .
+%%   . .      +-----------------+      . .
+%%   . . . . . . . . . . . . . . . . . . .
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+%% Default image clearance is set by |\bleed| global length.
+%%
+\ResettableMacro{ImagePageFillCaption}[1]{%
+	\captioncell[top, align=flushright]{%
+		\captionformat{#1}}}
+\ImagePageTemplate{ImagePageFill}{%
+	\ImagePageFit*[%
+		fill, 
+		#1]{#2}{#3}}
+
+
+%% \DescribeMacro{\ImageHalfPageL\{..\}}
+%% \DescribeMacro{\ImageHalfPageLCaption\{..\}}
+%% \DescribeMacro{\resetImageHalfPageLCaption}
+%% \DescribeMacro{\ImageHalfPageL*\{..\}}
+%
+%% Left half of image filling page with full bleed.
+%
+%%	>> \imageleftspreadfullbleed[<vertical-offset>]{<caption>}{<image>}
+%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%  . . . . . . . . . . . . . 
+%%  . +-----------------=     
+%%  . |   .             =     
+%%  . |       .         =     
+%%  . |           .     =     
+%%  . |               . =     
+%%  . |               image
+%%  . |               . =     
+%%  . |           .     =     
+%%  . |       .         =     
+%%  . |   .           c =     
+%%  . +-----------------=     
+%%  . . . . . . . . . . . . . 
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+% XXX TEST...
+% XXX do a better default...
+\ResettableMacro{ImageHalfPageLCaption}[1]{%
+	\captioncell[bottom, align=flushright]{%
+		\captionformat{#1}}}
+\ImagePageTemplate{ImageHalfPageL}{%
+	\begin{spreadtopages*}[2]{photobook at ImageHalfPageL@cell}%
+		\imagecell[%
+			fill, 
+			clearance=-\bleed,
+			scale=\imagescale,
+			offsettop=\imageoffsettop,
+			offsetleft=\imageoffsetleft,
+			captionclearparent=\captionclearpage,
+			#1]{#2}{#3}%
+	\end{spreadtopages*}%
+	%
+	% XXX PRECLEAR do we need clear page here???
+	%\clearpage%
+	\usespreadpage[1]{photobook at ImageHalfPageL@cell}}
+
+
+
+%% \DescribeMacro{\ImageHalfPageR\{..\}}
+%% \DescribeMacro{\ImageHalfPageRCaption\{..\}}
+%% \DescribeMacro{\resetImageHalfPageRCaption}
+%% \DescribeMacro{\ImageHalfPageR*\{..\}}
+%
+%% Right half of image filling page with full bleed.
+%
+%%	>> \imagerightspreadfullbleed[<vertical-offset>]{<caption>}{<image>}
+%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%  . . . . . . . . . . . . .
+%%      =-----------------+ .
+%%      =             .   | .
+%%      =         .       | .
+%%      =     .           | .
+%%      = .               | .
+%%    image               | .
+%%      = .               | .
+%%      =     .           | .
+%%      =         .       | .
+%%      =             . c | .
+%%      =-----------------+ .
+%%  . . . . . . . . . . . . .
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+% XXX TEST...
+% XXX do a better default...
+\ResettableMacro{ImageHalfPageRCaption}[1]{%
+	\captioncell[bottom, align=flushright]{%
+		\captionformat{#1}}}
+\ImagePageTemplate{ImageHalfPageR}{%
+	\begin{spreadtopages*}[2]{photobook at ImageHalfPageR@cell}%
+		\imagecell[%
+			fill, 
+			clearance=-\bleed, 
+			scale=\imagescale,
+			offsettop=\imageoffsettop,
+			offsetleft=\imageoffsetleft,
+			captionclearparent=\captionclearpage,
+			#1]{#2}{#3}%
+	\end{spreadtopages*}%
+	%
+	% XXX PRECLEAR do we need clear page here???
+	%\clearpage%
+	\usespreadpage[2]{photobook at ImageHalfPageR@cell}}
+
+
+
+%----------------------------------------------------------------------
+%%%% Spread Templates
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%%%%% No bleed
+
+% XXX TEST!!
+% XXX doc...
+% XXX Should we make this just like with pages, i.e. \imagePage{..} and 
+%		\ImagePageFit{..}, the first places relative to text and raises 
+%		slightly while the second simply centers...
+%% \DescribeMacro{\ImageSpread\{..\}}
+%% \DescribeMacro{\ImageSpreadCaption\{..\}}
+%% \DescribeMacro{\resetImageSpreadCaption}
+%% \DescribeMacro{\ImageSpread*\{..\}}
+%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%    +---------------=---------------+ 
+%%    | +-------------=-------------+ | 
+%%    | |  .          =          .  | | 
+%%    | |      .      =      .      | | 
+%%    | |          .  =  .          | | 
+%%    | |           image           | | 
+%%    | |          .  =  .          | | 
+%%    | |      .      =      .      | | 
+%%    | |  .          =          .  | | 
+%%    | +-------------=-------------+ | 
+%%    +---------------=---------------+ 
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+% XXX do a better default...
+%		...adaptive???
+\ResettableMacro{ImageSpreadCaption}[1]{%
+	\captioncell[under]{%
+		\captionformat{#1}}}
+\ImagePageTemplate{ImageSpread}{%
+	\cleartoleftpage%
+	\begin{spreadtopages}[2]%
+		\imagecell[%
+			fit, 
+			clearance=\clearimage, 
+			scale=\imagescale,
+			offsettop=\imageoffsettop,
+			offsetleft=\imageoffsetleft,
+			captionclearparent=\captionclearpage,
+			#1]{#2}{#3}%
+	\end{spreadtopages}}
+
+
+%% \DescribeMacro{\ImageSpread<D>\{..\}}
+%% \DescribeMacro{\ImageSpread<D>Caption\{..\}}
+%% \DescribeMacro{\resetImageSpread<D>Caption}
+%% \DescribeMacro{\ImageSpread<D>*\{..\}}
+%
+%% |<D>| can be one of T, B, L or R, for top, bottom, left and right 
+%% respectively.
+%%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%    +---------------=---------------+  +---------------=---------------+   
+%%    | +-------------=-------------+ |  |               =               |   
+%%    | |  .          =          .  | |  |  c            =               |   
+%%    | |       .     =     .       | |  | +-------------=-------------+ |   
+%%    | |           image           | |  | |  .          =          .  | |   
+%%    | |       .    (T)    .       | |  | |       .     =     .       | |   
+%%    | |  .          =          .  | |  | |           image           | |   
+%%    | +-------------=-------------+ |  | |       .    (B)    .       | |   
+%%    |               =            c  |  | |  .          =          .  | |   
+%%    |               =               |  | +-------------=-------------+ |   
+%%    +---------------=---------------+  +---------------=---------------+   
+%%
+%%    +---------------=---------------+  +---------------=---------------+ 
+%%    | +-------------=---------+     |  |     +---------=-------------+ | 
+%%    | |  .          =      .  |     |  |     |  .      =          .  | | 
+%%    | |     .       =   .     |     |  |     |     .   =       .     | | 
+%%    | |        .    =.        |     |  |     |        .=    .        | | 
+%%    | |         image         |     |  |     |         image         | | 
+%%    | |        . (L)=.        |     |  |     |        .=(R) .        | | 
+%%    | |     .       =   .     |     |  |     |     .   =       .     | | 
+%%    | |  .          =      .  |     |  |     |  .      =          .  | | 
+%%    | +-------------=---------+ c   |  |   c +---------=-------------+ | 
+%%    +---------------=---------------+  +---------------=---------------+ 
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+\ResettableMacro{ImageSpreadTCaption}[1]{%
+	\captioncell[under]{%
+		\captionformat{#1}}}
+\ImagePageTemplate{ImageSpreadT}{%
+	\ImageSpread*[%
+		top, 
+		#1]{#2}{#3}}
+
+\ResettableMacro{ImageSpreadBCaption}[1]{%
+	\captioncell[over]{%
+		\captionformat{#1}}}
+\ImagePageTemplate{ImageSpreadB}{%
+	\ImageSpread*[%
+		bottom, 
+		#1]{#2}{#3}}
+
+\ResettableMacro{ImageSpreadLCaption}[1]{%
+	\captionblockcell[right, clearance=\captionclearpage]{%
+		\captionformat{#1}}}
+\ImagePageTemplate{ImageSpreadL}{%
+	\ImageSpread*[%
+		left, 
+		#1]{#2}{#3}}
+
+\ResettableMacro{ImageSpreadRCaption}[1]{%
+	\captionblockcell[left, clearance=\captionclearpage]{%
+		\captionformat{#1}}}
+\ImagePageTemplate{ImageSpreadR}{%
+	\ImageSpread*[%
+		right, 
+		#1]{#2}{#3}}
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%%%%% Partial bleed
+
+
+%% \DescribeMacro{\ImageSpreadFit\{..\}}
+%% \DescribeMacro{\ImageSpreadFitCaption\{..\}}
+%% \DescribeMacro{\resetImageSpreadFitCaption}
+%% \DescribeMacro{\ImageSpreadFit*\{..\}}
+%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%                                                  . . . . . . . . . . .
+%%     +---------------=---------------+      +---------------=---------------+  
+%%     |               =               |      |     |.        =        .|.    |  
+%%   . |---------------=---------------| .    |     |  .      =      .  |     |  
+%%   . |    .          =          .    | .    |     |    .    =    .    |     |  
+%%   . |         .     =     .         | .    |     |      .  =  .      |     |  
+%%   . |             image             | .    |     |       image       |     |  
+%%   . |         .     =     .         | .    |     |      .  =  .      |     |  
+%%   . |    .          =          .    | .    |     |    .    =    .    |     |  
+%%   . |---------------=---------------| .    |     |  .      =      .  |     |  
+%%     |               =             c |      |     |.        =        .| c   |  
+%%     +---------------=---------------+      +---------------=---------------+  
+%%                                                  . . . . . . . . . . .
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+% XXX TEST...
+% XXX make caption adaptive...
+\ResettableMacro{ImageSpreadFitCaption}[1]{%
+	\captioncell[under]{%
+		\captionformat{#1}}}
+\ImagePageTemplate{ImageSpreadFit}{%
+	\cleartoleftpage%
+	\begin{spreadtopages}[2]%
+		\imagecell[%
+			fit, 
+			clearance=-\bleed, 
+			scale=\imagescale,
+			offsettop=\imageoffsettop,
+			offsetleft=\imageoffsetleft,
+			captionclearparent=\captionclearpage,
+			#1]{#2}{#3}%
+	\end{spreadtopages}}
+
+
+%% \DescribeMacro{\ImageSpread<D>\{..\}}
+%% \DescribeMacro{\ImageSpread<D>Caption\{..\}}
+%% \DescribeMacro{\resetImageSpread<D>Caption}
+%% \DescribeMacro{\ImageSpread<D>*\{..\}}
+%
+%% Image spread aligned left (with bleed).
+%
+%% 	>> \ImageSpread<D>[<options>]{<caption>}{<image>}
+%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%                                           
+%%  . . . . . . . . . . . . . . . . . . .           
+%%  . +---------------=---------------+ .    +---------------=---------------+  
+%%  . |   .           =           .   | .    | c             =               |  
+%%  . |       .       =       .       | .  . |---------------=---------------| .
+%%  . |           .   =   .           | .  . |   .           =           .   | .
+%%  . |             image             | .  . |       .       =       .       | .
+%%  . |           .  (T)   .          | .  . |           .   =   .           | .
+%%  . |       .       =       .       | .  . |             image             | .
+%%  . |   .           =           .   | .  . |           .  (B)  .           | .
+%%  . |---------------=---------------| .  . |       .       =       .       | .
+%%    |               =             c |    . |   .           =           .   | .
+%%    +---------------=---------------+    . +---------------=---------------+ .
+%%                                         . . . . . . . . . . . . . . . . . . .
+%%
+%%  . . . . . . . . . . . . . . . .              . . . . . . . . . . . . . . . .
+%%  . +---------------=---------------+      +---------------=---------------+ .
+%%  . | .             =         . |   |      |   | .         =             . | .
+%%  . |    .          =      .    |   |      |   |    .      =          .    | .
+%%  . |       .       =   .       |   |      |   |       .   =       .       | .
+%%  . |          .    =.          |   |      |   |          .=   .           | .
+%%  . |           image           |   |      |   |          image            | .
+%%  . |          . (L)=.          |   |      |   |          .(R) .           | .
+%%  . |       .       =   .       |   |      |   |       .   =       .       | .
+%%  . |    .          =      .    |   |      |   |    .      =          .    | .
+%%  . | .             =         . | c |      | c | .         =             . | .
+%%  . +---------------=---------------+      +---------------=---------------+ .
+%%  . . . . . . . . . . . . . . . .              . . . . . . . . . . . . . . . .
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+% XXX TEST...
+% XXX do a better default...
+% XXX need a caption box...
+\ResettableMacro{ImageSpreadFitTCaption}[1]{%
+	\captioncell[under]{%
+		\captionformat{#1}}}
+\ImagePageTemplate{ImageSpreadFitT}{%
+	\ImageSpreadFit*[top, #1]{#2}{#3}}
+
+\ResettableMacro{ImageSpreadFitBCaption}[1]{%
+	\captioncell[over]{%
+		\captionformat{#1}}}
+\ImagePageTemplate{ImageSpreadFitB}{%
+	\ImageSpreadFit*[bottom, #1]{#2}{#3}}
+
+\ResettableMacro{ImageSpreadFitLCaption}[1]{%
+	\captionblockcell[right, clearance=\captionclearpage]{%
+		\captionformat{#1}}}
+\ImagePageTemplate{ImageSpreadFitL}{%
+	\ImageSpreadFit*[left, #1]{#2}{#3}}
+
+\ResettableMacro{ImageSpreadFitRCaption}[1]{%
+	\captionblockcell[left, clearance=\captionclearpage]{%
+		\captionformat{#1}}}
+\ImagePageTemplate{ImageSpreadFitR}{%
+	\ImageSpreadFit*[right, #1]{#2}{#3}}
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%%%%% Full bleed
+
+%% \DescribeMacro{\ImageSpreadFill\{..\}}
+%% \DescribeMacro{\ImageSpreadFillCaption\{..\}}
+%% \DescribeMacro{\resetImageSpreadFillCaption}
+%% \DescribeMacro{\ImageSpreadFill*\{..\}}
+%
+%% Image spread with full bleed.
+%
+%%	>> \ImageSpreadFill[<options>]{<caption>}{<image>}
+%
+%% \begin{minipage}{\textwidth}
+%% \begin{verbatim}
+%%
+%%  . . . . . . . . . . . . . . . . . . .
+%%  . +---------------=---------------+ .
+%%  . |   .           =           .   | .
+%%  . |      .        =        .      | .
+%%  . |         .     =     .         | .
+%%  . |            .  =  .            | .
+%%  . |             image             | .
+%%  . |            .  =  .            | .
+%%  . |         .     =     .         | .
+%%  . |      .        =        .      | .
+%%  . |   .           =           . c | .
+%%  . +---------------=---------------+ .
+%%  . . . . . . . . . . . . . . . . . . .
+%%
+%% \end{verbatim}
+%% \end{minipage}
+%%
+
+% XXX do a better default...
+\ResettableMacro{ImageSpreadFillCaption}[1]{%
+	\captioncell[bottom, align=flushright]{%
+		\captionformat{#1}}}
+\ImagePageTemplate{ImageSpreadFill}{%
+	\cleartoleftpage%
+	\begin{spreadtopages}[2]%
+		\imagecell[%
+			fill, 
+			clearance=-\bleed, 
+			scale=\imagescale,
+			offsettop=\imageoffsettop,
+			offsetleft=\imageoffsetleft,
+			captionclearparent=\captionclearpage,
+			#1]{#2}{#3}%
+	\end{spreadtopages}}
+
+
+
+%----------------------------------------------------------------------
+%%%% Meta Macros / Environments
+%
+%% These macros and environments are used internally to help define cells
+%% and templates and thus can be useful when extending the functionality 
+%% of this class both when authoring styles and when creating user 
+%% macros/templates.\footnote{%
+%% 		Note that in code the relevant meta-macros are defined in the logical 
+%% 		locations for each macro, i.e. before first use and at the start of 
+%% 		the relevant context. This section in the reference is placed near 
+%% 		the end so as to focus the user's attention on the main class interface,
+%% 		class internal architecture and extension API being secondary.}
+%%
+%% \input{\jobname-meta}
+%%
+%%
+
+
+
+%----------------------------------------------------------------------
+%%%% Miscellaneous
+
+%% \DescribeMacro{\PageInfo}
+%
+%% Display basic paper / page / cell geometry.
+%%
+\newcommand\PageInfo[1][mm]{%
+	Layout: \layoutmode
+	\par
+	paper: \lenprint[#1]{\paperwidth} x \lenprint[#1]{\paperheight} (w. bleeds) \\
+	block: \lenprint[#1]{\blockwidth} x \lenprint[#1]{\blockheight} \\
+	cell: \lenprint[#1]{\cellparentwidth} x \lenprint[#1]{\cellparentheight} \\
+	bleed: \lenprint[#1]{\bleed}}
+
+
+%% \DescribeMacro{\GenerateTemplate\{..\}}
+%
+%% Generate template page for current |layoutmode|.
+%
+%%	>> \GenerateTemplate
+%
+%% Cell size can be printed in |mm| (default) or in any explicit unit 
+%% supported by \LaTeX.
+%
+%%	>> \GenerateTemplate{<unit>}
+%
+%% This can be useful if one needs to make the cover/jacket/... in either a 
+%% different software package or by hand.
+%%
+%% This is a no-op for |layoutmode=block|.
+%%
+% XXX should digits/rounding be configurable???
+\newcommand\photobook at TemplateCell[2][mm]{
+	\begin{center}
+		\vfill%
+		#2 \\
+		(\lenprint[#1]{\cellwidth} \space x \lenprint[#1]{\cellheight})
+		\vfill%
+		\vspace{0pt}%
+	\end{center}%
+	\ignorespaces}
+
+\newcommand\GenerateTemplate[1][mm]{
+	\TPoptions{showboxes=true}%
+	\begin{page}
+		\setlength{\parindent}{0em}
+		% NOTE: only the relevant blocks will be visible...
+		\ifendpaperlayout%
+			\begin{leftside}
+				\photobook at TemplateCell[#1]{ENDPAPER LEFT}
+			\end{leftside}
+			\begin{rightside}
+				\photobook at TemplateCell[#1]{ENDPAPER RIGHT}
+			\end{rightside}\fi%
+		\ifcoverlikelayout%
+			\begin{frontcover}
+				\photobook at TemplateCell[#1]{FRONT COVER}
+			\end{frontcover}
+			\begin{vspine}%
+				\photobook at TemplateCell[#1]{SPINE}%
+			\end{vspine}
+			\begin{backcover}
+				\photobook at TemplateCell[#1]{BACK COVER}
+			\end{backcover}\fi%
+		\ifjacketlayout%
+			\begin{frontflap}%
+				\photobook at TemplateCell[#1]{FRONT FLAP}
+			\end{frontflap}
+			\begin{backflap}%
+				\photobook at TemplateCell[#1]{BACK FLAP}
+			\end{backflap}\fi%
+	\end{page}}
+
+
+% XXX place marks in bleed area...
+% XXX do this for all pages... (???)
+\newcommand\ShowMarks[1][1pt]{%
+	% general...
+	% XXX corners / cut marks...
+	\ifendpaperlayout%
+		% XXX fold...
+	\fi%
+	\ifcoverlikelayout%
+		% XXX spine...
+		% XXX folds...
+	\fi%
+	\ifjacketlayout%
+		% XXX spine...
+		% XXX folds...
+	\fi}
+
+
+% XXX EXPERIMENTAL...
+\def\photobook at pdfboxstore@stored{}
+
+% XXX should these be stacked???
+% XXX handle slot name...
+\newcommand\storepdfboxes[1][stored]{%
+	\edef\photobook at pdfboxstore@stored{%
+		\photobook at pdfboxes}}
+
+% XXX handle slot name...
+\newcommand\restorepdfboxes[1][stored]{%
+	\expandafter\pdfpageattr\expandafter{\photobook at pdfboxstore@stored}}
+
+
+%% \DescribeMacro{\pdfboxesset\{..\}}
+%
+%%	>> \pdfboxesset[<bleed>]{<bleedblockwidth>}{<bleedblockheight>}
+%%
+\newcommand\pdfboxesset[3][\bleed]{%
+	% calculate pdf box dimensions in pt...
+	\edef\photobook at pdfboxesset@w{\strip at pt\dimexpr 
+		0.996264009963\dimexpr #2 \relax\relax}%
+	\edef\photobook at pdfboxesset@h{\strip at pt\dimexpr 
+		0.996264009963\dimexpr #3 \relax\relax}%
+	\edef\photobook at pdfboxesset@bleed{\strip at pt\dimexpr 
+		0.996264009963\dimexpr #1 \relax\relax}%
+	\edef\photobook at pdfboxesset@t{\strip at pt\dimexpr 
+		0.996264009963\dimexpr #3 - #1 \relax\relax}%
+	\edef\photobook at pdfboxesset@r{\strip at pt\dimexpr 
+		0.996264009963\dimexpr #2 - #1 \relax\relax}%
+	%
+	\edef\photobook at pdfboxes{%
+		/MediaBox [0 0 \photobook at pdfboxesset@w\space \photobook at pdfboxesset@h]
+		/BleedBox [0 0 \photobook at pdfboxesset@w\space \photobook at pdfboxesset@h]
+		/ArtBox [
+			\photobook at pdfboxesset@bleed\space \photobook at pdfboxesset@bleed\space 
+			\photobook at pdfboxesset@r\space \photobook at pdfboxesset@t]
+		/TrimBox [
+			\photobook at pdfboxesset@bleed\space \photobook at pdfboxesset@bleed\space 
+			\photobook at pdfboxesset@r\space \photobook at pdfboxesset@t]
+		/CropBox [
+			\photobook at pdfboxesset@bleed\space \photobook at pdfboxesset@bleed\space 
+			\photobook at pdfboxesset@r\space \photobook at pdfboxesset@t]}%
+	%
+	% set the boxes...
+	\ifxetex%
+		% XXX make this reusable -- currently this will add new boxes per 
+		%		call, need to cleanup...
+		\AtBeginShipout{\AtBeginShipoutAddToBox{%
+			\special{pdf:put @thispage << \photobook at pdfboxes >>}}}%
+	\else%
+		\expandafter\pdfpageattr\expandafter{\photobook at pdfboxes}\fi}
+
+
+%% \DescribeMacro{\pdfcommentcell\{..\}}
+%
+%% Add pdf comment as margin overlay.
+%%
+%%	>> \pdfcommentcell[<options>]{<comment>}
+%%
+% XXX BUG: this takes up space...
+\newcommand\pdfcommentcell[2][]{%
+	\begin{cell*}{
+				\ifnumodd{\thepage}{%
+					\cellwidth - \marginparwidth - 2\bleed - 1cm
+				}{%
+					\bleed + 1cm},
+				\bleed + 1cm
+			}{\marginparwidth}{1pt}%
+		\pdfcomment[color=yellow, #1]{#2}%
+	\end{cell*}}
+
+
+%% \DescribeMacro{\pdfpagecount\{..\}}
+%
+%%	Get pdf page count
+%%
+%%	>>	\pdfpagecount{<file.pdf>}
+%%
+\newcommand\pdfpagecount[1]{%
+	\ifpdftex%
+		\pdfximage{#1}%
+    	\number\pdflastximagepages%
+	\else\ifxetex%
+		\number\XeTeXpdfpagecount"#1"%
+	\else\ifluatex%
+		\number\directlua{%
+			local pages = 0
+			local doc = pdfe.open("\luaescapestring{#1}")
+			if doc then
+				pages = pdfe.getnofpages(doc)
+				pdfe.close(doc)
+			end
+			tex.write(pages) }\fi\fi}
+
+
+%% \DescribeMacro{\pdfspinewidth\{..\}}
+%
+%%	Calculate spine thickness
+%%
+%%	>>	\pdfspinewidth{<paper-thikness>}{<cover-thikness>}{<block-pdf>}
+%%
+% NOTE: really "like" how LaTeX overcomplicats simple math...
+\newcommand\pdfspinewidth[3]{%
+	\setlength\spinewidth{\dimexpr
+			(#1 mm) * \numexpr \pdfpagecount{#3} / 2 \relax
+			+ ((#2 mm) * 2)
+		\relax}}
+
+
+
+%----------------------------------------------------------------------
+% Index...
+%
+% XXX this prints trash at this point...
+%		...I do not want to build the index manually but it seems that
+%		we are slowly moving in that direction...
+%%% \printindex
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%%% XXX DEBUG...
+%%%\AtBeginDocument{
+%%%}
+
+
+% - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+%% \blankfootnote{%
+%%		Why ASCII diagrams instead of normal graphics, you might ask?
+%%		Well, for the same reason as photo-books in \LaTeX\ -- I liked 
+%%		the idea of it, the simplicity, and thought that it would be fun to 
+%%		see how far can I push things before it all	falling apart on me, and... 
+%%		We are here, at the end, and it all is still here too :)}
+
+
+
+%----------------------------------------------------------------------
+%% \end{document} %                         vim:set ts=4 sw=4 nowrap :


Property changes on: trunk/Master/texmf-dist/tex/latex/photobook/photobook.cls
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Modified: trunk/Master/tlpkg/bin/tlpkg-ctan-check
===================================================================
--- trunk/Master/tlpkg/bin/tlpkg-ctan-check	2022-09-15 19:55:43 UTC (rev 64403)
+++ trunk/Master/tlpkg/bin/tlpkg-ctan-check	2022-09-15 19:57:32 UTC (rev 64404)
@@ -626,7 +626,7 @@
     phfnote phfparen phfqit phfquotetext
     phfsvnwatermark phfthm
     philex philokalia philosophersimprint
-    phonenumbers phonetic phonrule photo physconst physics physunits
+    phonenumbers phonetic phonrule photo photobook physconst physics physunits
     piano picinpar pict2e
     pictex pictex2 pictexsum picture piechartmp piff pigpen
     pinlabel pinoutikz pitex piton pittetd pixelart

Modified: trunk/Master/tlpkg/libexec/ctan2tds
===================================================================
--- trunk/Master/tlpkg/libexec/ctan2tds	2022-09-15 19:55:43 UTC (rev 64403)
+++ trunk/Master/tlpkg/libexec/ctan2tds	2022-09-15 19:57:32 UTC (rev 64404)
@@ -2917,6 +2917,7 @@
  'patch',               '\.doc',
  'pax',			'build.xml|lib|license|src|' . $standardsource,
  'pdfx',                'rvdtx\.sty|' . $standardsource,
+ 'photobook',		'NULL',	# keep together
  'poetrytex',           'Makefile|' . $standardsource,
  'pseudo',		'NULL',	# keep together
  'pst-pdf',		'\.(dtx|ins|e?ps|png)$|CHANGES.tex',

Modified: trunk/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc
===================================================================
--- trunk/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc	2022-09-15 19:55:43 UTC (rev 64403)
+++ trunk/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc	2022-09-15 19:57:32 UTC (rev 64404)
@@ -1031,6 +1031,7 @@
 depend philex
 depend phonenumbers
 depend photo
+depend photobook
 depend picture
 depend piff
 depend pkgloader

Added: trunk/Master/tlpkg/tlpsrc/photobook.tlpsrc
===================================================================


More information about the tex-live-commits mailing list.