more fiddling with edgestyles
[swftools.git] / lib / gfxpoly.c
index acf2de3..a687e63 100644 (file)
@@ -233,6 +233,9 @@ unsigned char* render_svp(ArtSVP*svp, intbbox_t*bbox, double zoom, ArtWindRule r
     return image;
 }
 
+#define MAX_WIDTH 8192
+#define MAX_HEIGHT 4096
+
 intbbox_t get_svp_bbox(ArtSVP*svp, double zoom)
 {
     int t;
@@ -256,9 +259,23 @@ intbbox_t get_svp_bbox(ArtSVP*svp, double zoom)
             if(x1 < b.xmin) b.xmin = x1;
             if(y1 < b.ymin) b.ymin = y1;
             if(x2 > b.xmax) b.xmax = x2;
-            if(y2 > b.xmax) b.ymax = y2;
+            if(y2 > b.ymax) b.ymax = y2;
         }
     }
+    if(b.xmax > (int)(MAX_WIDTH*zoom))
+       b.xmax = (int)(MAX_WIDTH*zoom);
+    if(b.ymax > (int)(MAX_HEIGHT*zoom))
+       b.ymax = (int)(MAX_HEIGHT*zoom);
+    if(b.xmin < -(int)(MAX_WIDTH*zoom))
+       b.xmin = -(int)(MAX_WIDTH*zoom);
+    if(b.ymin < -(int)(MAX_HEIGHT*zoom))
+       b.ymin = -(int)(MAX_HEIGHT*zoom);
+    
+    if(b.xmin > b.xmax) 
+       b.xmin = b.xmax;
+    if(b.ymin > b.ymax) 
+       b.ymin = b.ymax;
+
     b.width = b.xmax - b.xmin;
     b.height = b.ymax - b.ymin;
     return b;
@@ -279,51 +296,39 @@ intbbox_t get_svp_bbox(ArtSVP*svp, double zoom)
 #define B00000010 0x02
 #define B00000001 0x01
 
-int compare_bitmaps(intbbox_t*bbox, unsigned char*data1, unsigned char*data2)
+static int compare_bitmaps(intbbox_t*bbox, unsigned char*data1, unsigned char*data2)
 {
-    int similar = 0;
+    if(!data1 || !data2) 
+        return 0;
     int x,y;
     int height = bbox->height;
     int width = bbox->width;
     int width8 = (width+7) >> 3;
     unsigned char*l1 = &data1[width8];
     unsigned char*l2 = &data2[width8];
-    int fail = 0;
     for(y=1;y<height-1;y++) {
         for(x=0;x<width8;x++) {
             unsigned a = l1[x-width8] & l1[x] & l1[x+width8];
             unsigned b = l2[x-width8] & l2[x] & l2[x+width8];
-
-            if((a&B11100000) && !(l2[x]&B01000000))
-                fail == 1;
-            if((a&B01110000) && !(l2[x]&B00100000))
-                fail == 1;
-            if((a&B00111000) && !(l2[x]&B00010000))
-                fail == 1;
-            if((a&B00011100) && !(l2[x]&B00001000))
-                fail == 1;
-            if((a&B00001110) && !(l2[x]&B00000100))
-                fail == 1;
-            if((a&B00000111) && !(l2[x]&B00000010))
-                fail == 1;
-
-            if((b&B11100000) && !(l1[x]&B01000000))
-                fail == 1;
-            if((b&B01110000) && !(l1[x]&B00100000))
-                fail == 1;
-            if((b&B00111000) && !(l1[x]&B00010000))
-                fail == 1;
-            if((b&B00011100) && !(l1[x]&B00001000))
-                fail == 1;
-            if((b&B00001110) && !(l1[x]&B00000100))
-                fail == 1;
-            if((b&B00000111) && !(l1[x]&B00000010))
-                fail == 1;
+            
+            if((a&B11100000) && !(l2[x]&B01000000)) return 0;
+            if((a&B01110000) && !(l2[x]&B00100000)) return 0;
+            if((a&B00111000) && !(l2[x]&B00010000)) return 0;
+            if((a&B00011100) && !(l2[x]&B00001000)) return 0;
+            if((a&B00001110) && !(l2[x]&B00000100)) return 0;
+            if((a&B00000111) && !(l2[x]&B00000010)) return 0;
+
+            if((b&B11100000) && !(l1[x]&B01000000)) return 0;
+            if((b&B01110000) && !(l1[x]&B00100000)) return 0;
+            if((b&B00111000) && !(l1[x]&B00010000)) return 0;
+            if((b&B00011100) && !(l1[x]&B00001000)) return 0;
+            if((b&B00001110) && !(l1[x]&B00000100)) return 0;
+            if((b&B00000111) && !(l1[x]&B00000010)) return 0;
         }
         l1 += width8;
         l2 += width8;
     }
-    return !fail;
+    return 1;
 }
 
 
