🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: comp.sources.bugs
1 messages
1 total messages Started by Chris Lewis Wed, 02 Dec 1992 03:28
Official Patch 14 for Psroff 3.0
#728
Author: Chris Lewis
Date: Wed, 02 Dec 1992 03:28
2486 lines
65713 bytes
Archive-name: psroff3.0/Patch.14
Submitted-by: clewis@ferret.ocunix.on.ca (Chris Lewis)

[Repost, previous copy black-holed.]

    This is official patch 14 for Psroff 3.0.
    Please apply it by:
	cd <psroff source directory>
	patch -N -p < <this file>
    
    The base release of psroff3.0 and first four patches were in
    comp.sources.unix volume 24.

    Psroff 3.0 is maintained in full patched, but shar'd form on
    ftp.uunet.ca.  You will want to pick up files:

    /distrib/chris_lewis/psroff3.0/part[00..11].Z

Major new features:
	- Laserjet fonts are automatically scaled on the fly,
	  so you can use any size of a font.  Previous versions
	  required you to obtain fonts from other sources to
	  get pointsizes other than 10.  (Note: Laserjet III, PCL5,
	  scalable fonts were already supported in the lj3 personalities)
	  Of particular interest to hp2pbm users to convert LJ
	  to other formats (such as Epson dotmatrix)
	- Full support for laserjet ditroff graphics: lines, arcs,
	  circles, ellipses, polygons, splines, with fill and line
	  thickness settings.  (Note: Laserjet III, PC5, HPGL/2
	  was already supported in the lj3 personalities.  This
	  extends it to PCL4 via raster graphics)
	  Of particular interest to hp2pbm users to convert LJ
	  to other formats (such as Epson dotmatrix)
	- seamless integration into groff: after installation,
	  both "psroff -Tg[lj, lj3, lj3u]" and "groff -T[lj, lj3, lj3u]"
	  will work.

