Annotation of parser3/src/lib/gd/gif.C, revision 1.1
1.1 ! paf 1: /** @file
! 2: Parser: image manipulations impl1.
! 3:
! 4: Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com)
! 5: Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
! 6: based on: gd
! 7:
! 8: Written by Tom Boutell, 5/94.
! 9: Copyright 1994, Cold Spring Harbor Labs.
! 10: Permission granted to use this code in any fashion provided
! 11: that this notice is retained and any alterations are
! 12: labeled as such. It is requested, but not required, that
! 13: you share extensions to this module with us so that we
! 14: can incorporate them into new versions.
! 15: */
! 16:
! 17: static const char * const IDENT_GIF_C="$Date: 2003/11/20 17:07:44 $";
! 18:
! 19: #include "gif.h"
! 20:
! 21: #include "mtables.h"
! 22: //#include "pa_common.h"
! 23:
! 24: //static void BrushApply(int x, int y);
! 25: //static void TileApply(int x, int y);
! 26:
! 27: void gdImage::Create(int asx, int asy) {
! 28: sx = asx;
! 29: sy = asy;
! 30:
! 31: int i;
! 32: pixels = (unsigned char **) malloc(sizeof(unsigned char *) * sx);
! 33: polyInts = 0;
! 34: polyAllocated = 0;
! 35: lineWidth = 1;
! 36: for (i=0; (i<asx); i++)
! 37: pixels[i] = (unsigned char *) malloc_atomic(asy);
! 38: colorsTotal = 0;
! 39: transparent = (-1);
! 40: interlace = 0;
! 41: }
! 42:
! 43: int gdImage::ColorClosest(int r, int g, int b, int tolerance)
! 44: {
! 45: int i;
! 46: long rd, gd, bd;
! 47: int ct = (-1);
! 48: long mindist = 0;
! 49: for (i=0; (i<(colorsTotal)); i++) {
! 50: long dist;
! 51: if (open[i]) {
! 52: continue;
! 53: }
! 54: rd = (red[i] - r);
! 55: gd = (green[i] - g);
! 56: bd = (blue[i] - b);
! 57: dist = rd * rd + gd * gd + bd * bd;
! 58: if ((i == 0) || (dist < mindist+tolerance)) {
! 59: mindist = dist;
! 60: ct = i;
! 61: }
! 62: }
! 63: return mindist<tolerance?ct:-1;
! 64: }
! 65:
! 66: int gdImage::ColorExact(int r, int g, int b)
! 67: {
! 68: int i;
! 69: for (i=0; (i<(colorsTotal)); i++) {
! 70: if (open[i]) {
! 71: continue;
! 72: }
! 73: if ((red[i] == r) &&
! 74: (green[i] == g) &&
! 75: (blue[i] == b)) {
! 76: return i;
! 77: }
! 78: }
! 79: return -1;
! 80: }
! 81:
! 82: int gdImage::ColorAllocate(int r, int g, int b)
! 83: {
! 84: int i;
! 85: int ct = (-1);
! 86: for (i=0; (i<(colorsTotal)); i++) {
! 87: if (open[i]) {
! 88: ct = i;
! 89: break;
! 90: }
! 91: }
! 92: if (ct == (-1)) {
! 93: ct = colorsTotal;
! 94: if (ct == gdMaxColors) {
! 95: return -1;
! 96: }
! 97: colorsTotal++;
! 98: }
! 99: red[ct] = r;
! 100: green[ct] = g;
! 101: blue[ct] = b;
! 102: open[ct] = 0;
! 103: return ct;
! 104: }
! 105:
! 106: int gdImage::ColorRGB(int r, int g, int b){
! 107: int idx=ColorExact(r,g,b);
! 108: return idx<0 ? ColorAllocate(r,g,b) : idx;
! 109: }
! 110:
! 111: int gdImage::Color(unsigned int rgb){
! 112: unsigned int b=rgb, g=b>>8, r=g>>8;
! 113: return ColorRGB(r & 0xFF,g & 0xFF,b & 0xFF);
! 114: }
! 115:
! 116: void gdImage::ColorDeallocate(int color)
! 117: {
! 118: /* Mark it open. */
! 119: open[color] = 1;
! 120: }
! 121:
! 122: void gdImage::SetColorTransparent(int color)
! 123: {
! 124: transparent = color;
! 125: }
! 126:
! 127:
! 128: void gdImage::SetPixel(int x, int y, int color)
! 129: {
! 130: //paf int p;
! 131:
! 132: switch (lineWidth){
! 133: case 1: {
! 134: DoSetPixel(x, y,color);
! 135: return;
! 136: }
! 137: case 2: {
! 138: DoSetPixel(x, y-1,color);
! 139: DoSetPixel(x-1, y,color);
! 140: DoSetPixel(x, y,color);
! 141: DoSetPixel(x+1, y,color);
! 142: DoSetPixel(x, y+1,color);
! 143: return;
! 144: }
! 145: default:{
! 146: int i,j;
! 147: for (i=-1;i<=1;i++) DoSetPixel(x+i, y-2,color);
! 148: for (j=-1;j<=1;j++) for (i=-2;i<=2;i++) DoSetPixel(x+i, y+j,color);
! 149: for (i=-1;i<=1;i++) DoSetPixel(x+i, y+2,color);
! 150: return;
! 151: }
! 152: }
! 153: }
! 154:
! 155: int gdImage::GetPixel(int x, int y)
! 156: {
! 157: return BoundsSafe(x, y) ? pixels[x][y]:0;
! 158: }
! 159:
! 160: /* Bresenham as presented in Foley & Van Dam */
! 161:
! 162: /* As above, plus dashing */
! 163:
! 164: #define styledSet \
! 165: { \
! 166: if (lineStyle) { \
! 167: if(!lineStyle[styleStep]) \
! 168: styleStep = 0; \
! 169: on=lineStyle[styleStep++]!=' '; \
! 170: } \
! 171: if (on) { \
! 172: SetPixel(x, y, color); \
! 173: } \
! 174: }
! 175:
! 176: void gdImage::Line(int x1, int y1, int x2, int y2, int color)
! 177: {
! 178: int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
! 179: int styleStep = 0;
! 180: int on = 1;
! 181: dx = abs(x2-x1);
! 182: dy = abs(y2-y1);
! 183: if (dy <= dx) {
! 184: d = 2*dy - dx;
! 185: incr1 = 2*dy;
! 186: incr2 = 2 * (dy - dx);
! 187: if (x1 > x2) {
! 188: x = x2;
! 189: y = y2;
! 190: ydirflag = (-1);
! 191: xend = x1;
! 192: } else {
! 193: x = x1;
! 194: y = y1;
! 195: ydirflag = 1;
! 196: xend = x2;
! 197: }
! 198: styledSet;
! 199: if (((y2 - y1) * ydirflag) > 0) {
! 200: while (x < xend) {
! 201: x++;
! 202: if (d <0) {
! 203: d+=incr1;
! 204: } else {
! 205: y++;
! 206: d+=incr2;
! 207: }
! 208: styledSet;
! 209: }
! 210: } else {
! 211: while (x < xend) {
! 212: x++;
! 213: if (d <0) {
! 214: d+=incr1;
! 215: } else {
! 216: y--;
! 217: d+=incr2;
! 218: }
! 219: styledSet;
! 220: }
! 221: }
! 222: } else {
! 223: d = 2*dx - dy;
! 224: incr1 = 2*dx;
! 225: incr2 = 2 * (dx - dy);
! 226: if (y1 > y2) {
! 227: y = y2;
! 228: x = x2;
! 229: yend = y1;
! 230: xdirflag = (-1);
! 231: } else {
! 232: y = y1;
! 233: x = x1;
! 234: yend = y2;
! 235: xdirflag = 1;
! 236: }
! 237: styledSet;
! 238: if (((x2 - x1) * xdirflag) > 0) {
! 239: while (y < yend) {
! 240: y++;
! 241: if (d <0) {
! 242: d+=incr1;
! 243: } else {
! 244: x++;
! 245: d+=incr2;
! 246: }
! 247: styledSet;
! 248: }
! 249: } else {
! 250: while (y < yend) {
! 251: y++;
! 252: if (d <0) {
! 253: d+=incr1;
! 254: } else {
! 255: x--;
! 256: d+=incr2;
! 257: }
! 258: styledSet;
! 259: }
! 260: }
! 261: }
! 262: }
! 263:
! 264: /* s and e are integers modulo 360 (degrees), with 0 degrees
! 265: being the rightmost extreme and degrees changing clockwise.
! 266: cx and cy are the center in pixels; w and h are the horizontal
! 267: and vertical diameter in pixels. Nice interface, but slow, since
! 268: I don't yet use Bresenham (I'm using an inefficient but
! 269: simple solution with too much work going on in it; generalizing
! 270: Bresenham to ellipses and partial arcs of ellipses is non-trivial,
! 271: at least for me) and there are other inefficiencies (small circles
! 272: do far too much work). */
! 273:
! 274: void gdImage::Arc(int cx, int cy, int w, int h, int s, int e, int color)
! 275: {
! 276: #if 0
! 277: if(s==0 && e==360) { // full
! 278: if(w==h) { // circle?
! 279: /* Bresenham octant code, which I should use eventually */
! 280: int x, y, d;
! 281: x = 0;
! 282: y = w/2;
! 283: d = 3-w;
! 284: while (x <= y) {
! 285: SetPixel(cx+x, cy+y, color);
! 286: SetPixel(cx+x, cy-y, color);
! 287: SetPixel(cx-x, cy+y, color);
! 288: SetPixel(cx-x, cy-y, color);
! 289: SetPixel(cx+y, cy+x, color);
! 290: SetPixel(cx+y, cy-x, color);
! 291: SetPixel(cx-y, cy+x, color);
! 292: SetPixel(cx-y, cy-x, color);
! 293: if (d < 0) {
! 294: d += 4 * x + 6;
! 295: } else {
! 296: d += 4 * (x - y) + 10;
! 297: y--;
! 298: }
! 299: x++;
! 300: }
! 301: } else { // full ellipse
! 302: w/=2;
! 303: h/=2;
! 304: int elx, ely;
! 305: long aa, aa2, bb, bb2, d, dx, dy;
! 306:
! 307: elx = 0; ely = h; aa = (long)w * w; aa2 = 2 * aa;
! 308: bb = (long)h * h; bb2 = 2 * bb;
! 309: d = bb - aa * h + aa/4; dx = 0; dy = aa2 * h;
! 310: SetPixel(cx, cy - ely, color); SetPixel(cx, cy + ely, color);
! 311: SetPixel(cx - w, cy, color); SetPixel(cx + w, cy, color);
! 312:
! 313: while (dx < dy)
! 314: {
! 315: if (d > 0) { ely--; dy-=aa2; d-=dy;}
! 316: elx++; dx+=bb2; d+=bb+dx;
! 317: SetPixel(cx + elx, cy + ely, color);
! 318: SetPixel(cx - elx, cy + ely, color);
! 319: SetPixel(cx + elx, cy - ely, color);
! 320: SetPixel(cx - elx, cy - ely, color);
! 321: };
! 322: d+=(3 * (aa - bb)/2 - (dx + dy))/2;
! 323: while (ely > 0)
! 324: {
! 325: if (d < 0) {elx++; dx+=bb2; d+=bb + dx;}
! 326: ely--; dy-=aa2; d+=aa - dy;
! 327: SetPixel(cx + elx, cy + ely, color);
! 328: SetPixel(cx - elx, cy + ely, color);
! 329: SetPixel(cx + elx, cy - ely, color);
! 330: SetPixel(cx - elx, cy - ely, color);
! 331: };
! 332: }
! 333: } else {
! 334: #endif
! 335: int i;
! 336: int lx = 0, ly = 0;
! 337: int w2, h2;
! 338: w2 = w/2;
! 339: h2 = h/2;
! 340: while (e < s) e += 360;
! 341: // paf
! 342: while(s<0) s+=360;
! 343: while(s>360) s-=360;
! 344: while(e<0) e+=360;
! 345: while(e>360) e-=360;
! 346: for (i=s; (i <= e); i++) {
! 347: int x, y;
! 348: x = ((long)cost[i] * (long)w2 / costScale) + cx;
! 349: y = ((long)sint[i] * (long)h2 / sintScale) + cy;
! 350: if (i != s) {
! 351: Line(lx, ly, x, y, color);
! 352: }
! 353: lx = x;
! 354: ly = y;
! 355: }
! 356: #if 0
! 357: }
! 358: #endif
! 359: }
! 360:
! 361: /*
! 362:
! 363: // http://firststeps.narod.ru/cgi/18.html
! 364:
! 365: int CGIScreen::Ellipse(int exc, int eyc, int ea, int eb , unsigned char Color)
! 366: {
! 367: int elx, ely;
! 368: long aa, aa2, bb, bb2, d, dx, dy;
! 369:
! 370: elx = 0; ely = eb; aa = (long)ea * ea; aa2 = 2 * aa;
! 371: bb = (long)eb * eb; bb2 = 2 * bb;
! 372: d = bb - aa * eb + aa/4; dx = 0; dy = aa2 * eb;
! 373: PutPixel(exc, eyc - ely, Color); PutPixel(exc, eyc + ely, Color);
! 374: PutPixel(exc - ea, eyc, Color); PutPixel(exc + ea, eyc, Color);
! 375:
! 376: while (dx < dy)
! 377: {
! 378: if (d > 0) { ely--; dy-=aa2; d-=dy;}
! 379: elx++; dx+=bb2; d+=bb+dx;
! 380: PutPixel(exc + elx, eyc + ely, Color);
! 381: PutPixel(exc - elx, eyc + ely, Color);
! 382: PutPixel(exc + elx, eyc - ely, Color);
! 383: PutPixel(exc - elx, eyc - ely, Color);
! 384: };
! 385: d+=(3 * (aa - bb)/2 - (dx + dy))/2;
! 386: while (ely > 0)
! 387: {
! 388: if (d < 0) {elx++; dx+=bb2; d+=bb + dx;}
! 389: ely--; dy-=aa2; d+=aa - dy;
! 390: PutPixel(exc + elx, eyc + ely, Color);
! 391: PutPixel(exc - elx, eyc + ely, Color);
! 392: PutPixel(exc + elx, eyc - ely, Color);
! 393: PutPixel(exc - elx, eyc - ely, Color);
! 394: };
! 395: return 0;
! 396: };
! 397:
! 398: */
! 399:
! 400:
! 401: void gdImage::Sector(int cx, int cy, int w, int h, int s, int e, int color)
! 402: {
! 403: int i;
! 404: int lx = 0, ly = 0;
! 405: int w2, h2;
! 406: w2 = w/2;
! 407: h2 = h/2;
! 408: while (e < s) e += 360;
! 409: // paf
! 410: while(s<0) s+=360;
! 411: while(s>360) s-=360;
! 412: while(e<0) e+=360;
! 413: while(e>360) e-=360;
! 414: for (i=s; (i <= e); i++) {
! 415: int x, y;
! 416: x = ((long)cost[i] * (long)w2 / costScale) + cx;
! 417: y = ((long)sint[i] * (long)h2 / sintScale) + cy;
! 418: if(i==s || i==e)
! 419: Line(cx, cy, x, y, color);
! 420: if (i != s) {
! 421: Line(lx, ly, x, y, color);
! 422: }
! 423: lx = x;
! 424: ly = y;
! 425: }
! 426: }
! 427:
! 428:
! 429:
! 430: void gdImage::FillToBorder(int x, int y, int border, int color)
! 431: {
! 432: if(!BoundsSafe(x, y)) //PAF
! 433: return;
! 434:
! 435: int lastBorder;
! 436: /* Seek left */
! 437: int leftLimit, rightLimit;
! 438: int i;
! 439: leftLimit = (-1);
! 440: if (border < 0) {
! 441: /* Refuse to fill to a non-solid border */
! 442: return;
! 443: }
! 444: for (i = x; (i >= 0); i--) {
! 445: if (GetPixel(i, y) == border) {
! 446: break;
! 447: }
! 448: SetPixel(i, y, color);
! 449: leftLimit = i;
! 450: }
! 451: if (leftLimit == (-1)) {
! 452: return;
! 453: }
! 454: /* Seek right */
! 455: rightLimit = x;
! 456: for (i = (x+1); (i < sx); i++) {
! 457: if (GetPixel(i, y) == border) {
! 458: break;
! 459: }
! 460: SetPixel(i, y, color);
! 461: rightLimit = i;
! 462: }
! 463: /* Look at lines above and below and start paints */
! 464: /* Above */
! 465: if (y > 0) {
! 466: lastBorder = 1;
! 467: for (i = leftLimit; (i <= rightLimit); i++) {
! 468: int c;
! 469: c = GetPixel(i, y-1);
! 470: if (lastBorder) {
! 471: if ((c != border) && (c != color)) {
! 472: FillToBorder(i, y-1,
! 473: border, color);
! 474: lastBorder = 0;
! 475: }
! 476: } else if ((c == border) || (c == color)) {
! 477: lastBorder = 1;
! 478: }
! 479: }
! 480: }
! 481: /* Below */
! 482: if (y < ((sy) - 1)) {
! 483: lastBorder = 1;
! 484: for (i = leftLimit; (i <= rightLimit); i++) {
! 485: int c;
! 486: c = GetPixel(i, y+1);
! 487: if (lastBorder) {
! 488: if ((c != border) && (c != color)) {
! 489: FillToBorder(i, y+1,
! 490: border, color);
! 491: lastBorder = 0;
! 492: }
! 493: } else if ((c == border) || (c == color)) {
! 494: lastBorder = 1;
! 495: }
! 496: }
! 497: }
! 498: }
! 499:
! 500: void gdImage::Fill(int x, int y, int color)
! 501: {
! 502: if(!BoundsSafe(x, y)) //PAF
! 503: return;
! 504:
! 505: int lastBorder;
! 506: int old;
! 507: int leftLimit, rightLimit;
! 508: int i;
! 509: old = GetPixel(x, y);
! 510: if (old == color) {
! 511: /* Nothing to be done */
! 512: return;
! 513: }
! 514: /* Seek left */
! 515: leftLimit = (-1);
! 516: for (i = x; (i >= 0); i--) {
! 517: if (GetPixel(i, y) != old) {
! 518: break;
! 519: }
! 520: SetPixel(i, y, color);
! 521: leftLimit = i;
! 522: }
! 523: if (leftLimit == (-1)) {
! 524: return;
! 525: }
! 526: /* Seek right */
! 527: rightLimit = x;
! 528: for (i = (x+1); (i < sx); i++) {
! 529: if (GetPixel(i, y) != old) {
! 530: break;
! 531: }
! 532: SetPixel(i, y, color);
! 533: rightLimit = i;
! 534: }
! 535: /* Look at lines above and below and start paints */
! 536: /* Above */
! 537: if (y > 0) {
! 538: lastBorder = 1;
! 539: for (i = leftLimit; (i <= rightLimit); i++) {
! 540: int c;
! 541: c = GetPixel(i, y-1);
! 542: if (lastBorder) {
! 543: if (c == old) {
! 544: Fill(i, y-1, color);
! 545: lastBorder = 0;
! 546: }
! 547: } else if (c != old) {
! 548: lastBorder = 1;
! 549: }
! 550: }
! 551: }
! 552: /* Below */
! 553: if (y < ((sy) - 1)) {
! 554: lastBorder = 1;
! 555: for (i = leftLimit; (i <= rightLimit); i++) {
! 556: int c;
! 557: c = GetPixel(i, y+1);
! 558: if (lastBorder) {
! 559: if (c == old) {
! 560: Fill(i, y+1, color);
! 561: lastBorder = 0;
! 562: }
! 563: } else if (c != old) {
! 564: lastBorder = 1;
! 565: }
! 566: }
! 567: }
! 568: }
! 569:
! 570: void gdImage::Rectangle(int x1, int y1, int x2, int y2, int color)
! 571: {
! 572: Line(x1, y1, x2, y1, color);
! 573: Line(x1, y2, x2, y2, color);
! 574: Line(x1, y1, x1, y2, color);
! 575: Line(x2, y1, x2, y2, color);
! 576: }
! 577:
! 578: void gdImage::FilledRectangle(int x1, int y1, int x2, int y2, int color)
! 579: {
! 580: if(x1>x2) {
! 581: int t=x1;
! 582: x1=x2;
! 583: x2=t;
! 584: }
! 585: if(y1>y2) {
! 586: int t=y1;
! 587: y1=y2;
! 588: y2=t;
! 589: }
! 590: int x, y;
! 591:
! 592: for (y=y1; (y<=y2); y++)
! 593: for (x=x1; (x<=x2); x++)
! 594: SetPixel(x, y, color);
! 595: }
! 596:
! 597: void gdImage::Copy(gdImage& dst, int dstX, int dstY, int srcX, int srcY, int w, int h)
! 598: {
! 599: int c;
! 600: int x, y;
! 601: int tox, toy;
! 602: int i;
! 603: int colorMap[gdMaxColors];
! 604: for (i=0; (i<gdMaxColors); i++) {
! 605: colorMap[i] = (-1);
! 606: }
! 607: toy = dstY;
! 608: for (y=srcY; (y < (srcY + h)); y++) {
! 609: tox = dstX;
! 610: for (x=srcX; (x < (srcX + w)); x++) {
! 611: int nc;
! 612: c = GetPixel(x, y);
! 613: /* Added 7/24/95: support transparent copies */
! 614: if (GetTransparent() == c) {
! 615: tox++;
! 616: continue;
! 617: }
! 618: /* Have we established a mapping for this color? */
! 619: if (colorMap[c] == (-1)) {
! 620: /* If it's the same image, mapping is trivial */
! 621: if (&dst == this) {
! 622: nc = c;
! 623: } else {
! 624: /* First look for an exact match */
! 625: nc = dst.ColorExact(
! 626: red[c], green[c],
! 627: blue[c]);
! 628: }
! 629: if (nc == (-1)) {
! 630: /* No, so try to allocate it */
! 631: nc = dst.ColorAllocate(
! 632: red[c], green[c],
! 633: blue[c]);
! 634: /* If we're out of colors, go for the
! 635: closest color */
! 636: if (nc == (-1)) {
! 637: nc = dst.ColorClosest(
! 638: red[c], green[c],
! 639: blue[c]);
! 640: }
! 641: }
! 642: colorMap[c] = nc;
! 643: }
! 644: dst.SetPixel(tox, toy, colorMap[c]);
! 645: tox++;
! 646: }
! 647: toy++;
! 648: }
! 649: }
! 650:
! 651: void gdImage::CopyResampled(gdImage& dst,
! 652: int dstX, int dstY,
! 653: int /*srcX*/, int /*srcY*/,
! 654: int dstW, int dstH,
! 655: int srcW, int srcH,
! 656: int tolerance)
! 657: {
! 658: gdImage& src=*this;
! 659: int x, y;
! 660: int srcTransparent=src.GetTransparent();
! 661: int dstTransparent=dst.GetTransparent();
! 662: for (y = dstY; (y < dstY + dstH); y++) {
! 663: for (x = dstX; (x < dstX + dstW); x++) {
! 664: int pd = dst.GetPixel (x, y);
! 665: /* Added 7/24/95: support transparent copies */
! 666: /* fixed by paf 20030116, another fix below */
! 667: if (pd == dstTransparent)
! 668: continue;
! 669:
! 670: double sy1, sy2, sx1, sx2;
! 671: double sx, sy;
! 672: double spixels = 0;
! 673: double red = 0.0, green = 0.0, blue = 0.0;
! 674: bool transparent=true;
! 675: sy1 = ((double) y - (double) dstY) * (double) srcH /
! 676: (double) dstH;
! 677: sy2 = ((double) (y + 1) - (double) dstY) * (double) srcH /
! 678: (double) dstH;
! 679: sy = sy1;
! 680: do
! 681: {
! 682: double yportion;
! 683: if (floor (sy) == floor (sy1))
! 684: {
! 685: yportion = 1.0 - (sy - floor (sy));
! 686: if (yportion > sy2 - sy1)
! 687: {
! 688: yportion = sy2 - sy1;
! 689: }
! 690: sy = floor (sy);
! 691: }
! 692: else if (sy == floor (sy2))
! 693: {
! 694: yportion = sy2 - floor (sy2);
! 695: }
! 696: else
! 697: {
! 698: yportion = 1.0;
! 699: }
! 700: sx1 = ((double) x - (double) dstX) * (double) srcW /
! 701: dstW;
! 702: sx2 = ((double) (x + 1) - (double) dstX) * (double) srcW /
! 703: dstW;
! 704: sx = sx1;
! 705: do
! 706: {
! 707: double xportion;
! 708: double pcontribution;
! 709: int p;
! 710: if (floor (sx) == floor (sx1))
! 711: {
! 712: xportion = 1.0 - (sx - floor (sx));
! 713: if (xportion > sx2 - sx1)
! 714: {
! 715: xportion = sx2 - sx1;
! 716: }
! 717: sx = floor (sx);
! 718: }
! 719: else if (sx == floor (sx2))
! 720: {
! 721: xportion = sx2 - floor (sx2);
! 722: }
! 723: else
! 724: {
! 725: xportion = 1.0;
! 726: }
! 727: pcontribution = xportion * yportion;
! 728: p = src.GetPixel (
! 729: (int) sx,
! 730: (int) sy);
! 731: // fix added 20020116 by paf to support transparent src
! 732: if (p!=srcTransparent) {
! 733: transparent = false;
! 734: red += Red (p) * pcontribution;
! 735: green += Green (p) * pcontribution;
! 736: blue += Blue (p) * pcontribution;
! 737: }
! 738: spixels += xportion * yportion;
! 739: sx += 1.0;
! 740: } while (sx < sx2);
! 741: sy += 1.0;
! 742: } while (sy < sy2);
! 743:
! 744: if(transparent)
! 745: continue;
! 746:
! 747: if (spixels != 0.0) {
! 748: red /= spixels;
! 749: green /= spixels;
! 750: blue /= spixels;
! 751: }
! 752: /* Clamping to allow for rounding errors above */
! 753: if (red > 255.0)
! 754: red = 255.0;
! 755: if (green > 255.0)
! 756: green = 255.0;
! 757: if (blue > 255.0)
! 758: blue = 255.0;
! 759:
! 760: red=round(red);
! 761: green=round(green);
! 762: blue=round(blue);
! 763: /* First look for an exact match */
! 764: int nc = dst.ColorExact((int)red, (int)green, (int)blue);
! 765: if (nc == (-1)) {
! 766: /* No, so go for the closest color with high tolerance */
! 767: nc = dst.ColorClosest((int)red, (int)green, (int)blue, tolerance);
! 768: if (nc == (-1)) {
! 769: /* Not found with even high tolerance, so try to allocate it */
! 770: nc = dst.ColorAllocate((int)red, (int)green, (int)blue);
! 771:
! 772: /* If we're out of colors, go for the closest color */
! 773: if (nc == (-1))
! 774: nc = dst.ColorClosest((int)red, (int)green, (int)blue);
! 775: }
! 776: }
! 777: dst.SetPixel(x, y, nc);
! 778: }
! 779: }
! 780: }
! 781:
! 782: void gdImage::Polygon(Point *p, int n, int c, bool closed)
! 783: {
! 784: int i;
! 785: int lx, ly;
! 786: if (!n) {
! 787: return;
! 788: }
! 789: lx = p->x;
! 790: ly = p->y;
! 791: if(closed)
! 792: Line(lx, ly, p[n-1].x, p[n-1].y, c);
! 793: for (i=1; (i < n); i++) {
! 794: p++;
! 795: Line(lx, ly, p->x, p->y, c);
! 796: lx = p->x;
! 797: ly = p->y;
! 798: }
! 799: }
! 800:
! 801: static int gdCompareInt(const void *a, const void *b)
! 802: {
! 803: return (*(const int *)a) - (*(const int *)b);
! 804: }
! 805:
! 806:
! 807:
! 808: void gdImage::FilledPolygon(Point *p, int n, int c)
! 809: {
! 810: int i;
! 811: int y;
! 812: int y1, y2;
! 813: int ints;
! 814: if (!n) {
! 815: return;
! 816: }
! 817: if (!polyAllocated) {
! 818: polyInts = (int *) malloc(sizeof(int) * n);
! 819: polyAllocated = n;
! 820: }
! 821: if (polyAllocated < n) {
! 822: while (polyAllocated < n) {
! 823: polyAllocated *= 2;
! 824: }
! 825: polyInts = (int *) realloc(polyInts,
! 826: sizeof(int) * polyAllocated);
! 827: }
! 828: y1 = p[0].y;
! 829: y2 = p[0].y;
! 830: for (i=1; (i < n); i++) {
! 831: if (p[i].y < y1) {
! 832: y1 = p[i].y;
! 833: }
! 834: if (p[i].y > y2) {
! 835: y2 = p[i].y;
! 836: }
! 837: }
! 838: for (y=y1; (y <= y2); y++) {
! 839: int interLast = 0;
! 840: int dirLast = 0;
! 841: int interFirst = 1;
! 842: ints = 0;
! 843: for (i=0; (i <= n); i++) {
! 844: int x1, x2;
! 845: int y1, y2;
! 846: int dir;
! 847: int ind1, ind2;
! 848: int lastInd1 = 0;
! 849: if ((i == n) || (!i)) {
! 850: ind1 = n-1;
! 851: ind2 = 0;
! 852: } else {
! 853: ind1 = i-1;
! 854: ind2 = i;
! 855: }
! 856: y1 = p[ind1].y;
! 857: y2 = p[ind2].y;
! 858: if (y1 < y2) {
! 859: y1 = p[ind1].y;
! 860: y2 = p[ind2].y;
! 861: x1 = p[ind1].x;
! 862: x2 = p[ind2].x;
! 863: dir = -1;
! 864: } else if (y1 > y2) {
! 865: y2 = p[ind1].y;
! 866: y1 = p[ind2].y;
! 867: x2 = p[ind1].x;
! 868: x1 = p[ind2].x;
! 869: dir = 1;
! 870: } else {
! 871: /* Horizontal; just draw it */
! 872: Line(
! 873: p[ind1].x, y1,
! 874: p[ind2].x, y1,
! 875: c);
! 876: continue;
! 877: }
! 878: if ((y >= y1) && (y <= y2)) {
! 879: int inter =
! 880: (y-y1) * (x2-x1) / (y2-y1) + x1;
! 881: /* Only count intersections once
! 882: except at maxima and minima. Also,
! 883: if two consecutive intersections are
! 884: endpoints of the same horizontal line
! 885: that is not at a maxima or minima,
! 886: discard the leftmost of the two. */
! 887: if (!interFirst) {
! 888: if ((p[ind1].y == p[lastInd1].y) &&
! 889: (p[ind1].x != p[lastInd1].x)) {
! 890: if (dir == dirLast) {
! 891: if (inter > interLast) {
! 892: /* Replace the old one */
! 893: polyInts[ints] = inter;
! 894: } else {
! 895: /* Discard this one */
! 896: }
! 897: continue;
! 898: }
! 899: }
! 900: if (inter == interLast) {
! 901: if (dir == dirLast) {
! 902: continue;
! 903: }
! 904: }
! 905: }
! 906: if (i > 0) {
! 907: polyInts[ints++] = inter;
! 908: }
! 909: lastInd1 = i;
! 910: dirLast = dir;
! 911: interLast = inter;
! 912: interFirst = 0;
! 913: }
! 914: }
! 915: qsort(polyInts, ints, sizeof(int), gdCompareInt);
! 916: for (i=0; (i < (ints-1)); i+=2)
! 917: Line(polyInts[i], y, polyInts[i+1], y, c);
! 918: }
! 919: }
! 920:
! 921: //001005paf this used in drawing straight lines in gdImage::FilledPolygonReplaceColor
! 922: void gdImage::LineReplaceColor(int x1, int y1, int x2, int y2, int a, int b) {
! 923: if(y1!=y2)
! 924: return;
! 925:
! 926: for(int x=x1; x<=x2; x++)
! 927: if(BoundsSafe(x, y1)) {
! 928: unsigned char *pixel=&pixels[x][y1];
! 929: if(*pixel==a)
! 930: *pixel=b;
! 931: }
! 932: }
! 933:
! 934: void gdImage::FilledPolygonReplaceColor(Point *p, int n, int a, int b)
! 935: {
! 936: int i;
! 937: int y;
! 938: int y1, y2;
! 939: int ints;
! 940: if (!n) {
! 941: return;
! 942: }
! 943: if (!polyAllocated) {
! 944: polyInts = (int *) malloc(sizeof(int) * n);
! 945: polyAllocated = n;
! 946: }
! 947: if (polyAllocated < n) {
! 948: while (polyAllocated < n) {
! 949: polyAllocated *= 2;
! 950: }
! 951: polyInts = (int *) realloc(polyInts,
! 952: sizeof(int) * polyAllocated);
! 953: }
! 954: y1 = p[0].y;
! 955: y2 = p[0].y;
! 956: for (i=1; (i < n); i++) {
! 957: if (p[i].y < y1) {
! 958: y1 = p[i].y;
! 959: }
! 960: if (p[i].y > y2) {
! 961: y2 = p[i].y;
! 962: }
! 963: }
! 964: for (y=y1; (y <= y2); y++) {
! 965: int interLast = 0;
! 966: int dirLast = 0;
! 967: int interFirst = 1;
! 968: ints = 0;
! 969: for (i=0; (i <= n); i++) {
! 970: int x1, x2;
! 971: int y1, y2;
! 972: int dir;
! 973: int ind1, ind2;
! 974: int lastInd1 = 0;
! 975: if ((i == n) || (!i)) {
! 976: ind1 = n-1;
! 977: ind2 = 0;
! 978: } else {
! 979: ind1 = i-1;
! 980: ind2 = i;
! 981: }
! 982: y1 = p[ind1].y;
! 983: y2 = p[ind2].y;
! 984: if (y1 < y2) {
! 985: y1 = p[ind1].y;
! 986: y2 = p[ind2].y;
! 987: x1 = p[ind1].x;
! 988: x2 = p[ind2].x;
! 989: dir = -1;
! 990: } else if (y1 > y2) {
! 991: y2 = p[ind1].y;
! 992: y1 = p[ind2].y;
! 993: x2 = p[ind1].x;
! 994: x1 = p[ind2].x;
! 995: dir = 1;
! 996: } else {
! 997: /* Horizontal; just draw it */
! 998: LineReplaceColor(
! 999: p[ind1].x, y1,
! 1000: p[ind2].x, y1,
! 1001: a,b);
! 1002: continue;
! 1003: }
! 1004: if ((y >= y1) && (y <= y2)) {
! 1005: int inter =
! 1006: (y-y1) * (x2-x1) / (y2-y1) + x1;
! 1007: /* Only count intersections once
! 1008: except at maxima and minima. Also,
! 1009: if two consecutive intersections are
! 1010: endpoints of the same horizontal line
! 1011: that is not at a maxima or minima,
! 1012: discard the leftmost of the two. */
! 1013: if (!interFirst) {
! 1014: if ((p[ind1].y == p[lastInd1].y) &&
! 1015: (p[ind1].x != p[lastInd1].x)) {
! 1016: if (dir == dirLast) {
! 1017: if (inter > interLast) {
! 1018: /* Replace the old one */
! 1019: polyInts[ints] = inter;
! 1020: } else {
! 1021: /* Discard this one */
! 1022: }
! 1023: continue;
! 1024: }
! 1025: }
! 1026: if (inter == interLast) {
! 1027: if (dir == dirLast) {
! 1028: continue;
! 1029: }
! 1030: }
! 1031: }
! 1032: if (i > 0) {
! 1033: polyInts[ints++] = inter;
! 1034: }
! 1035: lastInd1 = i;
! 1036: dirLast = dir;
! 1037: interLast = inter;
! 1038: interFirst = 0;
! 1039: }
! 1040: }
! 1041: qsort(polyInts, ints, sizeof(int), gdCompareInt);
! 1042: for (i=0; (i < (ints-1)); i+=2) {
! 1043: LineReplaceColor(polyInts[i], y,
! 1044: polyInts[i+1], y, a,b);
! 1045: }
! 1046: }
! 1047: }
! 1048:
! 1049: void gdImage::SetInterlace(int interlaceArg)
! 1050: {
! 1051: interlace = interlaceArg;
! 1052: }
! 1053:
! 1054: void gdImage::SetLineWidth(int width)
! 1055: {
! 1056: lineWidth=width;
! 1057: }
! 1058:
! 1059: void gdImage::SetLineStyle(const char* alineStyle)
! 1060: {
! 1061: lineStyle=alineStyle;
! 1062: }
! 1063:
E-mail: