Annotation of parser3/src/classes/gd/gif.C, revision 1.3
1.3 ! paf 1: /** @file
! 2: Parser: image manipulations impl1.
! 3:
! 4: Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
! 5:
! 6: $Id: response.C,v 1.6 2001/04/03 08:23:06 paf Exp $
! 7: */
! 8:
1.1 paf 9: #include <string.h>
10: #include <stdlib.h>
11: #include <math.h>
12:
13: #include "gif.h"
14:
1.2 paf 15: //static void BrushApply(int x, int y);
16: //static void TileApply(int x, int y);
1.1 paf 17:
1.2 paf 18: void gdImage::Create(int asx, int asy) {
19: sx = asx;
20: sy = asy;
21:
22: int i;
23: pixels = (unsigned char **) malloc(sizeof(unsigned char *) * sx);
24: polyInts = 0;
25: polyAllocated = 0;
26: styleWidth = 1;
27: for (i=0; (i<asx); i++)
28: pixels[i] = (unsigned char *) calloc(asy);
29: colorsTotal = 0;
30: transparent = (-1);
31: interlace = 0;
1.1 paf 32: }
33:
1.2 paf 34: int gdImage::ColorClosest(int r, int g, int b)
1.1 paf 35: {
36: int i;
37: long rd, gd, bd;
38: int ct = (-1);
39: long mindist = 0;
1.2 paf 40: for (i=0; (i<(colorsTotal)); i++) {
1.1 paf 41: long dist;
1.2 paf 42: if (open[i]) {
1.1 paf 43: continue;
44: }
1.2 paf 45: rd = (red[i] - r);
46: gd = (green[i] - g);
47: bd = (blue[i] - b);
1.1 paf 48: dist = rd * rd + gd * gd + bd * bd;
49: if ((i == 0) || (dist < mindist)) {
50: mindist = dist;
51: ct = i;
52: }
53: }
54: return ct;
55: }
56:
1.2 paf 57: int gdImage::ColorExact(int r, int g, int b)
1.1 paf 58: {
59: int i;
1.2 paf 60: for (i=0; (i<(colorsTotal)); i++) {
61: if (open[i]) {
1.1 paf 62: continue;
63: }
1.2 paf 64: if ((red[i] == r) &&
65: (green[i] == g) &&
66: (blue[i] == b)) {
1.1 paf 67: return i;
68: }
69: }
70: return -1;
71: }
72:
1.2 paf 73: int gdImage::ColorAllocate(int r, int g, int b)
1.1 paf 74: {
75: int i;
76: int ct = (-1);
1.2 paf 77: for (i=0; (i<(colorsTotal)); i++) {
78: if (open[i]) {
1.1 paf 79: ct = i;
80: break;
81: }
82: }
83: if (ct == (-1)) {
1.2 paf 84: ct = colorsTotal;
1.1 paf 85: if (ct == gdMaxColors) {
86: return -1;
87: }
1.2 paf 88: colorsTotal++;
1.1 paf 89: }
1.2 paf 90: red[ct] = r;
91: green[ct] = g;
92: blue[ct] = b;
93: open[ct] = 0;
1.1 paf 94: return ct;
95: }
96:
1.2 paf 97: int gdImage::ColorRGB(int r, int g, int b){
98: int idx=ColorExact(r,g,b);
99: return idx<0 ? ColorAllocate(r,g,b) : idx;
1.1 paf 100: }
101:
1.2 paf 102: int gdImage::Color(unsigned int rgb){
1.1 paf 103: unsigned int b=rgb, g=b>>8, r=g>>8;
1.2 paf 104: return ColorRGB(r & 0xFF,g & 0xFF,b & 0xFF);
1.1 paf 105: }
106:
1.2 paf 107: void gdImage::ColorDeallocate(int color)
1.1 paf 108: {
109: /* Mark it open. */
1.2 paf 110: open[color] = 1;
1.1 paf 111: }
112:
1.2 paf 113: void gdImage::SetColorTransparent(int color)
1.1 paf 114: {
1.2 paf 115: transparent = color;
1.1 paf 116: }
117:
118:
1.2 paf 119: void gdImage::SetPixel(int x, int y, int color)
1.1 paf 120: {
121: //paf int p;
122:
1.2 paf 123: switch (styleWidth){
1.1 paf 124: case 1: {
1.2 paf 125: DoSetPixel(x, y,color);
1.1 paf 126: return;
127: }
128: case 2: {
1.2 paf 129: DoSetPixel(x, y-1,color);
130: DoSetPixel(x-1, y,color);
131: DoSetPixel(x, y,color);
132: DoSetPixel(x+1, y,color);
133: DoSetPixel(x, y+1,color);
1.1 paf 134: return;
135: }
136: default:{
137: int i,j;
1.2 paf 138: for (i=-1;i<=1;i++) DoSetPixel(x+i, y-2,color);
139: for (j=-1;j<=1;j++) for (i=-2;i<=2;i++) DoSetPixel(x+i, y+j,color);
140: for (i=-1;i<=1;i++) DoSetPixel(x+i, y+2,color);
1.1 paf 141: return;
142: }
143: }
144: }
145:
1.2 paf 146: int gdImage::GetPixel(int x, int y)
1.1 paf 147: {
1.2 paf 148: return BoundsSafe(x, y) ? pixels[x][y]:0;
1.1 paf 149: }
150:
151: /* Bresenham as presented in Foley & Van Dam */
152:
1.2 paf 153: void gdImage::Line(int x1, int y1, int x2, int y2, int color)
1.1 paf 154: {
155: int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
156: dx = abs(x2-x1);
157: dy = abs(y2-y1);
158: if (dy <= dx) {
159: d = 2*dy - dx;
160: incr1 = 2*dy;
161: incr2 = 2 * (dy - dx);
162: if (x1 > x2) {
163: x = x2;
164: y = y2;
165: ydirflag = (-1);
166: xend = x1;
167: } else {
168: x = x1;
169: y = y1;
170: ydirflag = 1;
171: xend = x2;
172: }
1.2 paf 173: SetPixel(x, y, color);
1.1 paf 174: if (((y2 - y1) * ydirflag) > 0) {
175: while (x < xend) {
176: x++;
177: if (d <0) {
178: d+=incr1;
179: } else {
180: y++;
181: d+=incr2;
182: }
1.2 paf 183: SetPixel(x, y, color);
1.1 paf 184: }
185: } else {
186: while (x < xend) {
187: x++;
188: if (d <0) {
189: d+=incr1;
190: } else {
191: y--;
192: d+=incr2;
193: }
1.2 paf 194: SetPixel(x, y, color);
1.1 paf 195: }
196: }
197: } else {
198: d = 2*dx - dy;
199: incr1 = 2*dx;
200: incr2 = 2 * (dx - dy);
201: if (y1 > y2) {
202: y = y2;
203: x = x2;
204: yend = y1;
205: xdirflag = (-1);
206: } else {
207: y = y1;
208: x = x1;
209: yend = y2;
210: xdirflag = 1;
211: }
1.2 paf 212: SetPixel(x, y, color);
1.1 paf 213: if (((x2 - x1) * xdirflag) > 0) {
214: while (y < yend) {
215: y++;
216: if (d <0) {
217: d+=incr1;
218: } else {
219: x++;
220: d+=incr2;
221: }
1.2 paf 222: SetPixel(x, y, color);
1.1 paf 223: }
224: } else {
225: while (y < yend) {
226: y++;
227: if (d <0) {
228: d+=incr1;
229: } else {
230: x--;
231: d+=incr2;
232: }
1.2 paf 233: SetPixel(x, y, color);
1.1 paf 234: }
235: }
236: }
237: }
238:
239: /* As above, plus dashing */
240:
241: #define dashedSet \
242: { \
243: dashStep++; \
244: if (dashStep == gdDashSize) { \
245: dashStep = 0; \
246: on = !on; \
247: } \
248: if (on) { \
1.2 paf 249: SetPixel(x, y, color); \
1.1 paf 250: } \
251: }
252:
1.2 paf 253: void gdImage::DashedLine(int x1, int y1, int x2, int y2, int color)
1.1 paf 254: {
255: int dx, dy, incr1, incr2, d, x, y, xend, yend, xdirflag, ydirflag;
256: int dashStep = 0;
257: int on = 1;
258: dx = abs(x2-x1);
259: dy = abs(y2-y1);
260: if (dy <= dx) {
261: d = 2*dy - dx;
262: incr1 = 2*dy;
263: incr2 = 2 * (dy - dx);
264: if (x1 > x2) {
265: x = x2;
266: y = y2;
267: ydirflag = (-1);
268: xend = x1;
269: } else {
270: x = x1;
271: y = y1;
272: ydirflag = 1;
273: xend = x2;
274: }
275: dashedSet;
276: if (((y2 - y1) * ydirflag) > 0) {
277: while (x < xend) {
278: x++;
279: if (d <0) {
280: d+=incr1;
281: } else {
282: y++;
283: d+=incr2;
284: }
285: dashedSet;
286: }
287: } else {
288: while (x < xend) {
289: x++;
290: if (d <0) {
291: d+=incr1;
292: } else {
293: y--;
294: d+=incr2;
295: }
296: dashedSet;
297: }
298: }
299: } else {
300: d = 2*dx - dy;
301: incr1 = 2*dx;
302: incr2 = 2 * (dx - dy);
303: if (y1 > y2) {
304: y = y2;
305: x = x2;
306: yend = y1;
307: xdirflag = (-1);
308: } else {
309: y = y1;
310: x = x1;
311: yend = y2;
312: xdirflag = 1;
313: }
314: dashedSet;
315: if (((x2 - x1) * xdirflag) > 0) {
316: while (y < yend) {
317: y++;
318: if (d <0) {
319: d+=incr1;
320: } else {
321: x++;
322: d+=incr2;
323: }
324: dashedSet;
325: }
326: } else {
327: while (y < yend) {
328: y++;
329: if (d <0) {
330: d+=incr1;
331: } else {
332: x--;
333: d+=incr2;
334: }
335: dashedSet;
336: }
337: }
338: }
339: }
340:
341: /* s and e are integers modulo 360 (degrees), with 0 degrees
342: being the rightmost extreme and degrees changing clockwise.
343: cx and cy are the center in pixels; w and h are the horizontal
344: and vertical diameter in pixels. Nice interface, but slow, since
345: I don't yet use Bresenham (I'm using an inefficient but
346: simple solution with too much work going on in it; generalizing
347: Bresenham to ellipses and partial arcs of ellipses is non-trivial,
348: at least for me) and there are other inefficiencies (small circles
349: do far too much work). */
350:
1.2 paf 351: void gdImage::FillToBorder(int x, int y, int border, int color)
1.1 paf 352: {
353: int lastBorder;
354: /* Seek left */
355: int leftLimit, rightLimit;
356: int i;
357: leftLimit = (-1);
358: if (border < 0) {
359: /* Refuse to fill to a non-solid border */
360: return;
361: }
362: for (i = x; (i >= 0); i--) {
1.2 paf 363: if (GetPixel(i, y) == border) {
1.1 paf 364: break;
365: }
1.2 paf 366: SetPixel(i, y, color);
1.1 paf 367: leftLimit = i;
368: }
369: if (leftLimit == (-1)) {
370: return;
371: }
372: /* Seek right */
373: rightLimit = x;
1.2 paf 374: for (i = (x+1); (i < sx); i++) {
375: if (GetPixel(i, y) == border) {
1.1 paf 376: break;
377: }
1.2 paf 378: SetPixel(i, y, color);
1.1 paf 379: rightLimit = i;
380: }
381: /* Look at lines above and below and start paints */
382: /* Above */
383: if (y > 0) {
384: lastBorder = 1;
385: for (i = leftLimit; (i <= rightLimit); i++) {
386: int c;
1.2 paf 387: c = GetPixel(i, y-1);
1.1 paf 388: if (lastBorder) {
389: if ((c != border) && (c != color)) {
1.2 paf 390: FillToBorder(i, y-1,
1.1 paf 391: border, color);
392: lastBorder = 0;
393: }
394: } else if ((c == border) || (c == color)) {
395: lastBorder = 1;
396: }
397: }
398: }
399: /* Below */
1.2 paf 400: if (y < ((sy) - 1)) {
1.1 paf 401: lastBorder = 1;
402: for (i = leftLimit; (i <= rightLimit); i++) {
403: int c;
1.2 paf 404: c = GetPixel(i, y+1);
1.1 paf 405: if (lastBorder) {
406: if ((c != border) && (c != color)) {
1.2 paf 407: FillToBorder(i, y+1,
1.1 paf 408: border, color);
409: lastBorder = 0;
410: }
411: } else if ((c == border) || (c == color)) {
412: lastBorder = 1;
413: }
414: }
415: }
416: }
417:
1.2 paf 418: void gdImage::Fill(int x, int y, int color)
1.1 paf 419: {
420: int lastBorder;
421: int old;
422: int leftLimit, rightLimit;
423: int i;
1.2 paf 424: old = GetPixel(x, y);
1.1 paf 425: if (old == color) {
426: /* Nothing to be done */
427: return;
428: }
429: /* Seek left */
430: leftLimit = (-1);
431: for (i = x; (i >= 0); i--) {
1.2 paf 432: if (GetPixel(i, y) != old) {
1.1 paf 433: break;
434: }
1.2 paf 435: SetPixel(i, y, color);
1.1 paf 436: leftLimit = i;
437: }
438: if (leftLimit == (-1)) {
439: return;
440: }
441: /* Seek right */
442: rightLimit = x;
1.2 paf 443: for (i = (x+1); (i < sx); i++) {
444: if (GetPixel(i, y) != old) {
1.1 paf 445: break;
446: }
1.2 paf 447: SetPixel(i, y, color);
1.1 paf 448: rightLimit = i;
449: }
450: /* Look at lines above and below and start paints */
451: /* Above */
452: if (y > 0) {
453: lastBorder = 1;
454: for (i = leftLimit; (i <= rightLimit); i++) {
455: int c;
1.2 paf 456: c = GetPixel(i, y-1);
1.1 paf 457: if (lastBorder) {
458: if (c == old) {
1.2 paf 459: Fill(i, y-1, color);
1.1 paf 460: lastBorder = 0;
461: }
462: } else if (c != old) {
463: lastBorder = 1;
464: }
465: }
466: }
467: /* Below */
1.2 paf 468: if (y < ((sy) - 1)) {
1.1 paf 469: lastBorder = 1;
470: for (i = leftLimit; (i <= rightLimit); i++) {
471: int c;
1.2 paf 472: c = GetPixel(i, y+1);
1.1 paf 473: if (lastBorder) {
474: if (c == old) {
1.2 paf 475: Fill(i, y+1, color);
1.1 paf 476: lastBorder = 0;
477: }
478: } else if (c != old) {
479: lastBorder = 1;
480: }
481: }
482: }
483: }
484:
1.2 paf 485: void gdImage::Rectangle(int x1, int y1, int x2, int y2, int color)
1.1 paf 486: {
1.2 paf 487: Line(x1, y1, x2, y1, color);
488: Line(x1, y2, x2, y2, color);
489: Line(x1, y1, x1, y2, color);
490: Line(x2, y1, x2, y2, color);
1.1 paf 491: }
492:
1.2 paf 493: void gdImage::FilledRectangle(int x1, int y1, int x2, int y2, int color)
1.1 paf 494: {
495: int x, y;
1.2 paf 496: for (y=y1; (y<=y2); y++)
497: for (x=x1; (x<=x2); x++)
498: SetPixel(x, y, color);
1.1 paf 499: }
500:
1.2 paf 501: void gdImage::Copy(gdImage& dst, int dstX, int dstY, int srcX, int srcY, int w, int h)
1.1 paf 502: {
503: int c;
504: int x, y;
505: int tox, toy;
506: int i;
507: int colorMap[gdMaxColors];
508: for (i=0; (i<gdMaxColors); i++) {
509: colorMap[i] = (-1);
510: }
511: toy = dstY;
512: for (y=srcY; (y < (srcY + h)); y++) {
513: tox = dstX;
514: for (x=srcX; (x < (srcX + w)); x++) {
515: int nc;
1.2 paf 516: c = GetPixel(x, y);
1.1 paf 517: /* Added 7/24/95: support transparent copies */
1.2 paf 518: if (GetTransparent() == c) {
1.1 paf 519: tox++;
520: continue;
521: }
522: /* Have we established a mapping for this color? */
523: if (colorMap[c] == (-1)) {
524: /* If it's the same image, mapping is trivial */
1.2 paf 525: if (&dst == this) {
1.1 paf 526: nc = c;
527: } else {
528: /* First look for an exact match */
1.2 paf 529: nc = dst.ColorExact(
530: red[c], green[c],
531: blue[c]);
1.1 paf 532: }
533: if (nc == (-1)) {
534: /* No, so try to allocate it */
1.2 paf 535: nc = dst.ColorAllocate(
536: red[c], green[c],
537: blue[c]);
1.1 paf 538: /* If we're out of colors, go for the
539: closest color */
540: if (nc == (-1)) {
1.2 paf 541: nc = dst.ColorClosest(
542: red[c], green[c],
543: blue[c]);
1.1 paf 544: }
545: }
546: colorMap[c] = nc;
547: }
1.2 paf 548: dst.SetPixel(tox, toy, colorMap[c]);
1.1 paf 549: tox++;
550: }
551: toy++;
552: }
553: }
554:
1.2 paf 555: static int gdGetWord(int *result, FILE *in)
1.1 paf 556: {
557: int r;
558: r = getc(in);
559: if (r == EOF) {
560: return 0;
561: }
562: *result = r << 8;
563: r = getc(in);
564: if (r == EOF) {
565: return 0;
566: }
567: *result += r;
568: return 1;
569: }
570:
1.2 paf 571: static void gdPutWord(int w, FILE *out)
1.1 paf 572: {
573: putc((unsigned char)(w >> 8), out);
574: putc((unsigned char)(w & 0xFF), out);
575: }
576:
1.2 paf 577: static int gdGetByte(int *result, FILE *in)
1.1 paf 578: {
579: int r;
580: r = getc(in);
581: if (r == EOF) {
582: return 0;
583: }
584: *result = r;
585: return 1;
586: }
587:
1.2 paf 588: void gdImage::Polygon(Point *p, int n, int c)
1.1 paf 589: {
590: int i;
591: int lx, ly;
592: if (!n) {
593: return;
594: }
595: lx = p->x;
596: ly = p->y;
1.2 paf 597: Line(lx, ly, p[n-1].x, p[n-1].y, c);
1.1 paf 598: for (i=1; (i < n); i++) {
599: p++;
1.2 paf 600: Line(lx, ly, p->x, p->y, c);
1.1 paf 601: lx = p->x;
602: ly = p->y;
603: }
604: }
605:
606: int gdCompareInt(const void *a, const void *b);
607:
1.2 paf 608: void gdImage::FilledPolygon(Point *p, int n, int c)
1.1 paf 609: {
610: int i;
611: int y;
612: int y1, y2;
613: int ints;
614: if (!n) {
615: return;
616: }
1.2 paf 617: if (!polyAllocated) {
618: polyInts = (int *) malloc(sizeof(int) * n);
619: polyAllocated = n;
1.1 paf 620: }
1.2 paf 621: if (polyAllocated < n) {
622: while (polyAllocated < n) {
623: polyAllocated *= 2;
1.1 paf 624: }
1.2 paf 625: polyInts = (int *) realloc(polyInts,
626: sizeof(int) * polyAllocated);
1.1 paf 627: }
628: y1 = p[0].y;
629: y2 = p[0].y;
630: for (i=1; (i < n); i++) {
631: if (p[i].y < y1) {
632: y1 = p[i].y;
633: }
634: if (p[i].y > y2) {
635: y2 = p[i].y;
636: }
637: }
638: for (y=y1; (y <= y2); y++) {
639: int interLast = 0;
640: int dirLast = 0;
641: int interFirst = 1;
642: ints = 0;
643: for (i=0; (i <= n); i++) {
644: int x1, x2;
645: int y1, y2;
646: int dir;
647: int ind1, ind2;
648: int lastInd1 = 0;
649: if ((i == n) || (!i)) {
650: ind1 = n-1;
651: ind2 = 0;
652: } else {
653: ind1 = i-1;
654: ind2 = i;
655: }
656: y1 = p[ind1].y;
657: y2 = p[ind2].y;
658: if (y1 < y2) {
659: y1 = p[ind1].y;
660: y2 = p[ind2].y;
661: x1 = p[ind1].x;
662: x2 = p[ind2].x;
663: dir = -1;
664: } else if (y1 > y2) {
665: y2 = p[ind1].y;
666: y1 = p[ind2].y;
667: x2 = p[ind1].x;
668: x1 = p[ind2].x;
669: dir = 1;
670: } else {
671: /* Horizontal; just draw it */
1.2 paf 672: Line(
1.1 paf 673: p[ind1].x, y1,
674: p[ind2].x, y1,
675: c);
676: continue;
677: }
678: if ((y >= y1) && (y <= y2)) {
679: int inter =
680: (y-y1) * (x2-x1) / (y2-y1) + x1;
681: /* Only count intersections once
682: except at maxima and minima. Also,
683: if two consecutive intersections are
684: endpoints of the same horizontal line
685: that is not at a maxima or minima,
686: discard the leftmost of the two. */
687: if (!interFirst) {
688: if ((p[ind1].y == p[lastInd1].y) &&
689: (p[ind1].x != p[lastInd1].x)) {
690: if (dir == dirLast) {
691: if (inter > interLast) {
692: /* Replace the old one */
1.2 paf 693: polyInts[ints] = inter;
1.1 paf 694: } else {
695: /* Discard this one */
696: }
697: continue;
698: }
699: }
700: if (inter == interLast) {
701: if (dir == dirLast) {
702: continue;
703: }
704: }
705: }
706: if (i > 0) {
1.2 paf 707: polyInts[ints++] = inter;
1.1 paf 708: }
709: lastInd1 = i;
710: dirLast = dir;
711: interLast = inter;
712: interFirst = 0;
713: }
714: }
1.2 paf 715: qsort(polyInts, ints, sizeof(int), gdCompareInt);
716: for (i=0; (i < (ints-1)); i+=2)
717: Line(polyInts[i], y, polyInts[i+1], y, c);
1.1 paf 718: }
719: }
720:
1.2 paf 721: //001005paf this used in drawing straight lines in gdImage::FilledPolygonReplaceColor
722: void gdImage::LineReplaceColor(int x1, int y1, int x2, int y2, int a, int b) {
1.1 paf 723: if(y1!=y2)
724: return;
725:
726: for(int x=x1; x<=x2; x++) {
1.2 paf 727: unsigned char *pixel=&pixels[x][y1];
1.1 paf 728: if(*pixel==a)
729: *pixel=b;
730: }
731: }
732:
1.2 paf 733: void gdImage::FilledPolygonReplaceColor(Point *p, int n, int a, int b)
1.1 paf 734: {
735: int i;
736: int y;
737: int y1, y2;
738: int ints;
739: if (!n) {
740: return;
741: }
1.2 paf 742: if (!polyAllocated) {
743: polyInts = (int *) malloc(sizeof(int) * n);
744: polyAllocated = n;
1.1 paf 745: }
1.2 paf 746: if (polyAllocated < n) {
747: while (polyAllocated < n) {
748: polyAllocated *= 2;
1.1 paf 749: }
1.2 paf 750: polyInts = (int *) realloc(polyInts,
751: sizeof(int) * polyAllocated);
1.1 paf 752: }
753: y1 = p[0].y;
754: y2 = p[0].y;
755: for (i=1; (i < n); i++) {
756: if (p[i].y < y1) {
757: y1 = p[i].y;
758: }
759: if (p[i].y > y2) {
760: y2 = p[i].y;
761: }
762: }
763: for (y=y1; (y <= y2); y++) {
764: int interLast = 0;
765: int dirLast = 0;
766: int interFirst = 1;
767: ints = 0;
768: for (i=0; (i <= n); i++) {
769: int x1, x2;
770: int y1, y2;
771: int dir;
772: int ind1, ind2;
773: int lastInd1 = 0;
774: if ((i == n) || (!i)) {
775: ind1 = n-1;
776: ind2 = 0;
777: } else {
778: ind1 = i-1;
779: ind2 = i;
780: }
781: y1 = p[ind1].y;
782: y2 = p[ind2].y;
783: if (y1 < y2) {
784: y1 = p[ind1].y;
785: y2 = p[ind2].y;
786: x1 = p[ind1].x;
787: x2 = p[ind2].x;
788: dir = -1;
789: } else if (y1 > y2) {
790: y2 = p[ind1].y;
791: y1 = p[ind2].y;
792: x2 = p[ind1].x;
793: x1 = p[ind2].x;
794: dir = 1;
795: } else {
796: /* Horizontal; just draw it */
1.2 paf 797: LineReplaceColor(
1.1 paf 798: p[ind1].x, y1,
799: p[ind2].x, y1,
800: a,b);
801: continue;
802: }
803: if ((y >= y1) && (y <= y2)) {
804: int inter =
805: (y-y1) * (x2-x1) / (y2-y1) + x1;
806: /* Only count intersections once
807: except at maxima and minima. Also,
808: if two consecutive intersections are
809: endpoints of the same horizontal line
810: that is not at a maxima or minima,
811: discard the leftmost of the two. */
812: if (!interFirst) {
813: if ((p[ind1].y == p[lastInd1].y) &&
814: (p[ind1].x != p[lastInd1].x)) {
815: if (dir == dirLast) {
816: if (inter > interLast) {
817: /* Replace the old one */
1.2 paf 818: polyInts[ints] = inter;
1.1 paf 819: } else {
820: /* Discard this one */
821: }
822: continue;
823: }
824: }
825: if (inter == interLast) {
826: if (dir == dirLast) {
827: continue;
828: }
829: }
830: }
831: if (i > 0) {
1.2 paf 832: polyInts[ints++] = inter;
1.1 paf 833: }
834: lastInd1 = i;
835: dirLast = dir;
836: interLast = inter;
837: interFirst = 0;
838: }
839: }
1.2 paf 840: qsort(polyInts, ints, sizeof(int), gdCompareInt);
1.1 paf 841: for (i=0; (i < (ints-1)); i+=2) {
1.2 paf 842: LineReplaceColor(polyInts[i], y,
843: polyInts[i+1], y, a,b);
1.1 paf 844: }
845: }
846: }
847:
1.2 paf 848: static int gdCompareInt(const void *a, const void *b)
1.1 paf 849: {
850: return (*(const int *)a) - (*(const int *)b);
851: }
852:
1.2 paf 853: void gdImage::SetInterlace(int interlaceArg)
1.1 paf 854: {
1.2 paf 855: interlace = interlaceArg;
1.1 paf 856: }
857:
1.2 paf 858: void gdImage::SetStyle(int width)
1.1 paf 859: {
1.2 paf 860: styleWidth=width;
1.1 paf 861: }
862:
E-mail: