Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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