[comp.sources.unix] v12i061: A PostScript interpreter, Part12/18

rsalz@uunet.UU.NET (Rich Salz) (11/09/87)

Submitted-by: Crispin Goswell <caag@vd.rl.ac.uk>
Posting-number: Volume 12, Issue 61
Archive-name: postscript/part12

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 12 (of 18)."
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'source/X.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'source/X.c'\"
else
echo shar: Extracting \"'source/X.c'\" \(15122 characters\)
sed "s/^X//" >'source/X.c' <<'END_OF_FILE'
X/*
X * Copyright (C) Rutherford Appleton Laboratory 1987
X * 
X * This source may be copied, distributed, altered or used, but not sold for profit
X * or incorporated into a product except under licence from the author.
X * It is not in the public domain.
X * This notice should remain in the source unaltered, and any changes to the source
X * made by persons other than the author should be marked as such.
X * 
X *	Crispin Goswell @ Rutherford Appleton Laboratory caag@uk.ac.rl.vd
X */
X#include "X/Xlib.h"
X
X#include "main.h"
X#include "graphics.h"
X
X#define TRANSFER_SIZE	256
X#define XMAX		65535
X
Xstatic int transfer [TRANSFER_SIZE + 1];
X
Xstatic unsigned char reverse [0x100];
X
Xstruct hardware
X {
X 	Window win;
X 	struct bitmap *bm;
X 	int width, height;
X };
X
Xstruct bitmap
X {
X 	short *data;
X 	Bitmap xbm;
X 	int width, height;
X };
X
Xstruct hardcolour
X {
X 	int pixel;
X 	Pixmap tile;
X };
X
Xstruct screen
X {
X 	float val;
X 	int sx, sy;
X 	Pixmap shade;
X } *screen = NULL;
X
Xstatic int screen_size, screen_side;
X
Xchar *malloc ();
X
Xstatic Display *theDisplay;
Xstatic float magnification;
X
Xstatic void InitTransfer ();
Xstatic struct hardcolour HardColour ();
X
Xstruct hardware *InitHardware ()
X {
X	if ((theDisplay = XOpenDisplay ("")) == NULL)
X	 {
X	 	fprintf (stderr, "Could not open display\n");
X	 	exit (1);
X	 }
X	magnification = DisplayHeight () / (11.0 * 72);
X	XSetDisplay (theDisplay);
X	InitReversal ();
X	InitRopMap ();
X	InitTransfer ();
X	
X	return 0;
X }
X
Xstatic struct hardware *NewHardware (win, bm, width, height) Window win; struct bitmap *bm; int width, height;
X {
X 	struct hardware *res = (struct hardware *) malloc (sizeof (struct hardware));
X 	
X 	res->win = win;
X 	res->bm = bm;
X 	res->width = width;
X 	res->height = height;
X 	
X 	return res;
X }
X
XSetClipHardware (bm, clip) struct hardware *bm, *clip;
X {
X }
X
Xint hard_size (width, height) int width, height;
X {
X	return ((width + 15) / 16) * height;
X }
X
Xstatic struct bitmap *NewBM (width, height) int width, height;
X {
X 	struct bitmap *res = (struct bitmap *) malloc (sizeof (struct bitmap));
X 	
X 	res->data = (short *) calloc (hard_size (width, height), sizeof (short));
X 	res->width = width;
X 	res->height = height;
X	res->xbm = 0;
X 	
X 	return res;
X }
X
Xstatic void DestroyBM (bm) struct bitmap *bm;
X {
X 	free ((char *) bm->data);
X 	if (bm->xbm != 0)
X 		XFreeBitmap (bm->xbm);
X 	free ((char *) bm);
X }
X
Xstatic Bitmap NeedBitmap (bm) struct bitmap *bm;
X {
X 	if (bm->xbm == 0)
X	 {
X 		bm->xbm = XStoreBitmap (bm->width, bm->height, bm->data);
X	 }
X 	return bm->xbm;
X }
X
Xstatic OODBitmap (bm) struct bitmap *bm;
X {
X 	if (bm->xbm != 0)
X 	 {
X 		XFreeBitmap (bm->xbm);
X 		bm->xbm = 0;
X 	 }
X }
X
Xstruct hardware *NewWindowHardware (width, height) int width, height;
X {
X 	Window win = XCreateWindow (RootWindow, 0, 0, width, height, 1, BlackPixmap, WhitePixmap);
X 	
X 	if (win == 0)
X 		return NULL;
X 	XMapWindow (win);
X 	
X 	return NewHardware (win, NULL, width, height);
X }
X
Xstruct hardware *NewBitmapHardware (width, height) int width, height;
X {
X 	return NewHardware (0, NewBM (width, height), width, height);
X }
X
Xvoid DestroyHardware (h) struct hardware *h;
X {
X 	if (IsWindowHardware (h))
X 		XDestroyWindow (h->win);
X 	else
X 		DestroyBM (h->bm);
X 	free ((char *) h);
X }
X
XMatrix DeviceMatrix (width, height) int width, height;
X {
X 	return NewMatrix (magnification, 0.0, 0.0, -magnification, 0.0, (float) height);
X }
X
XDevicePoint HardwareExtent (h) struct hardware *h;
X {
X 	return h == NULL ? NewDevicePoint (0, 0) : NewDevicePoint (h->width, h->height);
X }
X
Xint IsWindowHardware (h) struct hardware *h;
X {
X 	return h->win != 0;
X }
X
Xstatic int single_rop [16];
X
Xstatic InitRopMap ()
X {
X	single_rop [ROP_FALSE] 	= single_rop [ROP_NOTAND] = single_rop [ROP_NOR]     = single_rop [ROP_NOTSOURCE] = ROP_FALSE;
X	single_rop [ROP_AND] 	= single_rop [ROP_DEST]   = single_rop [ROP_NXOR]    = single_rop [ROP_NOTOR] 	  = ROP_DEST;
X	single_rop [ROP_ANDNOT] = single_rop [ROP_XOR]	  = single_rop [ROP_NOTDEST] = single_rop [ROP_NAND] 	  = ROP_NOTDEST;
X	single_rop [ROP_SOURCE] = single_rop [ROP_OR] 	  = single_rop [ROP_ORNOT]   = single_rop [ROP_TRUE] 	  = ROP_TRUE;
X }
X
Xstatic int Xvalue (ax, ay, bx, by, cy) int ax, ay, bx, by, cy;
X {
X 	return bx + (cy - by) * (ax - bx) / (float) (ay - by);
X }
X
Xstatic void PaintBlob (to, top, bottom, left, right, col)
X	struct hardware *to;
X	int top, bottom, *left, *right;
X	struct hardcolour col;
X {
X 	int i, op, offset = top;
X 	
X	if (col.tile == 0)
X  		for (i = top; i <= bottom; i++)
X 	 		XPixSet (to->win, left[i - offset], i, right[i - offset] - left[i - offset] + 1, 1, col.pixel);
X 	else
X 		for (i = top; i <= bottom; i++)
X 			XTileSet (to->win, left[i - offset], i, right[i - offset] - left[i - offset] + 1, 1, col.tile);
X }
X
Xvoid PaintTrapezoid (to, lefttop, leftbottom, righttop, rightbottom, top, bottom, colour)
X	struct hardware *to;
X	DevicePoint lefttop, leftbottom, righttop, rightbottom;
X	int top, bottom;
X	Colour colour;
X {
X 	struct hardcolour col;
X 	int i, j, temp; char c;
X 	static int left [1024], right [1024];
X 	
X 	int 	ltx = Xvalue (lefttop.dx, 	lefttop.dy, 	leftbottom.dx, 	leftbottom.dy, 	top),
X 		rtx = Xvalue (righttop.dx, 	righttop.dy, 	rightbottom.dx, rightbottom.dy, top),
X 		lbx = Xvalue (lefttop.dx, 	lefttop.dy, 	leftbottom.dx, 	leftbottom.dy, 	bottom),
X 		rbx = Xvalue (righttop.dx, 	righttop.dy, 	rightbottom.dx, rightbottom.dy, bottom);
X 	
X 	col = HardColour (colour);
X 	
X 	if (ltx == lbx && rtx == rbx)
X 	 {
X 	 	if (rtx < ltx)
X 	 		temp = rtx, rtx = ltx, ltx = temp;
X 	 	
X 		if (col.tile == 0)
X 	 		XPixSet (to->win, ltx, top, rtx - ltx + 1, bottom - top + 1, col.pixel);
X 		else
X			XTileSet (to->win, ltx, top, rtx - ltx + 1, bottom - top + 1, col.tile);
X 		return;
X 	 }
X 	
X 	for (i = top, j = 0; i <= bottom; i++, j++)
X 	 {
X 	 	int 	lx = Xvalue (lefttop.dx, 	lefttop.dy, 	leftbottom.dx, leftbottom.dy,  i),
X 			rx = Xvalue (righttop.dx, 	righttop.dy, 	rightbottom.dx,rightbottom.dy, i);
X 		
X 		if (rx < lx)
X 			temp = rx, rx = lx, lx = temp;
X 		
X 		left [j] = lx; right [j] = rx;
X 	 }
X 	PaintBlob (to, top, bottom, left, right, col);
X }
X
Xstatic void RasterBlob (to, top, bottom, left, right, rop)
X	struct hardware *to;
X	int top, bottom, *left, *right, rop;
X {
X 	int i, op, offset = top;
X 	
X 	switch (rop)
X 	 {
X 	 	case ROP_FALSE: 	op = GXclear; break;
X 	 	case ROP_DEST: 		return;
X 	 	case ROP_NOTDEST: 	op = GXinvert; break;
X 	 	case ROP_TRUE: 		op = GXset; break;
X 	 }
X 	for (i = top; i <= bottom; i++)
X 		XCopyArea (to->win, 0, 0, left[i - offset], i, right[i - offset] - left[i - offset] + 1, 1, op, ~0);
X }
X
Xstatic void RasterTrapezoid (to, lefttop, leftbottom, righttop, rightbottom, top, bottom, rop)
X	struct hardware *to;
X	DevicePoint lefttop, leftbottom, righttop, rightbottom;
X	int top, bottom, rop;
X {
X 	int i, j, temp; char c;
X 	static int left [1024], right [1024];
X 	
X 	int 	ltx = Xvalue (lefttop.dx, 	lefttop.dy, 	leftbottom.dx, 	leftbottom.dy, 	top),
X 		rtx = Xvalue (righttop.dx, 	righttop.dy, 	rightbottom.dx, rightbottom.dy, top),
X 		lbx = Xvalue (lefttop.dx, 	lefttop.dy, 	leftbottom.dx, 	leftbottom.dy, 	bottom),
X 		rbx = Xvalue (righttop.dx, 	righttop.dy, 	rightbottom.dx, rightbottom.dy, bottom);
X 	
X 	if (ltx == lbx && rtx == rbx)
X 	 {
X 	 	int op;
X 	 	
X 	 	if (rtx < ltx)
X 	 		temp = rtx, rtx = ltx, ltx = temp;
X 	 	
X 		switch (rop)
X 		 {
X 	 		case ROP_FALSE: 	op = GXclear; break;
X 	 		case ROP_DEST: 		return;
X 	 		case ROP_NOTDEST: 	op = GXinvert; break;
X 	 		case ROP_TRUE: 		op = GXset; break;
X 		 }
X 		XCopyArea (to->win, 0, 0, ltx, top, rtx - ltx + 1, bottom - top + 1, op, ~0);
X 		return;
X 	 }
X 	
X 	for (i = top, j = 0; i <= bottom; i++, j++)
X 	 {
X 	 	int 	lx = Xvalue (lefttop.dx, 	lefttop.dy, 	leftbottom.dx, leftbottom.dy,  i),
X 			rx = Xvalue (righttop.dx, 	righttop.dy, 	rightbottom.dx,rightbottom.dy, i);
X 		
X 		if (rx < lx)
X 			temp = rx, rx = lx, lx = temp;
X 		
X 		left [j] = lx; right [j] = rx;
X 	 }
X 	RasterBlob (to, top, bottom, left, right, single_rop [rop]);
X }
X
Xvoid Paint (from, to, fromPoint, toPoint, extent, colour)
X	struct hardware *from, *to;
X	DevicePoint fromPoint, toPoint, extent;
X	Colour colour;
X {
X 	if (to == NULL)
X 		return;
X 	if (from && IsWindowHardware (from))
X 	 {
X 	 	fprintf (stderr, "driver for Paint cannot use Window as source\n");
X 	 	exit (1);
X 	 }
X 	if (IsWindowHardware (to))
X 	 {
X 	 	struct hardcolour col;
X 	 	
X 	 	col = HardColour (colour);
X 	 	if (col.tile == 0)
X 	 		if (from == NULL)
X 	 			XPixSet (to->win, toPoint.dx, toPoint.dy, extent.dx, extent.dy, col.pixel);
X 	 		else
X			 {
X				Pixmap pm = XMakePixmap (NeedBitmap (from->bm), AllPlanes, 0);
X				
X  	 			XPixmapPut (to->win, fromPoint.dx, fromPoint.dy, toPoint.dx, toPoint.dy, extent.dx, extent.dy, pm, GXandInverted, AllPlanes);
X  	 			XFreePixmap (pm);
X 				pm = XMakePixmap (NeedBitmap (from->bm), col.pixel, 0);
X				
X  	 			XPixmapPut (to->win, fromPoint.dx, fromPoint.dy, toPoint.dx, toPoint.dy, extent.dx, extent.dy, pm, GXor, AllPlanes);
X  	 			XFreePixmap (pm);
X  	 		 }
X	 	else
X 	 		if (from == NULL)
X  	 			XTileSet (to->win, toPoint.dx, toPoint.dy, extent.dx, extent.dy, col.tile);
X 	 		else
X			 {
X				Pixmap pm = XMakePixmap (NeedBitmap (from->bm), BlackPixel, WhitePixel);
X				
X  	 			XPixmapPut (to->win, fromPoint.dx, fromPoint.dy, toPoint.dx, toPoint.dy, extent.dx, extent.dy, pm, GXandInverted, AllPlanes);
X  	 			XFreePixmap (pm);
X  	 		 }
X	 }
X 	else
X 	 {
X  	 	fprintf (stderr, "driver for Paint cannot use Window as source\n");
X 	 	exit (1);
X	 }
X }
X
Xvoid BitBlt (from, to, fromPoint, toPoint, extent, rop)
X	struct hardware *from, *to;
X	DevicePoint fromPoint, toPoint, extent;
X	int rop;
X {
X 	if (to == NULL)
X 		return;
X 	if (IsWindowHardware (to))
X 	 {
X 	 	fprintf (stderr, "driver for BitBlt cannot use Window as Destination\n");
X 	 	exit (1);
X 	 }
X 	else
X 	 {
X 	 	if (rop == ROP_SOURCE && fromPoint.dx == 0 && fromPoint.dy == 0 && toPoint.dx == 0 && toPoint.dy == 0)
X 	 	 {
X 	 	 	DevicePoint exfrom, exto;
X 	 	 	
X 	 	 	exfrom = HardwareExtent (from); exto = HardwareExtent (to);
X 	 	 	if (exfrom.dx == extent.dx && exfrom.dy == extent.dy && exto.dx == extent.dx && exto.dy == extent.dy)
X 	 	 	 {
X 	 	 	 	Bcopy ((char *) (to->bm->data), (char *) (from->bm->data), sizeof (short) * hard_size (to->width, to->height));
X 	 	 	 	OODBitmap (to->bm);
X 	 	 	 	
X 	 	 	 	return;
X 	 	 	 }
X 	 	 		
X 	 	 }
X 	 }
X 	fprintf (stderr, "driver for BitBlt can't cope with general case\n");
X 	exit (1);
X }
X
Xvoid PaintLine (h, fromPoint, toPoint, colour) struct hardware *h; DevicePoint fromPoint, toPoint; Colour colour;
X {
X	struct hardcolour col;
X
X	col = HardColour (colour);
X
X	if (col.tile == screen[0].shade)
X		col.pixel = BlackPixel,
X		col.tile = 0;
X	else if (col.tile == screen[screen_size].shade)
X		col.pixel == WhitePixel,
X		col.tile = 0;
X	else
X		;
X	if (!IsWindowHardware (h))
X	 {
X		fprintf (stderr, "driver for PaintLine cannot cope with bitmaps\n");
X		return;
X	 }
X	if (col.tile == 0)
X		XLine (h->win, fromPoint.dx, fromPoint.dy, toPoint.dx, toPoint.dy, 1, 1, col.pixel, GXcopy, AllPlanes);
X	else
X	 {
X		fprintf (stderr, "driver for PaintLine cannot cope with textured lines\n");
X		XLine (h->win, fromPoint.dx, fromPoint.dy, toPoint.dx, toPoint.dy, 1, 1, col.pixel, GXcopy, AllPlanes);
X	 }
X }
X
Xvoid Line (h, fromPoint, toPoint, rop) struct hardware *h; DevicePoint fromPoint, toPoint; Colour rop;
X {
X }
X
Xstruct hardware *HardwareFromString (s, width, height) unsigned char *s; int width, height;
X {
X	int words = (width + 15) / 16;
X	struct bitmap *BM = NewBM (width, height);
X	short *d = BM->data;
X	int odd = ((width + 7) / 8) & 1;
X	int i, j;
X
X	for (i = 0; i < height; i++)
X	 {
X		for (j = 0; j < words - odd; j++)
X		 {
X			short word = reverse [*s++];
X
X			*d++ = word | (reverse [*s++] << 8);
X		 }
X		if (odd)
X			*d++ = reverse [*s++];
X	 }
X	return NewHardware (0, BM, width, height);
X }
X
Xchar *StringFromHardware (h) struct hardware *h;
X {
X	int words = (h->width + 15) / 16;
X	char *string = malloc ((h->width + 7) / 8 * h->height), *s = string;
X	int i, j, odd = ((h->width + 7) / 8) & 1;
X	short *d = h->bm->data;
X
X	for (i = 0; i < h->height; i++)
X	 {
X		for (j = 0; j < words - odd; j++)
X		 {
X			short word = *d++;
X
X			*s++ = reverse [word & 0xFF];
X			*s++ = reverse [(word >> 8) & 0xFF];
X		 }
X		if (odd)
X			*s++ = reverse [*d++ & 0xFF];
X	 }
X	return string;
X }
X
XInitReversal ()
X {
X	int i, j;
X
X	for (i = 0; i < 0x100; i++)
X	 {
X		unsigned char r = 0;
X
X		for (j = 0; j < 8; j++)
X			r |= (1 & (i >> j)) << (7 - j);
X		reverse [i] = r;
X	 }
X }
X
Xvoid HardUpdate ()
X {
X 	XFlush ();
X }
X
Xstatic struct hardcolour HardColour (colour) Colour colour;
X {
X 	struct hardcolour res;
X	int col;
X 	
X	if (DisplayPlanes () != 1)
X	 {
X		Color def;
X		float r, g, b;
X
X		ColourRGB (colour, &r, &g, &b);
X		def.red = XMAX * r;
X		def.green = XMAX * g;
X		def.blue = XMAX * b;
X
X		XGetHardwareColor (&def);
X
X		res.tile = 0;
X		res.pixel = def.pixel;
X
X		return res;
X	 }
X	
X	col = transfer [(int) (TRANSFER_SIZE * colour.brightness + .5)];
X	
X 	res.tile = screen[(int) (col * (float) screen_size / TRANSFER_SIZE + 0.5)].shade;
X 	
X 	return res;
X }
X
Xstatic void InitTransfer ()
X {
X 	int i;
X 	
X 	for (i = 0; i <= TRANSFER_SIZE; i++)
X 		transfer [i] = i;
X }
X
Xint TransferSize ()
X {
X	return TRANSFER_SIZE;
X }
X
Xvoid SetTransfer (tran) float *tran;
X {
X 	int i;
X 	
X 	for (i = 0; i < TRANSFER_SIZE; i++)
X 		transfer [i] = (TRANSFER_SIZE - 1) * tran[i] + .5;
X }
X
Xint ScreenSize (freq, rot) float freq, rot;
X {
X 	int size = magnification * 72 / freq + 0.5;
X 	
X 	return size * size;
X }
X
Xvoid BuildScreen (freq, rotation, x, y) float freq, rotation, *x, *y;
X {
X 	int size = magnification * 72 / freq + 0.5;
X 	int i, j;
X 	
X 	for (i = 0; i < size; i++)
X 		for (j = 0; j < size; j++)
X 			*x++ = (2 * i - size + 1) / (float) size,
X 			*y++ = (2 * j - size + 1) / (float) size;
X }
X
Xstatic sgn (a) float a;
X {
X	if (a == 0)
X		return 0;
X	else if (a < 0)
X		return -1;
X	else
X		return 1;
X }
X
Xstatic int screen_cmp (a, b) char *a, *b;
X {
X 	struct screen *aa = (struct screen *) a, *bb = (struct screen *) b;
X 	
X 	return sgn (aa->val - bb->val);
X }
X
Xvoid SetScreen (freq, rotation, thresh) float freq, rotation, *thresh;
X {
X 	struct bitmap *temp;
X 	int i, j, size = magnification * 72 / freq + 0.5;
X 	struct screen *p;
X 	
X 	if (screen)
X 	 {
X 	 	for (i = 0; i < screen_size; i++)
X 	 		XFreePixmap (screen [i].shade);
X 	 	free ((char *) screen);
X 	 }
X 	p = screen = (struct screen *) malloc (((screen_size = size * size) + 1) * sizeof (struct screen));
X 	screen_side = size;
X 	for (i = 0; i < size; i++)
X 		for (j = 0; j < size; j++)
X 		 {
X 		 	p->val = *thresh++;
X 		 	p->sx = i;
X 		 	p->sy = j;
X 		 	++p;
X 		 }
X 	qsort ((char *) screen, (unsigned) screen_size, sizeof (struct screen), screen_cmp);
X 	
X 	temp = NewBM (size, size);
X 	
X 	for (i = 0; i < screen_size; i++)
X 	 {
X 	 	screen [i].shade = XMakePixmap (NeedBitmap (temp), WhitePixel, BlackPixel);
X 	 	SetBit (temp, screen[i].sx, screen[i].sy);
X 	 	OODBitmap (temp);
X 	 }
X 	screen[screen_size].shade = XMakePixmap (NeedBitmap (temp), WhitePixel, BlackPixel);
X 	OODBitmap (temp);
X }
X
XSetBit (bm, x, y) struct bitmap *bm; int x, y;
X {
X 	int words = ((bm->width + 15) / 16);
X 	
X 	OODBitmap (bm);
X 	bm->data[y * words + (x >> 4)] |= 1 << (x & 0xF);
X }
X
XUpdateControl (h, i) struct hardware *h; int i;
X {
X }
END_OF_FILE
if test 15122 -ne `wc -c <'source/X.c'`; then
    echo shar: \"'source/X.c'\" unpacked with wrong size!
