first version of new polygon intersector
[swftools.git] / lib / gfxpoly.c
index acf2de3..a08899d 100644 (file)
 #include "gfxtools.h"
 #include "gfxpoly.h"
 #include "mem.h"
+#ifdef INTERNAL_LIBART
 #include "art/libart.h"
 #include "art/art_svp_intersect.h"
 #include "art/art_svp_ops.h"
+#else
+#include <libart_lgpl/libart.h>
+#include <libart_lgpl/art_svp_intersect.h>
+#include <libart_lgpl/art_svp_ops.h>
+#endif
 #include "log.h"
 #include <assert.h>
 #include <memory.h>
@@ -233,6 +239,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;
@@ -259,6 +268,20 @@ intbbox_t get_svp_bbox(ArtSVP*svp, double zoom)
             if(y2 > b.xmax) 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;
@@ -361,11 +384,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 +415,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 +449,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 +541,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 +698,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 +747,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;
@@ -906,11 +946,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 +960,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;
@@ -984,7 +1019,7 @@ gfxline_t* gfxpoly_to_gfxline(gfxpoly_t*poly)
 gfxpoly_t* gfxpoly_fillToPoly(gfxline_t*line)
 {
     /* 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