home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume12 / postscript / part12 < prev    next >
Encoding:
Internet Message Format  |  1987-11-07  |  47.5 KB

  1. Subject:  v12i061:  A PostScript interpreter, Part12/18
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rs@uunet.UU.NET
  5.  
  6. Submitted-by: Crispin Goswell <caag@vd.rl.ac.uk>
  7. Posting-number: Volume 12, Issue 61
  8. Archive-name: postscript/part12
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 12 (of 18)."
  17. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  18. if test -f 'source/X.c' -a "${1}" != "-c" ; then 
  19.   echo shar: Will not clobber existing file \"'source/X.c'\"
  20. else
  21. echo shar: Extracting \"'source/X.c'\" \(15122 characters\)
  22. sed "s/^X//" >'source/X.c' <<'END_OF_FILE'
  23. X/*
  24. X * Copyright (C) Rutherford Appleton Laboratory 1987
  25. X * 
  26. X * This source may be copied, distributed, altered or used, but not sold for profit
  27. X * or incorporated into a product except under licence from the author.
  28. X * It is not in the public domain.
  29. X * This notice should remain in the source unaltered, and any changes to the source
  30. X * made by persons other than the author should be marked as such.
  31. X * 
  32. X *    Crispin Goswell @ Rutherford Appleton Laboratory caag@uk.ac.rl.vd
  33. X */
  34. X#include "X/Xlib.h"
  35. X
  36. X#include "main.h"
  37. X#include "graphics.h"
  38. X
  39. X#define TRANSFER_SIZE    256
  40. X#define XMAX        65535
  41. X
  42. Xstatic int transfer [TRANSFER_SIZE + 1];
  43. X
  44. Xstatic unsigned char reverse [0x100];
  45. X
  46. Xstruct hardware
  47. X {
  48. X     Window win;
  49. X     struct bitmap *bm;
  50. X     int width, height;
  51. X };
  52. X
  53. Xstruct bitmap
  54. X {
  55. X     short *data;
  56. X     Bitmap xbm;
  57. X     int width, height;
  58. X };
  59. X
  60. Xstruct hardcolour
  61. X {
  62. X     int pixel;
  63. X     Pixmap tile;
  64. X };
  65. X
  66. Xstruct screen
  67. X {
  68. X     float val;
  69. X     int sx, sy;
  70. X     Pixmap shade;
  71. X } *screen = NULL;
  72. X
  73. Xstatic int screen_size, screen_side;
  74. X
  75. Xchar *malloc ();
  76. X
  77. Xstatic Display *theDisplay;
  78. Xstatic float magnification;
  79. X
  80. Xstatic void InitTransfer ();
  81. Xstatic struct hardcolour HardColour ();
  82. X
  83. Xstruct hardware *InitHardware ()
  84. X {
  85. X    if ((theDisplay = XOpenDisplay ("")) == NULL)
  86. X     {
  87. X         fprintf (stderr, "Could not open display\n");
  88. X         exit (1);
  89. X     }
  90. X    magnification = DisplayHeight () / (11.0 * 72);
  91. X    XSetDisplay (theDisplay);
  92. X    InitReversal ();
  93. X    InitRopMap ();
  94. X    InitTransfer ();
  95. X    
  96. X    return 0;
  97. X }
  98. X
  99. Xstatic struct hardware *NewHardware (win, bm, width, height) Window win; struct bitmap *bm; int width, height;
  100. X {
  101. X     struct hardware *res = (struct hardware *) malloc (sizeof (struct hardware));
  102. X     
  103. X     res->win = win;
  104. X     res->bm = bm;
  105. X     res->width = width;
  106. X     res->height = height;
  107. X     
  108. X     return res;
  109. X }
  110. X
  111. XSetClipHardware (bm, clip) struct hardware *bm, *clip;
  112. X {
  113. X }
  114. X
  115. Xint hard_size (width, height) int width, height;
  116. X {
  117. X    return ((width + 15) / 16) * height;
  118. X }
  119. X
  120. Xstatic struct bitmap *NewBM (width, height) int width, height;
  121. X {
  122. X     struct bitmap *res = (struct bitmap *) malloc (sizeof (struct bitmap));
  123. X     
  124. X     res->data = (short *) calloc (hard_size (width, height), sizeof (short));
  125. X     res->width = width;
  126. X     res->height = height;
  127. X    res->xbm = 0;
  128. X     
  129. X     return res;
  130. X }
  131. X
  132. Xstatic void DestroyBM (bm) struct bitmap *bm;
  133. X {
  134. X     free ((char *) bm->data);
  135. X     if (bm->xbm != 0)
  136. X         XFreeBitmap (bm->xbm);
  137. X     free ((char *) bm);
  138. X }
  139. X
  140. Xstatic Bitmap NeedBitmap (bm) struct bitmap *bm;
  141. X {
  142. X     if (bm->xbm == 0)
  143. X     {
  144. X         bm->xbm = XStoreBitmap (bm->width, bm->height, bm->data);
  145. X     }
  146. X     return bm->xbm;
  147. X }
  148. X
  149. Xstatic OODBitmap (bm) struct bitmap *bm;
  150. X {
  151. X     if (bm->xbm != 0)
  152. X      {
  153. X         XFreeBitmap (bm->xbm);
  154. X         bm->xbm = 0;
  155. X      }
  156. X }
  157. X
  158. Xstruct hardware *NewWindowHardware (width, height) int width, height;
  159. X {
  160. X     Window win = XCreateWindow (RootWindow, 0, 0, width, height, 1, BlackPixmap, WhitePixmap);
  161. X     
  162. X     if (win == 0)
  163. X         return NULL;
  164. X     XMapWindow (win);
  165. X     
  166. X     return NewHardware (win, NULL, width, height);
  167. X }
  168. X
  169. Xstruct hardware *NewBitmapHardware (width, height) int width, height;
  170. X {
  171. X     return NewHardware (0, NewBM (width, height), width, height);
  172. X }
  173. X
  174. Xvoid DestroyHardware (h) struct hardware *h;
  175. X {
  176. X     if (IsWindowHardware (h))
  177. X         XDestroyWindow (h->win);
  178. X     else
  179. X         DestroyBM (h->bm);
  180. X     free ((char *) h);
  181. X }
  182. X
  183. XMatrix DeviceMatrix (width, height) int width, height;
  184. X {
  185. X     return NewMatrix (magnification, 0.0, 0.0, -magnification, 0.0, (float) height);
  186. X }
  187. X
  188. XDevicePoint HardwareExtent (h) struct hardware *h;
  189. X {
  190. X     return h == NULL ? NewDevicePoint (0, 0) : NewDevicePoint (h->width, h->height);
  191. X }
  192. X
  193. Xint IsWindowHardware (h) struct hardware *h;
  194. X {
  195. X     return h->win != 0;
  196. X }
  197. X
  198. Xstatic int single_rop [16];
  199. X
  200. Xstatic InitRopMap ()
  201. X {
  202. X    single_rop [ROP_FALSE]     = single_rop [ROP_NOTAND] = single_rop [ROP_NOR]     = single_rop [ROP_NOTSOURCE] = ROP_FALSE;
  203. X    single_rop [ROP_AND]     = single_rop [ROP_DEST]   = single_rop [ROP_NXOR]    = single_rop [ROP_NOTOR]       = ROP_DEST;
  204. X    single_rop [ROP_ANDNOT] = single_rop [ROP_XOR]      = single_rop [ROP_NOTDEST] = single_rop [ROP_NAND]       = ROP_NOTDEST;
  205. X    single_rop [ROP_SOURCE] = single_rop [ROP_OR]       = single_rop [ROP_ORNOT]   = single_rop [ROP_TRUE]       = ROP_TRUE;
  206. X }
  207. X
  208. Xstatic int Xvalue (ax, ay, bx, by, cy) int ax, ay, bx, by, cy;
  209. X {
  210. X     return bx + (cy - by) * (ax - bx) / (float) (ay - by);
  211. X }
  212. X
  213. Xstatic void PaintBlob (to, top, bottom, left, right, col)
  214. X    struct hardware *to;
  215. X    int top, bottom, *left, *right;
  216. X    struct hardcolour col;
  217. X {
  218. X     int i, op, offset = top;
  219. X     
  220. X    if (col.tile == 0)
  221. X          for (i = top; i <= bottom; i++)
  222. X              XPixSet (to->win, left[i - offset], i, right[i - offset] - left[i - offset] + 1, 1, col.pixel);
  223. X     else
  224. X         for (i = top; i <= bottom; i++)
  225. X             XTileSet (to->win, left[i - offset], i, right[i - offset] - left[i - offset] + 1, 1, col.tile);
  226. X }
  227. X
  228. Xvoid PaintTrapezoid (to, lefttop, leftbottom, righttop, rightbottom, top, bottom, colour)
  229. X    struct hardware *to;
  230. X    DevicePoint lefttop, leftbottom, righttop, rightbottom;
  231. X    int top, bottom;
  232. X    Colour colour;
  233. X {
  234. X     struct hardcolour col;
  235. X     int i, j, temp; char c;
  236. X     static int left [1024], right [1024];
  237. X     
  238. X     int     ltx = Xvalue (lefttop.dx,     lefttop.dy,     leftbottom.dx,     leftbottom.dy,     top),
  239. X         rtx = Xvalue (righttop.dx,     righttop.dy,     rightbottom.dx, rightbottom.dy, top),
  240. X         lbx = Xvalue (lefttop.dx,     lefttop.dy,     leftbottom.dx,     leftbottom.dy,     bottom),
  241. X         rbx = Xvalue (righttop.dx,     righttop.dy,     rightbottom.dx, rightbottom.dy, bottom);
  242. X     
  243. X     col = HardColour (colour);
  244. X     
  245. X     if (ltx == lbx && rtx == rbx)
  246. X      {
  247. X          if (rtx < ltx)
  248. X              temp = rtx, rtx = ltx, ltx = temp;
  249. X          
  250. X         if (col.tile == 0)
  251. X              XPixSet (to->win, ltx, top, rtx - ltx + 1, bottom - top + 1, col.pixel);
  252. X         else
  253. X            XTileSet (to->win, ltx, top, rtx - ltx + 1, bottom - top + 1, col.tile);
  254. X         return;
  255. X      }
  256. X     
  257. X     for (i = top, j = 0; i <= bottom; i++, j++)
  258. X      {
  259. X          int     lx = Xvalue (lefttop.dx,     lefttop.dy,     leftbottom.dx, leftbottom.dy,  i),
  260. X             rx = Xvalue (righttop.dx,     righttop.dy,     rightbottom.dx,rightbottom.dy, i);
  261. X         
  262. X         if (rx < lx)
  263. X             temp = rx, rx = lx, lx = temp;
  264. X         
  265. X         left [j] = lx; right [j] = rx;
  266. X      }
  267. X     PaintBlob (to, top, bottom, left, right, col);
  268. X }
  269. X
  270. Xstatic void RasterBlob (to, top, bottom, left, right, rop)
  271. X    struct hardware *to;
  272. X    int top, bottom, *left, *right, rop;
  273. X {
  274. X     int i, op, offset = top;
  275. X     
  276. X     switch (rop)
  277. X      {
  278. X          case ROP_FALSE:     op = GXclear; break;
  279. X          case ROP_DEST:         return;
  280. X          case ROP_NOTDEST:     op = GXinvert; break;
  281. X          case ROP_TRUE:         op = GXset; break;
  282. X      }
  283. X     for (i = top; i <= bottom; i++)
  284. X         XCopyArea (to->win, 0, 0, left[i - offset], i, right[i - offset] - left[i - offset] + 1, 1, op, ~0);
  285. X }
  286. X
  287. Xstatic void RasterTrapezoid (to, lefttop, leftbottom, righttop, rightbottom, top, bottom, rop)
  288. X    struct hardware *to;
  289. X    DevicePoint lefttop, leftbottom, righttop, rightbottom;
  290. X    int top, bottom, rop;
  291. X {
  292. X     int i, j, temp; char c;
  293. X     static int left [1024], right [1024];
  294. X     
  295. X     int     ltx = Xvalue (lefttop.dx,     lefttop.dy,     leftbottom.dx,     leftbottom.dy,     top),
  296. X         rtx = Xvalue (righttop.dx,     righttop.dy,     rightbottom.dx, rightbottom.dy, top),
  297. X         lbx = Xvalue (lefttop.dx,     lefttop.dy,     leftbottom.dx,     leftbottom.dy,     bottom),
  298. X         rbx = Xvalue (righttop.dx,     righttop.dy,     rightbottom.dx, rightbottom.dy, bottom);
  299. X     
  300. X     if (ltx == lbx && rtx == rbx)
  301. X      {
  302. X          int op;
  303. X          
  304. X          if (rtx < ltx)
  305. X              temp = rtx, rtx = ltx, ltx = temp;
  306. X          
  307. X         switch (rop)
  308. X          {
  309. X              case ROP_FALSE:     op = GXclear; break;
  310. X              case ROP_DEST:         return;
  311. X              case ROP_NOTDEST:     op = GXinvert; break;
  312. X              case ROP_TRUE:         op = GXset; break;
  313. X          }
  314. X         XCopyArea (to->win, 0, 0, ltx, top, rtx - ltx + 1, bottom - top + 1, op, ~0);
  315. X         return;
  316. X      }
  317. X     
  318. X     for (i = top, j = 0; i <= bottom; i++, j++)
  319. X      {
  320. X          int     lx = Xvalue (lefttop.dx,     lefttop.dy,     leftbottom.dx, leftbottom.dy,  i),
  321. X             rx = Xvalue (righttop.dx,     righttop.dy,     rightbottom.dx,rightbottom.dy, i);
  322. X         
  323. X         if (rx < lx)
  324. X             temp = rx, rx = lx, lx = temp;
  325. X         
  326. X         left [j] = lx; right [j] = rx;
  327. X      }
  328. X     RasterBlob (to, top, bottom, left, right, single_rop [rop]);
  329. X }
  330. X
  331. Xvoid Paint (from, to, fromPoint, toPoint, extent, colour)
  332. X    struct hardware *from, *to;
  333. X    DevicePoint fromPoint, toPoint, extent;
  334. X    Colour colour;
  335. X {
  336. X     if (to == NULL)
  337. X         return;
  338. X     if (from && IsWindowHardware (from))
  339. X      {
  340. X          fprintf (stderr, "driver for Paint cannot use Window as source\n");
  341. X          exit (1);
  342. X      }
  343. X     if (IsWindowHardware (to))
  344. X      {
  345. X          struct hardcolour col;
  346. X          
  347. X          col = HardColour (colour);
  348. X          if (col.tile == 0)
  349. X              if (from == NULL)
  350. X                  XPixSet (to->win, toPoint.dx, toPoint.dy, extent.dx, extent.dy, col.pixel);
  351. X              else
  352. X             {
  353. X                Pixmap pm = XMakePixmap (NeedBitmap (from->bm), AllPlanes, 0);
  354. X                
  355. X                   XPixmapPut (to->win, fromPoint.dx, fromPoint.dy, toPoint.dx, toPoint.dy, extent.dx, extent.dy, pm, GXandInverted, AllPlanes);
  356. X                   XFreePixmap (pm);
  357. X                 pm = XMakePixmap (NeedBitmap (from->bm), col.pixel, 0);
  358. X                
  359. X                   XPixmapPut (to->win, fromPoint.dx, fromPoint.dy, toPoint.dx, toPoint.dy, extent.dx, extent.dy, pm, GXor, AllPlanes);
  360. X                   XFreePixmap (pm);
  361. X                }
  362. X         else
  363. X              if (from == NULL)
  364. X                   XTileSet (to->win, toPoint.dx, toPoint.dy, extent.dx, extent.dy, col.tile);
  365. X              else
  366. X             {
  367. X                Pixmap pm = XMakePixmap (NeedBitmap (from->bm), BlackPixel, WhitePixel);
  368. X                
  369. X                   XPixmapPut (to->win, fromPoint.dx, fromPoint.dy, toPoint.dx, toPoint.dy, extent.dx, extent.dy, pm, GXandInverted, AllPlanes);
  370. X                   XFreePixmap (pm);
  371. X                }
  372. X     }
  373. X     else
  374. X      {
  375. X           fprintf (stderr, "driver for Paint cannot use Window as source\n");
  376. X          exit (1);
  377. X     }
  378. X }
  379. X
  380. Xvoid BitBlt (from, to, fromPoint, toPoint, extent, rop)
  381. X    struct hardware *from, *to;
  382. X    DevicePoint fromPoint, toPoint, extent;
  383. X    int rop;
  384. X {
  385. X     if (to == NULL)
  386. X         return;
  387. X     if (IsWindowHardware (to))
  388. X      {
  389. X          fprintf (stderr, "driver for BitBlt cannot use Window as Destination\n");
  390. X          exit (1);
  391. X      }
  392. X     else
  393. X      {
  394. X          if (rop == ROP_SOURCE && fromPoint.dx == 0 && fromPoint.dy == 0 && toPoint.dx == 0 && toPoint.dy == 0)
  395. X           {
  396. X               DevicePoint exfrom, exto;
  397. X               
  398. X               exfrom = HardwareExtent (from); exto = HardwareExtent (to);
  399. X               if (exfrom.dx == extent.dx && exfrom.dy == extent.dy && exto.dx == extent.dx && exto.dy == extent.dy)
  400. X                {
  401. X                    Bcopy ((char *) (to->bm->data), (char *) (from->bm->data), sizeof (short) * hard_size (to->width, to->height));
  402. X                    OODBitmap (to->bm);
  403. X                    
  404. X                    return;
  405. X                }
  406. X                   
  407. X           }
  408. X      }
  409. X     fprintf (stderr, "driver for BitBlt can't cope with general case\n");
  410. X     exit (1);
  411. X }
  412. X
  413. Xvoid PaintLine (h, fromPoint, toPoint, colour) struct hardware *h; DevicePoint fromPoint, toPoint; Colour colour;
  414. X {
  415. X    struct hardcolour col;
  416. X
  417. X    col = HardColour (colour);
  418. X
  419. X    if (col.tile == screen[0].shade)
  420. X        col.pixel = BlackPixel,
  421. X        col.tile = 0;
  422. X    else if (col.tile == screen[screen_size].shade)
  423. X        col.pixel == WhitePixel,
  424. X        col.tile = 0;
  425. X    else
  426. X        ;
  427. X    if (!IsWindowHardware (h))
  428. X     {
  429. X        fprintf (stderr, "driver for PaintLine cannot cope with bitmaps\n");
  430. X        return;
  431. X     }
  432. X    if (col.tile == 0)
  433. X        XLine (h->win, fromPoint.dx, fromPoint.dy, toPoint.dx, toPoint.dy, 1, 1, col.pixel, GXcopy, AllPlanes);
  434. X    else
  435. X     {
  436. X        fprintf (stderr, "driver for PaintLine cannot cope with textured lines\n");
  437. X        XLine (h->win, fromPoint.dx, fromPoint.dy, toPoint.dx, toPoint.dy, 1, 1, col.pixel, GXcopy, AllPlanes);
  438. X     }
  439. X }
  440. X
  441. Xvoid Line (h, fromPoint, toPoint, rop) struct hardware *h; DevicePoint fromPoint, toPoint; Colour rop;
  442. X {
  443. X }
  444. X
  445. Xstruct hardware *HardwareFromString (s, width, height) unsigned char *s; int width, height;
  446. X {
  447. X    int words = (width + 15) / 16;
  448. X    struct bitmap *BM = NewBM (width, height);
  449. X    short *d = BM->data;
  450. X    int odd = ((width + 7) / 8) & 1;
  451. X    int i, j;
  452. X
  453. X    for (i = 0; i < height; i++)
  454. X     {
  455. X        for (j = 0; j < words - odd; j++)
  456. X         {
  457. X            short word = reverse [*s++];
  458. X
  459. X            *d++ = word | (reverse [*s++] << 8);
  460. X         }
  461. X        if (odd)
  462. X            *d++ = reverse [*s++];
  463. X     }
  464. X    return NewHardware (0, BM, width, height);
  465. X }
  466. X
  467. Xchar *StringFromHardware (h) struct hardware *h;
  468. X {
  469. X    int words = (h->width + 15) / 16;
  470. X    char *string = malloc ((h->width + 7) / 8 * h->height), *s = string;
  471. X    int i, j, odd = ((h->width + 7) / 8) & 1;
  472. X    short *d = h->bm->data;
  473. X
  474. X    for (i = 0; i < h->height; i++)
  475. X     {
  476. X        for (j = 0; j < words - odd; j++)
  477. X         {
  478. X            short word = *d++;
  479. X
  480. X            *s++ = reverse [word & 0xFF];
  481. X            *s++ = reverse [(word >> 8) & 0xFF];
  482. X         }
  483. X        if (odd)
  484. X            *s++ = reverse [*d++ & 0xFF];
  485. X     }
  486. X    return string;
  487. X }
  488. X
  489. XInitReversal ()
  490. X {
  491. X    int i, j;
  492. X
  493. X    for (i = 0; i < 0x100; i++)
  494. X     {
  495. X        unsigned char r = 0;
  496. X
  497. X        for (j = 0; j < 8; j++)
  498. X            r |= (1 & (i >> j)) << (7 - j);
  499. X        reverse [i] = r;
  500. X     }
  501. X }
  502. X
  503. Xvoid HardUpdate ()
  504. X {
  505. X     XFlush ();
  506. X }
  507. X
  508. Xstatic struct hardcolour HardColour (colour) Colour colour;
  509. X {
  510. X     struct hardcolour res;
  511. X    int col;
  512. X     
  513. X    if (DisplayPlanes () != 1)
  514. X     {
  515. X        Color def;
  516. X        float r, g, b;
  517. X
  518. X        ColourRGB (colour, &r, &g, &b);
  519. X        def.red = XMAX * r;
  520. X        def.green = XMAX * g;
  521. X        def.blue = XMAX * b;
  522. X
  523. X        XGetHardwareColor (&def);
  524. X
  525. X        res.tile = 0;
  526. X        res.pixel = def.pixel;
  527. X
  528. X        return res;
  529. X     }
  530. X    
  531. X    col = transfer [(int) (TRANSFER_SIZE * colour.brightness + .5)];
  532. X    
  533. X     res.tile = screen[(int) (col * (float) screen_size / TRANSFER_SIZE + 0.5)].shade;
  534. X     
  535. X     return res;
  536. X }
  537. X
  538. Xstatic void InitTransfer ()
  539. X {
  540. X     int i;
  541. X     
  542. X     for (i = 0; i <= TRANSFER_SIZE; i++)
  543. X         transfer [i] = i;
  544. X }
  545. X
  546. Xint TransferSize ()
  547. X {
  548. X    return TRANSFER_SIZE;
  549. X }
  550. X
  551. Xvoid SetTransfer (tran) float *tran;
  552. X {
  553. X     int i;
  554. X     
  555. X     for (i = 0; i < TRANSFER_SIZE; i++)
  556. X         transfer [i] = (TRANSFER_SIZE - 1) * tran[i] + .5;
  557. X }
  558. X
  559. Xint ScreenSize (freq, rot) float freq, rot;
  560. X {
  561. X     int size = magnification * 72 / freq + 0.5;
  562. X     
  563. X     return size * size;
  564. X }
  565. X
  566. Xvoid BuildScreen (freq, rotation, x, y) float freq, rotation, *x, *y;
  567. X {
  568. X     int size = magnification * 72 / freq + 0.5;
  569. X     int i, j;
  570. X     
  571. X     for (i = 0; i < size; i++)
  572. X         for (j = 0; j < size; j++)
  573. X             *x++ = (2 * i - size + 1) / (float) size,
  574. X             *y++ = (2 * j - size + 1) / (float) size;
  575. X }
  576. X
  577. Xstatic sgn (a) float a;
  578. X {
  579. X    if (a == 0)
  580. X        return 0;
  581. X    else if (a < 0)
  582. X        return -1;
  583. X    else
  584. X        return 1;
  585. X }
  586. X
  587. Xstatic int screen_cmp (a, b) char *a, *b;
  588. X {
  589. X     struct screen *aa = (struct screen *) a, *bb = (struct screen *) b;
  590. X     
  591. X     return sgn (aa->val - bb->val);
  592. X }
  593. X
  594. Xvoid SetScreen (freq, rotation, thresh) float freq, rotation, *thresh;
  595. X {
  596. X     struct bitmap *temp;
  597. X     int i, j, size = magnification * 72 / freq + 0.5;
  598. X     struct screen *p;
  599. X     
  600. X     if (screen)
  601. X      {
  602. X          for (i = 0; i < screen_size; i++)
  603. X              XFreePixmap (screen [i].shade);
  604. X          free ((char *) screen);
  605. X      }
  606. X     p = screen = (struct screen *) malloc (((screen_size = size * size) + 1) * sizeof (struct screen));
  607. X     screen_side = size;
  608. X     for (i = 0; i < size; i++)
  609. X         for (j = 0; j < size; j++)
  610. X          {
  611. X              p->val = *thresh++;
  612. X              p->sx = i;
  613. X              p->sy = j;
  614. X              ++p;
  615. X          }
  616. X     qsort ((char *) screen, (unsigned) screen_size, sizeof (struct screen), screen_cmp);
  617. X     
  618. X     temp = NewBM (size, size);
  619. X     
  620. X     for (i = 0; i < screen_size; i++)
  621. X      {
  622. X          screen [i].shade = XMakePixmap (NeedBitmap (temp), WhitePixel, BlackPixel);
  623. X          SetBit (temp, screen[i].sx, screen[i].sy);
  624. X          OODBitmap (temp);
  625. X      }
  626. X     screen[screen_size].shade = XMakePixmap (NeedBitmap (temp), WhitePixel, BlackPixel);
  627. X     OODBitmap (temp);
  628. X }
  629. X
  630. XSetBit (bm, x, y) struct bitmap *bm; int x, y;
  631. X {
  632. X     int words = ((bm->width + 15) / 16);
  633. X     
  634. X     OODBitmap (bm);
  635. X     bm->data[y * words + (x >> 4)] |= 1 << (x & 0xF);
  636. X }
  637. X
  638. XUpdateControl (h, i) struct hardware *h; int i;
  639. X {
  640. X }
  641. END_OF_FILE
  642. if test 15122 -ne `wc -c <'source/X.c'`; then
  643.     echo shar: \"'source/X.c'\" unpacked with wrong size!
  644. fi
  645. # end of 'source/X.c'
  646. fi
  647. if test -f 'source/cache.c' -a "${1}" != "-c" ; then 
  648.   echo shar: Will not clobber existing file \"'source/cache.c'\"
  649. else
  650. echo shar: Extracting \"'source/cache.c'\" \(14908 characters\)
  651. sed "s/^X//" >'source/cache.c' <<'END_OF_FILE'
  652. X/*
  653. X * Copyright (C) Rutherford Appleton Laboratory 1987
  654. X * 
  655. X * This source may be copied, distributed, altered or used, but not sold for profit
  656. X * or incorporated into a product except under licence from the author.
  657. X * It is not in the public domain.
  658. X * This notice should remain in the source unaltered, and any changes to the source
  659. X * made by persons other than the author should be marked as such.
  660. X * 
  661. X *    Crispin Goswell @ Rutherford Appleton Laboratory caag@uk.ac.rl.vd
  662. X */
  663. X#include "main.h"
  664. X#include "graphics.h"
  665. X
  666. Xstatic struct cache
  667. X {
  668. X    struct cache *cache_next, *cache_prev;
  669. X    int fid;
  670. X    Matrix mat;                    /* character -> device */
  671. X    int width, height, swidth, sheight;     /* device coords */
  672. X } cache_header = { &cache_header, &cache_header },
  673. X     *cache_ring = &cache_header;
  674. X
  675. Xstatic struct char_table {
  676. X    Object         char_key;
  677. X    struct cache     *char_cache;
  678. X    
  679. X    struct device     *char_device;
  680. X    Point         char_width;            /* character coords */
  681. X} *CharTable;
  682. X
  683. Xstatic int bsize = 0, bmax = 0;
  684. Xstatic int msize = 0, mmax = 0;
  685. Xstatic int csize = 0, cmax = 0;
  686. X
  687. Xstatic int maxbits = 0;
  688. X
  689. Xstatic int CacheStatus ();
  690. Xstatic int PSetCharWidth ();
  691. Xstatic int SetCacheLimit ();
  692. Xstatic int PCurrentCharWidth ();
  693. Xstatic int PSetCacheDevice ();
  694. Xstatic int SetCache ();
  695. Xstatic int SaveCurrentFont ();
  696. X
  697. Xint SetCacheDevice ();
  698. Xstatic struct cache *NewCache (), *CacheRemove ();
  699. X
  700. XInitCache ()
  701. X {
  702. X     InstallOp ("cachestatus",    CacheStatus,        0, 7, 0, 0);
  703. X     InstallOp ("setcachedevice",    PSetCacheDevice,    6, 0, 0, 0, Float, Float, Float, Float, Float, Float);
  704. X     InstallOp ("setcharwidth",    PSetCharWidth,        2, 0, 0, 0, Float, Float);
  705. X     InstallOp (".currentcharwidth",    PCurrentCharWidth,    0, 2, 0, 0);
  706. X     InstallOp ("setcachelimit",    SetCacheLimit,        1, 0, 0, 0, Integer);
  707. X     InstallOp ("setcache",        SetCache,        3, 0, 0, 0, Integer, Integer, Integer);
  708. X    InstallOp ("savecurrentfont",    SaveCurrentFont,        0, 0, 0, 0);
  709. X }
  710. X
  711. Xstatic InitCharTable ()
  712. X {
  713. X     int i;
  714. X     
  715. X     CharTable = (struct char_table *) Malloc ((unsigned) (sizeof (struct char_table) * cmax));
  716. X     for (i = 0; i < cmax; i++)
  717. X         CharTable[i].char_cache = NULL;
  718. X }
  719. X
  720. Xstatic struct char_table *CharAddition (table, cache, key, size)
  721. X        struct char_table *table;
  722. X        struct cache *cache;
  723. X        Object key;
  724. X        int size;
  725. X {
  726. X     int i, h = (BodyInteger (key) + (int) cache) % size;
  727. X     
  728. X    for (i = h;;)
  729. X     {
  730. X         if (table[i].char_cache == NULL)
  731. X         {
  732. X            table[i].char_key = key;
  733. X            table[i].char_cache = cache;
  734. X            
  735. X            return &table[i];
  736. X         }
  737. X        if (++i == size)
  738. X            i = 0;
  739. X        if (i == h)
  740. X            return NULL;
  741. X     }
  742. X }
  743. X
  744. XCharStore (key, width, dev) Object key; Point width; struct device *dev;
  745. X {
  746. X     struct char_table *p;
  747. X     
  748. X    while (csize == cmax)
  749. X        DestroyCache (CacheRemove (cache_ring->cache_prev));
  750. X     
  751. X    if (p = CharAddition (CharTable, gstate->show->ccache, key, cmax))
  752. X     {
  753. X        p->char_width = width;
  754. X        p->char_device = dev;
  755. X        ++csize;
  756. X     }
  757. X    else
  758. X        Panic ("dictionary full in CharStore");
  759. X }
  760. X
  761. Xstatic struct char_table *CharFind (table, cache, key, size)
  762. X        struct char_table *table;
  763. X        struct cache *cache;
  764. X        Object key;
  765. X        int size;
  766. X {
  767. X     int i, h = (BodyInteger (key) + (int) cache) % size;
  768. X     
  769. X    for (i = h;;)
  770. X     {
  771. X/*         if (table[i].char_cache == NULL)
  772. X             return NULL;
  773. X*/         if (table[i].char_cache == cache && Equal (key, table[i].char_key))
  774. X            return &table[i];
  775. X        if (++i == size)
  776. X            i = 0;
  777. X        if (i == h)
  778. X            break;
  779. X     }
  780. X    return NULL;
  781. X }
  782. X
  783. Xstatic struct char_table *CharLoad (key) Object key;
  784. X {
  785. X     return CharFind (CharTable, gstate->show->ccache, key, cmax);
  786. X }
  787. X
  788. Xstatic FlushChars (p) struct cache *p;
  789. X {
  790. X     int i;
  791. X     
  792. X    for (i = 0; i < cmax; i++)
  793. X         if (CharTable[i].char_cache == p)
  794. X          {
  795. X             CharTable[i].char_cache = NULL;
  796. X             --csize;
  797. X          }
  798. X }
  799. X
  800. X/* convert bounding box to equivalent one in device coordinates */
  801. XDeviceBBox (left, right, top, bottom, llx, urx, ury, lly) float *left, *right, *top, *bottom, llx, urx, ury, lly;
  802. X {
  803. X     HardPoint ll;
  804. X     
  805. X     ll = ExtToInt (NewPoint (llx, lly));
  806. X     
  807. X     *left = *right = ll.hx; *top = *bottom = ll.hy;
  808. X     
  809. X     Bound (left, right, top, bottom, ExtToInt (NewPoint (urx, lly)));
  810. X     Bound (left, right, top, bottom, ExtToInt (NewPoint (llx, ury)));
  811. X     Bound (left, right, top, bottom, ExtToInt (NewPoint (urx, ury)));
  812. X }
  813. X
  814. Xint EqVector (a, b) Vector a, b;
  815. X {
  816. X     return (int) a.vx == (int) b.vx && (int) a.vy == (int) b.vy;
  817. X }
  818. X
  819. Xstatic int PCurrentCharWidth ()
  820. X {
  821. X     VOID Push (OpStack, MakeReal (gstate->show->Width.x));
  822. X     VOID Push (OpStack, MakeReal (gstate->show->Width.y));
  823. X     return TRUE;
  824. X }
  825. X
  826. Xstatic int PSetCharWidth (wx, wy) Object wx, wy;
  827. X {
  828. X     if (!gstate->show->InShow)
  829. X         return Error (PUndefined);
  830. X     SetCharWidth (NewPoint (BodyReal (wx), BodyReal (wy)));
  831. X     return TRUE;
  832. X }
  833. X
  834. XSetCharWidth (width) Point width;
  835. X {
  836. X     gstate->show->Width = width;
  837. X }
  838. X
  839. Xstatic int PSetCacheDevice (wx, wy, llx, lly, urx, ury)  Object wx, wy, llx, lly, urx, ury;
  840. X {
  841. X     if (!gstate->show->InShow)
  842. X         return Error (PUndefined);
  843. X     return SetCacheDevice (gstate->show->CharName,
  844. X                 NewPoint (BodyReal (wx), BodyReal (wy)),
  845. X                 BodyReal (llx), BodyReal (lly),
  846. X                 BodyReal (urx), BodyReal (ury));
  847. X }
  848. X
  849. Xstatic int CharTooBig (width, height) float width, height;
  850. X {
  851. X    return width * height > maxbits * 8;
  852. X }
  853. X
  854. Xint SetCacheDevice (name, char_width, llx, lly, urx, ury)
  855. X        Object name; Point char_width; float llx, lly, urx, ury;
  856. X {
  857. X     float left, right, top, bottom, width, height;
  858. X     struct device *new_char;
  859. X     struct cache *ccache = gstate->show->ccache;
  860. X     
  861. X     SetCharWidth (char_width);
  862. X     if (!ccache)
  863. X         return TRUE;
  864. X     DeviceBBox (&left, &right, &top, &bottom, llx, urx, ury, lly);
  865. X     width = right - left; height = top - bottom;
  866. X     
  867. X     if (CharTooBig (width, height))
  868. X         return TRUE;
  869. X     
  870. X     new_char = NewCacheDevice (ccache->mat, ccache->width, ccache->height, ccache->swidth, ccache->sheight);
  871. X     CharStore (name, char_width, LinkDevice (new_char));
  872. X     SetDevice (new_char);
  873. X     
  874. X     PathFree (gstate->clip);
  875. X     gstate->clip = NewClipPath (0.0, width, height, 0.0);
  876. X     gstate->CTM.tx = ccache->swidth;
  877. X     gstate->CTM.ty = ccache->sheight;
  878. X     VOID MoveTo (gstate->path, ExtToInt (NewPoint (0.0, 0.0)));
  879. X     
  880. X     return TRUE;
  881. X }
  882. X
  883. XprintMatrix (m) Matrix m;
  884. X {
  885. X    printf ("[%g %g]\n", m.A, m.B);
  886. X    printf ("[%g %g]\n", m.C, m.D);
  887. X    printf ("[%g %g]\n", m.tx, m.ty);
  888. X }
  889. X
  890. X#ifdef notdef
  891. Xint EqFont (m, n, bbox) Matrix m, n; float *bbox;
  892. X {
  893. X     Vector morigin, norigin, mright, nright, mbottom, nbottom;
  894. X     
  895. X     morigin = Transform (NewVector (bbox [BBOX_LEFT], bbox [BBOX_TOP], 1.0), m);
  896. X     norigin = Transform (NewVector (bbox [BBOX_LEFT], bbox [BBOX_TOP], 1.0), n);
  897. X     mright  = DiffVector (Transform (NewVector (bbox [BBOX_RIGHT], bbox [BBOX_TOP], 1.0), m), morigin);
  898. X     nright  = DiffVector (Transform (NewVector (bbox [BBOX_RIGHT], bbox [BBOX_TOP], 1.0), n), norigin);
  899. X     mbottom = DiffVector (Transform (NewVector (bbox [BBOX_LEFT],  bbox [BBOX_BOTTOM], 1.0), m), morigin);
  900. X     nbottom = DiffVector (Transform (NewVector (bbox [BBOX_LEFT],  bbox [BBOX_BOTTOM], 1.0), n), norigin);
  901. X     
  902. X     return EqVector (mbottom, nbottom) && EqVector (mright, nright);
  903. X }
  904. X#endif
  905. X
  906. Xint EqFont (m, n) Matrix m, n;
  907. X {
  908. X    return m.A == n.A && m.B == n.B && m.C == n.C && m.D == n.D;
  909. X }
  910. X
  911. Xextern float fontbboxCache[];
  912. Xextern int fidCache;
  913. X
  914. Xstruct cache *SearchCache (m, fid) Matrix m; int fid;
  915. X {
  916. X     struct cache *p;
  917. X     
  918. X     for (p = cache_ring->cache_next; p != cache_ring; p = p->cache_next)
  919. X         if (p->fid == fid && EqFont (m, p->mat))
  920. X          {
  921. X              if (cache_ring->cache_next != p)
  922. X                 CacheInsert (cache_ring->cache_next, CacheRemove (p));
  923. X             return cache_ring->cache_next;
  924. X          }
  925. X     
  926. X     return NULL;
  927. X }
  928. X
  929. Xint FindCache ()
  930. X {
  931. X     HardPoint origin;
  932. X     float left, right, top, bottom;
  933. X     int width, height, swidth, sheight;
  934. X     
  935. X     if ((gstate->show->ccache = SearchCache (gstate->CTM, fidCache)) != NULL)
  936. X         return TRUE;
  937. X     Message ("building a new cache");
  938. X    DeviceBBox (&left, &right, &top, &bottom,
  939. X            fontbboxCache[BBOX_LEFT], fontbboxCache[BBOX_RIGHT], fontbboxCache[BBOX_BOTTOM], fontbboxCache[BBOX_TOP]);
  940. X     
  941. X     width = right - left; height = top - bottom;
  942. X     if (CharTooBig ((float) width, (float) height))
  943. X      {
  944. X          Message ("character too big to cache");
  945. X        return TRUE;
  946. X     }
  947. X     
  948. X     if (msize == mmax)
  949. X         DestroyCache (CacheRemove (cache_ring->cache_prev));
  950. X    
  951. X    origin = ExtToInt (NewPoint (0.0, 0.0));
  952. X    swidth = origin.hx - left; sheight = origin.hy - bottom;
  953. X     
  954. X     CacheInsert (cache_ring->cache_next,
  955. X             NewCache (fidCache,
  956. X                 gstate->CTM,
  957. X                 width, height,
  958. X                 swidth, sheight));
  959. X     gstate->show->ccache = cache_ring->cache_next;
  960. X     
  961. X     LoadDiskCache (gstate->CTM, fontbboxCache);
  962. X     
  963. X     return TRUE;
  964. X }
  965. X
  966. Xint CacheShow (name, cp) Object name; HardPoint cp;
  967. X {
  968. X     struct char_table *b;
  969. X     struct cache *ccache = gstate->show->ccache;
  970. X     DevicePoint from, to, extent;
  971. X     
  972. X     if (!ccache)
  973. X         return FALSE;
  974. X     gstate->show->CharName = name;
  975. X     if ((b = CharLoad (name)) == NULL)
  976. X         return FALSE;
  977. X     /* SetCharWidth (b->char_width); */
  978. X     gstate->show->Width = b->char_width;
  979. X     
  980. X     from.dx = from.dy = 0;
  981. X     to.dx = cp.hx - ccache->swidth;
  982. X     to.dy = cp.hy - ccache->sheight;
  983. X    extent.dx = ccache->width; extent.dy = ccache->height;
  984. X    
  985. X    Paint (b->char_device->dev, gstate->device->dev, from, to, extent, gstate->colour);
  986. X     
  987. X    return TRUE;
  988. X }
  989. X
  990. Xstatic struct cache *NewCache (fid, m, width, height, swidth, sheight)
  991. X    int fid; Matrix m; int width, height, swidth, sheight;
  992. X {
  993. X     struct cache *res = (struct cache *) Malloc (sizeof (struct cache));
  994. X     
  995. X     m.tx = m.ty = 0.0;
  996. X     res->fid    = fid;
  997. X     res->mat    = m;
  998. X     res->width    = width;
  999. X     res->height    = height;
  1000. X     res->swidth    = swidth;
  1001. X     res->sheight    = sheight;
  1002. X    
  1003. X     return res;
  1004. X }
  1005. X
  1006. Xstatic DestroyCache (p) struct cache *p;
  1007. X {
  1008. X    FlushChars (p);
  1009. X     Free ((char *) p);
  1010. X }
  1011. X
  1012. Xstatic CacheInsert (where, cache) struct cache *where, *cache;
  1013. X {
  1014. X     cache->cache_next = where; cache->cache_prev = where->cache_prev;
  1015. X     where->cache_prev->cache_next = cache;
  1016. X     where->cache_prev = cache;
  1017. X     ++msize;
  1018. X }
  1019. X
  1020. Xstatic struct cache *CacheRemove (item) struct cache *item;
  1021. X {
  1022. X     item->cache_prev->cache_next = item->cache_next;
  1023. X     item->cache_next->cache_prev = item->cache_prev;
  1024. X     --msize;
  1025. X     
  1026. X     return item;
  1027. X }
  1028. X
  1029. Xstatic int SetCacheLimit (mb) Object mb;
  1030. X {
  1031. X     int b = BodyInteger (mb);
  1032. X     if (b < 0)
  1033. X         return Error (PRangeCheck);
  1034. X     maxbits = b;
  1035. X     return TRUE;
  1036. X }
  1037. X
  1038. Xstatic int SetCache (bitmap, fonts, chars) Object bitmap, fonts, chars;
  1039. X {
  1040. X     int b = BodyInteger (bitmap);
  1041. X     int f = BodyInteger (fonts);
  1042. X     int c = BodyInteger (chars);
  1043. X     
  1044. X     if (b < 0 || f < 0 || c < 0)
  1045. X         return Error (PRangeCheck);
  1046. X     bmax = b; mmax = f; cmax = c;
  1047. X     InitCharTable ();
  1048. X     return TRUE;
  1049. X }
  1050. X
  1051. Xstatic int CacheStatus ()
  1052. X {
  1053. X     VOID Push (OpStack, MakeInteger (bsize));
  1054. X      VOID Push (OpStack, MakeInteger (bmax));
  1055. X     VOID Push (OpStack, MakeInteger (msize));
  1056. X     VOID Push (OpStack, MakeInteger (mmax));
  1057. X     VOID Push (OpStack, MakeInteger (csize));
  1058. X     VOID Push (OpStack, MakeInteger (cmax));
  1059. X     VOID Push (OpStack, MakeInteger (maxbits));
  1060. X     
  1061. X     return TRUE;
  1062. X}
  1063. X
  1064. XLoadDiskCache (m, bbox) Matrix m; float *bbox;
  1065. X {
  1066. X     Object font_name;
  1067. X     FILE *fp;
  1068. X     Vector origin, right, bottom;
  1069. X     char disk_name [BUFSIZE], *bits, mess[BUFSIZ];
  1070. X/*     struct hardware *screen = gstate->device->dev; */
  1071. X     
  1072. X     Message ("Attempting to find a cache on disk");
  1073. X     font_name = DictLoad (gstate->font, FontName);
  1074. X     if (TypeOf (font_name) != Name)
  1075. X         return;
  1076. X     origin = Transform (NewVector (bbox [BBOX_LEFT], bbox [BBOX_TOP], 1.0), m);
  1077. X     right  = DiffVector (Transform (NewVector (bbox [BBOX_RIGHT], bbox [BBOX_TOP], 1.0), m),    origin);
  1078. X     bottom = DiffVector (Transform (NewVector (bbox [BBOX_LEFT],  bbox [BBOX_BOTTOM], 1.0), m), origin);
  1079. X     VOID sprintf (disk_name,
  1080. X         "%s/cache/%.*s/%3d%3d%3d%3d",
  1081. X         library,
  1082. X         lengthName (font_name), BodyName (font_name),
  1083. X         (int) right.vx, (int) right.vy, (int) bottom.vx, (int) bottom.vy);
  1084. X     Message (disk_name);
  1085. X     if ((fp = fopen (disk_name, "r")) == NULL)
  1086. X         return;
  1087. X     Message ("found a disk cache");
  1088. X     VOID GSave ();
  1089. X     bits = Malloc ((unsigned) maxbits);
  1090. X     
  1091. X      sprintf (mess, "width = %d, height = %d\n", gstate->show->ccache->width, gstate->show->ccache->height);
  1092. X     Message (mess);
  1093. X    sprintf (mess, "computed length = %d", gstate->show->ccache->height * ((gstate->show->ccache->width + 7) / 8));
  1094. X     Message (mess);
  1095. X     
  1096. X     while (!feof (fp))
  1097. X      {
  1098. X          char char_name [BUFSIZE];
  1099. X          struct hardware *newdev;
  1100. X          int width, height, length;
  1101. X          
  1102. X          if (fscanf (fp, "%s %d %d %d\n",
  1103. X                  char_name,
  1104. X                  &width, &height,
  1105. X                  &length) == EOF)
  1106. X              break;
  1107. X          VOID fread (bits, (unsigned) length, 1, fp);
  1108. X          VOID getc (fp);
  1109. X          newdev = HardwareFromString (bits, gstate->show->ccache->width, gstate->show->ccache->height);
  1110. X /*         VOID BitBlt (newdev, screen,
  1111. X                  NewDevicePoint (0, 0), NewDevicePoint (200, 200),
  1112. X                  NewDevicePoint (gstate->show->ccache->width, gstate->show->ccache->height),
  1113. X                  ROP_SOURCE);
  1114. X*/         
  1115. X          VOID SetCacheDevice (NameFrom (char_name),
  1116. X                  NewPoint ((float) width, (float) height),
  1117. X                  bbox [BBOX_LEFT],  bbox [BBOX_TOP],
  1118. X                  bbox [BBOX_RIGHT], bbox [BBOX_BOTTOM]);
  1119. X         
  1120. X         VOID BitBlt (newdev, gstate->device->dev,
  1121. X                  NewDevicePoint (0, 0), NewDevicePoint (0, 0),
  1122. X                  NewDevicePoint (gstate->show->ccache->width, gstate->show->ccache->height),
  1123. X                  ROP_SOURCE);
  1124. X          DestroyHardware (newdev);
  1125. X      }
  1126. X     Free (bits);
  1127. X     VOID GRestore ();
  1128. X     VOID fclose (fp);
  1129. X     Message ("load completed");
  1130. X }
  1131. X
  1132. Xstatic int SaveCurrentFont ()
  1133. X {
  1134. X     Matrix fm, m;
  1135. X     Vector origin, right, bottom;
  1136. X     Object font_name;
  1137. X     FILE *fp;
  1138. X     char disk_name [BUFSIZE];
  1139. X     int i;
  1140. X     float bbox[4];
  1141. X     struct cache *ccache;
  1142. X     
  1143. X     ExtractMatrix (&fm, DictLoad (gstate->font, FontMatrix));
  1144. X     m = MatMult (fm, gstate->CTM);
  1145. X     ExtractBBox (bbox, DictLoad (gstate->font, FontBBox));
  1146. X     font_name = DictLoad (gstate->font, FontName);
  1147. X     
  1148. X     origin = Transform (NewVector (bbox [BBOX_LEFT], bbox [BBOX_TOP], 1.0), m);
  1149. X     right  = DiffVector (Transform (NewVector (bbox [BBOX_RIGHT], bbox [BBOX_TOP], 1.0), m),    origin);
  1150. X     bottom = DiffVector (Transform (NewVector (bbox [BBOX_LEFT],  bbox [BBOX_BOTTOM], 1.0), m), origin);
  1151. X      
  1152. X    if ((ccache = SearchCache (m, BodyFontID (DictLoad (gstate->font, Fid)))) == NULL)
  1153. X         return Error (PInvFont);
  1154. X     
  1155. X      Message (disk_name);
  1156. X    VOID sprintf (disk_name,
  1157. X         "%s/cache/%.*s/%3d%3d%3d%3d",
  1158. X         library,
  1159. X         lengthName (font_name), BodyName (font_name),
  1160. X         (int) right.vx, (int) right.vy, (int) bottom.vx, (int) bottom.vy);
  1161. X     
  1162. X     if ((fp = fopen (disk_name, "w")) == NULL)
  1163. X         return Error (PInvFileAccess);
  1164. X     
  1165. X     for (i = 0; i < cmax; i++)
  1166. X      if (CharTable[i].char_cache == ccache)
  1167. X       {
  1168. X           Object char_name;
  1169. X           char *bits;
  1170. X           DevicePoint extent;
  1171. X           int length;
  1172. X           
  1173. X           char_name = CharTable[i].char_key;
  1174. X           extent = HardwareExtent (CharTable[i].char_device->dev);
  1175. X           length = (extent.dx + 7) / 8 * extent.dy;
  1176. X          bits = StringFromHardware (CharTable[i].char_device->dev);
  1177. X         VOID fprintf (fp,
  1178. X              "%.*s %d %d %d\n",
  1179. X              lengthName (char_name), BodyName (char_name),
  1180. X              (int) CharTable [i].char_width.x,
  1181. X              (int) CharTable [i].char_width.y,
  1182. X              length);
  1183. X          VOID fwrite (bits, (unsigned) length, 1, fp);
  1184. X          putc ('\n', fp);
  1185. X/*           Free (bits);*/
  1186. X             
  1187. X       }
  1188. X     
  1189. X     VOID fclose (fp);
  1190. X     
  1191. X     return TRUE;
  1192. X }
  1193. END_OF_FILE
  1194. if test 14908 -ne `wc -c <'source/cache.c'`; then
  1195.     echo shar: \"'source/cache.c'\" unpacked with wrong size!
  1196. fi
  1197. # end of 'source/cache.c'
  1198. fi
  1199. if test -f 'source/fill.c' -a "${1}" != "-c" ; then 
  1200.   echo shar: Will not clobber existing file \"'source/fill.c'\"
  1201. else
  1202. echo shar: Extracting \"'source/fill.c'\" \(14650 characters\)
  1203. sed "s/^X//" >'source/fill.c' <<'END_OF_FILE'
  1204. X/*
  1205. X * Copyright (C) Rutherford Appleton Laboratory 1987
  1206. X * 
  1207. X * This source may be copied, distributed, altered or used, but not sold for profit
  1208. X * or incorporated into a product except under licence from the author.
  1209. X * It is not in the public domain.
  1210. X * This notice should remain in the source unaltered, and any changes to the source
  1211. X * made by persons other than the author should be marked as such.
  1212. X * 
  1213. X *    Crispin Goswell @ Rutherford Appleton Laboratory caag@uk.ac.rl.vd
  1214. X */
  1215. X#include "main.h"
  1216. X#include "graphics.h"
  1217. X
  1218. X#define MAXPATHELEMENTS    15000
  1219. X
  1220. X/*
  1221. X * Trapezoid decomposition algorithm:
  1222. X * 
  1223. X *    Edges are characterised by a line description, with topY, bottomY, topX, bottomX, startingY
  1224. X *     Build edge lists from path.
  1225. X *    Sort edges on top Y value.
  1226. X *    find topmost interestingY value, which will be the minimum topY. This becomes interestingY.
  1227. X *    loop
  1228. X *        examine edge list from here to end. Move edges with topY value less than interestingY into
  1229. X *            interesting edge set, computing intersections for each as you go. This should establish next
  1230. X *            interestingY value, nextY.
  1231. X *        form the pairings for all edges in the interesting set, according to the fill rule at interestingY.
  1232. X *            to do this, while inside, keep a pointer to the last up-transition edge, and pair it with the
  1233. X *            next down-transition edge.
  1234. X *            for any edges which have changed pairing, emit a trapezoid from their startingY to interestingY,
  1235. X *            (if they were paired) and set their startingY to interestingY
  1236. X *        break if (ninteresting == 0 && nedges_left == 0)
  1237. X *        interestingY := nextY
  1238. X *    pool
  1239. X */        
  1240. X
  1241. Xstatic struct edge
  1242. X {
  1243. X    int topX, topY, bottomX, bottomY; short dir;
  1244. X    struct edge *pair;
  1245. X    int startingY, where, up, clip;
  1246. X    int name;
  1247. X };
  1248. X
  1249. Xint names = 0;
  1250. X
  1251. Xextern int in_stroke;
  1252. X
  1253. Xint InitClip ();
  1254. Xstatic int Clip ();
  1255. Xstatic int EOClip ();
  1256. Xint Fill ();
  1257. Xstatic int EOFill ();
  1258. Xstatic int PClipPath ();
  1259. X
  1260. XInitFill ()
  1261. X {
  1262. X     InstallOp ("initclip",        InitClip,    0, 0, 0, 0);
  1263. X     InstallOp ("clip",        Clip,        0, 0, 0, 0);
  1264. X     InstallOp ("eoclip",        EOClip,        0, 0, 0, 0);
  1265. X     InstallOp ("fill",        Fill,        0, 0, 0, 0);
  1266. X     InstallOp ("eofill",        EOFill,        0, 0, 0, 0);
  1267. X     InstallOp ("clippath",        PClipPath,    0, 0, 0, 0);
  1268. X }
  1269. X
  1270. Xstatic struct hardware *output_device;
  1271. Xstatic Colour output_colour;
  1272. X
  1273. Xstatic int FillIt ();
  1274. Xstatic int EoRule (), NwRule ();
  1275. X
  1276. Xstatic void EmitTrapezoid (left, right, top, bottom) struct edge *left, *right; int top, bottom;
  1277. X {
  1278. X     struct edge *temp;
  1279. X     
  1280. X     if (left->topX > right->topX || left->bottomX > right->bottomX)
  1281. X         temp = left, left = right, right = temp;
  1282. X     PaintTrapezoid (output_device,
  1283. X         NewDevicePoint (left->topX, left->topY),
  1284. X         NewDevicePoint (left->bottomX, left->bottomY),
  1285. X         NewDevicePoint (right->topX, right->topY),
  1286. X         NewDevicePoint (right->bottomX, right->bottomY),
  1287. X         top, bottom,
  1288. X         output_colour);
  1289. X }
  1290. X
  1291. Xint Fill ()
  1292. X {
  1293. X    int res;
  1294. X    
  1295. X    if (gstate->device->dev == NULL)
  1296. X        return PNewPath ();
  1297. X    
  1298. X    output_device = gstate->device->dev;
  1299. X    output_colour = gstate->colour;
  1300. X     res = FillIt (gstate->path, NwRule, gstate->clip, NwRule, EmitTrapezoid);
  1301. X                         /* XXX needs optimising */
  1302. X     
  1303. X    VOID PNewPath ();
  1304. X    
  1305. X    return res;
  1306. X }
  1307. X
  1308. Xstatic int EOFill ()
  1309. X {
  1310. X    int res;
  1311. X    
  1312. X    if (gstate->device->dev == NULL)
  1313. X        return PNewPath ();
  1314. X    
  1315. X     output_device = gstate->device->dev;
  1316. X    output_colour = gstate->colour;
  1317. X    res = FillIt (gstate->path, EoRule, gstate->clip, NwRule, EmitTrapezoid);
  1318. X                         /* XXX needs optimising */
  1319. X     
  1320. X    VOID PNewPath ();
  1321. X    
  1322. X    return res;
  1323. X }
  1324. X
  1325. Xstatic Path output_path;
  1326. X
  1327. Xstatic void PathTrapezoid (left, right, top, bottom) struct edge *left, *right; int top, bottom;
  1328. X {
  1329. X     int ll, ul, lr, ur;
  1330. X     struct edge *temp;
  1331. X     
  1332. X     if (left->topX > right->topX || left->bottomX > right->bottomX)
  1333. X         temp = left, left = right, right = temp;
  1334. X     
  1335. X     ll = Xvalue (left->topX, left->topY, left->bottomX, left->bottomY, bottom);
  1336. X     ul = Xvalue (left->topX, left->topY, left->bottomX, left->bottomY, top);
  1337. X     lr = Xvalue (right->topX, right->topY, right->bottomX, right->bottomY, bottom);
  1338. X     ur = Xvalue (right->topX, right->topY, right->bottomX, right->bottomY, top);
  1339. X     
  1340. X     MoveTo (output_path, NewHardPoint ((float) ll, (float) bottom));
  1341. X     LineTo (output_path, NewHardPoint ((float) lr, (float) bottom));
  1342. X     LineTo (output_path, NewHardPoint ((float) ur, (float) top));
  1343. X     LineTo (output_path, NewHardPoint ((float) ul, (float) top));
  1344. X     ClosePath (output_path);
  1345. X }
  1346. X
  1347. Xint InitClip ()
  1348. X {
  1349. X     PathFree (gstate->clip);
  1350. X     gstate->clip = PathCopy (gstate->device->default_clip);
  1351. X     
  1352. X     UnlinkDevice (gstate->clipdevice);
  1353. X      gstate->clipdevice = NULL;
  1354. X      
  1355. X     SetClipHardware (gstate->device->dev, NULL);
  1356. X    
  1357. X    return TRUE;
  1358. X }
  1359. X
  1360. Xstatic int Clip ()
  1361. X {
  1362. X    int res;
  1363. X    
  1364. X    
  1365. X    output_path = NewPath ();
  1366. X     res = FillIt (gstate->path, NwRule, gstate->clip, NwRule, PathTrapezoid);
  1367. X                         /* XXX - needs optimising */
  1368. X     
  1369. X     PathFree (gstate->clip);
  1370. X     gstate->clip = output_path;
  1371. X     
  1372. X     if (res)
  1373. X      {
  1374. X          gstate->clipdevice = UniqueDevice (gstate->clipdevice);
  1375. X          SetClipHardware (gstate->device->dev, gstate->clipdevice->dev);
  1376. X          
  1377. X        output_device = gstate->clipdevice->dev;
  1378. X         output_colour = NewColour (0.0, 0.0, 0.0);
  1379. X         res = FillIt (gstate->clip, NwRule, gstate->device->default_clip, NwRule, EmitTrapezoid);
  1380. X      }
  1381. X    return res;
  1382. X }
  1383. X
  1384. Xstatic int EOClip ()
  1385. X {
  1386. X    int res;
  1387. X    
  1388. X    output_path = NewPath ();
  1389. X    res = FillIt (gstate->path, EoRule, gstate->clip, NwRule, PathTrapezoid);
  1390. X                         /* XXX - needs optimising */
  1391. X     
  1392. X     PathFree (gstate->clip);
  1393. X     gstate->clip = output_path;
  1394. X     
  1395. X     if (res)
  1396. X      {
  1397. X         gstate->clipdevice = UniqueDevice (gstate->clipdevice);
  1398. X            SetClipHardware (gstate->device->dev, gstate->clipdevice->dev);
  1399. X           
  1400. X        output_device = gstate->clipdevice->dev;
  1401. X         output_colour = NewColour (0.0, 0.0, 0.0);
  1402. X         res = FillIt (gstate->clip, NwRule, gstate->device->default_clip, NwRule, EmitTrapezoid);
  1403. X      }
  1404. X    return res;
  1405. X }
  1406. X
  1407. Xstatic int PClipPath ()
  1408. X {
  1409. X     PathFree (gstate->path);
  1410. X     gstate->path = PathCopy (gstate->clip);
  1411. X     gstate->cp_defined = TRUE;
  1412. X     gstate->cp = gstate->path->last->pe.point;
  1413. X     
  1414. X     return TRUE;
  1415. X }
  1416. X
  1417. X/****************************/
  1418. X
  1419. Xstatic struct edge edge [MAXPATHELEMENTS];
  1420. X
  1421. Xstatic struct edge *interesting [MAXPATHELEMENTS];
  1422. X
  1423. Xstatic int nedges, here, ninteresting;
  1424. X
  1425. Xstatic int interestingY, nextY;
  1426. X
  1427. Xstatic int infinity;
  1428. X
  1429. Xstatic int FillIt (path_a, rule_a, path_b, rule_b, emitfn)
  1430. X    Path path_a, path_b; int (*rule_a)(), (*rule_b)(); void (*emitfn)();
  1431. X {
  1432. X    Path new;
  1433. X    static int edgecmp ();
  1434. X    static void Trapezoids (), BuildEdgeList ();
  1435. X    
  1436. X    if (EmptyPath (path_a) || EmptyPath (path_b))
  1437. X        return TRUE;
  1438. X    
  1439. X    path_a = FlattenPath (path_a);
  1440. X    path_b = FlattenPath (path_b);
  1441. X    
  1442. X    if (!CloseAll (path_a) || !CloseAll (path_b))
  1443. X     {
  1444. X        PathFree (path_a);
  1445. X        PathFree (path_b);
  1446. X        
  1447. X        return FALSE;
  1448. X     }
  1449. X    
  1450. X    nedges = 0;
  1451. X    BuildEdgeList (path_a, TRUE);
  1452. X    BuildEdgeList (path_b, FALSE);
  1453. X     qsort ((char *) edge, (unsigned) nedges, sizeof (struct edge), edgecmp);
  1454. X    PathFree (path_a);
  1455. X    PathFree (path_b);
  1456. X    Trapezoids (rule_a, rule_b, emitfn);
  1457. X    
  1458. X    return TRUE;
  1459. X }
  1460. X
  1461. Xstatic void AddLowest ();
  1462. X
  1463. Xstatic void Trapezoids (rule_a, rule_b, emitfn) int (*rule_a)(), (*rule_b)(); void (*emitfn)();
  1464. X {
  1465. X    static void FindInfinity (), AddInteresting ();
  1466. X    
  1467. X    nextY = edge[0].topY;
  1468. X    AddLowest (nextY);
  1469. X    FindInfinity ();
  1470. X    
  1471. X    here = 0;
  1472. X    ninteresting = 0;
  1473. X    names = 0;
  1474. X    
  1475. X    while (here != nedges || ninteresting)
  1476. X     {
  1477. X         static void RemoveEdges ();
  1478. X         
  1479. X         interestingY = nextY;
  1480. X         ProcessEdges (rule_a, rule_b, emitfn);
  1481. X         
  1482. X         AddInteresting ();
  1483. X         
  1484. X         RemoveEdges (interestingY, emitfn);
  1485. X         
  1486. X         ProcessEdges (rule_a, rule_b, emitfn);
  1487. X     }
  1488. X }
  1489. X
  1490. XProcessEdges (rule_a, rule_b, emitfn) int (*rule_a)(), (*rule_b)(); void (*emitfn)();
  1491. X {
  1492. X    struct edge *up_edge;
  1493. X    int i, count_a = 0, count_b = 0;
  1494. X    static void RemoveEdges ();
  1495. X    
  1496. X    for (i = 0; i < ninteresting; i++)
  1497. X     {
  1498. X         static void Emit ();
  1499. X         int d_a = 0, d_b = 0;
  1500. X         
  1501. X         if (interesting[i]->clip)
  1502. X             d_a = interesting[i]->dir;
  1503. X         else
  1504. X             d_b = interesting[i]->dir;
  1505. X
  1506. X         if (UpEdge (count_a, count_b, d_a, d_b, rule_a, rule_b))
  1507. X             up_edge = interesting[i];
  1508. X         else if (DownEdge (count_a, count_b, d_a, d_b, rule_a, rule_b))
  1509. X              ThisBit (up_edge, interesting[i], interestingY, emitfn);
  1510. X         else
  1511. X              NotThisBit (interesting[i], interestingY, emitfn);
  1512. X         
  1513. X         count_a += d_a;
  1514. X         count_b += d_b;
  1515. X     }
  1516. X    if (count_a || count_b)
  1517. X        fprintf (stderr, "count_a = %dcount_b = %d\n", count_a, count_b);
  1518. X    PanicIf (count_a || count_b, "something wrong in area fill");
  1519. X }
  1520. X
  1521. XThisBit (left, right, where, emitfn) struct edge *left, *right; int where; void (*emitfn)();    
  1522. X {
  1523. X     if (left->pair != right || right->up)
  1524. X      {
  1525. X          if (left->pair != NULL)
  1526. X          {
  1527. X             (*emitfn) (left, left->pair, left->startingY, left->where);
  1528. X             left->pair->startingY = left->pair->where;
  1529. X              left->pair->pair->startingY = left->pair->pair->where;
  1530. X              left->pair->pair = NULL;
  1531. X         }
  1532. X         if (right->pair != NULL)
  1533. X          {
  1534. X             (*emitfn) (right, right->pair, right->startingY, right->where);
  1535. X             right->pair->startingY = right->pair->where;
  1536. X              right->pair->pair->startingY = right->pair->pair->where;
  1537. X              right->pair->pair = NULL;
  1538. X         }
  1539. X         
  1540. X          left->pair = right;
  1541. X         right->pair = left;
  1542. X         left->startingY = right->startingY = where;
  1543. X     }
  1544. X     left->where = right->where = where;
  1545. X     left->up = TRUE; right->up = FALSE;
  1546. X }
  1547. X
  1548. XNotThisBit (edge, where, emitfn) struct edge *edge; int where; void (*emitfn)();    
  1549. X {
  1550. X     if (edge->pair != NULL)
  1551. X      {
  1552. X         (*emitfn) (edge, edge->pair, edge->startingY, where);
  1553. X         edge->pair->startingY = where;
  1554. X         edge->pair->where = where;
  1555. X         edge->pair->pair = NULL;
  1556. X         edge->pair = NULL;
  1557. X     }
  1558. X      edge->startingY = where;
  1559. X     edge->where = where;
  1560. X }
  1561. X
  1562. Xstatic void RemoveEdges (interestingY, emitfn) int interestingY; void (*emitfn)();
  1563. X {
  1564. X     int i, j = 0;
  1565. X     
  1566. X     for (i = 0; i < ninteresting; i++)
  1567. X        if (interesting [i]->bottomY > interestingY)
  1568. X             interesting [j++] = interesting [i];
  1569. X         else
  1570. X             NotThisBit (interesting[i], interestingY, emitfn);
  1571. X     ninteresting = j;
  1572. X }
  1573. X
  1574. 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) ();
  1575. X {
  1576. X     return (*rule_b)(count_b + inc_b) && !(*rule_a) (count_a) && (*rule_a) (count_a + inc_a) ||
  1577. X         (*rule_a)(count_a + inc_a) && !(*rule_b) (count_b) && (*rule_b) (count_b + inc_b);
  1578. X }
  1579. X
  1580. 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) ();
  1581. X {
  1582. X     return (*rule_b)(count_b + inc_b) && (*rule_a) (count_a) && !(*rule_a) (count_a + inc_a) ||
  1583. X         (*rule_a)(count_a + inc_a) && (*rule_b) (count_b) && !(*rule_b) (count_b + inc_b);
  1584. X }
  1585. X
  1586. Xstatic int EoRule (n) int n;
  1587. X {
  1588. X    return n & 1;
  1589. X }
  1590. X
  1591. Xstatic int NwRule (n) int n;
  1592. X {
  1593. X    return n;
  1594. X }
  1595. X
  1596. Xstatic float Yintersect (a, b) struct edge *a, *b;
  1597. X {
  1598. X     float
  1599. X         num =   (a->bottomX * a->topY - a->bottomY * a->topX) * (b->topY - b->bottomY) -
  1600. X             (b->bottomX * b->topY - b->bottomY * b->topX) * (a->topY - a->bottomY),
  1601. X         denom = (a->bottomX - a->topX) * (b->topY - b->bottomY) -
  1602. X             (b->bottomX - b->topX) * (a->topY - a->bottomY);
  1603. X     
  1604. X     if (denom == 0)
  1605. X      {
  1606. X         return infinity;
  1607. X      }
  1608. X    return num / denom;
  1609. X }
  1610. X
  1611. Xstatic int Xvalue (ax, ay, bx, by, cy) int ax, ay, bx, by, cy;
  1612. X {
  1613. X     return bx + (cy - by) * (ax - bx) / (float) (ay - by);
  1614. X }
  1615. X
  1616. Xstatic int intercmp (aa, bb) char *aa, *bb;
  1617. X {
  1618. X     struct edge *a = *(struct edge **) aa, *b = *(struct edge **) bb;
  1619. X     int sign;
  1620. X    
  1621. X    sign = Xvalue (a->topX, a->topY, a->bottomX, a->bottomY, interestingY + 1) -
  1622. X             Xvalue (b->topX, b->topY, b->bottomX, b->bottomY, interestingY + 1);
  1623. X    if (sign == 0)
  1624. X        return a->bottomX - b->bottomX;
  1625. X    return sign;
  1626. X }
  1627. X
  1628. Xstatic void AddInteresting ()
  1629. X {
  1630. X    int i;
  1631. X         
  1632. X    nextY = infinity;
  1633. X    for (; here < nedges && edge[here].topY <= interestingY; here++) /* look at each new interesting edge */
  1634. X     {
  1635. X         int i, n;
  1636. X         
  1637. X        for (i = 0; i < ninteresting; i++) /* look at all possible intersections */
  1638. X         {
  1639. X             int inter = Yintersect (&edge[here], interesting[i]);
  1640. X             
  1641. X             if (inter >= interestingY && inter <= edge[here].bottomY && inter <= interesting[i]->bottomY)
  1642. X                 AddLowest (inter);
  1643. X         }
  1644. X        n = ninteresting++;
  1645. X        interesting[n] = &edge[here];
  1646. X        interesting[n]->pair = NULL;
  1647. X        interesting[n]->up = FALSE;
  1648. X        interesting[n]->startingY = interesting[n]->where = edge[here].topY;
  1649. X        interesting[n]->name = names++;
  1650. X     }
  1651. X    i = NextLowest (interestingY);
  1652. X    if (i)
  1653. X        nextY = i;
  1654. X    if (here != nedges && edge[here].topY < nextY)
  1655. X        nextY = edge[here].topY;
  1656. X    for (i = 0; i < ninteresting; i++)
  1657. X     {
  1658. X        if (interesting[i]->topY > interestingY && interesting[i]->topY < nextY)
  1659. X            nextY = interesting[i]->topY;
  1660. X        if (interesting[i]->bottomY > interestingY && interesting[i]->bottomY < nextY)
  1661. X            nextY = interesting[i]->bottomY;
  1662. X     }
  1663. X    qsort ((char *) interesting, (unsigned) ninteresting, sizeof (struct edge *), intercmp);
  1664. X }
  1665. X
  1666. Xstatic void FindInfinity ()
  1667. X {
  1668. X     int i;
  1669. X     
  1670. X    infinity = edge[0].topY;
  1671. X    for (i = 0; i < nedges; i++)
  1672. X        if (edge[i].bottomY > infinity)
  1673. X            infinity = edge[i].bottomY;
  1674. X }
  1675. X
  1676. X/***************************/
  1677. X
  1678. Xstatic int edgecmp (a, b) char *a, *b;
  1679. X {
  1680. X     struct edge *aa = (struct edge *) a, *bb = (struct edge *) b;
  1681. X     
  1682. X     return aa->topY - bb->topY;
  1683. X }
  1684. X
  1685. Xstatic int AddEdge (e, from, to, clip) struct edge *e; HardPoint from, to; int clip;
  1686. X {
  1687. X     int dir = 1;
  1688. X     HardPoint temp;
  1689. X     
  1690. X     if ((int) (from.hy) == (int) (to.hy))
  1691. X         return 0;
  1692. X     if ((int) (from.hy) > (int) (to.hy))
  1693. X      {
  1694. X         temp = from; from = to; to = temp;
  1695. X         dir = -dir;
  1696. X      }
  1697. X     e->topX = from.hx;
  1698. X      e->topY = from.hy;
  1699. X    e->bottomX = to.hx;
  1700. X     e->bottomY = to.hy;
  1701. X    e->dir = dir;
  1702. X    e->clip = clip;
  1703. X    
  1704. X     return 1;
  1705. X }
  1706. X
  1707. Xstatic void BuildEdgeList (path, clip) Path path; int clip;
  1708. X {
  1709. X     Path p;
  1710. X     HardPoint move, here;
  1711. X     
  1712. X     for (p = path->next; p != path; p = p->next)
  1713. X      switch (p->ptype)
  1714. X       {
  1715. X           case EMove: move = here = p->pe.point; break;
  1716. X           case ELine:
  1717. X               nedges += AddEdge (&edge[nedges], here, p->pe.point, clip);
  1718. X               here = p->pe.point;
  1719. X               break;
  1720. X           
  1721. X           case EClose:
  1722. X               nedges += AddEdge (&edge[nedges], here, move, clip);
  1723. X               here = move;
  1724. X               break;
  1725. X       }
  1726. X }
  1727. X
  1728. X/* keep list of interesting entries to come */
  1729. X
  1730. Xstruct lowest
  1731. X {
  1732. X    struct lowest *higher;
  1733. X    int e;
  1734. X } *lowest_free = NULL, *lowest = NULL;
  1735. X
  1736. Xstatic int NextLowest (y) int y;
  1737. X {
  1738. X    int res;
  1739. X    struct lowest *p;
  1740. X    
  1741. X    for (p = lowest; p && p->e <= y; p = lowest)    /* delete any which are now irrelevent */
  1742. X     {
  1743. X         lowest = p->higher;
  1744. X         p->higher = lowest_free;
  1745. X         lowest_free = p;
  1746. X     }
  1747. X    
  1748. X    if (lowest == NULL)
  1749. X        return 0;
  1750. X    res = lowest->e;
  1751. X    
  1752. X    return res;
  1753. X }
  1754. X
  1755. Xstatic void AddLowest (e) int e;
  1756. X {
  1757. X     struct lowest *res, *p, *q;
  1758. X     
  1759. X     for (p = lowest; p && p->e < e; q = p, p = p->higher)
  1760. X         ;
  1761. X     
  1762. X     if (p && p->e == e)
  1763. X         return;
  1764. X    if (lowest_free == NULL)
  1765. X         res = (struct lowest *) Malloc (sizeof (struct lowest));
  1766. X     else
  1767. X         res = lowest_free, lowest_free = lowest_free->higher;
  1768. X     
  1769. X      res->e = e;
  1770. X     res->higher = p;
  1771. X     if (p != lowest)
  1772. X         q->higher = res;
  1773. X     else
  1774. X         lowest = res;
  1775. X }
  1776. END_OF_FILE
  1777. if test 14650 -ne `wc -c <'source/fill.c'`; then
  1778.     echo shar: \"'source/fill.c'\" unpacked with wrong size!
  1779. fi
  1780. # end of 'source/fill.c'
  1781. fi
  1782. echo shar: End of archive 12 \(of 18\).
  1783. cp /dev/null ark12isdone
  1784. MISSING=""
  1785. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ; do
  1786.     if test ! -f ark${I}isdone ; then
  1787.     MISSING="${MISSING} ${I}"
  1788.     fi
  1789. done
  1790. if test "${MISSING}" = "" ; then
  1791.     echo You have unpacked all 18 archives.
  1792.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1793. else
  1794.     echo You still need to unpack the following archives:
  1795.     echo "        " ${MISSING}
  1796. fi
  1797. ##  End of shell archive.
  1798. exit 0
  1799.