#!/bin/sh
#
# Requires bc, od -w1, sed, tr, echo -n, pnmcrop, tempfile
# And via var: DYEPS2PBM

PROGNAME=dytextlab
VERSION=1.0
COPYRIGHT="Copyright (C) 2008  J.A.Bezemer@opensourcepartners.nl  GPL>=2"

##### Real program begins at "main" label, see below


showhelp () {
  echo "
USAGE: $PROGNAME [options] [--] [textline]...  [< textlines]  [> outputfile]

Generate (and print) a simple text label for Dymo LabelManager PC and PC-II
label tape printers.
Text lines as arguments and/or via stdin.
Normally writes .pbm format to stdout, unless -P given.

Options:
  -a <L|C|R>    Align multi-line labels Left, Center (default), Right
  -C            After any text arguments, always Continue reading stdin
  -d <float>    Between-lines Distance (dymopix), default 2, may be negative
  -f <name>     PostScript font name like Times-Italic, default Helvetica
                See "'"less `locate Fontmap.GS`"'" for names of standard fonts
  -F <file>     Load PostScript font file, .pfa or .pfb format
		Also handles TrueType if re-packed as Type42, see readme
                If no -f given, try to extract font name from the file
  -h            This help
  -i <float>    Italicize or slant factor, default 0 = normal, useful: -1 .. 1
  -l <float>    Line height (dymopix) for all lines, default via -Ls/-Lm  "'(*)'"
  -Ls <float>   Line height (dymopix) for single-line labels if no -l given,
                default 50  "'(*)'"
  -Lm <float>   Total used height (dymopix) for multi-line labels if no -l
                given, default 80. Actual line height is this value divided
                by the number of lines (minus -d value), but <= -Ls value  "'(*)'"
  -m            Generate Mirrored text
  -M <int>      Printer model, 1=LMPC 2=LMPC2(default), or 7..48=tape height in
                bytes (8 pixels), 49+=tape height in pixels (LMPC=96 LMPC2=128)
  -P "'"psstdout"'" Dump generated PostScript to stdout (no conversion to .pbm)
  -P <printer>  Print generated .pbm directly to printer via lpr -P  (see -Z)
  -s <float>    Stretch text horizontally, default 1 = normal, useful: .5 .. 3
  -u <float>    Move text Up (or down), default 0, 1 (and -1) is text height
  -Z <..>       LPRng -Z options, multiple=additive, passed to lpr (if -P given)
  --            End of options, use when first line begins with "'"-"'"

Option parameters can be either -o<param> or -o <param> .

Use /etc/${PROGNAME}rc and/or "'~'"/.${PROGNAME}rc to set customized default options,
such as printer model. (System-wide and personal, respectively.)
Also see dytextlabrc.example.

"'(*): When using the full font range, from g and y to  and , most fonts will
actually end up somewhat larger than the requested height. Always keep a
reasonable margin to prevent printing on the roller.
'"
                       max (LMPC1)   suggested max total height
   6mm      1/4in       42               38
   9mm      3/8in       63               58
  12mm      1/2in       85               80
  18/19mm   3/4in      127 (96)         120 (90)
  24mm       1in       128 (96)         120 (90)

Example:  $PROGNAME -Pdymopbm -Zi:red-on-white "'"Some Text" "Line 2"'"

Version $VERSION  $COPYRIGHT
"
}


errorexit () {
  echo "$PROGNAME Error: $1" 1>&2
  [ -n "$FONTFILETMP" ] && rm -f "$FONTFILETMP"
  exit 1
}


# Quickly check that bc result is present, otherwise error out
checkbc () {
  [ -n "$1" ] ||
    errorexit "Internal error (bc), probably some option non-numeric or illegal"
}


checkposint () {
# $1: input to check
# $2: option name for error message
  [ -n "$1" ] ||
    errorexit "$2 value must be positive integer; you supplied "'"'"$1"'"'
  [ -z "`echo "$1" | tr -d '0-9'`" ] ||
    errorexit "$2 value must be positive integer; you supplied "'"'"$1"'"'
}


checkposfloat () {
# $1: input to check
# $2: option name for error message
  [ -n "$1" ] ||
    errorexit "$2 value must be positive float; you supplied "'"'"$1"'"'
  [ -z "`echo "$1" | tr -d '0-9.'`" ] ||
    errorexit "$2 value must be positive float; you supplied "'"'"$1"'"'
  CHECKPOSFLOAT1="${1#*.}"
  [ "x$CHECKPOSFLOAT1" = "x${CHECKPOSFLOAT1#*.}" ] ||
    errorexit "$2 value must be positive float; you supplied "'"'"$1"'"'
}


checkposnegfloat () {
# $1: input to check
# $2: option name for error message
  # checkposfloat "${1#-}" "$2"   works but gives wrong message
  [ -n "$1" ] ||
    errorexit "$2 value must be positive or negative float; you supplied "'"'"$1"'"'
  [ -z "`echo "${1#-}" | tr -d '0-9.'`" ] ||
    errorexit "$2 value must be positive or negative float; you supplied "'"'"$1"'"'
  CHECKPOSFLOAT1="${1#*.}"
  [ "x$CHECKPOSFLOAT1" = "x${CHECKPOSFLOAT1#*.}" ] ||
    errorexit "$2 value must be positive or negative float; you supplied "'"'"$1"'"'
}


checkpsidentifier () {
# $1: input to check
# $2: option name for error message

  [ -n "$1" ] ||
    errorexit "$2 value must be a valid PostScript identifier; you supplied "'"'"$1"'"'

  # PS RefManual says anything but whitespace and ()<>[]{}/% is allowed,
  # but probably not \.
  [ -z "`echo "$1" | tr -d -c '\000- %()/<>[\\]{}\177-\377'`" ] ||
    errorexit "$2 value must be a valid PostScript identifier; you supplied "'"'"$1"'"'
}


checkfileexists () {
# $1: input to check
# $2: option name for error message

  [ -r "$1" ] ||
    errorexit "$2 "'"'"$1"'" does not exist or is not readable'
}


checkalign () {
# $ALIGN: input and output
  case "$ALIGN" in
     [Ll]*)	ALIGN=L ;;
     [Cc]*)	ALIGN=C ;;
     [Rr]*)	ALIGN=R ;;
     *)		errorexit "align must be left, center or right; you supplied "'"'"$ALIGN"'"'
  esac
}


extractfontname () {
# $1 = filename (.pfb/.pfa)
# sets $FONTNAME to /Font-Name  (empty = failed)

  FONTNAME="`
    sed -e 's|/| /|g ; s|%| %|g' < "$1" |	# "..def/b c def" seems allowed
      tr ' \t\r\n' '\n\n\n\n' |			# everything its own line
      sed -n -e '
	\X^/FontName$X {
			; # this triggers as soon as first /FontName found
	  :empty
	  n		; # get new line
	  h		; # pattern to hold space (next subst may change pat)
	  s|^/||	; # try to substitute first /
	  t found	; # branch if subst succeeded
	  b empty	; # otherwise try next line

	  :found
	  g		; # hold space to pattern
	  p		; # print pattern
	  b		; # branch to nowhere = script end
	}
	'`"
}
#extractfontname "$@" ; echo "$FONTNAME" ; exit


##### "main":

ALIGN=C				# -a option (L or C or R)
CONTSTDIN=0			# -C option (0 or 1)
LDIST=2				# -d option
FONTNAMEDEFAULT=Helvetica	# default if no -f and no -F
FONTFILE=""			# -F option
LHGT=""				# -l option
TLHGTSIN=50			# -Ls option
TLHGTMUL=80			# -Lm option
SLANT=0				# -i option
MIRROR=0			# -m option (0 or 1)
TAPEHGT=2			# -M option
PRINTEROUT=""			# -P option
HSTRETCH=1			# -s option
MOVEUP=0			# -u option
ZOPT=""				# -Z _appends_ to this with comma  (INCLUDE -Z)
ZOPTIFNONE=""			# default if no -Z and no ZOPT=    (INCLUDE -Z)
				# (-Z and ZOPT= _overwrite_ this)

DYEPS2PBM="`dirname "$0"`"/dyeps2pbm
PFB2PFA="pfbtopfa"		# from ghostscript
#PFB2PFA="pfb2pfa"		# from tetex-bin


FIGBOTTOM=1710.0		# can be anything now
FIGDPI=1143.0000		# namely 45 p/mm * 25.4 mm/inch
				# can also be anything now, but note that
				# $XPOSRIGHT/$FIGDPI is max tape length (in
				# inches)
DYMODPI=180.0
XPOSLEFT=0
XPOSRIGHT=90000
XPOSCENTER="$(($XPOSRIGHT - $XPOSLEFT))"
XPOSCENTER="$(($XPOSCENTER / 2))"


# Include customizations if available

[ -r /etc/"$PROGNAME"rc ] &&
  . /etc/"$PROGNAME"rc

[ -r "$HOME"/."$PROGNAME"rc ] &&
  . "$HOME"/."$PROGNAME"rc


# Parse options

FONTFILETMP=""	# removed by errorexit if nonzero
FONTNAME=""
NONOPT=0

#while [ -n "$1" ] ; do   --first line may be ""
while [ "$#" -ge 1 ] ; do
  case "$1" in

    # Keep this alphabetic

    -a)		ALIGN="$2"
		checkalign
		shift ; shift ;;
    -a*)	ALIGN="${1#-?}"
		checkalign
		shift ;;

    -C)		CONTSTDIN=1	# Continue from stdin even if non-opt args
		shift ;;	# (Note stdin with "read": no lead/trail spaces)

    -d)		LDIST="$2"
		checkposnegfloat "$LDIST" "line distance"
		shift ; shift ;;
    -d*)	LDIST="${1#-?}"
		checkposnegfloat "$LDIST" "line distance"
		shift ;;

    -f)		FONTNAME="$2"
		checkpsidentifier "$FONTNAME" "font name"
		shift ; shift ;;
    -f*)	FONTNAME="${1#-?}"
		checkpsidentifier "$FONTNAME" "font name"
		shift ;;

    -F)		FONTFILE="$2"
		checkfileexists "$FONTFILE" "font file"
		shift ; shift ;;
    -F*)	FONTFILE="${1#-?}"
		checkfileexists "$FONTFILE" "font file"
		shift ;;

    -h*|--h*)	showhelp
		exit ;;

    -i)		SLANT="$2"				# italicize = slant
		checkposnegfloat "$SLANT" "italicize/slant"
		shift ; shift ;;
    -i*)	SLANT="${1#-?}"
		checkposnegfloat "$SLANT" "italicize/slant"
		shift ;;

    -l)		LHGT="$2"
		checkposfloat "$LHGT" "line height"
		shift ; shift ;;
    -l*)	LHGT="${1#-?}"
		checkposfloat "$LHGT" "line height"
		shift ;;

    -Ls)	TLHGTSIN="$2"
		checkposfloat "$TLHGTSIN" "line height"
		shift ; shift ;;
    -Ls*)	TLHGTSIN="${1#-??}"
		checkposfloat "$TLHGTSIN" "line height"
		shift ;;

    -Lm)	TLHGTMUL="$2"
		checkposfloat "$TLHGTMUL" "line height"
		shift ; shift ;;
    -Lm*)	TLHGTMUL="${1#-??}"
		checkposfloat "$TLHGTMUL" "line height"
		shift ;;

    -m)		MIRROR=1
		shift ;;

    -M)		TAPEHGT="$2"
		checkposint "$TAPEHGT" "printer model"
		shift ; shift ;;
    -M*)	TAPEHGT="${1#-?}"
		checkposint "$TAPEHGT" "printer model"
		shift ;;

    -P)		PRINTEROUT="$2"
		shift ; shift ;;
    -P*)	PRINTEROUT="${1#-?}"
		shift ;;

    -s)		HSTRETCH="$2"
		checkposfloat "$HSTRETCH" "horizontal stretch"
		shift ; shift ;;
    -s*)	HSTRETCH="${1#-?}"
		checkposfloat "$HSTRETCH" "horizontal stretch"
		shift ;;

    -u)		MOVEUP="$2"
		checkposnegfloat "$MOVEUP" "move-up"
		shift ; shift ;;
    -u*)	MOVEUP="${1#-?}"
		checkposnegfloat "$MOVEUP" "move-up"
		shift ;;

    -Z)		if [ -z "$ZOPT" ] ; then
		  ZOPT="-Z$2"
		else
		  ZOPT="$ZOPT,$2"
		fi
		shift ; shift ;;
    -Z*)	if [ -z "$ZOPT" ] ; then
		  ZOPT="-Z${1#-?}"
		else
		  ZOPT="$ZOPT,${1#-?}"
		fi
		shift ;;


    --)		shift
		NONOPT=1
		break ;;

    # These must be last:

    -*)		errorexit 'Unknown option "'"$1"'", try -h' ;;

    *)		NONOPT=1
		break ;;
  esac