PL15 will be out soon, many minor little extensions planned, eg: german
\(ss character etc.

./man/psxlate.1.S		man page example improvment from vidiot
./widths/installdit.S		groff fixes
./utils/Makefile		scaleljfonts
./utils/catconv.S		fix character extension fakeout for CAT troff
./utils/pk2ditwid.c		groff compatibility problems
./dt.c				font switch bug fixed.
./ps.c				chars < ' ' should be octalized
./defs.h			PL14
./Makefile			scaleljfonts, pkscale.o inclusion
./opt.c				debug statements accidentally deleted.
./lj.c				font scaling, drawing support
./ljdraw.c			major changes for drawing support
./lj3draw.c			Ypos caching botch
./pkscale.c			header banging botch
./pk.h				pkscale() decl.

Patchwrapped: 921126233632

Index: ./man/psxlate.1.S
*** /tmp/PATCHold/./man/psxlate.1.S	Thu Nov 26 23:33:12 1992
--- ./man/psxlate.1.S	Thu Nov 26 23:33:13 1992
***************
*** 1,4 ****
! .\"Copyright 1991 by Chris Lewis 2.8 91/07/11
  .TH PSXLATE %%MANEXT%% "Psroff %%T2VERSION%%"
  .SH NAME
  psxlate \- General Postscript page flipper etcetera
--- 1,4 ----
! .\"Copyright 1991 by Chris Lewis 2.9 92/11/11
  .TH PSXLATE %%MANEXT%% "Psroff %%T2VERSION%%"
  .SH NAME
  psxlate \- General Postscript page flipper etcetera
***************
*** 16,32 ****
  .BI ">" output file
  .SH DESCRIPTION
  .B Psxlate
! reads a Postscript file that are conformant with the Adobe Document
  Structuring Convention standard (DSC), shuffles the pages around according
  to the parameters, and outputs the result.
- Further, if you have
- .B psnup
- from comp.sources.misc (volume 16), you can use the postscript files
- that come with it to do n-up printing.
  ``Conformant'' in this context, means files that begin with ``%!PS\-Adobe\-'',
  have pages that are prefixed with ``%%Page:'' comments and have a trailer
  prefixed by ``%%Trailer:''.
  Case is significant.
  .PP
  .B Psxlate
  is ideally used as the filter in your print spooler system.
--- 16,37 ----
  .BI ">" output file
  .SH DESCRIPTION
  .B Psxlate
! reads a Postscript file that is conformant with the Adobe Document
  Structuring Convention standard (DSC), shuffles the pages around according
  to the parameters, and outputs the result.
  ``Conformant'' in this context, means files that begin with ``%!PS\-Adobe\-'',
  have pages that are prefixed with ``%%Page:'' comments and have a trailer
  prefixed by ``%%Trailer:''.
  Case is significant.
+ It also PostScript that contains embedded EPS files provided that they are
+ compliant with the DSC and use BeginDocument/EndDocument.
+ .PP
+ If you have
+ .B psnup
+ from comp.sources.misc (volume 16),
+ .B psxlate
+ can be configured to use it to provide n-up printing.
+ that come with it to do n-up printing.
  .PP
  .B Psxlate
  is ideally used as the filter in your print spooler system.
***************
*** 74,88 ****
  characters, some UNIX systems can't send 8-bit characters down
  a serial line without grave difficulty, and it sort of defeats the
  purpose of Postscript in the first place.
- .SH OPTIONS
  .PP
! The
  .B \-d
! option enables debugging.
! .PP
! The
  .B \-n
! option permits you to select specific pages for printing.
  You can specify pages or ranges of pages.
  Ie: \-n4,5,20-25
  Selects the fourth, fifth and 20th thru 25th pages for printing.
--- 79,104 ----
  characters, some UNIX systems can't send 8-bit characters down
  a serial line without grave difficulty, and it sort of defeats the
  purpose of Postscript in the first place.
  .PP
! If, when working with PostScript that contains inclusions of other
! PostScript (ie: groff PostScript inclusions), you find that Psxlate
! generates output that has the pages scrambled or PostScript errors,
! the inclusions were probably done incorrectly.
! According to the DSC (3, possibly 2 as well), included PostScript
! should start with "%%BeginDocument:" and end with "%%EndDocument".
! If these aren't there, any EPS comments inside may confuse
! .BR psxlate .
! If this happens, you should either modify the application that
! includes the PostScript to insert the BeginDocument and EndDocument
! comments, or manually insert them into the EPS before doing the
! inclusion.
! .SH OPTIONS
! .TP
  .B \-d
! This option enables debugging.
! .TP
  .B \-n
! Permits you to select specific pages for printing.
  You can specify pages or ranges of pages.
  Ie: \-n4,5,20-25
  Selects the fourth, fifth and 20th thru 25th pages for printing.
***************
*** 93,112 ****
  sees them.
  If the second part of a range is omitted, it means to the end of the document.
  If the first part of a range is omitted, it means from the beginning of the document.
! .PP
  The other options,
  .BR r ,
  .BR b ,
  .BR 2 ,
! .B c ,
  plus any others locally implemented, denote different shuffle
  algorithms which will be applied in-turn to the Postscript and
  can be specified more than once.
  Specification of none of these options gives no shuffle at all.
! .PP
! The
! .B r
! option denotes page reversal - the order of the pages will be
  reversed.
  This is particularly handy for laser printers that stack face up
  (eg: the Canon I Laser engine in older HP Laserjets and Apple Laserwriters)
--- 109,127 ----
  sees them.
  If the second part of a range is omitted, it means to the end of the document.
  If the first part of a range is omitted, it means from the beginning of the document.
! .sp .65v
  The other options,
  .BR r ,
  .BR b ,
  .BR 2 ,
! .BR c ,
  plus any others locally implemented, denote different shuffle
  algorithms which will be applied in-turn to the Postscript and
  can be specified more than once.
  Specification of none of these options gives no shuffle at all.
! .TP
! .B \-r
! Denotes page reversal - the order of the pages will be
  reversed.
  This is particularly handy for laser printers that stack face up
  (eg: the Canon I Laser engine in older HP Laserjets and Apple Laserwriters)
***************
*** 113,129 ****
  and without reversal would require you to do a lot of page shuffling.
  If used in conjunction with the \-p and \-s options, this will
  also generate the n-up pages in the correct order.
! .PP
! The
! .B b
! option denotes book order:
! .PP
  1 2 3 4 5 6 7 8 .... n
! .PP
  is transformed into:
! .PP
  n 1 n\-2 3 n\-4 5 ... 2 n\-1 4 n\-3 ...
! .PP
  This is the order that you would output pages for 2-up printing to
  be rebound into a book.
  This can be used in conjunction with the
--- 128,149 ----
  and without reversal would require you to do a lot of page shuffling.
  If used in conjunction with the \-p and \-s options, this will
  also generate the n-up pages in the correct order.
! Under most circumstances, this option should be placed after a
! .B \-2B
! or
! .BR \-2E .
! Placing it first may cause the wrong pages to be printed from what is expected.
! See the notes below for examples.
! .TP
! .B \-b
! Denotes book order:
! .sp .35v
  1 2 3 4 5 6 7 8 .... n
! .sp .35v
  is transformed into:
! .sp .35v
  n 1 n\-2 3 n\-4 5 ... 2 n\-1 4 n\-3 ...
! .sp .35v
  This is the order that you would output pages for 2-up printing to
  be rebound into a book.
  This can be used in conjunction with the
***************
*** 137,172 ****
  You should consult your printer manual to find out the proper orientation.
  Up to 3 blank pages are inserted on the end to get a multiple of 4
  pages in total.
! .PP
! The
  .B \-c
! option is the ``couple swap'' option.
  It is similar to reversal, except that it is pairs of pages that
  are swapped.
  As in:
! .PP
  1 2 3 4 5 6 ... n
! .PP
  is converted to:
! .PP
  n\-1 n n\-3 n\-2 ... 1 2
! .PP
  This is useful for running after the
  .B \-b
  option for printers that need reversal, but since you'll be shuffling
  the pages anyways, it's probably not all that critical.
  A single page may be appended to get the number of pages to be even.
! .PP
! The
  .B \-2
! option transforms:
! .PP
  1 2 3 4 5 6 7 8
! .PP
  into:
  1 3 5 7 ... 2 4 6 8
! .PP
  suitable for portrait two-sided output.
  .SH "NOTES FOR PSNUP (\-p/\-s)"
  The
  .B Psnup
--- 157,207 ----
  You should consult your printer manual to find out the proper orientation.
  Up to 3 blank pages are inserted on the end to get a multiple of 4
  pages in total.
! .TP
  .B \-c
! This is the ``couple swap'' option.
  It is similar to reversal, except that it is pairs of pages that
  are swapped.
  As in:
! .sp .35v
  1 2 3 4 5 6 ... n
! .sp .35v
  is converted to:
! .sp .35v
  n\-1 n n\-3 n\-2 ... 1 2
! .sp .35v
  This is useful for running after the
  .B \-b
  option for printers that need reversal, but since you'll be shuffling
  the pages anyways, it's probably not all that critical.
  A single page may be appended to get the number of pages to be even.
! .TP
  .B \-2
! This option transforms:
! .sp .35v
  1 2 3 4 5 6 7 8
! .sp .35v
  into:
+ .sp .35v
  1 3 5 7 ... 2 4 6 8
! .sp .35v
  suitable for portrait two-sided output.
+ .TP
+ .B \-B
+ This option prints the first half of the pages.
+ It is normally used in conjunction with
+ .B \-2
+ or
+ .BR \-b .
+ See the notes below for examples.
+ .TP
+ .B \-E
+ This option prints the last half of the pages.
+ It is normally used in conjunction with
+ .B \-2
+ or
+ .BR \-b .
+ See the notes below for examples.
  .SH "NOTES FOR PSNUP (\-p/\-s)"
  The
  .B Psnup
***************
*** 211,225 ****
  can run
  .B psxlate
  on that.
! To print two sided on a reversing printer, you would type:
! .sp
! .nf
  psroff .... \-t files > /tmp/saveit
  psxlate \-2B < /tmp/saveit | <your printer spooler>
! change paper around
! psxlate \-r2E < /tmp/saveit | <your printer spooler>
  .fi
  .PP
  On a non-reversing printer, the
  .B \-r
  option wouldn't be necessary.
--- 246,308 ----
  can run
  .B psxlate
  on that.
! To print two sided, you would type (the Apple LaserWriter/LaserWriterPlus
! cannot be used for double-sided printing):
! .PP
  psroff .... \-t files > /tmp/saveit
+ .PP
+ For the Apple LaserWriter II series of printers, using the top output tray,
+ the following would be done:
+ .nf
+ psxlate \-2Br < /tmp/saveit | <your printer spooler>
+ Move the paper from the output tray to the paper tray, white side up:
  psxlate \-2B < /tmp/saveit | <your printer spooler>
! .fi
! .PP
! When using the Apple LaserWriter II series of printers you must remember to
! turn the paper around 180 degrees, before placing the output stack into the
! paper tray.
! Otherwise the second pass will print upside-down.
! .PP
! Also note that the Apple LaserWriter IINT printer has a nasty habit of
! curling the paper bad enough during the first pass that the second pass
! may jam or wrinkle.
! .PP
! If groff is used as the troff processor, then the resulting PostScript file
! can be edited and made to print upside-down.
! Then the paper can be moved from the output tray to the paper tray,
! without turning it around 180 degrees.
! .PP
! Place the following lines into an executable file named
! .BR upsxlate :
! .PP
! .nf
! #!/bin/sh
! sed -e "/1 -1 scale/s/scale/scale 612 PL translate 180 rotate/" | psxlate $*
  .fi
  .PP
+ Using the exact same syntax as
+ .BR psxlate ,
+ the
+ .B
+ upsxlate
+ script will cause the groff portrait output to print upside down.
+ .PP
+ If you are printing on a Sun SPARCprinter, the following is used to print
+ double-sided:
+ .PP
+ .nf
+ psxlate \-2Er < /tmp/saveit | lpr -Psparc
+ move the paper from the output tray to the paper tray (face up):
+ psxlate \-2E < /tmp/saveit | lpr -Psparc
+ .fi
+ .PP
+ The first batch printed to the SPARCprinter will contain all of the odd pages,
+ in reverse order, placing page one on the top of the output stack.
+ When the second batch is printed, all of the even pages will be done in
+ ascending order.
+ When completed, the output stack will be in the correct order.
+ .PP
  On a non-reversing printer, the
  .B \-r
  option wouldn't be necessary.
***************
*** 256,259 ****
  .B sed
  to delete them.
  .SH AUTHOR
! Written by Chris Lewis
--- 339,343 ----
  .B sed
  to delete them.
  .SH AUTHOR
! Written by Chris Lewis.
! Examples provided by Michael Brown.
Index: ./widths/installdit.S
*** /tmp/PATCHold/./widths/installdit.S	Thu Nov 26 23:33:26 1992
--- ./widths/installdit.S	Thu Nov 26 23:33:27 1992
***************
*** 5,18 ****
  #    See the LICENSE file for a full description of the restrictions
  #    under which this software is provided.
  #
! #1.9 92/06/01
  MAKEDEV=%%MAKEDEV%%
! if [ ! -f "$MAKEDEV" ]
! then
!     echo "no $MAKEDEV program - don't worry unless you're using psroff"
!     echo "with REAL ditroff instead of C/A/T troff"
!     exit 0
! fi
  if [ "$1" = "-i" ]
  then
      install=1
--- 5,13 ----
  #    See the LICENSE file for a full description of the restrictions
  #    under which this software is provided.
  #
! #1.10 92/11/26
  MAKEDEV=%%MAKEDEV%%
! LIBDIR=%%LIBDIR%%
  if [ "$1" = "-i" ]
  then
      install=1
***************
*** 37,43 ****
      else
  	srcfont=$Targ
      fi
!     echo "PROCESSING $i: width=$width, psroff widths: $srcfont"
      if [ -z "$width" ]
      then
  	echo "Something wrong with $i entry, skipping (no width)"
--- 32,38 ----
      else
  	srcfont=$Targ
      fi
!     echo "CHECKING $i: width=$width, psroff widths: $srcfont"
      if [ -z "$width" ]
      then
  	echo "Something wrong with $i entry, skipping (no width)"
***************
*** 56,61 ****
--- 51,61 ----
      fi
      if [ -z "$install" ]
      then
+ 	if [ ! -r $MAKEDEV ]
+ 	then
+ 	    echo "No MAKEDEV ($MAKEDEV) skipping"
+ 	    continue
+ 	fi
  	if [ -r $dir/ditdone ]
  	then
  	    continue
***************
*** 67,72 ****
--- 67,73 ----
  	$MAKEDEV DESC
  	cd ..
      else
+ 	groffpostpro=''
  	if [ -n "$Garg" ]
  	then
  	    if [ ! -d %%GFONTDIR%% ]
***************
*** 76,81 ****
--- 77,83 ----
  	    else
  		echo "H'm, looks like groff width tables in %%GFONTDIR%%"
  		destdir=%%GFONTDIR%%/dev$width
+ 		groffpostpro=$LIBDIR/troff2ps_$width
  	    fi
  	else
  	    destdir=%%FONTDIR%%/dev$width
***************
*** 83,89 ****
--- 85,93 ----
  	if [ ! -d $destdir ]
  	then
  	    mkdir $destdir
+ 	    chmod 755 $destdir
  	    echo "Psroff-built width tables" > $destdir/PSROFF-BUILT
+ 	    chmod 644 $destdir/PSROFF-BUILT
  	fi
  	if [ ! -w $destdir ]
  	then
***************
*** 109,114 ****
--- 113,131 ----
  	then
  	    echo "INSTALLING ditroff widths from $dir into $destdir"
  	    cp $list $destdir
+ 	    chmod 644 $destdir/*
+ 	    if [ -n "$groffpostpro" ]
+ 	    then
+ 		echo "  inserting groff postpro line into $destdir/DESC"
+ 		sed -e "/font/a\\
+ postpro $groffpostpro" $destdir/DESC > /tmp/$$
+ 		mv /tmp/$$ $destdir/DESC
+ 		chmod 644 $destdir/DESC
+ 		echo "   installing groff postprocessor in $LIBDIR"
+ 		rm -f $groffpostpro
+ 		echo "$LIBDIR/troff2ps $t2arg" > $groffpostpro
+ 		chmod 755 $groffpostpro
+ 	    fi
  	fi
  	cd ../
      fi
Index: ./utils/Makefile
*** /tmp/PATCHold/./utils/Makefile	Thu Nov 26 23:33:37 1992
--- ./utils/Makefile	Thu Nov 26 23:33:38 1992
***************
*** 4,10 ****
  #    See the LICENSE file for a full description of the restrictions
  #    under which this software is provided.
  #
! #2.11 92/05/19
  SCRIPTS	= psdtwd showfont mkenctab calcfonts catconv dodps
  PROGRAMS = hpinterp psxlate pk2sfp pk2ditwid pktype dumpft pk2ps lj2ps \
  	asc2ps
--- 4,10 ----
  #    See the LICENSE file for a full description of the restrictions
  #    under which this software is provided.
  #
! #2.12 92/10/30
  SCRIPTS	= psdtwd showfont mkenctab calcfonts catconv dodps
  PROGRAMS = hpinterp psxlate pk2sfp pk2ditwid pktype dumpft pk2ps lj2ps \
  	asc2ps
***************
*** 36,42 ****
  	rm -f T
  
  #	This isn't perfect, but close
! ../debug.o ../pk.o ../cattab.o: ../defs.h ../pk.h
  	@echo "Some troff2ps objects are out of date"
  	@echo "Make troff2ps at the top level first"
  	exit
--- 36,42 ----
  	rm -f T
  
  #	This isn't perfect, but close
! ../debug.o ../pk.o ../cattab.o ../pkscale.o: ../defs.h ../pk.h
  	@echo "Some troff2ps objects are out of date"
  	@echo "Make troff2ps at the top level first"
  	exit
Index: ./utils/catconv.S
*** /tmp/PATCHold/./utils/catconv.S	Thu Nov 26 23:33:48 1992
--- ./utils/catconv.S	Thu Nov 26 23:33:49 1992
***************
*** 10,16 ****
  #
  #	This does a very simpleminded conversion of ditroff-only-isms
  #	(such as graphics) into something handleable by CAT troff.
! #	1.11 92/06/02
  $cc{'em'}=1; $cc{'ru'}=1; $cc{'14'}=1; $cc{'12'}=1; $cc{'hy'}=1;
  $cc{'34'}=1; $cc{'fi'}=1; $cc{'fl'}=1; $cc{'ff'}=1; $cc{'ct'}=1;
  $cc{'Fl'}=1; $cc{'Fi'}=1; $cc{'de'}=1; $cc{'dg'}=1; $cc{'rg'}=1;
--- 10,16 ----
  #
  #	This does a very simpleminded conversion of ditroff-only-isms
  #	(such as graphics) into something handleable by CAT troff.
! #	1.12 92/11/26
  $cc{'em'}=1; $cc{'ru'}=1; $cc{'14'}=1; $cc{'12'}=1; $cc{'hy'}=1;
  $cc{'34'}=1; $cc{'fi'}=1; $cc{'fl'}=1; $cc{'ff'}=1; $cc{'ct'}=1;
  $cc{'Fl'}=1; $cc{'Fi'}=1; $cc{'de'}=1; $cc{'dg'}=1; $cc{'rg'}=1;
***************
*** 114,120 ****
  	    } else {
  		printf STDERR "Don't know the width of \\($char";
  	    }
! 	    $newline .= "\\ka\\o'\\(bs\\(bs'C$char\\(bs\\h'|\\nau+\\w'$w''";
  	}
      }
      $newline .= $line;
--- 114,120 ----
  	    } else {
  		printf STDERR "Don't know the width of \\($char";
  	    }
! 	    $newline .= "\\ka\\o'\\(bs\\(bs'C$char\\(bs\\h'|\\nau+\\w\"$w\"'";
  	}
      }
      $newline .= $line;
Index: ./utils/pk2ditwid.c
*** /tmp/PATCHold/./utils/pk2ditwid.c	Thu Nov 26 23:33:57 1992
--- ./utils/pk2ditwid.c	Thu Nov 26 23:33:58 1992
***************
*** 10,16 ****
  
  #ifndef	lint
  static char SCCSID[] =
!     "@(#)pk2ditwid.c 2.4 Copyright 91/12/26 17:59:20 Chris Lewis";
  #endif
  
  #include "defs.h"
--- 10,16 ----
  
  #ifndef	lint
  static char SCCSID[] =
!     "@(#)pk2ditwid.c 2.5 Copyright 92/11/26 19:45:39 Chris Lewis";
  #endif
  
  #include "defs.h"
***************
*** 132,137 ****
--- 132,139 ----
  	    fprintf(fout, "# %s\n", buf);
  	    fprintf(fout, "# Generated by pk2ditwid\n");
  	    fprintf(fout, "name %s\n", buf);
+ 	    if (buf[0] == 'S')
+ 		fprintf(fout, "special\n");
  	    fprintf(fout, "spacewidth 22\n");
  	    fprintf(fout, "charset\n");
  	}
***************
*** 179,185 ****
  		fprintf(fout, "%s\t%ld\t%d\t",
  		    et->e_name, et->e_wid & 0x3f, (et->e_wid>>6)&0x3);
  		for (pp = et->e_seq; *pp; pp++)
! 		    fprintf(fout, "\\%03o", (*pp)&0xff);
  		fprintf(fout, "\n");
  	    }
  	}
--- 181,187 ----
  		fprintf(fout, "%s\t%ld\t%d\t",
  		    et->e_name, et->e_wid & 0x3f, (et->e_wid>>6)&0x3);
  		for (pp = et->e_seq; *pp; pp++)
! 		    fprintf(fout, "%04o", (*pp)&0xff);
  		fprintf(fout, "\n");
  	    }
  	}
Index: ./dt.c
*** /tmp/PATCHold/./dt.c	Thu Nov 26 23:34:08 1992
--- ./dt.c	Thu Nov 26 23:34:10 1992
***************
*** 12,18 ****
  
  #ifndef	lint
  static char SCCSid[] =
!     "@(#)dt.c: 2.13 Copyright 91/11/22 03:55:58 Chris Lewis";
  #endif
  
  /*	These two tables are always included so that we have the
--- 12,18 ----
  
  #ifndef	lint
  static char SCCSid[] =
!     "@(#)dt.c: 2.14 Copyright 92/11/26 23:31:01 Chris Lewis";
  #endif
  
  /*	These two tables are always included so that we have the
***************
*** 420,425 ****
--- 420,428 ----
  	return;
      }
  
+     DBP((D_BEND, "font, pfont, flags, seq = %d,%d,%02x,%s\n",
+ 	font, pfont, fonttable[pfont].flags, sequence));
+ 
      /*	We're committed now - the "if" statements avoid floating
  	arithmetic on slow machines */
  
***************
*** 432,438 ****
  #ifdef DTOPT
  	checknl();
  #endif /* DTOPT */
! 	printf("x font %d %s\n", font+1, fonttable[pfont].troffName);
  	fonttable[pfont].flags |= MOUNTED;
  	lastFont = 9999;
      }
--- 435,441 ----
  #ifdef DTOPT
  	checknl();
  #endif /* DTOPT */
! 	printf("x font %d %s\n", pfont+1, fonttable[pfont].troffName);
  	fonttable[pfont].flags |= MOUNTED;
  	lastFont = 9999;
      }
***************
*** 444,453 ****
  #endif /* DTOPT */
  
  	fonttable[pfont].flags |= USED;
! 	printf("f%d\n", font+1);
  	printf("s%d\n", points);
  	lastPoints = points;
! 	lastFont = font;
      }
  
  #ifndef DTOPT
--- 447,456 ----
  #endif /* DTOPT */
  
  	fonttable[pfont].flags |= USED;
! 	printf("f%d\n", pfont+1);
  	printf("s%d\n", points);
  	lastPoints = points;
! 	lastFont = pfont;
      }
  
  #ifndef DTOPT
***************
*** 591,596 ****
--- 594,600 ----
  
  dtEpilog() {
  
+     int i;
  #ifdef DTOPT
      checknl();
  #endif /* DTOPT */
***************
*** 599,604 ****
--- 603,613 ----
      printf("x stop\n");
  #ifndef	NOCHATTER
      printf("#Pages: %d\n", currentPage);
+     printf("#FontsUsed:");
+     for (i = 0; i < MAXFONTS; i++)
+ 	if (fonttable[i].flags&USED)
+ 	    printf(" %s", fonttable[i].fontName);
+     putchar('\n');
  #endif
  }
  
Index: ./ps.c
*** /tmp/PATCHold/./ps.c	Thu Nov 26 23:34:23 1992
--- ./ps.c	Thu Nov 26 23:34:26 1992
***************
*** 15,21 ****
  
  #ifndef	lint
  static char SCCSid[] =
!     "@(#)ps.c: 2.20 Copyright 92/06/01 21:18:19 Chris Lewis";
  #endif
  
  /*	ps.c will generate some additional "print" commands to cause
--- 15,21 ----
  
  #ifndef	lint
  static char SCCSid[] =
!     "@(#)ps.c: 2.21 Copyright 92/11/26 19:41:28 Chris Lewis";
  #endif
  
  /*	ps.c will generate some additional "print" commands to cause
***************
*** 362,368 ****
  register char *sequence; {
      putchar('(');
      while(*sequence) {
! 	if ((*sequence)&0x80)
  	    printf("\\%03o", (*sequence++)&0xff);
  	else if (*sequence == '(' || *sequence == ')' ||
  	    *sequence == '\\')
--- 362,368 ----
  register char *sequence; {
      putchar('(');
      while(*sequence) {
! 	if (((*sequence)&0x80) || (*sequence < ' '))
  	    printf("\\%03o", (*sequence++)&0xff);
  	else if (*sequence == '(' || *sequence == ')' ||
  	    *sequence == '\\')
Index: ./defs.h
*** /tmp/PATCHold/./defs.h	Thu Nov 26 23:34:39 1992
--- ./defs.h	Thu Nov 26 23:34:41 1992
***************
*** 9,15 ****
   */
  
  /*	Official Release and Patch level:	*/
! #define	T2VERSION	"@(#)PSROFF Copyright 92/07/09 Chris Lewis - R3 PL13"
  
  /*	Configuration parameters:
   */
--- 9,15 ----
   */
  
  /*	Official Release and Patch level:	*/
! #define	T2VERSION	"@(#)PSROFF Copyright 92/10/30 Chris Lewis - R3 PL14"
  
  /*	Configuration parameters:
   */
***************
*** 133,138 ****
--- 133,140 ----
  #define	DT	/* ditroff */
  
  /*	Laserjet driver config: */
+ #define PKSCALE	/* enable lj font built-in scaling.  Needs PK */
+ 
  #define	PK	/* enable PK font downloading (needs LJ) */
  
  #define	SFP	/* enable SFP incremental font downloading (needs PK).
***************
*** 218,223 ****
--- 220,229 ----
  #endif
  
  #if	!defined(LJ) && defined(PK)
+ #include	"Pointless to define PK without LJ"
+ #endif
+ 
+ #if	!defined(PK) && defined(PKSCALE)
  #include	"Pointless to define PK without LJ"
  #endif
  
Index: ./Makefile
*** /tmp/PATCHold/./Makefile	Thu Nov 26 23:34:53 1992
--- ./Makefile	Thu Nov 26 23:34:55 1992
***************
*** 7,13 ****
  #    Function: Upper level makefile; configuration options.
  #
  #
! #ident  "@(#)Makefile: 2.34 Copyright 92/07/09 23:36:01 Chris Lewis"
  
  #	If you're not sure whether you have a System V make, leave
  #	this alone, and run the make anyways.  If it dies horribly
--- 7,13 ----
  #    Function: Upper level makefile; configuration options.
  #
  #
! #ident  "@(#)Makefile: 2.35 Copyright 92/10/30 02:28:20 Chris Lewis"
  
  #	If you're not sure whether you have a System V make, leave
  #	this alone, and run the make anyways.  If it dies horribly
***************
*** 110,116 ****
  
  #	Compile flags needed to compile things on your machine.
  #	Usually just -O.  May need to tell gcc that this isn't
! #	Posix compliant code.
  #
  CCFLAGS = -O
  
--- 110,116 ----
  
  #	Compile flags needed to compile things on your machine.
  #	Usually just -O.  May need to tell gcc that this isn't
! #	Posix compliant code.  RISC Ultrix needs "-Olimit 600".
  #
  CCFLAGS = -O
  
***************
*** 181,187 ****
  
  #	Drivers:
  
! BACKENDS = lj.o pk.o pkc.o ljdraw.o lj3draw.o ps.o dt.o dit.o
  
  DEFINES	= '-DLIBDIR="$(LIBDIR)/lib"' '-DFONTDIR="$(FONTDIR)"'\
  	'-DLJF="$(LJF)"' $(CCFLAGS)
--- 181,187 ----
  
  #	Drivers:
  
! BACKENDS = lj.o pk.o pkc.o pkscale.o ljdraw.o lj3draw.o ps.o dt.o dit.o
  
  DEFINES	= '-DLIBDIR="$(LIBDIR)/lib"' '-DFONTDIR="$(FONTDIR)"'\
  	'-DLJF="$(LJF)"' $(CCFLAGS)
***************
*** 212,218 ****
  CFLAGS	= $(DEFINES)
  
  all:	troff2ps myuid subst.done makeincl psroff README TROUBLE LASERFONTS \
! 	MISC DITROFF INSTALL LICENSE LJIII zap pkscale.o submakes
  
  subst.done:	sedscript
  	rm -f psroff makeincl
--- 212,218 ----
  CFLAGS	= $(DEFINES)
  
  all:	troff2ps myuid subst.done makeincl psroff README TROUBLE LASERFONTS \
! 	MISC DITROFF INSTALL LICENSE LJIII zap submakes
  
  subst.done:	sedscript
  	rm -f psroff makeincl
***************
*** 300,305 ****
--- 300,323 ----
  	@echo "don't panic if the next line dies"
  	$(IGNORESH) test -z "$(PKFONTS)" -o ! -d "$(NEWFONTS)" \
  	    || cp $(NEWFONTS)/* $(LJF)
+ 
+ scaleljfonts: myuid
+ 	test "`./myuid`" = 0 || \
+ 	    ( echo "ERROR: You must be root to scale LJ fonts" ; exit 1 )
+ 	[ -r $(LIBDIR)/lib/lj/R.10.pk ] || \
+ 	    ( echo "ERROR: Laserjet fonts not installed" ; exit 1 )
+ 	cd $(LIBDIR)/lib/lj ; \
+ 	    for i in *.10.* ; \
+ 	    do \
+ 		b=`basename $$i .10.sfp` ; \
+ 		b=`basename $$i .10.pk` ; \
+ 		for j in 6 7 8 9 11 12 14 16 18 20 22 24 28 36 ; \
+ 		do \
+ 		    [ -r $$b.$$j.pk ] && continue ; \
+ 		    echo "Making $$b.$$j.sfp" ; \
+ 		    $(LIBDIR)/pk2sfp -o $$j $$i > $$b.$$j.sfp ; \
+ 		done ; \
+ 	    done
  
  register:
  	make troff2ps makeincl
Index: ./opt.c
*** /tmp/PATCHold/./opt.c	Thu Nov 26 23:35:17 1992
--- ./opt.c	Thu Nov 26 23:35:18 1992
***************
*** 23,29 ****
  #ifdef	OPT
  #ifndef	lint
  static char SCCSid[] =
!     "@(#)opt.c: 2.12 Copyright 92/06/01 21:16:34 Chris Lewis";
  #endif
  
  struct insbuf {
--- 23,29 ----
  #ifdef	OPT
  #ifndef	lint
  static char SCCSid[] =
!     "@(#)opt.c: 2.13 Copyright 92/10/30 02:25:40 Chris Lewis";
  #endif
  
  struct insbuf {
***************
*** 81,92 ****
--- 81,96 ----
  
      if (insptr->xpos < insbuf[0].xpos) {
  	DBP((D_CAT, "canonflush: BACK (%d chars)\n", insptr - insbuf + 1));
+ #if defined(DEBUG)
  	insdump(insbuf, insptr);
+ #endif
  	for(ip = insptr;ip >= insbuf; ip--)
  	    canonchar(ip->xpos, insypos, ip->font, ip->points, ip->nc);
      } else {
  	DBP((D_CAT, "canonflush: FORW (%d chars)\n", insptr - insbuf + 1));
+ #if defined(DEBUG)
  	insdump(insbuf, insptr);
+ #endif
  	for(ip = insbuf;ip <= insptr; ip++)
  	    canonchar(ip->xpos, insypos, ip->font, ip->points, ip->nc);
      }
***************
*** 356,361 ****
--- 360,366 ----
  }
  #endif
  
+ #if defined(DEBUG)
  insdump(b, p)
  register struct insbuf *b, *p; {
      if (!(debug&D_VERB))
***************
*** 364,366 ****
--- 369,372 ----
      for(; b <= p; b++)
  	DBP((D_VERB, "%d %d\n", b->xpos, b->nc));
  }
+ #endif
Index: ./lj.c
*** /tmp/PATCHold/./lj.c	Thu Nov 26 23:35:30 1992
--- ./lj.c	Thu Nov 26 23:35:32 1992
***************
*** 32,38 ****
  
  #ifndef	lint
  static char SCCSid[] =
!     "@(#)lj.c: 2.11 Copyright 92/01/28 22:50:03 Chris Lewis";
  #endif
  
  struct troff2befont ljStdFont[108] = {
--- 32,38 ----
  
  #ifndef	lint
  static char SCCSid[] =
!     "@(#)lj.c: 2.13 Copyright 92/11/26 19:43:30 Chris Lewis";
  #endif
  
  struct troff2befont ljStdFont[108] = {
***************
*** 304,310 ****
  int fontCount = 0;
  
  ljPage() {
!     printf("\033&l0H");
      pagePending = 1;
  }
  
--- 304,313 ----
  int fontCount = 0;
  
  ljPage() {
!     if (!pagePending) {
! 	emitrast();
! 	printf("\033&l0H");
!     }
      pagePending = 1;
  }
  
***************
*** 385,390 ****
--- 388,430 ----
      return (points);
  }
  
+ #ifdef PKSCALE
+ static int
+ scalematch(font, points, type)
+ int font, points;
+ char *type; {
+     register char *p;
+     register int i, t;
+ 
+     p = fonttable[font].fontFlags;
+ 
+     for (i = points; i <= 36; i++)
+ 	switch(t = p[ptcvt(i)]) {
+ 	    case 'S':
+ 	    case 'P':
+ 		t = tolower(t);
+ 	    case 's':
+ 	    case 'p':
+ 		*type = t;
+ 		return(i);
+ 	}
+ 
+     for (i = points; i >= 6; i--)
+ 	switch(t = p[ptcvt(i)]) {
+ 	    case 'S':
+ 	    case 'P':
+ 		t = tolower(t);
+ 	    case 's':
+ 	    case 'p':
+ 		*type = t;
+ 		return(i);
+ 	}
+ 
+     return(-1);
+ }
+ #endif
+ 
+ 
  #ifdef	INCR
  dumpseq(font, pointidx, seq)
  int font, pointidx;
***************
*** 431,436 ****
--- 471,477 ----
      extern FILE *popen();
      register char *pf, *p;
      register struct pkp *pk;
+     char resulttype;
  #if	!defined(INCR) && defined(PK)
      register struct pkc *pc;
  #endif
***************
*** 438,443 ****
--- 479,485 ----
  #ifndef	PARTIAL
      FILE *fontfile;
  #endif
+     int scalepoints;
      int count;
      int ftid;
  
***************
*** 451,468 ****
  	return;
  #endif
  
      points = bestmatch(font, selpoints);
      pointidx = ptcvt(points);
  
      pf = &fonttable[font].fontFlags[pointidx];
      ftid = (font << 4) + pointidx;
  
! #ifdef	INCR
  #ifdef	SFP
!     if (*pf == 'S' || *pf == 'P') {
! #else
!     if (*pf == 'P') {
  #endif
  	/* header downloaded, check and download individual characters */
  	dumpseq(font, pointidx, sequence);
  
--- 493,517 ----
  	return;
  #endif
  
+ #ifdef PKSCALE
+     points = selpoints;
+ #else
      points = bestmatch(font, selpoints);
+ #endif
      pointidx = ptcvt(points);
  
      pf = &fonttable[font].fontFlags[pointidx];
      ftid = (font << 4) + pointidx;
  
! #if defined(INCR) || defined(SFP) || defined(PKSCALE)
!     if (
! #ifdef	PKSCALE
! 	*pf == 'N' ||
! #endif
  #ifdef	SFP
! 	*pf == 'S' ||
  #endif
+ 	*pf == 'P') {
  	/* header downloaded, check and download individual characters */
  	dumpseq(font, pointidx, sequence);
  
***************
*** 484,490 ****
      lastPoints = selpoints;
      lastFont = font;
  
!     switch(*pf) {
  #ifdef	PK
  	case 'p':
  #ifdef	PARTIAL
--- 533,549 ----
      lastPoints = selpoints;
      lastFont = font;
  
!     scalepoints = points;
! 
!     switch(resulttype = *pf) {
! #ifdef	PKSCALE
! 	case 'n':
! 	    scalepoints = scalematch(font, points, &resulttype);
! 	    /* on a successful call, *pf is now either "s" or
! 	       "p".  */
! 	    DBP((D_FONT,"Scale select %s.%d via '%d' points (%c)\n",
! 		fonttable[font].troffName, points, scalepoints, *pf));
! #endif
  #ifdef	PK
  	case 'p':
  #ifdef	PARTIAL
***************
*** 491,498 ****
  	case 's':
  #endif
  	    sprintf(buf, "%s/%s.%d.%s", LJF,
! 		fonttable[font].troffName, points,
! 		    (*pf == 's') ? "sfp":"pk");
  
  	    fontCount++;
  	    if (fontCount >= MAXDLFONTS) {
--- 550,557 ----
  	case 's':
  #endif
  	    sprintf(buf, "%s/%s.%d.%s", LJF,
! 		fonttable[font].troffName, scalepoints,
! 		(resulttype == 's') ? "sfp":"pk");
  
  	    fontCount++;
  	    if (fontCount >= MAXDLFONTS) {
***************
*** 508,514 ****
  		points, buf));
  
  	    /* Read the PK file in-core */
! 	    pk = pk_read(buf,fontcode);
  
  	    /* Set the fontid we'll use */
  	    printf("\033*c%dd4F", ftid);
--- 567,582 ----
  		points, buf));
  
  	    /* Read the PK file in-core */
! 	    pk = pk_read(buf, fontcode);
! 
! #ifdef	PKSCALE
! 	    if (scalepoints != points) {
! 		DBP((D_FONT, "SCALE %d->%d (font thinks it's %d)\n",
! 		    scalepoints, points, pk->pkp_npts));
! 		pk = pkscale(pk, points);	/* destroys old PK */
! 		DBP((D_FONT, "font now thinks it's %d\n", pk->pkp_npts));
! 	    }
! #endif
  
  	    /* Set the fontid we'll use */
  	    printf("\033*c%dd4F", ftid);
***************
*** 597,606 ****
  #endif
  	    /* Fall Thru */
  
! 	case 'S': case 'P':
  	    /* Select primary font by font id */
  	setdownloaded:
! 	    DBP((D_FONT, "Selecting font2 %d\n", ftid));
  	    printf("\033(%dX", ftid);
  	    break;
  
--- 665,674 ----
  #endif
  	    /* Fall Thru */
  
! 	case 'S': case 'P': case 'N':
  	    /* Select primary font by font id */
  	setdownloaded:
! 	    DBP((D_FONT, "Selecting fontid %d\n", ftid));
  	    printf("\033(%dX", ftid);
  	    break;
  
***************
*** 624,635 ****
  
  static fixpoints(points)
  int points; {
!     static char ptab[30] = {
  	 6,  7,  8,  9, 10, 11,
  	12, 12, 14, 14, 16, 16,
  	18, 18, 20, 20, 22, 22,
  	24, 24, 24, 28, 28, 28,
! 	28, 28, 28, 28, 36, 36};
  
      if (points < 6)
  	return(6);
--- 692,704 ----
  
  static fixpoints(points)
  int points; {
!     static char ptab[31] = {
  	 6,  7,  8,  9, 10, 11,
  	12, 12, 14, 14, 16, 16,
  	18, 18, 20, 20, 22, 22,
  	24, 24, 24, 28, 28, 28,
! 	28, 28, 28, 28, 36, 36,
! 	36};
  
      if (points < 6)
  	return(6);
***************
*** 748,767 ****
      for (c = 0; fonttable[c].troffName; c++) {
  	register int i;
  	for (i = 0, p = fonttable[c].fontFlags; *p; p++, i++)
! #ifdef	SFP
! 	    if (*p == 'p' || *p == 's') {
  #else
! 	    if (*p == 'p') {
  #endif
! 		DBP((D_FONT, "Allocating font %d, size %d\n",
! 		    c, i));
! 		if (!fonttable[c].map) {
! 		    fonttable[c].map = (struct downmaps *)
! 			mustmalloc(sizeof(struct downmaps), "downmaps");
! 		}
! 		fonttable[c].map->nm[i] = (ETYP *) mustmalloc(ELEN *
! 		    sizeof(ETYP), "Nmaps");
! 		fonttable[c].map->lastpage[i] = 0;
  	    }
      }
  
--- 817,842 ----
      for (c = 0; fonttable[c].troffName; c++) {
  	register int i;
  	for (i = 0, p = fonttable[c].fontFlags; *p; p++, i++)
! 	    switch(*p) {
! 		case 'n':
! #ifndef PKSCALE	
! 		    break;
  #else
! 		    /* FALLTHRU */
  #endif
! #ifdef	SFP
! 		case 's':
! #endif
! 		case 'p':
! 		    DBP((D_FONT, "Allocating font %d, size %d\n",
! 			c, i));
! 		    if (!fonttable[c].map) {
! 			fonttable[c].map = (struct downmaps *)
! 			    mustmalloc(sizeof(struct downmaps), "downmaps");
! 		    }
! 		    fonttable[c].map->nm[i] = (ETYP *) mustmalloc(ELEN *
! 			sizeof(ETYP), "Nmaps");
! 		    fonttable[c].map->lastpage[i] = 0;
  	    }
      }
  
Index: ./ljdraw.c
*** /tmp/PATCHold/./ljdraw.c	Thu Nov 26 23:35:49 1992
--- ./ljdraw.c	Thu Nov 26 23:35:52 1992
***************
*** 6,13 ****
      this software is provided.
  
      Function:		LaserJet driver, drawing code.
! 
! 			Needs LJII or later (rules)
  
  */
  
--- 6,26 ----
      this software is provided.
  
      Function:		LaserJet driver, drawing code.
! 			Needs LJII (actually PCL4) or later (rules)
!     
!     Currently supports:
! 	line thickness set
! 	fill set
! 	circle & ellipse, c&e fill
! 	lines
! 	polygons
! 	splines
!     
!     TODO: 
! 	- polyfill.  Polyfill probably never unless somebody
! 	  gives me a polygon fill algorithm (hint hint!)
! 	- optimize emitrast some more.  (wastes up to 25 bytes per subsequent
! 	  raster line where the start point is within 2/3 inch.)
  
  */
  
***************
*** 15,24 ****
  
  #if	defined(LJ) && defined(INSPECIAL)
  #include "lj.h"
  
  #ifndef	lint
  static char SCCSid[] =
!     "@(#)ljdraw.c: 1.1 Copyright 92/01/23 14:26:18 Chris Lewis";
  #endif
  
  static int ljLine();
--- 28,38 ----
  
  #if	defined(LJ) && defined(INSPECIAL)
  #include "lj.h"
+ #include "math.h"
  
  #ifndef	lint
  static char SCCSid[] =
!     "@(#)ljdraw.c: 1.2 Copyright 92/11/26 19:39:27 Chris Lewis";
  #endif
  
  static int ljLine();
***************
*** 25,38 ****
  
  /*	Do ditroff drawing command in s from origX,origY.
  	If opcode 0 just moveto
- 
- 	This is hardly complete.  Consider it a skeleton
- 	for further work.  Before extending it beyond
- 	horizontal and vertical lines, I'm going to switch
- 	the whole driver over to 300ths from 720ths.
- 	Which should eliminate a little jitter, and removes
- 	a lot of excess work in line drawing.
   */
  ljDraw(origX, origY, opcode, ctindex, numbers, saves)
  int origX, origY;
  int opcode;
--- 39,59 ----
  
  /*	Do ditroff drawing command in s from origX,origY.
  	If opcode 0 just moveto
   */
+ 
+ int curthick = 1;	/* half of current thickness */
+ int curfill = 0;	/* solid black 1000 is solid white */
+ 
+ int drawDot();
+ #define sqr(x)	((x) * (x))
+ 
+ static long	rastcount, total;
+ 
+ #ifndef M_PI
+ #define	M_PI	3.141529
+ #endif
+ #define	RAD_C	(M_PI*2)
+ 
  ljDraw(origX, origY, opcode, ctindex, numbers, saves)
  int origX, origY;
  int opcode;
***************
*** 40,49 ****
  int ctindex;
  short *numbers; {
  
!     int i, fill = 0;
!     static float curfill = 0;
!     static int curthick = 1;
!     static int warned = 0;
  
      /* map absolute beginning position. */
      origX = TROFF2LJX(origX);
--- 61,67 ----
  int ctindex;
  short *numbers; {
  
!     int i;
  
      /* map absolute beginning position. */
      origX = TROFF2LJX(origX);
***************
*** 50,192 ****
      origY = TROFF2LJY(origY);
  
      if (!opcode) {
! 	printf(XY, origX, origY);
! 	lastYPos = origY;
  	return;
      }
  
-     if (opcode != 'l')
- 	if (!warned) {
- 	    fprintf(stderr, "%s: only lines are currently supported\n", progname);
- 	    warned = 1;
- 	    return;
- 	}
- 
      switch (opcode) {
  	case 'f':
  	    if (ctindex == 2)
  		ctindex = 1;
! 	    if (!require(1, ctindex, "set fill", saves))
! 		curfill = (double) numbers[0] / 1000;
  	    return;
  	case 't':
  	    if (ctindex == 2)
  		ctindex = 1;
! 	    if (!require(1, ctindex, "set thick", saves))
! 		curthick = numbers[0];
  	    return;
      }
  
- 
      DBP((D_CAT, "ljDraw: (%d,%d): %s\n", origX, origY, saves));
  
      switch (opcode) {
! 	case 'C':
  	    if (ctindex == 2)
  		ctindex = 1;
- 	case 'E':
- 	case 'P':
- 	    fill = 1;
- 	    if (opcode != 'P')
- 		break;
- 	case 'l':
- 	case 'a':
- 	case 'p':
- 	case '~':
- 	    for (i = 0; i < ctindex; i++)
- 		numbers[i] = numbers[i] * LJRESOLUTION / TROFFRESOLUTION;
      }
      switch(opcode) {
  	case 'l':
  	    if (require(2, ctindex, "line", saves))
  		return;
- 	    DBP((D_CAT, "drawline: %d, %d\n", numbers[0], numbers[1]));
  	    ljLine(origX, origY, origX + numbers[0], origY + numbers[1]);
! 	    break;
! #if	0
! 	case 'a':
! 	    if (require(4, ctindex, "arc", saves))
! 		return;
! 	    for (i = 0; i < 4; i++) {
! 		emitnums(numbers[i]);
! 	    }
! 	    putnl("Arc");
! 	    break;
  	case 'C':
  	case 'c':
  	    if (require(1, ctindex, "circle", saves))
  		return;
  	    numbers[1] = numbers[0];
! 	    ctindex++;
  	case 'E':
  	case 'e':
  	    if (require(2, ctindex, "ellipse", saves))
  		return;
! 	    DBP((D_CAT, "drawellipse: %d, %d\n", numbers[0], numbers[1]));
! 	    emitnums((int) numbers[0]);
! 	    emitnums((int) numbers[1]);
! 	    putnl("Ellipse");
! 	    break;
  	case 'P':
  	case 'p':
  	    if (ctindex&1) {
! 		fprintf(stderr, "%s: even number of points for polygon: %s\n",
  		    progname, saves);
! 		break;
! 	    }
! 	    for (i = 0; i < ctindex; i += 2) {
! 		emitnums((int) numbers[i]);
! 		emitnums((int) numbers[i+1]);
! 		putnl("rlineto");
  	    }
! 	    putnl(" closepath");
! 	    break;
! 	case '~':
! 	    if (ctindex < 4) {
! 		fprintf(stderr, "%s: too few points to spline: %s\n",
  		    progname, saves);
! 		break;
! 	    }
! 	    emitnums(numbers[0]/2);
! 	    emitnums(numbers[1]/2);
! 	    putnl("rlineto");
! 	    /* NUM/DEN should be between 0 and 1; the closer it is to 1
! 		the tighter the curve will be to the guiding lines; 2/3
! 		is the standard value */
! #define	NUM	2
! #define	DEN	3
! 	    for (i = 0; i < ctindex - 2; i += 2) {
! 		emitnums((numbers[i]*NUM)/(2*DEN));
! 		emitnums((numbers[i + 1]*NUM)/(2*DEN));
! 		emitnums(numbers[i]/2 + (numbers[i + 2]*(DEN - NUM))/(2*DEN));
! 		emitnums(numbers[i + 1]/2 + (numbers[i + 3]*(DEN - NUM))/(2*DEN));
! 		emitnums((numbers[i] - numbers[i]/2) + numbers[i + 2]/2);
! 		emitnums((numbers[i + 1] - numbers[i + 1]/2) + numbers[i + 3]/2);
! 		putnl("rcurveto");
  	    }
! 	    emitnums(numbers[ctindex - 2] - numbers[ctindex - 2]/2);
! 	    emitnums(numbers[ctindex - 1] - numbers[ctindex - 1]/2);
! 	    putnl("rlineto");
! 	    break;
! #endif
  	default:
  	    fprintf(stderr, "%s: invalid draw code %c (%s)\n", progname, opcode,
  		saves);
! 	    break;
      }
  }
  
! static
! linwid() {
!     register int a;
!     a = lastPoints / 4;
!     if (!a)
! 	a = 1;
!     else if (a > 10)
! 	a = 10;
!     return(a);
  }
!     
  
  static ljPos(x, y)
  register int x, y; {
--- 68,246 ----
      origY = TROFF2LJY(origY);
  
      if (!opcode) {
! 	ljPos(origX, origY);
  	return;
      }
  
      switch (opcode) {
  	case 'f':
  	    if (ctindex == 2)
  		ctindex = 1;
! 	    if (!require(1, ctindex, "set fill", saves)) {
! 		curfill = numbers[0];
! 		if (curfill < 0)
! 		    curfill = 0;
! 		if (curfill > 1000)
! 		    curfill = 1000;
! 		DBP((D_PIC, "FILL: %d\n", curfill));
! 	    }
  	    return;
  	case 't':
  	    if (ctindex == 2)
  		ctindex = 1;
! 	    if (!require(1, ctindex, "set thick", saves)) {
! 		curthick = numbers[0] / 2;
! 		if (curthick < 1)
! 		    curthick = 1;
! 		DBP((D_PIC, "THICK: %d\n", curthick));
! 	    }
  	    return;
      }
  
      DBP((D_CAT, "ljDraw: (%d,%d): %s\n", origX, origY, saves));
  
      switch (opcode) {
! 	case 'C': case 'c':
  	    if (ctindex == 2)
  		ctindex = 1;
      }
+ 
+     for (i = 0; i < ctindex; i++)
+ 	numbers[i] = numbers[i] * LJRESOLUTION / TROFFRESOLUTION;
+ 
      switch(opcode) {
  	case 'l':
  	    if (require(2, ctindex, "line", saves))
  		return;
  	    ljLine(origX, origY, origX + numbers[0], origY + numbers[1]);
! 	    return;
! 
  	case 'C':
  	case 'c':
  	    if (require(1, ctindex, "circle", saves))
  		return;
  	    numbers[1] = numbers[0];
! 	    ljCircle(origX + numbers[0] / 2, origY, numbers[0] / 2,
! 		drawDot, opcode == 'C' ? curfill: -1);
! 	    return;
! 
  	case 'E':
  	case 'e':
  	    if (require(2, ctindex, "ellipse", saves))
  		return;
! 	    ljEllipse(origX + numbers[0] / 2, origY, numbers[0]/2, numbers[1]/2,
! 		opcode == 'E' ? curfill: -1);
! 	    return;
! 
  	case 'P':
  	case 'p':
  	    if (ctindex&1) {
! 		fprintf(stderr, "%s: need even number of points for polygon: %s\n",
  		    progname, saves);
! 		return;
  	    }
! 	    ljPoly(origX, origY, ctindex, numbers);
! 	    return;
! 
! 	case 'a':
! 	    if (require(4, ctindex, "arc", saves))
! 		return;
! 	    ljArc(origX, origY, numbers[0], numbers[1], numbers[2], numbers[3]);
! 	    return;
! 
! 	case '~': 
! 	    if (ctindex < 4 || (ctindex&1)) {
! 		fprintf(stderr, "%s: too few points to spline, or odd point count: %s\n",
  		    progname, saves);
! 		return;
  	    }
! 	    ljSpline(origX, origY, ctindex, numbers);
! 	    return;
! 	    
  	default:
  	    fprintf(stderr, "%s: invalid draw code %c (%s)\n", progname, opcode,
  		saves);
! 	    return;
      }
  }
  
! /* Can't do polygon fill.  Probably never will - needs far more
!    advanced techniques than I'm willing to do */
! 
! ljPoly(curx, cury, ctindex, numbers)
! int curx, cury, ctindex;
! short *numbers; {
!     int i;
! 
!     DBP((D_PIC, "ljPoly\n"));
! 
!     for (i = 0; i < ctindex; i += 2) {
! 	ljLine(curx, cury, curx + numbers[i], cury + numbers[i+1]);
! 	curx += numbers[i];
! 	cury += numbers[i+1];
!     }
! 
! }
! 
! int lx, ly;
! 
! ljSpline(ox, oy, ctindex, numbers)
! int ox, oy, ctindex;
! short *numbers; {
! 
!     int dx = numbers[0], dy = numbers[1];
!     int sx = ox, sy = oy, tx = sx + dx, ty = sy + dy;
!     int i;
! 
!     DBP((D_PIC, "ljSpline\n"));
! 
!     ljLine(sx, sy, lx = (sx + tx) / 2, ly = (sy + ty) / 2);
! 
!     for (i = 2; i < ctindex; i += 2) {
! 	int ux = ox + (dx += numbers[i]);
! 	int uy = oy + (dy += numbers[i+1]);
! 
! 	flatten((sx + tx*5)/6, (sy + ty*5)/6, (tx*5 + ux) / 6,
! 		(ty*5 + uy) / 6, (tx + ux) / 2, (ty + uy) / 2);
! 	sx = tx;
! 	sy = ty;
! 	tx = ux;
! 	ty = uy;
! 	}
!     ljLine(lx, ly, tx, ty);
  }
! 
! #define FLAT 1
! flatten(x2, y2, x3, y3, x4, y4)
! int x2, y2, x3, y3, x4, y4; {
! 
!     int x1 = lx, y1 = ly, dx, dy, n1, n2, n;
! 
!     dx = x4 - x1;
!     dy = y4 - y1;
! 
!     n1 = dy*(x2 - x1) - dx*(y2 - y1);
!     n2 = dy*(x3 - x1) - dx*(y3 - y1);
! 
!     if (n1 < 0)
! 	n1 = -n1;
!     if (n2 < 0)
! 	n2 = -n2;
! 
!     n = n1 > n2 ? n1 : n2;
! 
!     if (n*n / (dy*dy + dx*dx) <= FLAT*FLAT) {
! 	ljLine(lx, ly, x4, y4);
! 	lx = x4;
! 	ly = y4;
!     } else {
! 	flatten( (x1 + x2)/2, (y1 + y2)/2,
! 		  (x1 + x2*2 + x3)/4, (y1 + y2*2 + y3)/4,
! 		  (x1 +3*x2 + 3*x3 + x4)/8, (y1 +3*y2 + 3*y3 + y4)/8);
! 	flatten( (x2 + x3*2 + x4)/4, (y2 + y3*2 + y4)/4,
! 		  (x3 + x4)/2, (y3 + y4)/2, x4, y4);
!     }
! }
  
  static ljPos(x, y)
  register int x, y; {
***************
*** 194,241 ****
      lastYPos = y;
  }
  
- static
- ljHLine(x0, y0, x1, y1)
- int x0, y0, x1, y1; {
-     static int warning = 0;
-     if (!warning) {
- 	fprintf(stderr, "%s: contains non-vertical or horizontal lines.  Ignored\n",
- 	    progname);
- 	warning = 1;
-     }
- }
  
  static
  ljVerLine(x0, y0, y1)
  register int x0, y0, y1; {
-     register int t;
      if (y0 > y1) {
  	t = y0;
  	y0 = y1;
  	y1 = t;
      }
!     t = linwid();
!     ljPos(x0, y0-t+1);
!     printf("\033*c%da%db0P", t, y1-y0+t);
  }
  
  static
  ljHorLine(x0, y0, x1)
  register int x0, y0, x1; {
-     register int t = linwid();
      if (x0 > x1) {
  	t = x0;
  	x0 = x1;
  	x1 = t;
      }
!     t = linwid();
!     ljPos(x0, y0-t+1);
!     printf("\033*c%da%db0P", x1-x0+t, t);
  }
  
  static
  ljLine(x0, y0, x1, y1)
  register int x0, y0, x1, y1; {
      if (y0 == y1)
  	ljHorLine(x0, y0, x1);
      else if (x0 == x1)
--- 248,288 ----
      lastYPos = y;
  }
  
  
  static
  ljVerLine(x0, y0, y1)
  register int x0, y0, y1; {
      if (y0 > y1) {
+ 	register int t;
  	t = y0;
  	y0 = y1;
  	y1 = t;
      }
!     ljPos(x0-curthick, y0);
!     printf("\033*c%da%db0P", curthick<<1, y1-y0);
!     ljCircle (x0, y0, curthick, drawDot, 0);
!     ljCircle (x0, y1, curthick, drawDot, 0);
  }
  
  static
  ljHorLine(x0, y0, x1)
  register int x0, y0, x1; {
      if (x0 > x1) {
+ 	register int t;
  	t = x0;
  	x0 = x1;
  	x1 = t;
      }
!     ljPos(x0, y0-curthick);
!     printf("\033*c%da%db0P", x1-x0, curthick<<1);
!     ljCircle (x0, y0, curthick, drawDot, 0);
!     ljCircle (x1, y0, curthick, drawDot, 0);
  }
  
  static
  ljLine(x0, y0, x1, y1)
  register int x0, y0, x1, y1; {
+     DBP((D_PIC, "ljLine: (%d,%d)..(%d,%d), curthick: %d\n", x0, y0, x1, y1, curthick));
      if (y0 == y1)
  	ljHorLine(x0, y0, x1);
      else if (x0 == x1)
***************
*** 243,248 ****
--- 290,786 ----
      else
  	ljHLine(x0, y0, x1, y1);
  
+ }
+ 
+ #define	abs(x)	((x) < 0? -(x): (x))
+ 
+ /*	Breshenham's line drawing algorithm.
+ 	Extended to full 4 quadrant line drawing.
+ 	Uses only adds/subtracts and <<1.
+ 	Should run like the proverbial bat */
+ 
+ ljHLine(x0, y0, x1, y1)
+ int x0, y0, x1, y1; {
+     extern int rev;
+     if (abs(y1 - y0) > abs(x1 - x0)) {
+ 	rev=1;
+ 	lineseg2(y0, x0, y1, x1);
+     } else {
+ 	rev=0;
+ 	lineseg2(x0, y0, x1, y1);
+     }
+     rev = 0;
+ }
+ 
+ int rev;
+ 		
+ /* extend base algorithm to -45..45 & 135..225 */
+ lineseg2(x0, y0, x1, y1)
+ int x0, y0, x1, y1; {
+     if (x1 < x0)
+ 	lineseg(x1, y1, x0, y0);
+     else
+ 	lineseg(x0, y0, x1, y1);
+ }
+ 
+ 
+ static
+ lineseg (x0, y0, x1, y1)
+ int x0, y0, x1, y1; {
+     register int dx, dy, iE, iNE, d, x, y, ddy;
+ 
+     /* extend algorithm to -45..45 */
+     dx = x1 - x0;
+     dy = y1 - y0;
+     if (dy < 0) {
+ 	ddy = -1;
+ 	dy = -dy;
+     } else
+ 	ddy = 1;
+ 
+     /* Basic algorithm, 0..45 degrees */
+     d = 2 * dy - dx;
+     iE = 2 * dy;
+     iNE = 2 * (dy - dx);
+     x = x0;
+     y = y0;
+     linePoints(x, y);
+     while (x < x1) {
+ 	if (d <= 0) {
+ 	    d = d + iE;
+ 	    x = x + 1;
+ 	} else {
+ 	    d = d + iNE;
+ 	    x = x + 1;
+ 	    y = y + ddy;
+ 	}
+ 	linePoints(x, y);
+     }
+ }
+ 
+ /* This procedure uses second-order partial differences to compute increments
+    in the decision variable.  Assumes center of circle is at origin.
+    It actually calculates only one octant, then circlePoints maps
+    it into the rest of a circle */
+ 
+ ljCircle (origx, origy, radius, dotfcn, fill)
+ int origx, origy, radius, fill;
+ FUNC dotfcn;
+ {
+     register int x, y, d, deltaE, deltaSE;
+ 
+     DBP((dotfcn == drawDot ? D_PIC: 0, "ljCircle: (%d,%d),r%d,f%d\n",
+ 	origx, origy, radius, fill));
+ 
+     x = 0;
+     y = radius;
+     d = 1 - radius;
+     deltaE = 3;
+     deltaSE = -2 * radius + 5;
+     circlePoints(origx, origy, x, y, dotfcn, fill);
+ 
+     while (y > x) {
+ 	if (d < 0) { /* select E */
+ 	    d += deltaE;
+ 	    deltaE += 2;
+ 	    deltaSE += 2;
+ 	    x++;
+ 	} else {	/* select SE */
+ 	    d += deltaSE;
+ 	    deltaE += 2;
+ 	    deltaSE += 4;
+ 	    x++;
+ 	    y--;
+ 	}
+ 	circlePoints(origx, origy, x, y, dotfcn, fill);
+     }
+ }
+ 
+ circlePoints(ox, oy, x, y, dotfcn, fill)
+ int ox, oy, x, y, fill;
+ FUNC dotfcn; {
+     if (fill != -1) {
+ 	dofill(ox, x, oy+y, fill);
+ 	dofill(ox, x, oy-y, fill);
+ 	dofill(ox, y, oy+x, fill);
+ 	dofill(ox, y, oy-x, fill);
+     } else {
+ 	dotfcn(ox+x, oy+y, dotfcn);
+ 	dotfcn(ox+x, oy-y, dotfcn);
+ 	dotfcn(ox-x, oy+y, dotfcn);
+ 	dotfcn(ox-x, oy-y, dotfcn);
+ 	dotfcn(ox+y, oy+x, dotfcn);
+ 	dotfcn(ox+y, oy-x, dotfcn);
+ 	dotfcn(ox-y, oy+x, dotfcn);
+ 	dotfcn(ox-y, oy-x, dotfcn);
+     }
+ }
+ 
+ /*	Describes octants, counterclockwise from 0.
+ 	0: off
+ 	1: on
+ 	2: calculate
+  */
+ static int	arcOctant[8], invert;
+ static double arcStart, arcEnd;
+ 
+ /* roughly the same as ljCircle, except octant selector gunge */
+ ljArc (x0, y0, xc, yc, x1, y1)
+ int x0, y0, xc, yc, x1, y1;
+ {
+     register int x, y, d, deltaE, deltaSE, radius;
+     double t, c;
+ 
+     DBP((D_PIC, "ljArc: %d, %d, %d, %d, %d, %d\n",
+ 	x0, y0, xc, yc, x1, y1));
+     {
+ 	int inttmp;
+ 
+ 	inttmp = x0 + xc;
+ 	x0 = xc;
+ 	xc = inttmp;
+ 
+ 	inttmp = y0 + yc;
+ 	y0 = yc;
+ 	yc = inttmp;
+     }
+ 
+     radius = sqrt((double) sqr(x0) + (double) sqr(y0)) + .5;
+     arcStart = atan2((double) y0, (double) -x0);
+     arcEnd = atan2((double) -y1, (double) x1);
+ 
+     if (arcStart < 0)
+ 	arcStart += RAD_C;
+     if (arcEnd < 0)
+ 	arcEnd += RAD_C;
+ 
+     if (arcStart > arcEnd) {
+ 	invert = 1;
+ 	t = arcStart;
+ 	arcStart = arcEnd;
+ 	arcEnd = t;
+     } else {
+ 	invert = 0;
+     }
+ 
+     DBP((D_PIC, "ljArc: (%d,%d),r%d,inv:%d, (%f,%f)\n",
+ 	xc, yc, radius, invert, arcStart, arcEnd));
+ 
+     for (x = 0; x < 8; x++)
+ 	arcOctant[x] = invert;
+ 
+     x = 8 * arcStart / (2*M_PI);
+     y = 8 * arcEnd / (2*M_PI);
+ 
+     arcOctant[x] = 2;
+     arcOctant[y] = 2;
+     for (d = x+1; d < y; d++)
+ 	arcOctant[d] = !invert;
+ 
+     t = 2*M_PI / 8;
+     for (x = 0; x < 8; x++) {
+ 	c = x*t;
+ 	DBP((D_PIC, "%d: %f:%f (%f:%f) %d (%d)\n", x, c, c+t, arcStart, arcEnd,
+ 	    arcOctant[x], invert));
+     }
+ 
+     x = 0;
+     y = radius;
+     d = 1 - radius;
+     deltaE = 3;
+     deltaSE = -2 * radius + 5;
+     arcPoints(xc, yc, x, y);
+ 
+     while (y > x) {
+ 	if (d < 0) { /* select E */
+ 	    d += deltaE;
+ 	    deltaE += 2;
+ 	    deltaSE += 2;
+ 	    x++;
+ 	} else {	/* select SE */
+ 	    d += deltaSE;
+ 	    deltaE += 2;
+ 	    deltaSE += 4;
+ 	    x++;
+ 	    y--;
+ 	}
+ 	arcPoints(xc, yc, x, y);
+     }
+ }
+ 
+ /* if (octant on) ||
+       (endpoints in this octant && calculation shows point should be here)
+    put a dot
+  */
+ 
+ #define arcDot(q, a, b, c, d) if (arcOctant[q] == 1 || \
+     (arcOctant[q] == 2 && \
+ 	((t = atan2((double) -b,(double) a)),t = (t<0?t+RAD_C:t),\
+ 	invert ^ (t >= arcStart && t <= arcEnd)))) \
+     drawDot(c,d)
+ 
+ 
+ arcPoints(ox, oy, x, y)
+ int ox, oy, x, y; {
+     double t;
+ 
+     arcDot(0, y, -x, ox+y, oy-x);
+     arcDot(1, x, -y, ox+x, oy-y);
+     arcDot(2, -x, -y, ox-x, oy-y);
+     arcDot(3, -y, -x, ox-y, oy-x);
+     arcDot(4, -y, x, ox-y, oy+x);
+     arcDot(5, -x, y, ox-x, oy+y);
+     arcDot(6, x, y, ox+x, oy+y);
+     arcDot(7, y, x, ox+y, oy+x);
+ }
+ 
+ /*	the fill range 0..1000 selects one of these 8
+ 	rows.  Each row describes a 8x8 fill pattern.
+  */
+ static char fillpat[9][8] = {
+     { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+     { 0xc3, 0xa5, 0x24, 0xe9, 0xe9, 0x24, 0xa5, 0xc3 },
+     { 0xe7, 0xc3, 0x24, 0x3c, 0x3c, 0x24, 0xc3, 0xe7 },
+     { 0xc3, 0x81, 0x00, 0x18, 0x18, 0x00, 0x81, 0xc3 },
+     { 0x81, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0x81 },
+     { 0x81, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x81 },
+     { 0x00, 0x42, 0x00, 0x18, 0x18, 0x00, 0x42, 0x00 },
+     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
+ };
+ 
+ /* fill from (x-dx,y) to (x+dx, y) with the fill pattern.
+ 
+     fill pattern is aligned on byte boundaries in raster,
+     so theoretically, we could convert this to 0..7
+     of bit-dinks, a multi-byte memset, and 0..7 more
+     bit-dinks.  Profiling doesn't seem to show this as significant.
+  */
+ 
+ dofill(x, dx, y, fill)
+ register int x, dx, y, fill; {
+     register int t, td;
+     static int lastind = -1;
+     register int ind = fill/125;
+     register char fp = fillpat[ind][y&7];
+ 
+ #ifdef DEBUG
+     if (lastind != ind) {
+ 	DBP((D_PIC, "dofill: (%d+-%d,%d) %d->%d, fp:%02x\n", x, dx, y, fill, ind, fp));
+ 	lastind = ind;
+     }
+ #endif
+ 
+     asetbit(x, y);	/* make sure row is allocated */
+ 
+     td = x + dx;
+ 
+     for (t = x - dx; t < td; t++)
+ 	if ((0x80 >> (t&7)) & fp)
+ 	    setbit(t, y);
+ 	else
+ 	    clearbit(t, y);
+ }
+ 
+ EllipsePoints (ox, oy, x, y, fill)
+ int ox, oy, x, y, fill; {
+     if (fill != -1) {
+ 	dofill(ox, x, oy+y, fill);
+ 	dofill(ox, x, oy-y, fill);
+     } else {
+ 	drawDot(ox + x, oy + y);
+ 	drawDot(ox + x, oy - y);
+ 	drawDot(ox - x, oy + y);
+ 	drawDot(ox - x, oy - y);
+     }
+ }
+ 
+ 
+ ljEllipse(ox, oy, a, b, fill)
+ int ox, oy, a, b, fill; {
+     int x, y;
+     double d1, d2;
+     int sqra = a*a,
+ 	sqrb = b*b;
+     DBP((D_PIC, "ljEllipse: (%d,%d),xr%d,yr%d,f%d\n",
+ 	ox, oy, a, b, fill));
+ 
+     x = 0;
+     y = b;
+     d1 = sqrb - sqra * b + (double) sqra / 4;
+     EllipsePoints(ox, oy, x, y, fill);
+ 
+     while (sqra * (y - .5) > sqrb * (x + 1)) {
+ 	if (d1 < 0) {
+ 	    d1 = d1 + sqrb * (2 * x + 3);
+ 	    x++;
+ 	} else {
+ 	    d1 = d1 + sqrb * (2 * x + 3) + sqra * (-2 * y + 2);
+ 	    x++;
+ 	    y--;
+ 	}
+ 	EllipsePoints(ox, oy, x, y, fill);
+     }
+ 
+     d2 = sqrb * sqr(x + .5) + sqra * sqr(y - 1) - sqra * sqrb;
+     while (y > 0) {
+ 	if (d2 < 0) {
+ 	    d2 = d2 + sqrb * (2 * x + 2) + sqra * (-2 * y + 3);
+ 	    x++;
+ 	    y--;
+ 	} else {
+ 	    d2 = d2 + sqra * (-2 * y + 3);
+ 	    y--;
+ 	}
+ 	EllipsePoints(ox, oy, x, y, fill);
+     }
+ }
+ 
+ linePoints(x, y)
+ int x, y; {
+     if (rev)
+ 	drawDot(y,x);
+     else
+ 	drawDot(x,y);
+ }
+ 
+ /* General point drawing routine.  The idea is to draw a filled circle
+    at each pixel with radius 1/2 the desired thickness.  Doing a filled
+    circle is a lot of bit-dinking, so we optimize by drawing unfilled
+    circles with minimum line-width, and rely on adjacent circles to fill
+    in the hole.  Means that lines shorter than the line thickness
+    may have some hollow bits.
+  */
+ drawDot(x, y)
+ int x, y; {
+     if (curthick <= 1) {
+ 	asetbit(x, y);
+ 	asetbit(x+1, y);
+ 	asetbit(x, y+1);
+ 	asetbit(x+1, y+1);
+     } else
+ 	ljCircle(x, y, curthick, asetbit, -1);
+ }
+ 
+ /*	RASTER ENGINE */
+ 
+ char **ljraster = NULL;
+ int thispage = 0;
+ 
+ /* only supports drawing resolution of 300 at the moment. */
+ #define DRAWRES	300
+ #define BYTESPERLINE (8 * DRAWRES) / 8
+ #define RESMULT (LJRESOLUTION / DRAWRES)
+ #define ESCLEN 25
+ 
+ 
+ int
+ nullscan(start, end)
+ register char *start, *end; {
+     register char *cur;
+     for (cur = start; cur < end && !*cur; cur++);
+     return(cur - start);
+ }
+ 
+ int
+ pixblock(start, end)
+ register char *start, *end; {
+     register char *cur;
+     register int numnulls;
+     if (end - start <= ESCLEN * 2)	/* no point optimizing */
+ 	return(end - start);
+     cur = start;
+ 
+     while(cur < end) {
+ 
+ 	for(; *cur && cur < end; cur++);
+ 
+ 	numnulls = nullscan(cur, end);
+ 
+ 	if (numnulls > ESCLEN)
+ 	    return(cur - start);
+ 	else
+ 	    cur += numnulls;
+     }
+     return(end - start);
+ }
+ 
+ emitrast()
+ {
+     int bperline;
+     int numx = BYTESPERLINE * 8;
+     int numy = pagelength;
+     register char *ip, *lineanch, *nip;
+     register currow, bcount;
+     int linecount = 0;
+ 
+     bperline = ((numx + 7) / 8);
+ 
+     if (!thispage)
+ 	return;
+ 
+     printf("\033*t%dR", DRAWRES);
+ 
+     for(currow = 0; currow < numy; currow++) {
+ 	linecount++;
+ 	if (!ljraster[currow])
+ 	    continue;
+ 	lineanch = ip = ljraster[currow];
+ 	nip = ip + bperline;
+ 	while (ip < nip && !*ip) ip++;
+ 	if (ip >= nip)
+ 	    continue;	/* line has no pixels */
+ 	while (!*(nip - 1)) nip--;	/* truncate trailing nulls */
+ 	while (ip < nip) {	/* inv: !*ip && !*nip */
+ 	    bcount = pixblock(ip, nip);
+ 	    printf("\033*p%dx%dY\033*r1A\033*b%dW",
+ 		(ip - lineanch) * 8 * RESMULT, currow * RESMULT, bcount);
+ 	    rastcount += bcount;
+ 	    total += (bcount + ESCLEN);
+ 	    fwrite(ip, 1, bcount, stdout);
+ 	    fputs("\033*rB", stdout);
+ 	    for(ip += bcount; ip < nip && !*ip; ip++);
+ 	}
+ 	free(ljraster[currow]);
+ 	ljraster[currow] = (char *) NULL;
+     }
+     DBP((D_PIC, "emit raster: %d lines, %d rastbytes, total %d bytes\n",
+ 	linecount, rastcount, total));
+     rastcount = total = 0;
+     thispage = 0;
+ }
+ 
+ asetbit(x, y)
+ register int x, y; {
+     thispage = 1;
+     if (y < 0 || y > pagelength) {
+ 	/*fprintf(stderr, "y (%d) too big or small (0..%d)\n", y, pagelength);*/
+ 	return;
+     }
+     if (x < 0 || x > BYTESPERLINE * 8) {
+ 	/*fprintf(stderr, "x (%d) too big or small (0..%d)\n", x, BYTESPERLINE*8);*/
+ 	return;
+     }
+     if (!ljraster) {
+ 	ljraster = (char **) mustmalloc(pagelength * sizeof(char *),
+ 	    "ljraster pointers");
+ 	clrarray(ljraster, pagelength * sizeof(char *));
+     }
+     if (!ljraster[y]) {
+ 	ljraster[y] = (char *) mustmalloc(BYTESPERLINE, "ljraster line");
+ 	clrarray(ljraster[y], BYTESPERLINE);
+     }
+     ljraster[y][x >> 3] |= (0x80 >> (x & 0x7));
+ }
+ 
+ setbit(x, y)
+ register int x, y; {
+     ljraster[y][x >> 3] |= (0x80 >> (x & 0x7));
+ }
+ 
+ clearbit(x, y)
+ register int x, y; {
+     ljraster[y][x >> 3] &= ~(0x80 >> (x & 0x7));
  }
  
  
Index: ./lj3draw.c
*** /tmp/PATCHold/./lj3draw.c	Thu Nov 26 23:36:08 1992
--- ./lj3draw.c	Thu Nov 26 23:36:09 1992
***************
*** 29,35 ****
  
  #ifndef	lint
  static char SCCSid[] =
!     "@(#)lj3draw.c: 1.2 Copyright 92/02/10 16:49:48 Chris Lewis";
  #endif
  
  #define to_deg(a)	((180.0/M_PI) * (a))
--- 29,35 ----
  
  #ifndef	lint
  static char SCCSid[] =
!     "@(#)lj3draw.c: 1.3 Copyright 92/11/26 19:42:32 Chris Lewis";
  #endif
  
  #define to_deg(a)	((180.0/M_PI) * (a))
***************
*** 120,125 ****
--- 120,126 ----
  	    return;
      }
      printf(XY,origX,origY);
+     lastYPos = -1;
      if (!opcode)
  	return;
  
Index: ./pkscale.c
*** /tmp/PATCHold/./pkscale.c	Thu Nov 26 23:36:17 1992
--- ./pkscale.c	Thu Nov 26 23:36:18 1992
***************
*** 12,18 ****
  #ifdef	PK
  
  #ifndef lint
! static char SCCSid[] = "@(#)pkscale.c 1.2 Copyright 92/05/19 23:10:53 Chris Lewis";
  #endif
  
  #include "pk.h"
--- 12,18 ----
  #ifdef	PK
  
  #ifndef lint
! static char SCCSid[] = "@(#)pkscale.c 1.3 Copyright 92/10/30 02:27:04 Chris Lewis";
  #endif
  
  #include "pk.h"
***************
*** 70,79 ****
--- 70,84 ----
      npkp->pkp_kh = scalenum(sf, npkp->pkp_kh);
      npkp->pkp_kl = scalenum(sf, npkp->pkp_kl);
  
+     DBP((D_FONT,"To scale %d characters\n", pkp->pkp_num));
      for (i = 0; i < pkp->pkp_num; i++) {
  	register struct ras *r;
+ 
  	pc = pkp->pkp_list[i];
  
+ 	DBP((D_FONT,"Scale char %ld (%c) to %d (%f)\n", pc->pkc_char,
+ 	    pc->pkc_char, target, sf));
+ 
  	/* create new char descriptor, initialized to old */
  	npc = (struct pkc *) mustmalloc(sizeof(struct pkc),
  	    "New PK character descriptor");
***************
*** 80,88 ****
--- 85,97 ----
  	*npc = *pc;
  	if (!npkp->pkp_chars)
  	    npkp->pkp_chars = npc;
+ 	else
+ 	    npkp->pkp_list[i-1]->pkc_next = npc;
+ 
  	npkp->pkp_last = npc;
  	npkp->pkp_list[i] = npc;
  
+ 
  	/* get a raster to play with */
  	pc->pkc_sfpr = pkrast(pc);
  	if (pc->pkc_pkr)
***************
*** 158,163 ****
--- 167,176 ----
  	for (x = 0, p = sl; x < sln; x++)
  	    *p++ = scale * x + .5;
      }
+ 
+     DBP((D_FONT, "rast %d:%d (%d) -> %d:%d (%d) (%f)\n",
+ 	from->ras_width, from->ras_height, from->ras_bytes,
+ 	to->ras_width, to->ras_height, to->ras_bytes, scale));
  
      clrarray(to->ras_raster, to->ras_bytes);
  
Index: ./pk.h
*** /tmp/PATCHold/./pk.h	Thu Nov 26 23:36:26 1992
--- ./pk.h	Thu Nov 26 23:36:27 1992
***************
*** 8,14 ****
      Function:		PK format font file description
   */
  
! /* 2.2 91/02/20 */
  
  #ifdef	PK
  
--- 8,14 ----
      Function:		PK format font file description
   */
  
! /* 2.3 92/10/30 */
  
  #ifdef	PK
  
***************
*** 51,56 ****
--- 51,59 ----
  };
  
  struct pkp *pk_read();
+ #ifdef PKSCALE
+ struct pkp *pkscale();
+ #endif
  
  struct pkc {
      long pkc_flag;	/* flag byte */



-- 
Chris Lewis; clewis@ferret.ocunix.on.ca; Phone: Canada 613 832-0541
Psroff 3.0 info: psroff-request@ferret.ocunix.on.ca
Ferret list: ferret-request@ferret.ocunix.on.ca
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads