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