fixed compiler warnings
[swftools.git] / lib / gfxpoly / poly.c
index 2b55041..53b45e2 100644 (file)
@@ -3,7 +3,6 @@
 #include <math.h>
 #include "../mem.h"
 #include "../types.h"
-#include "../q.h"
 #include "../MD5.h"
 #include "poly.h"
 #include "active.h"
@@ -20,7 +19,7 @@ void gfxpoly_fail(char*expr, char*file, int line, const char*function)
        exit(1);
     }
 
-    void*md5 = init_md5();
+    void*md5 = initialize_md5();
    
     int s,t;
     gfxpolystroke_t*stroke = current_polygon->strokes;
@@ -69,7 +68,7 @@ static void point_free(void*o)
     p->y = 0;
     free(p);
 }
-static type_t point_type = {
+type_t point_type = {
     equals: point_equals,
     hash: point_hash,
     dup: point_dup,
@@ -136,7 +135,8 @@ typedef struct _status {
     windrule_t*windrule;
     windcontext_t*context;
     segment_t*ending_segments;
-    polywriter_t writer;
+
+    gfxpolystroke_t*strokes;
 #ifdef CHECKS
     dict_t*seen_crossings; //list of crossing we saw so far
     dict_t*intersecting_segs; //list of segments intersecting in this scanline
@@ -145,6 +145,15 @@ typedef struct _status {
 } status_t;
 
 
+int gfxpoly_num_segments(gfxpoly_t*poly)
+{
+    gfxpolystroke_t*stroke = poly->strokes;
+    int count = 0;
+    for(;stroke;stroke=stroke->next) {
+       count++;
+    }
+    return count;
+}
 int gfxpoly_size(gfxpoly_t*poly)
 {
     int s,t;
@@ -158,6 +167,7 @@ int gfxpoly_size(gfxpoly_t*poly)
 
 char gfxpoly_check(gfxpoly_t*poly)
 {
+    current_polygon = poly;
     dict_t*d = dict_new2(&point_type);
     int s,t;
     gfxpolystroke_t*stroke = poly->strokes;
@@ -250,8 +260,8 @@ static void event_dump(event_t*e)
     }
 }
 
-static inline max32(int32_t v1, int32_t v2) {return v1>v2?v1:v2;}
-static inline min32(int32_t v1, int32_t v2) {return v1<v2?v1:v2;}
+static inline int32_t max32(int32_t v1, int32_t v2) {return v1>v2?v1:v2;}
+static inline int32_t min32(int32_t v1, int32_t v2) {return v1<v2?v1:v2;}
 
 static void segment_dump(segment_t*s)
 {
@@ -295,6 +305,11 @@ static void segment_init(segment_t*s, int32_t x1, int32_t y1, int32_t x2, int32_
     s->nr = segment_count++;
 
 #ifdef CHECKS
+    /* notice: on some systems (with some compilers), for the line 
+       (1073741823,-1073741824)->(1073741823,1073741823)
+       we get LINE_EQ(s->a, s) == 1. 
+       That's why we now clamp to 26 bit.
+    */
     assert(LINE_EQ(s->a, s) == 0);
     assert(LINE_EQ(s->b, s) == 0);
 
@@ -370,10 +385,6 @@ static void advance_stroke(queue_t*queue, hqueue_t*hqueue, gfxpolystroke_t*strok
        }
     }
     if(s) {
-#ifdef DEBUG
-       fprintf(stderr, "attaching contingency of stroke %08x to segment [%d] %s\n",
-               stroke, s, s->delta.y?"":"(horizontal)");
-#endif
        s->stroke = stroke;
        s->stroke_pos = pos;
     }
@@ -647,13 +658,38 @@ 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;
+
         // omit horizontal lines
         if(s->pos.y != p.y) {
             point_t a = s->pos;
             point_t b = p;
             assert(a.y != b.y);
-           status->writer.moveto(&status->writer, a.x, a.y);
-           status->writer.lineto(&status->writer, b.x, b.y);
+
+            gfxpolystroke_t*stroke = status->strokes;
+           while(stroke) {
+               point_t p = stroke->points[stroke->num_points-1];
+               if(p.x == a.x && p.y == a.y && stroke->fs == fs)
+                   break;
+               stroke = stroke->next;
+           }
+           if(!stroke) {
+               stroke = rfx_calloc(sizeof(gfxpolystroke_t));
+               stroke->dir = DIR_DOWN;
+               stroke->fs = fs;
+               stroke->next = status->strokes;
+               status->strokes = stroke;
+               stroke->points_size = 2;
+               stroke->points = rfx_calloc(sizeof(point_t)*stroke->points_size);
+               stroke->points[0] = a;
+               stroke->num_points = 1;
+           } else if(stroke->num_points == stroke->points_size) {
+               stroke->points_size *= 2;
+               stroke->points = rfx_realloc(stroke->points, sizeof(point_t)*stroke->points_size);
+           }
+           stroke->points[stroke->num_points++] = b;
         }
     } else {
 #ifdef DEBUG
@@ -909,7 +945,8 @@ static void recalculate_windings(status_t*status, segrange_t*range)
             s->fs_out = status->windrule->diff(&wind, &s->wind);
 
 #ifdef DEBUG
-            fprintf(stderr, "[%d] %s/%d/%s/%s %s\n", s->nr, s->dir==DIR_UP?"up":"down", s->wind.wind_nr, s->wind.is_filled?"fill":"nofill", s->fs_out?"draw":"omit",
+            fprintf(stderr, "[%d] dir=%s wind=%d wind.filled=%s fs_old/new=%s/%s %s\n", s->nr, s->dir==DIR_UP?"up":"down", s->wind.wind_nr, s->wind.is_filled?"fill":"nofill", 
+                   fs_old?"draw":"omit", s->fs_out?"draw":"omit",
                    fs_old!=s->fs_out?"CHANGED":"");
 #endif
             assert(!(!s->changed && fs_old!=s->fs_out));
@@ -1176,27 +1213,32 @@ static void add_horizontals(gfxpoly_t*poly, windrule_t*windrule, windcontext_t*c
             e = hqueue_get(&hqueue);
         } while(e && y == e->p.y);
 
-        assert(!fill); // check that polygon is not bleeding
+#ifdef CHECKS
+       char bleeding = fill;
+        assert(!bleeding);
+#endif
     }
 
     actlist_destroy(actlist);
     hqueue_destroy(&hqueue);
 }
 
-gfxpoly_t* gfxpoly_process(gfxpoly_t*poly, windrule_t*windrule, windcontext_t*context)
+gfxpoly_t* gfxpoly_process(gfxpoly_t*poly1, gfxpoly_t*poly2, windrule_t*windrule, windcontext_t*context)
 {
-    current_polygon = poly;
+    current_polygon = poly1;
 
     status_t status;
     memset(&status, 0, sizeof(status_t));
     queue_init(&status.queue);
-    gfxpoly_enqueue(poly, &status.queue, 0, /*polygon nr*/0);
+    gfxpoly_enqueue(poly1, &status.queue, 0, /*polygon nr*/0);
+    if(poly2) {
+       assert(poly1->gridsize == poly2->gridsize);
+       gfxpoly_enqueue(poly2, &status.queue, 0, /*polygon nr*/1);
+    }
 
     status.windrule = windrule;
     status.context = context;
     status.actlist = actlist_new();
-    gfxpolywriter_init(&status.writer);
-    status.writer.setgridsize(&status.writer, poly->gridsize);
 
 #ifdef CHECKS
     status.seen_crossings = dict_new2(&point_type);
@@ -1254,8 +1296,20 @@ gfxpoly_t* gfxpoly_process(gfxpoly_t*poly, windrule_t*windrule, windcontext_t*co
     queue_destroy(&status.queue);
     xrow_destroy(status.xrow);
 
-    gfxpoly_t*p = (gfxpoly_t*)status.writer.finish(&status.writer);
+    gfxpoly_t*p = (gfxpoly_t*)malloc(sizeof(gfxpoly_t));
+    p->gridsize = poly1->gridsize;
+    p->strokes = status.strokes;
 
     add_horizontals(p, &windrule_evenodd, context); // output is always even/odd
     return p;
 }
+
+static windcontext_t twopolygons = {2};
+gfxpoly_t* gfxpoly_intersect(gfxpoly_t*p1, gfxpoly_t*p2)
+{
+    return gfxpoly_process(p1, p2, &windrule_intersect, &twopolygons);
+}
+gfxpoly_t* gfxpoly_union(gfxpoly_t*p1, gfxpoly_t*p2)
+{
+    return gfxpoly_process(p1, p2, &windrule_union, &twopolygons);
+}