X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fgfxpoly%2Fpoly.c;h=ca81be1d57e54d06b0f2712b174c2a4634736e0f;hb=refs%2Ftags%2Fpolyok;hp=7036a61b59ad0dd5192d1f81c88dc48ae7979232;hpb=f7e9e8a9616f1ecb26776369fda6807cf8821a68;p=swftools.git diff --git a/lib/gfxpoly/poly.c b/lib/gfxpoly/poly.c index 7036a61..ca81be1 100644 --- a/lib/gfxpoly/poly.c +++ b/lib/gfxpoly/poly.c @@ -13,7 +13,10 @@ static gfxpoly_t*current_polygon = 0; void gfxpoly_fail(char*expr, char*file, int line, const char*function) { - if(!current_polygon) {fprintf(stderr, "error outside polygon\n");exit(1);} + if(!current_polygon) { + fprintf(stderr, "assert(%s) failed in %s in line %d: %s\n", expr, file, line, function); + exit(1); + } void*md5 = init_md5(); @@ -110,15 +113,21 @@ static int compare_events(const void*_a,const void*_b) /* we need to schedule end after intersect (so that a segment about to end has a chance to tear up a few other segs first) and start events after end (in order not to confuse the intersection check, which - assumes there's an actual y overlap between active segments)). + assumes there's an actual y overlap between active segments, and + because ending segments in the active list make it difficult to insert + starting segments at the right position)). Horizontal lines come last, because the only purpose they have is to create snapping coordinates for the segments (still) existing in this scanline. */ d = b->type - a->type; if(d) return d; - d = b->p.x - a->p.x; - return d; + return 0; + + /* I don't see any reason why we would need to order by x- at least as long + as we do horizontal lines in a seperate pass */ + //d = b->p.x - a->p.x; + //return d; } gfxpoly_t* gfxpoly_new(double gridsize) @@ -186,6 +195,7 @@ void gfxpoly_dump(gfxpoly_t*poly) { edge_t* s = poly->edges; double g = poly->gridsize; + fprintf(stderr, "polyon %08x (gridsize: %f)\n", poly, poly->gridsize); while(s) { fprintf(stderr, "(%f,%f) -> (%f,%f)\n", s->a.x*g, s->a.y*g, s->b.x*g, s->b.y*g); s = s->next; @@ -358,7 +368,6 @@ static void schedule_crossing(status_t*status, segment_t*s1, segment_t*s2) /* the code that's required (and the checks you can perform) before it can be said with 100% certainty that we indeed have a valid crossing amazes me every time. -mk */ - #ifdef CHECKS assert(s1!=s2); assert(s1->right == s2); @@ -596,7 +605,6 @@ static void segrange_test_segment_min(segrange_t*range, segment_t*seg, int32_t y /* we need to calculate the xpos anew (and can't use start coordinate or intersection coordinate), because we need the xpos exactly at the end of this scanline. - TODO: might be faster to use XPOS_COMPARE here (see also _max) */ double x = XPOS(seg, y); if(!range->segmin || xxmin) { @@ -652,7 +660,7 @@ static void add_points_to_positively_sloped_segments(status_t*status, int32_t y, //break; } } - seg = actlist_right(status->actlist, seg); + seg = seg->right; } } segrange_test_segment_min(range, first, y); @@ -691,7 +699,7 @@ static void add_points_to_negatively_sloped_segments(status_t*status, int32_t y, //break; } } - seg = actlist_left(status->actlist, seg); + seg = seg->left; } } segrange_test_segment_min(range, last, y); @@ -721,6 +729,7 @@ static void add_points_to_ending_segments(status_t*status, int32_t y) if(status->xrow->num == 1) { // shortcut + assert(seg->b.x == status->xrow->x[0]); point_t p = {status->xrow->x[0], y}; insert_point_into_segment(status, seg, p); } else { @@ -798,7 +807,7 @@ static void recalculate_windings(status_t*status, segrange_t*range) #endif if(end) - end = actlist_right(status->actlist, end); + end = end->right; while(s!=end) { #ifndef CHECKS if(s->changed) @@ -888,12 +897,13 @@ static void event_apply(status_t*status, event_t*e) assert(!dict_contains(status->intersecting_segs, s)); assert(!dict_contains(status->segs_with_point, s)); #endif - segment_t*left = actlist_left(status->actlist, s); - segment_t*right = actlist_right(status->actlist, s); + segment_t*left = s->left; + segment_t*right = s->right; actlist_delete(status->actlist, s); if(left && right) schedule_crossing(status, left, right); + /* schedule segment for xrow handling */ s->left = 0; s->right = status->ending_segments; status->ending_segments = s; break; @@ -906,8 +916,8 @@ static void event_apply(status_t*status, event_t*e) segment_t*s = e->s1; assert(e->p.x == s->a.x && e->p.y == s->a.y); actlist_insert(status->actlist, s->a, s->b, s); - segment_t*left = actlist_left(status->actlist, s); - segment_t*right = actlist_right(status->actlist, s); + segment_t*left = s->left; + segment_t*right = s->right; if(left) schedule_crossing(status, left, s); if(right) @@ -920,10 +930,11 @@ static void event_apply(status_t*status, event_t*e) #ifdef DEBUG event_dump(e); #endif - if(actlist_right(status->actlist, e->s1) == e->s2 && - actlist_left(status->actlist, e->s2) == e->s1) { + if(e->s1->right == e->s2) { + assert(e->s2->left == e->s1); exchange_two(status, e); } else { + assert(e->s2->left != e->s1); #ifdef DEBUG fprintf(stderr, "Ignore this crossing ([%d] not next to [%d])\n", e->s1->nr, e->s2->nr); #endif @@ -999,18 +1010,18 @@ static void add_horizontals(gfxpoly_t*poly, windrule_t*windrule, windcontext_t*c assert(xp.x); edge_t*l= malloc(sizeof(edge_t)); l->a.y = l->b.y = y; - /* TODO: strictly speaking we need to draw from low x to high x so that left/right fillstyles add up - (because the horizontal line's fill style controls the area *below* the line) + /* we draw from low x to high x so that left/right fillstyles add up + (because the horizontal line's fill style controls the area *below* the line) */ - l->a.x = x; - l->b.x = e->p.x; + l->a.x = e->p.x; + l->b.x = x; l->next = poly->edges; poly->edges = l; #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 */ - segment_t* start = actlist_find(actlist, l->a, l->a); - segment_t* s = actlist_find(actlist, l->b, l->b); + segment_t* start = actlist_find(actlist, l->b, l->b); + segment_t* s = actlist_find(actlist, l->a, l->a); while(s!=start) { assert(s->a.y == y || s->b.y == y); s = s->left; @@ -1020,7 +1031,6 @@ static void add_horizontals(gfxpoly_t*poly, windrule_t*windrule, windcontext_t*c segment_t*left = 0; segment_t*s = e->s1; - windstate_t before,after; switch(e->type) { case EVENT_START: { assert(e->p.x == s->a.x && e->p.y == s->a.y); @@ -1032,17 +1042,11 @@ static void add_horizontals(gfxpoly_t*poly, windrule_t*windrule, windcontext_t*c e.s2 = 0; heap_put(queue, &e); left = actlist_left(actlist, s); - - before = left?left->wind:windrule->start(context); - after = s->wind = windrule->add(context, before, s->fs, s->dir, s->polygon_nr); break; } case EVENT_END: { left = actlist_left(actlist, s); actlist_delete(actlist, s); - - before = s->wind; - after = left?left->wind:windrule->start(context); break; } default: assert(0); @@ -1051,12 +1055,11 @@ 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 DEBUG - fprintf(stderr, "%d) event=%s[%d] left:[%d] x:%d before:%d after:%d\n", + fprintf(stderr, "%d) event=%s[%d] left:[%d] x:%d\n", y, e->type==EVENT_START?"start":"end", s->nr, left?left->nr:-1, - x, - before.is_filled, after.is_filled); + x); #endif if(e->type == EVENT_END)