fixed format warnings
[swftools.git] / lib / gfxpoly / renderpoly.c
index 9ec6abf..240859d 100644 (file)
@@ -34,9 +34,10 @@ static inline void add_pixel(renderbuf_t*buf, double x, int y, segment_dir_t dir
     p.dir = dir;
     p.fs = fs;
     p.polygon_nr = polygon_nr;
-
-    if(x >= buf->bbox.xmax || y >= buf->bbox.ymax || y < buf->bbox.ymin) 
+    
+    if(y >= buf->bbox.ymax || y < buf->bbox.ymin) 
         return;
+
     renderline_t*l = &buf->lines[y-buf->bbox.ymin];
 
     if(l->num == l->size) {
@@ -47,7 +48,6 @@ static inline void add_pixel(renderbuf_t*buf, double x, int y, segment_dir_t dir
     l->num++;
 }
 #define CUT 0.5
-#define INT(x) ((int)((x)+16)-16)
 static void add_line(renderbuf_t*buf, double x1, double y1, double x2, double y2, fillstyle_t*fs, int polygon_nr)
 {
     x1 *= buf->zoom;
@@ -65,14 +65,14 @@ static void add_line(renderbuf_t*buf, double x1, double y1, double x2, double y2
     }
     diffx = x2 - x1;
     diffy = y2 - y1;
-    ny1 = INT(y1)+CUT;
-    ny2 = INT(y2)+CUT;
+    ny1 = floor(y1)+CUT;
+    ny2 = floor(y2)+CUT;
 
     if(ny1 < y1) {
-        ny1 = INT(y1) + 1.0 + CUT;
+        ny1 = floor(y1) + 1.0 + CUT;
     }
     if(ny2 >= y2) {
-        ny2 = INT(y2) - 1.0 + CUT;
+        ny2 = floor(y2) - 1.0 + CUT;
     }
     if(ny1 > ny2)
         return;
@@ -81,8 +81,8 @@ static void add_line(renderbuf_t*buf, double x1, double y1, double x2, double y2
     x1 = x1 + (ny1-y1)*stepx;
     x2 = x2 + (ny2-y2)*stepx;
 
-    int posy=INT(ny1);
-    int endy=INT(ny2);
+    int posy=floor(ny1);
+    int endy=floor(ny2);
     double posx=0;
     double startx = x1;
 
@@ -118,7 +118,7 @@ static void fill_bitwise(unsigned char*line, int x1, int x2)
     }
 }
 
-unsigned char* render_polygon(gfxpoly_t*polygon, intbbox_t*bbox, double zoom, windrule_t*rule)
+unsigned char* render_polygon(gfxpoly_t*polygon, intbbox_t*bbox, double zoom, windrule_t*rule, windcontext_t*context)
 {
     renderbuf_t _buf, *buf=&_buf;
     buf->width = (bbox->xmax - bbox->xmin);
@@ -126,9 +126,10 @@ unsigned char* render_polygon(gfxpoly_t*polygon, intbbox_t*bbox, double zoom, wi
     buf->bbox = *bbox;
     buf->zoom = zoom * polygon->gridsize;
     int width8 = (buf->width+7) >> 3;
+    char bleeding = 0;
     unsigned char* image = (unsigned char*)malloc(width8*buf->height);
     memset(image, 0, width8*buf->height);
-    
+
     buf->lines = (renderline_t*)rfx_alloc(buf->height*sizeof(renderline_t));
     int y;
     for(y=0;y<buf->height;y++) {
@@ -137,10 +138,15 @@ unsigned char* render_polygon(gfxpoly_t*polygon, intbbox_t*bbox, double zoom, wi
         buf->lines[y].num = 0;
     }
 
-    edge_t*e;
     int polygon_nr = 0;
-    for(e=polygon->edges;e;e=e->next) {
-        add_line(buf, e->a.x, e->a.y, e->b.x, e->b.y, e->style, polygon_nr);
+    int s,t;
+    gfxpolystroke_t*stroke = polygon->strokes;
+    for(;stroke;stroke=stroke->next) {
+       for(t=0;t<stroke->num_points-1;t++) {
+           point_t a = stroke->points[t];
+           point_t b = stroke->points[t+1];
+           add_line(buf, a.x, a.y, b.x, b.y, stroke->fs, polygon_nr);
+       }
     }
 
     for(y=0;y<buf->height;y++) {
@@ -150,28 +156,29 @@ unsigned char* render_polygon(gfxpoly_t*polygon, intbbox_t*bbox, double zoom, wi
        int num = buf->lines[y].num;
         qsort(points, num, sizeof(renderpoint_t), compare_renderpoints);
         int lastx = 0;
-
-        windstate_t fill = rule->start(1);
+        
+        windstate_t fill = rule->start(context);
         for(n=0;n<num;n++) {
             renderpoint_t*p = &points[n];
             int x = (int)(p->x - bbox->xmin);
-            
+
             if(x < lastx)
-                x = lastx;
-            if(x > buf->width) {
-                break;
-            }
-            if(fill.is_filled && x!=lastx) {
+                x = lastx; 
+            if(x > buf->width)
+                x = buf->width;
+
+            if(fill.is_filled && lastx<x) {
                 fill_bitwise(line, lastx, x);
             }
-            fill = rule->add(fill, p->fs, p->dir, p->polygon_nr);
+            fill = rule->add(context, fill, p->fs, p->dir, p->polygon_nr);
             lastx = x;
         }
         if(fill.is_filled && lastx!=buf->width) {
-            
-            return 0;// return an error, we're bleeding
-
-            fill_bitwise(line, lastx, buf->width);
+            /* we're bleeding, fill over padding, too. */
+            fprintf(stderr, "Polygon %08x is bleeding in line %d\n", (int)polygon, y);
+            fill_bitwise(line, lastx, width8*8);
+           assert(line[width8-1]&0x01);
+           bleeding = 1;
         }
     }
     
@@ -181,6 +188,9 @@ unsigned char* render_polygon(gfxpoly_t*polygon, intbbox_t*bbox, double zoom, wi
         }
         memset(&buf->lines[y], 0, sizeof(renderline_t));
     }
+    if(bleeding) {
+       assert(!bitmap_ok(bbox, image));
+    }
     free(buf->lines);buf->lines=0;
     return image;
 }
@@ -188,8 +198,16 @@ unsigned char* render_polygon(gfxpoly_t*polygon, intbbox_t*bbox, double zoom, wi
 #define MAX_WIDTH 8192
 #define MAX_HEIGHT 4096
 
-static inline max(double a, double b) {return a>b?a:b;}
-static inline min(double a, double b) {return a<b?a:b;}
+static inline double max(double a, double b) {return a>b?a:b;}
+static inline double min(double a, double b) {return a<b?a:b;}
+
+static int adjust_x(int xmin, int xmax)
+{
+    xmax += 8;
+    while(((xmax - xmin)&0x07) != 0x04)
+        xmax++;
+    return xmax;
+}
 
 intbbox_t intbbox_new(int x1, int y1, int x2, int y2)
 {
@@ -198,39 +216,40 @@ intbbox_t intbbox_new(int x1, int y1, int x2, int y2)
     b.ymin = y1;
     b.xmax = x2;
     b.ymax = y2;
-    b.width = x2-x1;
-    b.height = y2-y1;
+    b.xmax = adjust_x(b.xmin, b.xmax);
+    b.width = b.xmax - b.xmin;
+    b.height = b.ymax - b.ymin;
     return b;
 }
 
 intbbox_t intbbox_from_polygon(gfxpoly_t*polygon, double zoom)
 {
-    int t;
     intbbox_t b = {0,0,0,0};
-    edge_t*e = polygon->edges;
 
-    zoom *= polygon->gridsize;
+    double g = zoom*polygon->gridsize;
 
-    if(e) {
-        b.xmin = e->a.x*zoom;
-        b.ymin = e->a.y*zoom;
-        b.xmax = e->a.x*zoom;
-        b.ymax = e->a.y*zoom;
+    if(polygon->strokes && polygon->strokes->num_points) {
+        b.xmin = polygon->strokes->points[0].x*g;
+        b.ymin = polygon->strokes->points[0].y*g;
+        b.xmax = polygon->strokes->points[0].x*g;
+        b.ymax = polygon->strokes->points[0].y*g;
     }
-    for(e=polygon->edges;e;e=e->next) {
-        double x_min = min(e->a.x,e->b.x)*zoom;
-        double y_min = min(e->a.y,e->b.y)*zoom;
-        double x_max = max(e->a.x,e->b.x)*zoom;
-        double y_max = max(e->a.y,e->b.y)*zoom;
-        int x1 = floor(x_min);
-        int y1 = floor(y_min);
-        int x2 = ceil(x_max);
-        int y2 = ceil(y_max);
-        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;
+    int s,t;
+    gfxpolystroke_t*stroke = polygon->strokes;
+    for(;stroke;stroke=stroke->next) {
+       for(t=0;t<stroke->num_points;t++) {
+           point_t p = stroke->points[t];
+           int x1 = floor(p.x);
+           int y1 = floor(p.y);
+           int x2 = ceil(p.x);
+           int y2 = ceil(p.y);
+           if(x1 < b.xmin) b.xmin = x1;
+           if(y1 < b.ymin) b.ymin = y1;
+           if(x2 > b.xmax) b.xmax = x2;
+           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))
@@ -244,6 +263,8 @@ intbbox_t intbbox_from_polygon(gfxpoly_t*polygon, double zoom)
        b.xmin = b.xmax;
     if(b.ymin > b.ymax) 
        b.ymin = b.ymax;
+    
+    b.xmax = adjust_x(b.xmin, b.xmax);
 
     b.width = b.xmax - b.xmin;
     b.height = b.ymax - b.ymin;
@@ -269,8 +290,22 @@ intbbox_t intbbox_from_polygon(gfxpoly_t*polygon, double zoom)
 #define B00000010 0x02
 #define B00000001 0x01
 
+int bitmap_ok(intbbox_t*bbox, unsigned char*data)
+{
+    int y;
+    int width8 = (bbox->width+7) >> 3;
+    for(y=0;y<bbox->height;y++) {
+        if(data[width8-1]&0x01)
+            return 0; //bleeding
+        data += width8;
+    }
+    return 1;
+}
+
 int compare_bitmaps(intbbox_t*bbox, unsigned char*data1, unsigned char*data2)
 {
+    if(!data1 || !data2) 
+        return 0;
     int x,y;
     int height = bbox->height;
     int width = bbox->width;