+ /*
+ |..| |...........| | |
+ |..| |...........| | |
+ |..+ + +..| +--+ +--+
+ |...........| |..| | |
+ |...........| |..| | |
+ */
+
+#ifdef DEBUG
+ fprintf(stderr, "========================================================================\n");
+#endif
+ heap_t* queue = heap_new(sizeof(event_t), compare_events_simple);
+ gfxpoly_enqueue(poly, queue, 0);
+
+ actlist_t* actlist = actlist_new();
+
+ event_t*e = heap_chopmax(queue);
+ int newstrokes_size = 4;
+ int num_newstrokes = 0;
+ gfxpolystroke_t*newstrokes = malloc(sizeof(gfxpolystroke_t)*newstrokes_size);
+ while(e) {
+ int32_t y = e->p.y;
+ int32_t x = 0;
+ char fill = 0;
+#ifdef DEBUG
+ fprintf(stderr, "----------------------------------- %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);
+
+ if(num_newstrokes == newstrokes_size) {
+ newstrokes_size = (newstrokes_size)<<1;
+ newstrokes = rfx_realloc(newstrokes, sizeof(gfxpolystroke_t)*newstrokes_size);
+ }
+ gfxpolystroke_t*stroke = &newstrokes[num_newstrokes++];
+ 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;
+ e.type = EVENT_END;
+ e.p = s->b;
+ e.s1 = s;
+ e.s2 = 0;
+ heap_put(queue, &e);
+ left = actlist_left(actlist, s);
+ break;
+ }
+ case EVENT_END: {
+ left = actlist_left(actlist, s);
+ actlist_delete(actlist, s);
+ advance_stroke(queue, 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);
+
+ free(e);
+ e = heap_chopmax(queue);
+ } while(e && y == e->p.y);
+
+ assert(!fill); // check that polygon is not bleeding
+ }
+
+ poly->strokes = rfx_realloc(poly->strokes, sizeof(gfxpolystroke_t)*(num_newstrokes+poly->num_strokes));
+ memcpy(&poly->strokes[poly->num_strokes], newstrokes, sizeof(gfxpolystroke_t)*num_newstrokes);
+ poly->num_strokes += num_newstrokes;
+ free(newstrokes);
+
+ actlist_destroy(actlist);
+ heap_destroy(queue);
+}
+
+gfxpoly_t* gfxpoly_process(gfxcompactpoly_t*poly, windrule_t*windrule, windcontext_t*context)
+{
+ current_polygon = poly;