+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;
+ char fill = 0;
+#ifdef DEBUG
+ fprintf(stderr, "HORIZONTALS ----------------------------------- %d\n", y);
+ actlist_dump(actlist, y-1);
+#endif
+#ifdef CHECKS
+ actlist_verify(actlist, y-1);
+#endif
+ do {
+ if(fill && x != e->p.x) {
+#ifdef DEBUG
+ fprintf(stderr, "%d) draw horizontal line from %d to %d\n", y, x, e->p.x);
+#endif
+ 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);
+ stroke->dir = DIR_UP; // FIXME
+ stroke->fs = 0;
+ point_t a,b;
+ a.y = b.y = y;
+ /* 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)
+ */
+ a.x = e->p.x;
+ b.x = 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 hacking through 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) {
+ assert(s->a.y == y || s->b.y == y);
+ s = s->left;
+ }
+#endif
+ }
+ 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);
+ 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);
+ 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);
+ break;
+ }
+ default: assert(0);
+ }
+
+ x = e->p.x;
+ fill ^= 1;//(before.is_filled != after.is_filled);
+#ifdef DEBUG
+ 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);
+#endif
+
+ if(e->type == EVENT_END)
+ segment_destroy(s);
+
+ event_free(e);
+ e = hqueue_get(&hqueue);
+ } while(e && y == e->p.y);
+
+#ifdef CHECKS
+ char bleeding = fill;
+ assert(!bleeding);
+#endif
+ }
+
+ actlist_destroy(actlist);
+ hqueue_destroy(&hqueue);
+}
+
+gfxpoly_t* gfxpoly_process(gfxpoly_t*poly1, gfxpoly_t*poly2, windrule_t*windrule, windcontext_t*context)