+#define IMAGER_NO_CONTEXT
#include "imager.h"
#include "draw.h"
#include "log.h"
pcord miny,maxy;
pcord minx,maxx;
int updown; /* -1 means down, 0 vertical, 1 up */
+ int dir; /* 1 for down, -1 for up */
} p_line;
typedef struct {
for (i = 0; i < count; ++i)
lines += polys[i].count;
- *line_count = lines;
-
line = lset = mymalloc(sizeof(p_line) * lines);
n = 0;
const i_polygon_t *p = polys + i;
for(j = 0; j < p->count; j++) {
- line->n = n++;
line->x1 = IMTRUNC(p->x[j]);
line->y1 = IMTRUNC(p->y[j]);
line->x2 = IMTRUNC(p->x[(j + 1) % p->count]);
line->y2 = IMTRUNC(p->y[(j + 1) % p->count]);
+
+ /* don't include purely horizontal lines, we don't usefully
+ intersect with them. */
+ if (line->y1 == line->y2)
+ continue;
+
line->miny = i_min(line->y1, line->y2);
line->maxy = i_max(line->y1, line->y2);
line->minx = i_min(line->x1, line->x2);
line->maxx = i_max(line->x1, line->x2);
+ line->n = n++;
++line;
}
}
+ *line_count = n;
return lset;
}
static
void
-mark_updown_slices(p_line *lset, p_slice *tllist, int count) {
+mark_updown_slices(pIMCTX, p_line *lset, p_slice *tllist, int count) {
p_line *l, *r;
int k;
for(k=0; k<count; k+=2) {
l = lset + tllist[k].n;
if (l->y1 == l->y2) {
- mm_log((1, "mark_updown_slices: horizontal line being marked: internal error!\n"));
+ im_log((aIMCTX,1, "mark_updown_slices: horizontal line being marked: internal error!\n"));
exit(3);
}
(l->y1 > l->y2) ? -1 : 1
:
(l->y1 > l->y2) ? 1 : -1;
+ l->dir = l->y1 < l->y2 ? 1 : -1;
POLY_DEB( printf("marking left line %d as %s(%d)\n", l->n,
l->updown ? l->updown == 1 ? "up" : "down" : "vert", l->updown, l->updown)
);
if (k+1 >= count) {
- mm_log((1, "Invalid polygon spec, odd number of line crossings.\n"));
+ im_log((aIMCTX, 1, "Invalid polygon spec, odd number of line crossings.\n"));
return;
}
r = lset + tllist[k+1].n;
if (r->y1 == r->y2) {
- mm_log((1, "mark_updown_slices: horizontal line being marked: internal error!\n"));
+ im_log((aIMCTX, 1, "mark_updown_slices: horizontal line being marked: internal error!\n"));
exit(3);
}
(r->y1 > r->y2) ? -1 : 1
:
(r->y1 > r->y2) ? 1 : -1;
+ r->dir = r->y1 < r->y2 ? 1 : -1;
POLY_DEB( printf("marking right line %d as %s(%d)\n", r->n,
r->updown ? r->updown == 1 ? "up" : "down" : "vert", r->updown, r->updown)
static int
i_poly_poly_aa_low(i_img *im, int count, const i_polygon_t *polys,
- void *ctx, scanline_flusher flusher) {
+ i_poly_fill_mode_t mode, void *ctx,
+ scanline_flusher flusher) {
int i ,k; /* Index variables */
i_img_dim clc; /* Lines inside current interval */
/* initialize to avoid compiler warnings */
p_line *lset; /* List of lines in polygon */
p_slice *tllist; /* List of slices */
size_t pcount, lcount;
+ dIMCTX;
+
+ 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));
+
+ i_clear_error();
- mm_log((1, "i_poly_poly_aa_low(im %p, count %d, polys %p, ctx %p, flusher %p)\n", im, count, polys, ctx, flusher));
+ if (count < 1) {
+ i_push_error(0, "no polygons to draw");
+ return 0;
+ }
+
+ for (k = 0; k < count; ++k) {
+ if (polys[k].count < 3) {
+ i_push_error(0, "polygons must have at least 3 points");
+ return 0;
+ }
+ }
for (k = 0; k < count; ++k) {
const i_polygon_t *p = polys + k;
- mm_log((2, "poly %d\n", k));
+ im_log((aIMCTX, 2, "poly %d\n", k));
for(i = 0; i < p->count; i++) {
- mm_log((2, " (%.2f, %.2f)\n", p->x[i], p->y[i]));
+ im_log((aIMCTX, 2, " (%.2f, %.2f)\n", p->x[i], p->y[i]));
}
}
clc = lines_in_interval(lset, lcount, tllist, pset[i].y, pset[i+1].y);
qsort(tllist, clc, sizeof(p_slice), (int(*)(const void *,const void *))p_compx);
- mark_updown_slices(lset, tllist, clc);
+ mark_updown_slices(aIMCTX, lset, tllist, clc);
POLY_DEB
(
tempy = i_min(cscl*16+16, pset[i+1].y);
POLY_DEB( printf("evaluating scan line %d \n", cscl) );
- for(k=0; k<clc-1; k+=2) {
- POLY_DEB( printf("evaluating slice %d\n", k) );
- render_slice_scanline(&templine, cscl, lset+tllist[k].n, lset+tllist[k+1].n, scan_miny, scan_maxy);
+ if (mode == i_pfm_evenodd) {
+ for(k=0; k<clc-1; k+=2) {
+ POLY_DEB( printf("evaluating slice %d\n", k) );
+ render_slice_scanline(&templine, cscl, lset+tllist[k].n, lset+tllist[k+1].n, scan_miny, scan_maxy);
+ }
+ }
+ else {
+ k = 0;
+ while (k < clc) {
+ p_line *left = lset + tllist[k++].n;
+ p_line *current = NULL;
+ int acc = left->dir;
+
+ while (k < clc && acc) {
+ current = lset + tllist[k++].n;
+ acc += current->dir;
+ }
+ if (acc == 0) {
+ render_slice_scanline(&templine, cscl, left, current,
+ scan_miny, scan_maxy);
+ }
+ }
}
if (16*coarse(tempy) == tempy) {
POLY_DEB( printf("flushing scan line %d\n", cscl) );
return 1;
}
+/*
+=item i_poly_poly_aa(im, count, polys, mode, color)
+=synopsis i_poly_poly_aa(im, 1, &poly, mode, color);
+=category Drawing
+
+Fill the C<count> polygons defined by C<polys> the color specified by
+C<color>.
+
+At least one polygon must be supplied.
+
+All polygons must have at least 3 points.
+
+=cut
+*/
+
int
i_poly_poly_aa(i_img *im, int count, const i_polygon_t *polys,
- const i_color *val) {
+ i_poly_fill_mode_t mode, const i_color *val) {
i_color c = *val;
- return i_poly_poly_aa_low(im, count, polys, &c, scanline_flush);
+ return i_poly_poly_aa_low(im, count, polys, mode, &c, scanline_flush);
+}
+
+/*
+=item i_poly_aa_m(im, count, x, y, mode, color)
+=synopsis i_poly_aa_m(im, count, x, y, mode, color);
+=category Drawing
+
+Fill a polygon defined by the points specified by the x and y arrays with
+the color specified by C<color>.
+
+=cut
+*/
+
+int
+i_poly_aa_m(i_img *im, int l, const double *x, const double *y,
+ i_poly_fill_mode_t mode, const i_color *val) {
+ i_polygon_t poly;
+
+ poly.count = l;
+ poly.x = x;
+ poly.y = y;
+ return i_poly_poly_aa(im, 1, &poly, mode, val);
}
int
poly.count = l;
poly.x = x;
poly.y = y;
- return i_poly_poly_aa(im, 1, &poly, val);
+ return i_poly_poly_aa(im, 1, &poly, i_pfm_evenodd, val);
}
struct poly_render_state {
}
}
+/*
+=item i_poly_poly_aa_cfill(im, count, polys, mode, fill)
+=synopsis i_poly_poly_aa_cfill(im, 1, &poly, mode, fill);
+=category Drawing
+
+Fill the C<count> polygons defined by C<polys> the fill specified by
+C<fill>.
+
+At least one polygon must be supplied.
+
+All polygons must have at least 3 points.
+
+=cut
+*/
+
int
i_poly_poly_aa_cfill(i_img *im, int count, const i_polygon_t *polys,
- i_fill_t *fill) {
+ i_poly_fill_mode_t mode, i_fill_t *fill) {
struct poly_render_state ctx;
int result;
ctx.fill = fill;
ctx.cover = mymalloc(im->xsize);
- result = i_poly_poly_aa_low(im, count, polys, &ctx, scanline_flush_render);
+ result = i_poly_poly_aa_low(im, count, polys, mode, &ctx,
+ scanline_flush_render);
myfree(ctx.cover);
i_render_done(&ctx.render);
return result;
}
+/*
+=item i_poly_aa_cfill_m(im, count, x, y, mode, fill)
+=synopsis i_poly_aa_cfill(im, count, x, y, mode, fill);
+=category Drawing
+
+Fill a polygon defined by the points specified by the x and y arrays with
+the fill specified by C<fill>.
+
+=cut
+*/
+
+int
+i_poly_aa_cfill_m(i_img *im, int l, const double *x, const double *y,
+ i_poly_fill_mode_t mode, i_fill_t *fill) {
+ i_polygon_t poly;
+
+ poly.count = l;
+ poly.x = x;
+ poly.y = y;
+
+ return i_poly_poly_aa_cfill(im, 1, &poly, mode, fill);
+}
+
int
i_poly_aa_cfill(i_img *im, int l, const double *x, const double *y,
i_fill_t *fill) {
poly.x = x;
poly.y = y;
- return i_poly_poly_aa_cfill(im, 1, &poly, fill);
+ return i_poly_poly_aa_cfill(im, 1, &poly, i_pfm_evenodd, fill);
}