|
|
1.3 paf 1: /** @file
2: Parser: image manipulations impl1.
3:
1.9 parser 4: Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
1.3 paf 5: Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
1.8 parser 6:
1.14 ! parser 7: $Id: gif.C,v 1.13 2001/10/08 16:06:49 parser Exp $
1.9 parser 8:
9: based on: gd
10:
11: Written by Tom Boutell, 5/94.
12: Copyright 1994, Cold Spring Harbor Labs.
13: Permission granted to use this code in any fashion provided
14: that this notice is retained and any alterations are
15: labeled as such. It is requested, but not required, that
16: you share extensions to this module with us so that we
17: can incorporate them into new versions.
1.3 paf 18: */
19:
1.1 paf 20: #include "gif.h"
21:
1.11 parser 22: #include "mtables.h"
23:
1.2 paf 24: //static void BrushApply(int x, int y);
25: //static void TileApply(int x, int y);
1.1 paf 26:
1.2 paf 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;
1.6 parser 35: lineWidth = 1; lineStyle=0;
1.2 paf 36: for (i=0; (i<asx); i++)
37: pixels[i] = (unsigned char *) calloc(asy);
38: colorsTotal = 0;
39: transparent = (-1);
40: interlace = 0;
1.1 paf 41: }
42:
1.2 paf 43: int gdImage::ColorClosest(int r, int g, int b)
1.1 paf 44: {
45: int i;
46: long rd, gd, bd;
47: int ct = (-1);
48: long mindist = 0;
1.2 paf 49: for (i=0; (i<(colorsTotal)); i++) {
1.1 paf 50: long dist;
1.2 paf 51: if (open[i]) {
1.1 paf 52: continue;
53: }
1.2 paf 54: rd = (red[i] - r);
55: gd = (green[i] - g);
56: bd = (blue[i] - b);
1.1 paf 57: dist = rd * rd + gd * gd + bd * bd;
58: if ((i == 0) || (dist < mindist)) {
59: mindist = dist;
60: ct = i;
61: }
62: }
63: return ct;
64: }
65:
1.2 paf 66: int gdImage::ColorExact(int r, int g, int b)
1.1 paf 67: {
68: int i;
1.2 paf 69: for (i=0; (i<(colorsTotal)); i++) {
70: if (open[i]) {
1.1 paf 71: continue;
72: }
1.2 paf 73: if ((red[i] == r) &&
74: (green[i] == g) &&
75: (blue[i] == b)) {
1.1 paf 76: return i;
77: }
78: }
79: return -1;
80: }
81:
1.2 paf 82: int gdImage::ColorAllocate(int r, int g, int b)
1.1 paf 83: {
84: int i;
85: int ct = (-1);
1.2 paf 86: for (i=0; (i<(colorsTotal)); i++) {
87: if (open[i]) {
1.1 paf 88: ct = i;
89: break;
90: }
91: }
92: if (ct == (-1)) {
1.2 paf 93: ct = colorsTotal;
1.1 paf 94: if (ct == gdMaxColors) {
95: return -1;
96: }
1.2 paf 97: colorsTotal++;
1.1 paf 98: }
1.2 paf 99: red[ct] = r;
100: green[ct] = g;
101: blue[ct] = b;
102: open[ct] = 0;
1.1 paf 103: return ct;
104: }
105:
1.2 paf 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;
1.1 paf 109: }
110:
1.2 paf 111: int gdImage::Color(unsigned int rgb){
1.1 paf 112: unsigned int b=rgb, g=b>>8, r=g>>8;
1.2 paf 113: return ColorRGB(r & 0xFF,g & 0xFF,b & 0xFF);
1.1 paf 114: }
115:
1.2 paf 116: void gdImage::ColorDeallocate(int color)
1.1 paf 117: {
118: /* Mark it open. */
1.2 paf 119: open[color] = 1;
1.1 paf 120: }
121:
1.2 paf 122: void gdImage::SetColorTransparent(int color)
1.1 paf 123: {
1.2 paf 124: transparent = color;
1.1 paf 125: }
126:
127:
1.2 paf 128: void gdImage::SetPixel(int x, int y, int color)
1.1 paf 129: {
130: //paf int p;
131:
1.6 parser 132: switch (lineWidth){
1.1 paf 133: case 1: {
1.2 paf 134: DoSetPixel(x, y,color);
1.1 paf 135: return;
136: }
137: case 2: {
1.2 paf 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);
1.1 paf 143: return;
144: }
145: default:{
146: int i,j;
1.2 paf 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);
1.1 paf 150: return;
151: }
152: }
153: }
154:
1.2 paf 155: int gdImage::GetPixel(int x, int y)
1.1 paf 156: {
1.2 paf 157: return BoundsSafe(x, y) ? pixels[x][y]:0;
1.1 paf 158: }
159:
160: /* Bresenham as presented in Foley & Van Dam */
161:
162: /* As above, plus dashing */
163:
1.6 parser 164: #define styledSet \
1.1 paf 165: { \
1.6 parser 166: if (lineStyle) { \
167: if(!lineStyle[styleStep]) \
168: styleStep = 0; \
169: on=lineStyle[styleStep++]!=' '; \
1.1 paf 170: } \
171: if (on) { \
1.2 paf 172: SetPixel(x, y, color); \
1.1 paf 173: } \
174: }
175:
1.6 parser 176: void gdImage::Line(int x1, int y1, int x2, int y2, int color)
1.1 paf 177: {
178: int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
1.6 parser 179: int styleStep = 0;
1.1 paf 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: }
1.6 parser 198: styledSet;
1.1 paf 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: }
1.6 parser 208: styledSet;
1.1 paf 209: }
210: } else {
211: while (x < xend) {
212: x++;
213: if (d <0) {
214: d+=incr1;
215: } else {
216: y--;
217: d+=incr2;
218: }
1.6 parser 219: styledSet;
1.1 paf 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: }
1.6 parser 237: styledSet;
1.1 paf 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: }
1.6 parser 247: styledSet;
1.1 paf 248: }
249: } else {
250: while (y < yend) {
251: y++;
252: if (d <0) {
253: d+=incr1;
254: } else {
255: x--;
256: d+=incr2;
257: }
1.6 parser 258: styledSet;
1.1 paf 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). */
1.11 parser 273:
274: void gdImage::Arc(int cx, int cy, int w, int h, int s, int e, int color)
275: {
1.14 ! parser 276: if(s==0 && e==360) { // full
! 277: if(w==h) { // circle?
! 278: /* Bresenham octant code, which I should use eventually */
! 279: int x, y, d;
! 280: x = 0;
! 281: y = w/2;
! 282: d = 3-w;
! 283: while (x <= y) {
! 284: SetPixel(cx+x, cy+y, color);
! 285: SetPixel(cx+x, cy-y, color);
! 286: SetPixel(cx-x, cy+y, color);
! 287: SetPixel(cx-x, cy-y, color);
! 288: SetPixel(cx+y, cy+x, color);
! 289: SetPixel(cx+y, cy-x, color);
! 290: SetPixel(cx-y, cy+x, color);
! 291: SetPixel(cx-y, cy-x, color);
! 292: if (d < 0) {
! 293: d += 4 * x + 6;
! 294: } else {
! 295: d += 4 * (x - y) + 10;
! 296: y--;
! 297: }
! 298: x++;
! 299: }
! 300: } else { // full ellipse
! 301: w/=2;
! 302: h/=2;
! 303: int elx, ely;
! 304: long aa, aa2, bb, bb2, d, dx, dy;
! 305:
! 306: elx = 0; ely = h; aa = (long)w * w; aa2 = 2 * aa;
! 307: bb = (long)h * h; bb2 = 2 * bb;
! 308: d = bb - aa * h + aa/4; dx = 0; dy = aa2 * h;
! 309: SetPixel(cx, cy - ely, color); SetPixel(cx, cy + ely, color);
! 310: SetPixel(cx - w, cy, color); SetPixel(cx + w, cy, color);
! 311:
! 312: while (dx < dy)
! 313: {
! 314: if (d > 0) { ely--; dy-=aa2; d-=dy;}
! 315: elx++; dx+=bb2; d+=bb+dx;
! 316: SetPixel(cx + elx, cy + ely, color);
! 317: SetPixel(cx - elx, cy + ely, color);
! 318: SetPixel(cx + elx, cy - ely, color);
! 319: SetPixel(cx - elx, cy - ely, color);
! 320: };
! 321: d+=(3 * (aa - bb)/2 - (dx + dy))/2;
! 322: while (ely > 0)
! 323: {
! 324: if (d < 0) {elx++; dx+=bb2; d+=bb + dx;}
! 325: ely--; dy-=aa2; d+=aa - dy;
! 326: SetPixel(cx + elx, cy + ely, color);
! 327: SetPixel(cx - elx, cy + ely, color);
! 328: SetPixel(cx + elx, cy - ely, color);
! 329: SetPixel(cx - elx, cy - ely, color);
! 330: };
! 331: }
! 332: } else {
1.13 parser 333: int i;
334: int lx = 0, ly = 0;
335: int w2, h2;
336: w2 = w/2;
337: h2 = h/2;
338: while (e < s) {
339: e += 360;
340: }
341: for (i=s; (i <= e); i++) {
342: int x, y;
343: x = ((long)cost[i % 360] * (long)w2 / costScale) + cx;
344: y = ((long)sint[i % 360] * (long)h2 / sintScale) + cy;
345: if (i != s) {
346: Line(lx, ly, x, y, color);
347: }
348: lx = x;
349: ly = y;
350: }
1.11 parser 351: }
352: }
1.14 ! parser 353:
! 354: /*
! 355:
! 356: // http://firststeps.narod.ru/cgi/18.html
! 357:
! 358: int CGIScreen::Ellipse(int exc, int eyc, int ea, int eb , unsigned char Color)
! 359: {
! 360: int elx, ely;
! 361: long aa, aa2, bb, bb2, d, dx, dy;
! 362:
! 363: elx = 0; ely = eb; aa = (long)ea * ea; aa2 = 2 * aa;
! 364: bb = (long)eb * eb; bb2 = 2 * bb;
! 365: d = bb - aa * eb + aa/4; dx = 0; dy = aa2 * eb;
! 366: PutPixel(exc, eyc - ely, Color); PutPixel(exc, eyc + ely, Color);
! 367: PutPixel(exc - ea, eyc, Color); PutPixel(exc + ea, eyc, Color);
! 368:
! 369: while (dx < dy)
! 370: {
! 371: if (d > 0) { ely--; dy-=aa2; d-=dy;}
! 372: elx++; dx+=bb2; d+=bb+dx;
! 373: PutPixel(exc + elx, eyc + ely, Color);
! 374: PutPixel(exc - elx, eyc + ely, Color);
! 375: PutPixel(exc + elx, eyc - ely, Color);
! 376: PutPixel(exc - elx, eyc - ely, Color);
! 377: };
! 378: d+=(3 * (aa - bb)/2 - (dx + dy))/2;
! 379: while (ely > 0)
! 380: {
! 381: if (d < 0) {elx++; dx+=bb2; d+=bb + dx;}
! 382: ely--; dy-=aa2; d+=aa - dy;
! 383: PutPixel(exc + elx, eyc + ely, Color);
! 384: PutPixel(exc - elx, eyc + ely, Color);
! 385: PutPixel(exc + elx, eyc - ely, Color);
! 386: PutPixel(exc - elx, eyc - ely, Color);
! 387: };
! 388: return 0;
! 389: };
! 390:
! 391: */
1.11 parser 392:
1.12 parser 393:
394: void gdImage::Sector(int cx, int cy, int w, int h, int s, int e, int color)
395: {
396: int i;
397: int lx = 0, ly = 0;
398: int w2, h2;
399: w2 = w/2;
400: h2 = h/2;
401: while (e < s) {
402: e += 360;
403: }
404: for (i=s; (i <= e); i++) {
405: int x, y;
406: x = ((long)cost[i % 360] * (long)w2 / costScale) + cx;
407: y = ((long)sint[i % 360] * (long)h2 / sintScale) + cy;
408: if(i==s || i==e)
409: Line(cx, cy, x, y, color);
410: if (i != s) {
411: Line(lx, ly, x, y, color);
412: }
413: lx = x;
414: ly = y;
415: }
416: }
1.11 parser 417:
418:
1.1 paf 419:
1.2 paf 420: void gdImage::FillToBorder(int x, int y, int border, int color)
1.1 paf 421: {
1.4 paf 422: if(!BoundsSafe(x, y)) //PAF
423: return;
424:
1.1 paf 425: int lastBorder;
426: /* Seek left */
427: int leftLimit, rightLimit;
428: int i;
429: leftLimit = (-1);
430: if (border < 0) {
431: /* Refuse to fill to a non-solid border */
432: return;
433: }
434: for (i = x; (i >= 0); i--) {
1.2 paf 435: if (GetPixel(i, y) == border) {
1.1 paf 436: break;
437: }
1.2 paf 438: SetPixel(i, y, color);
1.1 paf 439: leftLimit = i;
440: }
441: if (leftLimit == (-1)) {
442: return;
443: }
444: /* Seek right */
445: rightLimit = x;
1.2 paf 446: for (i = (x+1); (i < sx); i++) {
447: if (GetPixel(i, y) == border) {
1.1 paf 448: break;
449: }
1.2 paf 450: SetPixel(i, y, color);
1.1 paf 451: rightLimit = i;
452: }
453: /* Look at lines above and below and start paints */
454: /* Above */
455: if (y > 0) {
456: lastBorder = 1;
457: for (i = leftLimit; (i <= rightLimit); i++) {
458: int c;
1.2 paf 459: c = GetPixel(i, y-1);
1.1 paf 460: if (lastBorder) {
461: if ((c != border) && (c != color)) {
1.2 paf 462: FillToBorder(i, y-1,
1.1 paf 463: border, color);
464: lastBorder = 0;
465: }
466: } else if ((c == border) || (c == color)) {
467: lastBorder = 1;
468: }
469: }
470: }
471: /* Below */
1.2 paf 472: if (y < ((sy) - 1)) {
1.1 paf 473: lastBorder = 1;
474: for (i = leftLimit; (i <= rightLimit); i++) {
475: int c;
1.2 paf 476: c = GetPixel(i, y+1);
1.1 paf 477: if (lastBorder) {
478: if ((c != border) && (c != color)) {
1.2 paf 479: FillToBorder(i, y+1,
1.1 paf 480: border, color);
481: lastBorder = 0;
482: }
483: } else if ((c == border) || (c == color)) {
484: lastBorder = 1;
485: }
486: }
487: }
488: }
489:
1.2 paf 490: void gdImage::Fill(int x, int y, int color)
1.1 paf 491: {
1.4 paf 492: if(!BoundsSafe(x, y)) //PAF
493: return;
494:
1.1 paf 495: int lastBorder;
496: int old;
497: int leftLimit, rightLimit;
498: int i;
1.2 paf 499: old = GetPixel(x, y);
1.1 paf 500: if (old == color) {
501: /* Nothing to be done */
502: return;
503: }
504: /* Seek left */
505: leftLimit = (-1);
506: for (i = x; (i >= 0); i--) {
1.2 paf 507: if (GetPixel(i, y) != old) {
1.1 paf 508: break;
509: }
1.2 paf 510: SetPixel(i, y, color);
1.1 paf 511: leftLimit = i;
512: }
513: if (leftLimit == (-1)) {
514: return;
515: }
516: /* Seek right */
517: rightLimit = x;
1.2 paf 518: for (i = (x+1); (i < sx); i++) {
519: if (GetPixel(i, y) != old) {
1.1 paf 520: break;
521: }
1.2 paf 522: SetPixel(i, y, color);
1.1 paf 523: rightLimit = i;
524: }
525: /* Look at lines above and below and start paints */
526: /* Above */
527: if (y > 0) {
528: lastBorder = 1;
529: for (i = leftLimit; (i <= rightLimit); i++) {
530: int c;
1.2 paf 531: c = GetPixel(i, y-1);
1.1 paf 532: if (lastBorder) {
533: if (c == old) {
1.2 paf 534: Fill(i, y-1, color);
1.1 paf 535: lastBorder = 0;
536: }
537: } else if (c != old) {
538: lastBorder = 1;
539: }
540: }
541: }
542: /* Below */
1.2 paf 543: if (y < ((sy) - 1)) {
1.1 paf 544: lastBorder = 1;
545: for (i = leftLimit; (i <= rightLimit); i++) {
546: int c;
1.2 paf 547: c = GetPixel(i, y+1);
1.1 paf 548: if (lastBorder) {
549: if (c == old) {
1.2 paf 550: Fill(i, y+1, color);
1.1 paf 551: lastBorder = 0;
552: }
553: } else if (c != old) {
554: lastBorder = 1;
555: }
556: }
557: }
558: }
559:
1.2 paf 560: void gdImage::Rectangle(int x1, int y1, int x2, int y2, int color)
1.1 paf 561: {
1.2 paf 562: Line(x1, y1, x2, y1, color);
563: Line(x1, y2, x2, y2, color);
564: Line(x1, y1, x1, y2, color);
565: Line(x2, y1, x2, y2, color);
1.1 paf 566: }
567:
1.2 paf 568: void gdImage::FilledRectangle(int x1, int y1, int x2, int y2, int color)
1.1 paf 569: {
1.10 parser 570: if(x1>x2) {
571: int t=x1;
572: x1=x2;
573: x2=t;
574: }
575: if(y1>y2) {
576: int t=y1;
577: y1=y2;
578: y2=t;
579: }
1.1 paf 580: int x, y;
1.10 parser 581:
1.2 paf 582: for (y=y1; (y<=y2); y++)
583: for (x=x1; (x<=x2); x++)
584: SetPixel(x, y, color);
1.1 paf 585: }
586:
1.2 paf 587: void gdImage::Copy(gdImage& dst, int dstX, int dstY, int srcX, int srcY, int w, int h)
1.1 paf 588: {
589: int c;
590: int x, y;
591: int tox, toy;
592: int i;
593: int colorMap[gdMaxColors];
594: for (i=0; (i<gdMaxColors); i++) {
595: colorMap[i] = (-1);
596: }
597: toy = dstY;
598: for (y=srcY; (y < (srcY + h)); y++) {
599: tox = dstX;
600: for (x=srcX; (x < (srcX + w)); x++) {
601: int nc;
1.2 paf 602: c = GetPixel(x, y);
1.1 paf 603: /* Added 7/24/95: support transparent copies */
1.2 paf 604: if (GetTransparent() == c) {
1.1 paf 605: tox++;
606: continue;
607: }
608: /* Have we established a mapping for this color? */
609: if (colorMap[c] == (-1)) {
610: /* If it's the same image, mapping is trivial */
1.2 paf 611: if (&dst == this) {
1.1 paf 612: nc = c;
613: } else {
614: /* First look for an exact match */
1.2 paf 615: nc = dst.ColorExact(
616: red[c], green[c],
617: blue[c]);
1.1 paf 618: }
619: if (nc == (-1)) {
620: /* No, so try to allocate it */
1.2 paf 621: nc = dst.ColorAllocate(
622: red[c], green[c],
623: blue[c]);
1.1 paf 624: /* If we're out of colors, go for the
625: closest color */
626: if (nc == (-1)) {
1.2 paf 627: nc = dst.ColorClosest(
628: red[c], green[c],
629: blue[c]);
1.1 paf 630: }
631: }
632: colorMap[c] = nc;
633: }
1.2 paf 634: dst.SetPixel(tox, toy, colorMap[c]);
1.1 paf 635: tox++;
636: }
637: toy++;
638: }
639: }
640:
1.2 paf 641: static int gdGetWord(int *result, FILE *in)
1.1 paf 642: {
643: int r;
644: r = getc(in);
645: if (r == EOF) {
646: return 0;
647: }
648: *result = r << 8;
649: r = getc(in);
650: if (r == EOF) {
651: return 0;
652: }
653: *result += r;
654: return 1;
655: }
656:
1.2 paf 657: static void gdPutWord(int w, FILE *out)
1.1 paf 658: {
659: putc((unsigned char)(w >> 8), out);
660: putc((unsigned char)(w & 0xFF), out);
661: }
662:
1.2 paf 663: static int gdGetByte(int *result, FILE *in)
1.1 paf 664: {
665: int r;
666: r = getc(in);
667: if (r == EOF) {
668: return 0;
669: }
670: *result = r;
671: return 1;
672: }
673:
1.6 parser 674: void gdImage::Polygon(Point *p, int n, int c, bool closed)
1.1 paf 675: {
676: int i;
677: int lx, ly;
678: if (!n) {
679: return;
680: }
681: lx = p->x;
682: ly = p->y;
1.6 parser 683: if(closed)
684: Line(lx, ly, p[n-1].x, p[n-1].y, c);
1.1 paf 685: for (i=1; (i < n); i++) {
686: p++;
1.2 paf 687: Line(lx, ly, p->x, p->y, c);
1.1 paf 688: lx = p->x;
689: ly = p->y;
690: }
691: }
692:
1.5 paf 693: static int gdCompareInt(const void *a, const void *b)
694: {
695: return (*(const int *)a) - (*(const int *)b);
696: }
697:
698:
1.1 paf 699:
1.2 paf 700: void gdImage::FilledPolygon(Point *p, int n, int c)
1.1 paf 701: {
702: int i;
703: int y;
704: int y1, y2;
705: int ints;
706: if (!n) {
707: return;
708: }
1.2 paf 709: if (!polyAllocated) {
710: polyInts = (int *) malloc(sizeof(int) * n);
711: polyAllocated = n;
1.1 paf 712: }
1.2 paf 713: if (polyAllocated < n) {
714: while (polyAllocated < n) {
715: polyAllocated *= 2;
1.1 paf 716: }
1.2 paf 717: polyInts = (int *) realloc(polyInts,
718: sizeof(int) * polyAllocated);
1.1 paf 719: }
720: y1 = p[0].y;
721: y2 = p[0].y;
722: for (i=1; (i < n); i++) {
723: if (p[i].y < y1) {
724: y1 = p[i].y;
725: }
726: if (p[i].y > y2) {
727: y2 = p[i].y;
728: }
729: }
730: for (y=y1; (y <= y2); y++) {
731: int interLast = 0;
732: int dirLast = 0;
733: int interFirst = 1;
734: ints = 0;
735: for (i=0; (i <= n); i++) {
736: int x1, x2;
737: int y1, y2;
738: int dir;
739: int ind1, ind2;
740: int lastInd1 = 0;
741: if ((i == n) || (!i)) {
742: ind1 = n-1;
743: ind2 = 0;
744: } else {
745: ind1 = i-1;
746: ind2 = i;
747: }
748: y1 = p[ind1].y;
749: y2 = p[ind2].y;
750: if (y1 < y2) {
751: y1 = p[ind1].y;
752: y2 = p[ind2].y;
753: x1 = p[ind1].x;
754: x2 = p[ind2].x;
755: dir = -1;
756: } else if (y1 > y2) {
757: y2 = p[ind1].y;
758: y1 = p[ind2].y;
759: x2 = p[ind1].x;
760: x1 = p[ind2].x;
761: dir = 1;
762: } else {
763: /* Horizontal; just draw it */
1.2 paf 764: Line(
1.1 paf 765: p[ind1].x, y1,
766: p[ind2].x, y1,
767: c);
768: continue;
769: }
770: if ((y >= y1) && (y <= y2)) {
771: int inter =
772: (y-y1) * (x2-x1) / (y2-y1) + x1;
773: /* Only count intersections once
774: except at maxima and minima. Also,
775: if two consecutive intersections are
776: endpoints of the same horizontal line
777: that is not at a maxima or minima,
778: discard the leftmost of the two. */
779: if (!interFirst) {
780: if ((p[ind1].y == p[lastInd1].y) &&
781: (p[ind1].x != p[lastInd1].x)) {
782: if (dir == dirLast) {
783: if (inter > interLast) {
784: /* Replace the old one */
1.2 paf 785: polyInts[ints] = inter;
1.1 paf 786: } else {
787: /* Discard this one */
788: }
789: continue;
790: }
791: }
792: if (inter == interLast) {
793: if (dir == dirLast) {
794: continue;
795: }
796: }
797: }
798: if (i > 0) {
1.2 paf 799: polyInts[ints++] = inter;
1.1 paf 800: }
801: lastInd1 = i;
802: dirLast = dir;
803: interLast = inter;
804: interFirst = 0;
805: }
806: }
1.2 paf 807: qsort(polyInts, ints, sizeof(int), gdCompareInt);
808: for (i=0; (i < (ints-1)); i+=2)
809: Line(polyInts[i], y, polyInts[i+1], y, c);
1.1 paf 810: }
811: }
812:
1.2 paf 813: //001005paf this used in drawing straight lines in gdImage::FilledPolygonReplaceColor
814: void gdImage::LineReplaceColor(int x1, int y1, int x2, int y2, int a, int b) {
1.1 paf 815: if(y1!=y2)
816: return;
817:
818: for(int x=x1; x<=x2; x++) {
1.2 paf 819: unsigned char *pixel=&pixels[x][y1];
1.1 paf 820: if(*pixel==a)
821: *pixel=b;
822: }
823: }
824:
1.2 paf 825: void gdImage::FilledPolygonReplaceColor(Point *p, int n, int a, int b)
1.1 paf 826: {
827: int i;
828: int y;
829: int y1, y2;
830: int ints;
831: if (!n) {
832: return;
833: }
1.2 paf 834: if (!polyAllocated) {
835: polyInts = (int *) malloc(sizeof(int) * n);
836: polyAllocated = n;
1.1 paf 837: }
1.2 paf 838: if (polyAllocated < n) {
839: while (polyAllocated < n) {
840: polyAllocated *= 2;
1.1 paf 841: }
1.2 paf 842: polyInts = (int *) realloc(polyInts,
843: sizeof(int) * polyAllocated);
1.1 paf 844: }
845: y1 = p[0].y;
846: y2 = p[0].y;
847: for (i=1; (i < n); i++) {
848: if (p[i].y < y1) {
849: y1 = p[i].y;
850: }
851: if (p[i].y > y2) {
852: y2 = p[i].y;
853: }
854: }
855: for (y=y1; (y <= y2); y++) {
856: int interLast = 0;
857: int dirLast = 0;
858: int interFirst = 1;
859: ints = 0;
860: for (i=0; (i <= n); i++) {
861: int x1, x2;
862: int y1, y2;
863: int dir;
864: int ind1, ind2;
865: int lastInd1 = 0;
866: if ((i == n) || (!i)) {
867: ind1 = n-1;
868: ind2 = 0;
869: } else {
870: ind1 = i-1;
871: ind2 = i;
872: }
873: y1 = p[ind1].y;
874: y2 = p[ind2].y;
875: if (y1 < y2) {
876: y1 = p[ind1].y;
877: y2 = p[ind2].y;
878: x1 = p[ind1].x;
879: x2 = p[ind2].x;
880: dir = -1;
881: } else if (y1 > y2) {
882: y2 = p[ind1].y;
883: y1 = p[ind2].y;
884: x2 = p[ind1].x;
885: x1 = p[ind2].x;
886: dir = 1;
887: } else {
888: /* Horizontal; just draw it */
1.2 paf 889: LineReplaceColor(
1.1 paf 890: p[ind1].x, y1,
891: p[ind2].x, y1,
892: a,b);
893: continue;
894: }
895: if ((y >= y1) && (y <= y2)) {
896: int inter =
897: (y-y1) * (x2-x1) / (y2-y1) + x1;
898: /* Only count intersections once
899: except at maxima and minima. Also,
900: if two consecutive intersections are
901: endpoints of the same horizontal line
902: that is not at a maxima or minima,
903: discard the leftmost of the two. */
904: if (!interFirst) {
905: if ((p[ind1].y == p[lastInd1].y) &&
906: (p[ind1].x != p[lastInd1].x)) {
907: if (dir == dirLast) {
908: if (inter > interLast) {
909: /* Replace the old one */
1.2 paf 910: polyInts[ints] = inter;
1.1 paf 911: } else {
912: /* Discard this one */
913: }
914: continue;
915: }
916: }
917: if (inter == interLast) {
918: if (dir == dirLast) {
919: continue;
920: }
921: }
922: }
923: if (i > 0) {
1.2 paf 924: polyInts[ints++] = inter;
1.1 paf 925: }
926: lastInd1 = i;
927: dirLast = dir;
928: interLast = inter;
929: interFirst = 0;
930: }
931: }
1.2 paf 932: qsort(polyInts, ints, sizeof(int), gdCompareInt);
1.1 paf 933: for (i=0; (i < (ints-1)); i+=2) {
1.2 paf 934: LineReplaceColor(polyInts[i], y,
935: polyInts[i+1], y, a,b);
1.1 paf 936: }
937: }
938: }
939:
1.2 paf 940: void gdImage::SetInterlace(int interlaceArg)
1.1 paf 941: {
1.2 paf 942: interlace = interlaceArg;
1.1 paf 943: }
944:
1.6 parser 945: void gdImage::SetLineWidth(int width)
946: {
947: lineWidth=width;
948: }
949:
950: void gdImage::SetLineStyle(const char *alineStyle)
1.1 paf 951: {
1.6 parser 952: lineStyle=alineStyle;
1.1 paf 953: }
954: