-static void add_horizontals(gfxpoly_t*poly, windrule_t*windrule, windcontext_t*context)
-{
- /*
- |..| |...........| | |
- |..| |...........| | |
- |..+ + +..| +--+ +--+
- |...........| |..| | |
- |...........| |..| | |
- */
-
-#ifdef DEBUG
- fprintf(stderr, "========================================================================\n");
-#endif
- hqueue_t hqueue;
- hqueue_init(&hqueue);
- gfxpoly_enqueue(poly, 0, &hqueue, 0);
-
- actlist_t* actlist = actlist_new();
-
- event_t*e = hqueue_get(&hqueue);
- while(e) {
- int32_t y = e->p.y;
- int32_t x = 0;
-#ifdef DEBUG
- fprintf(stderr, "HORIZONTALS ----------------------------------- %f\n", y);
- actlist_dump(actlist, y-1, 1.0);
-#endif
-#ifdef CHECKS
- actlist_verify(actlist, y-1);
-#endif
- edgestyle_t*fill = 0;
- int wind = 0;
-
- do {
- assert(e->s1->fs);
- if(fill && x != e->p.x) {
- assert(abs(wind)==1);
- assert(x<e->p.x);
-
- gfxpolystroke_t*stroke = rfx_calloc(sizeof(gfxpolystroke_t));
- stroke->next = poly->strokes;
- poly->strokes = stroke;
-
- stroke->num_points = 2;
- stroke->points = malloc(sizeof(point_t)*2);
-
- if(wind>0) {
- stroke->dir = DIR_DOWN;
- } else {
- stroke->dir = DIR_UP;
- }
-#ifdef DEBUG
- fprintf(stderr, "%d) draw horizontal line from %d to %d (dir=%s)\n", y, x, e->p.x, stroke->dir==DIR_UP?"up":"down");
-#endif
-
- stroke->fs = fill;
- point_t a,b;
- a.y = b.y = y;
- a.x = x;
- b.x = e->p.x;
- stroke->points[0] = a;
- stroke->points[1] = b;
-#ifdef CHECKS
- /* the output should always be intersection free polygons, so check this horizontal
- line isn't puncturing any segments in the active list */
- segment_t* start = actlist_find(actlist, a, a);
- segment_t* s = actlist_find(actlist, b, b);
- while(s!=start) {
- assert(s->a.y == y || s->b.y == y);
- s = s->left;
- }
-#endif
- }
-
- segment_t*s = e->s1;
-
- segment_t*left = 0;
- switch(e->type) {
- case EVENT_START: {
- assert(e->p.x == s->a.x && e->p.y == s->a.y);
- actlist_insert(actlist, s->a, s->b, s);
- event_t* e = event_new();
- e->type = EVENT_END;
- e->p = s->b;
- e->s1 = s;
- e->s2 = 0;
- hqueue_put(&hqueue, e);
- left = actlist_left(actlist, s);
- wind += e->s1->dir==DIR_DOWN?-1:1;
- break;
- }
- case EVENT_END: {
- left = actlist_left(actlist, s);
- actlist_delete(actlist, s);
- advance_stroke(0, &hqueue, s->stroke, s->polygon_nr, s->stroke_pos);
- wind += e->s1->dir==DIR_DOWN?1:-1;
- break;
- }
- default: assert(0);
- }
-
- x = e->p.x;
-
- fill = fill?0:&edgestyle_default;
-#if 0
- if(windrule==&windrule_evenodd) {
- 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);
- 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);
- }
- }
- assert(!!fill == !!fill2);
- }
-#endif
-
-#ifdef DEBUG
- fprintf(stderr, "%d) event=%s[%d] left:[%d] x:%d dir:%s\n",
- y, e->type==EVENT_START?"start":"end",
- s->nr,
- left?left->nr:-1,
- x, s->dir==DIR_UP?"up":"down");
-#endif
-
- if(e->type == EVENT_END)
- segment_destroy(s);
-
- event_free(e);
- e = hqueue_get(&hqueue);
- } while(e && y == e->p.y);
-
-#ifdef CHECKS
- edgestyle_t*bleeding = fill;
- assert(!bleeding);
- segment_t*s = actlist_leftmost(actlist);
- int dir = 0;
- while(s) {
- dir += s->dir==DIR_UP?-1:1;
- s = actlist_right(actlist, s);
- }
- assert(!dir);
-#endif
- }
-
- actlist_destroy(actlist);
- hqueue_destroy(&hqueue);
-}
-