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