done


# Translate tape height if needed

if [ "$TAPEHGT" -le 6 ] ; then
  # height is model number
  case "$TAPEHGT" in
    0|1)	TAPEHGT=96 ;;
    2)		TAPEHGT=128 ;;
    *)		errorexit "Printer model $TAPEHGT unknown"
  esac

elif [ "$TAPEHGT" -le 48 ] ; then
  # height in bytes
  TAPEHGT="$(($TAPEHGT * 8))"

#else: $TAPEHGT already in pixels
fi


# Set default font name or read from file (early, to show any errors
# before reading stdin)

if [ -z "$FONTNAME" ] ; then
  if [ -z "$FONTFILE" ] ; then
    FONTNAME="$FONTNAMEDEFAULT"

  else
    # try to extract from font file
    extractfontname "$FONTFILE"
    [ -n "$FONTNAME" ] ||
      errorexit "Could not extract font name from file "'"'"$FONTFILE"'"'
    # delete '/'
    FONTNAME="${FONTNAME#/}"
  fi
fi


# Find out the max number of lines, to protect against feeding large files.
# This limits stdin reads, so need to calculate first.

if [ -n "$LHGT" ] ; then
  # forced line height
  MAXL="`echo "scale=0 ;
		a = ( $TAPEHGT + $LDIST ) / ( $LHGT + $LDIST ) ;
		if ( ( $LHGT + $LDIST ) <= 0 ) a = 0 ;
		a ;
		" | bc`"		# LDIST < -LHGT would be line reversal!
  checkbc "$MAXL"
  [ "$MAXL" -ge 1 ] ||
    errorexit "Line height too large to fit on tape"

else
  # non-forced mode

  # first check if TLHGTSIN/MUL are reasonable
  [ "x`echo "if ( $TLHGTSIN <= $TAPEHGT ) 1" | bc`" = "x1" ] ||
    errorexit "Single-line height $TLHGTSIN is larger than tape height $TAPEHGT"

  [ "x`echo "if ( $TLHGTMUL <= $TAPEHGT ) 1" | bc`" = "x1" ] ||
    errorexit "Multi-line total height $TLHGTMUL is larger than tape height $TAPEHGT"

  # 6 dymopoints is minimum line height in non-forced mode
  MAXL="`echo "scale=0 ;
		a = ( $TLHGTMUL + $LDIST ) / ( 6 + $LDIST ) ;
		if ( ( 6 + $LDIST ) <= 0 ) a = ( $TLHGTMUL + $LDIST ) / 1 ;
		a ;
		" | bc`"		# LDIST < -6 should be possible
  checkbc "$MAXL"
  [ "$MAXL" -ge 1 ] ||
    errorexit "Line height too small to fit even one line on tape"
fi


# Now read lines from stdin if needed

if [ "x$NONOPT" = "x1" ] && [ "x$CONTSTDIN" = "x0" ] ; then
  # no stdin needed
  [ "$#" -le "$MAXL" ] ||
    errorexit "Too many lines given"

else
  [ "x$NONOPT" = "x0" ] && set --	# Clean any remaining options

  [ "$#" -le "$MAXL" ] ||
    errorexit "Too many lines given"

  while read NEWL ; do
    set -- "$@" "$NEWL"
    [ "$#" -le "$MAXL" ] ||
      errorexit "Too many lines given (stdin)"
  done

  [ "$#" -le "$MAXL" ] ||
    errorexit "Too many lines given"
fi

LINS="$#"
#echo "Printing $LINS lines: $@"


# Determine final font size if not forced

if [ -z "$LHGT" ] ; then
  if [ "x$LINS" = "x1" ] ; then
    LHGT="$TLHGTSIN"

  else
    # multi-line

    # N*H+(N-1)*D=T
    # N*H=T-(N-1)*D
    # H=( T-(N-1)*D )/N
    LHGT="`echo "scale=10 ; ( $TLHGTMUL - ( $LINS - 1 ) * $LDIST ) / $LINS" | bc`"
    checkbc "$LHGT"

    # No need to check >=6dymopix since we already limited $LINS

    # No use in converting to integer dymopix since font will not be
    # _exactly_ LHGT high anyway.

    # Still check if larger than $TLHGTSIN
    [ "x`echo "scale=10 ; if ( $LHGT > $TLHGTSIN ) 1" | bc`" = "x1" ] &&
      LHGT="$TLHGTSIN"
  fi
fi

SCALEFONT="`echo "scale=10 ; ($LHGT / $DYMODPI) * $FIGDPI" | bc`"
checkbc "$SCALEFONT"

#echo "Line heigth: $LHGT Scalefont: $SCALEFONT"


# Convert font file if needed
if [ "x${FONTFILE%[Pp][Ff][Bb]}" != "x$FONTFILE" ] ; then
  FONTFILETMP="`tempfile`" ||
    errorexit "Could not make a tempfile"
  [ -r "$FONTFILETMP" ] ||
    errorexit "Could not make a tempfile"

  "$PFB2PFA" "$FONTFILE" "$FONTFILETMP" ||
    errorexit "Could not convert $FONTFILE to .pfa format"

  # pfbtopfa doesn't pass exitcode correctly?
  [ -s "$FONTFILETMP" ] ||
    errorexit "Could not convert $FONTFILE to .pfa format"

  FONTFILE="$FONTFILETMP"
fi


# Calc/select various parameters

case "$ALIGN" in
  L)	XPOS="$XPOSLEFT" ; [ "x$MIRROR" = "x1" ] && XPOS="$XPOSRIGHT" ;;
  C)	XPOS="$XPOSCENTER" ;;
  *)	XPOS="$XPOSRIGHT"; [ "x$MIRROR" = "x1" ] && XPOS="$XPOSLEFT"  ;;
esac

BBOXY="`echo "scale=0 ; ($TAPEHGT * 72) / $DYMODPI + 1" | bc`"
checkbc "$BBOXY"
# note that too-large is no problem, dyeps2pbm will fix it.
BBOXX="`echo "scale=0 ; ($XPOSRIGHT * 72) / $FIGDPI + 100" | bc`"
checkbc "$BBOXX"


# Before outputting anything, fist check if calculations will work at all

LN=0
    # IDENTICAL to below:
    YPOS="`echo "scale=10 ; $FIGBOTTOM - (( ($TAPEHGT - $LINS * $LHGT - ($LINS - 1) * $LDIST )/2 + ($LINS - 1 - $LN) * ($LHGT + $LDIST) ) / $DYMODPI * $FIGDPI )" | bc`"
    checkbc "$YPOS"


# Output stuff

(
  echo "%!PS-Adobe-2.0 EPSF-2.0
%%Creator: $PROGNAME, derived from fig2dev Version 3.2 Patchlevel 5-alpha7
%%BoundingBox: 0 0 $BBOXX $BBOXY
%%EndComments

	newpath
	0 $BBOXY moveto 0 0 lineto $BBOXX 0 lineto $BBOXX $BBOXY lineto
	closepath clip
	newpath

	23.6 $FIGBOTTOM 72 mul $FIGDPI div translate
	1 -1 scale
  "

  # Copy the header from below
  sed -n -e '
	/^>>>HEADER<<<$/ {
			; # triggers on first >>>HEADER<<< line found
	  :loop
	  n		; # get new line, and immediately exit on EOF
	  p		; # print line
	  b loop	; # repeat
	}
  ' < "$0"

  [ -n "$FONTFILE" ] && cat "$FONTFILE"

  [ "x$MIRROR" = "x1" ] && HSTRETCH="-$HSTRETCH"

  echo "
	%0.06299 0.06299 sc   --we can be more exact
	72 $FIGDPI div dup sc

	/$FONTNAME /$FONTNAME-iso isovec ReEncode
	/$FONTNAME-iso ff

	/BaselineFrac 0.20 def		% reasonable default
	
	dup /FontBBox known
	{
	  dup /FontBBox get

	  % some fonts have { .. }, others have [ .. ], get works always

			% font  [-x-y+x+y]		|head
	  dup 1 get	% font  [-x-y+x+y] -ymin	|head
	  neg		% font  [-x-y+x+y]  ymin	|head
	  dup		% font  [-x-y+x+y]  ymin  ymin	|head
	  3 -1 roll	% font  ymin  ymin  [-x-y+x+y]	|head
	  3 get		% font  ymin  ymin  ymax	|head
	  add		% font  ymin  ytot		|head
	  dup 0 eq	% font  ymin  ytot  tr/fal	|head
	  {		%   (if true, ytot==0)
			% font  ymin  0			|head
	    pop pop	% font				|head
			%   Leave BaselineFrac at default (above)
	  }
	  {		%   (if false, ytot!=0: we can divide)
			% font  ymin  ytot		|head
	    div		% font  yfrac			|head
	    /BaselineFrac exch def
			%   BaselineFrac now fraction of total "y-to-M" height
	  } ifelse
			% font				|head
	} if

	% Print out the BaselineFrac. Try with Times-Roman or Symbol
	%dup 150 scf sf
	%$XPOSLEFT $FIGBOTTOM 500 sub m
	%(BaselineFrac = ) sh		% Duh, vertically mirrored. don't care.
	%/str 200 string def
	%BaselineFrac str cvs sh

	% Makefont now does all at once: scaling, stretching, slanting,
	% and hightening, so that cursorpoint is real bottom instead of
	% baseline, plus any manual move-up.

	% (font still on stack)
	[ $SCALEFONT $HSTRETCH mul
	  0
	  $SLANT $SCALEFONT mul
	  $SCALEFONT
	  0
	  $SCALEFONT BaselineFrac mul $SCALEFONT $MOVEUP mul add
	] makefont sf

	% Thanks to "Practical Postscript"
	% and http://atrey.karlin.mff.cuni.cz/~milanek/PostScript/Reference/
	% ...oh okay. So that was cleverly ripped from Adobe's PS RefManual,
	% such as http://www-cdf.fnal.gov/offline/PostScript/PLRM3.pdf

	col0
  "

  LN=0
  while [ "$#" -ge 1 ] ; do

    # Calc y position (fig units); see breakdown in Notes section below
    # IDENTICAL to above:
    YPOS="`echo "scale=10 ; $FIGBOTTOM - (( ($TAPEHGT - $LINS * $LHGT - ($LINS - 1) * $LDIST )/2 + ($LINS - 1 - $LN) * ($LHGT + $LDIST) ) / $DYMODPI * $FIGDPI )" | bc`"
    checkbc "$YPOS"

    #echo "Printing line $LN at $XPOS $YPOS: $1"

    echo "$XPOS $YPOS m"
    echo "gs 1 -1 sc"
    echo -n "("
    # Escaping only non-ascii is hard, so just escape everything
    echo -n "$1" | od -to1 -An -w1 -v | sed -e 's/ //g ; s/^/\\/' | tr -d '\n'
    echo ")"

    case "$ALIGN" in
      L)  echo "sh gr" ;;
      C)  echo "dup sw pop 2 div neg 0 rm  sh gr" ;;
      *)  echo "dup sw pop neg 0 rm  sh gr" ;;
    esac
    echo ""

    shift
    LN="$(($LN + 1))"
  done

  echo '$F2psEnd
        rs
        showpage
        %%Trailer
        %EOF'
) |
  if [ "x$PRINTEROUT" = "xpsstdout" ] ; then
    cat
  else

    "$DYEPS2PBM" "$TAPEHGT" |
      pnmcrop -white -top -bottom |

      if [ -z "$PRINTEROUT" ] ; then
        # pbm to stdout
        cat
      else
	[ -z "$ZOPT" ] &&
	  ZOPT="$ZOPTIFNONE"

        if [ -n "$ZOPT" ] ; then
          lpr -P"$PRINTEROUT" "$ZOPT"
        else
          lpr -P"$PRINTEROUT"
        fi
      fi
  fi


[ -n "$FONTFILETMP" ] && rm -f "$FONTFILETMP"

exit 0


##############################################################################

Notes:

Based on xfig/fig2dev.

fig -> eps  1 -1 scale  0.06299 0.06299 sc  from 72dpi => 1143dpi = 45dpmm!

xfig font "size 100" becomes 1587.50 scalefont  so 1587.5/1143=100/72!!dpi
  xfig.3.2.5-alpha5.orig.tar.gz already has correct_font_size=true in main.c
  -> correct_font_size can't be false any more!

xfig point is baseline...            v-- from real bottom of letters
  helv: 11-109(/72) baseline=30 so 19.4%   avantg: 13-114 basel=34 so 20.8%
  [Better now: automatically in PostScript from FontBBox]

Calculation for LMPC2:
available Y: 900-1710=810figpix /1143*180=127.56dymopix =~128 =correct
  12pt=12/72*180=29.99=30dymopix  and 30/180*1143=190.50 scalefont (okay!)
  mid: 127.56-30=98 /2=49 =bottommarg (we calc from bottom)
  now 20% of 30 =0.20*30=6.0dymopix so baseline is 49+6.0=55.0dymopix
  so 55.0/180*1143=349.25figpix and absolute 1710-349.25=1360.75
  xfig "first guess" was 1350 ==good!

General case with LINS lines of LHGT dymopix and LDIST dymopix between lines:
  bottom margin is ( TAPEHGT-LINS*LHGT-(LINS-1)*LDIST )/2
  line LN starts above bottom margin: (LINS-1-LN)*(LHGT+LDIST)
  and minus 20% of LHGT  [This not needed any more, auto-calc in postscript!]
    => all dymopix
  then 1710-(dymopix/180*1143) gives figpix=epscoord


##############################################################################

EPS Header stuff, fetched from here by sed, up to EOF:
>>>HEADER<<<

/$F2psDict 200 dict def
$F2psDict begin
$F2psDict /mtrx matrix put

/col0 {0.000 0.000 0.000 srgb} bind def
/col7 {1.000 1.000 1.000 srgb} bind def

end
save

/cp {closepath} bind def
/ef {eofill} bind def
/gr {grestore} bind def
/gs {gsave} bind def
/sa {save} bind def
/rs {restore} bind def
/l {lineto} bind def
/m {moveto} bind def
/rm {rmoveto} bind def
/n {newpath} bind def
/s {stroke} bind def
/sh {show} bind def
/slc {setlinecap} bind def
/slj {setlinejoin} bind def
/slw {setlinewidth} bind def
/srgb {setrgbcolor} bind def
/rot {rotate} bind def
/sc {scale} bind def
/sd {setdash} bind def
/ff {findfont} bind def
/sf {setfont} bind def
/scf {scalefont} bind def
/sw {stringwidth} bind def
/tr {translate} bind def
/tnt {dup dup currentrgbcolor
  4 -2 roll dup 1 exch sub 3 -1 roll mul add
  4 -2 roll dup 1 exch sub 3 -1 roll mul add
  4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
  bind def
/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
  4 -2 roll mul srgb} bind def

