"Fossies" - the Fresh Open Source Software Archive

Member "libgd-2.3.2/src/gd.c" (3 Mar 2021, 106789 Bytes) of package /linux/www/libgd-2.3.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "gd.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.3.1_vs_2.3.2.

    1 #include <stdio.h>
    2 #include <math.h>
    3 #include <string.h>
    4 #include <stdlib.h>
    5 #include <stdarg.h>
    6 
    7 #ifdef HAVE_CONFIG_H
    8 #include "config.h"
    9 #endif
   10 
   11 #include "gd_intern.h"
   12 
   13 /* 2.03: don't include zlib here or we can't build without PNG */
   14 #include "gd.h"
   15 #include "gdhelpers.h"
   16 #include "gd_color.h"
   17 #include "gd_errors.h"
   18 
   19 /* 2.0.12: this now checks the clipping rectangle */
   20 #define gdImageBoundsSafeMacro(im, x, y) (!((((y) < (im)->cy1) || ((y) > (im)->cy2)) || (((x) < (im)->cx1) || ((x) > (im)->cx2))))
   21 
   22 #ifdef _OSD_POSIX       /* BS2000 uses the EBCDIC char set instead of ASCII */
   23 #define CHARSET_EBCDIC
   24 #define __attribute__(any)  /*nothing */
   25 #endif
   26 /*_OSD_POSIX*/
   27 
   28 #ifndef CHARSET_EBCDIC
   29 #define ASC(ch)  ch
   30 #else /*CHARSET_EBCDIC */
   31 #define ASC(ch) gd_toascii[(unsigned char)ch]
   32 static const unsigned char gd_toascii[256] = {
   33     /*00 */ 0x00, 0x01, 0x02, 0x03, 0x85, 0x09, 0x86, 0x7f,
   34     0x87, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /*................ */
   35     /*10 */ 0x10, 0x11, 0x12, 0x13, 0x8f, 0x0a, 0x08, 0x97,
   36     0x18, 0x19, 0x9c, 0x9d, 0x1c, 0x1d, 0x1e, 0x1f, /*................ */
   37     /*20 */ 0x80, 0x81, 0x82, 0x83, 0x84, 0x92, 0x17, 0x1b,
   38     0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07, /*................ */
   39     /*30 */ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04,
   40     0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a, /*................ */
   41     /*40 */ 0x20, 0xa0, 0xe2, 0xe4, 0xe0, 0xe1, 0xe3, 0xe5,
   42     0xe7, 0xf1, 0x60, 0x2e, 0x3c, 0x28, 0x2b, 0x7c, /* .........`.<(+| */
   43     /*50 */ 0x26, 0xe9, 0xea, 0xeb, 0xe8, 0xed, 0xee, 0xef,
   44     0xec, 0xdf, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x9f, /*&.........!$*);. */
   45     /*60 */ 0x2d, 0x2f, 0xc2, 0xc4, 0xc0, 0xc1, 0xc3, 0xc5,
   46     0xc7, 0xd1, 0x5e, 0x2c, 0x25, 0x5f, 0x3e, 0x3f,
   47     /*-/........^,%_>?*/
   48     /*70 */ 0xf8, 0xc9, 0xca, 0xcb, 0xc8, 0xcd, 0xce, 0xcf,
   49     0xcc, 0xa8, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22, /*..........:#@'=" */
   50     /*80 */ 0xd8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
   51     0x68, 0x69, 0xab, 0xbb, 0xf0, 0xfd, 0xfe, 0xb1, /*.abcdefghi...... */
   52     /*90 */ 0xb0, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70,
   53     0x71, 0x72, 0xaa, 0xba, 0xe6, 0xb8, 0xc6, 0xa4, /*.jklmnopqr...... */
   54     /*a0 */ 0xb5, 0xaf, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
   55     0x79, 0x7a, 0xa1, 0xbf, 0xd0, 0xdd, 0xde, 0xae, /*..stuvwxyz...... */
   56     /*b0 */ 0xa2, 0xa3, 0xa5, 0xb7, 0xa9, 0xa7, 0xb6, 0xbc,
   57     0xbd, 0xbe, 0xac, 0x5b, 0x5c, 0x5d, 0xb4, 0xd7, /*...........[\].. */
   58     /*c0 */ 0xf9, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
   59     0x48, 0x49, 0xad, 0xf4, 0xf6, 0xf2, 0xf3, 0xf5, /*.ABCDEFGHI...... */
   60     /*d0 */ 0xa6, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50,
   61     0x51, 0x52, 0xb9, 0xfb, 0xfc, 0xdb, 0xfa, 0xff, /*.JKLMNOPQR...... */
   62     /*e0 */ 0xd9, 0xf7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
   63     0x59, 0x5a, 0xb2, 0xd4, 0xd6, 0xd2, 0xd3, 0xd5, /*..STUVWXYZ...... */
   64     /*f0 */ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
   65     0x38, 0x39, 0xb3, 0x7b, 0xdc, 0x7d, 0xda, 0x7e  /*0123456789.{.}.~ */
   66 };
   67 #endif /*CHARSET_EBCDIC */
   68 
   69 extern const int gdCosT[];
   70 extern const int gdSinT[];
   71 
   72 /**
   73  * Group: Error Handling
   74  */
   75 
   76 void gd_stderr_error(int priority, const char *format, va_list args)
   77 {
   78     switch (priority) {
   79     case GD_ERROR:
   80         fputs("GD Error: ", stderr);
   81         break;
   82     case GD_WARNING:
   83         fputs("GD Warning: ", stderr);
   84         break;
   85     case GD_NOTICE:
   86         fputs("GD Notice: ", stderr);
   87         break;
   88     case GD_INFO:
   89         fputs("GD Info: ", stderr);
   90         break;
   91     case GD_DEBUG:
   92         fputs("GD Debug: ", stderr);
   93         break;
   94     }
   95     vfprintf(stderr, format, args);
   96     fflush(stderr);
   97 }
   98 
   99 static gdErrorMethod gd_error_method = gd_stderr_error;
  100 
  101 static void _gd_error_ex(int priority, const char *format, va_list args)
  102 {
  103     if (gd_error_method) {
  104         gd_error_method(priority, format, args);
  105     }
  106 }
  107 
  108 void gd_error(const char *format, ...)
  109 {
  110     va_list args;
  111 
  112     va_start(args, format);
  113     _gd_error_ex(GD_WARNING, format, args);
  114     va_end(args);
  115 }
  116 void gd_error_ex(int priority, const char *format, ...)
  117 {
  118     va_list args;
  119 
  120     va_start(args, format);
  121     _gd_error_ex(priority, format, args);
  122     va_end(args);
  123 }
  124 
  125 /*
  126     Function: gdSetErrorMethod
  127 */
  128 BGD_DECLARE(void) gdSetErrorMethod(gdErrorMethod error_method)
  129 {
  130     gd_error_method = error_method;
  131 }
  132 
  133 /*
  134     Function: gdClearErrorMethod
  135 */
  136 BGD_DECLARE(void) gdClearErrorMethod(void)
  137 {
  138     gd_error_method = gd_stderr_error;
  139 }
  140 
  141 static void gdImageBrushApply (gdImagePtr im, int x, int y);
  142 static void gdImageTileApply (gdImagePtr im, int x, int y);
  143 
  144 BGD_DECLARE(int) gdImageGetTrueColorPixel (gdImagePtr im, int x, int y);
  145 
  146 /**
  147  * Group: Creation and Destruction
  148  */
  149 
  150 /*
  151     Function: gdImageCreate
  152 
  153       gdImageCreate is called to create palette-based images, with no
  154       more than 256 colors. The image must eventually be destroyed using
  155       gdImageDestroy().
  156 
  157     Parameters:
  158 
  159         sx - The image width.
  160         sy - The image height.
  161 
  162     Returns:
  163 
  164         A pointer to the new image or NULL if an error occurred.
  165 
  166     Example:
  167       (start code)
  168 
  169       gdImagePtr im;
  170       im = gdImageCreate(64, 64);
  171       // ... Use the image ...
  172       gdImageDestroy(im);
  173 
  174       (end code)
  175 
  176     See Also:
  177 
  178         <gdImageCreateTrueColor>
  179 
  180  */
  181 BGD_DECLARE(gdImagePtr) gdImageCreate (int sx, int sy)
  182 {
  183     int i;
  184     gdImagePtr im;
  185 
  186     if (overflow2(sx, sy)) {
  187         return NULL;
  188     }
  189 
  190     if (overflow2(sizeof (unsigned char *), sy)) {
  191         return NULL;
  192     }
  193     if (overflow2(sizeof (unsigned char), sx)) {
  194         return NULL;
  195     }
  196 
  197     im = (gdImage *) gdCalloc(1, sizeof(gdImage));
  198     if (!im) {
  199         return NULL;
  200     }
  201 
  202     /* Row-major ever since gd 1.3 */
  203     im->pixels = (unsigned char **) gdMalloc (sizeof (unsigned char *) * sy);
  204     if (!im->pixels) {
  205         gdFree(im);
  206         return NULL;
  207     }
  208 
  209     im->polyInts = 0;
  210     im->polyAllocated = 0;
  211     im->brush = 0;
  212     im->tile = 0;
  213     im->style = 0;
  214     for (i = 0; (i < sy); i++) {
  215         /* Row-major ever since gd 1.3 */
  216         im->pixels[i] = (unsigned char *) gdCalloc (sx, sizeof (unsigned char));
  217         if (!im->pixels[i]) {
  218             for (--i ; i >= 0; i--) {
  219                 gdFree(im->pixels[i]);
  220             }
  221             gdFree(im->pixels);
  222             gdFree(im);
  223             return NULL;
  224         }
  225 
  226     }
  227     im->sx = sx;
  228     im->sy = sy;
  229     im->colorsTotal = 0;
  230     im->transparent = (-1);
  231     im->interlace = 0;
  232     im->thick = 1;
  233     im->AA = 0;
  234     for (i = 0; (i < gdMaxColors); i++) {
  235         im->open[i] = 1;
  236     };
  237     im->trueColor = 0;
  238     im->tpixels = 0;
  239     im->cx1 = 0;
  240     im->cy1 = 0;
  241     im->cx2 = im->sx - 1;
  242     im->cy2 = im->sy - 1;
  243     im->res_x = GD_RESOLUTION;
  244     im->res_y = GD_RESOLUTION;
  245     im->interpolation = NULL;
  246     im->interpolation_id = GD_BILINEAR_FIXED;
  247     return im;
  248 }
  249 
  250 
  251 
  252 /*
  253     Function: gdImageCreateTrueColor
  254 
  255       <gdImageCreateTrueColor> is called to create truecolor images,
  256       with an essentially unlimited number of colors. Invoke
  257       <gdImageCreateTrueColor> with the x and y dimensions of the
  258       desired image. <gdImageCreateTrueColor> returns a <gdImagePtr>
  259       to the new image, or NULL if unable to allocate the image. The
  260       image must eventually be destroyed using <gdImageDestroy>().
  261 
  262       Truecolor images are always filled with black at creation
  263       time. There is no concept of a "background" color index.
  264 
  265     Parameters:
  266 
  267         sx - The image width.
  268         sy - The image height.
  269 
  270     Returns:
  271 
  272         A pointer to the new image or NULL if an error occurred.
  273 
  274     Example:
  275       (start code)
  276 
  277       gdImagePtr im;
  278       im = gdImageCreateTrueColor(64, 64);
  279       // ... Use the image ...
  280       gdImageDestroy(im);
  281 
  282       (end code)
  283 
  284     See Also:
  285 
  286         <gdImageCreateTrueColor>
  287 
  288 */
  289 BGD_DECLARE(gdImagePtr) gdImageCreateTrueColor (int sx, int sy)
  290 {
  291     int i;
  292     gdImagePtr im;
  293 
  294     if (overflow2(sx, sy)) {
  295         return NULL;
  296     }
  297     if (overflow2(sizeof (int *), sy)) {
  298         return 0;
  299     }
  300     if (overflow2(sizeof(int), sx)) {
  301         return NULL;
  302     }
  303 
  304     im = (gdImage *) gdMalloc (sizeof (gdImage));
  305     if (!im) {
  306         return 0;
  307     }
  308     memset (im, 0, sizeof (gdImage));
  309 
  310     im->tpixels = (int **) gdMalloc (sizeof (int *) * sy);
  311     if (!im->tpixels) {
  312         gdFree(im);
  313         return 0;
  314     }
  315     im->polyInts = 0;
  316     im->polyAllocated = 0;
  317     im->brush = 0;
  318     im->tile = 0;
  319     im->style = 0;
  320     for (i = 0; (i < sy); i++) {
  321         im->tpixels[i] = (int *) gdCalloc (sx, sizeof (int));
  322         if (!im->tpixels[i]) {
  323             /* 2.0.34 */
  324             i--;
  325             while (i >= 0) {
  326                 gdFree(im->tpixels[i]);
  327                 i--;
  328             }
  329             gdFree(im->tpixels);
  330             gdFree(im);
  331             return 0;
  332         }
  333     }
  334     im->sx = sx;
  335     im->sy = sy;
  336     im->transparent = (-1);
  337     im->interlace = 0;
  338     im->trueColor = 1;
  339     /* 2.0.2: alpha blending is now on by default, and saving of alpha is
  340        off by default. This allows font antialiasing to work as expected
  341        on the first try in JPEGs -- quite important -- and also allows
  342        for smaller PNGs when saving of alpha channel is not really
  343        desired, which it usually isn't! */
  344     im->saveAlphaFlag = 0;
  345     im->alphaBlendingFlag = 1;
  346     im->thick = 1;
  347     im->AA = 0;
  348     im->cx1 = 0;
  349     im->cy1 = 0;
  350     im->cx2 = im->sx - 1;
  351     im->cy2 = im->sy - 1;
  352     im->res_x = GD_RESOLUTION;
  353     im->res_y = GD_RESOLUTION;
  354     im->interpolation = NULL;
  355     im->interpolation_id = GD_BILINEAR_FIXED;
  356     return im;
  357 }
  358 
  359 /*
  360   Function: gdImageDestroy
  361 
  362     <gdImageDestroy> is used to free the memory associated with an
  363     image. It is important to invoke <gdImageDestroy> before exiting
  364     your program or assigning a new image to a <gdImagePtr> variable.
  365 
  366   Parameters:
  367 
  368     im  - Pointer to the gdImage to delete.
  369 
  370   Returns:
  371 
  372     Nothing.
  373 
  374   Example:
  375     (start code)
  376 
  377     gdImagePtr im;
  378     im = gdImageCreate(10, 10);
  379     // ... Use the image ...
  380     // Now destroy it
  381     gdImageDestroy(im);
  382 
  383     (end code)
  384 
  385 */
  386 
  387 BGD_DECLARE(void) gdImageDestroy (gdImagePtr im)
  388 {
  389     int i;
  390     if (im->pixels) {
  391         for (i = 0; (i < im->sy); i++) {
  392             gdFree (im->pixels[i]);
  393         }
  394         gdFree (im->pixels);
  395     }
  396     if (im->tpixels) {
  397         for (i = 0; (i < im->sy); i++) {
  398             gdFree (im->tpixels[i]);
  399         }
  400         gdFree (im->tpixels);
  401     }
  402     if (im->polyInts) {
  403         gdFree (im->polyInts);
  404     }
  405     if (im->style) {
  406         gdFree (im->style);
  407     }
  408     gdFree (im);
  409 }
  410 
  411 /**
  412  * Group: Color
  413  */
  414 
  415 /**
  416  * Function: gdImageColorClosest
  417  *
  418  * Gets the closest color of the image
  419  *
  420  * This is a simplified variant of <gdImageColorClosestAlpha> where the alpha
  421  * channel is always opaque.
  422  *
  423  * Parameters:
  424  *   im - The image.
  425  *   r  - The value of the red component.
  426  *   g  - The value of the green component.
  427  *   b  - The value of the blue component.
  428  *
  429  * Returns:
  430  *   The closest color already available in the palette for palette images;
  431  *   the color value of the given components for truecolor images.
  432  *
  433  * See also:
  434  *   - <gdImageColorExact>
  435  */
  436 BGD_DECLARE(int) gdImageColorClosest (gdImagePtr im, int r, int g, int b)
  437 {
  438     return gdImageColorClosestAlpha (im, r, g, b, gdAlphaOpaque);
  439 }
  440 
  441 /**
  442  * Function: gdImageColorClosestAlpha
  443  *
  444  * Gets the closest color of the image
  445  *
  446  * Parameters:
  447  *   im - The image.
  448  *   r  - The value of the red component.
  449  *   g  - The value of the green component.
  450  *   b  - The value of the blue component.
  451  *   a  - The value of the alpha component.
  452  *
  453  * Returns:
  454  *   The closest color already available in the palette for palette images;
  455  *   the color value of the given components for truecolor images.
  456  *
  457  * See also:
  458  *   - <gdImageColorExactAlpha>
  459  */
  460 BGD_DECLARE(int) gdImageColorClosestAlpha (gdImagePtr im, int r, int g, int b, int a)
  461 {
  462     int i;
  463     long rd, gd, bd, ad;
  464     int ct = (-1);
  465     int first = 1;
  466     long mindist = 0;
  467     if (im->trueColor) {
  468         return gdTrueColorAlpha (r, g, b, a);
  469     }
  470     for (i = 0; (i < (im->colorsTotal)); i++) {
  471         long dist;
  472         if (im->open[i]) {
  473             continue;
  474         }
  475         rd = (im->red[i] - r);
  476         gd = (im->green[i] - g);
  477         bd = (im->blue[i] - b);
  478         /* gd 2.02: whoops, was - b (thanks to David Marwood) */
  479         /* gd 2.16: was blue rather than alpha! Geez! Thanks to
  480            Artur Jakub Jerzak */
  481         ad = (im->alpha[i] - a);
  482         dist = rd * rd + gd * gd + bd * bd + ad * ad;
  483         if (first || (dist < mindist)) {
  484             mindist = dist;
  485             ct = i;
  486             first = 0;
  487         }
  488     }
  489     return ct;
  490 }
  491 
  492 /* This code is taken from http://www.acm.org/jgt/papers/SmithLyons96/hwb_rgb.html, an article
  493  * on colour conversion to/from RBG and HWB colour systems.
  494  * It has been modified to return the converted value as a * parameter.
  495  */
  496 
  497 #define RETURN_HWB(h, w, b) {HWB->H = h; HWB->W = w; HWB->B = b; return HWB;}
  498 #define RETURN_RGB(r, g, b) {RGB->R = r; RGB->G = g; RGB->B = b; return RGB;}
  499 #define HWB_UNDEFINED -1
  500 #define SETUP_RGB(s, r, g, b) {s.R = r/255.0; s.G = g/255.0; s.B = b/255.0;}
  501 
  502 /*
  503  * Theoretically, hue 0 (pure red) is identical to hue 6 in these transforms. Pure
  504  * red always maps to 6 in this implementation. Therefore UNDEFINED can be
  505  * defined as 0 in situations where only unsigned numbers are desired.
  506  */
  507 typedef struct {
  508     float R, G, B;
  509 }
  510 RGBType;
  511 typedef struct {
  512     float H, W, B;
  513 }
  514 HWBType;
  515 
  516 static HWBType *
  517 RGB_to_HWB (RGBType RGB, HWBType * HWB)
  518 {
  519 
  520     /*
  521      * RGB are each on [0, 1]. W and B are returned on [0, 1] and H is
  522      * returned on [0, 6]. Exception: H is returned UNDEFINED if W == 1 - B.
  523      */
  524 
  525     float R = RGB.R, G = RGB.G, B = RGB.B, w, v, b, f;
  526     int i;
  527 
  528     w = MIN3 (R, G, B);
  529     v = MAX3 (R, G, B);
  530     b = 1 - v;
  531     if (v == w)
  532         RETURN_HWB (HWB_UNDEFINED, w, b);
  533     f = (R == w) ? G - B : ((G == w) ? B - R : R - G);
  534     i = (R == w) ? 3 : ((G == w) ? 5 : 1);
  535     RETURN_HWB (i - f / (v - w), w, b);
  536 
  537 }
  538 
  539 static float
  540 HWB_Diff (int r1, int g1, int b1, int r2, int g2, int b2)
  541 {
  542     RGBType RGB1, RGB2;
  543     HWBType HWB1, HWB2;
  544     float diff;
  545 
  546     SETUP_RGB (RGB1, r1, g1, b1);
  547     SETUP_RGB (RGB2, r2, g2, b2);
  548 
  549     RGB_to_HWB (RGB1, &HWB1);
  550     RGB_to_HWB (RGB2, &HWB2);
  551 
  552     /*
  553      * I made this bit up; it seems to produce OK results, and it is certainly
  554      * more visually correct than the current RGB metric. (PJW)
  555      */
  556 
  557     if ((HWB1.H == HWB_UNDEFINED) || (HWB2.H == HWB_UNDEFINED)) {
  558         diff = 0;           /* Undefined hues always match... */
  559     } else {
  560         diff = fabs (HWB1.H - HWB2.H);
  561         if (diff > 3) {
  562             diff = 6 - diff;    /* Remember, it's a colour circle */
  563         }
  564     }
  565 
  566     diff =
  567         diff * diff + (HWB1.W - HWB2.W) * (HWB1.W - HWB2.W) + (HWB1.B -
  568                 HWB2.B) * (HWB1.B -
  569                            HWB2.B);
  570 
  571     return diff;
  572 }
  573 
  574 
  575 #if 0
  576 /*
  577  * This is not actually used, but is here for completeness, in case someone wants to
  578  * use the HWB stuff for anything else...
  579  */
  580 static RGBType *
  581 HWB_to_RGB (HWBType HWB, RGBType * RGB)
  582 {
  583 
  584     /*
  585      * H is given on [0, 6] or UNDEFINED. W and B are given on [0, 1].
  586      * RGB are each returned on [0, 1].
  587      */
  588 
  589     float h = HWB.H, w = HWB.W, b = HWB.B, v, n, f;
  590     int i;
  591 
  592     v = 1 - b;
  593     if (h == HWB_UNDEFINED)
  594         RETURN_RGB (v, v, v);
  595     i = floor (h);
  596     f = h - i;
  597     if (i & 1)
  598         f = 1 - f;          /* if i is odd */
  599     n = w + f * (v - w);        /* linear interpolation between w and v */
  600     switch (i) {
  601     case 6:
  602     case 0:
  603         RETURN_RGB (v, n, w);
  604     case 1:
  605         RETURN_RGB (n, v, w);
  606     case 2:
  607         RETURN_RGB (w, v, n);
  608     case 3:
  609         RETURN_RGB (w, n, v);
  610     case 4:
  611         RETURN_RGB (n, w, v);
  612     case 5:
  613         RETURN_RGB (v, w, n);
  614     }
  615 
  616     return RGB;
  617 
  618 }
  619 #endif
  620 
  621 /*
  622     Function: gdImageColorClosestHWB
  623 */
  624 BGD_DECLARE(int) gdImageColorClosestHWB (gdImagePtr im, int r, int g, int b)
  625 {
  626     int i;
  627     /* long rd, gd, bd; */
  628     int ct = (-1);
  629     int first = 1;
  630     float mindist = 0;
  631     if (im->trueColor) {
  632         return gdTrueColor (r, g, b);
  633     }
  634     for (i = 0; (i < (im->colorsTotal)); i++) {
  635         float dist;
  636         if (im->open[i]) {
  637             continue;
  638         }
  639         dist = HWB_Diff (im->red[i], im->green[i], im->blue[i], r, g, b);
  640         if (first || (dist < mindist)) {
  641             mindist = dist;
  642             ct = i;
  643             first = 0;
  644         }
  645     }
  646     return ct;
  647 }
  648 
  649 /**
  650  * Function: gdImageColorExact
  651  *
  652  * Gets the exact color of the image
  653  *
  654  * This is a simplified variant of <gdImageColorExactAlpha> where the alpha
  655  * channel is always opaque.
  656  *
  657  * Parameters:
  658  *   im - The image.
  659  *   r  - The value of the red component.
  660  *   g  - The value of the green component.
  661  *   b  - The value of the blue component.
  662  *
  663  * Returns:
  664  *   The exact color already available in the palette for palette images; if
  665  *   there is no exact color, -1 is returned.
  666  *   For truecolor images the color value of the given components is returned.
  667  *
  668  * See also:
  669  *   - <gdImageColorClosest>
  670  */
  671 BGD_DECLARE(int) gdImageColorExact (gdImagePtr im, int r, int g, int b)
  672 {
  673     return gdImageColorExactAlpha (im, r, g, b, gdAlphaOpaque);
  674 }
  675 
  676 /**
  677  * Function: gdImageColorExactAlpha
  678  *
  679  * Gets the exact color of the image
  680  *
  681  * Parameters:
  682  *   im - The image.
  683  *   r  - The value of the red component.
  684  *   g  - The value of the green component.
  685  *   b  - The value of the blue component.
  686  *   a  - The value of the alpha component.
  687  *
  688  * Returns:
  689  *   The exact color already available in the palette for palette images; if
  690  *   there is no exact color, -1 is returned.
  691  *   For truecolor images the color value of the given components is returned.
  692  *
  693  * See also:
  694  *   - <gdImageColorClosestAlpha>
  695  *   - <gdTrueColorAlpha>
  696  */
  697 BGD_DECLARE(int) gdImageColorExactAlpha (gdImagePtr im, int r, int g, int b, int a)
  698 {
  699     int i;
  700     if (im->trueColor) {
  701         return gdTrueColorAlpha (r, g, b, a);
  702     }
  703     for (i = 0; (i < (im->colorsTotal)); i++) {
  704         if (im->open[i]) {
  705             continue;
  706         }
  707         if ((im->red[i] == r) &&
  708                 (im->green[i] == g) && (im->blue[i] == b) && (im->alpha[i] == a)) {
  709             return i;
  710         }
  711     }
  712     return -1;
  713 }
  714 
  715 /**
  716  * Function: gdImageColorAllocate
  717  *
  718  * Allocates a color
  719  *
  720  * This is a simplified variant of <gdImageColorAllocateAlpha> where the alpha
  721  * channel is always opaque.
  722  *
  723  * Parameters:
  724  *   im - The image.
  725  *   r  - The value of the red component.
  726  *   g  - The value of the green component.
  727  *   b  - The value of the blue component.
  728  *
  729  * Returns:
  730  *   The color value.
  731  *
  732  * See also:
  733  *   - <gdImageColorDeallocate>
  734  */
  735 BGD_DECLARE(int) gdImageColorAllocate (gdImagePtr im, int r, int g, int b)
  736 {
  737     return gdImageColorAllocateAlpha (im, r, g, b, gdAlphaOpaque);
  738 }
  739 
  740 /**
  741  * Function: gdImageColorAllocateAlpha
  742  *
  743  * Allocates a color
  744  *
  745  * This is typically used for palette images, but can be used for truecolor
  746  * images as well.
  747  *
  748  * Parameters:
  749  *   im - The image.
  750  *   r  - The value of the red component.
  751  *   g  - The value of the green component.
  752  *   b  - The value of the blue component.
  753  *
  754  * Returns:
  755  *   The color value.
  756  *
  757  * See also:
  758  *   - <gdImageColorDeallocate>
  759  */
  760 BGD_DECLARE(int) gdImageColorAllocateAlpha (gdImagePtr im, int r, int g, int b, int a)
  761 {
  762     int i;
  763     int ct = (-1);
  764     if (im->trueColor) {
  765         return gdTrueColorAlpha (r, g, b, a);
  766     }
  767     for (i = 0; (i < (im->colorsTotal)); i++) {
  768         if (im->open[i]) {
  769             ct = i;
  770             break;
  771         }
  772     }
  773     if (ct == (-1)) {
  774         ct = im->colorsTotal;
  775         if (ct == gdMaxColors) {
  776             return -1;
  777         }
  778         im->colorsTotal++;
  779     }
  780     im->red[ct] = r;
  781     im->green[ct] = g;
  782     im->blue[ct] = b;
  783     im->alpha[ct] = a;
  784     im->open[ct] = 0;
  785     return ct;
  786 }
  787 
  788 /*
  789     Function: gdImageColorResolve
  790 
  791     gdImageColorResolve is an alternative for the code fragment
  792     (start code)
  793     if ((color=gdImageColorExact(im,R,G,B)) < 0)
  794       if ((color=gdImageColorAllocate(im,R,G,B)) < 0)
  795         color=gdImageColorClosest(im,R,G,B);
  796     (end code)
  797     in a single function.    Its advantage is that it is guaranteed to
  798     return a color index in one search over the color table.
  799 */
  800 
  801 BGD_DECLARE(int) gdImageColorResolve (gdImagePtr im, int r, int g, int b)
  802 {
  803     return gdImageColorResolveAlpha (im, r, g, b, gdAlphaOpaque);
  804 }
  805 
  806 /*
  807     Function: gdImageColorResolveAlpha
  808 */
  809 BGD_DECLARE(int) gdImageColorResolveAlpha (gdImagePtr im, int r, int g, int b, int a)
  810 {
  811     int c;
  812     int ct = -1;
  813     int op = -1;
  814     long rd, gd, bd, ad, dist;
  815     long mindist = 4 * 255 * 255;   /* init to max poss dist */
  816     if (im->trueColor) {
  817         return gdTrueColorAlpha (r, g, b, a);
  818     }
  819 
  820     for (c = 0; c < im->colorsTotal; c++) {
  821         if (im->open[c]) {
  822             op = c;     /* Save open slot */
  823             continue;       /* Color not in use */
  824         }
  825         if (c == im->transparent) {
  826             /* don't ever resolve to the color that has
  827              * been designated as the transparent color */
  828             continue;
  829         }
  830         rd = (long) (im->red[c] - r);
  831         gd = (long) (im->green[c] - g);
  832         bd = (long) (im->blue[c] - b);
  833         ad = (long) (im->alpha[c] - a);
  834         dist = rd * rd + gd * gd + bd * bd + ad * ad;
  835         if (dist < mindist) {
  836             if (dist == 0) {
  837                 return c;       /* Return exact match color */
  838             }
  839             mindist = dist;
  840             ct = c;
  841         }
  842     }
  843     /* no exact match.  We now know closest, but first try to allocate exact */
  844     if (op == -1) {
  845         op = im->colorsTotal;
  846         if (op == gdMaxColors) {
  847             /* No room for more colors */
  848             return ct;      /* Return closest available color */
  849         }
  850         im->colorsTotal++;
  851     }
  852     im->red[op] = r;
  853     im->green[op] = g;
  854     im->blue[op] = b;
  855     im->alpha[op] = a;
  856     im->open[op] = 0;
  857     return op;          /* Return newly allocated color */
  858 }
  859 
  860 /**
  861  * Function: gdImageColorDeallocate
  862  *
  863  * Removes a palette entry
  864  *
  865  * This is a no-op for truecolor images.
  866  *
  867  * Parameters:
  868  *   im    - The image.
  869  *   color - The palette index.
  870  *
  871  * See also:
  872  *   - <gdImageColorAllocate>
  873  *   - <gdImageColorAllocateAlpha>
  874  */
  875 BGD_DECLARE(void) gdImageColorDeallocate (gdImagePtr im, int color)
  876 {
  877     if (im->trueColor || (color >= gdMaxColors) || (color < 0)) {
  878         return;
  879     }
  880     /* Mark it open. */
  881     im->open[color] = 1;
  882 }
  883 
  884 /**
  885  * Function: gdImageColorTransparent
  886  *
  887  * Sets the transparent color of the image
  888  *
  889  * Parameter:
  890  *   im    - The image.
  891  *   color - The color.
  892  *
  893  * See also:
  894  *   - <gdImageGetTransparent>
  895  */
  896 BGD_DECLARE(void) gdImageColorTransparent (gdImagePtr im, int color)
  897 {
  898     if (color < 0) {
  899         return;
  900     }
  901 
  902     if (!im->trueColor) {
  903         if (color >= gdMaxColors) {
  904             return;
  905         }
  906         if (im->transparent != -1) {
  907             im->alpha[im->transparent] = gdAlphaOpaque;
  908         }
  909         im->alpha[color] = gdAlphaTransparent;
  910     }
  911     im->transparent = color;
  912 }
  913 
  914 /*
  915     Function: gdImagePaletteCopy
  916 */
  917 BGD_DECLARE(void) gdImagePaletteCopy (gdImagePtr to, gdImagePtr from)
  918 {
  919     int i;
  920     int x, y, p;
  921     int xlate[256];
  922     if (to->trueColor) {
  923         return;
  924     }
  925     if (from->trueColor) {
  926         return;
  927     }
  928 
  929     for (i = 0; i < 256; i++) {
  930         xlate[i] = -1;
  931     };
  932 
  933     for (y = 0; y < (to->sy); y++) {
  934         for (x = 0; x < (to->sx); x++) {
  935             /* Optimization: no gdImageGetPixel */
  936             p = to->pixels[y][x];
  937             if (xlate[p] == -1) {
  938                 /* This ought to use HWB, but we don't have an alpha-aware
  939                    version of that yet. */
  940                 xlate[p] =
  941                     gdImageColorClosestAlpha (from, to->red[p], to->green[p],
  942                                               to->blue[p], to->alpha[p]);
  943                 /*printf("Mapping %d (%d, %d, %d, %d) to %d (%d, %d, %d, %d)\n", */
  944                 /*      p,  to->red[p], to->green[p], to->blue[p], to->alpha[p], */
  945                 /*      xlate[p], from->red[xlate[p]], from->green[xlate[p]], from->blue[xlate[p]], from->alpha[xlate[p]]); */
  946             };
  947             /* Optimization: no gdImageSetPixel */
  948             to->pixels[y][x] = xlate[p];
  949         };
  950     };
  951 
  952     for (i = 0; (i < (from->colorsTotal)); i++) {
  953         /*printf("Copying color %d (%d, %d, %d, %d)\n", i, from->red[i], from->blue[i], from->green[i], from->alpha[i]); */
  954         to->red[i] = from->red[i];
  955         to->blue[i] = from->blue[i];
  956         to->green[i] = from->green[i];
  957         to->alpha[i] = from->alpha[i];
  958         to->open[i] = 0;
  959     };
  960 
  961     for (i = from->colorsTotal; (i < to->colorsTotal); i++) {
  962         to->open[i] = 1;
  963     };
  964 
  965     to->colorsTotal = from->colorsTotal;
  966 
  967 }
  968 
  969 /*
  970     Function: gdImageColorReplace
  971 */
  972 BGD_DECLARE(int) gdImageColorReplace (gdImagePtr im, int src, int dst)
  973 {
  974     register int x, y;
  975     int n = 0;
  976 
  977     if (src == dst) {
  978         return 0;
  979     }
  980 
  981 #define REPLACING_LOOP(pixel) do {                              \
  982         for (y = im->cy1; y <= im->cy2; y++) {                  \
  983             for (x = im->cx1; x <= im->cx2; x++) {              \
  984                 if (pixel(im, x, y) == src) {                   \
  985                     gdImageSetPixel(im, x, y, dst);             \
  986                     n++;                                        \
  987                 }                                               \
  988             }                                                   \
  989         }                                                       \
  990     } while (0)
  991 
  992     if (im->trueColor) {
  993         REPLACING_LOOP(gdImageTrueColorPixel);
  994     } else {
  995         REPLACING_LOOP(gdImagePalettePixel);
  996     }
  997 
  998 #undef REPLACING_LOOP
  999 
 1000     return n;
 1001 }
 1002 
 1003 /*
 1004     Function: gdImageColorReplaceThreshold
 1005 */
 1006 BGD_DECLARE(int) gdImageColorReplaceThreshold (gdImagePtr im, int src, int dst, float threshold)
 1007 {
 1008     register int x, y;
 1009     int n = 0;
 1010 
 1011     if (src == dst) {
 1012         return 0;
 1013     }
 1014 
 1015 #define REPLACING_LOOP(pixel) do {                                      \
 1016         for (y = im->cy1; y <= im->cy2; y++) {                          \
 1017             for (x = im->cx1; x <= im->cx2; x++) {                      \
 1018                 if (gdColorMatch(im, src, pixel(im, x, y), threshold)) { \
 1019                     gdImageSetPixel(im, x, y, dst);                     \
 1020                     n++;                                                \
 1021                 }                                                       \
 1022             }                                                           \
 1023         }                                                               \
 1024     } while (0)
 1025 
 1026     if (im->trueColor) {
 1027         REPLACING_LOOP(gdImageTrueColorPixel);
 1028     } else {
 1029         REPLACING_LOOP(gdImagePalettePixel);
 1030     }
 1031 
 1032 #undef REPLACING_LOOP
 1033 
 1034     return n;
 1035 }
 1036 
 1037 static int colorCmp (const void *x, const void *y)
 1038 {
 1039     int a = *(int const *)x;
 1040     int b = *(int const *)y;
 1041     return (a > b) - (a < b);
 1042 }
 1043 
 1044 /*
 1045     Function: gdImageColorReplaceArray
 1046 */
 1047 BGD_DECLARE(int) gdImageColorReplaceArray (gdImagePtr im, int len, int *src, int *dst)
 1048 {
 1049     register int x, y;
 1050     int c, *d, *base;
 1051     int i, n = 0;
 1052 
 1053     if (len <= 0 || src == dst) {
 1054         return 0;
 1055     }
 1056     if (len == 1) {
 1057         return gdImageColorReplace(im, src[0], dst[0]);
 1058     }
 1059     if (overflow2(len, sizeof(int)<<1)) {
 1060         return -1;
 1061     }
 1062     base = (int *)gdMalloc(len * (sizeof(int)<<1));
 1063     if (!base) {
 1064         return -1;
 1065     }
 1066     for (i = 0; i < len; i++) {
 1067         base[(i<<1)]   = src[i];
 1068         base[(i<<1)+1] = dst[i];
 1069     }
 1070     qsort(base, len, sizeof(int)<<1, colorCmp);
 1071 
 1072 #define REPLACING_LOOP(pixel) do {                                      \
 1073         for (y = im->cy1; y <= im->cy2; y++) {                          \
 1074             for (x = im->cx1; x <= im->cx2; x++) {                      \
 1075                 c = pixel(im, x, y);                                    \
 1076                 if ( (d = (int *)bsearch(&c, base, len, sizeof(int)<<1, colorCmp)) ) { \
 1077                     gdImageSetPixel(im, x, y, d[1]);                    \
 1078                     n++;                                                \
 1079                 }                                                       \
 1080             }                                                           \
 1081         }                                                               \
 1082     } while (0)
 1083 
 1084     if (im->trueColor) {
 1085         REPLACING_LOOP(gdImageTrueColorPixel);
 1086     } else {
 1087         REPLACING_LOOP(gdImagePalettePixel);
 1088     }
 1089 
 1090 #undef REPLACING_LOOP
 1091 
 1092     gdFree(base);
 1093     return n;
 1094 }
 1095 
 1096 /*
 1097     Function: gdImageColorReplaceCallback
 1098 */
 1099 BGD_DECLARE(int) gdImageColorReplaceCallback (gdImagePtr im, gdCallbackImageColor callback)
 1100 {
 1101     int c, d, n = 0;
 1102 
 1103     if (!callback) {
 1104         return 0;
 1105     }
 1106     if (im->trueColor) {
 1107         register int x, y;
 1108 
 1109         for (y = im->cy1; y <= im->cy2; y++) {
 1110             for (x = im->cx1; x <= im->cx2; x++) {
 1111                 c = gdImageTrueColorPixel(im, x, y);
 1112                 if ( (d = callback(im, c)) != c) {
 1113                     gdImageSetPixel(im, x, y, d);
 1114                     n++;
 1115                 }
 1116             }
 1117         }
 1118     } else { /* palette */
 1119         int *sarr, *darr;
 1120         int k, len = 0;
 1121 
 1122         sarr = (int *)gdCalloc(im->colorsTotal, sizeof(int));
 1123         if (!sarr) {
 1124             return -1;
 1125         }
 1126         for (c = 0; c < im->colorsTotal; c++) {
 1127             if (!im->open[c]) {
 1128                 sarr[len++] = c;
 1129             }
 1130         }
 1131         darr = (int *)gdCalloc(len, sizeof(int));
 1132         if (!darr) {
 1133             gdFree(sarr);
 1134             return -1;
 1135         }
 1136         for (k = 0; k < len; k++) {
 1137             darr[k] = callback(im, sarr[k]);
 1138         }
 1139         n = gdImageColorReplaceArray(im, k, sarr, darr);
 1140         gdFree(darr);
 1141         gdFree(sarr);
 1142     }
 1143     return n;
 1144 }
 1145 
 1146 /* 2.0.10: before the drawing routines, some code to clip points that are
 1147  * outside the drawing window.  Nick Atty (nick@canalplan.org.uk)
 1148  *
 1149  * This is the Sutherland Hodgman Algorithm, as implemented by
 1150  * Duvanenko, Robbins and Gyurcsik - SH(DRG) for short.  See Dr Dobb's
 1151  * Journal, January 1996, pp107-110 and 116-117
 1152  *
 1153  * Given the end points of a line, and a bounding rectangle (which we
 1154  * know to be from (0,0) to (SX,SY)), adjust the endpoints to be on
 1155  * the edges of the rectangle if the line should be drawn at all,
 1156  * otherwise return a failure code */
 1157 
 1158 /* this does "one-dimensional" clipping: note that the second time it
 1159    is called, all the x parameters refer to height and the y to width
 1160    - the comments ignore this (if you can understand it when it's
 1161    looking at the X parameters, it should become clear what happens on
 1162    the second call!)  The code is simplified from that in the article,
 1163    as we know that gd images always start at (0,0) */
 1164 
 1165 /* 2.0.26, TBB: we now have to respect a clipping rectangle, it won't
 1166     necessarily start at 0. */
 1167 
 1168 static int
 1169 clip_1d (int *x0, int *y0, int *x1, int *y1, int mindim, int maxdim)
 1170 {
 1171     double m;           /* gradient of line */
 1172     if (*x0 < mindim) {
 1173         /* start of line is left of window */
 1174         if (*x1 < mindim)       /* as is the end, so the line never cuts the window */
 1175             return 0;
 1176         m = (*y1 - *y0) / (double) (*x1 - *x0); /* calculate the slope of the line */
 1177         /* adjust x0 to be on the left boundary (ie to be zero), and y0 to match */
 1178         *y0 -= (int)(m * (*x0 - mindim));
 1179         *x0 = mindim;
 1180         /* now, perhaps, adjust the far end of the line as well */
 1181         if (*x1 > maxdim) {
 1182             *y1 += m * (maxdim - *x1);
 1183             *x1 = maxdim;
 1184         }
 1185         return 1;
 1186     }
 1187     if (*x0 > maxdim) {
 1188         /* start of line is right of window -
 1189         complement of above */
 1190         if (*x1 > maxdim)       /* as is the end, so the line misses the window */
 1191             return 0;
 1192         m = (*y1 - *y0) / (double) (*x1 - *x0); /* calculate the slope of the line */
 1193         *y0 += (int)(m * (maxdim - *x0));   /* adjust so point is on the right
 1194                                boundary */
 1195         *x0 = maxdim;
 1196         /* now, perhaps, adjust the end of the line */
 1197         if (*x1 < mindim) {
 1198             *y1 -= (int)(m * (*x1 - mindim));
 1199             *x1 = mindim;
 1200         }
 1201         return 1;
 1202     }
 1203     /* the final case - the start of the line is inside the window */
 1204     if (*x1 > maxdim) {
 1205         /* other end is outside to the right */
 1206         m = (*y1 - *y0) / (double) (*x1 - *x0); /* calculate the slope of the line */
 1207         *y1 += (int)(m * (maxdim - *x1));
 1208         *x1 = maxdim;
 1209         return 1;
 1210     }
 1211     if (*x1 < mindim) {
 1212         /* other end is outside to the left */
 1213         m = (*y1 - *y0) / (double) (*x1 - *x0); /* calculate the slope of the line */
 1214         *y1 -= (int)(m * (*x1 - mindim));
 1215         *x1 = mindim;
 1216         return 1;
 1217     }
 1218     /* only get here if both points are inside the window */
 1219     return 1;
 1220 }
 1221 
 1222 /* end of line clipping code */
 1223 
 1224 /**
 1225  * Group: Pixels
 1226  */
 1227 
 1228 /*
 1229     Function: gdImageSetPixel
 1230 */
 1231 BGD_DECLARE(void) gdImageSetPixel (gdImagePtr im, int x, int y, int color)
 1232 {
 1233     int p;
 1234     switch (color) {
 1235     case gdStyled:
 1236         if (!im->style) {
 1237             /* Refuse to draw if no style is set. */
 1238             return;
 1239         } else {
 1240             p = im->style[im->stylePos++];
 1241         }
 1242         if (p != (gdTransparent)) {
 1243             gdImageSetPixel (im, x, y, p);
 1244         }
 1245         im->stylePos = im->stylePos % im->styleLength;
 1246         break;
 1247     case gdStyledBrushed:
 1248         if (!im->style) {
 1249             /* Refuse to draw if no style is set. */
 1250             return;
 1251         }
 1252         p = im->style[im->stylePos++];
 1253         if ((p != gdTransparent) && (p != 0)) {
 1254             gdImageSetPixel (im, x, y, gdBrushed);
 1255         }
 1256         im->stylePos = im->stylePos % im->styleLength;
 1257         break;
 1258     case gdBrushed:
 1259         gdImageBrushApply (im, x, y);
 1260         break;
 1261     case gdTiled:
 1262         gdImageTileApply (im, x, y);
 1263         break;
 1264     case gdAntiAliased:
 1265         /* This shouldn't happen (2.0.26) because we just call
 1266           gdImageAALine now, but do something sane. */
 1267         gdImageSetPixel(im, x, y, im->AA_color);
 1268         break;
 1269     default:
 1270         if (gdImageBoundsSafeMacro (im, x, y)) {
 1271             if (im->trueColor) {
 1272                 switch (im->alphaBlendingFlag) {
 1273                     default:
 1274                     case gdEffectReplace:
 1275                         im->tpixels[y][x] = color;
 1276                         break;
 1277                     case gdEffectAlphaBlend:
 1278                     case gdEffectNormal:
 1279                         im->tpixels[y][x] = gdAlphaBlend(im->tpixels[y][x], color);
 1280                         break;
 1281                     case gdEffectOverlay :
 1282                         im->tpixels[y][x] = gdLayerOverlay(im->tpixels[y][x], color);
 1283                         break;
 1284                     case gdEffectMultiply :
 1285                         im->tpixels[y][x] = gdLayerMultiply(im->tpixels[y][x], color);
 1286                         break;
 1287                 }
 1288             } else {
 1289                 im->pixels[y][x] = color;
 1290             }
 1291         }
 1292         break;
 1293     }
 1294 }
 1295 
 1296 static void
 1297 gdImageBrushApply (gdImagePtr im, int x, int y)
 1298 {
 1299     int lx, ly;
 1300     int hy;
 1301     int hx;
 1302     int x1, y1, x2, y2;
 1303     int srcx, srcy;
 1304     if (!im->brush) {
 1305         return;
 1306     }
 1307     hy = gdImageSY (im->brush) / 2;
 1308     y1 = y - hy;
 1309     y2 = y1 + gdImageSY (im->brush);
 1310     hx = gdImageSX (im->brush) / 2;
 1311     x1 = x - hx;
 1312     x2 = x1 + gdImageSX (im->brush);
 1313     srcy = 0;
 1314     if (im->trueColor) {
 1315         if (im->brush->trueColor) {
 1316             for (ly = y1; (ly < y2); ly++) {
 1317                 srcx = 0;
 1318                 for (lx = x1; (lx < x2); lx++) {
 1319                     int p;
 1320                     p = gdImageGetTrueColorPixel (im->brush, srcx, srcy);
 1321                     /* 2.0.9, Thomas Winzig: apply simple full transparency */
 1322                     if (p != gdImageGetTransparent (im->brush)) {
 1323                         gdImageSetPixel (im, lx, ly, p);
 1324                     }
 1325                     srcx++;
 1326                 }
 1327                 srcy++;
 1328             }
 1329         } else {
 1330             /* 2.0.12: Brush palette, image truecolor (thanks to Thorben Kundinger
 1331                for pointing out the issue) */
 1332             for (ly = y1; (ly < y2); ly++) {
 1333                 srcx = 0;
 1334                 for (lx = x1; (lx < x2); lx++) {
 1335                     int p, tc;
 1336                     p = gdImageGetPixel (im->brush, srcx, srcy);
 1337                     tc = gdImageGetTrueColorPixel (im->brush, srcx, srcy);
 1338                     /* 2.0.9, Thomas Winzig: apply simple full transparency */
 1339                     if (p != gdImageGetTransparent (im->brush)) {
 1340                         gdImageSetPixel (im, lx, ly, tc);
 1341                     }
 1342                     srcx++;
 1343                 }
 1344                 srcy++;
 1345             }
 1346         }
 1347     } else {
 1348         for (ly = y1; (ly < y2); ly++) {
 1349             srcx = 0;
 1350             for (lx = x1; (lx < x2); lx++) {
 1351                 int p;
 1352                 p = gdImageGetPixel (im->brush, srcx, srcy);
 1353                 /* Allow for non-square brushes! */
 1354                 if (p != gdImageGetTransparent (im->brush)) {
 1355                     /* Truecolor brush. Very slow
 1356                        on a palette destination. */
 1357                     if (im->brush->trueColor) {
 1358                         gdImageSetPixel (im, lx, ly,
 1359                                          gdImageColorResolveAlpha (im,
 1360                                                  gdTrueColorGetRed
 1361                                                  (p),
 1362                                                  gdTrueColorGetGreen
 1363                                                  (p),
 1364                                                  gdTrueColorGetBlue
 1365                                                  (p),
 1366                                                  gdTrueColorGetAlpha
 1367                                                  (p)));
 1368                     } else {
 1369                         gdImageSetPixel (im, lx, ly, im->brushColorMap[p]);
 1370                     }
 1371                 }
 1372                 srcx++;
 1373             }
 1374             srcy++;
 1375         }
 1376     }
 1377 }
 1378 
 1379 static void
 1380 gdImageTileApply (gdImagePtr im, int x, int y)
 1381 {
 1382     gdImagePtr tile = im->tile;
 1383     int srcx, srcy;
 1384     int p;
 1385     if (!tile) {
 1386         return;
 1387     }
 1388     srcx = x % gdImageSX (tile);
 1389     srcy = y % gdImageSY (tile);
 1390     if (im->trueColor) {
 1391         p = gdImageGetPixel (tile, srcx, srcy);
 1392         if (p != gdImageGetTransparent (tile)) {
 1393             if (!tile->trueColor) {
 1394                 p = gdTrueColorAlpha(tile->red[p], tile->green[p], tile->blue[p], tile->alpha[p]);
 1395             }
 1396             gdImageSetPixel (im, x, y, p);
 1397         }
 1398     } else {
 1399         p = gdImageGetPixel (tile, srcx, srcy);
 1400         /* Allow for transparency */
 1401         if (p != gdImageGetTransparent (tile)) {
 1402             if (tile->trueColor) {
 1403                 /* Truecolor tile. Very slow
 1404                    on a palette destination. */
 1405                 gdImageSetPixel (im, x, y,
 1406                                  gdImageColorResolveAlpha (im,
 1407                                          gdTrueColorGetRed
 1408                                          (p),
 1409                                          gdTrueColorGetGreen
 1410                                          (p),
 1411                                          gdTrueColorGetBlue
 1412                                          (p),
 1413                                          gdTrueColorGetAlpha
 1414                                          (p)));
 1415             } else {
 1416                 gdImageSetPixel (im, x, y, im->tileColorMap[p]);
 1417             }
 1418         }
 1419     }
 1420 }
 1421 
 1422 /**
 1423  * Function: gdImageGetPixel
 1424  *
 1425  * Gets a pixel color as stored in the image.
 1426  *
 1427  * Parameters:
 1428  *   im - The image.
 1429  *   x  - The x-coordinate.
 1430  *   y  - The y-coordinate.
 1431  *
 1432  * See also:
 1433  *   - <gdImageGetTrueColorPixel>
 1434  *   - <gdImagePalettePixel>
 1435  *   - <gdImageTrueColorPixel>
 1436  */
 1437 BGD_DECLARE(int) gdImageGetPixel (gdImagePtr im, int x, int y)
 1438 {
 1439     if (gdImageBoundsSafeMacro (im, x, y)) {
 1440         if (im->trueColor) {
 1441             return im->tpixels[y][x];
 1442         } else {
 1443             return im->pixels[y][x];
 1444         }
 1445     } else {
 1446         return 0;
 1447     }
 1448 }
 1449 
 1450 /**
 1451  * Function: gdImageGetTrueColorPixel
 1452  *
 1453  * Gets a pixel color always as truecolor value.
 1454  *
 1455  * Parameters:
 1456  *   im - The image.
 1457  *   x  - The x-coordinate.
 1458  *   y  - The y-coordinate.
 1459  *
 1460  * See also:
 1461  *   - <gdImageGetPixel>
 1462  *   - <gdImageTrueColorPixel>
 1463  */
 1464 BGD_DECLARE(int) gdImageGetTrueColorPixel (gdImagePtr im, int x, int y)
 1465 {
 1466     int p = gdImageGetPixel (im, x, y);
 1467     if (!im->trueColor) {
 1468         return gdTrueColorAlpha (im->red[p], im->green[p], im->blue[p],
 1469                                  (im->transparent == p) ? gdAlphaTransparent :
 1470                                  im->alpha[p]);
 1471     } else {
 1472         return p;
 1473     }
 1474 }
 1475 
 1476 /**
 1477  * Group: Primitives
 1478  */
 1479 
 1480 /*
 1481     Function: gdImageAABlend
 1482 
 1483     NO-OP, kept for library compatibility.
 1484 */
 1485 BGD_DECLARE(void) gdImageAABlend (gdImagePtr im)
 1486 {
 1487     (void)im;
 1488 }
 1489 
 1490 static void gdImageAALine (gdImagePtr im, int x1, int y1, int x2, int y2, int col);
 1491 
 1492 static void _gdImageFilledHRectangle (gdImagePtr im, int x1, int y1, int x2, int y2,
 1493         int color);
 1494 
 1495 static void gdImageHLine(gdImagePtr im, int y, int x1, int x2, int col)
 1496 {
 1497     if (im->thick > 1) {
 1498         int thickhalf = im->thick >> 1;
 1499         _gdImageFilledHRectangle(im, x1, y - thickhalf, x2, y + im->thick - thickhalf - 1, col);
 1500     } else {
 1501         if (x2 < x1) {
 1502             int t = x2;
 1503             x2 = x1;
 1504             x1 = t;
 1505         }
 1506 
 1507         for (; x1 <= x2; x1++) {
 1508             gdImageSetPixel(im, x1, y, col);
 1509         }
 1510     }
 1511     return;
 1512 }
 1513 
 1514 static void gdImageVLine(gdImagePtr im, int x, int y1, int y2, int col)
 1515 {
 1516     if (im->thick > 1) {
 1517         int thickhalf = im->thick >> 1;
 1518         gdImageFilledRectangle(im, x - thickhalf, y1, x + im->thick - thickhalf - 1, y2, col);
 1519     } else {
 1520         if (y2 < y1) {
 1521             int t = y1;
 1522             y1 = y2;
 1523             y2 = t;
 1524         }
 1525 
 1526         for (; y1 <= y2; y1++) {
 1527             gdImageSetPixel(im, x, y1, col);
 1528         }
 1529     }
 1530     return;
 1531 }
 1532 
 1533 /*
 1534     Function: gdImageLine
 1535 
 1536     Bresenham as presented in Foley & Van Dam.
 1537 */
 1538 BGD_DECLARE(void) gdImageLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
 1539 {
 1540     int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
 1541     int wid;
 1542     int w, wstart;
 1543     int thick;
 1544 
 1545     if (color == gdAntiAliased) {
 1546         /*
 1547           gdAntiAliased passed as color: use the much faster, much cheaper
 1548           and equally attractive gdImageAALine implementation. That
 1549           clips too, so don't clip twice.
 1550         */
 1551         gdImageAALine(im, x1, y1, x2, y2, im->AA_color);
 1552         return;
 1553     }
 1554     /* 2.0.10: Nick Atty: clip to edges of drawing rectangle, return if no
 1555        points need to be drawn. 2.0.26, TBB: clip to edges of clipping
 1556        rectangle. We were getting away with this because gdImageSetPixel
 1557        is used for actual drawing, but this is still more efficient and opens
 1558        the way to skip per-pixel bounds checking in the future. */
 1559 
 1560     if (clip_1d (&x1, &y1, &x2, &y2, im->cx1, im->cx2) == 0)
 1561         return;
 1562     if (clip_1d (&y1, &x1, &y2, &x2, im->cy1, im->cy2) == 0)
 1563         return;
 1564     thick = im->thick;
 1565 
 1566     dx = abs (x2 - x1);
 1567     dy = abs (y2 - y1);
 1568 
 1569     if (dx == 0) {
 1570         gdImageVLine(im, x1, y1, y2, color);
 1571         return;
 1572     } else if (dy == 0) {
 1573         gdImageHLine(im, y1, x1, x2, color);
 1574         return;
 1575     }
 1576 
 1577     if (dy <= dx) {
 1578         /* More-or-less horizontal. use wid for vertical stroke */
 1579         /* Doug Claar: watch out for NaN in atan2 (2.0.5) */
 1580 
 1581         /* 2.0.12: Michael Schwartz: divide rather than multiply;
 1582               TBB: but watch out for /0! */
 1583         double ac = cos (atan2 (dy, dx));
 1584         if (ac != 0) {
 1585             wid = thick / ac;
 1586         } else {
 1587             wid = 1;
 1588         }
 1589         if (wid == 0) {
 1590             wid = 1;
 1591         }
 1592         d = 2 * dy - dx;
 1593         incr1 = 2 * dy;
 1594         incr2 = 2 * (dy - dx);
 1595         if (x1 > x2) {
 1596             x = x2;
 1597             y = y2;
 1598             ydirflag = (-1);
 1599             xend = x1;
 1600         } else {
 1601             x = x1;
 1602             y = y1;
 1603             ydirflag = 1;
 1604             xend = x2;
 1605         }
 1606 
 1607         /* Set up line thickness */
 1608         wstart = y - wid / 2;
 1609         for (w = wstart; w < wstart + wid; w++)
 1610             gdImageSetPixel (im, x, w, color);
 1611 
 1612         if (((y2 - y1) * ydirflag) > 0) {
 1613             while (x < xend) {
 1614                 x++;
 1615                 if (d < 0) {
 1616                     d += incr1;
 1617                 } else {
 1618                     y++;
 1619                     d += incr2;
 1620                 }
 1621                 wstart = y - wid / 2;
 1622                 for (w = wstart; w < wstart + wid; w++)
 1623                     gdImageSetPixel (im, x, w, color);
 1624             }
 1625         } else {
 1626             while (x < xend) {
 1627                 x++;
 1628                 if (d < 0) {
 1629                     d += incr1;
 1630                 } else {
 1631                     y--;
 1632                     d += incr2;
 1633                 }
 1634                 wstart = y - wid / 2;
 1635                 for (w = wstart; w < wstart + wid; w++)
 1636                     gdImageSetPixel (im, x, w, color);
 1637             }
 1638         }
 1639     } else {
 1640         /* More-or-less vertical. use wid for horizontal stroke */
 1641         /* 2.0.12: Michael Schwartz: divide rather than multiply;
 1642            TBB: but watch out for /0! */
 1643         double as = sin (atan2 (dy, dx));
 1644         if (as != 0) {
 1645             wid = thick / as;
 1646         } else {
 1647             wid = 1;
 1648         }
 1649         if (wid == 0)
 1650             wid = 1;
 1651 
 1652         d = 2 * dx - dy;
 1653         incr1 = 2 * dx;
 1654         incr2 = 2 * (dx - dy);
 1655         if (y1 > y2) {
 1656             y = y2;
 1657             x = x2;
 1658             yend = y1;
 1659             xdirflag = (-1);
 1660         } else {
 1661             y = y1;
 1662             x = x1;
 1663             yend = y2;
 1664             xdirflag = 1;
 1665         }
 1666 
 1667         /* Set up line thickness */
 1668         wstart = x - wid / 2;
 1669         for (w = wstart; w < wstart + wid; w++)
 1670             gdImageSetPixel (im, w, y, color);
 1671 
 1672         if (((x2 - x1) * xdirflag) > 0) {
 1673             while (y < yend) {
 1674                 y++;
 1675                 if (d < 0) {
 1676                     d += incr1;
 1677                 } else {
 1678                     x++;
 1679                     d += incr2;
 1680                 }
 1681                 wstart = x - wid / 2;
 1682                 for (w = wstart; w < wstart + wid; w++)
 1683                     gdImageSetPixel (im, w, y, color);
 1684             }
 1685         } else {
 1686             while (y < yend) {
 1687                 y++;
 1688                 if (d < 0) {
 1689                     d += incr1;
 1690                 } else {
 1691                     x--;
 1692                     d += incr2;
 1693                 }
 1694                 wstart = x - wid / 2;
 1695                 for (w = wstart; w < wstart + wid; w++)
 1696                     gdImageSetPixel (im, w, y, color);
 1697             }
 1698         }
 1699     }
 1700 
 1701 }
 1702 static void dashedSet (gdImagePtr im, int x, int y, int color,
 1703                        int *onP, int *dashStepP, int wid, int vert);
 1704 
 1705 /*
 1706     Function: gdImageDashedLine
 1707 */
 1708 BGD_DECLARE(void) gdImageDashedLine (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
 1709 {
 1710     int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
 1711     int dashStep = 0;
 1712     int on = 1;
 1713     int wid;
 1714     int vert;
 1715     int thick = im->thick;
 1716 
 1717     dx = abs (x2 - x1);
 1718     dy = abs (y2 - y1);
 1719     if (dy <= dx) {
 1720         /* More-or-less horizontal. use wid for vertical stroke */
 1721         /* 2.0.12: Michael Schwartz: divide rather than multiply;
 1722            TBB: but watch out for /0! */
 1723         double as = sin (atan2 (dy, dx));
 1724         if (as != 0) {
 1725             wid = thick / as;
 1726         } else {
 1727             wid = 1;
 1728         }
 1729         vert = 1;
 1730 
 1731         d = 2 * dy - dx;
 1732         incr1 = 2 * dy;
 1733         incr2 = 2 * (dy - dx);
 1734         if (x1 > x2) {
 1735             x = x2;
 1736             y = y2;
 1737             ydirflag = (-1);
 1738             xend = x1;
 1739         } else {
 1740             x = x1;
 1741             y = y1;
 1742             ydirflag = 1;
 1743             xend = x2;
 1744         }
 1745         dashedSet (im, x, y, color, &on, &dashStep, wid, vert);
 1746         if (((y2 - y1) * ydirflag) > 0) {
 1747             while (x < xend) {
 1748                 x++;
 1749                 if (d < 0) {
 1750                     d += incr1;
 1751                 } else {
 1752                     y++;
 1753                     d += incr2;
 1754                 }
 1755                 dashedSet (im, x, y, color, &on, &dashStep, wid, vert);
 1756             }
 1757         } else {
 1758             while (x < xend) {
 1759                 x++;
 1760                 if (d < 0) {
 1761                     d += incr1;
 1762                 } else {
 1763                     y--;
 1764                     d += incr2;
 1765                 }
 1766                 dashedSet (im, x, y, color, &on, &dashStep, wid, vert);
 1767             }
 1768         }
 1769     } else {
 1770         /* 2.0.12: Michael Schwartz: divide rather than multiply;
 1771            TBB: but watch out for /0! */
 1772         double as = sin (atan2 (dy, dx));
 1773         if (as != 0) {
 1774             wid = thick / as;
 1775         } else {
 1776             wid = 1;
 1777         }
 1778         vert = 0;
 1779 
 1780         d = 2 * dx - dy;
 1781         incr1 = 2 * dx;
 1782         incr2 = 2 * (dx - dy);
 1783         if (y1 > y2) {
 1784             y = y2;
 1785             x = x2;
 1786             yend = y1;
 1787             xdirflag = (-1);
 1788         } else {
 1789             y = y1;
 1790             x = x1;
 1791             yend = y2;
 1792             xdirflag = 1;
 1793         }
 1794         dashedSet (im, x, y, color, &on, &dashStep, wid, vert);
 1795         if (((x2 - x1) * xdirflag) > 0) {
 1796             while (y < yend) {
 1797                 y++;
 1798                 if (d < 0) {
 1799                     d += incr1;
 1800                 } else {
 1801                     x++;
 1802                     d += incr2;
 1803                 }
 1804                 dashedSet (im, x, y, color, &on, &dashStep, wid, vert);
 1805             }
 1806         } else {
 1807             while (y < yend) {
 1808                 y++;
 1809                 if (d < 0) {
 1810                     d += incr1;
 1811                 } else {
 1812                     x--;
 1813                     d += incr2;
 1814                 }
 1815                 dashedSet (im, x, y, color, &on, &dashStep, wid, vert);
 1816             }
 1817         }
 1818     }
 1819 }
 1820 
 1821 static void
 1822 dashedSet (gdImagePtr im, int x, int y, int color,
 1823            int *onP, int *dashStepP, int wid, int vert)
 1824 {
 1825     int dashStep = *dashStepP;
 1826     int on = *onP;
 1827     int w, wstart;
 1828 
 1829     dashStep++;
 1830     if (dashStep == gdDashSize) {
 1831         dashStep = 0;
 1832         on = !on;
 1833     }
 1834     if (on) {
 1835         if (vert) {
 1836             wstart = y - wid / 2;
 1837             for (w = wstart; w < wstart + wid; w++)
 1838                 gdImageSetPixel (im, x, w, color);
 1839         } else {
 1840             wstart = x - wid / 2;
 1841             for (w = wstart; w < wstart + wid; w++)
 1842                 gdImageSetPixel (im, w, y, color);
 1843         }
 1844     }
 1845     *dashStepP = dashStep;
 1846     *onP = on;
 1847 }
 1848 
 1849 /*
 1850     Function: gdImageBoundsSafe
 1851 */
 1852 BGD_DECLARE(int) gdImageBoundsSafe (gdImagePtr im, int x, int y)
 1853 {
 1854     return gdImageBoundsSafeMacro (im, x, y);
 1855 }
 1856 
 1857 /**
 1858  * Function: gdImageChar
 1859  *
 1860  * Draws a single character.
 1861  *
 1862  * Parameters:
 1863  *  im    - The image to draw onto.
 1864  *  f     - The raster font.
 1865  *  x     - The x coordinate of the upper left pixel.
 1866  *  y     - The y coordinate of the upper left pixel.
 1867  *  c     - The character.
 1868  *  color - The color.
 1869  *
 1870  * Variants:
 1871  *  - <gdImageCharUp>
 1872  *
 1873  * See also:
 1874  *  - <gdFontPtr>
 1875  */
 1876 BGD_DECLARE(void) gdImageChar (gdImagePtr im, gdFontPtr f, int x, int y, int c, int color)
 1877 {
 1878     int cx, cy;
 1879     int px, py;
 1880     int fline;
 1881     const int xuppper = (x > INT_MAX - f->w) ? INT_MAX : x + f->w;
 1882     const int yuppper = (y > INT_MAX - f->h) ? INT_MAX : y + f->h;
 1883     cx = 0;
 1884     cy = 0;
 1885 #ifdef CHARSET_EBCDIC
 1886     c = ASC (c);
 1887 #endif /*CHARSET_EBCDIC */
 1888     if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
 1889         return;
 1890     }
 1891     fline = (c - f->offset) * f->h * f->w;
 1892     for (py = y; py < yuppper; py++) {
 1893         for (px = x; px < xuppper; px++) {
 1894             if (f->data[fline + cy * f->w + cx]) {
 1895                 gdImageSetPixel (im, px, py, color);
 1896             }
 1897             cx++;
 1898         }
 1899         cx = 0;
 1900         cy++;
 1901     }
 1902 }
 1903 
 1904 /**
 1905  * Function: gdImageCharUp
 1906  */
 1907 BGD_DECLARE(void) gdImageCharUp (gdImagePtr im, gdFontPtr f, int x, int y, int c, int color)
 1908 {
 1909     int cx, cy;
 1910     int px, py;
 1911     int fline;
 1912     const int xuppper = (x > INT_MAX - f->h) ? INT_MAX : x + f->h;
 1913     const int ylower = (y < INT_MIN + f->w) ? INT_MIN : y - f->w;
 1914     cx = 0;
 1915     cy = 0;
 1916 #ifdef CHARSET_EBCDIC
 1917     c = ASC (c);
 1918 #endif /*CHARSET_EBCDIC */
 1919     if ((c < f->offset) || (c >= (f->offset + f->nchars))) {
 1920         return;
 1921     }
 1922     fline = (c - f->offset) * f->h * f->w;
 1923     for (py = y; py > ylower; py--) {
 1924         for (px = x; px < xuppper; px++) {
 1925             if (f->data[fline + cy * f->w + cx]) {
 1926                 gdImageSetPixel (im, px, py, color);
 1927             }
 1928             cy++;
 1929         }
 1930         cy = 0;
 1931         cx++;
 1932     }
 1933 }
 1934 
 1935 /**
 1936  * Function: gdImageString
 1937  *
 1938  * Draws a character string.
 1939  *
 1940  * Parameters:
 1941  *  im    - The image to draw onto.
 1942  *  f     - The raster font.
 1943  *  x     - The x coordinate of the upper left pixel.
 1944  *  y     - The y coordinate of the upper left pixel.
 1945  *  c     - The character string.
 1946  *  color - The color.
 1947  *
 1948  * Variants:
 1949  *  - <gdImageStringUp>
 1950  *  - <gdImageString16>
 1951  *  - <gdImageStringUp16>
 1952  *
 1953  * See also:
 1954  *  - <gdFontPtr>
 1955  *  - <gdImageStringTTF>
 1956  */
 1957 BGD_DECLARE(void) gdImageString (gdImagePtr im, gdFontPtr f,
 1958                                  int x, int y, unsigned char *s, int color)
 1959 {
 1960     int i;
 1961     int l;
 1962     l = strlen ((char *) s);
 1963     for (i = 0; (i < l); i++) {
 1964         gdImageChar (im, f, x, y, s[i], color);
 1965         x += f->w;
 1966     }
 1967 }
 1968 
 1969 /**
 1970  * Function: gdImageStringUp
 1971  */
 1972 BGD_DECLARE(void) gdImageStringUp (gdImagePtr im, gdFontPtr f,
 1973                                    int x, int y, unsigned char *s, int color)
 1974 {
 1975     int i;
 1976     int l;
 1977     l = strlen ((char *) s);
 1978     for (i = 0; (i < l); i++) {
 1979         gdImageCharUp (im, f, x, y, s[i], color);
 1980         y -= f->w;
 1981     }
 1982 }
 1983 
 1984 static int strlen16 (unsigned short *s);
 1985 
 1986 /**
 1987  * Function: gdImageString16
 1988  */
 1989 BGD_DECLARE(void) gdImageString16 (gdImagePtr im, gdFontPtr f,
 1990                                    int x, int y, unsigned short *s, int color)
 1991 {
 1992     int i;
 1993     int l;
 1994     l = strlen16 (s);
 1995     for (i = 0; (i < l); i++) {
 1996         gdImageChar (im, f, x, y, s[i], color);
 1997         x += f->w;
 1998     }
 1999 }
 2000 
 2001 /**
 2002  * Function: gdImageStringUp16
 2003  */
 2004 BGD_DECLARE(void) gdImageStringUp16 (gdImagePtr im, gdFontPtr f,
 2005                                      int x, int y, unsigned short *s, int color)
 2006 {
 2007     int i;
 2008     int l;
 2009     l = strlen16 (s);
 2010     for (i = 0; (i < l); i++) {
 2011         gdImageCharUp (im, f, x, y, s[i], color);
 2012         y -= f->w;
 2013     }
 2014 }
 2015 
 2016 static int
 2017 strlen16 (unsigned short *s)
 2018 {
 2019     int len = 0;
 2020     while (*s) {
 2021         s++;
 2022         len++;
 2023     }
 2024     return len;
 2025 }
 2026 
 2027 #ifndef HAVE_LSQRT
 2028 /* If you don't have a nice square root function for longs, you can use
 2029    ** this hack
 2030  */
 2031 long
 2032 lsqrt (long n)
 2033 {
 2034     long result = (long) sqrt ((double) n);
 2035     return result;
 2036 }
 2037 #endif
 2038 
 2039 /* s and e are integers modulo 360 (degrees), with 0 degrees
 2040    being the rightmost extreme and degrees changing clockwise.
 2041    cx and cy are the center in pixels; w and h are the horizontal
 2042    and vertical diameter in pixels. */
 2043 
 2044 /*
 2045     Function: gdImageArc
 2046 */
 2047 BGD_DECLARE(void) gdImageArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e,
 2048                               int color)
 2049 {
 2050     gdImageFilledArc (im, cx, cy, w, h, s, e, color, gdNoFill);
 2051 }
 2052 
 2053 /*
 2054     Function: gdImageFilledArc
 2055 */
 2056 BGD_DECLARE(void) gdImageFilledArc (gdImagePtr im, int cx, int cy, int w, int h, int s, int e,
 2057                                     int color, int style)
 2058 {
 2059     gdPoint pts[363];
 2060     int i, pti;
 2061     int lx = 0, ly = 0;
 2062     int fx = 0, fy = 0;
 2063     int startx = -1, starty = -1, endx = -1, endy = -1;
 2064 
 2065     if ((s % 360)  == (e % 360)) {
 2066         s = 0;
 2067         e = 360;
 2068     } else {
 2069         if (s > 360) {
 2070             s = s % 360;
 2071         }
 2072 
 2073         if (e > 360) {
 2074             e = e % 360;
 2075         }
 2076 
 2077         while (s < 0) {
 2078             s += 360;
 2079         }
 2080 
 2081         while (e < s) {
 2082             e += 360;
 2083         }
 2084 
 2085         if (s == e) {
 2086             s = 0;
 2087             e = 360;
 2088         }
 2089     }
 2090 
 2091     for (i = s, pti = 1; (i <= e); i++, pti++) {
 2092         int x, y;
 2093         x = endx = ((long) gdCosT[i % 360] * (long) w / (2 * 1024)) + cx;
 2094         y = endy = ((long) gdSinT[i % 360] * (long) h / (2 * 1024)) + cy;
 2095         if (i != s) {
 2096             if (!(style & gdChord)) {
 2097                 if (style & gdNoFill) {
 2098                     gdImageLine (im, lx, ly, x, y, color);
 2099                 } else {
 2100                     if (y == ly) {
 2101                         pti--; /* don't add this point */
 2102                         if (((i > 270 || i < 90) && x > lx) || ((i >  90 && i < 270) && x < lx)) {
 2103                             /* replace the old x coord, if increasing on the
 2104                                right side or decreasing on the left side */
 2105                             pts[pti].x = x;
 2106                         }
 2107                     } else {
 2108                         pts[pti].x = x;
 2109                         pts[pti].y = y;
 2110                     }
 2111                 }
 2112             }
 2113         } else {
 2114             fx = x;
 2115             fy = y;
 2116 
 2117             if (!(style & (gdChord | gdNoFill))) {
 2118                 pts[0].x = cx;
 2119                 pts[0].y = cy;
 2120                 pts[pti].x = startx = x;
 2121                 pts[pti].y = starty = y;
 2122             }
 2123         }
 2124         lx = x;
 2125         ly = y;
 2126     }
 2127     if (style & gdChord) {
 2128         if (style & gdNoFill) {
 2129             if (style & gdEdged) {
 2130                 gdImageLine (im, cx, cy, lx, ly, color);
 2131                 gdImageLine (im, cx, cy, fx, fy, color);
 2132             }
 2133             gdImageLine (im, fx, fy, lx, ly, color);
 2134         } else {
 2135             pts[0].x = fx;
 2136             pts[0].y = fy;
 2137             pts[1].x = lx;
 2138             pts[1].y = ly;
 2139             pts[2].x = cx;
 2140             pts[2].y = cy;
 2141             gdImageFilledPolygon (im, pts, 3, color);
 2142         }
 2143     } else {
 2144         if (style & gdNoFill) {
 2145             if (style & gdEdged) {
 2146                 gdImageLine (im, cx, cy, lx, ly, color);
 2147                 gdImageLine (im, cx, cy, fx, fy, color);
 2148             }
 2149         } else {
 2150             if (e - s < 360) {
 2151                 if (pts[1].x != startx && pts[1].y == starty) {
 2152                     /* start point has been removed due to y-coord fix => insert it */
 2153                     for (i = pti; i > 1; i--) {
 2154                         pts[i].x = pts[i-1].x;
 2155                         pts[i].y = pts[i-1].y;
 2156                     }
 2157                     pts[1].x = startx;
 2158                     pts[1].y = starty;
 2159                     pti++;
 2160                 }
 2161                 if (pts[pti-1].x != endx && pts[pti-1].y == endy) {
 2162                     /* end point has been removed due to y-coord fix => insert it */
 2163                     pts[pti].x = endx;
 2164                     pts[pti].y = endy;
 2165                     pti++;
 2166                 }
 2167             }
 2168             pts[pti].x = cx;
 2169             pts[pti].y = cy;
 2170             gdImageFilledPolygon(im, pts, pti+1, color);
 2171         }
 2172     }
 2173 }
 2174 
 2175 /*
 2176     Function: gdImageEllipse
 2177 */
 2178 BGD_DECLARE(void) gdImageEllipse(gdImagePtr im, int mx, int my, int w, int h, int c)
 2179 {
 2180     int x=0,mx1=0,mx2=0,my1=0,my2=0;
 2181     int64_t aq,bq,dx,dy,r,rx,ry,a,b;
 2182 
 2183     a=w>>1;
 2184     b=h>>1;
 2185     gdImageSetPixel(im,mx+a, my, c);
 2186     gdImageSetPixel(im,mx-a, my, c);
 2187     mx1 = mx-a;
 2188     my1 = my;
 2189     mx2 = mx+a;
 2190     my2 = my;
 2191 
 2192     aq = a * a;
 2193     bq = b * b;
 2194     dx = aq << 1;
 2195     dy = bq << 1;
 2196     r  = a * bq;
 2197     rx = r << 1;
 2198     ry = 0;
 2199     x = a;
 2200     while (x > 0) {
 2201         if (r > 0) {
 2202             my1++;
 2203             my2--;
 2204             ry +=dx;
 2205             r  -=ry;
 2206         }
 2207         if (r <= 0) {
 2208             x--;
 2209             mx1++;
 2210             mx2--;
 2211             rx -=dy;
 2212             r  +=rx;
 2213         }
 2214         gdImageSetPixel(im,mx1, my1, c);
 2215         gdImageSetPixel(im,mx1, my2, c);
 2216         gdImageSetPixel(im,mx2, my1, c);
 2217         gdImageSetPixel(im,mx2, my2, c);
 2218     }
 2219 }
 2220 
 2221 
 2222 /*
 2223     Function: gdImageFilledEllipse
 2224 */
 2225 BGD_DECLARE(void) gdImageFilledEllipse (gdImagePtr im, int mx, int my, int w, int h, int c)
 2226 {
 2227     int x=0,mx1=0,mx2=0,my1=0,my2=0;
 2228     int64_t aq,bq,dx,dy,r,rx,ry,a,b;
 2229     int i;
 2230     int old_y2;
 2231 
 2232     a=w>>1;
 2233     b=h>>1;
 2234 
 2235     for (x = mx-a; x <= mx+a; x++) {
 2236         gdImageSetPixel(im, x, my, c);
 2237     }
 2238 
 2239     mx1 = mx-a;
 2240     my1 = my;
 2241     mx2 = mx+a;
 2242     my2 = my;
 2243 
 2244     aq = a * a;
 2245     bq = b * b;
 2246     dx = aq << 1;
 2247     dy = bq << 1;
 2248     r  = a * bq;
 2249     rx = r << 1;
 2250     ry = 0;
 2251     x = a;
 2252     old_y2=-2;
 2253     while (x > 0) {
 2254         if (r > 0) {
 2255             my1++;
 2256             my2--;
 2257             ry +=dx;
 2258             r  -=ry;
 2259         }
 2260         if (r <= 0) {
 2261             x--;
 2262             mx1++;
 2263             mx2--;
 2264             rx -=dy;
 2265             r  +=rx;
 2266         }
 2267 
 2268         if(old_y2!=my2) {
 2269             for(i=mx1; i<=mx2; i++) {
 2270                 gdImageSetPixel(im,i,my2,c);
 2271                 gdImageSetPixel(im,i,my1,c);
 2272             }
 2273         }
 2274         old_y2 = my2;
 2275     }
 2276 }
 2277 
 2278 /*
 2279     Function: gdImageFillToBorder
 2280 */
 2281 BGD_DECLARE(void) gdImageFillToBorder (gdImagePtr im, int x, int y, int border, int color)
 2282 {
 2283     int lastBorder;
 2284     /* Seek left */
 2285     int leftLimit, rightLimit;
 2286     int i;
 2287     int restoreAlphaBleding;
 2288 
 2289     if (border < 0 || color < 0) {
 2290         /* Refuse to fill to a non-solid border */
 2291         return;
 2292     }
 2293 
 2294     if (!im->trueColor) {
 2295         if (color > (im->colorsTotal - 1) || border > (im->colorsTotal - 1)) {
 2296             return;
 2297         }
 2298     }
 2299 
 2300     leftLimit = (-1);
 2301 
 2302     restoreAlphaBleding = im->alphaBlendingFlag;
 2303     im->alphaBlendingFlag = 0;
 2304 
 2305     if (x >= im->sx) {
 2306         x = im->sx - 1;
 2307     } else if (x < 0) {
 2308         x = 0;
 2309     }
 2310     if (y >= im->sy) {
 2311         y = im->sy - 1;
 2312     } else if (y < 0) {
 2313         y = 0;
 2314     }
 2315 
 2316     for (i = x; (i >= 0); i--) {
 2317         if (gdImageGetPixel (im, i, y) == border) {
 2318             break;
 2319         }
 2320         gdImageSetPixel (im, i, y, color);
 2321         leftLimit = i;
 2322     }
 2323     if (leftLimit == (-1)) {
 2324         im->alphaBlendingFlag = restoreAlphaBleding;
 2325         return;
 2326     }
 2327     /* Seek right */
 2328     rightLimit = x;
 2329     for (i = (x + 1); (i < im->sx); i++) {
 2330         if (gdImageGetPixel (im, i, y) == border) {
 2331             break;
 2332         }
 2333         gdImageSetPixel (im, i, y, color);
 2334         rightLimit = i;
 2335     }
 2336     /* Look at lines above and below and start paints */
 2337     /* Above */
 2338     if (y > 0) {
 2339         lastBorder = 1;
 2340         for (i = leftLimit; (i <= rightLimit); i++) {
 2341             int c;
 2342             c = gdImageGetPixel (im, i, y - 1);
 2343             if (lastBorder) {
 2344                 if ((c != border) && (c != color)) {
 2345                     gdImageFillToBorder (im, i, y - 1, border, color);
 2346                     lastBorder = 0;
 2347                 }
 2348             } else if ((c == border) || (c == color)) {
 2349                 lastBorder = 1;
 2350             }
 2351         }
 2352     }
 2353     /* Below */
 2354     if (y < ((im->sy) - 1)) {
 2355         lastBorder = 1;
 2356         for (i = leftLimit; (i <= rightLimit); i++) {
 2357             int c = gdImageGetPixel (im, i, y + 1);
 2358             if (lastBorder) {
 2359                 if ((c != border) && (c != color)) {
 2360                     gdImageFillToBorder (im, i, y + 1, border, color);
 2361                     lastBorder = 0;
 2362                 }
 2363             } else if ((c == border) || (c == color)) {
 2364                 lastBorder = 1;
 2365             }
 2366         }
 2367     }
 2368     im->alphaBlendingFlag = restoreAlphaBleding;
 2369 }
 2370 
 2371 /*
 2372  * set the pixel at (x,y) and its 4-connected neighbors
 2373  * with the same pixel value to the new pixel value nc (new color).
 2374  * A 4-connected neighbor:  pixel above, below, left, or right of a pixel.
 2375  * ideas from comp.graphics discussions.
 2376  * For tiled fill, the use of a flag buffer is mandatory. As the tile image can
 2377  * contain the same color as the color to fill. To do not bloat normal filling
 2378  * code I added a 2nd private function.
 2379  */
 2380 
 2381 static int gdImageTileGet (gdImagePtr im, int x, int y)
 2382 {
 2383     int srcx, srcy;
 2384     int tileColor,p;
 2385     if (!im->tile) {
 2386         return -1;
 2387     }
 2388     srcx = x % gdImageSX(im->tile);
 2389     srcy = y % gdImageSY(im->tile);
 2390     p = gdImageGetPixel(im->tile, srcx, srcy);
 2391     if (p == im->tile->transparent) {
 2392         tileColor = im->transparent;
 2393     } else if (im->trueColor) {
 2394         if (im->tile->trueColor) {
 2395             tileColor = p;
 2396         } else {
 2397             tileColor = gdTrueColorAlpha( gdImageRed(im->tile,p), gdImageGreen(im->tile,p), gdImageBlue (im->tile,p), gdImageAlpha (im->tile,p));
 2398         }
 2399     } else {
 2400         if (im->tile->trueColor) {
 2401             tileColor = gdImageColorResolveAlpha(im, gdTrueColorGetRed (p), gdTrueColorGetGreen (p), gdTrueColorGetBlue (p), gdTrueColorGetAlpha (p));
 2402         } else {
 2403             tileColor = gdImageColorResolveAlpha(im, gdImageRed (im->tile,p), gdImageGreen (im->tile,p), gdImageBlue (im->tile,p), gdImageAlpha (im->tile,p));
 2404         }
 2405     }
 2406     return tileColor;
 2407 }
 2408 
 2409 
 2410 
 2411 /* horizontal segment of scan line y */
 2412 struct seg {
 2413     int y, xl, xr, dy;
 2414 };
 2415 
 2416 /* max depth of stack */
 2417 #define FILL_MAX ((int)(im->sy*im->sx)/4)
 2418 #define FILL_PUSH(Y, XL, XR, DY) \
 2419     if (sp<stack+FILL_MAX && Y+(DY)>=0 && Y+(DY)<wy2) \
 2420     {sp->y = Y; sp->xl = XL; sp->xr = XR; sp->dy = DY; sp++;}
 2421 
 2422 #define FILL_POP(Y, XL, XR, DY) \
 2423     {sp--; Y = sp->y+(DY = sp->dy); XL = sp->xl; XR = sp->xr;}
 2424 
 2425 static void _gdImageFillTiled(gdImagePtr im, int x, int y, int nc);
 2426 
 2427 /*
 2428     Function: gdImageFill
 2429 */
 2430 BGD_DECLARE(void) gdImageFill(gdImagePtr im, int x, int y, int nc)
 2431 {
 2432     int l, x1, x2, dy;
 2433     int oc;   /* old pixel value */
 2434     int wx2,wy2;
 2435 
 2436     int alphablending_bak;
 2437 
 2438     /* stack of filled segments */
 2439     /* struct seg stack[FILL_MAX],*sp = stack; */
 2440     struct seg *stack;
 2441     struct seg *sp;
 2442 
 2443     if (!im->trueColor && nc > (im->colorsTotal - 1)) {
 2444         return;
 2445     }
 2446 
 2447     alphablending_bak = im->alphaBlendingFlag;
 2448     im->alphaBlendingFlag = 0;
 2449 
 2450     if (nc==gdTiled) {
 2451         _gdImageFillTiled(im,x,y,nc);
 2452         im->alphaBlendingFlag = alphablending_bak;
 2453         return;
 2454     }
 2455 
 2456     wx2=im->sx;
 2457     wy2=im->sy;
 2458     oc = gdImageGetPixel(im, x, y);
 2459     if (oc==nc || x<0 || x>wx2 || y<0 || y>wy2) {
 2460         im->alphaBlendingFlag = alphablending_bak;
 2461         return;
 2462     }
 2463 
 2464     /* Do not use the 4 neighbors implementation with
 2465     * small images
 2466     */
 2467     if (im->sx < 4) {
 2468         int ix = x, iy = y, c;
 2469         do {
 2470             do {
 2471                 c = gdImageGetPixel(im, ix, iy);
 2472                 if (c != oc) {
 2473                     goto done;
 2474                 }
 2475                 gdImageSetPixel(im, ix, iy, nc);
 2476             } while(ix++ < (im->sx -1));
 2477             ix = x;
 2478         } while(iy++ < (im->sy -1));
 2479         goto done;
 2480     }
 2481 
 2482     if(overflow2(im->sy, im->sx)) {
 2483         return;
 2484     }
 2485 
 2486     if(overflow2(sizeof(struct seg), ((im->sy * im->sx) / 4))) {
 2487         return;
 2488     }
 2489 
 2490     stack = (struct seg *)gdMalloc(sizeof(struct seg) * ((int)(im->sy*im->sx)/4));
 2491     if (!stack) {
 2492         return;
 2493     }
 2494     sp = stack;
 2495 
 2496     /* required! */
 2497     FILL_PUSH(y,x,x,1);
 2498     /* seed segment (popped 1st) */
 2499     FILL_PUSH(y+1, x, x, -1);
 2500     while (sp>stack) {
 2501         FILL_POP(y, x1, x2, dy);
 2502 
 2503         for (x=x1; x>=0 && gdImageGetPixel(im,x, y)==oc; x--) {
 2504             gdImageSetPixel(im,x, y, nc);
 2505         }
 2506         if (x>=x1) {
 2507             goto skip;
 2508         }
 2509         l = x+1;
 2510 
 2511         /* leak on left? */
 2512         if (l<x1) {
 2513             FILL_PUSH(y, l, x1-1, -dy);
 2514         }
 2515         x = x1+1;
 2516         do {
 2517             for (; x<=wx2 && gdImageGetPixel(im,x, y)==oc; x++) {
 2518                 gdImageSetPixel(im, x, y, nc);
 2519             }
 2520             FILL_PUSH(y, l, x-1, dy);
 2521             /* leak on right? */
 2522             if (x>x2+1) {
 2523                 FILL_PUSH(y, x2+1, x-1, -dy);
 2524             }
 2525 skip:
 2526             for (x++; x<=x2 && (gdImageGetPixel(im, x, y)!=oc); x++);
 2527 
 2528             l = x;
 2529         } while (x<=x2);
 2530     }
 2531 
 2532     gdFree(stack);
 2533 
 2534 done:
 2535     im->alphaBlendingFlag = alphablending_bak;
 2536 }
 2537 
 2538 static void _gdImageFillTiled(gdImagePtr im, int x, int y, int nc)
 2539 {
 2540     int l, x1, x2, dy;
 2541     int oc;   /* old pixel value */
 2542     int wx2,wy2;
 2543     /* stack of filled segments */
 2544     struct seg *stack;
 2545     struct seg *sp;
 2546     char *pts;
 2547 
 2548     if (!im->tile) {
 2549         return;
 2550     }
 2551 
 2552     wx2=im->sx;
 2553     wy2=im->sy;
 2554 
 2555     if(overflow2(im->sy, im->sx)) {
 2556         return;
 2557     }
 2558 
 2559     if(overflow2(sizeof(struct seg), ((im->sy * im->sx) / 4))) {
 2560         return;
 2561     }
 2562 
 2563     pts = (char *) gdCalloc(im->sy * im->sx, sizeof(char));
 2564     if (!pts) {
 2565         return;
 2566     }
 2567 
 2568     stack = (struct seg *)gdMalloc(sizeof(struct seg) * ((int)(im->sy*im->sx)/4));
 2569     if (!stack) {
 2570         gdFree(pts);
 2571         return;
 2572     }
 2573     sp = stack;
 2574 
 2575     oc = gdImageGetPixel(im, x, y);
 2576 
 2577     /* required! */
 2578     FILL_PUSH(y,x,x,1);
 2579     /* seed segment (popped 1st) */
 2580     FILL_PUSH(y+1, x, x, -1);
 2581     while (sp>stack) {
 2582         FILL_POP(y, x1, x2, dy);
 2583         for (x=x1; x>=0 && (!pts[y + x*wy2] && gdImageGetPixel(im,x,y)==oc); x--) {
 2584             nc = gdImageTileGet(im,x,y);
 2585             pts[y + x*wy2]=1;
 2586             gdImageSetPixel(im,x, y, nc);
 2587         }
 2588         if (x>=x1) {
 2589             goto skip;
 2590         }
 2591         l = x+1;
 2592 
 2593         /* leak on left? */
 2594         if (l<x1) {
 2595             FILL_PUSH(y, l, x1-1, -dy);
 2596         }
 2597         x = x1+1;
 2598         do {
 2599             for (; x<wx2 && (!pts[y + x*wy2] && gdImageGetPixel(im,x, y)==oc) ; x++) {
 2600                 if (pts[y + x*wy2]) {
 2601                     /* we should never be here */
 2602                     break;
 2603                 }
 2604                 nc = gdImageTileGet(im,x,y);
 2605                 pts[y + x*wy2]=1;
 2606                 gdImageSetPixel(im, x, y, nc);
 2607             }
 2608             FILL_PUSH(y, l, x-1, dy);
 2609             /* leak on right? */
 2610             if (x>x2+1) {
 2611                 FILL_PUSH(y, x2+1, x-1, -dy);
 2612             }
 2613 skip:
 2614             for (x++; x<=x2 && (pts[y + x*wy2] || gdImageGetPixel(im,x, y)!=oc); x++);
 2615             l = x;
 2616         } while (x<=x2);
 2617     }
 2618 
 2619     gdFree(pts);
 2620     gdFree(stack);
 2621 }
 2622 
 2623 /**
 2624  * Function: gdImageRectangle
 2625  *
 2626  * Draws a rectangle.
 2627  *
 2628  * Parameters:
 2629  *   im    - The image.
 2630  *   x1    - The x-coordinate of one of the corners.
 2631  *   y1    - The y-coordinate of one of the corners.
 2632  *   x2    - The x-coordinate of another corner.
 2633  *   y2    - The y-coordinate of another corner.
 2634  *   color - The color.
 2635  *
 2636  * See also:
 2637  *   - <gdImageFilledRectangle>
 2638  */
 2639 BGD_DECLARE(void) gdImageRectangle (gdImagePtr im, int x1, int y1, int x2, int y2, int color)
 2640 {
 2641     int thick = im->thick;
 2642 
 2643     if (x1 == x2 && y1 == y2 && thick == 1) {
 2644         gdImageSetPixel(im, x1, y1, color);
 2645         return;
 2646     }
 2647 
 2648     if (y2 < y1) {
 2649         int t = y1;
 2650         y1 = y2;
 2651         y2 = t;
 2652     }
 2653 
 2654     if (x2 < x1) {
 2655         int t = x1;
 2656         x1 = x2;
 2657         x2 = t;
 2658     }
 2659 
 2660     if (thick > 1) {
 2661         int cx, cy, x1ul, y1ul, x2lr, y2lr;
 2662         int half = thick >> 1;
 2663         x1ul = x1 - half;
 2664         y1ul = y1 - half;
 2665 
 2666         x2lr = x2 + half;
 2667         y2lr = y2 + half;
 2668 
 2669         cy = y1ul + thick;
 2670         while (cy-- > y1ul) {
 2671             cx = x1ul - 1;
 2672             while (cx++ < x2lr) {
 2673                 gdImageSetPixel(im, cx, cy, color);
 2674             }
 2675         }
 2676 
 2677         cy = y2lr - thick;
 2678         while (cy++ < y2lr) {
 2679             cx = x1ul - 1;
 2680             while (cx++ < x2lr) {
 2681                 gdImageSetPixel(im, cx, cy, color);
 2682             }
 2683         }
 2684 
 2685         cy = y1ul + thick - 1;
 2686         while (cy++ < y2lr -thick) {
 2687             cx = x1ul - 1;
 2688             while (cx++ < x1ul + thick) {
 2689                 gdImageSetPixel(im, cx, cy, color);
 2690             }
 2691         }
 2692 
 2693         cy = y1ul + thick - 1;
 2694         while (cy++ < y2lr -thick) {
 2695             cx = x2lr - thick - 1;
 2696             while (cx++ < x2lr) {
 2697                 gdImageSetPixel(im, cx, cy, color);
 2698             }
 2699         }
 2700 
 2701         return;
 2702     } else {
 2703         if (x1 == x2 || y1 == y2) {
 2704             gdImageLine(im, x1, y1, x2, y2, color);
 2705         } else {
 2706             gdImageLine(im, x1, y1, x2, y1, color);
 2707             gdImageLine(im, x1, y2, x2, y2, color);
 2708             gdImageLine(im, x1, y1 + 1, x1, y2 - 1, color);
 2709             gdImageLine(im, x2, y1 + 1, x2, y2 - 1, color);
 2710         }
 2711     }
 2712 }
 2713 
 2714 static void _gdImageFilledHRectangle (gdImagePtr im, int x1, int y1, int x2, int y2,
 2715         int color)
 2716 {
 2717     int x, y;
 2718 
 2719     if (x1 == x2 && y1 == y2) {
 2720         gdImageSetPixel(im, x1, y1, color);
 2721         return;
 2722     }
 2723 
 2724     if (x1 > x2) {
 2725         x = x1;
 2726         x1 = x2;
 2727         x2 = x;
 2728     }
 2729 
 2730     if (y1 > y2) {
 2731         y = y1;
 2732         y1 = y2;
 2733         y2 = y;
 2734     }
 2735 
 2736     if (x1 < 0) {
 2737         x1 = 0;
 2738     }
 2739 
 2740     if (x2 >= gdImageSX(im)) {
 2741         x2 = gdImageSX(im) - 1;
 2742     }
 2743 
 2744     if (y1 < 0) {
 2745         y1 = 0;
 2746     }
 2747 
 2748     if (y2 >= gdImageSY(im)) {
 2749         y2 = gdImageSY(im) - 1;
 2750     }
 2751 
 2752     for (x = x1; (x <= x2); x++) {
 2753         for (y = y1; (y <= y2); y++) {
 2754             gdImageSetPixel (im, x, y, color);
 2755         }
 2756     }
 2757 }
 2758 
 2759 static void _gdImageFilledVRectangle (gdImagePtr im, int x1, int y1, int x2, int y2,
 2760         int color)
 2761 {
 2762     int x, y;
 2763 
 2764     if (x1 == x2 && y1 == y2) {
 2765         gdImageSetPixel(im, x1, y1, color);
 2766         return;
 2767     }
 2768 
 2769     if (x1 > x2) {
 2770         x = x1;
 2771         x1 = x2;
 2772         x2 = x;
 2773     }
 2774 
 2775     if (y1 > y2) {
 2776         y = y1;
 2777         y1 = y2;
 2778         y2 = y;
 2779     }
 2780 
 2781     if (x1 < 0) {
 2782         x1 = 0;
 2783     }
 2784 
 2785     if (x2 >= gdImageSX(im)) {
 2786         x2 = gdImageSX(im) - 1;
 2787     }
 2788 
 2789     if (y1 < 0) {
 2790         y1 = 0;
 2791     }
 2792 
 2793     if (y2 >= gdImageSY(im)) {
 2794         y2 = gdImageSY(im) - 1;
 2795     }
 2796 
 2797     for (y = y1; (y <= y2); y++) {
 2798         for (x = x1; (x <= x2); x++) {
 2799             gdImageSetPixel (im, x, y, color);
 2800         }
 2801     }
 2802 }
 2803 
 2804 /*
 2805     Function: gdImageFilledRectangle
 2806 */
 2807 BGD_DECLARE(void) gdImageFilledRectangle (gdImagePtr im, int x1, int y1, int x2, int y2,
 2808         int color)
 2809 {
 2810     _gdImageFilledVRectangle(im, x1, y1, x2, y2, color);
 2811 }
 2812 
 2813 /**
 2814  * Group: Cloning and Copying
 2815  */
 2816 
 2817 /**
 2818  * Function: gdImageClone
 2819  *
 2820  * Clones an image
 2821  *
 2822  * Creates an exact duplicate of the given image.
 2823  *
 2824  * Parameters:
 2825  *   src - The source image.
 2826  *
 2827  * Returns:
 2828  *   The cloned image on success, NULL on failure.
 2829  */
 2830 BGD_DECLARE(gdImagePtr) gdImageClone (gdImagePtr src) {
 2831     gdImagePtr dst;
 2832     register int i, x;
 2833 
 2834     if (src->trueColor) {
 2835         dst = gdImageCreateTrueColor(src->sx , src->sy);
 2836     } else {
 2837         dst = gdImageCreate(src->sx , src->sy);
 2838     }
 2839 
 2840     if (dst == NULL) {
 2841         return NULL;
 2842     }
 2843 
 2844     if (src->trueColor == 0) {
 2845         dst->colorsTotal = src->colorsTotal;
 2846         for (i = 0; i < gdMaxColors; i++) {
 2847             dst->red[i]   = src->red[i];
 2848             dst->green[i] = src->green[i];
 2849             dst->blue[i]  = src->blue[i];
 2850             dst->alpha[i] = src->alpha[i];
 2851             dst->open[i]  = src->open[i];
 2852         }
 2853         for (i = 0; i < src->sy; i++) {
 2854             for (x = 0; x < src->sx; x++) {
 2855                 dst->pixels[i][x] = src->pixels[i][x];
 2856             }
 2857         }
 2858     } else {
 2859         for (i = 0; i < src->sy; i++) {
 2860             for (x = 0; x < src->sx; x++) {
 2861                 dst->tpixels[i][x] = src->tpixels[i][x];
 2862             }
 2863         }
 2864     }
 2865 
 2866     dst->interlace   = src->interlace;
 2867 
 2868     dst->alphaBlendingFlag = src->alphaBlendingFlag;
 2869     dst->saveAlphaFlag     = src->saveAlphaFlag;
 2870     dst->AA                = src->AA;
 2871     dst->AA_color          = src->AA_color;
 2872     dst->AA_dont_blend     = src->AA_dont_blend;
 2873 
 2874     dst->cx1 = src->cx1;
 2875     dst->cy1 = src->cy1;
 2876     dst->cx2 = src->cx2;
 2877     dst->cy2 = src->cy2;
 2878 
 2879     dst->res_x = src->res_x;
 2880     dst->res_y = src->res_y;
 2881 
 2882     dst->paletteQuantizationMethod     = src->paletteQuantizationMethod;
 2883     dst->paletteQuantizationSpeed      = src->paletteQuantizationSpeed;
 2884     dst->paletteQuantizationMinQuality = src->paletteQuantizationMinQuality;
 2885     dst->paletteQuantizationMinQuality = src->paletteQuantizationMinQuality;
 2886 
 2887     dst->interpolation_id = src->interpolation_id;
 2888     dst->interpolation    = src->interpolation;
 2889 
 2890     if (src->brush) {
 2891         dst->brush = gdImageClone(src->brush);
 2892     }
 2893 
 2894     if (src->tile) {
 2895         dst->tile = gdImageClone(src->tile);
 2896     }
 2897 
 2898     if (src->style) {
 2899         gdImageSetStyle(dst, src->style, src->styleLength);
 2900         dst->stylePos = src->stylePos;
 2901     }
 2902 
 2903     for (i = 0; i < gdMaxColors; i++) {
 2904         dst->brushColorMap[i] = src->brushColorMap[i];
 2905         dst->tileColorMap[i] = src->tileColorMap[i];
 2906     }
 2907 
 2908     if (src->polyAllocated > 0) {
 2909         dst->polyAllocated = src->polyAllocated;
 2910         for (i = 0; i < src->polyAllocated; i++) {
 2911             dst->polyInts[i] = src->polyInts[i];
 2912         }
 2913     }
 2914 
 2915     return dst;
 2916 }
 2917 
 2918 /**
 2919  * Function: gdImageCopy
 2920  *
 2921  * Copy an area of an image to another image
 2922  *
 2923  * Parameters:
 2924  *   dst  - The destination image.
 2925  *   src  - The source image.
 2926  *   dstX - The x-coordinate of the upper left corner to copy to.
 2927  *   dstY - The y-coordinate of the upper left corner to copy to.
 2928  *   srcX - The x-coordinate of the upper left corner to copy from.
 2929  *   srcY - The y-coordinate of the upper left corner to copy from.
 2930  *   w    - The width of the area to copy.
 2931  *   h    - The height of the area to copy.
 2932  *
 2933  * See also:
 2934  *   - <gdImageCopyMerge>
 2935  *   - <gdImageCopyMergeGray>
 2936  */
 2937 BGD_DECLARE(void) gdImageCopy (gdImagePtr dst, gdImagePtr src, int dstX, int dstY, int srcX,
 2938                                int srcY, int w, int h)
 2939 {
 2940     int c;
 2941     int x, y;
 2942     int tox, toy;
 2943     int i;
 2944     int colorMap[gdMaxColors];
 2945 
 2946     if (dst->trueColor) {
 2947         /* 2.0: much easier when the destination is truecolor. */
 2948         /* 2.0.10: needs a transparent-index check that is still valid if
 2949          *          * the source is not truecolor. Thanks to Frank Warmerdam.
 2950          */
 2951 
 2952         if (src->trueColor) {
 2953             for (y = 0; (y < h); y++) {
 2954                 for (x = 0; (x < w); x++) {
 2955                     int c = gdImageGetTrueColorPixel (src, srcX + x, srcY + y);
 2956                     if (c != src->transparent) {
 2957                         gdImageSetPixel (dst, dstX + x, dstY + y, c);
 2958                     }
 2959                 }
 2960             }
 2961         } else {
 2962             /* source is palette based */
 2963             for (y = 0; (y < h); y++) {
 2964                 for (x = 0; (x < w); x++) {
 2965                     int c = gdImageGetPixel (src, srcX + x, srcY + y);
 2966                     if (c != src->transparent) {
 2967                         gdImageSetPixel(dst, dstX + x, dstY + y, gdTrueColorAlpha(src->red[c], src->green[c], src->blue[c], src->alpha[c]));
 2968                     }
 2969                 }
 2970             }
 2971         }
 2972         return;
 2973     }
 2974 
 2975     for (i = 0; (i < gdMaxColors); i++) {
 2976         colorMap[i] = (-1);
 2977     }
 2978     toy = dstY;
 2979     for (y = srcY; (y < (srcY + h)); y++) {
 2980         tox = dstX;
 2981         for (x = srcX; (x < (srcX + w)); x++) {
 2982             int nc;
 2983             int mapTo;
 2984             c = gdImageGetPixel (src, x, y);
 2985             /* Added 7/24/95: support transparent copies */
 2986             if (gdImageGetTransparent (src) == c) {
 2987                 tox++;
 2988                 continue;
 2989             }
 2990             /* Have we established a mapping for this color? */
 2991             if (src->trueColor) {
 2992                 /* 2.05: remap to the palette available in the
 2993                  destination image. This is slow and
 2994                  works badly, but it beats crashing! Thanks
 2995                  to Padhrig McCarthy. */
 2996                 mapTo = gdImageColorResolveAlpha (dst,
 2997                                                   gdTrueColorGetRed (c),
 2998                                                   gdTrueColorGetGreen (c),
 2999                                                   gdTrueColorGetBlue (c),
 3000                                                   gdTrueColorGetAlpha (c));
 3001             } else if (colorMap[c] == (-1)) {
 3002                 /* If it's the same image, mapping is trivial */
 3003                 if (dst == src) {
 3004                     nc = c;
 3005                 } else {
 3006                     /* Get best match possible. This
 3007                        function never returns error. */
 3008                     nc = gdImageColorResolveAlpha (dst,
 3009                                                    src->red[c], src->green[c],
 3010                                                    src->blue[c], src->alpha[c]);
 3011                 }
 3012                 colorMap[c] = nc;
 3013                 mapTo = colorMap[c];
 3014             } else {
 3015                 mapTo = colorMap[c];
 3016             }
 3017             gdImageSetPixel (dst, tox, toy, mapTo);
 3018             tox++;
 3019         }
 3020         toy++;
 3021     }
 3022 }
 3023 
 3024 /**
 3025  * Function: gdImageCopyMerge
 3026  *
 3027  * Copy an area of an image to another image ignoring alpha
 3028  *
 3029  * The source area will be copied to the destination are by merging the pixels.
 3030  *
 3031  * Note:
 3032  *   This function is a substitute for real alpha channel operations,
 3033  *   so it doesn't pay attention to the alpha channel.
 3034  *
 3035  * Parameters:
 3036  *   dst  - The destination image.
 3037  *   src  - The source image.
 3038  *   dstX - The x-coordinate of the upper left corner to copy to.
 3039  *   dstY - The y-coordinate of the upper left corner to copy to.
 3040  *   srcX - The x-coordinate of the upper left corner to copy from.
 3041  *   srcY - The y-coordinate of the upper left corner to copy from.
 3042  *   w    - The width of the area to copy.
 3043  *   h    - The height of the area to copy.
 3044  *   pct  - The percentage in range 0..100.
 3045  *
 3046  * See also:
 3047  *   - <gdImageCopy>
 3048  *   - <gdImageCopyMergeGray>
 3049  */
 3050 BGD_DECLARE(void) gdImageCopyMerge (gdImagePtr dst, gdImagePtr src, int dstX, int dstY,
 3051                                     int srcX, int srcY, int w, int h, int pct)
 3052 {
 3053 
 3054     int c, dc;
 3055     int x, y;
 3056     int tox, toy;
 3057     int ncR, ncG, ncB;
 3058     toy = dstY;
 3059     for (y = srcY; (y < (srcY + h)); y++) {
 3060         tox = dstX;
 3061         for (x = srcX; (x < (srcX + w)); x++) {
 3062             int nc;
 3063             c = gdImageGetPixel (src, x, y);
 3064             /* Added 7/24/95: support transparent copies */
 3065             if (gdImageGetTransparent (src) == c) {
 3066                 tox++;
 3067                 continue;
 3068             }
 3069             /* If it's the same image, mapping is trivial */
 3070             if (dst == src) {
 3071                 nc = c;
 3072             } else {
 3073                 dc = gdImageGetPixel (dst, tox, toy);
 3074 
 3075                 ncR = gdImageRed (src, c) * (pct / 100.0)
 3076                       + gdImageRed (dst, dc) * ((100 - pct) / 100.0);
 3077                 ncG = gdImageGreen (src, c) * (pct / 100.0)
 3078                       + gdImageGreen (dst, dc) * ((100 - pct) / 100.0);
 3079                 ncB = gdImageBlue (src, c) * (pct / 100.0)
 3080                       + gdImageBlue (dst, dc) * ((100 - pct) / 100.0);
 3081 
 3082                 /* Find a reasonable color */
 3083                 nc = gdImageColorResolve (dst, ncR, ncG, ncB);
 3084             }
 3085             gdImageSetPixel (dst, tox, toy, nc);
 3086             tox++;
 3087         }
 3088         toy++;
 3089     }
 3090 }
 3091 
 3092 /**
 3093  * Function: gdImageCopyMergeGray
 3094  *
 3095  * Copy an area of an image to another image ignoring alpha
 3096  *
 3097  * The source area will be copied to the grayscaled destination area by merging
 3098  * the pixels.
 3099  *
 3100  * Note:
 3101  *   This function is a substitute for real alpha channel operations,
 3102  *   so it doesn't pay attention to the alpha channel.
 3103  *
 3104  * Parameters:
 3105  *   dst  - The destination image.
 3106  *   src  - The source image.
 3107  *   dstX - The x-coordinate of the upper left corner to copy to.
 3108  *   dstY - The y-coordinate of the upper left corner to copy to.
 3109  *   srcX - The x-coordinate of the upper left corner to copy from.
 3110  *   srcY - The y-coordinate of the upper left corner to copy from.
 3111  *   w    - The width of the area to copy.
 3112  *   h    - The height of the area to copy.
 3113  *   pct  - The percentage of the source color intensity in range 0..100.
 3114  *
 3115  * See also:
 3116  *   - <gdImageCopy>
 3117  *   - <gdImageCopyMerge>
 3118  */
 3119 BGD_DECLARE(void) gdImageCopyMergeGray (gdImagePtr dst, gdImagePtr src, int dstX, int dstY,
 3120                                         int srcX, int srcY, int w, int h, int pct)
 3121 {
 3122 
 3123     int c, dc;
 3124     int x, y;
 3125     int tox, toy;
 3126     int ncR, ncG, ncB;
 3127     float g;
 3128     toy = dstY;
 3129     for (y = srcY; (y < (srcY + h)); y++) {
 3130         tox = dstX;
 3131         for (x = srcX; (x < (srcX + w)); x++) {
 3132             int nc;
 3133             c = gdImageGetPixel (src, x, y);
 3134             /* Added 7/24/95: support transparent copies */
 3135             if (gdImageGetTransparent (src) == c) {
 3136                 tox++;
 3137                 continue;
 3138             }
 3139             /*
 3140              * If it's the same image, mapping is NOT trivial since we
 3141              * merge with greyscale target, but if pct is 100, the grey
 3142              * value is not used, so it becomes trivial. pjw 2.0.12.
 3143              */
 3144             if (dst == src && pct == 100) {
 3145                 nc = c;
 3146             } else {
 3147                 dc = gdImageGetPixel (dst, tox, toy);
 3148                 g = 0.29900 * gdImageRed(dst, dc)
 3149                     + 0.58700 * gdImageGreen(dst, dc) + 0.11400 * gdImageBlue(dst, dc);
 3150 
 3151                 ncR = gdImageRed (src, c) * (pct / 100.0)
 3152                       + g * ((100 - pct) / 100.0);
 3153                 ncG = gdImageGreen (src, c) * (pct / 100.0)
 3154                       + g * ((100 - pct) / 100.0);
 3155                 ncB = gdImageBlue (src, c) * (pct / 100.0)
 3156                       + g * ((100 - pct) / 100.0);
 3157 
 3158                 /* First look for an exact match */
 3159                 nc = gdImageColorExact (dst, ncR, ncG, ncB);
 3160                 if (nc == (-1)) {
 3161                     /* No, so try to allocate it */
 3162                     nc = gdImageColorAllocate (dst, ncR, ncG, ncB);
 3163                     /* If we're out of colors, go for the
 3164                        closest color */
 3165                     if (nc == (-1)) {
 3166                         nc = gdImageColorClosest (dst, ncR, ncG, ncB);
 3167                     }
 3168                 }
 3169             }
 3170             gdImageSetPixel (dst, tox, toy, nc);
 3171             tox++;
 3172         }
 3173         toy++;
 3174     }
 3175 }
 3176 
 3177 /**
 3178  * Function: gdImageCopyResized
 3179  *
 3180  * Copy a resized area from an image to another image
 3181  *
 3182  * If the source and destination area differ in size, the area will be resized
 3183  * using nearest-neighbor interpolation.
 3184  *
 3185  * Parameters:
 3186  *   dst  - The destination image.
 3187  *   src  - The source image.
 3188  *   dstX - The x-coordinate of the upper left corner to copy to.
 3189  *   dstY - The y-coordinate of the upper left corner to copy to.
 3190  *   srcX - The x-coordinate of the upper left corner to copy from.
 3191  *   srcY - The y-coordinate of the upper left corner to copy from.
 3192  *   dstW - The width of the area to copy to.
 3193  *   dstH - The height of the area to copy to.
 3194  *   srcW - The width of the area to copy from.
 3195  *   srcH - The height of the area to copy from.
 3196  *
 3197  * See also:
 3198  *   - <gdImageCopyResampled>
 3199  *   - <gdImageScale>
 3200  */
 3201 BGD_DECLARE(void) gdImageCopyResized (gdImagePtr dst, gdImagePtr src, int dstX, int dstY,
 3202                                       int srcX, int srcY, int dstW, int dstH, int srcW,
 3203                                       int srcH)
 3204 {
 3205     int c;
 3206     int x, y;
 3207     int tox, toy;
 3208     int ydest;
 3209     int i;
 3210     int colorMap[gdMaxColors];
 3211     /* Stretch vectors */
 3212     int *stx;
 3213     int *sty;
 3214     /* We only need to use floating point to determine the correct
 3215        stretch vector for one line's worth. */
 3216     if (overflow2(sizeof (int), srcW)) {
 3217         return;
 3218     }
 3219     if (overflow2(sizeof (int), srcH)) {
 3220         return;
 3221     }
 3222     stx = (int *) gdMalloc (sizeof (int) * srcW);
 3223     if (!stx) {
 3224         return;
 3225     }
 3226 
 3227     sty = (int *) gdMalloc (sizeof (int) * srcH);
 3228     if (!sty) {
 3229         gdFree(stx);
 3230         return;
 3231     }
 3232 
 3233     /* Fixed by Mao Morimoto 2.0.16 */
 3234     for (i = 0; (i < srcW); i++) {
 3235         stx[i] = dstW * (i + 1) / srcW - dstW * i / srcW;
 3236     }
 3237     for (i = 0; (i < srcH); i++) {
 3238         sty[i] = dstH * (i + 1) / srcH - dstH * i / srcH;
 3239     }
 3240     for (i = 0; (i < gdMaxColors); i++) {
 3241         colorMap[i] = (-1);
 3242     }
 3243     toy = dstY;
 3244     for (y = srcY; (y < (srcY + srcH)); y++) {
 3245         for (ydest = 0; (ydest < sty[y - srcY]); ydest++) {
 3246             tox = dstX;
 3247             for (x = srcX; (x < (srcX + srcW)); x++) {
 3248                 int nc = 0;
 3249                 int mapTo;
 3250                 if (!stx[x - srcX]) {
 3251                     continue;
 3252                 }
 3253                 if (dst->trueColor) {
 3254                     /* 2.0.9: Thorben Kundinger: Maybe the source image is not
 3255                        a truecolor image */
 3256                     if (!src->trueColor) {
 3257                         int tmp = gdImageGetPixel (src, x, y);
 3258                         mapTo = gdImageGetTrueColorPixel (src, x, y);
 3259                         if (gdImageGetTransparent (src) == tmp) {
 3260                             /* 2.0.21, TK: not tox++ */
 3261                             tox += stx[x - srcX];
 3262                             continue;
 3263                         }
 3264                     } else {
 3265                         /* TK: old code follows */
 3266                         mapTo = gdImageGetTrueColorPixel (src, x, y);
 3267                         /* Added 7/24/95: support transparent copies */
 3268                         if (gdImageGetTransparent (src) == mapTo) {
 3269                             /* 2.0.21, TK: not tox++ */
 3270                             tox += stx[x - srcX];
 3271                             continue;
 3272                         }
 3273                     }
 3274                 } else {
 3275                     c = gdImageGetPixel (src, x, y);
 3276                     /* Added 7/24/95: support transparent copies */
 3277                     if (gdImageGetTransparent (src) == c) {
 3278                         tox += stx[x - srcX];
 3279                         continue;
 3280                     }
 3281                     if (src->trueColor) {
 3282                         /* Remap to the palette available in the
 3283                            destination image. This is slow and
 3284                            works badly. */
 3285                         mapTo = gdImageColorResolveAlpha (dst,
 3286                                                           gdTrueColorGetRed (c),
 3287                                                           gdTrueColorGetGreen
 3288                                                           (c),
 3289                                                           gdTrueColorGetBlue
 3290                                                           (c),
 3291                                                           gdTrueColorGetAlpha
 3292                                                           (c));
 3293                     } else {
 3294                         /* Have we established a mapping for this color? */
 3295                         if (colorMap[c] == (-1)) {
 3296                             /* If it's the same image, mapping is trivial */
 3297                             if (dst == src) {
 3298                                 nc = c;
 3299                             } else {
 3300                                 /* Find or create the best match */
 3301                                 /* 2.0.5: can't use gdTrueColorGetRed, etc with palette */
 3302                                 nc = gdImageColorResolveAlpha (dst,
 3303                                                                gdImageRed (src,
 3304                                                                        c),
 3305                                                                gdImageGreen
 3306                                                                (src, c),
 3307                                                                gdImageBlue (src,
 3308                                                                        c),
 3309                                                                gdImageAlpha
 3310                                                                (src, c));
 3311                             }
 3312                             colorMap[c] = nc;
 3313                         }
 3314                         mapTo = colorMap[c];
 3315                     }
 3316                 }
 3317                 for (i = 0; (i < stx[x - srcX]); i++) {
 3318                     gdImageSetPixel (dst, tox, toy, mapTo);
 3319                     tox++;
 3320                 }
 3321             }
 3322             toy++;
 3323         }
 3324     }
 3325     gdFree (stx);
 3326     gdFree (sty);
 3327 }
 3328 
 3329 /**
 3330  * Function: gdImageCopyRotated
 3331  *
 3332  * Copy a rotated area from an image to another image
 3333  *
 3334  * The area is counter-clockwise rotated using nearest-neighbor interpolation.
 3335  *
 3336  * Parameters:
 3337  *   dst   - The destination image.
 3338  *   src   - The source image.
 3339  *   dstX  - The x-coordinate of the center of the area to copy to.
 3340  *   dstY  - The y-coordinate of the center of the area to copy to.
 3341  *   srcX  - The x-coordinate of the upper left corner to copy from.
 3342  *   srcY  - The y-coordinate of the upper left corner to copy from.
 3343  *   srcW  - The width of the area to copy from.
 3344  *   srcH  - The height of the area to copy from.
 3345  *   angle - The angle in degrees.
 3346  *
 3347  * See also:
 3348  *   - <gdImageRotateInterpolated>
 3349  */
 3350 BGD_DECLARE(void) gdImageCopyRotated (gdImagePtr dst,
 3351                                       gdImagePtr src,
 3352                                       double dstX, double dstY,
 3353                                       int srcX, int srcY,
 3354                                       int srcWidth, int srcHeight, int angle)
 3355 {
 3356     double dx, dy;
 3357     double radius = sqrt (srcWidth * srcWidth + srcHeight * srcHeight);
 3358     double aCos = cos (angle * .0174532925);
 3359     double aSin = sin (angle * .0174532925);
 3360     double scX = srcX + ((double) srcWidth) / 2;
 3361     double scY = srcY + ((double) srcHeight) / 2;
 3362     int cmap[gdMaxColors];
 3363     int i;
 3364 
 3365     /*
 3366          2.0.34: transparency preservation. The transparentness of
 3367          the transparent color is more important than its hue.
 3368     */
 3369     if (src->transparent != -1) {
 3370         if (dst->transparent == -1) {
 3371             dst->transparent = src->transparent;
 3372         }
 3373     }
 3374 
 3375     for (i = 0; (i < gdMaxColors); i++) {
 3376         cmap[i] = (-1);
 3377     }
 3378     for (dy = dstY - radius; (dy <= dstY + radius); dy++) {
 3379         for (dx = dstX - radius; (dx <= dstX + radius); dx++) {
 3380             double sxd = (dx - dstX) * aCos - (dy - dstY) * aSin;
 3381             double syd = (dy - dstY) * aCos + (dx - dstX) * aSin;
 3382             int sx = sxd + scX;
 3383             int sy = syd + scY;
 3384             if ((sx >= srcX) && (sx < srcX + srcWidth) &&
 3385                     (sy >= srcY) && (sy < srcY + srcHeight)) {
 3386                 int c = gdImageGetPixel (src, sx, sy);
 3387                 /* 2.0.34: transparency wins */
 3388                 if (c == src->transparent) {
 3389                     gdImageSetPixel (dst, dx, dy, dst->transparent);
 3390                 } else if (!src->trueColor) {
 3391                     /* Use a table to avoid an expensive
 3392                        lookup on every single pixel */
 3393                     if (cmap[c] == -1) {
 3394                         cmap[c] = gdImageColorResolveAlpha (dst,
 3395                                                             gdImageRed (src, c),
 3396                                                             gdImageGreen (src,
 3397                                                                     c),
 3398                                                             gdImageBlue (src,
 3399                                                                     c),
 3400                                                             gdImageAlpha (src,
 3401                                                                     c));
 3402                     }
 3403                     gdImageSetPixel (dst, dx, dy, cmap[c]);
 3404                 } else {
 3405                     gdImageSetPixel (dst,
 3406                                      dx, dy,
 3407                                      gdImageColorResolveAlpha (dst,
 3408                                              gdImageRed (src,
 3409                                                          c),
 3410                                              gdImageGreen
 3411                                              (src, c),
 3412                                              gdImageBlue (src,
 3413                                                           c),
 3414                                              gdImageAlpha
 3415                                              (src, c)));
 3416                 }
 3417             }
 3418         }
 3419     }
 3420 }
 3421 
 3422 /* When gd 1.x was first created, floating point was to be avoided.
 3423    These days it is often faster than table lookups or integer
 3424    arithmetic. The routine below is shamelessly, gloriously
 3425    floating point. TBB */
 3426 
 3427 /* 2.0.10: cast instead of floor() yields 35% performance improvement.
 3428     Thanks to John Buckman. */
 3429 
 3430 #define floor2(exp) ((long) exp)
 3431 /*#define floor2(exp) floor(exp)*/
 3432 
 3433 /**
 3434  * Function: gdImageCopyResampled
 3435  *
 3436  * Copy a resampled area from an image to another image
 3437  *
 3438  * If the source and destination area differ in size, the area will be resized
 3439  * using bilinear interpolation for truecolor images, and nearest-neighbor
 3440  * interpolation for palette images.
 3441  *
 3442  * Parameters:
 3443  *   dst  - The destination image.
 3444  *   src  - The source image.
 3445  *   dstX - The x-coordinate of the upper left corner to copy to.
 3446  *   dstY - The y-coordinate of the upper left corner to copy to.
 3447  *   srcX - The x-coordinate of the upper left corner to copy from.
 3448  *   srcY - The y-coordinate of the upper left corner to copy from.
 3449  *   dstW - The width of the area to copy to.
 3450  *   dstH - The height of the area to copy to.
 3451  *   srcW - The width of the area to copy from.
 3452  *   srcH - The height of the area to copy from.
 3453  *
 3454  * See also:
 3455  *   - <gdImageCopyResized>
 3456  *   - <gdImageScale>
 3457  */
 3458 BGD_DECLARE(void) gdImageCopyResampled (gdImagePtr dst,
 3459                                         gdImagePtr src,
 3460                                         int dstX, int dstY,
 3461                                         int srcX, int srcY,
 3462                                         int dstW, int dstH, int srcW, int srcH)
 3463 {
 3464     int x, y;
 3465     if (!dst->trueColor) {
 3466         gdImageCopyResized (dst, src, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH);
 3467         return;
 3468     }
 3469     for (y = dstY; (y < dstY + dstH); y++) {
 3470         for (x = dstX; (x < dstX + dstW); x++) {
 3471             float sy1, sy2, sx1, sx2;
 3472             float sx, sy;
 3473             float spixels = 0.0;
 3474             float red = 0.0, green = 0.0, blue = 0.0, alpha = 0.0;
 3475             float alpha_factor, alpha_sum = 0.0, contrib_sum = 0.0;
 3476             sy1 = ((float)(y - dstY)) * (float)srcH / (float)dstH;
 3477             sy2 = ((float)(y + 1 - dstY)) * (float) srcH / (float) dstH;
 3478             sy = sy1;
 3479             do {
 3480                 float yportion;
 3481                 if (floorf(sy) == floorf(sy1)) {
 3482                     yportion = 1.0 - (sy - floorf(sy));
 3483                     if (yportion > sy2 - sy1) {
 3484                         yportion = sy2 - sy1;
 3485                     }
 3486                     sy = floorf(sy);
 3487                 } else if (sy == floorf(sy2)) {
 3488                     yportion = sy2 - floorf(sy2);
 3489                 } else {
 3490                     yportion = 1.0;
 3491                 }
 3492                 sx1 = ((float)(x - dstX)) * (float) srcW / dstW;
 3493                 sx2 = ((float)(x + 1 - dstX)) * (float) srcW / dstW;
 3494                 sx = sx1;
 3495                 do {
 3496                     float xportion;
 3497                     float pcontribution;
 3498                     int p;
 3499                     if (floorf(sx) == floorf(sx1)) {
 3500                         xportion = 1.0 - (sx - floorf(sx));
 3501                         if (xportion > sx2 - sx1) {
 3502                             xportion = sx2 - sx1;
 3503                         }
 3504                         sx = floorf(sx);
 3505                     } else if (sx == floorf(sx2)) {
 3506                         xportion = sx2 - floorf(sx2);
 3507                     } else {
 3508                         xportion = 1.0;
 3509                     }
 3510                     pcontribution = xportion * yportion;
 3511                     p = gdImageGetTrueColorPixel(src, (int) sx + srcX, (int) sy + srcY);
 3512 
 3513                     alpha_factor = ((gdAlphaMax - gdTrueColorGetAlpha(p))) * pcontribution;
 3514                     red += gdTrueColorGetRed (p) * alpha_factor;
 3515                     green += gdTrueColorGetGreen (p) * alpha_factor;
 3516                     blue += gdTrueColorGetBlue (p) * alpha_factor;
 3517                     alpha += gdTrueColorGetAlpha (p) * pcontribution;
 3518                     alpha_sum += alpha_factor;
 3519                     contrib_sum += pcontribution;
 3520                     spixels += xportion * yportion;
 3521                     sx += 1.0;
 3522                 }
 3523                 while (sx < sx2);
 3524                 sy += 1.0f;
 3525             }
 3526             while (sy < sy2);
 3527 
 3528             if (spixels != 0.0) {
 3529                 red /= spixels;
 3530                 green /= spixels;
 3531                 blue /= spixels;
 3532                 alpha /= spixels;
 3533             }
 3534             if ( alpha_sum != 0.0) {
 3535                 if( contrib_sum != 0.0) {
 3536                     alpha_sum /= contrib_sum;
 3537                 }
 3538                 red /= alpha_sum;
 3539                 green /= alpha_sum;
 3540                 blue /= alpha_sum;
 3541             }
 3542             /* Clamping to allow for rounding errors above */
 3543             if (red > 255.0) {
 3544                 red = 255.0;
 3545             }
 3546             if (green > 255.0) {
 3547                 green = 255.0;
 3548             }
 3549             if (blue > 255.0f) {
 3550                 blue = 255.0;
 3551             }
 3552             if (alpha > gdAlphaMax) {
 3553                 alpha = gdAlphaMax;
 3554             }
 3555             gdImageSetPixel(dst, x, y, gdTrueColorAlpha ((int) red, (int) green, (int) blue, (int) alpha));
 3556         }
 3557     }
 3558 }
 3559 
 3560 /**
 3561  * Group: Polygons
 3562  */
 3563 
 3564 /**
 3565  * Function: gdImagePolygon
 3566  *
 3567  * Draws a closed polygon
 3568  *
 3569  * Parameters:
 3570  *   im - The image.
 3571  *   p  - The vertices as array of <gdPoint>s.
 3572  *   n  - The number of vertices.
 3573  *   c  - The color.
 3574  *
 3575  * See also:
 3576  *   - <gdImageOpenPolygon>
 3577  *   - <gdImageFilledPolygon>
 3578  */
 3579 BGD_DECLARE(void) gdImagePolygon (gdImagePtr im, gdPointPtr p, int n, int c)
 3580 {
 3581     if (n <= 0) {
 3582         return;
 3583     }
 3584 
 3585 
 3586     gdImageLine (im, p->x, p->y, p[n - 1].x, p[n - 1].y, c);
 3587     gdImageOpenPolygon (im, p, n, c);
 3588 }
 3589 
 3590 /**
 3591  * Function: gdImageOpenPolygon
 3592  *
 3593  * Draws an open polygon
 3594  *
 3595  * Parameters:
 3596  *   im - The image.
 3597  *   p  - The vertices as array of <gdPoint>s.
 3598  *   n  - The number of vertices.
 3599  *   c  - The color
 3600  *
 3601  * See also:
 3602  *   - <gdImagePolygon>
 3603  */
 3604 BGD_DECLARE(void) gdImageOpenPolygon (gdImagePtr im, gdPointPtr p, int n, int c)
 3605 {
 3606     int i;
 3607     int lx, ly;
 3608     if (n <= 0) {
 3609         return;
 3610     }
 3611 
 3612 
 3613     lx = p->x;
 3614     ly = p->y;
 3615     for (i = 1; (i < n); i++) {
 3616         p++;
 3617         gdImageLine (im, lx, ly, p->x, p->y, c);
 3618         lx = p->x;
 3619         ly = p->y;
 3620     }
 3621 
 3622 }
 3623 
 3624 /* THANKS to Kirsten Schulz for the polygon fixes! */
 3625 
 3626 /* The intersection finding technique of this code could be improved  */
 3627 /* by remembering the previous intertersection, and by using the slope. */
 3628 /* That could help to adjust intersections  to produce a nice */
 3629 /* interior_extrema. */
 3630 
 3631 /**
 3632  * Function: gdImageFilledPolygon
 3633  *
 3634  * Draws a filled polygon
 3635  *
 3636  * The polygon is filled using the even-odd fillrule what can leave unfilled
 3637  * regions inside of self-intersecting polygons. This behavior might change in
 3638  * a future version.
 3639  *
 3640  * Parameters:
 3641  *   im - The image.
 3642  *   p  - The vertices as array of <gdPoint>s.
 3643  *   n  - The number of vertices.
 3644  *   c  - The color
 3645  *
 3646  * See also:
 3647  *   - <gdImagePolygon>
 3648  */
 3649 BGD_DECLARE(void) gdImageFilledPolygon (gdImagePtr im, gdPointPtr p, int n, int c)
 3650 {
 3651     int i;
 3652     int j;
 3653     int index;
 3654     int y;
 3655     int miny, maxy, pmaxy;
 3656     int x1, y1;
 3657     int x2, y2;
 3658     int ind1, ind2;
 3659     int ints;
 3660     int fill_color;
 3661     if (n <= 0) {
 3662         return;
 3663     }
 3664 
 3665     if (c == gdAntiAliased) {
 3666         fill_color = im->AA_color;
 3667     } else {
 3668         fill_color = c;
 3669     }
 3670     if (!im->polyAllocated) {
 3671         if (overflow2(sizeof (int), n)) {
 3672             return;
 3673         }
 3674         im->polyInts = (int *) gdMalloc (sizeof (int) * n);
 3675         if (!im->polyInts) {
 3676             return;
 3677         }
 3678         im->polyAllocated = n;
 3679     }
 3680     if (im->polyAllocated < n) {
 3681         while (im->polyAllocated < n) {
 3682             im->polyAllocated *= 2;
 3683         }
 3684         if (overflow2(sizeof (int), im->polyAllocated)) {
 3685             return;
 3686         }
 3687         im->polyInts = (int *) gdReallocEx (im->polyInts,
 3688                             sizeof (int) * im->polyAllocated);
 3689         if (!im->polyInts) {
 3690             return;
 3691         }
 3692     }
 3693     miny = p[0].y;
 3694     maxy = p[0].y;
 3695     for (i = 1; (i < n); i++) {
 3696         if (p[i].y < miny) {
 3697             miny = p[i].y;
 3698         }
 3699         if (p[i].y > maxy) {
 3700             maxy = p[i].y;
 3701         }
 3702     }
 3703     /* necessary special case: horizontal line */
 3704     if (n > 1 && miny == maxy) {
 3705         x1 = x2 = p[0].x;
 3706         for (i = 1; (i < n); i++) {
 3707             if (p[i].x < x1) {
 3708                 x1 = p[i].x;
 3709             } else if (p[i].x > x2) {
 3710                 x2 = p[i].x;
 3711             }
 3712         }
 3713         gdImageLine(im, x1, miny, x2, miny, c);
 3714         return;
 3715     }
 3716     pmaxy = maxy;
 3717     /* 2.0.16: Optimization by Ilia Chipitsine -- don't waste time offscreen */
 3718     /* 2.0.26: clipping rectangle is even better */
 3719     if (miny < im->cy1) {
 3720         miny = im->cy1;
 3721     }
 3722     if (maxy > im->cy2) {
 3723         maxy = im->cy2;
 3724     }
 3725     /* Fix in 1.3: count a vertex only once */
 3726     for (y = miny; (y <= maxy); y++) {
 3727         ints = 0;
 3728         for (i = 0; (i < n); i++) {
 3729             if (!i) {
 3730                 ind1 = n - 1;
 3731                 ind2 = 0;
 3732             } else {
 3733                 ind1 = i - 1;
 3734                 ind2 = i;
 3735             }
 3736             y1 = p[ind1].y;
 3737             y2 = p[ind2].y;
 3738             if (y1 < y2) {
 3739                 x1 = p[ind1].x;
 3740                 x2 = p[ind2].x;
 3741             } else if (y1 > y2) {
 3742                 y2 = p[ind1].y;
 3743                 y1 = p[ind2].y;
 3744                 x2 = p[ind1].x;
 3745                 x1 = p[ind2].x;
 3746             } else {
 3747                 continue;
 3748             }
 3749 
 3750             /* Do the following math as float intermediately, and round to ensure
 3751              * that Polygon and FilledPolygon for the same set of points have the
 3752              * same footprint. */
 3753 
 3754             if ((y >= y1) && (y < y2)) {
 3755                 im->polyInts[ints++] = (int) ((float) ((y - y1) * (x2 - x1)) /
 3756                                               (float) (y2 - y1) + 0.5 + x1);
 3757             } else if ((y == pmaxy) && (y == y2)) {
 3758                 im->polyInts[ints++] = x2;
 3759             }
 3760         }
 3761         /*
 3762           2.0.26: polygons pretty much always have less than 100 points,
 3763           and most of the time they have considerably less. For such trivial
 3764           cases, insertion sort is a good choice. Also a good choice for
 3765           future implementations that may wish to indirect through a table.
 3766         */
 3767         for (i = 1; (i < ints); i++) {
 3768             index = im->polyInts[i];
 3769             j = i;
 3770             while ((j > 0) && (im->polyInts[j - 1] > index)) {
 3771                 im->polyInts[j] = im->polyInts[j - 1];
 3772                 j--;
 3773             }
 3774             im->polyInts[j] = index;
 3775         }
 3776         for (i = 0; (i < (ints-1)); i += 2) {
 3777             /* 2.0.29: back to gdImageLine to prevent segfaults when
 3778               performing a pattern fill */
 3779             gdImageLine (im, im->polyInts[i], y, im->polyInts[i + 1], y,
 3780                          fill_color);
 3781         }
 3782     }
 3783     /* If we are drawing this AA, then redraw the border with AA lines. */
 3784     /* This doesn't work as well as I'd like, but it doesn't clash either. */
 3785     if (c == gdAntiAliased) {
 3786         gdImagePolygon (im, p, n, c);
 3787     }
 3788 }
 3789 
 3790 /**
 3791  * Group: other
 3792  */
 3793 
 3794 static void gdImageSetAAPixelColor(gdImagePtr im, int x, int y, int color, int t);
 3795 
 3796 /**
 3797  * Function: gdImageSetStyle
 3798  *
 3799  * Sets the style for following drawing operations
 3800  *
 3801  * Parameters:
 3802  *   im        - The image.
 3803  *   style     - An array of color values.
 3804  *   noOfPixel - The number of color values.
 3805  */
 3806 BGD_DECLARE(void) gdImageSetStyle (gdImagePtr im, int *style, int noOfPixels)
 3807 {
 3808     if (im->style) {
 3809         gdFree (im->style);
 3810     }
 3811     if (overflow2(sizeof (int), noOfPixels)) {
 3812         return;
 3813     }
 3814     im->style = (int *) gdMalloc (sizeof (int) * noOfPixels);
 3815     if (!im->style) {
 3816         return;
 3817     }
 3818     memcpy (im->style, style, sizeof (int) * noOfPixels);
 3819     im->styleLength = noOfPixels;
 3820     im->stylePos = 0;
 3821 }
 3822 
 3823 /**
 3824  * Function: gdImageSetThickness
 3825  *
 3826  * Sets the thickness for following drawing operations
 3827  *
 3828  * Parameters:
 3829  *   im        - The image.
 3830  *   thickness - The thickness in pixels.
 3831  */
 3832 BGD_DECLARE(void) gdImageSetThickness (gdImagePtr im, int thickness)
 3833 {
 3834     im->thick = thickness;
 3835 }
 3836 
 3837 /**
 3838  * Function: gdImageSetBrush
 3839  *
 3840  * Sets the brush for following drawing operations
 3841  *
 3842  * Parameters:
 3843  *   im    - The image.
 3844  *   brush - The brush image.
 3845  */
 3846 BGD_DECLARE(void) gdImageSetBrush (gdImagePtr im, gdImagePtr brush)
 3847 {
 3848     int i;
 3849     im->brush = brush;
 3850     if ((!im->trueColor) && (!im->brush->trueColor)) {
 3851         for (i = 0; (i < gdImageColorsTotal (brush)); i++) {
 3852             int index;
 3853             index = gdImageColorResolveAlpha (im,
 3854                                               gdImageRed (brush, i),
 3855                                               gdImageGreen (brush, i),
 3856                                               gdImageBlue (brush, i),
 3857                                               gdImageAlpha (brush, i));
 3858             im->brushColorMap[i] = index;
 3859         }
 3860     }
 3861 }
 3862 
 3863 /*
 3864     Function: gdImageSetTile
 3865 */
 3866 BGD_DECLARE(void) gdImageSetTile (gdImagePtr im, gdImagePtr tile)
 3867 {
 3868     int i;
 3869     im->tile = tile;
 3870     if ((!im->trueColor) && (!im->tile->trueColor)) {
 3871         for (i = 0; (i < gdImageColorsTotal (tile)); i++) {
 3872             int index;
 3873             index = gdImageColorResolveAlpha (im,
 3874                                               gdImageRed (tile, i),
 3875                                               gdImageGreen (tile, i),
 3876                                               gdImageBlue (tile, i),
 3877                                               gdImageAlpha (tile, i));
 3878             im->tileColorMap[i] = index;
 3879         }
 3880     }
 3881 }
 3882 
 3883 /**
 3884  * Function: gdImageSetAntiAliased
 3885  *
 3886  * Set the color for subsequent anti-aliased drawing
 3887  *
 3888  * If <gdAntiAliased> is passed as color to drawing operations that support
 3889  * anti-aliased drawing (such as <gdImageLine> and <gdImagePolygon>), the actual
 3890  * color to be used can be set with this function.
 3891  *
 3892  * Example: draw an anti-aliased blue line:
 3893  * | gdImageSetAntiAliased(im, gdTrueColorAlpha(0, 0, gdBlueMax, gdAlphaOpaque));
 3894  * | gdImageLine(im, 10,10, 20,20, gdAntiAliased);
 3895  *
 3896  * Parameters:
 3897  *   im - The image.
 3898  *   c  - The color.
 3899  *
 3900  * See also:
 3901  *   - <gdImageSetAntiAliasedDontBlend>
 3902  */
 3903 BGD_DECLARE(void) gdImageSetAntiAliased (gdImagePtr im, int c)
 3904 {
 3905     im->AA = 1;
 3906     im->AA_color = c;
 3907     im->AA_dont_blend = -1;
 3908 }
 3909 
 3910 /**
 3911  * Function: gdImageSetAntiAliasedDontBlend
 3912  *
 3913  * Set the color and "dont_blend" color for subsequent anti-aliased drawing
 3914  *
 3915  * This extended variant of <gdImageSetAntiAliased> allows to also specify a
 3916  * (background) color that will not be blended in anti-aliased drawing
 3917  * operations.
 3918  *
 3919  * Parameters:
 3920  *   im         - The image.
 3921  *   c          - The color.
 3922  *   dont_blend - Whether to blend.
 3923  */
 3924 BGD_DECLARE(void) gdImageSetAntiAliasedDontBlend (gdImagePtr im, int c, int dont_blend)
 3925 {
 3926     im->AA = 1;
 3927     im->AA_color = c;
 3928     im->AA_dont_blend = dont_blend;
 3929 }
 3930 
 3931 /**
 3932  * Function: gdImageInterlace
 3933  *
 3934  * Sets whether an image is interlaced
 3935  *
 3936  * This is relevant only when saving the image in a format that supports
 3937  * interlacing.
 3938  *
 3939  * Parameters:
 3940  *   im           - The image.
 3941  *   interlaceArg - Whether the image is interlaced.
 3942  *
 3943  * See also:
 3944  *   - <gdImageGetInterlaced>
 3945 */
 3946 BGD_DECLARE(void) gdImageInterlace (gdImagePtr im, int interlaceArg)
 3947 {
 3948     im->interlace = interlaceArg;
 3949 }
 3950 
 3951 /**
 3952  * Function: gdImageCompare
 3953  *
 3954  * Compare two images
 3955  *
 3956  * Parameters:
 3957  *   im1 - An image.
 3958  *   im2 - Another image.
 3959  *
 3960  * Returns:
 3961  *   A bitmask of <Image Comparison> flags where each set flag signals
 3962  *   which attributes of the images are different.
 3963  */
 3964 BGD_DECLARE(int) gdImageCompare (gdImagePtr im1, gdImagePtr im2)
 3965 {
 3966     int x, y;
 3967     int p1, p2;
 3968     int cmpStatus = 0;
 3969     int sx, sy;
 3970 
 3971     if (im1->interlace != im2->interlace) {
 3972         cmpStatus |= GD_CMP_INTERLACE;
 3973     }
 3974 
 3975     if (im1->transparent != im2->transparent) {
 3976         cmpStatus |= GD_CMP_TRANSPARENT;
 3977     }
 3978 
 3979     if (im1->trueColor != im2->trueColor) {
 3980         cmpStatus |= GD_CMP_TRUECOLOR;
 3981     }
 3982 
 3983     sx = im1->sx;
 3984     if (im1->sx != im2->sx) {
 3985         cmpStatus |= GD_CMP_SIZE_X + GD_CMP_IMAGE;
 3986         if (im2->sx < im1->sx) {
 3987             sx = im2->sx;
 3988         }
 3989     }
 3990 
 3991     sy = im1->sy;
 3992     if (im1->sy != im2->sy) {
 3993         cmpStatus |= GD_CMP_SIZE_Y + GD_CMP_IMAGE;
 3994         if (im2->sy < im1->sy) {
 3995             sy = im2->sy;
 3996         }
 3997     }
 3998 
 3999     if (im1->colorsTotal != im2->colorsTotal) {
 4000         cmpStatus |= GD_CMP_NUM_COLORS;
 4001     }
 4002 
 4003     for (y = 0; (y < sy); y++) {
 4004         for (x = 0; (x < sx); x++) {
 4005             p1 =
 4006                 im1->trueColor ? gdImageTrueColorPixel (im1, x,
 4007                         y) :
 4008                 gdImagePalettePixel (im1, x, y);
 4009             p2 =
 4010                 im2->trueColor ? gdImageTrueColorPixel (im2, x,
 4011                         y) :
 4012                 gdImagePalettePixel (im2, x, y);
 4013             if (gdImageRed (im1, p1) != gdImageRed (im2, p2)) {
 4014                 cmpStatus |= GD_CMP_COLOR + GD_CMP_IMAGE;
 4015                 break;
 4016             }
 4017             if (gdImageGreen (im1, p1) != gdImageGreen (im2, p2)) {
 4018                 cmpStatus |= GD_CMP_COLOR + GD_CMP_IMAGE;
 4019                 break;
 4020             }
 4021             if (gdImageBlue (im1, p1) != gdImageBlue (im2, p2)) {
 4022                 cmpStatus |= GD_CMP_COLOR + GD_CMP_IMAGE;
 4023                 break;
 4024             }
 4025 #if 0
 4026             /* Soon we'll add alpha channel to palettes */
 4027             if (gdImageAlpha (im1, p1) != gdImageAlpha (im2, p2)) {
 4028                 cmpStatus |= GD_CMP_COLOR + GD_CMP_IMAGE;
 4029                 break;
 4030             }
 4031 #endif
 4032         }
 4033         if (cmpStatus & GD_CMP_COLOR) {
 4034             break;
 4035         };
 4036     }
 4037 
 4038     return cmpStatus;
 4039 }
 4040 
 4041 
 4042 /* Thanks to Frank Warmerdam for this superior implementation
 4043     of gdAlphaBlend(), which merges alpha in the
 4044     destination color much better. */
 4045 
 4046 /**
 4047  * Function: gdAlphaBlend
 4048  *
 4049  * Blend two colors
 4050  *
 4051  * Parameters:
 4052  *   dst - The color to blend onto.
 4053  *   src - The color to blend.
 4054  *
 4055  * See also:
 4056  *   - <gdImageAlphaBlending>
 4057  *   - <gdLayerOverlay>
 4058  *   - <gdLayerMultiply>
 4059  */
 4060 BGD_DECLARE(int) gdAlphaBlend (int dst, int src)
 4061 {
 4062     int src_alpha = gdTrueColorGetAlpha(src);
 4063     int dst_alpha, alpha, red, green, blue;
 4064     int src_weight, dst_weight, tot_weight;
 4065 
 4066     /* -------------------------------------------------------------------- */
 4067     /*      Simple cases we want to handle fast.                            */
 4068     /* -------------------------------------------------------------------- */
 4069     if( src_alpha == gdAlphaOpaque )
 4070         return src;
 4071 
 4072     dst_alpha = gdTrueColorGetAlpha(dst);
 4073     if( src_alpha == gdAlphaTransparent )
 4074         return dst;
 4075     if( dst_alpha == gdAlphaTransparent )
 4076         return src;
 4077 
 4078     /* -------------------------------------------------------------------- */
 4079     /*      What will the source and destination alphas be?  Note that      */
 4080     /*      the destination weighting is substantially reduced as the       */
 4081     /*      overlay becomes quite opaque.                                   */
 4082     /* -------------------------------------------------------------------- */
 4083     src_weight = gdAlphaTransparent - src_alpha;
 4084     dst_weight = (gdAlphaTransparent - dst_alpha) * src_alpha / gdAlphaMax;
 4085     tot_weight = src_weight + dst_weight;
 4086 
 4087     /* -------------------------------------------------------------------- */
 4088     /*      What red, green and blue result values will we use?             */
 4089     /* -------------------------------------------------------------------- */
 4090     alpha = src_alpha * dst_alpha / gdAlphaMax;
 4091 
 4092     red = (gdTrueColorGetRed(src) * src_weight
 4093            + gdTrueColorGetRed(dst) * dst_weight) / tot_weight;
 4094     green = (gdTrueColorGetGreen(src) * src_weight
 4095              + gdTrueColorGetGreen(dst) * dst_weight) / tot_weight;
 4096     blue = (gdTrueColorGetBlue(src) * src_weight
 4097             + gdTrueColorGetBlue(dst) * dst_weight) / tot_weight;
 4098 
 4099     /* -------------------------------------------------------------------- */
 4100     /*      Return merged result.                                           */
 4101     /* -------------------------------------------------------------------- */
 4102     return ((alpha << 24) + (red << 16) + (green << 8) + blue);
 4103 }
 4104 
 4105 static int gdAlphaOverlayColor (int src, int dst, int max );
 4106 
 4107 /**
 4108  * Function: gdLayerOverlay
 4109  *
 4110  * Overlay two colors
 4111  *
 4112  * Parameters:
 4113  *   dst - The color to overlay onto.
 4114  *   src - The color to overlay.
 4115  *
 4116  * See also:
 4117  *   - <gdImageAlphaBlending>
 4118  *   - <gdAlphaBlend>
 4119  *   - <gdLayerMultiply>
 4120  */
 4121 BGD_DECLARE(int) gdLayerOverlay (int dst, int src)
 4122 {
 4123     int a1, a2;
 4124     a1 = gdAlphaMax - gdTrueColorGetAlpha(dst);
 4125     a2 = gdAlphaMax - gdTrueColorGetAlpha(src);
 4126     return ( ((gdAlphaMax - a1*a2/gdAlphaMax) << 24) +
 4127         (gdAlphaOverlayColor( gdTrueColorGetRed(src), gdTrueColorGetRed(dst), gdRedMax ) << 16) +
 4128         (gdAlphaOverlayColor( gdTrueColorGetGreen(src), gdTrueColorGetGreen(dst), gdGreenMax ) << 8) +
 4129         (gdAlphaOverlayColor( gdTrueColorGetBlue(src), gdTrueColorGetBlue(dst), gdBlueMax ))
 4130         );
 4131 }
 4132 
 4133 /* Apply 'overlay' effect - background pixels are colourised by the foreground colour */
 4134 static int gdAlphaOverlayColor (int src, int dst, int max )
 4135 {
 4136     dst = dst << 1;
 4137     if( dst > max ) {
 4138         /* in the "light" zone */
 4139         return dst + (src << 1) - (dst * src / max) - max;
 4140     } else {
 4141         /* in the "dark" zone */
 4142         return dst * src / max;
 4143     }
 4144 }
 4145 
 4146 /**
 4147  * Function: gdLayerMultiply
 4148  *
 4149  * Overlay two colors with multiply effect
 4150  *
 4151  * Parameters:
 4152  *   dst - The color to overlay onto.
 4153  *   src - The color to overlay.
 4154  *
 4155  * See also:
 4156  *   - <gdImageAlphaBlending>
 4157  *   - <gdAlphaBlend>
 4158  *   - <gdLayerOverlay>
 4159  */
 4160 BGD_DECLARE(int) gdLayerMultiply (int dst, int src)
 4161 {
 4162     int a1, a2, r1, r2, g1, g2, b1, b2;
 4163     a1 = gdAlphaMax - gdTrueColorGetAlpha(src);
 4164     a2 = gdAlphaMax - gdTrueColorGetAlpha(dst);
 4165 
 4166     r1 = gdRedMax - (a1 * (gdRedMax - gdTrueColorGetRed(src))) / gdAlphaMax;
 4167     r2 = gdRedMax - (a2 * (gdRedMax - gdTrueColorGetRed(dst))) / gdAlphaMax;
 4168     g1 = gdGreenMax - (a1 * (gdGreenMax - gdTrueColorGetGreen(src))) / gdAlphaMax;
 4169     g2 = gdGreenMax - (a2 * (gdGreenMax - gdTrueColorGetGreen(dst))) / gdAlphaMax;
 4170     b1 = gdBlueMax - (a1 * (gdBlueMax - gdTrueColorGetBlue(src))) / gdAlphaMax;
 4171     b2 = gdBlueMax - (a2 * (gdBlueMax - gdTrueColorGetBlue(dst))) / gdAlphaMax ;
 4172 
 4173     a1 = gdAlphaMax - a1;
 4174     a2 = gdAlphaMax - a2;
 4175     return ( ((a1*a2/gdAlphaMax) << 24) +
 4176              ((r1*r2/gdRedMax) << 16) +
 4177              ((g1*g2/gdGreenMax) << 8) +
 4178              ((b1*b2/gdBlueMax))
 4179         );
 4180 }
 4181 
 4182 /**
 4183  *  Function: gdImageAlphaBlending
 4184  *
 4185  *  Set the effect for subsequent drawing operations
 4186  *
 4187  *  Note that the effect is used for truecolor images only.
 4188  *
 4189  * Parameters:
 4190  *   im               - The image.
 4191  *   alphaBlendingArg - The effect.
 4192  *
 4193  * See also:
 4194  *   - <Effects>
 4195  */
 4196 BGD_DECLARE(void) gdImageAlphaBlending (gdImagePtr im, int alphaBlendingArg)
 4197 {
 4198     im->alphaBlendingFlag = alphaBlendingArg;
 4199 }
 4200 
 4201 /**
 4202  * Function: gdImageSaveAlpha
 4203  *
 4204  * Sets the save alpha flag
 4205  *
 4206  * The save alpha flag specifies whether the alpha channel of the pixels should
 4207  * be saved. This is supported only for image formats that support full alpha
 4208  * transparency, e.g. PNG.
 4209  */
 4210 BGD_DECLARE(void) gdImageSaveAlpha (gdImagePtr im, int saveAlphaArg)
 4211 {
 4212     im->saveAlphaFlag = saveAlphaArg;
 4213 }
 4214 
 4215 /**
 4216  * Function: gdImageSetClip
 4217  *
 4218  * Sets the clipping rectangle
 4219  *
 4220  * The clipping rectangle restricts the drawing area for following drawing
 4221  * operations.
 4222  *
 4223  * Parameters:
 4224  *   im - The image.
 4225  *   x1 - The x-coordinate of the upper left corner.
 4226  *   y1 - The y-coordinate of the upper left corner.
 4227  *   x2 - The x-coordinate of the lower right corner.
 4228  *   y2 - The y-coordinate of the lower right corner.
 4229  *
 4230  * See also:
 4231  *   - <gdImageGetClip>
 4232  */
 4233 BGD_DECLARE(void) gdImageSetClip (gdImagePtr im, int x1, int y1, int x2, int y2)
 4234 {
 4235     if (x1 < 0) {
 4236         x1 = 0;
 4237     }
 4238     if (x1 >= im->sx) {
 4239         x1 = im->sx - 1;
 4240     }
 4241     if (x2 < 0) {
 4242         x2 = 0;
 4243     }
 4244     if (x2 >= im->sx) {
 4245         x2 = im->sx - 1;
 4246     }
 4247     if (y1 < 0) {
 4248         y1 = 0;
 4249     }
 4250     if (y1 >= im->sy) {
 4251         y1 = im->sy - 1;
 4252     }
 4253     if (y2 < 0) {
 4254         y2 = 0;
 4255     }
 4256     if (y2 >= im->sy) {
 4257         y2 = im->sy - 1;
 4258     }
 4259     im->cx1 = x1;
 4260     im->cy1 = y1;
 4261     im->cx2 = x2;
 4262     im->cy2 = y2;
 4263 }
 4264 
 4265 /**
 4266  * Function: gdImageGetClip
 4267  *
 4268  * Gets the current clipping rectangle
 4269  *
 4270  * Parameters:
 4271  *   im - The image.
 4272  *   x1P - (out) The x-coordinate of the upper left corner.
 4273  *   y1P - (out) The y-coordinate of the upper left corner.
 4274  *   x2P - (out) The x-coordinate of the lower right corner.
 4275  *   y2P - (out) The y-coordinate of the lower right corner.
 4276  *
 4277  * See also:
 4278  *   - <gdImageSetClip>
 4279  */
 4280 BGD_DECLARE(void) gdImageGetClip (gdImagePtr im, int *x1P, int *y1P, int *x2P, int *y2P)
 4281 {
 4282     *x1P = im->cx1;
 4283     *y1P = im->cy1;
 4284     *x2P = im->cx2;
 4285     *y2P = im->cy2;
 4286 }
 4287 
 4288 /**
 4289  * Function: gdImageSetResolution
 4290  *
 4291  * Sets the resolution of an image.
 4292  *
 4293  * Parameters:
 4294  *   im    - The image.
 4295  *   res_x - The horizontal resolution in DPI.
 4296  *   res_y - The vertical resolution in DPI.
 4297  *
 4298  * See also:
 4299  *   - <gdImageResolutionX>
 4300  *   - <gdImageResolutionY>
 4301  */
 4302 BGD_DECLARE(void) gdImageSetResolution(gdImagePtr im, const unsigned int res_x, const unsigned int res_y)
 4303 {
 4304     if (res_x > 0) im->res_x = res_x;
 4305     if (res_y > 0) im->res_y = res_y;
 4306 }
 4307 
 4308 /*
 4309  * Added on 2003/12 by Pierre-Alain Joye (pajoye@pearfr.org)
 4310  * */
 4311 #define BLEND_COLOR(a, nc, c, cc) \
 4312 nc = (cc) + (((((c) - (cc)) * (a)) + ((((c) - (cc)) * (a)) >> 8) + 0x80) >> 8);
 4313 
 4314 static void gdImageSetAAPixelColor(gdImagePtr im, int x, int y, int color, int t)
 4315 {
 4316     int dr,dg,db,p,r,g,b;
 4317 
 4318     /* 2.0.34: watch out for out of range calls */
 4319     if (!gdImageBoundsSafeMacro(im, x, y)) {
 4320         return;
 4321     }
 4322     p = gdImageGetPixel(im,x,y);
 4323     /* TBB: we have to implement the dont_blend stuff to provide
 4324       the full feature set of the old implementation */
 4325     if ((p == color)
 4326             || ((p == im->AA_dont_blend)
 4327                 && (t != 0x00))) {
 4328         return;
 4329     }
 4330     dr = gdTrueColorGetRed(color);
 4331     dg = gdTrueColorGetGreen(color);
 4332     db = gdTrueColorGetBlue(color);
 4333 
 4334     r = gdTrueColorGetRed(p);
 4335     g = gdTrueColorGetGreen(p);
 4336     b = gdTrueColorGetBlue(p);
 4337 
 4338     BLEND_COLOR(t, dr, r, dr);
 4339     BLEND_COLOR(t, dg, g, dg);
 4340     BLEND_COLOR(t, db, b, db);
 4341     im->tpixels[y][x] = gdTrueColorAlpha(dr, dg, db, gdAlphaOpaque);
 4342 }
 4343 
 4344 static void gdImageAALine (gdImagePtr im, int x1, int y1, int x2, int y2, int col)
 4345 {
 4346     /* keep them as 32bits */
 4347     long x, y, inc, frac;
 4348     long dx, dy,tmp;
 4349     int w, wid, wstart;
 4350     int thick = im->thick;
 4351 
 4352     if (!im->trueColor) {
 4353         /* TBB: don't crash when the image is of the wrong type */
 4354         gdImageLine(im, x1, y1, x2, y2, col);
 4355         return;
 4356     }
 4357 
 4358     /* TBB: use the clipping rectangle */
 4359     if (clip_1d (&x1, &y1, &x2, &y2, im->cx1, im->cx2) == 0)
 4360         return;
 4361     if (clip_1d (&y1, &x1, &y2, &x2, im->cy1, im->cy2) == 0)
 4362         return;
 4363 
 4364     dx = x2 - x1;
 4365     dy = y2 - y1;
 4366 
 4367     if (dx == 0 && dy == 0) {
 4368         /* TBB: allow setting points */
 4369         gdImageSetPixel(im, x1, y1, col);
 4370         return;
 4371     } else {
 4372         double ag;
 4373         /* Cast the long to an int to avoid compiler warnings about truncation.
 4374          * This isn't a problem as computed dy/dx values came from ints above. */
 4375         ag = fabs(abs((int)dy) < abs((int)dx) ? cos(atan2(dy, dx)) : sin(atan2(dy, dx)));
 4376         if (ag != 0) {
 4377             wid = thick / ag;
 4378         } else {
 4379             wid = 1;
 4380         }
 4381         if (wid == 0) {
 4382             wid = 1;
 4383         }
 4384     }
 4385 
 4386     /* Axis aligned lines */
 4387     if (dx == 0) {
 4388         gdImageVLine(im, x1, y1, y2, col);
 4389         return;
 4390     } else if (dy == 0) {
 4391         gdImageHLine(im, y1, x1, x2, col);
 4392         return;
 4393     }
 4394 
 4395     if (abs((int)dx) > abs((int)dy)) {
 4396         if (dx < 0) {
 4397             tmp = x1;
 4398             x1 = x2;
 4399             x2 = tmp;
 4400             tmp = y1;
 4401             y1 = y2;
 4402             y2 = tmp;
 4403             dx = x2 - x1;
 4404             dy = y2 - y1;
 4405         }
 4406         y = y1;
 4407         inc = (dy * 65536) / dx;
 4408         frac = 0;
 4409         /* TBB: set the last pixel for consistency (<=) */
 4410         for (x = x1 ; x <= x2 ; x++) {
 4411             wstart = y - wid / 2;
 4412             for (w = wstart; w < wstart + wid; w++) {
 4413                 gdImageSetAAPixelColor(im, x , w , col , (frac >> 8) & 0xFF);
 4414                 gdImageSetAAPixelColor(im, x , w + 1 , col, (~frac >> 8) & 0xFF);
 4415             }
 4416             frac += inc;
 4417             if (frac >= 65536) {
 4418                 frac -= 65536;
 4419                 y++;
 4420             } else if (frac < 0) {
 4421                 frac += 65536;
 4422                 y--;
 4423             }
 4424         }
 4425     } else {
 4426         if (dy < 0) {
 4427             tmp = x1;
 4428             x1 = x2;
 4429             x2 = tmp;
 4430             tmp = y1;
 4431             y1 = y2;
 4432             y2 = tmp;
 4433             dx = x2 - x1;
 4434             dy = y2 - y1;
 4435         }
 4436         x = x1;
 4437         inc = (dx * 65536) / dy;
 4438         frac = 0;
 4439         /* TBB: set the last pixel for consistency (<=) */
 4440         for (y = y1 ; y <= y2 ; y++) {
 4441             wstart = x - wid / 2;
 4442             for (w = wstart; w < wstart + wid; w++) {
 4443                 gdImageSetAAPixelColor(im, w , y  , col, (frac >> 8) & 0xFF);
 4444                 gdImageSetAAPixelColor(im, w + 1, y, col, (~frac >> 8) & 0xFF);
 4445             }
 4446             frac += inc;
 4447             if (frac >= 65536) {
 4448                 frac -= 65536;
 4449                 x++;
 4450             } else if (frac < 0) {
 4451                 frac += 65536;
 4452                 x--;
 4453             }
 4454         }
 4455     }
 4456 }
 4457 
 4458 
 4459 /**
 4460  * Function: gdImagePaletteToTrueColor
 4461  *
 4462  * Convert a palette image to true color
 4463  *
 4464  * Parameters:
 4465  *   src - The image.
 4466  *
 4467  * Returns:
 4468  *   Non-zero if the conversion succeeded, zero otherwise.
 4469  *
 4470  * See also:
 4471  *   - <gdImageTrueColorToPalette>
 4472  */
 4473 BGD_DECLARE(int) gdImagePaletteToTrueColor(gdImagePtr src)
 4474 {
 4475     unsigned int y;
 4476     unsigned int yy;
 4477 
 4478     if (src == NULL) {
 4479         return 0;
 4480     }
 4481 
 4482     if (src->trueColor == 1) {
 4483         return 1;
 4484     } else {
 4485         unsigned int x;
 4486         const unsigned int sy = gdImageSY(src);
 4487         const unsigned int sx = gdImageSX(src);
 4488 
 4489         src->tpixels = (int **) gdMalloc(sizeof(int *) * sy);
 4490         if (src->tpixels == NULL) {
 4491             return 0;
 4492         }
 4493 
 4494         for (y = 0; y < sy; y++) {
 4495             const unsigned char *src_row = src->pixels[y];
 4496             int * dst_row;
 4497 
 4498             /* no need to calloc it, we overwrite all pxl anyway */
 4499             src->tpixels[y] = (int *) gdMalloc(sx * sizeof(int));
 4500             if (src->tpixels[y] == NULL) {
 4501                 goto clean_on_error;
 4502             }
 4503 
 4504             dst_row = src->tpixels[y];
 4505             for (x = 0; x < sx; x++) {
 4506                 const unsigned char c = *(src_row + x);
 4507                 if (c == src->transparent) {
 4508                     *(dst_row + x) = gdTrueColorAlpha(0, 0, 0, 127);
 4509                 } else {
 4510                     *(dst_row + x) = gdTrueColorAlpha(src->red[c], src->green[c], src->blue[c], src->alpha[c]);
 4511                 }
 4512             }
 4513         }
 4514     }
 4515 
 4516     /* free old palette buffer (y is sy) */
 4517     for (yy = 0; yy < y; yy++) {
 4518         gdFree(src->pixels[yy]);
 4519     }
 4520     gdFree(src->pixels);
 4521     src->trueColor = 1;
 4522     src->pixels = NULL;
 4523     src->alphaBlendingFlag = 0;
 4524     src->saveAlphaFlag = 1;
 4525 
 4526     if (src->transparent >= 0) {
 4527         const unsigned char c = src->transparent;
 4528         src->transparent =  gdTrueColorAlpha(src->red[c], src->green[c], src->blue[c], src->alpha[c]);
 4529     }
 4530 
 4531     return 1;
 4532 
 4533 clean_on_error:
 4534     /* free new true color buffer (y is not allocated, have failed) */
 4535     for (yy = 0; yy < y; yy++) {
 4536         gdFree(src->tpixels[yy]);
 4537     }
 4538     gdFree(src->tpixels);
 4539     return 0;
 4540 }