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