File Coverage

polygon.c
Criterion Covered Total %
statement 252 263 95.8
branch 145 158 91.7
condition n/a
subroutine n/a
pod n/a
total 397 421 94.3


line stmt bran cond sub pod time code
1             #define IMAGER_NO_CONTEXT
2             #include "imager.h"
3             #include "draw.h"
4             #include "log.h"
5             #include "imrender.h"
6             #include "imageri.h"
7              
8             #define IMTRUNC(x) ((int)((x)*16))
9              
10             #define coarse(x) ((x)/16)
11             #define fine(x) ((x)%16)
12              
13             /*#define DEBUG_POLY*/
14             #ifdef DEBUG_POLY
15             #define POLY_DEB(x) x
16             #else
17             #define POLY_DEB(x)
18             #endif
19              
20              
21             typedef i_img_dim pcord;
22              
23             typedef struct {
24             size_t n;
25             pcord x,y;
26             } p_point;
27              
28             typedef struct {
29             size_t n;
30             pcord x1,y1;
31             pcord x2,y2;
32             pcord miny,maxy;
33             pcord minx,maxx;
34             int updown; /* -1 means down, 0 vertical, 1 up */
35             int dir; /* 1 for down, -1 for up */
36             } p_line;
37              
38             typedef struct {
39             size_t n;
40             double x;
41             } p_slice;
42              
43             typedef struct {
44             int *line; /* temporary buffer for scanline */
45             i_img_dim linelen; /* length of scanline */
46             } ss_scanline;
47              
48             static
49             int
50 7353           p_compy(const p_point *p1, const p_point *p2) {
51 7353 100         if (p1->y > p2->y) return 1;
52 3396 100         if (p1->y < p2->y) return -1;
53 551           return 0;
54             }
55              
56             static
57             int
58 4052           p_compx(const p_slice *p1, const p_slice *p2) {
59 4052 100         if (p1->x > p2->x) return 1;
60 1824 100         if (p1->x < p2->x) return -1;
61 14           return 0;
62             }
63              
64             /* Change this to int? and round right goddamn it! */
65              
66             static
67             double
68 93277           p_eval_aty(p_line *l, pcord y) {
69             int t;
70 93277           t=l->y2-l->y1;
71 93277 50         if (t) return ( (y-l->y1)*l->x2 + (l->y2-y)*l->x1 )/t;
72 0           return (l->x1+l->x2)/2.0;
73             }
74              
75             static
76             double
77 57255           p_eval_atx(p_line *l, pcord x) {
78             int t;
79 57255           t = l->x2-l->x1;
80 57255 50         if (t) return ( (x-l->x1)*l->y2 + (l->x2-x)*l->y1 )/t;
81 0           return (l->y1+l->y2)/2.0;
82             }
83              
84             static
85             p_line *
86 97           line_set_new(const i_polygon_t *polys, size_t count, size_t *line_count) {
87             size_t i, j, n;
88             p_line *lset, *line;
89 97           size_t lines = 0;
90            
91 202 100         for (i = 0; i < count; ++i)
92 105           lines += polys[i].count;
93              
94 97           line = lset = mymalloc(sizeof(p_line) * lines);
95              
96 97           n = 0;
97 202 100         for (i = 0; i < count; ++i) {
98 105           const i_polygon_t *p = polys + i;
99              
100 2077 100         for(j = 0; j < p->count; j++) {
101 1972           line->x1 = IMTRUNC(p->x[j]);
102 1972           line->y1 = IMTRUNC(p->y[j]);
103 1972           line->x2 = IMTRUNC(p->x[(j + 1) % p->count]);
104 1972           line->y2 = IMTRUNC(p->y[(j + 1) % p->count]);
105              
106             /* don't include purely horizontal lines, we don't usefully
107             intersect with them. */
108 1972 100         if (line->y1 == line->y2)
109 94           continue;
110              
111 1878           line->miny = i_min(line->y1, line->y2);
112 1878           line->maxy = i_max(line->y1, line->y2);
113 1878           line->minx = i_min(line->x1, line->x2);
114 1878           line->maxx = i_max(line->x1, line->x2);
115 1878           line->n = n++;
116 1878           ++line;
117             }
118             }
119 97           *line_count = n;
120              
121 97           return lset;
122             }
123              
124             static
125             p_point *
126 97           point_set_new(const i_polygon_t *polys, size_t count, size_t *point_count) {
127             size_t i, j, n;
128             p_point *pset, *pt;
129 97           size_t points = 0;
130            
131 202 100         for (i = 0; i < count; ++i)
132 105           points += polys[i].count;
133              
134 97           *point_count = points;
135              
136 97           pt = pset = mymalloc(sizeof(p_point) * points);
137              
138 97           n = 0;
139 202 100         for (i = 0; i < count; ++i) {
140 105           const i_polygon_t *p = polys + i;
141              
142 2077 100         for(j = 0; j < p->count; j++) {
143 1972           pt->n = n++;
144 1972           pt->x = IMTRUNC(p->x[j]);
145 1972           pt->y = IMTRUNC(p->y[j]);
146 1972           ++pt;
147             }
148             }
149 97           return pset;
150             }
151              
152             static
153             void
154 5419           ss_scanline_reset(ss_scanline *ss) {
155 5419           memset(ss->line, 0, sizeof(int) * ss->linelen);
156 5419           }
157              
158             static
159             void
160 97           ss_scanline_init(ss_scanline *ss, i_img_dim linelen, int linepairs) {
161 97           ss->line = mymalloc( sizeof(int) * linelen );
162 97           ss->linelen = linelen;
163 97           ss_scanline_reset(ss);
164 97           }
165              
166             static
167             void
168 97           ss_scanline_exorcise(ss_scanline *ss) {
169 97           myfree(ss->line);
170 97           }
171            
172            
173              
174              
175             /* returns the number of matches */
176              
177             static
178             int
179 1357           lines_in_interval(p_line *lset, int l, p_slice *tllist, pcord minc, pcord maxc) {
180             int k;
181 1357           int count = 0;
182 179922 100         for(k=0; k
183 178565 100         if (lset[k].maxy > minc && lset[k].miny < maxc) {
    100          
184 4298 50         if (lset[k].miny == lset[k].maxy) {
185             POLY_DEB( printf(" HORIZONTAL - skipped\n") );
186             } else {
187 4298           tllist[count].x=p_eval_aty(&lset[k],(minc+maxc)/2.0 );
188 4298           tllist[count].n=k;
189 4298           count++;
190             }
191             }
192             }
193 1357           return count;
194             }
195              
196             /* marks the up variable for all lines in a slice */
197              
198             static
199             void
200 1357           mark_updown_slices(pIMCTX, p_line *lset, p_slice *tllist, int count) {
201             p_line *l, *r;
202             int k;
203 3506 100         for(k=0; k
204 2149           l = lset + tllist[k].n;
205              
206 2149 50         if (l->y1 == l->y2) {
207 0           im_log((aIMCTX,1, "mark_updown_slices: horizontal line being marked: internal error!\n"));
208 0           exit(3);
209             }
210              
211 4298           l->updown = (l->x1 == l->x2) ?
212 4220 100         0 :
213 2071           (l->x1 > l->x2)
214             ?
215 1053 100         (l->y1 > l->y2) ? -1 : 1
216 4142 100         :
217 1018 100         (l->y1 > l->y2) ? 1 : -1;
218 2149 100         l->dir = l->y1 < l->y2 ? 1 : -1;
219              
220             POLY_DEB( printf("marking left line %d as %s(%d)\n", l->n,
221             l->updown ? l->updown == 1 ? "up" : "down" : "vert", l->updown, l->updown)
222             );
223              
224 2149 50         if (k+1 >= count) {
225 0           im_log((aIMCTX, 1, "Invalid polygon spec, odd number of line crossings.\n"));
226 0           return;
227             }
228              
229 2149           r = lset + tllist[k+1].n;
230 2149 50         if (r->y1 == r->y2) {
231 0           im_log((aIMCTX, 1, "mark_updown_slices: horizontal line being marked: internal error!\n"));
232 0           exit(3);
233             }
234              
235 4298           r->updown = (r->x1 == r->x2) ?
236 4239 100         0 :
237 2090           (r->x1 > r->x2)
238             ?
239 1041 100         (r->y1 > r->y2) ? -1 : 1
240 4180 100         :
241 1049 100         (r->y1 > r->y2) ? 1 : -1;
242 2149 100         r->dir = r->y1 < r->y2 ? 1 : -1;
243            
244             POLY_DEB( printf("marking right line %d as %s(%d)\n", r->n,
245             r->updown ? r->updown == 1 ? "up" : "down" : "vert", r->updown, r->updown)
246             );
247             }
248             }
249              
250             static
251             unsigned char
252 1672998           saturate(int in) {
253 1672998 100         if (in>255) { return 255; }
254 1484294 100         else if (in>0) return in;
255 1465094           return 0;
256             }
257              
258             typedef void (*scanline_flusher)(i_img *im, ss_scanline *ss, int y, void *ctx);
259              
260             /* This function must be modified later to do proper blending */
261              
262             static void
263 4782           scanline_flush(i_img *im, ss_scanline *ss, int y, void *ctx) {
264             int x, ch, tv;
265             i_color t;
266 4782           i_color *val = (i_color *)ctx;
267             POLY_DEB( printf("Flushing line %d\n", y) );
268 1620262 100         for(x=0; xxsize; x++) {
269 1615480           tv = saturate(ss->line[x]);
270 1615480           i_gpix(im, x, y, &t);
271 6461920 100         for(ch=0; chchannels; ch++)
272 4846440           t.channel[ch] = tv/255.0 * val->channel[ch] + (1.0-tv/255.0) * t.channel[ch];
273 1615480           i_ppix(im, x, y, &t);
274             }
275 4782           }
276              
277              
278              
279             static
280             int
281 5731           trap_square(pcord xlen, pcord ylen, double xl, double yl) {
282             POLY_DEB( printf("trap_square: %d %d %.2f %.2f\n", xlen, ylen, xl, yl) );
283 5731           return xlen*ylen-(xl*yl)/2.0;
284             }
285              
286              
287             /*
288             pixel_coverage calculates the 'left side' pixel coverage of a pixel that is
289             within the min/max ranges. The shape always corresponds to a square with some
290             sort of a triangle cut from it (which can also yield a triangle).
291             */
292              
293              
294             static
295             int
296 23091           pixel_coverage(p_line *line, pcord minx, pcord maxx, pcord miny, pcord maxy) {
297             double lycross, rycross;
298             int l, r;
299              
300             POLY_DEB
301             (
302             printf(" pixel_coverage(..., minx %g, maxx%g, miny %g, maxy %g)\n",
303             minx/16.0, maxx/16.0, miny/16.0, maxy/16.0)
304             );
305              
306 23091 100         if (!line->updown) {
307 520           l = r = 0;
308             } else {
309 22571           lycross = p_eval_atx(line, minx);
310 22571           rycross = p_eval_atx(line, maxx);
311 22571 100         l = lycross <= maxy && lycross >= miny; /* true if it enters through left side */
    100          
312 22571 100         r = rycross <= maxy && rycross >= miny; /* true if it enters through left side */
    100          
313             }
314             POLY_DEB(
315             printf(" %4s(%+d): ", line->updown ? line->updown == 1 ? "up" : "down" : "vert", line->updown);
316             printf(" (%2d,%2d) [%3d-%3d, %3d-%3d] lycross=%.2f rycross=%.2f", coarse(minx), coarse(miny), minx, maxx, miny, maxy, lycross, rycross);
317             printf(" l=%d r=%d\n", l, r)
318             );
319            
320 23091 100         if (l && r)
    100          
321 4237 100         return line->updown == 1 ?
322 2016           (double)(maxx-minx) * (2.0*maxy-lycross-rycross)/2.0 /* up case */
323             :
324 2221           (double)(maxx-minx) * (lycross+rycross-2*miny)/2.0; /* down case */
325            
326 18854 100         if (!l && !r) return (maxy-miny)*(maxx*2-p_eval_aty(line, miny)-p_eval_aty(line, maxy))/2.0;
    100          
327              
328 12113 100         if (l && !r)
    50          
329 5731           return line->updown == 1 ?
330 8165 100         trap_square(maxx-minx, maxy-miny, p_eval_aty(line, miny)-minx, p_eval_atx(line, minx)-miny) :
331 2434           trap_square(maxx-minx, maxy-miny, p_eval_aty(line, maxy)-minx, maxy-p_eval_atx(line, minx));
332            
333              
334 6382 50         if (!l && r) {
    50          
335 12764 100         int r = line->updown == 1 ?
336 3194           (maxx-p_eval_aty(line, maxy))*(maxy-p_eval_atx(line, maxx))/2.0 :
337 3188           (maxx-p_eval_aty(line, miny))*(p_eval_atx(line, maxx)-miny)/2.0;
338 6382           return r;
339             }
340              
341             /* NOTREACHED */
342 0           return 0; /* silence compiler warning */
343             }
344              
345              
346              
347              
348              
349             /*
350             handle the scanline slice in three steps
351            
352             1. Where only the left edge is inside a pixel
353             2a. Where both left and right edge are inside a pixel
354             2b. Where neither left or right edge are inside a pixel
355             3. Where only the right edge is inside a pixel
356             */
357              
358             static
359             void
360 7923           render_slice_scanline(ss_scanline *ss, int y, p_line *l, p_line *r, pcord miny, pcord maxy) {
361            
362             pcord lminx, lmaxx; /* left line min/max within y bounds in fine coords */
363             pcord rminx, rmaxx; /* right line min/max within y bounds in fine coords */
364             i_img_dim cpix; /* x-coordinate of current pixel */
365             i_img_dim startpix; /* temporary variable for "start of this interval" */
366             i_img_dim stoppix; /* temporary variable for "end of this interval" */
367              
368             /* Find the y bounds of scanline_slice */
369              
370             POLY_DEB
371             (
372             printf("render_slice_scanline(..., y=%d)\n");
373             printf(" left n=%d p1(%.2g, %.2g) p2(%.2g,%.2g) min(%.2g, %.2g) max(%.2g,%.2g) updown(%d)\n",
374             l->n, l->x1/16.0, l->y1/16.0, l->x2/16.0, l->y2/16.0,
375             l->minx/16.0, l->miny/16.0, l->maxx/16.0, l->maxy/16.0,
376             l->updown);
377             printf(" right n=%d p1(%.2g, %.2g) p2(%.2g,%.2g) min(%.2g, %.2g) max(%.2g,%.2g) updown(%d)\n",
378             r->n, r->x1/16.0, r->y1/16.0, r->x2/16.0, r->y2/16.0,
379             r->minx/16.0, r->miny/16.0, r->maxx/16.0, r->maxy/16.0,
380             r->updown);
381             );
382            
383 7923           lminx = i_min( p_eval_aty(l, maxy), p_eval_aty(l, miny) );
384 7923           lmaxx = i_max( p_eval_aty(l, maxy), p_eval_aty(l, miny) );
385              
386 7923           rminx = i_min( p_eval_aty(r, maxy), p_eval_aty(r, miny) );
387 7923           rmaxx = i_max( p_eval_aty(r, maxy), p_eval_aty(r, miny) );
388              
389 7923           startpix = i_max( coarse(lminx), 0 );
390 7923           stoppix = i_min( coarse(rmaxx-1), ss->linelen-1 );
391              
392             POLY_DEB( printf(" miny=%g maxy=%g\n", miny/16.0, maxy/16.0) );
393            
394 290282 100         for(cpix=startpix; cpix<=stoppix; cpix++) {
395 282359           int lt = coarse(lmaxx-1) >= cpix;
396 282359           int rt = coarse(rminx) <= cpix;
397            
398             int A, B, C;
399            
400             POLY_DEB( printf(" (%d,%d) lt=%d rt=%d\n", cpix, y, lt, rt) );
401              
402 282359 100         A = lt ? pixel_coverage(l, cpix*16, cpix*16+16, miny, maxy) : 0;
403 282359 100         B = lt ? 0 : 16*(maxy-miny);
404 282359 100         C = rt ? pixel_coverage(r, cpix*16, cpix*16+16, miny, maxy) : 0;
405              
406             POLY_DEB( printf(" A=%d B=%d C=%d\n", A, B, C) );
407              
408 282359           ss->line[cpix] += A+B-C;
409              
410             }
411             POLY_DEB( printf("end render_slice_scanline()\n") );
412 7923           }
413              
414             /* Antialiasing polygon algorithm
415             specs:
416             1. only nice polygons - no crossovers
417             2. 1/16 pixel resolution
418             3. full antialiasing ( complete spectrum of blends )
419             4. uses hardly any memory
420             5. no subsampling phase
421            
422              
423             Algorithm outline:
424             1. Split into vertical intervals.
425             2. handle each interval
426              
427             For each interval we must:
428             1. find which lines are in it
429             2. order the lines from in increasing x order.
430             since we are assuming no crossovers it is sufficent
431             to check a single point on each line.
432             */
433              
434             /*
435             Definitions:
436            
437             1. Interval: A vertical segment in which no lines cross nor end.
438             2. Scanline: A physical line, contains 16 subpixels in the horizontal direction
439             3. Slice: A start stop line pair.
440            
441             */
442              
443              
444             static int
445 99           i_poly_poly_aa_low(i_img *im, int count, const i_polygon_t *polys,
446             i_poly_fill_mode_t mode, void *ctx,
447             scanline_flusher flusher) {
448             int i ,k; /* Index variables */
449             i_img_dim clc; /* Lines inside current interval */
450             /* initialize to avoid compiler warnings */
451 99           pcord tempy = 0;
452 99           i_img_dim cscl = 0; /* Current scanline */
453              
454             ss_scanline templine; /* scanline accumulator */
455             p_point *pset; /* List of points in polygon */
456             p_line *lset; /* List of lines in polygon */
457             p_slice *tllist; /* List of slices */
458             size_t pcount, lcount;
459 99           dIMCTX;
460              
461 99           im_log((aIMCTX, 1, "i_poly_poly_aa_low(im %p, count %d, polys %p, ctx %p, flusher %p)\n", im, count, polys, ctx, flusher));
462              
463 99           i_clear_error();
464              
465 99 50         if (count < 1) {
466 0           i_push_error(0, "no polygons to draw");
467 0           return 0;
468             }
469              
470 204 100         for (k = 0; k < count; ++k) {
471 107 100         if (polys[k].count < 3) {
472 2           i_push_error(0, "polygons must have at least 3 points");
473 2           return 0;
474             }
475             }
476              
477 202 100         for (k = 0; k < count; ++k) {
478 105           const i_polygon_t *p = polys + k;
479 105           im_log((aIMCTX, 2, "poly %d\n", k));
480 2077 100         for(i = 0; i < p->count; i++) {
481 1972           im_log((aIMCTX, 2, " (%.2f, %.2f)\n", p->x[i], p->y[i]));
482             }
483             }
484              
485              
486             POLY_DEB(
487             fflush(stdout);
488             setbuf(stdout, NULL);
489             );
490              
491 97           pset = point_set_new(polys, count, &pcount);
492 97           lset = line_set_new(polys, count, &lcount);
493              
494 97           ss_scanline_init(&templine, im->xsize, lcount);
495              
496 97           tllist = mymalloc(sizeof(p_slice) * lcount);
497            
498 97           qsort(pset, pcount, sizeof(p_point), (int(*)(const void *,const void *))p_compy);
499            
500             POLY_DEB(
501             for(i=0;i
502             printf("%d [ %d ] (%d , %d) -> (%d , %d) yspan ( %d , %d )\n",
503             i, lset[i].n, lset[i].x1, lset[i].y1, lset[i].x2, lset[i].y2, lset[i].miny, lset[i].maxy);
504             }
505             printf("MAIN LOOP\n\n");
506             );
507            
508              
509             /* loop on intervals */
510 1972 100         for(i=0; i
511 1875           i_img_dim startscan = i_max( coarse(pset[i].y), 0);
512 1875           i_img_dim stopscan = i_min( coarse(pset[i+1].y+15), im->ysize);
513             pcord miny, maxy; /* y bounds in fine coordinates */
514              
515             POLY_DEB( pcord cc = (pset[i].y + pset[i+1].y)/2 );
516              
517             POLY_DEB(
518             printf("current slice is %d: %d to %d ( cpoint %d ) scanlines %d to %d\n",
519             i, pset[i].y, pset[i+1].y, cc, startscan, stopscan)
520             );
521            
522 1875 100         if (pset[i].y == pset[i+1].y) {
523             POLY_DEB( printf("current slice thickness = 0 => skipping\n") );
524 518           continue;
525             }
526              
527 1357           clc = lines_in_interval(lset, lcount, tllist, pset[i].y, pset[i+1].y);
528 1357           qsort(tllist, clc, sizeof(p_slice), (int(*)(const void *,const void *))p_compx);
529              
530 1357           mark_updown_slices(aIMCTX, lset, tllist, clc);
531              
532             POLY_DEB
533             (
534             printf("Interval contains %d lines\n", clc);
535             for(k=0; k
536             int lno = tllist[k].n;
537             p_line *ln = lset+lno;
538             printf("%d: line #%2d: (%2d, %2d)->(%2d, %2d) (%2d/%2d, %2d/%2d) -> (%2d/%2d, %2d/%2d) alignment=%s\n",
539             k, lno, ln->x1, ln->y1, ln->x2, ln->y2,
540             coarse(ln->x1), fine(ln->x1),
541             coarse(ln->y1), fine(ln->y1),
542             coarse(ln->x2), fine(ln->x2),
543             coarse(ln->y2), fine(ln->y2),
544             ln->updown == 0 ? "vert" : ln->updown == 1 ? "up" : "down");
545            
546             }
547             );
548 1357           maxy = im->ysize * 16;
549 1357           miny = 0;
550 5655 100         for (k = 0; k < clc; ++k) {
551 4298           p_line const * line = lset + tllist[k].n;
552 4298 100         if (line->miny > miny)
553 2006           miny = line->miny;
554 4298 100         if (line->maxy < maxy)
555 1989           maxy = line->maxy;
556             POLY_DEB( printf(" line miny %g maxy %g\n", line->miny/16.0, line->maxy/16.0) );
557             }
558             POLY_DEB( printf("miny %g maxy %g\n", miny/16.0, maxy/16.0) );
559              
560 7820 100         for(cscl=startscan; cscl
561 6463           pcord scan_miny = i_max(miny, cscl * 16);
562 6463           pcord scan_maxy = i_min(maxy, (cscl + 1 ) * 16);
563            
564 6463           tempy = i_min(cscl*16+16, pset[i+1].y);
565             POLY_DEB( printf("evaluating scan line %d \n", cscl) );
566 6463 100         if (mode == i_pfm_evenodd) {
567 13826 100         for(k=0; k
568             POLY_DEB( printf("evaluating slice %d\n", k) );
569 7603           render_slice_scanline(&templine, cscl, lset+tllist[k].n, lset+tllist[k+1].n, scan_miny, scan_maxy);
570             }
571             }
572             else {
573 240           k = 0;
574 560 100         while (k < clc) {
575 320           p_line *left = lset + tllist[k++].n;
576 320           p_line *current = NULL;
577 320           int acc = left->dir;
578              
579 800 100         while (k < clc && acc) {
    100          
580 480           current = lset + tllist[k++].n;
581 480           acc += current->dir;
582             }
583 320 50         if (acc == 0) {
584 320           render_slice_scanline(&templine, cscl, left, current,
585             scan_miny, scan_maxy);
586             }
587             }
588             }
589 6463 100         if (16*coarse(tempy) == tempy) {
590             POLY_DEB( printf("flushing scan line %d\n", cscl) );
591 5322           flusher(im, &templine, cscl, ctx);
592 5322           ss_scanline_reset(&templine);
593             }
594             /*
595             else {
596             scanline_flush(im, &templine, cscl, val);
597             ss_scanline_reset(&templine);
598             return 0;
599             }
600             */
601             }
602             } /* Intervals */
603 97 100         if (16*coarse(tempy) != tempy)
604 83           flusher(im, &templine, cscl-1, ctx);
605              
606 97           ss_scanline_exorcise(&templine);
607 97           myfree(pset);
608 97           myfree(lset);
609 97           myfree(tllist);
610              
611 99           return 1;
612             }
613              
614             /*
615             =item i_poly_poly_aa(im, count, polys, mode, color)
616             =synopsis i_poly_poly_aa(im, 1, &poly, mode, color);
617             =category Drawing
618              
619             Fill the C polygons defined by C the color specified by
620             C.
621              
622             At least one polygon must be supplied.
623              
624             All polygons must have at least 3 points.
625              
626             =cut
627             */
628              
629             int
630 94           i_poly_poly_aa(i_img *im, int count, const i_polygon_t *polys,
631             i_poly_fill_mode_t mode, const i_color *val) {
632 94           i_color c = *val;
633 94           return i_poly_poly_aa_low(im, count, polys, mode, &c, scanline_flush);
634             }
635              
636             /*
637             =item i_poly_aa_m(im, count, x, y, mode, color)
638             =synopsis i_poly_aa_m(im, count, x, y, mode, color);
639             =category Drawing
640              
641             Fill a polygon defined by the points specified by the x and y arrays with
642             the color specified by C.
643              
644             =cut
645             */
646              
647             int
648 63           i_poly_aa_m(i_img *im, int l, const double *x, const double *y,
649             i_poly_fill_mode_t mode, const i_color *val) {
650             i_polygon_t poly;
651              
652 63           poly.count = l;
653 63           poly.x = x;
654 63           poly.y = y;
655 63           return i_poly_poly_aa(im, 1, &poly, mode, val);
656             }
657              
658             int
659 25           i_poly_aa(i_img *im, int l, const double *x, const double *y, const i_color *val) {
660             i_polygon_t poly;
661              
662 25           poly.count = l;
663 25           poly.x = x;
664 25           poly.y = y;
665 25           return i_poly_poly_aa(im, 1, &poly, i_pfm_evenodd, val);
666             }
667              
668             struct poly_render_state {
669             i_render render;
670             i_fill_t *fill;
671             unsigned char *cover;
672             };
673              
674             static void
675 623           scanline_flush_render(i_img *im, ss_scanline *ss, int y, void *ctx) {
676             i_img_dim x;
677             i_img_dim left, right;
678 623           struct poly_render_state *state = (struct poly_render_state *)ctx;
679              
680 623           left = 0;
681 58408 50         while (left < im->xsize && ss->line[left] <= 0)
    100          
682 57785           ++left;
683 623 50         if (left < im->xsize) {
684 623           right = im->xsize;
685             /* since going from the left found something, moving from the
686             right should */
687 54820 100         while (/* right > left && */ ss->line[right-1] <= 0)
688 54197           --right;
689            
690             /* convert to the format the render interface wants */
691 58141 100         for (x = left; x < right; ++x) {
692 57518           state->cover[x-left] = saturate(ss->line[x]);
693             }
694 623           i_render_fill(&state->render, left, y, right-left, state->cover,
695             state->fill);
696             }
697 623           }
698              
699             /*
700             =item i_poly_poly_aa_cfill(im, count, polys, mode, fill)
701             =synopsis i_poly_poly_aa_cfill(im, 1, &poly, mode, fill);
702             =category Drawing
703              
704             Fill the C polygons defined by C the fill specified by
705             C.
706              
707             At least one polygon must be supplied.
708              
709             All polygons must have at least 3 points.
710              
711             =cut
712             */
713              
714             int
715 5           i_poly_poly_aa_cfill(i_img *im, int count, const i_polygon_t *polys,
716             i_poly_fill_mode_t mode, i_fill_t *fill) {
717             struct poly_render_state ctx;
718             int result;
719              
720 5           i_render_init(&ctx.render, im, im->xsize);
721 5           ctx.fill = fill;
722 5           ctx.cover = mymalloc(im->xsize);
723              
724 5           result = i_poly_poly_aa_low(im, count, polys, mode, &ctx,
725             scanline_flush_render);
726              
727 5           myfree(ctx.cover);
728 5           i_render_done(&ctx.render);
729              
730 5           return result;
731             }
732              
733             /*
734             =item i_poly_aa_cfill_m(im, count, x, y, mode, fill)
735             =synopsis i_poly_aa_cfill(im, count, x, y, mode, fill);
736             =category Drawing
737              
738             Fill a polygon defined by the points specified by the x and y arrays with
739             the fill specified by C.
740              
741             =cut
742             */
743              
744             int
745 4           i_poly_aa_cfill_m(i_img *im, int l, const double *x, const double *y,
746             i_poly_fill_mode_t mode, i_fill_t *fill) {
747             i_polygon_t poly;
748              
749 4           poly.count = l;
750 4           poly.x = x;
751 4           poly.y = y;
752              
753 4           return i_poly_poly_aa_cfill(im, 1, &poly, mode, fill);
754             }
755              
756             int
757 1           i_poly_aa_cfill(i_img *im, int l, const double *x, const double *y,
758             i_fill_t *fill) {
759             i_polygon_t poly;
760              
761 1           poly.count = l;
762 1           poly.x = x;
763 1           poly.y = y;
764              
765 1           return i_poly_poly_aa_cfill(im, 1, &poly, i_pfm_evenodd, fill);
766             }