From: Matthias Kramm Date: Thu, 1 Apr 2010 21:25:34 +0000 (-0700) Subject: reworked edgestyle logic X-Git-Tag: version-0-9-1~5^2~17 X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=commitdiff_plain;h=afeee73172d508d2e7e4efd028939e36356fbe8e reworked edgestyle logic --- diff --git a/lib/gfxpoly/Makefile b/lib/gfxpoly/Makefile index 7a8b9cc..d91c78f 100644 --- a/lib/gfxpoly/Makefile +++ b/lib/gfxpoly/Makefile @@ -36,7 +36,7 @@ xrow.o: xrow.c xrow.h ../q.h ../mem.h stroke.o: stroke.c poly.h convert.h wind.h $(CC) -c stroke.c -o stroke.o -GFX=../gfxfont.o ../gfxtools.o ../devices/ops.o ../devices/polyops.o ../devices/text.o ../devices/bbox.o ../devices/render.o ../devices/rescale.o ../devices/record.o +GFX=../gfxfont.o ../gfxtools.o ../gfximage.o ../devices/ops.o ../devices/polyops.o ../devices/text.o ../devices/bbox.o ../devices/render.o ../devices/rescale.o ../devices/record.o stroke: test_stroke.c $(OBJS) ../libgfxswf.a ../librfxswf.a ../libbase.a $(CC) test_stroke.c $(OBJS) ../libgfxswf.a ../librfxswf.a $(GFX) ../libbase.a -o stroke $(LIBS) diff --git a/lib/gfxpoly/active.c b/lib/gfxpoly/active.c index b723185..ae570fd 100644 --- a/lib/gfxpoly/active.c +++ b/lib/gfxpoly/active.c @@ -31,7 +31,7 @@ void actlist_dump(actlist_t*a, int32_t y) } lastx = x; } - fprintf(stderr, "[%d]", s->nr); + fprintf(stderr, "[%d]", (int)s->nr); s = s->right; if(s) fprintf(stderr, " "); else fprintf(stderr, " y=%d\n", y); @@ -100,7 +100,7 @@ segment_t* actlist_find(actlist_t*a, point_t p1, point_t p2) actlist_dump(a, p1.y); segment_t*s = a->list; while(s) { - fprintf(stderr, "[%d] %f/%f (%d,%d) -> (%d,%d)\n", s->nr, + fprintf(stderr, "[%d] %f/%f (%d,%d) -> (%d,%d)\n", SEGNR(s), single_cmp(s,p1), cmp(s,p1,p2), s->a.x, s->a.y, s->b.x, s->b.y); s = s->right; diff --git a/lib/gfxpoly/convert.c b/lib/gfxpoly/convert.c index 0a2cc93..28c3b7a 100644 --- a/lib/gfxpoly/convert.c +++ b/lib/gfxpoly/convert.c @@ -133,6 +133,7 @@ void finish_segment(compactpoly_t*data) return; point_t*p = malloc(sizeof(point_t)*data->num_points); gfxpolystroke_t*s = rfx_calloc(sizeof(gfxpolystroke_t)); + s->fs = &edgestyle_default; s->next = data->poly->strokes; data->poly->strokes = s; s->num_points = s->points_size = data->num_points; diff --git a/lib/gfxpoly/poly.c b/lib/gfxpoly/poly.c index eb1b6b1..36304ae 100644 --- a/lib/gfxpoly/poly.c +++ b/lib/gfxpoly/poly.c @@ -172,6 +172,12 @@ char gfxpoly_check(gfxpoly_t*poly) int s,t; gfxpolystroke_t*stroke = poly->strokes; for(;stroke;stroke=stroke->next) { + /* In order to not confuse the fill/wind logic, existing segments must have + a non-zero edge style */ + assert(stroke->fs); + + /* put all the segments into dictionaries so that we can check + that the endpoint multiplicity is two */ for(s=0;snum_points;s++) { point_t p = stroke->points[s]; int num = (s>=1 && snum_points-1)?2:1; // mid points are two points (start+end) @@ -201,14 +207,14 @@ void gfxpoly_dump(gfxpoly_t*poly) { int s,t; double g = poly->gridsize; - fprintf(stderr, "polyon %08x (gridsize: %f)\n", (int)poly, poly->gridsize); + fprintf(stderr, "polyon %p (gridsize: %f)\n", poly, poly->gridsize); gfxpolystroke_t*stroke = poly->strokes; for(;stroke;stroke=stroke->next) { - fprintf(stderr, "%08x", (int)stroke); + fprintf(stderr, "%p", stroke); for(s=0;snum_points-1;s++) { point_t a = stroke->points[s]; point_t b = stroke->points[s+1]; - fprintf(stderr, "%s (%f,%f) -> (%f,%f)%s\n", s?" ":"", a.x*g, a.y*g, b.x*g, b.y*g, + fprintf(stderr, "%s (%f,%f) -> (%f,%f)%s\n", s?" ":"", a.x*g, a.y*g, b.x*g, b.y*g, s==stroke->num_points-2?"]":""); } } @@ -248,13 +254,13 @@ inline static void event_free(event_t*e) static void event_dump(event_t*e) { if(e->type == EVENT_HORIZONTAL) { - fprintf(stderr, "Horizontal [%d] (%d,%d) -> (%d,%d)\n", e->s1->nr, e->s1->a.x, e->s1->a.y, e->s1->b.x, e->s1->b.y); + fprintf(stderr, "Horizontal [%d] (%d,%d) -> (%d,%d)\n", (int)e->s1->nr, e->s1->a.x, e->s1->a.y, e->s1->b.x, e->s1->b.y); } else if(e->type == EVENT_START) { - fprintf(stderr, "event: segment [%d] starts at (%d,%d)\n", e->s1->nr, e->p.x, e->p.y); + fprintf(stderr, "event: segment [%d] starts at (%d,%d)\n", (int)e->s1->nr, e->p.x, e->p.y); } else if(e->type == EVENT_END) { - fprintf(stderr, "event: segment [%d] ends at (%d,%d)\n", e->s1->nr, e->p.x, e->p.y); + fprintf(stderr, "event: segment [%d] ends at (%d,%d)\n", (int)e->s1->nr, e->p.x, e->p.y); } else if(e->type == EVENT_CROSS) { - fprintf(stderr, "event: segment [%d] and [%d] intersect at (%d,%d)\n", e->s1->nr, e->s2->nr, e->p.x, e->p.y); + fprintf(stderr, "event: segment [%d] and [%d] intersect at (%d,%d)\n", (int)e->s1->nr, (int)e->s2->nr, e->p.x, e->p.y); } else { assert(0); } @@ -265,14 +271,15 @@ static inline int32_t min32(int32_t v1, int32_t v2) {return v1(%d,%d) ", s->nr, s->a.x, s->a.y, s->b.x, s->b.y); - fprintf(stderr, " dx:%d dy:%d k:%f dx/dy=%f\n", s->delta.x, s->delta.y, s->k, - (double)s->delta.x / s->delta.y); + fprintf(stderr, "[%d] (%d,%d)->(%d,%d) ", (int)s->nr, s->a.x, s->a.y, s->b.x, s->b.y); + fprintf(stderr, " dx:%d dy:%d k:%f dx/dy=%f fs=%p\n", s->delta.x, s->delta.y, s->k, + (double)s->delta.x / s->delta.y, s->fs_orig); } -static void segment_init(segment_t*s, int32_t x1, int32_t y1, int32_t x2, int32_t y2, int polygon_nr, segment_dir_t dir) +static void segment_init(segment_t*s, int32_t x1, int32_t y1, int32_t x2, int32_t y2, edgestyle_t*fs, int polygon_nr, segment_dir_t dir) { s->dir = dir; + s->fs_orig = fs; if(y1!=y2) { assert(y1num_points-1) { assert(stroke->points[pos].y <= stroke->points[pos+1].y); - s = segment_new(stroke->points[pos], stroke->points[pos+1], polygon_nr, stroke->dir); + s = segment_new(stroke->points[pos], stroke->points[pos+1], stroke->fs, polygon_nr, stroke->dir); pos++; s->stroke = 0; s->stroke_pos = 0; #ifdef DEBUG /*if(l->tmp) s->nr = l->tmp;*/ - fprintf(stderr, "[%d] (%d,%d) -> (%d,%d) %s (stroke %08x, %d more to come)\n", + fprintf(stderr, "[%d] (%d,%d) -> (%d,%d) %s (stroke %p, %d more to come)\n", s->nr, s->a.x, s->a.y, s->b.x, s->b.y, s->dir==DIR_UP?"up":"down", stroke, stroke->num_points - 1 - pos); #endif @@ -658,9 +665,7 @@ static void insert_point_into_segment(status_t*status, segment_t*s, point_t p) fprintf(stderr, "[%d] receives next point (%d,%d)->(%d,%d) (drawing)\n", s->nr, s->pos.x, s->pos.y, p.x, p.y); #endif - /* XXX we probably will never output circular/anticircular polygons, but if - we do, we would need to set the segment direction here */ - fillstyle_t*fs = s->fs_out; + edgestyle_t*fs = s->fs_out; // omit horizontal lines if(s->pos.y != p.y) { @@ -669,6 +674,8 @@ static void insert_point_into_segment(status_t*status, segment_t*s, point_t p) assert(a.y != b.y); gfxpolystroke_t*stroke = status->strokes; + /* find a stoke to attach this segment to. It has to have an endpoint + matching our start point, and a matching edgestyle */ while(stroke) { point_t p = stroke->points[stroke->num_points-1]; if(p.x == a.x && p.y == a.y && stroke->fs == fs) @@ -686,6 +693,7 @@ static void insert_point_into_segment(status_t*status, segment_t*s, point_t p) stroke->points[0] = a; stroke->num_points = 1; } else if(stroke->num_points == stroke->points_size) { + assert(stroke->fs); stroke->points_size *= 2; stroke->points = rfx_realloc(stroke->points, sizeof(point_t)*stroke->points_size); } @@ -913,7 +921,7 @@ static void recalculate_windings(status_t*status, segrange_t*range) s = range->segmin; #endif #ifdef CHECKS - /* test sanity: check that we don't have changed segments + /* test sanity: verify that we don't have changed segments outside of the given range */ s = actlist_leftmost(status->actlist); while(s && s!=range->segmin) { @@ -926,7 +934,7 @@ static void recalculate_windings(status_t*status, segrange_t*range) s = s->left; } /* in check mode, go through the whole interval so we can test - that all polygons where the fillstyle changed also have seg->changed=1 */ + that all polygons where the edgestyle changed also have seg->changed=1 */ s = actlist_leftmost(status->actlist); end = 0; #endif @@ -940,8 +948,8 @@ static void recalculate_windings(status_t*status, segrange_t*range) { segment_t* left = actlist_left(status->actlist, s); windstate_t wind = left?left->wind:status->windrule->start(status->context); - s->wind = status->windrule->add(status->context, wind, s->fs, s->dir, s->polygon_nr); - fillstyle_t*fs_old = s->fs_out; + s->wind = status->windrule->add(status->context, wind, s->fs_orig, s->dir, s->polygon_nr); + edgestyle_t*fs_old = s->fs_out; s->fs_out = status->windrule->diff(&wind, &s->wind); #ifdef DEBUG @@ -1096,7 +1104,7 @@ static void check_status(status_t*status) s->pos.y != s->b.y) && !dict_contains(status->segs_with_point, s)) { fprintf(stderr, "Error: segment [%d] (%sslope) intersects in scanline %d, but it didn't receive a point\n", - s->nr, + SEGNR(s), s->delta.x<0?"-":"+", status->y); assert(0); @@ -1128,7 +1136,7 @@ static void add_horizontals(gfxpoly_t*poly, windrule_t*windrule, windcontext_t*c while(e) { int32_t y = e->p.y; int32_t x = 0; - char fill = 0; + windstate_t w = windrule->start(context); #ifdef DEBUG fprintf(stderr, "HORIZONTALS ----------------------------------- %d\n", y); actlist_dump(actlist, y-1); @@ -1136,7 +1144,11 @@ static void add_horizontals(gfxpoly_t*poly, windrule_t*windrule, windcontext_t*c #ifdef CHECKS actlist_verify(actlist, y-1); #endif + edgestyle_t*fill = 0; + edgestyle_t*fill2 = 0; + do { + assert(e->s1->fs_orig); if(fill && x != e->p.x) { #ifdef DEBUG fprintf(stderr, "%d) draw horizontal line from %d to %d\n", y, x, e->p.x); @@ -1150,7 +1162,7 @@ static void add_horizontals(gfxpoly_t*poly, windrule_t*windrule, windcontext_t*c stroke->num_points = 2; stroke->points = malloc(sizeof(point_t)*2); stroke->dir = DIR_UP; // FIXME - stroke->fs = 0; + stroke->fs = fill; point_t a,b; a.y = b.y = y; /* we draw from low x to high x so that left/right fillstyles add up @@ -1162,7 +1174,7 @@ static void add_horizontals(gfxpoly_t*poly, windrule_t*windrule, windcontext_t*c stroke->points[1] = b; #ifdef CHECKS /* the output should always be intersection free polygons, so check this horizontal - line isn't hacking through any segments in the active list */ + line isn't puncturing any segments in the active list */ segment_t* start = actlist_find(actlist, b, b); segment_t* s = actlist_find(actlist, a, a); while(s!=start) { @@ -1171,9 +1183,40 @@ static void add_horizontals(gfxpoly_t*poly, windrule_t*windrule, windcontext_t*c } #endif } + + /* + before1 / after1 + -----+----------- + before2 / after2 + / + */ + + edgestyle_t*old_fill = fill; + windstate_t before1 = w; + windstate_t after1; + /* the current horizontal line is between before1 and before2: */ + windstate_t before2 = fill?windrule->add(context, before1, fill, DIR_UNKNOWN, -1):before1; + windstate_t after2; + + segment_t*s = e->s1; + assert(!e->s2); + + switch(e->type) { + case EVENT_START: { + after1 = before1; + after2 = windrule->add(context, before2, s->fs_orig, DIR_UNKNOWN, s->polygon_nr); + break; + } + case EVENT_END: { + after1 = windrule->add(context, before1, s->fs_orig, DIR_UNKNOWN, s->polygon_nr); + after2 = before2; + break; + } + default: assert(0); + } + fill2 = windrule->diff(&after1, &after2); + segment_t*left = 0; - segment_t*s = e->s1; - switch(e->type) { case EVENT_START: { assert(e->p.x == s->a.x && e->p.y == s->a.y); @@ -1197,7 +1240,29 @@ static void add_horizontals(gfxpoly_t*poly, windrule_t*windrule, windcontext_t*c } x = e->p.x; - fill ^= 1;//(before.is_filled != after.is_filled); +#ifdef CHECKS + if(windrule==&windrule_evenodd) { + fill = fill?0:&edgestyle_default; + if(!!fill != !!fill2) { + segment_dump(s); + event_dump(e); + printf("at y=%d x=%d (hline:%p)\n", e->p.y, x, old_fill); + if(e->type==EVENT_END) { + printf(" %9p\n", s->fs_orig); + printf(" |\n"); + } + printf(" %3d %c%2d \n", before1.is_filled, e->type==EVENT_END?'|':' ', after1.is_filled); + printf("%12p -----+----- %p\n", old_fill, fill2); + printf(" %3d %c%2d \n", before2.is_filled, e->type==EVENT_START?'|':' ', after2.is_filled); + if(e->type==EVENT_START) { + printf(" |\n"); + printf(" %9p\n", s->fs_orig); + } + } + assert(!!fill == !!fill2); + } +#endif + #ifdef DEBUG fprintf(stderr, "%d) event=%s[%d] left:[%d] x:%d\n", y, e->type==EVENT_START?"start":"end", @@ -1214,7 +1279,7 @@ static void add_horizontals(gfxpoly_t*poly, windrule_t*windrule, windcontext_t*c } while(e && y == e->p.y); #ifdef CHECKS - char bleeding = fill; + edgestyle_t*bleeding = fill; assert(!bleeding); #endif } @@ -1249,6 +1314,7 @@ gfxpoly_t* gfxpoly_process(gfxpoly_t*poly1, gfxpoly_t*poly2, windrule_t*windrule event_t*e = queue_get(&status.queue); while(e) { + assert(e->s1->fs_orig); status.y = e->p.y; #ifdef CHECKS assert(status.y>=lasty); @@ -1300,7 +1366,18 @@ gfxpoly_t* gfxpoly_process(gfxpoly_t*poly1, gfxpoly_t*poly2, windrule_t*windrule p->gridsize = poly1->gridsize; p->strokes = status.strokes; - add_horizontals(p, &windrule_evenodd, context); // output is always even/odd +#ifdef CHECKS + /* we only add segments with non-empty edgestyles to strokes in + recalculate_windings, but better safe than sorry */ + gfxpolystroke_t*stroke = p->strokes; + while(stroke) { + assert(stroke->fs); + stroke = stroke->next; + } +#endif + + //add_horizontals(p, &windrule_evenodd, context); // output is always even/odd + add_horizontals(p, windrule, context); return p; } diff --git a/lib/gfxpoly/poly.h b/lib/gfxpoly/poly.h index 68eec9b..625d632 100644 --- a/lib/gfxpoly/poly.h +++ b/lib/gfxpoly/poly.h @@ -4,15 +4,15 @@ #include #include "../q.h" #include "../types.h" +#include "wind.h" //#define DEBUG -//#define CHECKS +#define CHECKS /* features */ #define SPLAY #define DONT_REMEMBER_CROSSINGS -typedef enum {DIR_UP, DIR_DOWN, DIR_UNKNOWN} segment_dir_t; typedef enum {EVENT_CROSS, EVENT_END, EVENT_START, EVENT_HORIZONTAL} eventtype_t; typedef enum {SLOPE_POSITIVE, SLOPE_NEGATIVE} slope_t; @@ -23,37 +23,14 @@ typedef struct _point { } point_t; type_t point_type; -typedef struct _fillstyle { - void*internal; -} fillstyle_t; - -typedef struct _windstate -{ - char is_filled; - int wind_nr; -} windstate_t; - -/* TODO: maybe we should merge windcontext and windrule */ -typedef struct _windcontext -{ - int num_polygons; -} windcontext_t; - -typedef struct _windrule -{ - windstate_t (*start)(windcontext_t* num_polygons); - windstate_t (*add)(windcontext_t*context, windstate_t left, fillstyle_t*edge, segment_dir_t dir, int polygon_nr); - fillstyle_t* (*diff)(windstate_t*left, windstate_t*right); -} windrule_t; - -#define SEGNR(s) ((s)?(s)->nr:-1) +#define SEGNR(s) ((int)((s)?(s)->nr:-1)) typedef struct _gfxpolystroke { segment_dir_t dir; + edgestyle_t*fs; int points_size; int num_points; point_t*points; - fillstyle_t*fs; struct _gfxpolystroke*next; } gfxpolystroke_t; typedef struct _gfxpoly { @@ -69,8 +46,8 @@ typedef struct _segment { int32_t minx, maxx; segment_dir_t dir; - fillstyle_t*fs; - fillstyle_t*fs_out; + edgestyle_t*fs_orig; + edgestyle_t*fs_out; #ifdef CHECKS char fs_out_ok; #endif diff --git a/lib/gfxpoly/renderpoly.c b/lib/gfxpoly/renderpoly.c index 240859d..9594bd2 100644 --- a/lib/gfxpoly/renderpoly.c +++ b/lib/gfxpoly/renderpoly.c @@ -7,7 +7,7 @@ typedef struct _renderpoint { double x; segment_dir_t dir; - fillstyle_t*fs; + edgestyle_t*fs; int polygon_nr; } renderpoint_t; @@ -27,7 +27,7 @@ typedef struct _renderbuf renderline_t*lines; } renderbuf_t; -static inline void add_pixel(renderbuf_t*buf, double x, int y, segment_dir_t dir, fillstyle_t*fs, int polygon_nr) +static inline void add_pixel(renderbuf_t*buf, double x, int y, segment_dir_t dir, edgestyle_t*fs, int polygon_nr) { renderpoint_t p; p.x = x; @@ -48,7 +48,7 @@ static inline void add_pixel(renderbuf_t*buf, double x, int y, segment_dir_t dir l->num++; } #define CUT 0.5 -static void add_line(renderbuf_t*buf, double x1, double y1, double x2, double y2, fillstyle_t*fs, int polygon_nr) +static void add_line(renderbuf_t*buf, double x1, double y1, double x2, double y2, edgestyle_t*fs, int polygon_nr) { x1 *= buf->zoom; y1 *= buf->zoom; @@ -175,7 +175,7 @@ unsigned char* render_polygon(gfxpoly_t*polygon, intbbox_t*bbox, double zoom, wi } if(fill.is_filled && lastx!=buf->width) { /* we're bleeding, fill over padding, too. */ - fprintf(stderr, "Polygon %08x is bleeding in line %d\n", (int)polygon, y); + fprintf(stderr, "Polygon %p is bleeding in line %d\n", polygon, y); fill_bitwise(line, lastx, width8*8); assert(line[width8-1]&0x01); bleeding = 1; diff --git a/lib/gfxpoly/test.c b/lib/gfxpoly/test.c index b5c192a..26ebd1b 100644 --- a/lib/gfxpoly/test.c +++ b/lib/gfxpoly/test.c @@ -180,7 +180,7 @@ int test0(int argn, char*argv[]) double ua=M_PI/4; matrix.m00=cos(ua);matrix.m10=sin(ua); matrix.m01=-sin(ua);matrix.m11=cos(ua); - //gfxline_transform(box1, &matrix); + gfxline_transform(box1, &matrix); //gfxline_t*b = 0; //b = gfxline_append(b, box1); @@ -192,9 +192,13 @@ int test0(int argn, char*argv[]) gfxline_free(box1); gfxline_free(box2); + + //gfxpoly_t*poly3 = gfxpoly_process(poly1, poly2, &windrule_intersect, &twopolygons); gfxpoly_t*poly3 = gfxpoly_process(poly1, poly2, &windrule_intersect, &twopolygons); gfxpoly_dump(poly3); + gfxline_t*line = gfxline_from_gfxpoly(poly3); + gfxline_dump(line, stdout, ""); gfxline_free(line); gfxpoly_destroy(poly1); @@ -594,6 +598,7 @@ finish: 0, internal: 0 }; +#if 0 void test5(int argn, char*argv[]) { gfxsource_t*driver = gfxsource_pdf_create(); @@ -629,6 +634,7 @@ void test5(int argn, char*argv[]) closedir(_dir); driver->destroy(driver); } +#endif int main(int argn, char*argv[]) { diff --git a/lib/gfxpoly/wind.c b/lib/gfxpoly/wind.c index db92905..f0eb110 100644 --- a/lib/gfxpoly/wind.c +++ b/lib/gfxpoly/wind.c @@ -1,6 +1,6 @@ -#include "wind.h" +#include "poly.h" -fillstyle_t fillstyle_default; +edgestyle_t edgestyle_default; windstate_t windstate_nonfilled = { is_filled: 0, @@ -13,17 +13,18 @@ windstate_t evenodd_start(windcontext_t*context) { return windstate_nonfilled; } -windstate_t evenodd_add(windcontext_t*context, windstate_t left, fillstyle_t*edge, segment_dir_t dir, int master) +windstate_t evenodd_add(windcontext_t*context, windstate_t left, edgestyle_t*edge, segment_dir_t dir, int master) { + assert(edge); left.is_filled ^= 1; return left; } -fillstyle_t* evenodd_diff(windstate_t*left, windstate_t*right) +edgestyle_t* evenodd_diff(windstate_t*left, windstate_t*right) { if(left->is_filled==right->is_filled) return 0; else - return &fillstyle_default; + return &edgestyle_default; } windrule_t windrule_evenodd = { @@ -34,29 +35,36 @@ windrule_t windrule_evenodd = { // -------------------- circular ---------------------- +edgestyle_t edgestyle_down; +edgestyle_t edgestyle_up; + windstate_t circular_start(windcontext_t*context) { return windstate_nonfilled; } -windstate_t circular_add(windcontext_t*context, windstate_t left, fillstyle_t*edge, segment_dir_t dir, int master) +windstate_t circular_add(windcontext_t*context, windstate_t left, edgestyle_t*edge, segment_dir_t dir, int master) { + assert(edge); /* which one is + and which one - doesn't actually make any difference */ if(dir == DIR_DOWN) - left.wind_nr++; + left.wind_nr++; else - left.wind_nr--; + left.wind_nr--; left.is_filled = left.wind_nr != 0; return left; } -fillstyle_t* circular_diff(windstate_t*left, windstate_t*right) +edgestyle_t* circular_diff(windstate_t*left, windstate_t*right) { - if(left->is_filled==right->is_filled) + if(left->is_filled==right->is_filled) { return 0; - else - return &fillstyle_default; + } else if(left->is_filled) { + return &edgestyle_down; + } else {//right->is_filled + return &edgestyle_up; + } } windrule_t windrule_circular = { @@ -72,7 +80,7 @@ windstate_t intersect_start(windcontext_t*context) return windstate_nonfilled; } -windstate_t intersect_add(windcontext_t*context, windstate_t left, fillstyle_t*edge, segment_dir_t dir, int master) +windstate_t intersect_add(windcontext_t*context, windstate_t left, edgestyle_t*edge, segment_dir_t dir, int master) { assert(master < context->num_polygons); @@ -81,12 +89,12 @@ windstate_t intersect_add(windcontext_t*context, windstate_t left, fillstyle_t*e return left; } -fillstyle_t* intersect_diff(windstate_t*left, windstate_t*right) +edgestyle_t* intersect_diff(windstate_t*left, windstate_t*right) { if(left->is_filled==right->is_filled) return 0; else - return &fillstyle_default; + return &edgestyle_default; } windrule_t windrule_intersect = { @@ -102,7 +110,7 @@ windstate_t union_start(windcontext_t*context) return windstate_nonfilled; } -windstate_t union_add(windcontext_t*context, windstate_t left, fillstyle_t*edge, segment_dir_t dir, int master) +windstate_t union_add(windcontext_t*context, windstate_t left, edgestyle_t*edge, segment_dir_t dir, int master) { assert(masteris_filled==right->is_filled) return 0; else - return &fillstyle_default; + return &edgestyle_default; } windrule_t windrule_union = { diff --git a/lib/gfxpoly/wind.h b/lib/gfxpoly/wind.h index 1dae74e..374b974 100644 --- a/lib/gfxpoly/wind.h +++ b/lib/gfxpoly/wind.h @@ -1,7 +1,35 @@ #ifndef __wind_h__ #define __wind_h__ -#include "poly.h" +/* Every segment has an original direction, which is the direction + the segment had in the input data. + as our scanline moves from minimum y to maximum y, "DOWN" means + the the (original) segment's y2 is larger than its y1 */ +typedef enum {DIR_UP, DIR_DOWN, DIR_UNKNOWN} segment_dir_t; + +typedef struct _edgestyle { + void*internal; +} edgestyle_t; + +extern edgestyle_t edgestyle_default; + +typedef struct _windstate +{ + char is_filled; + int wind_nr; +} windstate_t; + +typedef struct _windcontext +{ + int num_polygons; +} windcontext_t; + +typedef struct _windrule +{ + windstate_t (*start)(windcontext_t* num_polygons); + windstate_t (*add)(windcontext_t*context, windstate_t left, edgestyle_t*edge, segment_dir_t dir, int polygon_nr); + edgestyle_t* (*diff)(windstate_t*left, windstate_t*right); +} windrule_t; extern windrule_t windrule_evenodd; extern windrule_t windrule_circular;