/reencdict 12 dict def /ReEncode { reencdict begin
/newcodesandnames exch def /newfontname exch def /basefontname exch def
/basefontdict basefontname findfont def /newfont basefontdict maxlength dict def
basefontdict { exch dup /FID ne { dup /Encoding eq
{ exch dup length array copy newfont 3 1 roll put }
{ exch newfont 3 1 roll put } ifelse } { pop pop } ifelse } forall
newfont /FontName newfontname put newcodesandnames aload pop
128 1 255 { newfont /Encoding get exch /.notdef put } for
newcodesandnames length 2 idiv { newfont /Encoding get 3 1 roll put } repeat
newfontname newfont definefont pop end } def

/isovec [
8#055 /minus 8#200 /grave 8#201 /acute 8#202 /circumflex 8#203 /tilde
8#204 /macron 8#205 /breve 8#206 /dotaccent 8#207 /dieresis
8#210 /ring 8#211 /cedilla 8#212 /hungarumlaut 8#213 /ogonek 8#214 /caron
8#220 /dotlessi 8#230 /oe 8#231 /OE
8#240 /space 8#241 /exclamdown 8#242 /cent 8#243 /sterling
8#244 /currency 8#245 /yen 8#246 /brokenbar 8#247 /section 8#250 /dieresis
8#251 /copyright 8#252 /ordfeminine 8#253 /guillemotleft 8#254 /logicalnot
8#255 /hyphen 8#256 /registered 8#257 /macron 8#260 /degree 8#261 /plusminus
8#262 /twosuperior 8#263 /threesuperior 8#264 /acute 8#265 /mu 8#266 /paragraph
8#267 /periodcentered 8#270 /cedilla 8#271 /onesuperior 8#272 /ordmasculine
8#273 /guillemotright 8#274 /onequarter 8#275 /onehalf
8#276 /threequarters 8#277 /questiondown 8#300 /Agrave 8#301 /Aacute
8#302 /Acircumflex 8#303 /Atilde 8#304 /Adieresis 8#305 /Aring
8#306 /AE 8#307 /Ccedilla 8#310 /Egrave 8#311 /Eacute
8#312 /Ecircumflex 8#313 /Edieresis 8#314 /Igrave 8#315 /Iacute
8#316 /Icircumflex 8#317 /Idieresis 8#320 /Eth 8#321 /Ntilde 8#322 /Ograve
8#323 /Oacute 8#324 /Ocircumflex 8#325 /Otilde 8#326 /Odieresis 8#327 /multiply
8#330 /Oslash 8#331 /Ugrave 8#332 /Uacute 8#333 /Ucircumflex
8#334 /Udieresis 8#335 /Yacute 8#336 /Thorn 8#337 /germandbls 8#340 /agrave
8#341 /aacute 8#342 /acircumflex 8#343 /atilde 8#344 /adieresis 8#345 /aring
8#346 /ae 8#347 /ccedilla 8#350 /egrave 8#351 /eacute
8#352 /ecircumflex 8#353 /edieresis 8#354 /igrave 8#355 /iacute
8#356 /icircumflex 8#357 /idieresis 8#360 /eth 8#361 /ntilde 8#362 /ograve
8#363 /oacute 8#364 /ocircumflex 8#365 /otilde 8#366 /odieresis 8#367 /divide
8#370 /oslash 8#371 /ugrave 8#372 /uacute 8#373 /ucircumflex
8#374 /udieresis 8#375 /yacute 8#376 /thorn 8#377 /ydieresis] def

/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
/$F2psEnd {$F2psEnteredState restore end} def

$F2psBegin
1 setmiterlimit
0 slj 0 slc

% end of header
