|
|
1.3 paf 1: /** @file
2: Parser: image manipulations impl1.
3:
4: Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf)
5:
1.4 ! paf 6: $Id: gif.C,v 1.3 2001/04/11 18:07:17 paf Exp $
1.3 paf 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: {
1.4 ! paf 353: if(!BoundsSafe(x, y)) //PAF
! 354: return;
! 355:
1.1 paf 356: int lastBorder;
357: /* Seek left */
358: int leftLimit, rightLimit;
359: int i;
360: leftLimit = (-1);
361: if (border < 0) {
362: /* Refuse to fill to a non-solid border */
363: return;
364: }
365: for (i = x; (i >= 0); i--) {
1.2 paf 366: if (GetPixel(i, y) == border) {
1.1 paf 367: break;
368: }
1.2 paf 369: SetPixel(i, y, color);
1.1 paf 370: leftLimit = i;
371: }
372: if (leftLimit == (-1)) {
373: return;
374: }
375: /* Seek right */
376: rightLimit = x;
1.2 paf 377: for (i = (x+1); (i < sx); i++) {
378: if (GetPixel(i, y) == border) {
1.1 paf 379: break;
380: }
1.2 paf 381: SetPixel(i, y, color);
1.1 paf 382: rightLimit = i;
383: }
384: /* Look at lines above and below and start paints */
385: /* Above */
386: if (y > 0) {
387: lastBorder = 1;
388: for (i = leftLimit; (i <= rightLimit); i++) {
389: int c;
1.2 paf 390: c = GetPixel(i, y-1);
1.1 paf 391: if (lastBorder) {
392: if ((c != border) && (c != color)) {
1.2 paf 393: FillToBorder(i, y-1,
1.1 paf 394: border, color);
395: lastBorder = 0;
396: }
397: } else if ((c == border) || (c == color)) {
398: lastBorder = 1;
399: }
400: }
401: }
402: /* Below */
1.2 paf 403: if (y < ((sy) - 1)) {
1.1 paf 404: lastBorder = 1;
405: for (i = leftLimit; (i <= rightLimit); i++) {
406: int c;
1.2 paf 407: c = GetPixel(i, y+1);
1.1 paf 408: if (lastBorder) {
409: if ((c != border) && (c != color)) {
1.2 paf 410: FillToBorder(i, y+1,
1.1 paf 411: border, color);
412: lastBorder = 0;
413: }
414: } else if ((c == border) || (c == color)) {
415: lastBorder = 1;
416: }
417: }
418: }
419: }
420:
1.2 paf 421: void gdImage::Fill(int x, int y, int color)
1.1 paf 422: {
1.4 ! paf 423: if(!BoundsSafe(x, y)) //PAF
! 424: return;
! 425:
1.1 paf 426: int lastBorder;
427: int old;
428: int leftLimit, rightLimit;
429: int i;
1.2 paf 430: old = GetPixel(x, y);
1.1 paf 431: if (old == color) {
432: /* Nothing to be done */
433: return;
434: }
435: /* Seek left */
436: leftLimit = (-1);
437: for (i = x; (i >= 0); i--) {
1.2 paf 438: if (GetPixel(i, y) != old) {
1.1 paf 439: break;
440: }
1.2 paf 441: SetPixel(i, y, color);
1.1 paf 442: leftLimit = i;
443: }
444: if (leftLimit == (-1)) {
445: return;
446: }
447: /* Seek right */
448: rightLimit = x;
1.2 paf 449: for (i = (x+1); (i < sx); i++) {
450: if (GetPixel(i, y) != old) {
1.1 paf 451: break;
452: }
1.2 paf 453: SetPixel(i, y, color);
1.1 paf 454: rightLimit = i;
455: }
456: /* Look at lines above and below and start paints */
457: /* Above */
458: if (y > 0) {
459: lastBorder = 1;
460: for (i = leftLimit; (i <= rightLimit); i++) {
461: int c;
1.2 paf 462: c = GetPixel(i, y-1);
1.1 paf 463: if (lastBorder) {
464: if (c == old) {
1.2 paf 465: Fill(i, y-1, color);
1.1 paf 466: lastBorder = 0;
467: }
468: } else if (c != old) {
469: lastBorder = 1;
470: }
471: }
472: }
473: /* Below */
1.2 paf 474: if (y < ((sy) - 1)) {
1.1 paf 475: lastBorder = 1;
476: for (i = leftLimit; (i <= rightLimit); i++) {
477: int c;
1.2 paf 478: c = GetPixel(i, y+1);
1.1 paf 479: if (lastBorder) {
480: if (c == old) {
1.2 paf 481: Fill(i, y+1, color);
1.1 paf 482: lastBorder = 0;
483: }
484: } else if (c != old) {
485: lastBorder = 1;
486: }
487: }
488: }
489: }
490:
1.2 paf 491: void gdImage::Rectangle(int x1, int y1, int x2, int y2, int color)
1.1 paf 492: {
1.2 paf 493: Line(x1, y1, x2, y1, color);
494: Line(x1, y2, x2, y2, color);
495: Line(x1, y1, x1, y2, color);
496: Line(x2, y1, x2, y2, color);
1.1 paf 497: }
498:
1.2 paf 499: void gdImage::FilledRectangle(int x1, int y1, int x2, int y2, int color)
1.1 paf 500: {
501: int x, y;
1.2 paf 502: for (y=y1; (y<=y2); y++)
503: for (x=x1; (x<=x2); x++)
504: SetPixel(x, y, color);
1.1 paf 505: }
506:
1.2 paf 507: void gdImage::Copy(gdImage& dst, int dstX, int dstY, int srcX, int srcY, int w, int h)
1.1 paf 508: {
509: int c;
510: int x, y;
511: int tox, toy;
512: int i;
513: int colorMap[gdMaxColors];
514: for (i=0; (i<gdMaxColors); i++) {
515: colorMap[i] = (-1);
516: }
517: toy = dstY;
518: for (y=srcY; (y < (srcY + h)); y++) {
519: tox = dstX;
520: for (x=srcX; (x < (srcX + w)); x++) {
521: int nc;
1.2 paf 522: c = GetPixel(x, y);
1.1 paf 523: /* Added 7/24/95: support transparent copies */
1.2 paf 524: if (GetTransparent() == c) {
1.1 paf 525: tox++;
526: continue;
527: }
528: /* Have we established a mapping for this color? */
529: if (colorMap[c] == (-1)) {
530: /* If it's the same image, mapping is trivial */
1.2 paf 531: if (&dst == this) {
1.1 paf 532: nc = c;
533: } else {
534: /* First look for an exact match */
1.2 paf 535: nc = dst.ColorExact(
536: red[c], green[c],
537: blue[c]);
1.1 paf 538: }
539: if (nc == (-1)) {
540: /* No, so try to allocate it */
1.2 paf 541: nc = dst.ColorAllocate(
542: red[c], green[c],
543: blue[c]);
1.1 paf 544: /* If we're out of colors, go for the
545: closest color */
546: if (nc == (-1)) {
1.2 paf 547: nc = dst.ColorClosest(
548: red[c], green[c],
549: blue[c]);
1.1 paf 550: }
551: }
552: colorMap[c] = nc;
553: }
1.2 paf 554: dst.SetPixel(tox, toy, colorMap[c]);
1.1 paf 555: tox++;
556: }
557: toy++;
558: }
559: }
560:
1.2 paf 561: static int gdGetWord(int *result, FILE *in)
1.1 paf 562: {
563: int r;
564: r = getc(in);
565: if (r == EOF) {
566: return 0;
567: }
568: *result = r << 8;
569: r = getc(in);
570: if (r == EOF) {
571: return 0;
572: }
573: *result += r;
574: return 1;
575: }
576:
1.2 paf 577: static void gdPutWord(int w, FILE *out)
1.1 paf 578: {
579: putc((unsigned char)(w >> 8), out);
580: putc((unsigned char)(w & 0xFF), out);
581: }
582:
1.2 paf 583: static int gdGetByte(int *result, FILE *in)
1.1 paf 584: {
585: int r;
586: r = getc(in);
587: if (r == EOF) {
588: return 0;
589: }
590: *result = r;
591: return 1;
592: }
593:
1.2 paf 594: void gdImage::Polygon(Point *p, int n, int c)
1.1 paf 595: {
596: int i;
597: int lx, ly;
598: if (!n) {
599: return;
600: }
601: lx = p->x;
602: ly = p->y;
1.2 paf 603: Line(lx, ly, p[n-1].x, p[n-1].y, c);
1.1 paf 604: for (i=1; (i < n); i++) {
605: p++;
1.2 paf 606: Line(lx, ly, p->x, p->y, c);
1.1 paf 607: lx = p->x;
608: ly = p->y;
609: }
610: }
611:
612: int gdCompareInt(const void *a, const void *b);
613:
1.2 paf 614: void gdImage::FilledPolygon(Point *p, int n, int c)
1.1 paf 615: {
616: int i;
617: int y;
618: int y1, y2;
619: int ints;
620: if (!n) {
621: return;
622: }
1.2 paf 623: if (!polyAllocated) {
624: polyInts = (int *) malloc(sizeof(int) * n);
625: polyAllocated = n;
1.1 paf 626: }
1.2 paf 627: if (polyAllocated < n) {
628: while (polyAllocated < n) {
629: polyAllocated *= 2;
1.1 paf 630: }
1.2 paf 631: polyInts = (int *) realloc(polyInts,
632: sizeof(int) * polyAllocated);
1.1 paf 633: }
634: y1 = p[0].y;
635: y2 = p[0].y;
636: for (i=1; (i < n); i++) {
637: if (p[i].y < y1) {
638: y1 = p[i].y;
639: }
640: if (p[i].y > y2) {
641: y2 = p[i].y;
642: }
643: }
644: for (y=y1; (y <= y2); y++) {
645: int interLast = 0;
646: int dirLast = 0;
647: int interFirst = 1;
648: ints = 0;
649: for (i=0; (i <= n); i++) {
650: int x1, x2;
651: int y1, y2;
652: int dir;
653: int ind1, ind2;
654: int lastInd1 = 0;
655: if ((i == n) || (!i)) {
656: ind1 = n-1;
657: ind2 = 0;
658: } else {
659: ind1 = i-1;
660: ind2 = i;
661: }
662: y1 = p[ind1].y;
663: y2 = p[ind2].y;
664: if (y1 < y2) {
665: y1 = p[ind1].y;
666: y2 = p[ind2].y;
667: x1 = p[ind1].x;
668: x2 = p[ind2].x;
669: dir = -1;
670: } else if (y1 > y2) {
671: y2 = p[ind1].y;
672: y1 = p[ind2].y;
673: x2 = p[ind1].x;
674: x1 = p[ind2].x;
675: dir = 1;
676: } else {
677: /* Horizontal; just draw it */
1.2 paf 678: Line(
1.1 paf 679: p[ind1].x, y1,
680: p[ind2].x, y1,
681: c);
682: continue;
683: }
684: if ((y >= y1) && (y <= y2)) {
685: int inter =
686: (y-y1) * (x2-x1) / (y2-y1) + x1;
687: /* Only count intersections once
688: except at maxima and minima. Also,
689: if two consecutive intersections are
690: endpoints of the same horizontal line
691: that is not at a maxima or minima,
692: discard the leftmost of the two. */
693: if (!interFirst) {
694: if ((p[ind1].y == p[lastInd1].y) &&
695: (p[ind1].x != p[lastInd1].x)) {
696: if (dir == dirLast) {
697: if (inter > interLast) {
698: /* Replace the old one */
1.2 paf 699: polyInts[ints] = inter;
1.1 paf 700: } else {
701: /* Discard this one */
702: }
703: continue;
704: }
705: }
706: if (inter == interLast) {
707: if (dir == dirLast) {
708: continue;
709: }
710: }
711: }
712: if (i > 0) {
1.2 paf 713: polyInts[ints++] = inter;
1.1 paf 714: }
715: lastInd1 = i;
716: dirLast = dir;
717: interLast = inter;
718: interFirst = 0;
719: }
720: }
1.2 paf 721: qsort(polyInts, ints, sizeof(int), gdCompareInt);
722: for (i=0; (i < (ints-1)); i+=2)
723: Line(polyInts[i], y, polyInts[i+1], y, c);
1.1 paf 724: }
725: }
726:
1.2 paf 727: //001005paf this used in drawing straight lines in gdImage::FilledPolygonReplaceColor
728: void gdImage::LineReplaceColor(int x1, int y1, int x2, int y2, int a, int b) {
1.1 paf 729: if(y1!=y2)
730: return;
731:
732: for(int x=x1; x<=x2; x++) {
1.2 paf 733: unsigned char *pixel=&pixels[x][y1];
1.1 paf 734: if(*pixel==a)
735: *pixel=b;
736: }
737: }
738:
1.2 paf 739: void gdImage::FilledPolygonReplaceColor(Point *p, int n, int a, int b)
1.1 paf 740: {
741: int i;
742: int y;
743: int y1, y2;
744: int ints;
745: if (!n) {
746: return;
747: }
1.2 paf 748: if (!polyAllocated) {
749: polyInts = (int *) malloc(sizeof(int) * n);
750: polyAllocated = n;
1.1 paf 751: }
1.2 paf 752: if (polyAllocated < n) {
753: while (polyAllocated < n) {
754: polyAllocated *= 2;
1.1 paf 755: }
1.2 paf 756: polyInts = (int *) realloc(polyInts,
757: sizeof(int) * polyAllocated);
1.1 paf 758: }
759: y1 = p[0].y;
760: y2 = p[0].y;
761: for (i=1; (i < n); i++) {
762: if (p[i].y < y1) {
763: y1 = p[i].y;
764: }
765: if (p[i].y > y2) {
766: y2 = p[i].y;
767: }
768: }
769: for (y=y1; (y <= y2); y++) {
770: int interLast = 0;
771: int dirLast = 0;
772: int interFirst = 1;
773: ints = 0;
774: for (i=0; (i <= n); i++) {
775: int x1, x2;
776: int y1, y2;
777: int dir;
778: int ind1, ind2;
779: int lastInd1 = 0;
780: if ((i == n) || (!i)) {
781: ind1 = n-1;
782: ind2 = 0;
783: } else {
784: ind1 = i-1;
785: ind2 = i;
786: }
787: y1 = p[ind1].y;
788: y2 = p[ind2].y;
789: if (y1 < y2) {
790: y1 = p[ind1].y;
791: y2 = p[ind2].y;
792: x1 = p[ind1].x;
793: x2 = p[ind2].x;
794: dir = -1;
795: } else if (y1 > y2) {
796: y2 = p[ind1].y;
797: y1 = p[ind2].y;
798: x2 = p[ind1].x;
799: x1 = p[ind2].x;
800: dir = 1;
801: } else {
802: /* Horizontal; just draw it */
1.2 paf 803: LineReplaceColor(
1.1 paf 804: p[ind1].x, y1,
805: p[ind2].x, y1,
806: a,b);
807: continue;
808: }
809: if ((y >= y1) && (y <= y2)) {
810: int inter =
811: (y-y1) * (x2-x1) / (y2-y1) + x1;
812: /* Only count intersections once
813: except at maxima and minima. Also,
814: if two consecutive intersections are
815: endpoints of the same horizontal line
816: that is not at a maxima or minima,
817: discard the leftmost of the two. */
818: if (!interFirst) {
819: if ((p[ind1].y == p[lastInd1].y) &&
820: (p[ind1].x != p[lastInd1].x)) {
821: if (dir == dirLast) {
822: if (inter > interLast) {
823: /* Replace the old one */
1.2 paf 824: polyInts[ints] = inter;
1.1 paf 825: } else {
826: /* Discard this one */
827: }
828: continue;
829: }
830: }
831: if (inter == interLast) {
832: if (dir == dirLast) {
833: continue;
834: }
835: }
836: }
837: if (i > 0) {
1.2 paf 838: polyInts[ints++] = inter;
1.1 paf 839: }
840: lastInd1 = i;
841: dirLast = dir;
842: interLast = inter;
843: interFirst = 0;
844: }
845: }
1.2 paf 846: qsort(polyInts, ints, sizeof(int), gdCompareInt);
1.1 paf 847: for (i=0; (i < (ints-1)); i+=2) {
1.2 paf 848: LineReplaceColor(polyInts[i], y,
849: polyInts[i+1], y, a,b);
1.1 paf 850: }
851: }
852: }
853:
1.2 paf 854: static int gdCompareInt(const void *a, const void *b)
1.1 paf 855: {
856: return (*(const int *)a) - (*(const int *)b);
857: }
858:
1.2 paf 859: void gdImage::SetInterlace(int interlaceArg)
1.1 paf 860: {
1.2 paf 861: interlace = interlaceArg;
1.1 paf 862: }
863:
1.2 paf 864: void gdImage::SetStyle(int width)
1.1 paf 865: {
1.2 paf 866: styleWidth=width;
1.1 paf 867: }
868: