#!/bin/sh #--------------- # A parametrized replacement for psnup -2 using pstops. # # The script computes bounding boxes using gs and deduces optimized reductions # on two pages per sheet with given margins or scaling. Pages can be arranged # for various kinds of folding or binding. #--------------- # Requires: gs, bc, pstops, psbook, pdftops #--------------- VERSION=2009-12-02 # Output parameters PAPER=a4 WIDTH=597 # 210mm HEIGHT=845 # 297mm MARGIN=30 INNER=1 SCALE= TWO=false BIND=top BBRANGE=- SIG= IN= OUT= DASHQ=-q VERBOSE=false BB_ODD= BB_EVEN= # Parse the command line while [ $# -gt 0 ]; do case "$1" in --help) cat <&2 exit 1 ;; *) if [ -z "$IN" ] then IN="$1" elif [ -z "$OUT" ] then OUT="$1" else echo "unused argument: $1" >&2 fi esac shift done if [ -z "$IN" ]; then echo "missing input file" >&2 exit 1 fi # Make a teporary file if needed TMP= make_ps () { case $(file -bL "$IN") in "PostScript document"*) ;; "PDF document"*) $VERBOSE && echo "converting to PS..." >&2 TMP2=$(mktemp) pdftops "$IN" "$TMP2" test -n "$TMP" && rm "$TMP" TMP="$TMP2" IN="$TMP" ;; "gzip compressed "*) $VERBOSE && echo "unzipping..." >&2 TMP2=$(mktemp) gunzip < "$IN" > "$TMP2" test -n "$TMP" && rm "$TMP" TMP="$TMP2" IN="$TMP" make_ps ;; *) echo "Unknown file type!" >&2 exit 1 esac } make_ps # Extract the bounding box for all pages of a given file. read_bbox() { gs -sDEVICE=bbox -sPAPERSIZE=$PAPER -r300x300 -q -dBATCH -dNOPAUSE "$1" 2>&1 | awk ' function min(x,y) { if (x < y) return x; else return y } function max(x,y) { if (x > y) return x; else return y } BEGIN { left = top = 10000; right = bottom = 0 } /%%BoundingBox:/ { left = min(left, $2); top = min(top, $3); right = max(right, $4); bottom = max(bottom, $5); } END { print left, top, right, bottom } ' } # Compute the maximum scaling factor given the bounding box max_scale() { bc <&2 if $TWO; then BB_ODD=$(psselect -o -p"$BBRANGE" "$IN" 2>/dev/null | read_bbox -) BB_EVEN=$(psselect -e -p"$BBRANGE" "$IN" 2>/dev/null | read_bbox -) else if [ "$BBRANGE" = "-" ]; then BB_ODD=$(read_bbox "$IN") else BB_ODD=$(psselect -p"$BBRANGE" "$IN" 2>/dev/null | read_bbox -) fi fi fi test -z "$BB_EVEN" && BB_EVEN="$BB_ODD" if $VERBOSE; then if $TWO; then echo "bounding box (odd): $BB_ODD" echo "bounding box (even): $BB_ODD" else echo "bounding box: $BB_ODD" fi fi # Deduce the scaling factor if needed if [ -z "$SCALE" ]; then if $TWO; then SCALE=$(bc <&2 # Process the file according to the chosen style command() { $VERBOSE && echo "-- $*" $* } case $BIND in top) command pstops $DASHQ -p$PAPER "2:\ 0$(spec_left $SCALE $BB_ODD 0)+1$(spec_left $SCALE $BB_EVEN 1)" "$IN" "$OUT" ;; left) command pstops $DASHQ -p$PAPER "4:\ 0$(spec_left $SCALE $BB_ODD 0)+1$(spec_left $SCALE $BB_EVEN 1),\ 2$(spec_right $SCALE $BB_ODD 1)+3$(spec_right $SCALE $BB_EVEN 0)" "$IN" "$OUT" ;; book) psbook $DASHQ $SIG $IN | command pstops $DASHQ -p$PAPER "4:\ 0$(spec_left $SCALE $BB_EVEN 0)+1$(spec_left $SCALE $BB_ODD 1),\ 2$(spec_right $SCALE $BB_EVEN 1)+3$(spec_right $SCALE $BB_ODD 0)" /dev/stdin "$OUT" esac test -n "$TMP" && rm "$TMP" || true