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