home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / gd201.zip / gd-2.0.1 / gd.c < prev    next >
C/C++ Source or Header  |  2001-04-03  |  51KB  |  2,527 lines

  1. #include <stdio.h>
  2. #include <math.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #include <zlib.h>
  6. #include "gd.h"
  7. #include "gdhelpers.h"
  8.  
  9. #ifdef _OSD_POSIX        /* BS2000 uses the EBCDIC char set instead of ASCII */
  10. #define CHARSET_EBCDIC
  11. #define __attribute__(any)    /*nothing */
  12. #endif
  13. /*_OSD_POSIX*/
  14.  
  15. #ifndef CHARSET_EBCDIC
  16. #define ASC(ch)  ch
  17. #else /*CHARSET_EBCDIC */
  18. #define ASC(ch) gd_toascii[(unsigned char)ch]
  19. static const unsigned char gd_toascii[256] =
  20. {
  21. /*00 */ 0x00, 0x01, 0x02, 0x03, 0x85, 0x09, 0x86, 0x7f,
  22.   0x87, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,    /*................ */
  23. /*10 */ 0x10, 0x11, 0x12, 0x13, 0x8f, 0x0a, 0x08, 0x97,
  24.   0x18, 0x19, 0x9c, 0x9d, 0x1c, 0x1d, 0x1e, 0x1f,    /*................ */
  25. /*20 */ 0x80, 0x81, 0x82, 0x83, 0x84, 0x92, 0x17, 0x1b,
  26.   0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07,    /*................ */
  27. /*30 */ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
  28.   0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a,    /*................ */
  29. /*40 */ 0x20, 0xa0, 0xe2, 0xe4, 0xe0, 0xe1, 0xe3, 0xe5,
  30.   0xe7, 0xf1, 0x60, 0x2e, 0x3c, 0x28, 0x2b, 0x7c,    /* .........`.<(+| */
  31. /*50 */ 0x26, 0xe9, 0xea, 0xeb, 0xe8, 0xed, 0xee, 0xef,
  32.   0xec, 0xdf, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x9f,    /*&.........!$*);. */
  33. /*60 */ 0x2d, 0x2f, 0xc2, 0xc4, 0xc0, 0xc1, 0xc3, 0xc5,
  34.   0xc7, 0xd1, 0x5e, 0x2c, 0x25, 0x5f, 0x3e, 0x3f,
  35. /*-/........^,%_>?*/
  36. /*70 */ 0xf8, 0xc9, 0xca, 0xcb, 0xc8, 0xcd, 0xce, 0xcf,
  37.   0xcc, 0xa8, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22,    /*..........:#@'=" */
  38. /*80 */ 0xd8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
  39.   0x68, 0x69, 0xab, 0xbb, 0xf0, 0xfd, 0xfe, 0xb1,    /*.abcdefghi...... */
  40. /*90 */ 0xb0, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
  41.   0x71, 0x72, 0xaa, 0xba, 0xe6, 0xb8, 0xc6, 0xa4,    /*.jklmnopqr...... */
  42. /*a0 */ 0xb5, 0xaf, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
  43.   0x79, 0x7a, 0xa1, 0xbf, 0xd0, 0xdd, 0xde, 0xae,    /*..stuvwxyz...... */
  44. /*b0 */ 0xa2, 0xa3, 0xa5, 0xb7, 0xa9, 0xa7, 0xb6, 0xbc,
  45.   0xbd, 0xbe, 0xac, 0x5b, 0x5c, 0x5d, 0xb4, 0xd7,    /*...........[\].. */
  46. /*c0 */ 0xf9, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
  47.   0x48, 0x49, 0xad, 0xf4, 0xf6, 0xf2, 0xf3, 0xf5,    /*.ABCDEFGHI...... */
  48. /*d0 */ 0xa6, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
  49.   0x51, 0x52, 0xb9, 0xfb, 0xfc, 0xdb, 0xfa, 0xff,    /*.JKLMNOPQR...... */
  50. /*e0 */ 0xd9, 0xf7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
  51.   0x59, 0x5a, 0xb2, 0xd4, 0xd6, 0xd2, 0xd3, 0xd5,    /*..STUVWXYZ...... */
  52. /*f0 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
  53.   0x38, 0x39, 0xb3, 0x7b, 0xdc, 0x7d, 0xda, 0x7e    /*0123456789.{.}.~ */
  54. };
  55. #endif /*CHARSET_EBCDIC */
  56.  
  57. extern int gdCosT[];
  58. extern int gdSinT[];
  59.  
  60. static void gdImageBrushApply (gdImagePtr im, int x, int y);
  61. static void gdImageTileApply (gdImagePtr im, int x, int y);
  62.  
  63. gdImagePtr
  64. gdImageCreate (int sx, int sy)
  65. {
  66.   int i;
  67.   gdImagePtr im;
  68.   im = (gdImage *) gdMalloc (sizeof (gdImage));
  69.   memset (im, 0, sizeof (gdImage));
  70.   /* Row-major ever since gd 1.3 */
  71.   im->pixels = (unsigned char **) gdMalloc (sizeof (unsigned char *) * sy);
  72.   im->polyInts = 0;
  73.   im->polyAllocated = 0;
  74.   im->brush = 0;
  75.   im->tile = 0;
  76.   im->style = 0;
  77.   for (i = 0; (i < sy); i++)
  78.     {
  79.       /* Row-major ever since gd 1.3 */
  80.       im->pixels[i] = (unsigned char *) gdCalloc (
  81.                         sx, sizeof (unsigned char));
  82.     }
  83.   im->sx = sx;
  84.   im->sy = sy;
  85.   im->colorsTotal = 0;
  86.   im->transparent = (-1);
  87.   im->interlace = 0;
  88.   im->thick = 1;
  89.   for (i = 0; (i < gdMaxColors); i++)
  90.     {
  91.       im->open[i] = 1;
  92.       im->red[i] = 0;
  93.       im->green[i] = 0;
  94.       im->blue[i] = 0;
  95.     };
  96.   im->trueColor = 0;
  97.   im->tpixels = 0;
  98.   return im;
  99. }
  100.  
  101. gdImagePtr
  102. gdImageCreateTrueColor (int sx, int sy)
  103. {
  104.   int i;
  105.   gdImagePtr im;
  106.   im = (gdImage *) gdMalloc (sizeof (gdImage));
  107.   memset (im, 0, sizeof (gdImage));
  108.   im->tpixels = (int **) gdMalloc (sizeof (int *) * sy);
  109.   im->polyInts = 0;
  110.   im->polyAllocated = 0;
  111.   im->brush = 0;
  112.   im->tile = 0;
  113.   im->style = 0;
  114.   for (i = 0; (i < sy); i++)
  115.     {
  116.       im->tpixels[i] = (int *) gdCalloc (
  117.                       sx, sizeof (int));
  118.     }
  119.   im->sx = sx;
  120.   im->sy = sy;
  121.   im->transparent = (-1);
  122.   im->interlace = 0;
  123.   im->trueColor = 1;
  124.   im->saveAlphaFlag = 1;
  125.   im->alphaBlendingFlag = 0;
  126.   im->thick = 1;
  127.   return im;
  128. }
  129.  
  130. void
  131. gdImageDestroy (gdImagePtr im)
  132. {
  133.   int i;
  134.   if (im->pixels)
  135.     {
  136.       for (i = 0; (i < im->sy); i++)
  137.     {
  138.       gdFree (im->pixels[i]);
  139.     }
  140.       gdFree (im->pixels);
  141.     }
  142.   if (im->tpixels)
  143.     {
  144.       for (i = 0; (i < im->sy); i++)
  145.     {
  146.       gdFree (im->tpixels[i]);
  147.     }
  148.       gdFree (im->tpixels);
  149.     }
  150.   if (im->polyInts)
  151.     {
  152.       gdFree (im->polyInts);
  153.     }
  154.   if (im->style)
  155.     {
  156.       gdFree (im->style);
  157.     }
  158.   gdFree (im);
  159. }
  160.  
  161. int
  162. gdImageColorClosest (gdImagePtr im, int r, int g, int b)
  163. {
  164.   return gdImageColorClosestAlpha (im, r, g, b, gdAlphaOpaque);
  165. }
  166.  
  167. int
  168. gdImageColorClosestAlpha (gdImagePtr im, int r, int g, int b, int a)
  169. {
  170.   int i;
  171.   long rd, gd, bd, ad;
  172.   int ct = (-1);
  173.   int first = 1;
  174.   long mindist = 0;
  175.   if (im->trueColor)
  176.     {
  177.       return gdTrueColorAlpha (r, g, b, a);
  178.     }
  179.   for (i = 0; (i < (im->colorsTotal)); i++)
  180.     {
  181.       long dist;
  182.       if (im->open[i])
  183.     {
  184.       continue;
  185.     }
  186.       rd = (im->red[i] - r);
  187.       gd = (im->green[i] - g);
  188.       bd = (im->blue[i] - b);
  189.       ad = (im->blue[i] - b);
  190.       dist = rd * rd + gd * gd + bd * bd + ad * ad;
  191.       if (first || (dist < mindist))
  192.     {
  193.       mindist = dist;
  194.       ct = i;
  195.       first = 0;
  196.     }
  197.     }
  198.   return ct;
  199. }
  200.  
  201. /* This code is taken from http://www.acm.org/jgt/papers/SmithLyons96/hwb_rgb.html, an article
  202.  * on colour conversion to/from RBG and HWB colour systems. 
  203.  * It has been modified to return the converted value as a * parameter. 
  204.  */
  205.  
  206. #define RETURN_HWB(h, w, b) {HWB->H = h; HWB->W = w; HWB->B = b; return HWB;}
  207. #define RETURN_RGB(r, g, b) {RGB->R = r; RGB->G = g; RGB->B = b; return RGB;}
  208. #define HWB_UNDEFINED -1
  209. #define SETUP_RGB(s, r, g, b) {s.R = r/255.0; s.G = g/255.0; s.B = b/255.0;}
  210.  
  211. #define MIN(a,b) ((a)<(b)?(a):(b))
  212. #define MIN3(a,b,c) ((a)<(b)?(MIN(a,c)):(MIN(b,c)))
  213. #define MAX(a,b) ((a)<(b)?(b):(a))
  214. #define MAX3(a,b,c) ((a)<(b)?(MAX(b,c)):(MAX(a,c)))
  215.  
  216.  
  217. /*
  218.  * Theoretically, hue 0 (pure red) is identical to hue 6 in these transforms. Pure 
  219.  * red always maps to 6 in this implementation. Therefore UNDEFINED can be 
  220.  * defined as 0 in situations where only unsigned numbers are desired.
  221.  */
  222. typedef struct
  223. {
  224.   float R, G, B;
  225. }
  226. RGBType;
  227. typedef struct
  228.   {
  229.     float H, W, B;
  230.   }
  231. HWBType;
  232.  
  233. static HWBType *
  234. RGB_to_HWB (RGBType RGB, HWBType * HWB)
  235. {
  236.  
  237.   /*
  238.    * RGB are each on [0, 1]. W and B are returned on [0, 1] and H is  
  239.    * returned on [0, 6]. Exception: H is returned UNDEFINED if W == 1 - B.  
  240.    */
  241.  
  242.   float R = RGB.R, G = RGB.G, B = RGB.B, w, v, b, f;
  243.   int i;
  244.  
  245.   w = MIN3 (R, G, B);
  246.   v = MAX3 (R, G, B);
  247.   b = 1 - v;
  248.   if (v == w)
  249.     RETURN_HWB (HWB_UNDEFINED, w, b);
  250.   f = (R == w) ? G - B : ((G == w) ? B - R : R - G);
  251.   i = (R == w) ? 3 : ((G == w) ? 5 : 1);
  252.   RETURN_HWB (i - f / (v - w), w, b);
  253.  
  254. }
  255.  
  256. static float
  257. HWB_Diff (int r1, int g1, int b1, int r2, int g2, int b2)
  258. {
  259.   RGBType RGB1, RGB2;
  260.   HWBType HWB1, HWB2;
  261.   float diff;
  262.  
  263.   SETUP_RGB (RGB1, r1, g1, b1);
  264.   SETUP_RGB (RGB2, r2, g2, b2);
  265.  
  266.   RGB_to_HWB (RGB1, &HWB1);
  267.   RGB_to_HWB (RGB2, &HWB2);
  268.  
  269.   /*
  270.    * I made this bit up; it seems to produce OK results, and it is certainly
  271.    * more visually correct than the current RGB metric. (PJW)
  272.    */
  273.  
  274.   if ((HWB1.H == HWB_UNDEFINED) || (HWB2.H == HWB_UNDEFINED))
  275.     {
  276.       diff = 0;            /* Undefined hues always match... */
  277.     }
  278.   else
  279.     {
  280.       diff = abs (HWB1.H - HWB2.H);
  281.       if (diff > 3)
  282.     {
  283.       diff = 6 - diff;    /* Remember, it's a colour circle */
  284.     }
  285.     }
  286.  
  287.   diff = diff * diff + (HWB1.W - HWB2.W) * (HWB1.W - HWB2.W) + (HWB1.B - HWB2.B) * (HWB1.B - HWB2.B);
  288.  
  289.   return diff;
  290. }
  291.  
  292.  
  293. /*
  294.  * This is not actually used, but is here for completeness, in case someone wants to
  295.  * use the HWB stuff for anything else...
  296.  */
  297. static RGBType *
  298. HWB_to_RGB (HWBType HWB, RGBType * RGB)
  299. {
  300.  
  301.   /* 
  302.    * H is given on [0, 6] or UNDEFINED. W and B are given on [0, 1].  
  303.    * RGB are each returned on [0, 1]. 
  304.    */
  305.  
  306.   float h = HWB.H, w = HWB.W, b = HWB.B, v, n, f;
  307.   int i;
  308.  
  309.   v = 1 - b;
  310.   if (h == HWB_UNDEFINED)
  311.     RETURN_RGB (v, v, v);
  312.   i = floor (h);
  313.   f = h - i;
  314.   if (i & 1)
  315.     f = 1 - f;            /* if i is odd */
  316.   n = w + f * (v - w);        /* linear interpolation between w and v */
  317.   switch (i)
  318.     {
  319.     case 6:
  320.     case 0:
  321.       RETURN_RGB (v, n, w);
  322.     case 1:
  323.       RETURN_RGB (n, v, w);
  324.     case 2:
  325.       RETURN_RGB (w, v, n);
  326.     case 3:
  327.       RETURN_RGB (w, n, v);
  328.     case 4:
  329.       RETURN_RGB (n, w, v);
  330.     case 5:
  331.       RETURN_RGB (v, w, n);
  332.     }
  333.  
  334.   return RGB;
  335.  
  336. }
  337.  
  338. int
  339. gdImageColorClosestHWB (gdImagePtr im, int r, int g, int b)
  340. {
  341.   int i;
  342.   /* long rd, gd, bd; */
  343.   int ct = (-1);
  344.   int first = 1;
  345.   float mindist = 0;
  346.   if (im->trueColor)
  347.     {
  348.       return gdTrueColor (r, g, b);
  349.     }
  350.   for (i = 0; (i < (im->colorsTotal)); i++)
  351.     {
  352.       float dist;
  353.       if (im->open[i])
  354.     {
  355.       continue;
  356.     }
  357.       dist = HWB_Diff (im->red[i], im->green[i], im->blue[i], r, g, b);
  358.       if (first || (dist < mindist))
  359.     {
  360.       mindist = dist;
  361.       ct = i;
  362.       first = 0;
  363.     }
  364.     }
  365.   return ct;
  366. }
  367.  
  368. int
  369. gdImageColorExact (gdImagePtr im, int r, int g, int b)
  370. {
  371.   return gdImageColorExactAlpha (im, r, g, b, gdAlphaOpaque);
  372. }
  373.  
  374. int
  375. gdImageColorExactAlpha (gdImagePtr im, int r, int g, int b, int a)
  376. {
  377.   int i;
  378.   if (im->trueColor)
  379.     {
  380.       return gdTrueColorAlpha (r, g, b, a);
  381.     }
  382.   for (i = 0; (i < (im->colorsTotal)); i++)
  383.     {
  384.       if (im->open[i])
  385.     {
  386.       continue;
  387.     }
  388.       if ((im->red[i] == r) &&
  389.       (im->green[i] == g) &&
  390.       (im->blue[i] == b) &&
  391.       (im->alpha[i] == a))
  392.     {
  393.       return i;
  394.     }
  395.     }
  396.   return -1;
  397. }
  398.  
  399. int
  400. gdImageColorAllocate (gdImagePtr im, int r, int g, int b)
  401. {
  402.   return gdImageColorAllocateAlpha (im, r, g, b, gdAlphaOpaque);
  403. }
  404.  
  405. int
  406. gdImageColorAllocateAlpha (gdImagePtr im, int r, int g, int b, int a)
  407. {
  408.   int i;
  409.   int ct = (-1);
  410.   if (im->trueColor)
  411.     {
  412.       return gdTrueColorAlpha (r, g, b, a);
  413.     }
  414.   for (i = 0; (i < (im->colorsTotal)); i++)
  415.     {
  416.       if (im->open[i])
  417.     {
  418.       ct = i;
  419.       break;
  420.     }
  421.     }
  422.   if (ct == (-1))
  423.     {
  424.       ct = im->colorsTotal;
  425.       if (ct == gdMaxColors)
  426.     {
  427.       return -1;
  428.     }
  429.       im->colorsTotal++;
  430.     }
  431.   im->red[ct] = r;
  432.   im->green[ct] = g;
  433.   im->blue[ct] = b;
  434.   im->alpha[ct] = a;
  435.   im->open[ct] = 0;
  436.   return ct;
  437. }
  438.  
  439. /*
  440.  * gdImageColorResolve is an alternative for the code fragment:
  441.  *
  442.  *      if ((color=gdImageColorExact(im,R,G,B)) < 0)
  443.  *        if ((color=gdImageColorAllocate(im,R,G,B)) < 0)
  444.  *          color=gdImageColorClosest(im,R,G,B);
  445.  *
  446.  * in a single function.    Its advantage is that it is guaranteed to
  447.  * return a color index in one search over the color table.
  448.  */
  449.  
  450. int
  451. gdImageColorResolve (gdImagePtr im, int r, int g, int b)
  452. {
  453.   return gdImageColorResolveAlpha (im, r, g, b, gdAlphaOpaque);
  454. }
  455.  
  456. int
  457. gdImageColorResolveAlpha (gdImagePtr im, int r, int g, int b, int a)
  458. {
  459.   int c;
  460.   int ct = -1;
  461.   int op = -1;
  462.   long rd, gd, bd, ad, dist;
  463.   long mindist = 4 * 255 * 255;    /* init to max poss dist */
  464.   if (im->trueColor)
  465.     {
  466.       return gdTrueColorAlpha (r, g, b, a);
  467.     }
  468.  
  469.   for (c = 0; c < im->colorsTotal; c++)
  470.     {
  471.       if (im->open[c])
  472.     {
  473.       op = c;        /* Save open slot */
  474.       continue;        /* Color not in use */
  475.     }
  476.       rd = (long) (im->red[c] - r);
  477.       gd = (long) (im->green[c] - g);
  478.       bd = (long) (im->blue[c] - b);
  479.       ad = (long) (im->alpha[c] - a);
  480.       dist = rd * rd + gd * gd + bd * bd + ad * ad;
  481.       if (dist < mindist)
  482.     {
  483.       if (dist == 0)
  484.         {
  485.           return c;        /* Return exact match color */
  486.         }
  487.       mindist = dist;
  488.       ct = c;
  489.     }
  490.     }
  491.   /* no exact match.  We now know closest, but first try to allocate exact */
  492.   if (op == -1)
  493.     {
  494.       op = im->colorsTotal;
  495.       if (op == gdMaxColors)
  496.     {            /* No room for more colors */
  497.       return ct;        /* Return closest available color */
  498.     }
  499.       im->colorsTotal++;
  500.     }
  501.   im->red[op] = r;
  502.   im->green[op] = g;
  503.   im->blue[op] = b;
  504.   im->alpha[op] = a;
  505.   im->open[op] = 0;
  506.   return op;            /* Return newly allocated color */
  507. }
  508.  
  509. void
  510. gdImageColorDeallocate (gdImagePtr im, int color)
  511. {
  512.   if (im->trueColor)
  513.     {
  514.       return;
  515.     }
  516.   /* Mark it open. */
  517.   im->open[color] = 1;
  518. }
  519.  
  520. void
  521. gdImageColorTransparent (gdImagePtr im, int color)
  522. {
  523.   if (!im->trueColor)
  524.     {
  525.       if (im->transparent != -1)
  526.     {
  527.       im->alpha[im->transparent] = gdAlphaOpaque;
  528.     }
  529.       if (color != -1)
  530.     {
  531.       im->alpha[color] = gdAlphaTransparent;
  532.     }
  533.     }
  534.   im->transparent = color;
  535. }
  536.  
  537. void
  538. gdImagePaletteCopy (gdImagePtr to, gdImagePtr from)
  539. {
  540.   int i;
  541.   int x, y, p;
  542.   int xlate[256];
  543.   if (to->trueColor)
  544.     {
  545.       return;
  546.     }
  547.   if (from->trueColor)
  548.     {
  549.       return;
  550.     }
  551.  
  552.   for (i = 0; i < 256; i++)
  553.     {
  554.       xlate[i] = -1;
  555.     };
  556.  
  557.   for (x = 0; x < (to->sx); x++)
  558.     {
  559.       for (y = 0; y < (to->sy); y++)
  560.     {
  561.       p = gdImageGetPixel (to, x, y);
  562.       if (xlate[p] == -1)
  563.         {
  564.           /* This ought to use HWB, but we don't have an alpha-aware
  565.              version of that yet. */
  566.           xlate[p] = gdImageColorClosestAlpha (from, to->red[p], to->green[p], to->blue[p], to->alpha[p]);
  567.           /*printf("Mapping %d (%d, %d, %d, %d) to %d (%d, %d, %d, %d)\n", */
  568.           /*      p,  to->red[p], to->green[p], to->blue[p], to->alpha[p], */
  569.           /*      xlate[p], from->red[xlate[p]], from->green[xlate[p]], from->blue[xlate[p]], from->alpha[xlate[p]]); */
  570.         };
  571.       gdImageSetPixel (to, x, y, xlate[p]);
  572.     };
  573.     };
  574.  
  575.   for (i = 0; (i < (from->colorsTotal)); i++)
  576.     {
  577.       /*printf("Copying color %d (%d, %d, %d, %d)\n", i, from->red[i], from->blue[i], from->green[i], from->alpha[i]); */
  578.       to->red[i] = from->red[i];
  579.       to->blue[i] = from->blue[i];
  580.       to->green[i] = from->green[i];
  581.       to->alpha[i] = from->alpha[i];
  582.       to->open[i] = 0;
  583.     };
  584.  
  585.   for (i = from->colorsTotal; (i < to->colorsTotal); i++)
  586.     {
  587.       to->open[i] = 1;
  588.     };
  589.  
  590.   to->colorsTotal = from->colorsTotal;
  591.  
  592. }
  593.  
  594. void
  595. gdImageSetPixel (gdImagePtr im, int x, int y, int color)
  596. {
  597.   int p;
  598.   switch (color)
  599.     {
  600.     case gdStyled:
  601.       if (!im->style)
  602.     {
  603.       /* Refuse to draw if no style is set. */
  604.       return;
  605.     }
  606.       else
  607.     {
  608.       p = im->style[im->stylePos++];
  609.     }
  610.       if (p != (gdTransparent))
  611.     {
  612.       gdImageSetPixel (im, x, y, p);
  613.     }
  614.       im->stylePos = im->stylePos % im->styleLength;
  615.       break;
  616.     case gdStyledBrushed:
  617.       if (!im->style)
  618.     {
  619.       /* Refuse to draw if no style is set. */
  620.       return;
  621.     }
  622.       p = im->style[im->stylePos++];
  623.       if ((p != gdTransparent) && (p != 0))
  624.     {
  625.       gdImageSetPixel (im, x, y, gdBrushed);
  626.     }
  627.       im->stylePos = im->stylePos % im->styleLength;
  628.       break;
  629.     case gdBrushed:
  630.       gdImageBrushApply (im, x, y);
  631.       break;
  632.     case gdTiled:
  633.       gdImageTileApply (im, x, y);
  634.       break;
  635.     default:
  636.       if (gdImageBoundsSafe (im, x, y))
  637.     {
  638.       if (im->trueColor)
  639.         {
  640.           if (im->alphaBlendingFlag)
  641.         {
  642.           im->tpixels[y][x] =
  643.             gdAlphaBlend (im->tpixels[y][x],
  644.                   color);
  645.         }
  646.           else
  647.         {
  648.           im->tpixels[y][x] = color;
  649.         }
  650.         }
  651.       else
  652.         {
  653.           im->pixels[y][x] = color;
  654.         }
  655.     }
  656.       break;
  657.     }
  658. }
  659.  
  660. static void
  661. gdImageBrushApply (gdImagePtr im, int x, int y)
  662. {
  663.   int lx, ly;
  664.   int hy;
  665.   int hx;
  666.   int x1, y1, x2, y2;
  667.   int srcx, srcy;
  668.   if (!im->brush)
  669.     {
  670.       return;
  671.     }
  672.   hy = gdImageSY (im->brush) / 2;
  673.   y1 = y - hy;
  674.   y2 = y1 + gdImageSY (im->brush);
  675.   hx = gdImageSX (im->brush) / 2;
  676.   x1 = x - hx;
  677.   x2 = x1 + gdImageSX (im->brush);
  678.   srcy = 0;
  679.   if (im->trueColor)
  680.     {
  681.       for (ly = y1; (ly < y2); ly++)
  682.     {
  683.       srcx = 0;
  684.       for (lx = x1; (lx < x2); lx++)
  685.         {
  686.           int p;
  687.           p = gdImageGetTrueColorPixel (
  688.                          im->brush, srcx, srcy);
  689.           gdImageSetPixel (im, lx, ly,
  690.                    p);
  691.           srcx++;
  692.         }
  693.       srcy++;
  694.     }
  695.     }
  696.   else
  697.     {
  698.       for (ly = y1; (ly < y2); ly++)
  699.     {
  700.       srcx = 0;
  701.       for (lx = x1; (lx < x2); lx++)
  702.         {
  703.           int p;
  704.           p = gdImageGetPixel (im->brush, srcx, srcy);
  705.           /* Allow for non-square brushes! */
  706.           if (p != gdImageGetTransparent (im->brush))
  707.         {
  708.           /* Truecolor brush. Very slow
  709.              on a palette destination. */
  710.           if (im->brush->trueColor)
  711.             {
  712.               gdImageSetPixel (im, lx, ly,
  713.                        gdImageColorResolveAlpha (
  714.                                   im,
  715.                               gdTrueColorGetRed (p),
  716.                             gdTrueColorGetGreen (p),
  717.                              gdTrueColorGetBlue (p),
  718.                           gdTrueColorGetAlpha (p)));
  719.             }
  720.           else
  721.             {
  722.               gdImageSetPixel (im, lx, ly,
  723.                        im->brushColorMap[p]);
  724.             }
  725.         }
  726.           srcx++;
  727.         }
  728.       srcy++;
  729.     }
  730.     }
  731. }
  732.  
  733. static void
  734. gdImageTileApply (gdImagePtr im, int x, int y)
  735. {
  736.   int srcx, srcy;
  737.   int p;
  738.   if (!im->tile)
  739.     {
  740.       return;
  741.     }
  742.   srcx = x % gdImageSX (im->tile);
  743.   srcy = y % gdImageSY (im->tile);
  744.   if (im->trueColor)
  745.     {
  746.       p = gdImageGetTrueColorPixel (im->tile, srcx, srcy);
  747.       gdImageSetPixel (im, x, y, p);
  748.     }
  749.   else
  750.     {
  751.       /* Allow for transparency */
  752.       if (p != gdImageGetTransparent (im->tile))
  753.     {
  754.       if (im->tile->trueColor)
  755.         {
  756.           /* Truecolor tile. Very slow
  757.              on a palette destination. */
  758.           gdImageSetPixel (im, x, y,
  759.                    gdImageColorResolveAlpha (
  760.                               im,
  761.                               gdTrueColorGetRed (p),
  762.                             gdTrueColorGetGreen (p),
  763.                              gdTrueColorGetBlue (p),
  764.                           gdTrueColorGetAlpha (p)));
  765.         }
  766.       else
  767.         {
  768.           gdImageSetPixel (im, x, y,
  769.                    im->tileColorMap[p]);
  770.         }
  771.     }
  772.     }
  773. }
  774.  
  775. int
  776. gdImageGetPixel (gdImagePtr im, int x, int y)
  777. {
  778.   if (gdImageBoundsSafe (im, x, y))
  779.     {
  780.       if (im->trueColor)
  781.     {
  782.       return im->tpixels[y][x];
  783.     }
  784.       else
  785.     {
  786.       return im->pixels[y][x];
  787.     }
  788.     }
  789.   else
  790.     {
  791.       return 0;
  792.     }
  793. }
  794.  
  795. int
  796. gdImageGetTrueColorPixel (gdImagePtr im, int x, int y)
  797. {
  798.   int p = gdImageGetPixel (im, x, y);
  799.   if (!im->trueColor)
  800.     {
  801.       return gdTrueColorAlpha (im->red[p], im->green[p], im->blue[p],
  802.                    (im->transparent == p) ? gdAlphaTransparent :
  803.                    gdAlphaOpaque);
  804.     }
  805.   else
  806.     {
  807.       return p;
  808.     }
  809. }
  810.  
  811. /* Bresenham as presented in Foley & Van Dam */
  812. void
  813. gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
  814. {
  815.   int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
  816.   int wid;
  817.   int w, wstart;
  818.   int thick = im->thick;
  819.   dx = abs (x2 - x1);
  820.   dy = abs (y2 - y1);
  821.   if (dy <= dx)
  822.     {
  823.       /* More-or-less horizontal. use wid for vertical stroke */
  824.       wid = thick * cos (atan2 (dy, dx));
  825.       if (wid == 0)
  826.     wid = 1;
  827.  
  828.       d = 2 * dy - dx;
  829.       incr1 = 2 * dy;
  830.       incr2 = 2 * (dy - dx);
  831.       if (x1 > x2)
  832.     {
  833.       x = x2;
  834.       y = y2;
  835.       ydirflag = (-1);
  836.       xend = x1;
  837.     }
  838.       else
  839.     {
  840.       x = x1;
  841.       y = y1;
  842.       ydirflag = 1;
  843.       xend = x2;
  844.     }
  845.  
  846.       /* Set up line thickness */
  847.       wstart = y - wid / 2;
  848.       for (w = wstart; w < wstart + wid; w++)
  849.     gdImageSetPixel (im, x, w, color);
  850.  
  851.       if (((y2 - y1) * ydirflag) > 0)
  852.     {
  853.       while (x < xend)
  854.         {
  855.           x++;
  856.           if (d < 0)
  857.         {
  858.           d += incr1;
  859.         }
  860.           else
  861.         {
  862.           y++;
  863.           d += incr2;
  864.         }
  865.           wstart = y - wid / 2;
  866.           for (w = wstart; w < wstart + wid; w++)
  867.         gdImageSetPixel (im, x, w, color);
  868.         }
  869.     }
  870.       else
  871.     {
  872.       while (x < xend)
  873.         {
  874.           x++;
  875.           if (d < 0)
  876.         {
  877.           d += incr1;
  878.         }
  879.           else
  880.         {
  881.           y--;
  882.           d += incr2;
  883.         }
  884.           wstart = y - wid / 2;
  885.           for (w = wstart; w < wstart + wid; w++)
  886.         gdImageSetPixel (im, x, w, color);
  887.         }
  888.     }
  889.     }
  890.   else
  891.     {
  892.       /* More-or-less vertical. use wid for horizontal stroke */
  893.       wid = thick * sin (atan2 (dy, dx));
  894.       if (wid == 0)
  895.     wid = 1;
  896.  
  897.       d = 2 * dx - dy;
  898.       incr1 = 2 * dx;
  899.       incr2 = 2 * (dx - dy);
  900.       if (y1 > y2)
  901.     {
  902.       y = y2;
  903.       x = x2;
  904.       yend = y1;
  905.       xdirflag = (-1);
  906.     }
  907.       else
  908.     {
  909.       y = y1;
  910.       x = x1;
  911.       yend = y2;
  912.       xdirflag = 1;
  913.     }
  914.  
  915.       /* Set up line thickness */
  916.       wstart = x - wid / 2;
  917.       for (w = wstart; w < wstart + wid; w++)
  918.     gdImageSetPixel (im, w, y, color);
  919.  
  920.       if (((x2 - x1) * xdirflag) > 0)
  921.     {
  922.       while (y < yend)
  923.         {
  924.           y++;
  925.           if (d < 0)
  926.         {
  927.           d += incr1;
  928.         }
  929.           else
  930.         {
  931.           x++;
  932.           d += incr2;
  933.         }
  934.           wstart = x - wid / 2;
  935.           for (w = wstart; w < wstart + wid; w++)
  936.         gdImageSetPixel (im, w, y, color);
  937.         }
  938.     }
  939.       else
  940.     {
  941.       while (y < yend)
  942.         {
  943.           y++;
  944.           if (d < 0)
  945.         {
  946.           d += incr1;
  947.         }
  948.           else
  949.         {
  950.           x--;
  951.           d += incr2;
  952.         }
  953.           wstart = x - wid / 2;
  954.           for (w = wstart; w < wstart + wid; w++)
  955.         gdImageSetPixel (im, w, y, color);
  956.         }
  957.     }
  958.     }
  959. }
  960. static void dashedSet (gdImagePtr im, int x, int y, int color,
  961.                int *onP, int *dashStepP, int wid, int vert);
  962.  
  963. void
  964. gdImageDashedLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
  965. {
  966.   int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
  967.   int dashStep = 0;
  968.   int on = 1;
  969.   int wid;
  970.   int w, wstart, vert;
  971.   int thick = im->thick;
  972.  
  973.   dx = abs (x2 - x1);
  974.   dy = abs (y2 - y1);
  975.   if (dy <= dx)
  976.     {
  977.       /* More-or-less horizontal. use wid for vertical stroke */
  978.       wid = thick * sin (atan2 (dy, dx));
  979.       vert = 1;
  980.  
  981.       d = 2 * dy - dx;
  982.       incr1 = 2 * dy;
  983.       incr2 = 2 * (dy - dx);
  984.       if (x1 > x2)
  985.     {
  986.       x = x2;
  987.       y = y2;
  988.       ydirflag = (-1);
  989.       xend = x1;
  990.     }
  991.       else
  992.     {
  993.       x = x1;
  994.       y = y1;
  995.       ydirflag = 1;
  996.       xend = x2;
  997.     }
  998.       dashedSet (im, x, y, color, &on, &dashStep, wid, vert);
  999.       if (((y2 - y1) * ydirflag) > 0)
  1000.     {
  1001.       while (x < xend)
  1002.         {
  1003.           x++;
  1004.           if (d < 0)
  1005.         {
  1006.           d += incr1;
  1007.         }
  1008.           else
  1009.         {
  1010.           y++;
  1011.           d += incr2;
  1012.         }
  1013.           dashedSet (im, x, y, color, &on, &dashStep, wid, vert);
  1014.         }
  1015.     }
  1016.       else
  1017.     {
  1018.       while (x < xend)
  1019.         {
  1020.           x++;
  1021.           if (d < 0)
  1022.         {
  1023.           d += incr1;
  1024.         }
  1025.           else
  1026.         {
  1027.           y--;
  1028.           d += incr2;
  1029.         }
  1030.           dashedSet (im, x, y, color, &on, &dashStep, wid, vert);
  1031.         }
  1032.     }
  1033.     }
  1034.   else
  1035.     {
  1036.       /* More-or-less vertical. use wid for horizontal stroke */
  1037.       wid = thick * sin (atan2 (dy, dx));
  1038.       vert = 0;
  1039.  
  1040.       d = 2 * dx - dy;
  1041.       incr1 = 2 * dx;
  1042.       incr2 = 2 * (dx - dy);
  1043.       if (y1 > y2)
  1044.     {
  1045.       y = y2;
  1046.       x = x2;
  1047.       yend = y1;
  1048.       xdirflag = (-1);
  1049.     }
  1050.       else
  1051.     {
  1052.       y = y1;
  1053.       x = x1;
  1054.       yend = y2;
  1055.       xdirflag = 1;
  1056.     }
  1057.       dashedSet (im, x, y, color, &on, &dashStep, wid, vert);
  1058.       if (((x2 - x1) * xdirflag) > 0)
  1059.     {
  1060.       while (y < yend)
  1061.         {
  1062.           y++;
  1063.           if (d < 0)
  1064.         {
  1065.           d += incr1;
  1066.         }
  1067.           else
  1068.         {
  1069.           x++;
  1070.           d += incr2;
  1071.         }
  1072.           dashedSet (im, x, y, color, &on, &dashStep, wid, vert);
  1073.         }
  1074.     }
  1075.       else
  1076.     {
  1077.       while (y < yend)
  1078.         {
  1079.           y++;
  1080.           if (d < 0)
  1081.         {
  1082.           d += incr1;
  1083.         }
  1084.           else
  1085.         {
  1086.           x--;
  1087.           d += incr2;
  1088.         }
  1089.           dashedSet (im, x, y, color, &on, &dashStep, wid, vert);
  1090.         }
  1091.     }
  1092.     }
  1093. }
  1094.  
  1095. static void
  1096. dashedSet (gdImagePtr im, int x, int y, int color,
  1097.        int *onP, int *dashStepP, int wid, int vert)
  1098. {
  1099.   int dashStep = *dashStepP;
  1100.   int on = *onP;
  1101.   int w, wstart;
  1102.  
  1103.   dashStep++;
  1104.   if (dashStep == gdDashSize)
  1105.     {
  1106.       dashStep = 0;
  1107.       on = !on;
  1108.     }
  1109.   if (on)
  1110.     {
  1111.       if (vert)
  1112.     {
  1113.       wstart = y - wid / 2;
  1114.       for (w = wstart; w < wstart + wid; w++)
  1115.         gdImageSetPixel (im, x, w, color);
  1116.     }
  1117.       else
  1118.     {
  1119.       wstart = x - wid / 2;
  1120.       for (w = wstart; w < wstart + wid; w++)
  1121.         gdImageSetPixel (im, w, y, color);
  1122.     }
  1123.     }
  1124.   *dashStepP = dashStep;
  1125.   *onP = on;
  1126. }
  1127.  
  1128. int
  1129. gdImageBoundsSafe (gdImagePtr im, int x, int y)
  1130. {
  1131.   return (!(((y < 0) || (y >= im->sy)) ||
  1132.         ((x < 0) || (x >= im->sx))));
  1133. }
  1134.  
  1135. void
  1136. gdImageChar (gdImagePtr im, gdFontPtr f, int x, int y,
  1137.          int c, int color)
  1138. {
  1139.   int cx, cy;
  1140.   int px, py;
  1141.   int fline;
  1142.   cx = 0;
  1143.   cy = 0;
  1144. #ifdef CHARSET_EBCDIC
  1145.   c = ASC (c);
  1146. #endif /*CHARSET_EBCDIC */
  1147.   if ((c < f->offset) || (c >= (f->offset + f->nchars)))
  1148.     {
  1149.       return;
  1150.     }
  1151.   fline = (c - f->offset) * f->h * f->w;
  1152.   for (py = y; (py < (y + f->h)); py++)
  1153.     {
  1154.       for (px = x; (px < (x + f->w)); px++)
  1155.     {
  1156.       if (f->data[fline + cy * f->w + cx])
  1157.         {
  1158.           gdImageSetPixel (im, px, py, color);
  1159.         }
  1160.       cx++;
  1161.     }
  1162.       cx = 0;
  1163.       cy++;
  1164.     }
  1165. }
  1166.  
  1167. void
  1168. gdImageCharUp (gdImagePtr im, gdFontPtr f,
  1169.            int x, int y, int c, int color)
  1170. {
  1171.   int cx, cy;
  1172.   int px, py;
  1173.   int fline;
  1174.   cx = 0;
  1175.   cy = 0;
  1176. #ifdef CHARSET_EBCDIC
  1177.   c = ASC (c);
  1178. #endif /*CHARSET_EBCDIC */
  1179.   if ((c < f->offset) || (c >= (f->offset + f->nchars)))
  1180.     {
  1181.       return;
  1182.     }
  1183.   fline = (c - f->offset) * f->h * f->w;
  1184.   for (py = y; (py > (y - f->w)); py--)
  1185.     {
  1186.       for (px = x; (px < (x + f->h)); px++)
  1187.     {
  1188.       if (f->data[fline + cy * f->w + cx])
  1189.         {
  1190.           gdImageSetPixel (im, px, py, color);
  1191.         }
  1192.       cy++;
  1193.     }
  1194.       cy = 0;
  1195.       cx++;
  1196.     }
  1197. }
  1198.  
  1199. void
  1200. gdImageString (gdImagePtr im, gdFontPtr f,
  1201.            int x, int y, unsigned char *s, int color)
  1202. {
  1203.   int i;
  1204.   int l;
  1205.   l = strlen ((char *) s);
  1206.   for (i = 0; (i < l); i++)
  1207.     {
  1208.       gdImageChar (im, f, x, y, s[i], color);
  1209.       x += f->w;
  1210.     }
  1211. }
  1212.  
  1213. void
  1214. gdImageStringUp (gdImagePtr im, gdFontPtr f,
  1215.          int x, int y, unsigned char *s, int color)
  1216. {
  1217.   int i;
  1218.   int l;
  1219.   l = strlen ((char *) s);
  1220.   for (i = 0; (i < l); i++)
  1221.     {
  1222.       gdImageCharUp (im, f, x, y, s[i], color);
  1223.       y -= f->w;
  1224.     }
  1225. }
  1226.  
  1227. static int strlen16 (unsigned short *s);
  1228.  
  1229. void
  1230. gdImageString16 (gdImagePtr im, gdFontPtr f,
  1231.          int x, int y, unsigned short *s, int color)
  1232. {
  1233.   int i;
  1234.   int l;
  1235.   l = strlen16 (s);
  1236.   for (i = 0; (i < l); i++)
  1237.     {
  1238.       gdImageChar (im, f, x, y, s[i], color);
  1239.       x += f->w;
  1240.     }
  1241. }
  1242.  
  1243. void
  1244. gdImageStringUp16 (gdImagePtr im, gdFontPtr f,
  1245.            int x, int y, unsigned short *s, int color)
  1246. {
  1247.   int i;
  1248.   int l;
  1249.   l = strlen16 (s);
  1250.   for (i = 0; (i < l); i++)
  1251.     {
  1252.       gdImageCharUp (im, f, x, y, s[i], color);
  1253.       y -= f->w;
  1254.     }
  1255. }
  1256.  
  1257. static int
  1258. strlen16 (unsigned short *s)
  1259. {
  1260.   int len = 0;
  1261.   while (*s)
  1262.     {
  1263.       s++;
  1264.       len++;
  1265.     }
  1266.   return len;
  1267. }
  1268.  
  1269. #ifndef HAVE_LSQRT
  1270. /* If you don't have a nice square root function for longs, you can use
  1271.    ** this hack
  1272.  */
  1273. long
  1274. lsqrt (long n)
  1275. {
  1276.   long result = (long) sqrt ((double) n);
  1277.   return result;
  1278. }
  1279. #endif
  1280.  
  1281. /* s and e are integers modulo 360 (degrees), with 0 degrees
  1282.    being the rightmost extreme and degrees changing clockwise.
  1283.    cx and cy are the center in pixels; w and h are the horizontal 
  1284.    and vertical diameter in pixels. Nice interface, but slow.
  1285.    See gd_arc_f_buggy.c for a better version that doesn't 
  1286.    seem to be bug-free yet. */
  1287.  
  1288. void 
  1289. gdImageArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e, int color)
  1290. {
  1291.   gdImageFilledArc (im, cx, cy, w, h, s, e, color, gdNoFill);
  1292. }
  1293.  
  1294. void 
  1295. gdImageFilledArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e, int color, int style)
  1296. {
  1297.   gdPoint pts[3];
  1298.   int i;
  1299.   int lx = 0, ly = 0;
  1300.   int fx, fy;
  1301.   int w2, h2;
  1302.   w2 = w / 2;
  1303.   h2 = h / 2;
  1304.   while (e < s)
  1305.     {
  1306.       e += 360;
  1307.     }
  1308.   for (i = s; (i <= e); i++)
  1309.     {
  1310.       int x, y;
  1311.       x = ((long) gdCosT[i % 360] * (long) w2 / 1024) + cx;
  1312.       y = ((long) gdSinT[i % 360] * (long) h2 / 1024) + cy;
  1313.       if (i != s)
  1314.     {
  1315.       if (!(style & gdChord))
  1316.         {
  1317.           if (style & gdNoFill)
  1318.         {
  1319.           gdImageLine (im, lx, ly, x, y, color);
  1320.         }
  1321.           else
  1322.         {
  1323.           /* This is expensive! */
  1324.           pts[0].x = lx;
  1325.           pts[0].y = ly;
  1326.           pts[1].x = x;
  1327.           pts[1].y = y;
  1328.           pts[2].x = cx;
  1329.           pts[2].y = cy;
  1330.           gdImageFilledPolygon (im, pts, 3, color);
  1331.         }
  1332.         }
  1333.     }
  1334.       else
  1335.     {
  1336.       fx = x;
  1337.       fy = y;
  1338.     }
  1339.       lx = x;
  1340.       ly = y;
  1341.     }
  1342.   if (style & gdChord)
  1343.     {
  1344.       if (style & gdNoFill)
  1345.     {
  1346.       if (style & gdEdged)
  1347.         {
  1348.           gdImageLine (im, cx, cy, lx, ly, color);
  1349.           gdImageLine (im, cx, cy, fx, fy, color);
  1350.         }
  1351.       gdImageLine (im, fx, fy, lx, ly, color);
  1352.     }
  1353.       else
  1354.     {
  1355.       pts[0].x = fx;
  1356.       pts[0].y = fy;
  1357.       pts[1].x = lx;
  1358.       pts[1].y = ly;
  1359.       pts[2].x = cx;
  1360.       pts[2].y = cy;
  1361.       gdImageFilledPolygon (im, pts, 3, color);
  1362.     }
  1363.     }
  1364.   else
  1365.     {
  1366.       if (style & gdNoFill)
  1367.     {
  1368.       if (style & gdEdged)
  1369.         {
  1370.           gdImageLine (im, cx, cy, lx, ly, color);
  1371.           gdImageLine (im, cx, cy, fx, fy, color);
  1372.         }
  1373.     }
  1374.     }
  1375. }
  1376.  
  1377. void 
  1378. gdImageFilledEllipse (gdImagePtr im, int cx, int cy, int w, int h, int color)
  1379. {
  1380.   gdImageFilledArc (im, cx, cy, w, h, 0, 360, color, gdPie);
  1381. }
  1382.  
  1383. void
  1384. gdImageFillToBorder (gdImagePtr im, int x, int y, int border, int color)
  1385. {
  1386.   int lastBorder;
  1387.   /* Seek left */
  1388.   int leftLimit, rightLimit;
  1389.   int i;
  1390.   leftLimit = (-1);
  1391.   if (border < 0)
  1392.     {
  1393.       /* Refuse to fill to a non-solid border */
  1394.       return;
  1395.     }
  1396.   for (i = x; (i >= 0); i--)
  1397.     {
  1398.       if (gdImageGetPixel (im, i, y) == border)
  1399.     {
  1400.       break;
  1401.     }
  1402.       gdImageSetPixel (im, i, y, color);
  1403.       leftLimit = i;
  1404.     }
  1405.   if (leftLimit == (-1))
  1406.     {
  1407.       return;
  1408.     }
  1409.   /* Seek right */
  1410.   rightLimit = x;
  1411.   for (i = (x + 1); (i < im->sx); i++)
  1412.     {
  1413.       if (gdImageGetPixel (im, i, y) == border)
  1414.     {
  1415.       break;
  1416.     }
  1417.       gdImageSetPixel (im, i, y, color);
  1418.       rightLimit = i;
  1419.     }
  1420.   /* Look at lines above and below and start paints */
  1421.   /* Above */
  1422.   if (y > 0)
  1423.     {
  1424.       lastBorder = 1;
  1425.       for (i = leftLimit; (i <= rightLimit); i++)
  1426.     {
  1427.       int c;
  1428.       c = gdImageGetPixel (im, i, y - 1);
  1429.       if (lastBorder)
  1430.         {
  1431.           if ((c != border) && (c != color))
  1432.         {
  1433.           gdImageFillToBorder (im, i, y - 1,
  1434.                        border, color);
  1435.           lastBorder = 0;
  1436.         }
  1437.         }
  1438.       else if ((c == border) || (c == color))
  1439.         {
  1440.           lastBorder = 1;
  1441.         }
  1442.     }
  1443.     }
  1444.   /* Below */
  1445.   if (y < ((im->sy) - 1))
  1446.     {
  1447.       lastBorder = 1;
  1448.       for (i = leftLimit; (i <= rightLimit); i++)
  1449.     {
  1450.       int c;
  1451.       c = gdImageGetPixel (im, i, y + 1);
  1452.       if (lastBorder)
  1453.         {
  1454.           if ((c != border) && (c != color))
  1455.         {
  1456.           gdImageFillToBorder (im, i, y + 1,
  1457.                        border, color);
  1458.           lastBorder = 0;
  1459.         }
  1460.         }
  1461.       else if ((c == border) || (c == color))
  1462.         {
  1463.           lastBorder = 1;
  1464.         }
  1465.     }
  1466.     }
  1467. }
  1468.  
  1469. void
  1470. gdImageFill (gdImagePtr im, int x, int y, int color)
  1471. {
  1472.   int lastBorder;
  1473.   int old;
  1474.   int leftLimit, rightLimit;
  1475.   int i;
  1476.   old = gdImageGetPixel (im, x, y);
  1477.   if (color == gdTiled)
  1478.     {
  1479.       /* Tile fill -- got to watch out! */
  1480.       int p, tileColor;
  1481.       int srcx, srcy;
  1482.       if (!im->tile)
  1483.     {
  1484.       return;
  1485.     }
  1486.       /* Refuse to flood-fill with a transparent pattern --
  1487.          I can't do it without allocating another image */
  1488.       if (gdImageGetTransparent (im->tile) != (-1))
  1489.     {
  1490.       return;
  1491.     }
  1492.       srcx = x % gdImageSX (im->tile);
  1493.       srcy = y % gdImageSY (im->tile);
  1494.       p = gdImageGetPixel (im->tile, srcx, srcy);
  1495.       if (im->trueColor)
  1496.     {
  1497.       tileColor = p;
  1498.     }
  1499.       else
  1500.     {
  1501.       if (im->tile->trueColor)
  1502.         {
  1503.           tileColor = gdImageColorResolveAlpha (im,
  1504.                             gdTrueColorGetRed (p),
  1505.                             gdTrueColorGetGreen (p),
  1506.                             gdTrueColorGetBlue (p),
  1507.                             gdTrueColorGetAlpha (p));
  1508.         }
  1509.       else
  1510.         {
  1511.           tileColor = im->tileColorMap[p];
  1512.         }
  1513.     }
  1514.       if (old == tileColor)
  1515.     {
  1516.       /* Nothing to be done */
  1517.       return;
  1518.     }
  1519.     }
  1520.   else
  1521.     {
  1522.       if (old == color)
  1523.     {
  1524.       /* Nothing to be done */
  1525.       return;
  1526.     }
  1527.     }
  1528.   /* Seek left */
  1529.   leftLimit = (-1);
  1530.   for (i = x; (i >= 0); i--)
  1531.     {
  1532.       if (gdImageGetPixel (im, i, y) != old)
  1533.     {
  1534.       break;
  1535.     }
  1536.       gdImageSetPixel (im, i, y, color);
  1537.       leftLimit = i;
  1538.     }
  1539.   if (leftLimit == (-1))
  1540.     {
  1541.       return;
  1542.     }
  1543.   /* Seek right */
  1544.   rightLimit = x;
  1545.   for (i = (x + 1); (i < im->sx); i++)
  1546.     {
  1547.       if (gdImageGetPixel (im, i, y) != old)
  1548.     {
  1549.       break;
  1550.     }
  1551.       gdImageSetPixel (im, i, y, color);
  1552.       rightLimit = i;
  1553.     }
  1554.   /* Look at lines above and below and start paints */
  1555.   /* Above */
  1556.   if (y > 0)
  1557.     {
  1558.       lastBorder = 1;
  1559.       for (i = leftLimit; (i <= rightLimit); i++)
  1560.     {
  1561.       int c;
  1562.       c = gdImageGetPixel (im, i, y - 1);
  1563.       if (lastBorder)
  1564.         {
  1565.           if (c == old)
  1566.         {
  1567.           gdImageFill (im, i, y - 1, color);
  1568.           lastBorder = 0;
  1569.         }
  1570.         }
  1571.       else if (c != old)
  1572.         {
  1573.           lastBorder = 1;
  1574.         }
  1575.     }
  1576.     }
  1577.   /* Below */
  1578.   if (y < ((im->sy) - 1))
  1579.     {
  1580.       lastBorder = 1;
  1581.       for (i = leftLimit; (i <= rightLimit); i++)
  1582.     {
  1583.       int c;
  1584.       c = gdImageGetPixel (im, i, y + 1);
  1585.       if (lastBorder)
  1586.         {
  1587.           if (c == old)
  1588.         {
  1589.           gdImageFill (im, i, y + 1, color);
  1590.           lastBorder = 0;
  1591.         }
  1592.         }
  1593.       else if (c != old)
  1594.         {
  1595.           lastBorder = 1;
  1596.         }
  1597.     }
  1598.     }
  1599. }
  1600.  
  1601. void
  1602. gdImageRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
  1603. {
  1604.   int x1h = x1, x1v = x1, y1h = y1, y1v = y1, x2h = x2, x2v = x2, y2h = y2,
  1605.     y2v = y2;
  1606.   int thick = im->thick;
  1607.   if (thick > 1)
  1608.     {
  1609.       int half = thick / 2;
  1610.       int half1 = thick - half;
  1611.  
  1612.       if (y1 < y2)
  1613.     {
  1614.       y1v = y1h - half;
  1615.       y2v = y2h + half1 - 1;
  1616.     }
  1617.       else
  1618.     {
  1619.       y1v = y1h + half1 - 1;
  1620.       y2v = y2h - half;
  1621.     }
  1622.     }
  1623.  
  1624.   gdImageLine (im, x1h, y1h, x2h, y1h, color);
  1625.   gdImageLine (im, x1h, y2h, x2h, y2h, color);
  1626.   gdImageLine (im, x1v, y1v, x1v, y2v, color);
  1627.   gdImageLine (im, x2v, y1v, x2v, y2v, color);
  1628. }
  1629.  
  1630. void
  1631. gdImageFilledRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
  1632. {
  1633.   int x, y;
  1634.   for (y = y1; (y <= y2); y++)
  1635.     {
  1636.       for (x = x1; (x <= x2); x++)
  1637.     {
  1638.       gdImageSetPixel (im, x, y, color);
  1639.     }
  1640.     }
  1641. }
  1642.  
  1643. void
  1644. gdImageCopy (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h)
  1645. {
  1646.   int c;
  1647.   int x, y;
  1648.   int tox, toy;
  1649.   int i;
  1650.   int colorMap[gdMaxColors];
  1651.   if (dst->trueColor)
  1652.     {
  1653.       /* 2.0: much easier when the destination is truecolor. */
  1654.       for (y = 0; (y < h); y++)
  1655.     {
  1656.       for (x = 0; (x < w); x++)
  1657.         {
  1658.           int c = gdImageGetTrueColorPixel (src, srcX + x,
  1659.                         srcY + y);
  1660.           if (c != src->transparent)
  1661.         {
  1662.           gdImageSetPixel (dst,
  1663.                    dstX + x,
  1664.                    dstY + y,
  1665.                    c);
  1666.         }
  1667.         }
  1668.     }
  1669.       return;
  1670.     }
  1671.   for (i = 0; (i < gdMaxColors); i++)
  1672.     {
  1673.       colorMap[i] = (-1);
  1674.     }
  1675.   toy = dstY;
  1676.   for (y = srcY; (y < (srcY + h)); y++)
  1677.     {
  1678.       tox = dstX;
  1679.       for (x = srcX; (x < (srcX + w)); x++)
  1680.     {
  1681.       int nc;
  1682.       c = gdImageGetPixel (src, x, y);
  1683.       /* Added 7/24/95: support transparent copies */
  1684.       if (gdImageGetTransparent (src) == c)
  1685.         {
  1686.           tox++;
  1687.           continue;
  1688.         }
  1689.       /* Have we established a mapping for this color? */
  1690.       if (colorMap[c] == (-1))
  1691.         {
  1692.           /* If it's the same image, mapping is trivial */
  1693.           if (dst == src)
  1694.         {
  1695.           nc = c;
  1696.         }
  1697.           else
  1698.         {
  1699.           /* Get best match possible. This
  1700.              function never returns error. */
  1701.           nc = gdImageColorResolveAlpha (
  1702.                           dst,
  1703.                           src->red[c], src->green[c],
  1704.                            src->blue[c], src->alpha[c]);
  1705.         }
  1706.           colorMap[c] = nc;
  1707.         }
  1708.       gdImageSetPixel (dst, tox, toy, colorMap[c]);
  1709.       tox++;
  1710.     }
  1711.       toy++;
  1712.     }
  1713. }
  1714.  
  1715. /* This function is a substitute for real alpha channel operations,
  1716.    so it doesn't pay attention to the alpha channel. */
  1717. void
  1718. gdImageCopyMerge (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h, int pct)
  1719. {
  1720.  
  1721.   int c, dc;
  1722.   int x, y;
  1723.   int tox, toy;
  1724.   int ncR, ncG, ncB;
  1725.   toy = dstY;
  1726.   for (y = srcY; (y < (srcY + h)); y++)
  1727.     {
  1728.       tox = dstX;
  1729.       for (x = srcX; (x < (srcX + w)); x++)
  1730.     {
  1731.       int nc;
  1732.       c = gdImageGetPixel (src, x, y);
  1733.       /* Added 7/24/95: support transparent copies */
  1734.       if (gdImageGetTransparent (src) == c)
  1735.         {
  1736.           tox++;
  1737.           continue;
  1738.         }
  1739.       /* If it's the same image, mapping is trivial */
  1740.       if (dst == src)
  1741.         {
  1742.           nc = c;
  1743.         }
  1744.       else
  1745.         {
  1746.           dc = gdImageGetPixel (dst, tox, toy);
  1747.  
  1748.           ncR = gdImageRed (src, c) * (pct / 100.0)
  1749.         + gdImageRed (dst, dc) * ((100 - pct) / 100.0);
  1750.           ncG = gdImageGreen (src, c) * (pct / 100.0)
  1751.         + gdImageGreen (dst, dc) * ((100 - pct) / 100.0);
  1752.           ncB = gdImageBlue (src, c) * (pct / 100.0)
  1753.         + gdImageBlue (dst, dc) * ((100 - pct) / 100.0);
  1754.  
  1755.           /* Find a reasonable color */
  1756.           nc = gdImageColorResolve (dst, ncR, ncG, ncB);
  1757.         }
  1758.       gdImageSetPixel (dst, tox, toy, nc);
  1759.       tox++;
  1760.     }
  1761.       toy++;
  1762.     }
  1763. }
  1764.  
  1765. /* This function is a substitute for real alpha channel operations,
  1766.    so it doesn't pay attention to the alpha channel. */
  1767. void
  1768. gdImageCopyMergeGray (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int w, int h, int pct)
  1769. {
  1770.  
  1771.   int c, dc;
  1772.   int x, y;
  1773.   int tox, toy;
  1774.   int ncR, ncG, ncB;
  1775.   float g;
  1776.   toy = dstY;
  1777.   for (y = srcY; (y < (srcY + h)); y++)
  1778.     {
  1779.       tox = dstX;
  1780.       for (x = srcX; (x < (srcX + w)); x++)
  1781.     {
  1782.       int nc;
  1783.       c = gdImageGetPixel (src, x, y);
  1784.       /* Added 7/24/95: support transparent copies */
  1785.       if (gdImageGetTransparent (src) == c)
  1786.         {
  1787.           tox++;
  1788.           continue;
  1789.         }
  1790.       /* If it's the same image, mapping is trivial */
  1791.       if (dst == src)
  1792.         {
  1793.           nc = c;
  1794.         }
  1795.       else
  1796.         {
  1797.           dc = gdImageGetPixel (dst, tox, toy);
  1798.           g = 0.29900 * dst->red[dc]
  1799.         + 0.58700 * dst->green[dc]
  1800.         + 0.11400 * dst->blue[dc];
  1801.  
  1802.           ncR = gdImageRed (src, c) * (pct / 100.0)
  1803.         + gdImageRed (dst, dc) * g *
  1804.         ((100 - pct) / 100.0);
  1805.           ncG = gdImageGreen (src, c) * (pct / 100.0)
  1806.         + gdImageGreen (dst, dc) * g *
  1807.         ((100 - pct) / 100.0);
  1808.           ncB = gdImageBlue (src, c) * (pct / 100.0)
  1809.         + gdImageBlue (dst, dc) * g *
  1810.         ((100 - pct) / 100.0);
  1811.  
  1812.           /* First look for an exact match */
  1813.           nc = gdImageColorExact (dst, ncR, ncG, ncB);
  1814.           if (nc == (-1))
  1815.         {
  1816.           /* No, so try to allocate it */
  1817.           nc = gdImageColorAllocate (dst, ncR, ncG, ncB);
  1818.           /* If we're out of colors, go for the
  1819.              closest color */
  1820.           if (nc == (-1))
  1821.             {
  1822.               nc = gdImageColorClosest (dst, ncR, ncG, ncB);
  1823.             }
  1824.         }
  1825.         }
  1826.       gdImageSetPixel (dst, tox, toy, nc);
  1827.       tox++;
  1828.     }
  1829.       toy++;
  1830.     }
  1831. }
  1832.  
  1833. void
  1834. gdImageCopyResized (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX, int srcY, int dstW, int dstH, int srcW, int srcH)
  1835. {
  1836.   int c;
  1837.   int x, y;
  1838.   int tox, toy;
  1839.   int ydest;
  1840.   int i;
  1841.   int colorMap[gdMaxColors];
  1842.   /* Stretch vectors */
  1843.   int *stx;
  1844.   int *sty;
  1845.   /* We only need to use floating point to determine the correct
  1846.      stretch vector for one line's worth. */
  1847.   double accum;
  1848.   stx = (int *) gdMalloc (sizeof (int) * srcW);
  1849.   sty = (int *) gdMalloc (sizeof (int) * srcH);
  1850.   accum = 0;
  1851.   for (i = 0; (i < srcW); i++)
  1852.     {
  1853.       int got;
  1854.       accum += (double) dstW / (double) srcW;
  1855.       got = (int) floor (accum);
  1856.       stx[i] = got;
  1857.       accum -= got;
  1858.     }
  1859.   accum = 0;
  1860.   for (i = 0; (i < srcH); i++)
  1861.     {
  1862.       int got;
  1863.       accum += (double) dstH / (double) srcH;
  1864.       got = (int) floor (accum);
  1865.       sty[i] = got;
  1866.       accum -= got;
  1867.     }
  1868.   for (i = 0; (i < gdMaxColors); i++)
  1869.     {
  1870.       colorMap[i] = (-1);
  1871.     }
  1872.   toy = dstY;
  1873.   for (y = srcY; (y < (srcY + srcH)); y++)
  1874.     {
  1875.       for (ydest = 0; (ydest < sty[y - srcY]); ydest++)
  1876.     {
  1877.       tox = dstX;
  1878.       for (x = srcX; (x < (srcX + srcW)); x++)
  1879.         {
  1880.           int nc;
  1881.           int mapTo;
  1882.           if (!stx[x - srcX])
  1883.         {
  1884.           continue;
  1885.         }
  1886.           if (dst->trueColor)
  1887.         {
  1888.           int d;
  1889.           mapTo = gdImageGetTrueColorPixel (src, x, y);
  1890.           /* Added 7/24/95: support transparent copies */
  1891.           if (gdImageGetTransparent (src) == mapTo)
  1892.             {
  1893.               tox++;
  1894.               continue;
  1895.             }
  1896.         }
  1897.           else
  1898.         {
  1899.           c = gdImageGetPixel (src, x, y);
  1900.           /* Added 7/24/95: support transparent copies */
  1901.           if (gdImageGetTransparent (src) == c)
  1902.             {
  1903.               tox += stx[x - srcX];
  1904.               continue;
  1905.             }
  1906.           if (src->trueColor)
  1907.             {
  1908.               /* Remap to the palette available in the
  1909.                  destination image. This is slow and
  1910.                  works badly. */
  1911.               mapTo = gdImageColorResolveAlpha (dst,
  1912.                               gdTrueColorGetRed (c),
  1913.                             gdTrueColorGetGreen (c),
  1914.                              gdTrueColorGetBlue (c),
  1915.                            gdTrueColorGetAlpha (c));
  1916.             }
  1917.           else
  1918.             {
  1919.               /* Have we established a mapping for this color? */
  1920.               if (colorMap[c] == (-1))
  1921.             {
  1922.               /* If it's the same image, mapping is trivial */
  1923.               if (dst == src)
  1924.                 {
  1925.                   nc = c;
  1926.                 }
  1927.               else
  1928.                 {
  1929.                   /* Find or create the best match */
  1930.                   mapTo = gdImageColorResolveAlpha (dst,
  1931.                               gdTrueColorGetRed (c),
  1932.                             gdTrueColorGetGreen (c),
  1933.                              gdTrueColorGetBlue (c),
  1934.                            gdTrueColorGetAlpha (c));
  1935.                 }
  1936.               colorMap[c] = nc;
  1937.             }
  1938.               mapTo = colorMap[c];
  1939.             }
  1940.         }
  1941.           for (i = 0; (i < stx[x - srcX]); i++)
  1942.         {
  1943.           gdImageSetPixel (dst, tox, toy, mapTo);
  1944.           tox++;
  1945.         }
  1946.         }
  1947.       toy++;
  1948.     }
  1949.     }
  1950.   gdFree (stx);
  1951.   gdFree (sty);
  1952. }
  1953.  
  1954. /* When gd 1.x was first created, floating point was to be avoided.
  1955.    These days it is often faster than table lookups or integer
  1956.    arithmetic. The routine below is shamelessly, gloriously
  1957.    floating point. TBB */
  1958.  
  1959. void
  1960. gdImageCopyResampled (gdImagePtr dst,
  1961.               gdImagePtr src,
  1962.               int dstX, int dstY,
  1963.               int srcX, int srcY,
  1964.               int dstW, int dstH,
  1965.               int srcW, int srcH)
  1966. {
  1967.   int x, y;
  1968.   float sx, sy;
  1969.   if (!dst->trueColor)
  1970.     {
  1971.       gdImageCopyResized (
  1972.                dst, src, dstX, dstY, srcX, srcY, dstW, dstH,
  1973.                srcW, srcH);
  1974.       return;
  1975.     }
  1976.   for (y = dstY; (y < dstY + dstH); y++)
  1977.     {
  1978.       for (x = dstX; (x < dstX + dstW); x++)
  1979.     {
  1980.       int pd = gdImageGetPixel (dst, x, y);
  1981.       float sy1, sy2, sx1, sx2;
  1982.       float sx, sy;
  1983.       float spixels = 0;
  1984.       float red = 0.0, green = 0.0, blue = 0.0, alpha = 0.0;
  1985.       sy1 = ((float) y - (float) dstY) * (float) srcH /
  1986.         (float) dstH;
  1987.       sy2 = ((float) (y + 1) - (float) dstY) * (float) srcH /
  1988.         (float) dstH;
  1989.       sy = sy1;
  1990.       do
  1991.         {
  1992.           float yportion;
  1993.           if (floor (sy) == floor (sy1))
  1994.         {
  1995.           yportion = 1.0 - (sy - floor (sy));
  1996.           if (yportion > sy2 - sy1)
  1997.             {
  1998.               yportion = sy2 - sy1;
  1999.             }
  2000.           sy = floor (sy);
  2001.         }
  2002.           else if (sy == floor (sy2))
  2003.         {
  2004.           yportion = sy2 - floor (sy2);
  2005.         }
  2006.           else
  2007.         {
  2008.           yportion = 1.0;
  2009.         }
  2010.           sx1 = ((float) x - (float) dstX) * (float) srcW /
  2011.         dstW;
  2012.           sx2 = ((float) (x + 1) - (float) dstX) * (float) srcW /
  2013.         dstW;
  2014.           sx = sx1;
  2015.           do
  2016.         {
  2017.           float xportion;
  2018.           float pcontribution;
  2019.           int p;
  2020.           if (floor (sx) == floor (sx1))
  2021.             {
  2022.               xportion = 1.0 - (sx - floor (sx));
  2023.               if (xportion > sx2 - sx1)
  2024.             {
  2025.               xportion = sx2 - sx1;
  2026.             }
  2027.               sx = floor (sx);
  2028.             }
  2029.           else if (sx == floor (sx2))
  2030.             {
  2031.               xportion = sx2 - floor (sx2);
  2032.             }
  2033.           else
  2034.             {
  2035.               xportion = 1.0;
  2036.             }
  2037.           pcontribution = xportion * yportion;
  2038.           p = gdImageGetTrueColorPixel (
  2039.                          src,
  2040.                          (int) sx,
  2041.                          (int) sy);
  2042.           red += gdTrueColorGetRed (p) * pcontribution;
  2043.           green += gdTrueColorGetGreen (p) * pcontribution;
  2044.           blue += gdTrueColorGetBlue (p) * pcontribution;
  2045.           alpha += gdTrueColorGetAlpha (p) * pcontribution;
  2046.           spixels += xportion * yportion;
  2047.           sx += 1.0;
  2048.         }
  2049.           while (sx < sx2);
  2050.           sy += 1.0;
  2051.         }
  2052.       while (sy < sy2);
  2053.       if (spixels != 0.0)
  2054.         {
  2055.           red /= spixels;
  2056.           green /= spixels;
  2057.           blue /= spixels;
  2058.           alpha /= spixels;
  2059.         }
  2060.       /* Clamping to allow for rounding errors above */
  2061.       if (red > 255.0)
  2062.         {
  2063.           red = 255.0;
  2064.         }
  2065.       if (green > 255.0)
  2066.         {
  2067.           green = 255.0;
  2068.         }
  2069.       if (blue > 255.0)
  2070.         {
  2071.           blue = 255.0;
  2072.         }
  2073.       if (alpha > gdAlphaMax)
  2074.         {
  2075.           alpha = gdAlphaMax;
  2076.         }
  2077.       gdImageSetPixel (dst,
  2078.                x, y,
  2079.                gdTrueColorAlpha ((int) red,
  2080.                          (int) green,
  2081.                          (int) blue,
  2082.                          (int) alpha));
  2083.     }
  2084.     }
  2085. }
  2086.  
  2087. gdImagePtr
  2088. gdImageCreateFromXbm (FILE * fd)
  2089. {
  2090.   gdImagePtr im;
  2091.   int bit;
  2092.   int w, h;
  2093.   int bytes;
  2094.   int ch;
  2095.   int i, x, y;
  2096.   char *sp;
  2097.   char s[161];
  2098.   if (!fgets (s, 160, fd))
  2099.     {
  2100.       return 0;
  2101.     }
  2102.   sp = &s[0];
  2103.   /* Skip #define */
  2104.   sp = strchr (sp, ' ');
  2105.   if (!sp)
  2106.     {
  2107.       return 0;
  2108.     }
  2109.   /* Skip width label */
  2110.   sp++;
  2111.   sp = strchr (sp, ' ');
  2112.   if (!sp)
  2113.     {
  2114.       return 0;
  2115.     }
  2116.   /* Get width */
  2117.   w = atoi (sp + 1);
  2118.   if (!w)
  2119.     {
  2120.       return 0;
  2121.     }
  2122.   if (!fgets (s, 160, fd))
  2123.     {
  2124.       return 0;
  2125.     }
  2126.   sp = s;
  2127.   /* Skip #define */
  2128.   sp = strchr (sp, ' ');
  2129.   if (!sp)
  2130.     {
  2131.       return 0;
  2132.     }
  2133.   /* Skip height label */
  2134.   sp++;
  2135.   sp = strchr (sp, ' ');
  2136.   if (!sp)
  2137.     {
  2138.       return 0;
  2139.     }
  2140.   /* Get height */
  2141.   h = atoi (sp + 1);
  2142.   if (!h)
  2143.     {
  2144.       return 0;
  2145.     }
  2146.   /* Skip declaration line */
  2147.   if (!fgets (s, 160, fd))
  2148.     {
  2149.       return 0;
  2150.     }
  2151.   bytes = (w * h / 8) + 1;
  2152.   im = gdImageCreate (w, h);
  2153.   gdImageColorAllocate (im, 255, 255, 255);
  2154.   gdImageColorAllocate (im, 0, 0, 0);
  2155.   x = 0;
  2156.   y = 0;
  2157.   for (i = 0; (i < bytes); i++)
  2158.     {
  2159.       char h[3];
  2160.       int b;
  2161.       /* Skip spaces, commas, CRs, 0x */
  2162.       while (1)
  2163.     {
  2164.       ch = getc (fd);
  2165.       if (ch == EOF)
  2166.         {
  2167.           goto fail;
  2168.         }
  2169.       if (ch == 'x')
  2170.         {
  2171.           break;
  2172.         }
  2173.     }
  2174.       /* Get hex value */
  2175.       ch = getc (fd);
  2176.       if (ch == EOF)
  2177.     {
  2178.       goto fail;
  2179.     }
  2180.       h[0] = ch;
  2181.       ch = getc (fd);
  2182.       if (ch == EOF)
  2183.     {
  2184.       goto fail;
  2185.     }
  2186.       h[1] = ch;
  2187.       h[2] = '\0';
  2188.       sscanf (h, "%x", &b);
  2189.       for (bit = 1; (bit <= 128); (bit = bit << 1))
  2190.     {
  2191.       gdImageSetPixel (im, x++, y, (b & bit) ? 1 : 0);
  2192.       if (x == im->sx)
  2193.         {
  2194.           x = 0;
  2195.           y++;
  2196.           if (y == im->sy)
  2197.         {
  2198.           return im;
  2199.         }
  2200.           /* Fix 8/8/95 */
  2201.           break;
  2202.         }
  2203.     }
  2204.     }
  2205.   /* Shouldn't happen */
  2206.   fprintf (stderr, "Error: bug in gdImageCreateFromXbm!\n");
  2207.   return 0;
  2208. fail:
  2209.   gdImageDestroy (im);
  2210.   return 0;
  2211. }
  2212.  
  2213. void
  2214. gdImagePolygon (gdImagePtr im, gdPointPtr p, int n, int c)
  2215. {
  2216.   int i;
  2217.   int lx, ly;
  2218.   if (!n)
  2219.     {
  2220.       return;
  2221.     }
  2222.   lx = p->x;
  2223.   ly = p->y;
  2224.   gdImageLine (im, lx, ly, p[n - 1].x, p[n - 1].y, c);
  2225.   for (i = 1; (i < n); i++)
  2226.     {
  2227.       p++;
  2228.       gdImageLine (im, lx, ly, p->x, p->y, c);
  2229.       lx = p->x;
  2230.       ly = p->y;
  2231.     }
  2232. }
  2233.  
  2234. int gdCompareInt (const void *a, const void *b);
  2235.  
  2236. /* THANKS to Kirsten Schulz for the polygon fixes! */
  2237.  
  2238. /* The intersection finding technique of this code could be improved  */
  2239. /* by remembering the previous intertersection, and by using the slope. */
  2240. /* That could help to adjust intersections  to produce a nice */
  2241. /* interior_extrema. */
  2242.  
  2243. void
  2244. gdImageFilledPolygon (gdImagePtr im, gdPointPtr p, int n, int c)
  2245. {
  2246.   int i;
  2247.   int y;
  2248.   int miny, maxy;
  2249.   int x1, y1;
  2250.   int x2, y2;
  2251.   int ind1, ind2;
  2252.   int ints;
  2253.   if (!n)
  2254.     {
  2255.       return;
  2256.     }
  2257.   if (!im->polyAllocated)
  2258.     {
  2259.       im->polyInts = (int *) gdMalloc (sizeof (int) * n);
  2260.       im->polyAllocated = n;
  2261.     }
  2262.   if (im->polyAllocated < n)
  2263.     {
  2264.       while (im->polyAllocated < n)
  2265.     {
  2266.       im->polyAllocated *= 2;
  2267.     }
  2268.       im->polyInts = (int *) gdRealloc (im->polyInts,
  2269.                     sizeof (int) * im->polyAllocated);
  2270.     }
  2271.   miny = p[0].y;
  2272.   maxy = p[0].y;
  2273.   for (i = 1; (i < n); i++)
  2274.     {
  2275.       if (p[i].y < miny)
  2276.     {
  2277.       miny = p[i].y;
  2278.     }
  2279.       if (p[i].y > maxy)
  2280.     {
  2281.       maxy = p[i].y;
  2282.     }
  2283.     }
  2284.   /* Fix in 1.3: count a vertex only once */
  2285.   for (y = miny; (y <= maxy); y++)
  2286.     {
  2287. /*1.4           int interLast = 0; */
  2288. /*              int dirLast = 0; */
  2289. /*              int interFirst = 1; */
  2290.       ints = 0;
  2291.       for (i = 0; (i < n); i++)
  2292.     {
  2293.       if (!i)
  2294.         {
  2295.           ind1 = n - 1;
  2296.           ind2 = 0;
  2297.         }
  2298.       else
  2299.         {
  2300.           ind1 = i - 1;
  2301.           ind2 = i;
  2302.         }
  2303.       y1 = p[ind1].y;
  2304.       y2 = p[ind2].y;
  2305.       if (y1 < y2)
  2306.         {
  2307.           x1 = p[ind1].x;
  2308.           x2 = p[ind2].x;
  2309.         }
  2310.       else if (y1 > y2)
  2311.         {
  2312.           y2 = p[ind1].y;
  2313.           y1 = p[ind2].y;
  2314.           x2 = p[ind1].x;
  2315.           x1 = p[ind2].x;
  2316.         }
  2317.       else
  2318.         {
  2319.           continue;
  2320.         }
  2321.       if ((y >= y1) && (y < y2))
  2322.         {
  2323.           im->polyInts[ints++] = (y - y1) * (x2 - x1) / (y2 - y1) + x1;
  2324.         }
  2325.       else if ((y == maxy) && (y > y1) && (y <= y2))
  2326.         {
  2327.           im->polyInts[ints++] = (y - y1) * (x2 - x1) / (y2 - y1) + x1;
  2328.         }
  2329.     }
  2330.       qsort (im->polyInts, ints, sizeof (int), gdCompareInt);
  2331.  
  2332.       for (i = 0; (i < (ints)); i += 2)
  2333.     {
  2334.       gdImageLine (im, im->polyInts[i], y,
  2335.                im->polyInts[i + 1], y, c);
  2336.     }
  2337.     }
  2338. }
  2339.  
  2340. int
  2341. gdCompareInt (const void *a, const void *b)
  2342. {
  2343.   return (*(const int *) a) - (*(const int *) b);
  2344. }
  2345.  
  2346. void
  2347. gdImageSetStyle (gdImagePtr im, int *style, int noOfPixels)
  2348. {
  2349.   if (im->style)
  2350.     {
  2351.       gdFree (im->style);
  2352.     }
  2353.   im->style = (int *)
  2354.     gdMalloc (sizeof (int) * noOfPixels);
  2355.   memcpy (im->style, style, sizeof (int) * noOfPixels);
  2356.   im->styleLength = noOfPixels;
  2357.   im->stylePos = 0;
  2358. }
  2359.  
  2360. void
  2361. gdImageSetThickness (gdImagePtr im, int thickness)
  2362. {
  2363.   im->thick = thickness;
  2364. }
  2365.  
  2366. void
  2367. gdImageSetBrush (gdImagePtr im, gdImagePtr brush)
  2368. {
  2369.   int i;
  2370.   im->brush = brush;
  2371.   if ((!im->trueColor) && (!im->brush->trueColor))
  2372.     {
  2373.       for (i = 0; (i < gdImageColorsTotal (brush)); i++)
  2374.     {
  2375.       int index;
  2376.       index = gdImageColorResolveAlpha (im,
  2377.                         gdImageRed (brush, i),
  2378.                         gdImageGreen (brush, i),
  2379.                         gdImageBlue (brush, i),
  2380.                         gdImageAlpha (brush, i));
  2381.       im->brushColorMap[i] = index;
  2382.     }
  2383.     }
  2384. }
  2385.  
  2386. void
  2387. gdImageSetTile (gdImagePtr im, gdImagePtr tile)
  2388. {
  2389.   int i;
  2390.   im->tile = tile;
  2391.   if ((!im->trueColor) && (!im->tile->trueColor))
  2392.     {
  2393.       for (i = 0; (i < gdImageColorsTotal (tile)); i++)
  2394.     {
  2395.       int index;
  2396.       index = gdImageColorResolveAlpha (im,
  2397.                         gdImageRed (tile, i),
  2398.                         gdImageGreen (tile, i),
  2399.                         gdImageBlue (tile, i),
  2400.                         gdImageAlpha (tile, i));
  2401.       im->tileColorMap[i] = index;
  2402.     }
  2403.     }
  2404. }
  2405.  
  2406. void
  2407. gdImageInterlace (gdImagePtr im, int interlaceArg)
  2408. {
  2409.   im->interlace = interlaceArg;
  2410. }
  2411.  
  2412. int
  2413. gdImageCompare (gdImagePtr im1, gdImagePtr im2)
  2414. {
  2415.   int x, y;
  2416.   int p1, p2;
  2417.   int cmpStatus = 0;
  2418.   int sx, sy;
  2419.  
  2420.   if (im1->interlace != im2->interlace)
  2421.     {
  2422.       cmpStatus |= GD_CMP_INTERLACE;
  2423.     }
  2424.  
  2425.   if (im1->transparent != im2->transparent)
  2426.     {
  2427.       cmpStatus |= GD_CMP_TRANSPARENT;
  2428.     }
  2429.  
  2430.   if (im1->trueColor != im2->trueColor)
  2431.     {
  2432.       cmpStatus |= GD_CMP_TRUECOLOR;
  2433.     }
  2434.  
  2435.   sx = im1->sx;
  2436.   if (im1->sx != im2->sx)
  2437.     {
  2438.       cmpStatus |= GD_CMP_SIZE_X + GD_CMP_IMAGE;
  2439.       if (im2->sx < im1->sx)
  2440.     {
  2441.       sx = im2->sx;
  2442.     }
  2443.     }
  2444.  
  2445.   sy = im1->sy;
  2446.   if (im1->sy != im2->sy)
  2447.     {
  2448.       cmpStatus |= GD_CMP_SIZE_Y + GD_CMP_IMAGE;
  2449.       if (im2->sy < im1->sy)
  2450.     {
  2451.       sy = im2->sy;
  2452.     }
  2453.     }
  2454.  
  2455.   if (im1->colorsTotal != im2->colorsTotal)
  2456.     {
  2457.       cmpStatus |= GD_CMP_NUM_COLORS;
  2458.     }
  2459.  
  2460.   for (y = 0; (y < sy); y++)
  2461.     {
  2462.       for (x = 0; (x < sx); x++)
  2463.     {
  2464.       p1 = im1->pixels[y][x];
  2465.       p2 = im2->pixels[y][x];
  2466.       if (gdImageRed (im1, p1) != gdImageRed (im2, p2))
  2467.         {
  2468.           cmpStatus |= GD_CMP_COLOR + GD_CMP_IMAGE;
  2469.           break;
  2470.         }
  2471.       if (gdImageGreen (im1, p1) != gdImageGreen (im2, p2))
  2472.         {
  2473.           cmpStatus |= GD_CMP_COLOR + GD_CMP_IMAGE;
  2474.           break;
  2475.         }
  2476.       if (gdImageBlue (im1, p1) != gdImageBlue (im2, p2))
  2477.         {
  2478.           cmpStatus |= GD_CMP_COLOR + GD_CMP_IMAGE;
  2479.           break;
  2480.         }
  2481. #if 0
  2482.       /* Soon we'll add alpha channel to palettes */
  2483.       if (gdImageAlpha (im1, p1) != gdImageAlpha (im2, p2))
  2484.         {
  2485.           cmpStatus |= GD_CMP_COLOR + GD_CMP_IMAGE;
  2486.           break;
  2487.         }
  2488. #endif
  2489.     }
  2490.       if (cmpStatus & GD_CMP_COLOR)
  2491.     {
  2492.       break;
  2493.     };
  2494.     }
  2495.  
  2496.   return cmpStatus;
  2497. }
  2498.  
  2499. int
  2500. gdAlphaBlend (int dst, int src)
  2501. {
  2502.   return (((((gdAlphaTransparent - gdTrueColorGetAlpha (src)) *
  2503.          gdTrueColorGetRed (src) / gdAlphaMax) +
  2504.         (gdTrueColorGetAlpha (src) *
  2505.          gdTrueColorGetRed (dst)) / gdAlphaMax) << 16) +
  2506.       ((((gdAlphaTransparent - gdTrueColorGetAlpha (src)) *
  2507.          gdTrueColorGetGreen (src) / gdAlphaMax) +
  2508.         (gdTrueColorGetAlpha (src) *
  2509.          gdTrueColorGetGreen (dst)) / gdAlphaMax) << 8) +
  2510.       (((gdAlphaTransparent - gdTrueColorGetAlpha (src)) *
  2511.         gdTrueColorGetBlue (src) / gdAlphaMax) +
  2512.        (gdTrueColorGetAlpha (src) *
  2513.         gdTrueColorGetBlue (dst)) / gdAlphaMax));
  2514. }
  2515.  
  2516. void
  2517. gdImageAlphaBlending (gdImagePtr im, int alphaBlendingArg)
  2518. {
  2519.   im->alphaBlendingFlag = alphaBlendingArg;
  2520. }
  2521.  
  2522. void
  2523. gdImageSaveAlpha (gdImagePtr im, int saveAlphaArg)
  2524. {
  2525.   im->saveAlphaFlag = saveAlphaArg;
  2526. }
  2527.