fi
# end of 'source/X.c'
fi
if test -f 'source/cache.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'source/cache.c'\"
else
echo shar: Extracting \"'source/cache.c'\" \(14908 characters\)
sed "s/^X//" >'source/cache.c' <<'END_OF_FILE'
X/*
X * Copyright (C) Rutherford Appleton Laboratory 1987
X * 
X * This source may be copied, distributed, altered or used, but not sold for profit
X * or incorporated into a product except under licence from the author.
X * It is not in the public domain.
X * This notice should remain in the source unaltered, and any changes to the source
X * made by persons other than the author should be marked as such.
X * 
X *	Crispin Goswell @ Rutherford Appleton Laboratory caag@uk.ac.rl.vd
X */
X#include "main.h"
X#include "graphics.h"
X
Xstatic struct cache
X {
X	struct cache *cache_next, *cache_prev;
X	int fid;
X	Matrix mat;					/* character -> device */
X	int width, height, swidth, sheight; 	/* device coords */
X } cache_header = { &cache_header, &cache_header },
X 	*cache_ring = &cache_header;
X
Xstatic struct char_table {
X	Object 		char_key;
X	struct cache 	*char_cache;
X	
X	struct device 	*char_device;
X	Point 		char_width;		    /* character coords */
X} *CharTable;
X
Xstatic int bsize = 0, bmax = 0;
Xstatic int msize = 0, mmax = 0;
Xstatic int csize = 0, cmax = 0;
X
Xstatic int maxbits = 0;
X
Xstatic int CacheStatus ();
Xstatic int PSetCharWidth ();
Xstatic int SetCacheLimit ();
Xstatic int PCurrentCharWidth ();
Xstatic int PSetCacheDevice ();
Xstatic int SetCache ();
Xstatic int SaveCurrentFont ();
X
Xint SetCacheDevice ();
Xstatic struct cache *NewCache (), *CacheRemove ();
X
XInitCache ()
X {
X 	InstallOp ("cachestatus",	CacheStatus,		0, 7, 0, 0);
X 	InstallOp ("setcachedevice",	PSetCacheDevice,	6, 0, 0, 0, Float, Float, Float, Float, Float, Float);
X 	InstallOp ("setcharwidth",	PSetCharWidth,		2, 0, 0, 0, Float, Float);
X 	InstallOp (".currentcharwidth",	PCurrentCharWidth,	0, 2, 0, 0);
X 	InstallOp ("setcachelimit",	SetCacheLimit,		1, 0, 0, 0, Integer);
X 	InstallOp ("setcache",		SetCache,		3, 0, 0, 0, Integer, Integer, Integer);
X	InstallOp ("savecurrentfont",	SaveCurrentFont,		0, 0, 0, 0);
X }
X
Xstatic InitCharTable ()
X {
X 	int i;
X 	
X 	CharTable = (struct char_table *) Malloc ((unsigned) (sizeof (struct char_table) * cmax));
X 	for (i = 0; i < cmax; i++)
X 		CharTable[i].char_cache = NULL;
X }
X
Xstatic struct char_table *CharAddition (table, cache, key, size)
X		struct char_table *table;
X		struct cache *cache;
X		Object key;
X		int size;
X {
X 	int i, h = (BodyInteger (key) + (int) cache) % size;
X 	
X	for (i = h;;)
X	 {
X	 	if (table[i].char_cache == NULL)
X		 {
X			table[i].char_key = key;
X			table[i].char_cache = cache;
X			
X			return &table[i];
X		 }
X		if (++i == size)
X			i = 0;
X		if (i == h)
X			return NULL;
X	 }
X }
X
XCharStore (key, width, dev) Object key; Point width; struct device *dev;
X {
X 	struct char_table *p;
X 	
X	while (csize == cmax)
X		DestroyCache (CacheRemove (cache_ring->cache_prev));
X 	
X	if (p = CharAddition (CharTable, gstate->show->ccache, key, cmax))
X	 {
X		p->char_width = width;
X		p->char_device = dev;
X		++csize;
X	 }
X	else
X		Panic ("dictionary full in CharStore");
X }
X
Xstatic struct char_table *CharFind (table, cache, key, size)
X		struct char_table *table;
X		struct cache *cache;
X		Object key;
X		int size;
X {
X 	int i, h = (BodyInteger (key) + (int) cache) % size;
X 	
X	for (i = h;;)
X	 {
X/*	 	if (table[i].char_cache == NULL)
X	 		return NULL;
X*/	 	if (table[i].char_cache == cache && Equal (key, table[i].char_key))
X			return &table[i];
X		if (++i == size)
X			i = 0;
X		if (i == h)
X			break;
X	 }
X	return NULL;
X }
X
Xstatic struct char_table *CharLoad (key) Object key;
X {
X 	return CharFind (CharTable, gstate->show->ccache, key, cmax);
X }
X
Xstatic FlushChars (p) struct cache *p;
X {
X 	int i;
X 	
X	for (i = 0; i < cmax; i++)
X	 	if (CharTable[i].char_cache == p)
X	 	 {
X	 		CharTable[i].char_cache = NULL;
X	 		--csize;
X	 	 }
X }
X
X/* convert bounding box to equivalent one in device coordinates */
XDeviceBBox (left, right, top, bottom, llx, urx, ury, lly) float *left, *right, *top, *bottom, llx, urx, ury, lly;
X {
X 	HardPoint ll;
X 	
X 	ll = ExtToInt (NewPoint (llx, lly));
X 	
X 	*left = *right = ll.hx; *top = *bottom = ll.hy;
X 	
X 	Bound (left, right, top, bottom, ExtToInt (NewPoint (urx, lly)));
X 	Bound (left, right, top, bottom, ExtToInt (NewPoint (llx, ury)));
X 	Bound (left, right, top, bottom, ExtToInt (NewPoint (urx, ury)));
X }
X
Xint EqVector (a, b) Vector a, b;
X {
X 	return (int) a.vx == (int) b.vx && (int) a.vy == (int) b.vy;
X }
X
Xstatic int PCurrentCharWidth ()
X {
X 	VOID Push (OpStack, MakeReal (gstate->show->Width.x));
X 	VOID Push (OpStack, MakeReal (gstate->show->Width.y));
X 	return TRUE;
X }
X
Xstatic int PSetCharWidth (wx, wy) Object wx, wy;
X {
X 	if (!gstate->show->InShow)
X 		return Error (PUndefined);
X 	SetCharWidth (NewPoint (BodyReal (wx), BodyReal (wy)));
X 	return TRUE;
X }
X
XSetCharWidth (width) Point width;
X {
X 	gstate->show->Width = width;
X }
X
Xstatic int PSetCacheDevice (wx, wy, llx, lly, urx, ury)  Object wx, wy, llx, lly, urx, ury;
X {
X 	if (!gstate->show->InShow)
X 		return Error (PUndefined);
X 	return SetCacheDevice (gstate->show->CharName,
X 				NewPoint (BodyReal (wx), BodyReal (wy)),
X 				BodyReal (llx), BodyReal (lly),
X 				BodyReal (urx), BodyReal (ury));
X }
X
Xstatic int CharTooBig (width, height) float width, height;
X {
X	return width * height > maxbits * 8;
X }
X
Xint SetCacheDevice (name, char_width, llx, lly, urx, ury)
X		Object name; Point char_width; float llx, lly, urx, ury;
X {
X 	float left, right, top, bottom, width, height;
X 	struct device *new_char;
X 	struct cache *ccache = gstate->show->ccache;
X 	
X 	SetCharWidth (char_width);
X 	if (!ccache)
X 		return TRUE;
X 	DeviceBBox (&left, &right, &top, &bottom, llx, urx, ury, lly);
X 	width = right - left; height = top - bottom;
X 	
X 	if (CharTooBig (width, height))
X 		return TRUE;
X 	
X 	new_char = NewCacheDevice (ccache->mat, ccache->width, ccache->height, ccache->swidth, ccache->sheight);
X 	CharStore (name, char_width, LinkDevice (new_char));
X 	SetDevice (new_char);
X 	
X 	PathFree (gstate->clip);
X 	gstate->clip = NewClipPath (0.0, width, height, 0.0);
X 	gstate->CTM.tx = ccache->swidth;
X 	gstate->CTM.ty = ccache->sheight;
X 	VOID MoveTo (gstate->path, ExtToInt (NewPoint (0.0, 0.0)));
X 	
X 	return TRUE;
X }
X
XprintMatrix (m) Matrix m;
X {
X	printf ("[%g %g]\n", m.A, m.B);
X	printf ("[%g %g]\n", m.C, m.D);
X	printf ("[%g %g]\n", m.tx, m.ty);
X }
X
X#ifdef notdef
Xint EqFont (m, n, bbox) Matrix m, n; float *bbox;
X {
X 	Vector morigin, norigin, mright, nright, mbottom, nbottom;
X 	
X 	morigin = Transform (NewVector (bbox [BBOX_LEFT], bbox [BBOX_TOP], 1.0), m);
X 	norigin = Transform (NewVector (bbox [BBOX_LEFT], bbox [BBOX_TOP], 1.0), n);
X 	mright  = DiffVector (Transform (NewVector (bbox [BBOX_RIGHT], bbox [BBOX_TOP], 1.0), m), morigin);
X 	nright  = DiffVector (Transform (NewVector (bbox [BBOX_RIGHT], bbox [BBOX_TOP], 1.0), n), norigin);
X 	mbottom = DiffVector (Transform (NewVector (bbox [BBOX_LEFT],  bbox [BBOX_BOTTOM], 1.0), m), morigin);
X 	nbottom = DiffVector (Transform (NewVector (bbox [BBOX_LEFT],  bbox [BBOX_BOTTOM], 1.0), n), norigin);
X 	
X 	return EqVector (mbottom, nbottom) && EqVector (mright, nright);
X }
X#endif
X
Xint EqFont (m, n) Matrix m, n;
X {
X	return m.A == n.A && m.B == n.B && m.C == n.C && m.D == n.D;
X }
X
Xextern float fontbboxCache[];
Xextern int fidCache;
X
Xstruct cache *SearchCache (m, fid) Matrix m; int fid;
X {
X 	struct cache *p;
X 	
X 	for (p = cache_ring->cache_next; p != cache_ring; p = p->cache_next)
X 		if (p->fid == fid && EqFont (m, p->mat))
X 		 {
X 		 	if (cache_ring->cache_next != p)
X 				CacheInsert (cache_ring->cache_next, CacheRemove (p));
X 			return cache_ring->cache_next;
X 		 }
X 	
X 	return NULL;
X }
X
Xint FindCache ()
X {
X 	HardPoint origin;
X 	float left, right, top, bottom;
X 	int width, height, swidth, sheight;
X 	
X 	if ((gstate->show->ccache = SearchCache (gstate->CTM, fidCache)) != NULL)
X 		return TRUE;
X 	Message ("building a new cache");
X	DeviceBBox (&left, &right, &top, &bottom,
X			fontbboxCache[BBOX_LEFT], fontbboxCache[BBOX_RIGHT], fontbboxCache[BBOX_BOTTOM], fontbboxCache[BBOX_TOP]);
X 	
X 	width = right - left; height = top - bottom;
X 	if (CharTooBig ((float) width, (float) height))
X 	 {
X 	 	Message ("character too big to cache");
X		return TRUE;
X	 }
X 	
X 	if (msize == mmax)
X 		DestroyCache (CacheRemove (cache_ring->cache_prev));
X	
X	origin = ExtToInt (NewPoint (0.0, 0.0));
X	swidth = origin.hx - left; sheight = origin.hy - bottom;
X 	
X 	CacheInsert (cache_ring->cache_next,
X 			NewCache (fidCache,
X 				gstate->CTM,
X 				width, height,
X 				swidth, sheight));
X 	gstate->show->ccache = cache_ring->cache_next;
X 	
X 	LoadDiskCache (gstate->CTM, fontbboxCache);
X 	
X 	return TRUE;
X }
X
Xint CacheShow (name, cp) Object name; HardPoint cp;
X {
X 	struct char_table *b;
X 	struct cache *ccache = gstate->show->ccache;
X 	DevicePoint from, to, extent;
X 	
X 	if (!ccache)
X 		return FALSE;
X 	gstate->show->CharName = name;
X 	if ((b = CharLoad (name)) == NULL)
X 		return FALSE;
X 	/* SetCharWidth (b->char_width); */
X 	gstate->show->Width = b->char_width;
X 	
X 	from.dx = from.dy = 0;
X 	to.dx = cp.hx - ccache->swidth;
X 	to.dy = cp.hy - ccache->sheight;
X	extent.dx = ccache->width; extent.dy = ccache->height;
X	
X	Paint (b->char_device->dev, gstate->device->dev, from, to, extent, gstate->colour);
X 	
X	return TRUE;
X }
X
Xstatic struct cache *NewCache (fid, m, width, height, swidth, sheight)
X	int fid; Matrix m; int width, height, swidth, sheight;
X {
X 	struct cache *res = (struct cache *) Malloc (sizeof (struct cache));
X 	
X 	m.tx = m.ty = 0.0;
X 	res->fid	= fid;
X 	res->mat	= m;
X 	res->width	= width;
X 	res->height	= height;
X 	res->swidth	= swidth;
X 	res->sheight	= sheight;
X	
X 	return res;
X }
X
Xstatic DestroyCache (p) struct cache *p;
X {
X	FlushChars (p);
X 	Free ((char *) p);
X }
X
Xstatic CacheInsert (where, cache) struct cache *where, *cache;
X {
X 	cache->cache_next = where; cache->cache_prev = where->cache_prev;
X 	where->cache_prev->cache_next = cache;
X 	where->cache_prev = cache;
X 	++msize;
X }
X
Xstatic struct cache *CacheRemove (item) struct cache *item;
X {
X 	item->cache_prev->cache_next = item->cache_next;
X 	item->cache_next->cache_prev = item->cache_prev;
X 	--msize;
X 	
X 	return item;
X }
X
Xstatic int SetCacheLimit (mb) Object mb;
X {
X 	int b = BodyInteger (mb);
X 	if (b < 0)
X 		return Error (PRangeCheck);
X 	maxbits = b;
X 	return TRUE;
X }
X
Xstatic int SetCache (bitmap, fonts, chars) Object bitmap, fonts, chars;
X {
X 	int b = BodyInteger (bitmap);
X 	int f = BodyInteger (fonts);
X 	int c = BodyInteger (chars);
X 	
X 	if (b < 0 || f < 0 || c < 0)
X 		return Error (PRangeCheck);
X 	bmax = b; mmax = f; cmax = c;
X 	InitCharTable ();
X 	return TRUE;
X }
X
Xstatic int CacheStatus ()
X {
X 	VOID Push (OpStack, MakeInteger (bsize));
X  	VOID Push (OpStack, MakeInteger (bmax));
X 	VOID Push (OpStack, MakeInteger (msize));
X 	VOID Push (OpStack, MakeInteger (mmax));
X 	VOID Push (OpStack, MakeInteger (csize));
X 	VOID Push (OpStack, MakeInteger (cmax));
X 	VOID Push (OpStack, MakeInteger (maxbits));
X 	
X 	return TRUE;
X}
X
XLoadDiskCache (m, bbox) Matrix m; float *bbox;
X {
X 	Object font_name;
X 	FILE *fp;
X 	Vector origin, right, bottom;
X 	char disk_name [BUFSIZE], *bits, mess[BUFSIZ];
X/* 	struct hardware *screen = gstate->device->dev; */
X 	
X 	Message ("Attempting to find a cache on disk");
X 	font_name = DictLoad (gstate->font, FontName);
X 	if (TypeOf (font_name) != Name)
X 		return;
X 	origin = Transform (NewVector (bbox [BBOX_LEFT], bbox [BBOX_TOP], 1.0), m);
X 	right  = DiffVector (Transform (NewVector (bbox [BBOX_RIGHT], bbox [BBOX_TOP], 1.0), m),    origin);
X 	bottom = DiffVector (Transform (NewVector (bbox [BBOX_LEFT],  bbox [BBOX_BOTTOM], 1.0), m), origin);
X 	VOID sprintf (disk_name,
X 		"%s/cache/%.*s/%3d%3d%3d%3d",
X 		library,
X 		lengthName (font_name), BodyName (font_name),
X 		(int) right.vx, (int) right.vy, (int) bottom.vx, (int) bottom.vy);
X 	Message (disk_name);
X 	if ((fp = fopen (disk_name, "r")) == NULL)
X 		return;
X 	Message ("found a disk cache");
X 	VOID GSave ();
X 	bits = Malloc ((unsigned) maxbits);
X 	
X  	sprintf (mess, "width = %d, height = %d\n", gstate->show->ccache->width, gstate->show->ccache->height);
X 	Message (mess);
X	sprintf (mess, "computed length = %d", gstate->show->ccache->height * ((gstate->show->ccache->width + 7) / 8));
X 	Message (mess);
X 	
X 	while (!feof (fp))
X 	 {
X 	 	char char_name [BUFSIZE];
X 	 	struct hardware *newdev;
X 	 	int width, height, length;
X 	 	
X 	 	if (fscanf (fp, "%s %d %d %d\n",
X 	 			char_name,
X 	 			&width, &height,
X 	 			&length) == EOF)
X 	 		break;
X	  	VOID fread (bits, (unsigned) length, 1, fp);
X 	 	VOID getc (fp);
X 	 	newdev = HardwareFromString (bits, gstate->show->ccache->width, gstate->show->ccache->height);
X /*	 	VOID BitBlt (newdev, screen,
X 	 			NewDevicePoint (0, 0), NewDevicePoint (200, 200),
X 	 			NewDevicePoint (gstate->show->ccache->width, gstate->show->ccache->height),
X 	 			ROP_SOURCE);
X*/	 	
X 	 	VOID SetCacheDevice (NameFrom (char_name),
X 	 			NewPoint ((float) width, (float) height),
X 	 			bbox [BBOX_LEFT],  bbox [BBOX_TOP],
X 	 			bbox [BBOX_RIGHT], bbox [BBOX_BOTTOM]);
X	 	
X	 	VOID BitBlt (newdev, gstate->device->dev,
X 	 			NewDevicePoint (0, 0), NewDevicePoint (0, 0),
X 	 			NewDevicePoint (gstate->show->ccache->width, gstate->show->ccache->height),
X 	 			ROP_SOURCE);
X 	 	DestroyHardware (newdev);
X 	 }
X 	Free (bits);
X 	VOID GRestore ();
X 	VOID fclose (fp);
X 	Message ("load completed");
X }
X
Xstatic int SaveCurrentFont ()
X {
X 	Matrix fm, m;
X 	Vector origin, right, bottom;
X 	Object font_name;
X 	FILE *fp;
X 	char disk_name [BUFSIZE];
X 	int i;
X 	float bbox[4];
X 	struct cache *ccache;
X 	
X 	ExtractMatrix (&fm, DictLoad (gstate->font, FontMatrix));
X 	m = MatMult (fm, gstate->CTM);
X 	ExtractBBox (bbox, DictLoad (gstate->font, FontBBox));
X 	font_name = DictLoad (gstate->font, FontName);
X 	
X 	origin = Transform (NewVector (bbox [BBOX_LEFT], bbox [BBOX_TOP], 1.0), m);
X 	right  = DiffVector (Transform (NewVector (bbox [BBOX_RIGHT], bbox [BBOX_TOP], 1.0), m),    origin);
X 	bottom = DiffVector (Transform (NewVector (bbox [BBOX_LEFT],  bbox [BBOX_BOTTOM], 1.0), m), origin);
X  	
X	if ((ccache = SearchCache (m, BodyFontID (DictLoad (gstate->font, Fid)))) == NULL)
X 		return Error (PInvFont);
X 	
X  	Message (disk_name);
X	VOID sprintf (disk_name,
X 		"%s/cache/%.*s/%3d%3d%3d%3d",
X 		library,
X 		lengthName (font_name), BodyName (font_name),
X 		(int) right.vx, (int) right.vy, (int) bottom.vx, (int) bottom.vy);
X 	
X 	if ((fp = fopen (disk_name, "w")) == NULL)
X 		return Error (PInvFileAccess);
X 	
X 	for (i = 0; i < cmax; i++)
X 	 if (CharTable[i].char_cache == ccache)
X 	  {
X 	  	Object char_name;
X 	  	char *bits;
X 	  	DevicePoint extent;
X 	  	int length;
X 	  	
X 	  	char_name = CharTable[i].char_key;
X 	  	extent = HardwareExtent (CharTable[i].char_device->dev);
X 	  	length = (extent.dx + 7) / 8 * extent.dy;
X 	 	bits = StringFromHardware (CharTable[i].char_device->dev);
X	 	VOID fprintf (fp,
X 	 		"%.*s %d %d %d\n",
X 	 		lengthName (char_name), BodyName (char_name),
X 	 		(int) CharTable [i].char_width.x,
X 	 		(int) CharTable [i].char_width.y,
X 	 		length);
X 	 	VOID fwrite (bits, (unsigned) length, 1, fp);
X 	 	putc ('\n', fp);
X/*  	 	Free (bits);*/
X	 		
X 	  }
X 	
X 	VOID fclose (fp);
X 	
X 	return TRUE;
X }
END_OF_FILE
if test 14908 -ne `wc -c <'source/cache.c'`; then
    echo shar: \"'source/cache.c'\" unpacked with wrong size!
