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