diff options
Diffstat (limited to 'Build/source/texk')
-rwxr-xr-x | Build/source/texk/texlive/linked_scripts/pdfxup/pdfxup | 1038 |
1 files changed, 703 insertions, 335 deletions
diff --git a/Build/source/texk/texlive/linked_scripts/pdfxup/pdfxup b/Build/source/texk/texlive/linked_scripts/pdfxup/pdfxup index 01669964583..62226cb45ab 100755 --- a/Build/source/texk/texlive/linked_scripts/pdfxup/pdfxup +++ b/Build/source/texk/texlive/linked_scripts/pdfxup/pdfxup @@ -2,10 +2,11 @@ shopt -s extglob shopt -s lastpipe -VERSION="1.30" -VDATE="2015/10/06" +VERSION="1.50" +VDATE="2019/12/31" ## see release notes at the end of this file. + : ${GS=`which gs`} if [ ! $? ]; then echo "ghostscript not found; aborting."; @@ -17,8 +18,9 @@ if [ ! $? ]; then exit 1; fi -declare -A BB NOBB; - +## default values for all options. +## Can be modified from command line +## For instance, run "VERB=4 pdfxup ..." function defaultvalues() { : ${dfpdfxupCOLS=2} @@ -26,6 +28,7 @@ function defaultvalues() : ${dfpdfxupLANDSC=1} : ${dfpdfxupPAP="a4"} : ${dfpdfxupBOOKLET=0} + : ${dfpdfxupCLIP=1} : ${dfpdfxupOUTF="pdfxup.pdf"} : ${dfpdfxupIHM="5pt"} : ${dfpdfxupIVM="5pt"} @@ -39,36 +42,41 @@ function defaultvalues() : ${dfpdfxupFW=".4pt"} : ${dfpdfxupPAGES="-"} : ${dfpdfxupBB="-"} + : ${dfpdfxupNOBB=""} + : ${dfpdfxupKBB="0"} : ${dfpdfxupGBB="0"} : ${dfpdfxupVERB=1} : ${dfpdfxupDEBUG=0} + : ${dfpdfxupWMPERIOD=1} } + function usage() { -defaultvalues; -echo "pdfxup: n-up pages of a PDF document, preserving readability -usage: `basename $0` [OPTIONS] file + defaultvalues; + echo "pdfxup: n-up pages of a PDF document, preserving readability +usage: `basename $0` [OPTIONS] file Available OPTIONS are: -x n n columns per page [default: \"$dfpdfxupCOLS\"] -y n n lines per page [default: \"$dfpdfxupROWS\"] -l [0|1] landscape-mode [default: \"$dfpdfxupLANDSC\"] -b [0|1|le|se] booklet-mode [default: \"$dfpdfxupBOOKLET\"] + -c [0|1] clip pages to bounding box [default: \"$dfpdfxupCLIP\"] -im n inner margins [default: \"$dfpdfxupIM\"] -m n margins [default: \"$dfpdfxupM\"] -is n interm. spaces [default: \"$dfpdfxupIS\"] -fw n frame width [default: \"$dfpdfxupFW\"] -o file write output to file [default: \"$dfpdfxupOUTF\"] - -p range restrict to range of pages [default: \"$dfpdfxupPAGES\"] - -nobb range page range to omit for computing bbox [default: \"$dfpdfxupNOBB\"] - -bb range page range to use for computing bbox [default: \"$dfpdfxupBB\"] + -p pages only include these pages [default: \"$dfpdfxupPAGES\" (all)] + -nobb pages pages to omit when computing b.box [default: \"$dfpdfxupNOBB\" (none)] + -bb pages pages to use for computing b.box [default: \"$dfpdfxupBB\" (all)] -g [0|1] only computes bounding box [default: \"$dfpdfxupGBB\"] -s x y X Y force bounding box [default: unset] -V [0-3] select verbosity [default: \"$dfpdfxupVERB\"] - -q run quietly (equiv. '-V=0') + -w file add watermarking [default: none] + -wp n repeat last n pages of watermark file [default: \"$dfpdfxupWMPERIOD\"] -i ask before overwriting/removing files -d debug mode: keep intermediary files - -v show version number and exit - -h show this help message"; + -v show version number and exit"; ## ## Some options are not presented, for the sake of brevity... @@ -79,47 +87,93 @@ Available OPTIONS are: ## -vm n vertical margin [default: \"$dfpdfxupVM\"] ## -ihs n interm. horizontal space [detault: \"$dfpdfxupIHS\"] ## -ivs n interm. vertical space [detault: \"$dfpdfxupIVS\"] +## -kbb keep original bounding box [default: \"$dfpdfxupKBB\"] ## -ps s output paper size [default: \"$dfpdfxupPAP\"] +## -q run quietly (equiv. '-V=0') +## -h show this help message ## ## ## -exit 0; + exit 0; } function setdefaultvalues() { - COLS=$dfpdfxupCOLS; - ROWS=$dfpdfxupROWS; - LANDSC=$dfpdfxupLANDSC; - BOOKLET=$dfpdfxupBOOKLET; - PAP=$dfpdfxupPAP; - OUTF=$dfpdfxupOUTF - IHM=$dfpdfxupIHM; - IVM=$dfpdfxupIVM; - IM=$dfpdfxupIM; - HM=$dfpdfxupHM; - VM=$dfpdfxupVM; - M=$dfpdfxupM; - IHS=$dfpdfxupIHS; - IVS=$dfpdfxupIVS; - IS=$dfpdfxupIS; - FW=$dfpdfxupFW; - VERB=$dfpdfxupVERB; - DEBUG=$dfpdfxupDEBUG; - nbNOBB=0; - nbBB=0; - GBB=$dfpdfxupGBB; - SBB=0; - x0=-1 - y0=-1 - h0=-1 - w0=-1 - ## the names for h and w should actually be X and Y: they are not width and height, - ## but coordinates of upper right corner. + COLS=$dfpdfxupCOLS; + ROWS=$dfpdfxupROWS; + LANDSC=$dfpdfxupLANDSC; + BOOKLET=$dfpdfxupBOOKLET; + CLIP=$dfpdfxupCLIP; + PAP=$dfpdfxupPAP; + OUTF=$dfpdfxupOUTF + IHM=$dfpdfxupIHM; + IVM=$dfpdfxupIVM; + IM=$dfpdfxupIM; + HM=$dfpdfxupHM; + VM=$dfpdfxupVM; + M=$dfpdfxupM; + IHS=$dfpdfxupIHS; + IVS=$dfpdfxupIVS; + IS=$dfpdfxupIS; + FW=$dfpdfxupFW; + ## don't overwrite VERB if set on command line + : ${VERB=$dfpdfxupVERB}; + DEBUG=$dfpdfxupDEBUG; + WATERMARK=""; + WATERMARKPERIOD=$dfpdfxupWMPERIOD; + KBB=$dfpdfxupKBB; + GBB=$dfpdfxupGBB; + SBB=0; + x0=-1 + y0=-1 + h0=-1 + w0=-1 + ## the names for h and w should actually be X and Y: they are not width and height, + ## but coordinates of upper right corner. + + ## Notice: PAGES, BB and NOBB will be set to default values if empty after + ## processing options +} + +## myecho handles several levels of verbosity +function myecho() +{ + ECHO=0; + case $1 in + +([0-9])\+) + if [[ $VERB -ge ${1%+} ]]; then ECHO=1; fi + ;; + +([0-9])) + if [[ $VERB -eq $1 ]]; then ECHO=1; fi + ;; + +([0-9])-) + if [[ $VERB -le ${1%-} ]]; then ECHO=1; fi + ;; + esac + if [[ $ECHO == 1 ]]; then + case $2 in + -*) + echo $2 "$3" + ;; + *) + echo "$2" + ;; + esac + fi } -function dimtopt() +## function to debug option processing +function showopts() +{ + if [[ OPTS -eq 0 ]]; then + OPTS=1; + fi + myecho 4+ " * $1" +} + +## transforms given dimension (in cm, mm, in) in pt +function dimtopt() { dim=$1; case $dim in @@ -139,7 +193,7 @@ function dimtopt() ;; *[!0-9]*) ## should not occur... has been filtered out by main 'case' - echo "Illegal unit of measure in option '$3'; ignoring"; + myecho 1+ " illegal unit of measure in option '$3'; ignoring"; dim=$2; ;; *) @@ -148,6 +202,7 @@ function dimtopt() esac } +## check valid unit for given dimension function testdim() { dim=$1; @@ -158,74 +213,90 @@ function testdim() dim=${dim}pt ;; +([0-9])*) - echo "Illegal unit of measure in option '$3'; ignoring"; + echo " illegal unit of measure in option '$3'; ignoring"; dim=$2; ;; *) - echo "Not a valid dimension in option '$3'; ignoring"; + echo " not a valid dimension in option '$3'; ignoring"; dim=$2; ;; esac } -function testrange() +## sets variable $in to 1 if $1 is in list of ranges $2 +function ifinrangelist() { - declare -a list=("${!2}"); - - in=0; - if [[ $3 -eq 0 ]]; then - return; - fi n=$1; - l=$3 - i=0; - while ( true ); do - if [[ $i -ge $l ]]; then break; fi - case ${list[$i]} in + list=$2; + in=0; + + for i in ${list//,/$IFS}; do + case $i in +([0-9])) - first=${list[$i]}; - last=${list[$i]}; - shift;; + first=$i; + last=$i;; -+([0-9])) first=1; - last=${list[$i]:1}; - shift;; + last=`echo $i|tr -d -`;; +([0-9])-) - first=${list[$i]::-1}; - last=$nbp; - shift;; + first=`echo $i|tr -d -`; + last=$nbp;; +([0-9])-+([0-9])) - first=${list[$i]%-*} - last=${list[$i]#*-} - shift;; + first=`echo $i|cut -d- -f1`; + last=`echo $i|cut -d- -f2`;; + -) + first=1; + last=$nbp;; + *) + myecho 1+ " error in range of pages (option '$3' contains '$i')"; esac if [[ $n -ge $first && $n -le $last ]]; then in=1; return; fi - eval i=$(( i+1 )) done + return; } -function myecho() +## normalize list + count number of pages to be displayed +function cleancslor() { - ECHO=0; - case $1 in - +([0-9])\+) - if [[ $VERB -ge ${1%+} ]]; then ECHO=1; fi;; - +([0-9])) - if [[ $VERB -eq $1 ]]; then ECHO=1; fi;; - +([0-9])-) - if [[ $VERB -le ${1%-} ]]; then ECHO=1; fi;; - esac - if [[ $ECHO == 1 ]]; then - case $2 in - -*) - echo $2 "$3";; + list=$1; + result=""; + for i in ${list//,/$IFS}; do + case $i in + +([0-9])) + result+="$i,"; + nbpages+=1;; + -+([0-9])) + result+="1$i,"; + nbpages+=${i#-};; + +([0-9])-) + result+="$i$nbp,"; + nbpages+=$(expr $nbp + 1 - ${i%-});; + +([0-9])-+([0-9])) + result+="$i,"; + nbpages+=$(expr 1 + `echo $i|cut -d- -f2` - `echo $i|cut -d- -f1`);; + -) + result+="1-$nbp,"; + nbpages+=$nbp;; + +([0-9])%+([0-9])) + ## explicitly list all values... + ## (simpler, but admitedly less efficient, + ## than handling real modulos) + declare -i cptr; + cptr=`echo $i|cut -d% -f1`; + step=`echo $i|cut -d% -f2`; + while [[ $cptr -le $nbp ]]; do + result+="$cptr,"; + nbpages+=1; + cptr+=$step; + done;; *) - echo "$2";; - esac - fi + ## anything else is discarded + ;; + esac + done } ARGS=$@; @@ -237,31 +308,36 @@ defaultvalues; setdefaultvalues; filename="temp-pdfxup-`date +%s`"; +OPTS=0; + +## go through all arguments and options +myecho 4+ "-> processing options"; +myecho 4+ " selected options: "; while [ $# != 0 ]; do case $1 in -x|--columns) COLS=$2; + showopts "columns=$COLS"; shift 2;; -x?(=)+([0-9])) COLS=`echo $1|sed -re "s/-x=?//"`; + showopts "columns=$COLS"; shift;; -y|--rows) ROWS=$2; + showopts "rows=$ROWS"; shift 2;; -y?(=)+([0-9])) ROWS=`echo $1|sed -re "s/-y=?//"`; + showopts "rows=$ROWS"; shift;; -l|--landscape) case $2 in - 0|1) - LANDSC=$2; - SHIFT=2; - ;; - yes|y) + 1|yes|y|true) LANDSC=1; SHIFT=2; ;; - no|n) + 0|no|n|false) LANDSC=0; SHIFT=2; ;; @@ -275,17 +351,19 @@ while [ $# != 0 ]; do #echo "Assuming you want landscape outupt..."; SHIFT=1; esac + if [[ $LANDSC -eq 1 ]]; then + showopts "landscape=true"; + else + showopts "landscape=false"; + fi shift $SHIFT;; -l*) ANS=`echo $1|sed -re "s/-l=?//"`; case $ANS in - 0|1) - LANDSC=$ANS; - ;; - yes|y) + 1|yes|y|true) LANDSC=1; ;; - no|n) + 0|no|n|false) LANDSC=0; ;; *) @@ -293,21 +371,27 @@ while [ $# != 0 ]; do #echo "Normal use of '$1' option is: '$1 [0|1]'"; #echo "Assuming you want landscape outupt..."; esac + if [[ $LANDSC -eq 1 ]]; then + showopts "landscape=true"; + else + showopts "landscape=false"; + fi shift;; -nl|--portrait|--no-landscape|--nolandscape) LANDSC=0; + showopts "landscape=false"; shift;; -b|--booklet) case $2 in - 0|1|le|se) - BOOKLET=$2; + se|short-edge) + BOOKLET="se"; SHIFT=2; ;; - yes|y) + 1|yes|y|true|le|long-edge) BOOKLET=1; SHIFT=2; ;; - no|n) + 0|no|n|false) BOOKLET=0; SHIFT=2; ;; @@ -323,18 +407,25 @@ while [ $# != 0 ]; do esac if [[ $BOOKLET != 0 ]]; then FW=0pt + # this is the default, but can be changed by passing -fw option + fi + if [[ $BOOKLET -eq 1 ]]; then + showopts "booklet (long-edge)"; + else if [[ $BOOKLET -eq "se" ]]; then + showopts "booklet (short edge)"; + fi fi shift $SHIFT;; - -b[^b]*) - ANS=`echo $1|sed -re "s/-b=?//"`; + -b[^b]*|--booklet*) + ANS=`echo $1|sed -re "s/--?b(ooklet)?=?//"`; case $ANS in - 0|1|le|se) - BOOKLET=$ANS; + se|short-edge) + BOOKLET="se"; ;; - yes|y) + 1|yes|y|true|le|long-edge) BOOKLET=1; ;; - no|n) + 0|no|n|false) BOOKLET=0; ;; *) @@ -344,161 +435,263 @@ while [ $# != 0 ]; do esac if [[ $BOOKLET != 0 ]]; then FW=0pt + # this is the default, but can be changed by passing -fw option + fi + if [[ $BOOKLET -eq 1 ]]; then + showopts "booklet (long-edge)"; + else if [[ $BOOKLET -eq "se" ]]; then + showopts "booklet (short edge)"; + fi + fi + shift;; + -c|--clip) + case $2 in + 1|yes|y|true) + CLIP=1; + SHIFT=2; + ;; + 0|no|n|false) + CLIP=0; + SHIFT=2; + ;; + *) + CLIP=1; + SHIFT=1; + esac + if [[ $CLIP -eq 1 ]]; then + showopts "clip=true"; + else + showopts "clip=false"; + fi + shift $SHIFT;; + -c*|--clip=*) + ANS=`echo $1|sed -re "s/--?c(lip)?=?//"`; + case $ANS in + 1|yes|y|true) + CLIP=1; + ;; + 0|no|n|false) + CLIP=0; + ;; + esac + if [[ $CLIP -eq 1 ]]; then + showopts "clip=true"; + else + showopts "clip=false"; fi shift;; -ps|--paper|--paper-size) PAP=$2; + showopts "paper size=$PAP"; shift 2;; -ps=*|--paper=*|--paper-size=*) ## '=' is compulsory, as we expect a string... ANS=`echo $1|sed -re "s/(-ps=|--paper=|--paper-size=)//"`; PAP=$ANS; + showopts "paper size=$PAP"; shift;; -p|--pages|--page) - PAGES=$2; + PAGES+="$2,"; + #showopts "pages=$PAGES"; shift 2;; -p*|--page*) - ANS=`echo $1|sed -re "s/(-p|--pages?)=?//"`; - PAGES=$ANS; - shift 2;; + ANS=`echo $1|sed -re "s/--?p(ages?)?=?//"`; + PAGES=+="$ANS,"; + #showopts "pages=$PAGES"; + shift;; -o|--out|--output-file|--outfile) OUTF=$2; + showopts "output file=$OUTF"; shift 2;; - -o*) - ANS=`echo $1|sed -re "s/-o=?//"`; + -o*|--out=*|--output-file=*|--outfile=*) + ANS=`echo $1|sed -re "s/--?o(ut(put-)?(file)?)?=?//"`; OUTF=$ANS; + showopts "output file=$OUTF"; shift;; -ihm|--innerhmargin) dimtopt $2 $dfpdfxupIHM "$1 $2"; IHM=$dim; + showopts "inner horizontal margin=$IHM"; shift 2;; -ihm?(=)+([0-9])*) ANS=`echo $1|sed -re "s/-ihm=?//"`; dimtopt $ANS $dfpdfxupIHM $1; IHM=$dim; + showopts "inner horizontal margin=$IHM"; shift;; -ivm|--innervmargin) dimtopt $2 $dfpdfxupIVM "$1 $2"; IVM=$dim; + showopts "inner vertical margin=$IVM"; shift 2;; -ivm?(=)+([0-9])*) ANS=`echo $1|sed -re "s/-ivm=?//"`; dimtopt $ANS $dfpdfxupIVM $1; IVM=$dim; + showopts "inner vertical margin=$IVM"; shift;; -im|--innermargins) dimtopt $2 $dfpdfxupIM "$1 $2"; IHM=$dim; IVM=$dim; + showopts "inner margins=$IHM"; shift 2;; -im?(=)+([0-9])*) ANS=`echo $1|sed -re "s/-im=?//"`; dimtopt $ANS $dfpdfxupIM $1; IHM=$dim; IVM=$dim; + showopts "inner margins=$IHM"; shift;; -hm|--hmargin) testdim $2 $dfpdfxupHM "$1 $2"; HM=$dim; + showopts "horizontal margin=$HM"; shift 2;; -hm?(=)+([0-9])*) ANS=`echo $1|sed -re "s/-hm=?//"`; testdim $ANS $dfpdfxupHM $1; HM=$dim; + showopts "horizontal margin=$HM"; shift;; -vm|--vmargin) testdim $2 $dfpdfxupVM "$1 $2"; VM=$dim; + showopts "vertical margin=$VM"; shift 2;; -vm?(=)+([0-9])*) ANS=`echo $1|sed -re "s/-vm=?//"`; testdim $ANS $dfpdfxupVM $1; VM=$dim; + showopts "vertical margin=$VM"; shift;; -m|--margins) testdim $2 $dfpdfxupM "$1 $2"; HM=$dim; VM=$dim; + showopts "margins=$HM"; shift 2;; -m?(=)+([0-9])*) ANS=`echo $1|sed -re "s/-m=?//"`; testdim $ANS $dfpdfxupM $1; HM=$dim; VM=$dim; + showopts "margins=$HM"; shift;; -ihs|--inthspace) testdim $2 $dfpdfxupIHS "$1 $2"; IHS=$dim; + showopts "horizontal space=$IHS"; shift 2;; -ihs?(=)+([0-9])*) ANS=`echo $1|sed -re "s/-ihs=?//"`; testdim $ANS $dfpdfxupIHS $1; IHS=$dim; + showopts "horizontal space=$IHS"; shift;; -ivs|--intvspace) testdim $2 $dfpdfxupIVS "$1 $2"; IVS=$dim; + showopts "vertical space=$IVS"; shift 2;; -ivs?(=)+([0-9])*) ANS=`echo $1|sed -re "s/-ivs=?//"`; testdim $ANS $dfpdfxupIVS $1; IVS=$dim; + showopts "vertical space=$IVS"; shift;; -is|--intspaces) testdim $2 $dfpdfxupIS "$1 $2"; IHS=$dim; IVS=$dim; + showopts "space=$IHS"; shift 2;; -is?(=)+([0-9])*) ANS=`echo $1|sed -re "s/-is=?//"`; testdim $ANS $dfpdfxupIS $1; IHS=$dim; IVS=$dim; + showopts "space=$IHS"; shift;; -fw|--framewidth) testdim $2 $dfpdfxupFW "$1 $2"; FW=$dim; + showopts "frame rule width=$FW"; shift 2;; -fw?(=)+([0-9])*) ANS=`echo $1|sed -re "s/-fw=?//"`; testdim $ANS $dfpdfxupFW $1; FW=$dim; + showopts "frame rule width=$FW"; shift;; -i) MVopt="-i"; RMopt="-i"; + showopts "interactive clean up: true"; shift;; -nobb|--nobb|-no-bb|--no-bb) - NOBB[$nbNOBB]=$2; - eval nbNOBB=$(( nbNOBB+1 )); + NOBB+="$2,"; shift 2;; - -nobb*|--nobb*|-no-bb*|--no-bb*) + -nobb*|--no-bb*) ANS=`echo $1|sed -re "s/--?no-?bb=?//"`; - NOBB[$nbNOBB]=$ANS; - eval nbNOBB=$(( nbNOBB+1 )); + NOBB+="$ANS,"; shift;; - -bb|--bb) - BB[$nbBB]=$2; - eval nbBB=$(( nbBB+1 )); + -bb|--bb|--bounding-box) + BB+="$2,"; shift 2;; - -bb*|--bb*) - ANS=`echo $1|sed -re "s/--?bb=?//"`; - BB[$nbBB]=$ANS; - eval nbBB=$(( nbBB+1 )); + -bb*|--bb*|--bounding-box) + ANS=`echo $1|sed -re "s/--?b(ounding-?)?b(ox)?=?//"`; + BB+="$ANS,"; shift;; - - - -g|--get-bb|--getbb) + -kbb|--keepbb|--keep-bb|--original-bb) case $2 in - 0|1) - GBB=$2; + 1|yes|y|true) + KBB=1; SHIFT=2; ;; - yes|y) + 0|no|n|false) + KBB=0; + SHIFT=2; + ;; + -*) + KBB=1; + SHIFT=1; + ;; + *) + KBB=1; + SHIFT=1; + esac + if [[ $KBB -eq 1 ]]; then + showopts "keep original bounding box=true"; + else + showopts "keep original bounding box=false"; + fi + shift $SHIFT;; + -kbb*|--keepbb*|--keep-bb*|--original-bb*) + ANS=`echo $1|sed -re "s/--?(k(eep-?)?bb|orig[^=]*bb)=?//"`; + case $ANS in + 1|yes|y|true) + KBB=1; + ;; + 0|no|n|false) + KBB=0; + ;; + *) + KBB=1; + esac + if [[ $KBB -eq 1 ]]; then + showopts "keep original bounding box=true"; + else + showopts "keep original bounding box=false"; + fi + shift;; + -g|--get-bb|--getbb) + case $2 in + 1|yes|y|true) GBB=1; SHIFT=2; ;; - no|n) + 0|no|n|false) GBB=0; SHIFT=2; ;; @@ -508,21 +701,21 @@ while [ $# != 0 ]; do ;; *) GBB=1; - #echo "Normal use of '$1' option is: '$1 [0|1]'"; - #echo "Assuming you want landscape outupt..."; SHIFT=1; esac + if [[ $GBB -eq 1 ]]; then + showopts "only compute bounding box=true"; + else + showopts "only compute bounding box=false"; + fi shift $SHIFT;; - -g*) - ANS=`echo $1|sed -re "s/-g=?//"`; + -g*|--get-bb=*|--getbb=*) + ANS=`echo $1|sed -re "s/--?g(etbb|et-bb)?=?//"`; case $ANS in - 0|1) - GBB=$ANS; - ;; - yes|y) + 1|yes|y|true) GBB=1; ;; - no|n) + 0|no|n|false) GBB=0; ;; *) @@ -530,8 +723,12 @@ while [ $# != 0 ]; do #echo "Normal use of '$1' option is: '$1 [0|1]'"; #echo "Assuming you want landscape outupt..."; esac + if [[ $GBB -eq 1 ]]; then + showopts "only compute bounding box=true"; + else + showopts "only compute bounding box=false"; + fi shift;; - -s|--set-bb|--setbb) case "$2$3$4$5" in +([0-9])) @@ -541,33 +738,61 @@ while [ $# != 0 ]; do BBW=$4; BBH=$5;; esac + showopts "bounding box set to $2 $3 $4 $5"; shift 5;; - -V) case $2 in @(0|1|2|3)) - VERB=$2; + if [[ $VERB -lt $2 ]]; then + VERB=$2; + fi SHIFT=2;; *) - VERB=2; + if [[ $VERB -lt 2 ]]; then + VERB=2; + fi SHIFT=1;; esac shift $SHIFT;; -V?(=)@(0|1|2|3)) - VERB=`echo $1|sed -re "s/-V=?//"`; + if [[ $VERB -lt `echo $1|sed -re "s/-V=?//"` ]]; then + VERB=`echo $1|sed -re "s/-V=?//"`; + fi shift;; -V?(=)+([0-9])) VERB=9; shift;; - -VV) - VERB=2; + -VV) + if [[ $VERB -lt 2 ]]; then + VERB=2; + fi shift;; -VVV) - VERB=3; + if [[ $VERB -lt 3 ]]; then + VERB=3; + fi shift;; -q|--quiet) VERB=0; shift;; + -w|--watermark|--watermark-file) + WATERMARK=$2; + showopts "watermarking with file $WATERMARK"; + shift 2;; + -w=*|--watermark=*|--watermark-file=*) + ANS=`echo $1|sed -re "s/--?w[^=]*=//"`; + WATERMARK=$ANS; + showopts "watermarking with file $WATERMARK"; + shift;; + -wp|--wperiod|--watermark-period) + WATERMARKPERIOD=$2; + showopts "watermarking period=$WATERMARKPERIOD"; + shift 2;; + -wp=*|--wperiod=*|--watermark-period=*) + ANS=`echo $1|sed -re "s/--?w[^=]*=//"`; + WATERMARKPERIOD=$ANS; + showopts "watermarking period=$WATERMARKPERIOD"; + shift;; -v|--version) echo "pdfxup version $VERSION (released $VDATE)"; exit 0;; @@ -576,10 +801,12 @@ while [ $# != 0 ]; do shift;; -*) usage;; - *:[0-9\-]*) + *:+([0-9\-,\%])) ARG=$1; - file=${ARG%:*} - PAGES=${ARG#*:} + file=${ARG%:*}; + PAGES+="${ARG#*:},"; + ## only one file is allowed, and no options + ## should appear after the file name... break;; *) file=$1; @@ -589,206 +816,232 @@ while [ $# != 0 ]; do esac; done +## this depends on verbosity, hence can only be announced *after* processing options... +myecho 3- "-> processing options"; + +## check input file if [[ $file == "" ]]; then - echo "pdfxup: no input file given; exiting."; + echo "pdfxup error: no input file given; exiting."; exit 0; fi -if [[ ! -e $file && `basename $file .pdf` == $file ]]; then - myecho 2+ "-> changing file name '$file' to '$file.pdf'"; - file="$file.pdf"; -fi; - if [[ ! -e $file ]]; then - echo "pdfxup: file $file not found; exiting."; + echo "pdfxup error: file $file not found; exiting."; exit 0; fi -## get number of pages +## get number of pages of input file nbp=`$GS -sDEVICE=bbox -dNOPAUSE -dQUIET -c "($file) (r) file runpdfbegin pdfpagecount = quit"` +## now we can deal with ranges of pages (BB, NOBB, PAGES) +declare -i nbpages; +nbpages=0; +if [[ ${BB} != "" ]]; then + BB=${BB%,}; + cleancslor $BB; + BB=${result%,}; + showopts "use for bounding-box computation: "${BB}; +else + if [[ ${PAGES} != "" ]]; then + BB=${PAGES%,}; + cleancslor $BB; + BB=${result%,}; + showopts "use for bounding-box computation: "${BB}; + else + BB=$dfpdfxupBB; + fi +fi +if [[ ${NOBB} != "" ]]; then + NOBB=${NOBB%,}; + cleancslor $NOBB; + NOBB=${result%,}; + showopts "exclude from bounding-box computation: "${NOBB}; +else + NOBB=$dfpdfxupNOBB; +fi +if [[ ${PAGES} != "" ]]; then + PAGES=${PAGES%,}; +else + PAGES=$dfpdfxupPAGES; +fi +nbpages=0; +cleancslor $PAGES; +PAGES=${result%,}; +showopts "pages to display: ${PAGES} (${nbpages} pages)"; + + +## clipping option +if [[ $CLIP != 0 ]]; then + myecho 2+ " clipping pages (anything outside bounding box will be dropped)"; + CLIPOPT=",clip"; +else + myecho 2+ " not clipping pages (anything outside bounding box will be displayed)"; + myecho 2+ " (pages may overlap)"; + CLIPOPT=""; +fi + + +## output file name +if [[ ! -e $file && `basename $file .pdf` == $file ]]; then + myecho 2+ " changing file name '$file' to '$file.pdf'"; + file="$file.pdf"; +fi; + + + +## special case: if booklet, we force the numbers of rows and cols if [[ $BOOKLET != 0 ]]; then if [[ $COLS != 2 || $ROWS != 1 || $LANDSC == 0 ]]; then - echo "forcing booklet mode: 2 cols, 1 row, landscape"; + echo " forcing booklet mode: 2 columns, 1 row, landscape mode"; COLS=2; ROWS=1; LANDSC=1; fi fi -firstp=1; -lastp=$nbp; -if [[ $PAGES =~ ([0-9]+|[0-9]*-[0-9]*) ]]; then - BB[$nbBB]=$PAGES; - eval nbBB=$(( nbBB+1 )); - case $PAGES in - -) - firstp=1; - lastp=$nbp;; - +([0-9])) - firstp=${PAGES}; - lastp=${PAGES};; - -+([0-9])) - firstp=1; - lastp=${PAGES:1};; - +([0-9])-) - firstp=${PAGES::-1}; - lastp=$nbp;; - +([0-9])-+([0-9])) - firstp=${PAGES%-*}; - lastp=${PAGES#*-};; - esac -fi -if [[ $nbBB == 0 ]]; then - BB[$nbBB]=$dfpdfxupBB; - nbBB=1; -fi -if [[ $nbNOBB == 0 ]]; then - NOBB[0]=""; +## check watermarking file +nbwp=1; ## set even if no watemark +if [[ $WATERMARK != "" ]]; then + if [[ ! -e $WATERMARK ]]; then + myecho 1+ " pdfxup: watermarking file not found. Omiting watermarking." + else + myecho 2+ " * using file $WATERMARK for watermarking"; + if [[ `file -b $WATERMARK | grep "PDF"` ]]; then + ## get number of pages of WATERMARK (PDF) file + nbwp=`$GS -sDEVICE=bbox -dNOPAUSE -dQUIET -c "($WATERMARK) (r) file runpdfbegin pdfpagecount = quit"` + if [[ $WATERMARKPERIOD -gt $nbwp || $WATERMARKPERIOD -lt 1 ]]; then + WATERMARKPERIOD=$nbwp; + fi + fi + fi fi +## start computing bounding box +x=$x0 +y=$y0 +w=$w0 +h=$h0 +curr=0 +page=0 +step=0 -if [[ $SBB == 0 ]]; then - myecho 1+ -n "-> computing bounding box"; - myecho 2+ ""; - - x=$x0 - y=$y0 - w=$w0 - h=$h0 - curr=0 - page=0 - -# $GS -dNOPAUSE -dSAFER -dQUIET -dBATCH -sDEVICE=bbox $file 2>&1 |\ -# grep "%%BoundingBox" |\ -# sed "s/^.*Box: //" > $filename-bb.txt -# for i in `cat $filename-bb.txt`; do -# case $curr in -# 0) -# thisx=$i; -# #if [[ $x -gt $i ]]; then x=$i; fi -# ;; -# 1) -# thisy=$i; -# #if [[ $y -gt $i ]]; then y=$i; fi -# ;; -# 2) -# thisw=$i; -# #if [[ $w -lt $i ]]; then w=$i; fi -# ;; -# 3) -# thish=$i; -# #if [[ $h -lt $i ]]; then h=$i; fi -# if [[ $x -lt 0 || $x -gt $thisx && $thisx+$thisw -gt 0 ]]; then x=$thisx; fi -# if [[ $y -lt 0 || $y -gt $thisy && $thisy+$thish -gt 0 ]]; then y=$thisy; fi -# if [[ $w -lt 0 || $w -lt $thisw && $thisx+$thisw -gt 0 ]]; then w=$thisw; fi -# if [[ $h -lt 0 || $h -lt $thish && $thisy+$thish -gt 0 ]]; then h=$thish; fi -# ;; -# esac -# eval curr=$(( (curr+1) % 4 )); -# done -# rm $filename-bb.txt - - for (( b=0; b<$nbBB; b++ )) - do - case ${BB[$b]} in - -) - first=1; - last=$nbp;; - +([0-9])) - first=${BB[$b]}; - last=${BB[$b]};; - -+([0-9])) - first=1; - last=${BB[$b]:1};; - +([0-9])-) - first=${BB[$b]::-1}; - last=$nbp;; - +([0-9])-+([0-9])) - first=${BB[$b]%-*}; - last=${BB[$b]#*-};; - esac - myecho 3+ " > $GS -dNOPAUSE -dSAFER -dQUIET -dBATCH -dFirstPage=$first -dLastPage=$last -sDEVICE=bbox $file" - $GS -dNOPAUSE -dSAFER -dQUIET -dBATCH -dFirstPage=$first -dLastPage=$last -sDEVICE=bbox $file 2>&1 | - while IFS= read -r line; do - bbox=`echo $line | grep "%%BoundingBox" | sed "s/^.*Box: //"`; - if [[ $bbox != "" ]]; then - for i in `echo $line | grep "%%BoundingBox" | sed "s/^.*Box: //"`; do - if [[ $curr == 0 ]]; then - eval page=$(( page+1 )); - fi - case $curr in - 0) - thisx=$i; - #if [[ $x -gt $i ]]; then x=$i; fi - ;; - 1) - thisy=$i; - #if [[ $y -gt $i ]]; then y=$i; fi - ;; - 2) - thisw=$i; - #if [[ $w -lt $i ]]; then w=$i; fi - ;; - 3) - thish=$i; - #if [[ $h -lt $i ]]; then h=$i; fi - testrange $page NOBB[@] $nbNOBB - if [ $in == 0 ]; then - if [[ $x -lt 0 || $x -gt $thisx && $thisx+$thisw -gt 0 ]]; then x=$thisx; fi - if [[ $y -lt 0 || $y -gt $thisy && $thisy+$thish -gt 0 ]]; then y=$thisy; fi - if [[ $w -lt 0 || $w -lt $thisw && $thisx+$thisw -gt 0 ]]; then w=$thisw; fi - if [[ $h -lt 0 || $h -lt $thish && $thisy+$thish -gt 0 ]]; then h=$thish; fi - myecho 1 -n "." - myecho 2 -ne " bbox: x=$x y=$y X=$w Y=$h (page $page) \\r"; - myecho 3+ " bbox: x=$x y=$y X=$w Y=$h (page $page) "; +if [[ $KBB == 0 ]]; then + if [[ $SBB == 0 ]]; then + myecho 1+ -n "-> computing bounding box"; + myecho 2+ ""; + + for r in ${BB//,/$IFS}; + do + case $r in + +([0-9])) + first=$r; + last=$r;; + -+([0-9])) + first=1; + last=`echo $r|tr -d -`;; + +([0-9])-) + first=`echo $r|tr -d -`; + last=$nbp;; + +([0-9])-+([0-9])) + first=`echo $r|cut -d- -f1`; + last=`echo $r|cut -d- -f2`;; + -) + first=1; + last=$nbp;; + esac + myecho 2+ " * $GS -dNOPAUSE -dSAFER -dQUIET -dBATCH -dFirstPage=$first -dLastPage=$last -sDEVICE=bbox $file" + $GS -dNOPAUSE -dSAFER -dQUIET -dBATCH -dFirstPage=$first -dLastPage=$last -sDEVICE=bbox $file 2>&1 | + while IFS= read -r line; do + bbox=`echo $line | grep "%%BoundingBox" | sed "s/^.*Box: //"`; + if [[ $bbox != "" ]]; then + for i in `echo $line | grep "%%BoundingBox" | sed "s/^.*Box: //"`; do + if [[ $curr == 0 ]]; then + eval page=$(( page+1 )); fi - ;; - esac - eval curr=$(( (curr+1) % 4 )); - done - fi - done; - done; -else - x=$BBX; - y=$BBY; - w=$BBW; - h=$BBH; + case $curr in + 0) + thisx=$i; + #if [[ $x -gt $i ]]; then x=$i; fi + ;; + 1) + thisy=$i; + #if [[ $y -gt $i ]]; then y=$i; fi + ;; + 2) + thisw=$i; + #if [[ $w -lt $i ]]; then w=$i; fi + ;; + 3) + thish=$i; + #if [[ $h -lt $i ]]; then h=$i; fi + ifinrangelist $page $NOBB; + if [ $in == 0 ]; then + eval step=$(( step+1 )); + if [[ $x -lt 0 || $x -gt $thisx && $thisx+$thisw -gt 0 ]]; then x=$thisx; fi + if [[ $y -lt 0 || $y -gt $thisy && $thisy+$thish -gt 0 ]]; then y=$thisy; fi + if [[ $w -lt 0 || $w -lt $thisw && $thisx+$thisw -gt 0 ]]; then w=$thisw; fi + if [[ $h -lt 0 || $h -lt $thish && $thisy+$thish -gt 0 ]]; then h=$thish; fi + myecho 1 -n "." + myecho 2 -ne " bbox: x=$x y=$y X=$w Y=$h (step $step) \\r"; + myecho 3+ " bbox: x=$x y=$y X=$w Y=$h (step $step) "; + fi + ;; + esac + eval curr=$(( (curr+1) % 4 )); + done + fi + done; + done; + else + x=$BBX; + y=$BBY; + w=$BBW; + h=$BBH; + fi fi -if [[ $x -eq $x0 && +EMPTYBB=$KBB; +if [[ $KBB == 0 && $x -eq $x0 && $y -eq $y0 && $h -eq $h0 && - $w -eq $w0 ]]; then - echo "empty bounding box; aborting." - exit 1; + $w -eq $w0 ]]; then + myecho 1+ ""; + myecho 1+ " * empty bounding box; keeping original margins"; + EMPTYBB=1; + #exit 1; fi -if [[ $SBB == 0 ]]; then +if [[ $SBB == 0 && $EMPTYBB == 0 ]]; then myecho 1 -n "." - myecho 2+ -ne " bbox: x=$x y=$y X=$w Y=$h (final) \\r"; - + myecho 2+ -ne " bbox: x=$x y=$y X=$w Y=$h (final) \\r"; + myecho 3+ ""; + myecho 3+ -ne " (processed $page pages) \\r"; myecho 1+ ""; fi if [[ $GBB != 0 ]]; then - myecho 1 "-> final bounding box: x=$x y=$y X=$w Y=$h"; + myecho 1+ " final bounding box: x=$x y=$y X=$w Y=$h"; exit 0; fi + +## compute options to pass to \includegraphics IHM=${IHM%pt}; IVM=${IVM%pt}; -eval x=$((x-IHM)) -eval y=$((y-IVM)) -eval w=$((w+IHM)) -eval h=$((h+IVM)) - - +if [[ $EMPTYBB -eq 0 ]]; then + eval x=$((x-IHM)) + eval y=$((y-IVM)) + eval w=$((w+IHM)) + eval h=$((h+IVM)) + BBOPTION="viewport=$x $y $w $h"; +else + BBOPTION="trim=-$IHM -$IVM -$IHM -$IVM"; +fi +## start writing .tex file cat > $filename.tex <<EOF \newif\ifbooklet \newif\iflongedge @@ -811,7 +1064,39 @@ cat >> $filename.tex <<EOF \IfFileExists{grffile.sty}{\usepackage{grffile}}{} \topskip=0pt + \makeatletter + + %% \nthvalue#1#2 looks for #1-th value in list of intervals #2 + \newcounter{result}% + \newif\iffound + \def\@parserange#1-#2-#3\@end#4\@end{% + \setcounter{result}{#4}% + \ifnum\value{result}=1\relax + \foundtrue + \setcounter{result}{#1}% + \else + \addtocounter{result}{-1}% + \ifx\relax#3\relax%% means that range contains no - + \else + \addtocounter{result}{#1}% + \ifnum#2<\value{result}\relax + \addtocounter{result}{-#2}% + \else + \foundtrue + \fi + \fi + \fi} + \def\parserange#1#2{\expandafter\@parserange#2-SINGLE-\@end#1\@end} + \def\@parsecsl#1,#2\@end#3\@end{% + \parserange{#3}{#1}% + \iffound\else + \ifx\relax#2\relax\else\@parsecsl#2\@end\value{result}\@end\fi\fi} + \def\nthvalue#1#2{\foundfalse\expandafter\@parsecsl#2,\@end#1\@end} + %% + \def\file{$file} + \def\pagelist{$PAGES} + \def\watermark{$WATERMARK} \pdfximage{\file} \parindent=0pt @@ -826,8 +1111,7 @@ cat >> $filename.tex <<EOF \newcounter{outpage} \newcounter{lastpage} %\setcounter{outpage}{\the\pdflastximagepages} - \setcounter{outpage}{$lastp} - \makeatletter + \setcounter{outpage}{$nbpages} \addtocounter{outpage}{-1} \divide\c@outpage by \nbhoriz \divide\c@outpage by \nbvert @@ -876,6 +1160,7 @@ cat >> $filename.tex <<EOF \divide\vresult by \nbvert % computing actual scale + \if0$EMPTYBB \newcounter{origx} \setcounter{origx}{$w} \addtocounter{origx}{-$x} @@ -898,6 +1183,7 @@ cat >> $filename.tex <<EOF \immediate\write\scale{\the\finalx} \fi \immediate\closeout\scale + \fi \begin{document} %\tracingoutput=1 @@ -905,12 +1191,14 @@ cat >> $filename.tex <<EOF %\tracingparagraphs=1 \makeatletter \newcounter{curroutpage} - \setcounter{curroutpage}{$firstp} + \setcounter{curroutpage}{1} \addtocounter{curroutpage}{-1} \newcounter{currpage} \newcounter{currcol} \newcounter{currline} \newcounter{realout} + \newcounter{wmout} + \newcounter{wmoutaux} %\showthe\value{outpage} %\showthe\value{curroutpage} \@whilenum \value{outpage}>\value{curroutpage} \do% @@ -933,6 +1221,7 @@ cat >> $filename.tex <<EOF \global\stepcounter{currcol}% \global\stepcounter{currpage}% \ifnum\value{currpage}>\value{lastpage}\else + %% computing page number corresponding to \currline and \currcol \setcounter{realout}{\value{currpage}}% \def\ang{0}% \ifbooklet @@ -981,12 +1270,40 @@ cat >> $filename.tex <<EOF \fi \fi \fi - \ifnum\value{realout}>$lastp + \ifnum\value{realout}>$nbpages\relax + %% if page above nb of pages, output blank page \hskip\hresult\hskip2\fboxrule - \else\fbox{\hbox to \hresult{\hfill - \expandafter\includegraphics\expandafter[viewport=$x $y $w $h,% + \else + %% otherwise compute corresponding page to display + %% first keep realout for watermarking... + \setcounter{wmoutaux}{\value{realout}}% + \setcounter{wmout}{\value{realout}}% + \nthvalue{\value{realout}}{\pagelist}% + \iffound\setcounter{realout}{\value{result}}% + \else %% hmmm... problem + \message{I'm messed up counting pages...}% + \fi + %% compute watermarking page (should be original realout?) + \ifx\watermark\@empty\else + \ifnum$nbwp<\value{wmoutaux}\relax + \addtocounter{wmoutaux}{-$nbwp}% + \addtocounter{wmoutaux}{-1}% + \divide\c@wmoutaux by $WATERMARKPERIOD\relax + \stepcounter{wmoutaux}% + \multiply\c@wmoutaux by $WATERMARKPERIOD\relax + \addtocounter{wmout}{-\value{wmoutaux}}% + \fi + \vbox to \vresult{\vfill + \hbox to 0pt{\hfill + \expandafter\includegraphics\expandafter[keepaspectratio,% + height=\vresult,width=\hresult,angle=\ang,% + page=\value{wmout}$CLIPOPT]{$WATERMARK}\hss}\vfill}% + \fi + \fbox{\vbox to \vresult{\vfill + \hbox to \hresult{\hfill + \expandafter\includegraphics\expandafter[$BBOPTION,% keepaspectratio,height=\vresult,width=\hresult,angle=\ang,% - page=\value{realout}]{\file}\hfill}}% + page=\value{realout}$CLIPOPT]{\file}\hfill}\vfill}}% \fi \fi}}% \clearpage% @@ -998,17 +1315,30 @@ EOF myecho 1+ "-> producing final file"; case $VERB in 0|1|2) - $PDFLATEX -interaction=batchmode $filename.tex > /dev/null 2>&1;; + myecho 2+ " * $PDFLATEX -interaction=nonstopmode $filename.tex" + $PDFLATEX -interaction=batchmode $filename.tex > /dev/null 2>&1 || \ + LATEXFAILED=1;; *) - myecho 3+ " > $PDFLATEX -interaction=nonstopmode $filename.tex" - $PDFLATEX -interaction=nonstopmode $filename.tex;; + myecho 3+ " * $PDFLATEX -interaction=nonstopmode $filename.tex" + $PDFLATEX -interaction=nonstopmode $filename.tex || LATEXFAILED=1;; esac -myecho 1+ " final scale: "`cat $filename.scl | sed -e "s/pt$//"`"%"; +if [[ $LATEXFAILED -eq 1 ]]; then + myecho 1+ ": failed!" + if [[ $DEBUG == 0 ]]; then + myecho 1+ "-> cleaning"; + myecho 2+ " * rm $RMopt $filename.*" + rm $RMopt $filename.* + fi + exit 0; +fi +if [[ $EMPTYBB -eq 0 ]]; then + myecho 1+ " final scale: "`cat $filename.scl | sed -e "s/pt$//"`"%" +fi +myecho 2+ " * mv $MVopt $filename.pdf $OUTF" +mv $MVopt $filename.pdf $OUTF if [[ $DEBUG == 0 ]]; then myecho 1+ "-> cleaning"; - myecho 3+ " > mv $MVopt $filename.pdf $OUTF" - mv $MVopt $filename.pdf $OUTF - myecho 3+ " > rm $RMopt $filename.*" + myecho 2+ " * rm $RMopt $filename.*" rm $RMopt $filename.* fi @@ -1046,16 +1376,18 @@ pdfxup has numerous options: either the 'long-edge' or the 'short edge' of the paper. 'long-edge' seems to be the most commonly used, but using '-b se' while produce a PDF booklet for 'short-edge' - 2-sided printing. - * '-p' can be used to only consider a range of pages of the - input file. We do not handle unions of page ranges, so that - only the last occurrence of '-p' will be used. The - restriction applies both for the computation of the - bounding box (and is compatible with the options '-bb' and - '-nobb' below) and for creating the final document. - Alternatively to '-p', the page range can be specified - after the file name, writing 'file.pdf:n-m' in place of - '-p n-m'. + 2-sided printing. + * '-c' clips pages to their bounding box: this is set by + default, so that any content outside bounding box will be + lost. Using "-c 0", anything outside the bounding box will + be displayed, and may overlap neighbouring pages. + * '-p' can be used to only consider a set of pages of the + input file. The set of pages to include is a comma- + separated list of pages, ranges of pages of the form + 'm-n', or sets of pages of the form "0%2" (all even- + numbered pages). Alternatively to '-p', the page range + can be specified after the file name, writing + 'file.pdf:<list>' in place of '-p <list>'. * '-bb' can be used to list the pages to be taken into account when computing the bounding box. This is especially useful for large documents, because computing the @@ -1078,3 +1410,39 @@ pdfxup has numerous options: its included page. * margins: margins of the final document * spacing: spacing between frames + * '-w file' can be used to add watermarking to all pages. The + file can be anything that pdflatex can handle (eg. png, pdf). + If it is a PDF with several pages, page n of the watermarking + file will be used with page n of the input file. By default, + the last page will be repeated if the input file has more + pages than the watermarking file. This behaviour can be + modified with the '-wp n' options, which asks to repeat the + last n pages instead of only the last one. Setting `-wp 0` + will repeat all the pages of the watermarking file. + +################################################################## +## +## Examples +## +################################################################## + +# pdfxup file.pdf + -> creates pdfxup.pdf from file.pdf with default options + (2-up, margins=5mm) +# pdfxup -bb 1-4 file.pdf + -> same behaviour, but computes the bounding box only using the + first 4 pages + (this saves time when processing long documents) +# pdfxup -b file.pdf + -> same behaviour, but creates a booklet +# pdfxup -kbb -b -o booklet.pdf file.pdf:3-25 + -> creates a booklet from pages 3-25 of file.pdf, without + reducing margins (option '-kbb' disables bounding-box + computation; equivalent to e.g. '-bb 0'); + name the resulting file booklet.pdf. +# pdfxup -kbb -x1 -y2 -l0 beamer-frames.pdf + -> arranges 2 beamer frames per page (not reducing margins) +# pdfxup -kbb -x2 -y2 -l1 beamer-frames.pdf + -> arranges 4 beamer frames per page (not reducing margins) +# pdfxup -fw0 -w draft.png file.pdf + -> remove frame border; add 'draft' watermarking on all pages |