fi
# end of 'source/cache.c'
fi
if test -f 'source/fill.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'source/fill.c'\"
else
echo shar: Extracting \"'source/fill.c'\" \(14650 characters\)
sed "s/^X//" >'source/fill.c' <<'END_OF_FILE'
X/*
X * Copyright (C) Rutherford Appleton Laboratory 1987
X * 
X * This source may be copied, distributed, altered or used, but not sold for profit
X * or incorporated into a product except under licence from the author.
X * It is not in the public domain.
X * This notice should remain in the source unaltered, and any changes to the source
X * made by persons other than the author should be marked as such.
X * 
X *	Crispin Goswell @ Rutherford Appleton Laboratory caag@uk.ac.rl.vd
X */
X#include "main.h"
X#include "graphics.h"
X
X#define MAXPATHELEMENTS	15000
X
X/*
X * Trapezoid decomposition algorithm:
X * 
X *	Edges are characterised by a line description, with topY, bottomY, topX, bottomX, startingY
X * 	Build edge lists from path.
X *	Sort edges on top Y value.
X *	find topmost interestingY value, which will be the minimum topY. This becomes interestingY.
X *	loop
X *		examine edge list from here to end. Move edges with topY value less than interestingY into
X *			interesting edge set, computing intersections for each as you go. This should establish next
X *			interestingY value, nextY.
X *		form the pairings for all edges in the interesting set, according to the fill rule at interestingY.
X *			to do this, while inside, keep a pointer to the last up-transition edge, and pair it with the
X *			next down-transition edge.
X *			for any edges which have changed pairing, emit a trapezoid from their startingY to interestingY,
X *			(if they were paired) and set their startingY to interestingY
X *		break if (ninteresting == 0 && nedges_left == 0)
X *		interestingY := nextY
X *	pool
X */		
X
Xstatic struct edge
X {
X	int topX, topY, bottomX, bottomY; short dir;
X	struct edge *pair;
X	int startingY, where, up, clip;
X	int name;
X };
X
Xint names = 0;
X
Xextern int in_stroke;
X
Xint InitClip ();
Xstatic int Clip ();
Xstatic int EOClip ();
Xint Fill ();
Xstatic int EOFill ();
Xstatic int PClipPath ();
X
XInitFill ()
X {
X 	InstallOp ("initclip",		InitClip,	0, 0, 0, 0);
X 	InstallOp ("clip",		Clip,		0, 0, 0, 0);
X 	InstallOp ("eoclip",		EOClip,		0, 0, 0, 0);
X 	InstallOp ("fill",		Fill,		0, 0, 0, 0);
X 	InstallOp ("eofill",		EOFill,		0, 0, 0, 0);
X 	InstallOp ("clippath",		PClipPath,	0, 0, 0, 0);
X }
X
Xstatic struct hardware *output_device;
Xstatic Colour output_colour;
X
Xstatic int FillIt ();
Xstatic int EoRule (), NwRule ();
X
Xstatic void EmitTrapezoid (left, right, top, bottom) struct edge *left, *right; int top, bottom;
X {
X 	struct edge *temp;
X 	
X 	if (left->topX > right->topX || left->bottomX > right->bottomX)
X 		temp = left, left = right, right = temp;
X 	PaintTrapezoid (output_device,
X 		NewDevicePoint (left->topX, left->topY),
X 		NewDevicePoint (left->bottomX, left->bottomY),
X 		NewDevicePoint (right->topX, right->topY),
X 		NewDevicePoint (right->bottomX, right->bottomY),
X 		top, bottom,
X 		output_colour);
X }
X
Xint Fill ()
X {
X	int res;
X	
X	if (gstate->device->dev == NULL)
X		return PNewPath ();
X	
X	output_device = gstate->device->dev;
X	output_colour = gstate->colour;
X 	res = FillIt (gstate->path, NwRule, gstate->clip, NwRule, EmitTrapezoid);
X 						/* XXX needs optimising */
X 	
X	VOID PNewPath ();
X	
X	return res;
X }
X
Xstatic int EOFill ()
X {
X	int res;
X	
X	if (gstate->device->dev == NULL)
X		return PNewPath ();
X	
X 	output_device = gstate->device->dev;
X	output_colour = gstate->colour;
X	res = FillIt (gstate->path, EoRule, gstate->clip, NwRule, EmitTrapezoid);
X 						/* XXX needs optimising */
X 	
X	VOID PNewPath ();
X	
X	return res;
X }
X
Xstatic Path output_path;
X
Xstatic void PathTrapezoid (left, right, top, bottom) struct edge *left, *right; int top, bottom;
X {
X 	int ll, ul, lr, ur;
X 	struct edge *temp;
X 	
X 	if (left->topX > right->topX || left->bottomX > right->bottomX)
X 		temp = left, left = right, right = temp;
X 	
X 	ll = Xvalue (left->topX, left->topY, left->bottomX, left->bottomY, bottom);
X 	ul = Xvalue (left->topX, left->topY, left->bottomX, left->bottomY, top);
X 	lr = Xvalue (right->topX, right->topY, right->bottomX, right->bottomY, bottom);
X 	ur = Xvalue (right->topX, right->topY, right->bottomX, right->bottomY, top);
X 	
X 	MoveTo (output_path, NewHardPoint ((float) ll, (float) bottom));
X 	LineTo (output_path, NewHardPoint ((float) lr, (float) bottom));
X 	LineTo (output_path, NewHardPoint ((float) ur, (float) top));
X 	LineTo (output_path, NewHardPoint ((float) ul, (float) top));
X 	ClosePath (output_path);
X }
X
Xint InitClip ()
X {
X 	PathFree (gstate->clip);
X 	gstate->clip = PathCopy (gstate->device->default_clip);
X 	
X 	UnlinkDevice (gstate->clipdevice);
X  	gstate->clipdevice = NULL;
X  	
X 	SetClipHardware (gstate->device->dev, NULL);
X	
X	return TRUE;
X }
X
Xstatic int Clip ()
X {
X	int res;
X	
X	
X	output_path = NewPath ();
X 	res = FillIt (gstate->path, NwRule, gstate->clip, NwRule, PathTrapezoid);
X 						/* XXX - needs optimising */
X 	
X 	PathFree (gstate->clip);
X 	gstate->clip = output_path;
X 	
X 	if (res)
X 	 {
X  		gstate->clipdevice = UniqueDevice (gstate->clipdevice);
X  		SetClipHardware (gstate->device->dev, gstate->clipdevice->dev);
X  		
X		output_device = gstate->clipdevice->dev;
X 		output_colour = NewColour (0.0, 0.0, 0.0);
X 		res = FillIt (gstate->clip, NwRule, gstate->device->default_clip, NwRule, EmitTrapezoid);
X 	 }
X	return res;
X }
X
Xstatic int EOClip ()
X {
X	int res;
X	
X	output_path = NewPath ();
X	res = FillIt (gstate->path, EoRule, gstate->clip, NwRule, PathTrapezoid);
X 						/* XXX - needs optimising */
X 	
X 	PathFree (gstate->clip);
X 	gstate->clip = output_path;
X 	
X 	if (res)
X 	 {
X 		gstate->clipdevice = UniqueDevice (gstate->clipdevice);
X    		SetClipHardware (gstate->device->dev, gstate->clipdevice->dev);
X   		
X		output_device = gstate->clipdevice->dev;
X 		output_colour = NewColour (0.0, 0.0, 0.0);
X 		res = FillIt (gstate->clip, NwRule, gstate->device->default_clip, NwRule, EmitTrapezoid);
X 	 }
X	return res;
X }
X
Xstatic int PClipPath ()
X {
X 	PathFree (gstate->path);
X 	gstate->path = PathCopy (gstate->clip);
X 	gstate->cp_defined = TRUE;
X 	gstate->cp = gstate->path->last->pe.point;
X 	
X 	return TRUE;
X }
X
X/****************************/
X
Xstatic struct edge edge [MAXPATHELEMENTS];
X
Xstatic struct edge *interesting [MAXPATHELEMENTS];
X
Xstatic int nedges, here, ninteresting;
X
Xstatic int interestingY, nextY;
X
Xstatic int infinity;
X
Xstatic int FillIt (path_a, rule_a, path_b, rule_b, emitfn)
X	Path path_a, path_b; int (*rule_a)(), (*rule_b)(); void (*emitfn)();
X {
X	Path new;
X	static int edgecmp ();
X	static void Trapezoids (), BuildEdgeList ();
X	
X	if (EmptyPath (path_a) || EmptyPath (path_b))
X		return TRUE;
X	
X	path_a = FlattenPath (path_a);
X	path_b = FlattenPath (path_b);
X	
X	if (!CloseAll (path_a) || !CloseAll (path_b))
X	 {
X		PathFree (path_a);
X		PathFree (path_b);
X		
X		return FALSE;
X	 }
X	
X	nedges = 0;
X	BuildEdgeList (path_a, TRUE);
X	BuildEdgeList (path_b, FALSE);
X 	qsort ((char *) edge, (unsigned) nedges, sizeof (struct edge), edgecmp);
X	PathFree (path_a);
X	PathFree (path_b);
X	Trapezoids (rule_a, rule_b, emitfn);
X	
X	return TRUE;
X }
X
Xstatic void AddLowest ();
X
Xstatic void Trapezoids (rule_a, rule_b, emitfn) int (*rule_a)(), (*rule_b)(); void (*emitfn)();
X {
X	static void FindInfinity (), AddInteresting ();
X	
X	nextY = edge[0].topY;
X	AddLowest (nextY);
X	FindInfinity ();
X	
X	here = 0;
X	ninteresting = 0;
X	names = 0;
X	
X	while (here != nedges || ninteresting)
X	 {
X	 	static void RemoveEdges ();
X	 	
X	 	interestingY = nextY;
X	 	ProcessEdges (rule_a, rule_b, emitfn);
X	 	
X	 	AddInteresting ();
X	 	
X	 	RemoveEdges (interestingY, emitfn);
X	 	
X	 	ProcessEdges (rule_a, rule_b, emitfn);
X	 }
X }
X
XProcessEdges (rule_a, rule_b, emitfn) int (*rule_a)(), (*rule_b)(); void (*emitfn)();
X {
X	struct edge *up_edge;
X	int i, count_a = 0, count_b = 0;
X	static void RemoveEdges ();
X	
X	for (i = 0; i < ninteresting; i++)
X	 {
X	 	static void Emit ();
X	 	int d_a = 0, d_b = 0;
X	 	
X	 	if (interesting[i]->clip)
X	 		d_a = interesting[i]->dir;
X	 	else
X	 		d_b = interesting[i]->dir;
X
X	 	if (UpEdge (count_a, count_b, d_a, d_b, rule_a, rule_b))
X	 		up_edge = interesting[i];
X	 	else if (DownEdge (count_a, count_b, d_a, d_b, rule_a, rule_b))
X	 	 	ThisBit (up_edge, interesting[i], interestingY, emitfn);
X	 	else
X	 	 	NotThisBit (interesting[i], interestingY, emitfn);
X	 	
X	 	count_a += d_a;
X	 	count_b += d_b;
X	 }
X	if (count_a || count_b)
X		fprintf (stderr, "count_a = %dcount_b = %d\n", count_a, count_b);
X	PanicIf (count_a || count_b, "something wrong in area fill");
X }
X
XThisBit (left, right, where, emitfn) struct edge *left, *right; int where; void (*emitfn)();	
X {
X 	if (left->pair != right || right->up)
X 	 {
X 	 	if (left->pair != NULL)
X 		 {
X 			(*emitfn) (left, left->pair, left->startingY, left->where);
X 			left->pair->startingY = left->pair->where;
X  			left->pair->pair->startingY = left->pair->pair->where;
X  			left->pair->pair = NULL;
X		 }
X 		if (right->pair != NULL)
X 		 {
X 			(*emitfn) (right, right->pair, right->startingY, right->where);
X 			right->pair->startingY = right->pair->where;
X  			right->pair->pair->startingY = right->pair->pair->where;
X  			right->pair->pair = NULL;
X		 }
X 		
X  		left->pair = right;
X 		right->pair = left;
X 		left->startingY = right->startingY = where;
X	 }
X 	left->where = right->where = where;
X 	left->up = TRUE; right->up = FALSE;
X }
X
XNotThisBit (edge, where, emitfn) struct edge *edge; int where; void (*emitfn)();	
X {
X 	if (edge->pair != NULL)
X 	 {
X 		(*emitfn) (edge, edge->pair, edge->startingY, where);
X 		edge->pair->startingY = where;
X 		edge->pair->where = where;
X 		edge->pair->pair = NULL;
X 		edge->pair = NULL;
X	 }
X  	edge->startingY = where;
X 	edge->where = where;
X }
X
Xstatic void RemoveEdges (interestingY, emitfn) int interestingY; void (*emitfn)();
X {
X 	int i, j = 0;
X 	
X 	for (i = 0; i < ninteresting; i++)
X		if (interesting [i]->bottomY > interestingY)
X 			interesting [j++] = interesting [i];
X 		else
X 			NotThisBit (interesting[i], interestingY, emitfn);
X 	ninteresting = j;
X }
X
Xstatic int UpEdge (count_a, count_b, inc_a, inc_b, rule_a, rule_b) int count_a, count_b, inc_a, inc_b, (*rule_a) (), (*rule_b) ();
X {
X 	return (*rule_b)(count_b + inc_b) && !(*rule_a) (count_a) && (*rule_a) (count_a + inc_a) ||
X 		(*rule_a)(count_a + inc_a) && !(*rule_b) (count_b) && (*rule_b) (count_b + inc_b);
X }
X
Xstatic int DownEdge (count_a, count_b, inc_a, inc_b, rule_a, rule_b) int count_a, count_b, inc_a, inc_b, (*rule_a) (), (*rule_b) ();
X {
X 	return (*rule_b)(count_b + inc_b) && (*rule_a) (count_a) && !(*rule_a) (count_a + inc_a) ||
X 		(*rule_a)(count_a + inc_a) && (*rule_b) (count_b) && !(*rule_b) (count_b + inc_b);
X }
X
Xstatic int EoRule (n) int n;
X {
X	return n & 1;
X }
X
Xstatic int NwRule (n) int n;
X {
X	return n;
X }
X
Xstatic float Yintersect (a, b) struct edge *a, *b;
X {
X 	float
X 		num =   (a->bottomX * a->topY - a->bottomY * a->topX) * (b->topY - b->bottomY) -
X 			(b->bottomX * b->topY - b->bottomY * b->topX) * (a->topY - a->bottomY),
X 		denom = (a->bottomX - a->topX) * (b->topY - b->bottomY) -
X 			(b->bottomX - b->topX) * (a->topY - a->bottomY);
X 	
X 	if (denom == 0)
X 	 {
X 		return infinity;
X 	 }
X	return num / denom;
X }
X
Xstatic int Xvalue (ax, ay, bx, by, cy) int ax, ay, bx, by, cy;
X {
X 	return bx + (cy - by) * (ax - bx) / (float) (ay - by);
X }
X
Xstatic int intercmp (aa, bb) char *aa, *bb;
X {
X 	struct edge *a = *(struct edge **) aa, *b = *(struct edge **) bb;
X 	int sign;
X	
X	sign = Xvalue (a->topX, a->topY, a->bottomX, a->bottomY, interestingY + 1) -
X		     Xvalue (b->topX, b->topY, b->bottomX, b->bottomY, interestingY + 1);
X	if (sign == 0)
X		return a->bottomX - b->bottomX;
X	return sign;
X }
X
Xstatic void AddInteresting ()
X {
X	int i;
X	 	
X	nextY = infinity;
X	for (; here < nedges && edge[here].topY <= interestingY; here++) /* look at each new interesting edge */
X	 {
X	 	int i, n;
X	 	
X		for (i = 0; i < ninteresting; i++) /* look at all possible intersections */
X		 {
X		 	int inter = Yintersect (&edge[here], interesting[i]);
X		 	
X		 	if (inter >= interestingY && inter <= edge[here].bottomY && inter <= interesting[i]->bottomY)
X		 		AddLowest (inter);
X		 }
X		n = ninteresting++;
X		interesting[n] = &edge[here];
X		interesting[n]->pair = NULL;
X		interesting[n]->up = FALSE;
X		interesting[n]->startingY = interesting[n]->where = edge[here].topY;
X		interesting[n]->name = names++;
X	 }
X	i = NextLowest (interestingY);
X	if (i)
X		nextY = i;
X	if (here != nedges && edge[here].topY < nextY)
X		nextY = edge[here].topY;
X	for (i = 0; i < ninteresting; i++)
X	 {
X		if (interesting[i]->topY > interestingY && interesting[i]->topY < nextY)
X			nextY = interesting[i]->topY;
X		if (interesting[i]->bottomY > interestingY && interesting[i]->bottomY < nextY)
X			nextY = interesting[i]->bottomY;
X	 }
X	qsort ((char *) interesting, (unsigned) ninteresting, sizeof (struct edge *), intercmp);
X }
X
Xstatic void FindInfinity ()
X {
X 	int i;
X 	
X	infinity = edge[0].topY;
X	for (i = 0; i < nedges; i++)
X		if (edge[i].bottomY > infinity)
X			infinity = edge[i].bottomY;
X }
X
X/***************************/
X
Xstatic int edgecmp (a, b) char *a, *b;
X {
X 	struct edge *aa = (struct edge *) a, *bb = (struct edge *) b;
X 	
X 	return aa->topY - bb->topY;
X }
X
Xstatic int AddEdge (e, from, to, clip) struct edge *e; HardPoint from, to; int clip;
X {
X 	int dir = 1;
X 	HardPoint temp;
X 	
X 	if ((int) (from.hy) == (int) (to.hy))
X 		return 0;
X 	if ((int) (from.hy) > (int) (to.hy))
X 	 {
X 		temp = from; from = to; to = temp;
X 		dir = -dir;
X 	 }
X 	e->topX = from.hx;
X  	e->topY = from.hy;
X	e->bottomX = to.hx;
X 	e->bottomY = to.hy;
X	e->dir = dir;
X	e->clip = clip;
X	
X 	return 1;
X }
X
Xstatic void BuildEdgeList (path, clip) Path path; int clip;
X {
X 	Path p;
X 	HardPoint move, here;
X 	
X 	for (p = path->next; p != path; p = p->next)
X 	 switch (p->ptype)
X 	  {
X 	  	case EMove: move = here = p->pe.point; break;
X 	  	case ELine:
X 	  		nedges += AddEdge (&edge[nedges], here, p->pe.point, clip);
X 	  		here = p->pe.point;
X 	  		break;
X 	  	
X 	  	case EClose:
X 	  		nedges += AddEdge (&edge[nedges], here, move, clip);
X 	  		here = move;
X 	  		break;
X 	  }
X }
X
X/* keep list of interesting entries to come */
X
Xstruct lowest
X {
X	struct lowest *higher;
X	int e;
X } *lowest_free = NULL, *lowest = NULL;
X
Xstatic int NextLowest (y) int y;
X {
X	int res;
X	struct lowest *p;
X	
X	for (p = lowest; p && p->e <= y; p = lowest)	/* delete any which are now irrelevent */
X	 {
X	 	lowest = p->higher;
X	 	p->higher = lowest_free;
X	 	lowest_free = p;
X	 }
X	
X	if (lowest == NULL)
X		return 0;
X	res = lowest->e;
X	
X	return res;
X }
X
Xstatic void AddLowest (e) int e;
X {
X 	struct lowest *res, *p, *q;
X 	
X 	for (p = lowest; p && p->e < e; q = p, p = p->higher)
X 		;
X 	
X 	if (p && p->e == e)
X 		return;
X	if (lowest_free == NULL)
X 		res = (struct lowest *) Malloc (sizeof (struct lowest));
X 	else
X 		res = lowest_free, lowest_free = lowest_free->higher;
X 	
X  	res->e = e;
X 	res->higher = p;
X 	if (p != lowest)
X 		q->higher = res;
X 	else
X 		lowest = res;
X }
END_OF_FILE
if test 14650 -ne `wc -c <'source/fill.c'`; then
    echo shar: \"'source/fill.c'\" unpacked with wrong size!
fi
# end of 'source/fill.c'
fi
echo shar: End of archive 12 \(of 18\).
cp /dev/null ark12isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 18 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0