@@ -361,11 +366,13 @@ static ArtVpath* gfxline_to_ArtVpath(gfxline_t*line, char fill)
 
     pos = 0;
     l2 = line;
+    int lastmove=-1;
     while(l2) {
        if(l2->type == gfx_moveTo) {
            vec[pos].code = ART_MOVETO_OPEN;
            vec[pos].x = l2->x;
            vec[pos].y = l2->y;
+            lastmove=pos;
            pos++; 
            assert(pos<=len);
        } else if(l2->type == gfx_lineTo) {
@@ -390,6 +397,16 @@ static ArtVpath* gfxline_to_ArtVpath(gfxline_t*line, char fill)
        }
        x = l2->x;
        y = l2->y;
+       
+        /* let closed line segments start w/ MOVETO instead of MOVETO_OPEN */
+        if(lastmove>=0 && l2->type!=gfx_moveTo && (!l2->next || l2->next->type == gfx_moveTo)) {
+            if(vec[lastmove].x == l2->x &&
+               vec[lastmove].y == l2->y) {
+                assert(vec[lastmove].code == ART_MOVETO_OPEN);
+                vec[lastmove].code = ART_MOVETO;
+            }
+        }
+
        l2 = l2->next;
     }
     vec[pos++].code = ART_END;
@@ -414,7 +431,7 @@ static ArtVpath* gfxline_to_ArtVpath(gfxline_t*line, char fill)
     }
 
     /* Find adjacent identical points. If an ajdacent pair of identical
-       points is found, the second is removed.
+       points is found, the second one is removed.
        So moveto x,y lineto x,y becomes moveto x,y
           lineto x,y lineto x,y becomes lineto x,y
           lineto x,y moveto x,y becomes lineto x,y
@@ -506,7 +523,13 @@ static double find_shear_value(ArtSVP*svp)
         }
         if(!fail) 
             break;
-        v = lrand48() / 2000000000.0;
+#ifdef HAVE_LRAND48
+       v = lrand48() / 2000000000.0;;
+#elif HAVE_RAND
+        v = rand() / 2000000000.0;
+#else
+#error "no lrand48()/rand() implementation found"
+#endif
         tries++;
     }
     return v;
@@ -657,7 +680,7 @@ int check_svp(ArtSVP*svp)
     qsort(seg_start, num_segs, sizeof(svp_segment_part_t*), compare_seg_start);
     qsort(seg_end, num_segs, sizeof(svp_segment_part_t*), compare_seg_end);
 
-    double lasty = y[0]+1;
+    double lasty = num_points?y[0]+1:0;
     int num_active = 0;
     int bleed = 0;
     double bleedy1=0,bleedy2 = 0;
@@ -706,7 +729,6 @@ void write_svp_postscript(const char*filename, ArtSVP*svp)
 {
     if(!svp)
        return;
-    printf("writing %s\n", filename);
     FILE*fi = fopen(filename, "wb");
     int i, j;
     double xmin=0,ymin=0,xmax=0,ymax=0;
@@ -889,7 +911,7 @@ static ArtSVP* gfxfillToSVP(gfxline_t*line, int perturb)
 
 //#ifdef SHEAR
 //    double shear = find_shear_value(svp);
-//    gfxline_t*line =  gfxpoly_to_gfxline((gfxpoly_t*)svp);
+//    gfxline_t*line =  gfxline_from_gfxpoly((gfxpoly_t*)svp);
 //    gfxline_t*l = line;
 //    while(l) {
 //        l->y += l->x*shear;
@@ -906,11 +928,6 @@ static ArtSVP* gfxfillToSVP(gfxline_t*line, int perturb)
 //#endif
 
 
-
-extern const ArtSVP* current_svp;
-extern void art_report_error();
-extern int art_error_in_intersector;
-
 ArtSVP* run_intersector(ArtSVP*svp, ArtWindRule rule)
 {
     ArtSvpWriter * swr = art_svp_writer_rewind_new(rule);
@@ -925,9 +942,9 @@ ArtSVP* run_intersector(ArtSVP*svp, ArtWindRule rule)
        current_svp = result;
        art_report_error(); // might set art_error_in_intersector
     } else {
+        msg("<verbose> Comparing polygon renderings of size %dx%d and %dx%d", bbox.width, bbox.height, bbox.width, bbox.height);
         unsigned char*data1 = render_svp(svp, &bbox, zoom, rule);
         unsigned char*data2 = render_svp(result, &bbox, zoom, ART_WIND_RULE_ODDEVEN);
-        msg("<verbose> Comparing polygon renderings of size %dx%d and %dx%d", bbox.width, bbox.height, bbox.width, bbox.height);
         if(!compare_bitmaps(&bbox, data1, data2)) {
             msg("<verbose> Bad SVP rewinding result- polygons don't match");
             current_svp = result;
@@ -946,7 +963,7 @@ ArtSVP* run_intersector(ArtSVP*svp, ArtWindRule rule)
     return result;
 }
 
-gfxline_t* gfxpoly_to_gfxline(gfxpoly_t*poly)
+gfxline_t* gfxline_from_gfxpoly(gfxpoly_t*poly)
 {
     ArtSVP*svp = (ArtSVP*)poly;
     int size = 0;
@@ -981,10 +998,10 @@ gfxline_t* gfxpoly_to_gfxline(gfxpoly_t*poly)
     }
 }
 
-gfxpoly_t* gfxpoly_fillToPoly(gfxline_t*line)
+gfxpoly_t* gfxpoly_from_fill(gfxline_t*line, double gridsize)
 {
     /* I'm not sure whether doing perturbation here is actually
-       a good idea- if that line has been run through the machine
+       a good idea- if that line has been run through the machinery
        several times already, it might be safer to leave it alone,
        since it should already be in a format libart can handle */
 #ifdef PERTURBATE
@@ -1081,7 +1098,7 @@ gfxpoly_t* gfxpoly_union(gfxpoly_t*poly1, gfxpoly_t*poly2)
     return (gfxpoly_t*)svp;
 }
 
-gfxpoly_t* gfxpoly_strokeToPoly(gfxline_t*line, gfxcoord_t width, gfx_capType cap_style, gfx_joinType joint_style, double miterLimit)
+gfxpoly_t* gfxpoly_from_stroke(gfxline_t*line, gfxcoord_t width, gfx_capType cap_style, gfx_joinType joint_style, double miterLimit, double gridsize)
 {
     ArtVpath* vec = gfxline_to_ArtVpath(line, 0);
     msg("<verbose> Casting gfxline of %d segments to a stroke-polygon", gfxline_len(line));
@@ -1105,31 +1122,26 @@ gfxpoly_t* gfxpoly_strokeToPoly(gfxline_t*line, gfxcoord_t width, gfx_capType ca
     return (gfxpoly_t*)svp;
 }
 
-gfxline_t* gfxline_circularToEvenOdd(gfxline_t*line)
+gfxline_t* gfxpoly_circular_to_evenodd(gfxline_t*line, double gridsize)
 {
     msg("<verbose> Converting circular-filled gfxline of %d segments to even-odd filled gfxline", gfxline_len(line));
     ArtSVP* svp = gfxfillToSVP(line, 1);
 
-    /* TODO: ART_WIND_RULE_POSITIVE means that a shape is visible if
-             positive and negative line segments add up to something positive.
-             I *think* that clockwise fill in PDF is defined in a way, however,
-             that the *last* shape's direction will determine whether something
-             is filled */
     ArtSVP* svp_rewinded;
     
-    svp_rewinded = run_intersector(svp, ART_WIND_RULE_POSITIVE);
+    svp_rewinded = run_intersector(svp, ART_WIND_RULE_NONZERO);
     if(!svp_rewinded) {
        art_svp_free(svp);
        return 0;
     }
 
-    gfxline_t* result = gfxpoly_to_gfxline((gfxpoly_t*)svp_rewinded);
+    gfxline_t* result = gfxline_from_gfxpoly((gfxpoly_t*)svp_rewinded);
     art_svp_free(svp);
     art_svp_free(svp_rewinded);
     return result;
 }
 
-gfxpoly_t* gfxpoly_createbox(double x1, double y1,double x2, double y2)
+gfxpoly_t* gfxpoly_createbox(double x1, double y1,double x2, double y2, double gridsize)
 {
     ArtVpath *vec = art_new (ArtVpath, 5+1);
     vec[0].code = ART_MOVETO;
@@ -1155,7 +1167,7 @@ gfxpoly_t* gfxpoly_createbox(double x1, double y1,double x2, double y2)
     return (gfxpoly_t*)svp;
 }
 
-void gfxpoly_free(gfxpoly_t*poly)
+void gfxpoly_destroy(gfxpoly_t*poly)
 {
     ArtSVP*svp = (ArtSVP*)poly;
     art_svp_free(svp);