X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Fgfxpoly%2Frenderpoly.c;h=240859ddb1afa35ecee6cec0e8bb3f3ce2aac579;hp=de7dc0a230e02afde87cacfa8be2e05830291b8f;hb=2391d7ae5d8a145a250a8b80ab8c93ba74eba030;hpb=e5ec9f136f070b7e824e223c0b67e28efd8c70f0 diff --git a/lib/gfxpoly/renderpoly.c b/lib/gfxpoly/renderpoly.c index de7dc0a..240859d 100644 --- a/lib/gfxpoly/renderpoly.c +++ b/lib/gfxpoly/renderpoly.c @@ -8,6 +8,7 @@ typedef struct _renderpoint double x; segment_dir_t dir; fillstyle_t*fs; + int polygon_nr; } renderpoint_t; typedef struct _renderline @@ -26,15 +27,17 @@ typedef struct _renderbuf renderline_t*lines; } renderbuf_t; -static inline void add_pixel(renderbuf_t*buf, double x, int y, segment_dir_t dir, fillstyle_t*fs) +static inline void add_pixel(renderbuf_t*buf, double x, int y, segment_dir_t dir, fillstyle_t*fs, int polygon_nr) { renderpoint_t p; p.x = x; p.dir = dir; p.fs = fs; - - if(x >= buf->bbox.xmax || y >= buf->bbox.ymax || y < buf->bbox.ymin) + p.polygon_nr = polygon_nr; + + if(y >= buf->bbox.ymax || y < buf->bbox.ymin) return; + renderline_t*l = &buf->lines[y-buf->bbox.ymin]; if(l->num == l->size) { @@ -45,8 +48,7 @@ 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) +static void add_line(renderbuf_t*buf, double x1, double y1, double x2, double y2, fillstyle_t*fs, int polygon_nr) { x1 *= buf->zoom; y1 *= buf->zoom; @@ -63,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; @@ -79,14 +81,14 @@ 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; while(posy<=endy) { double xx = startx + posx; - add_pixel(buf, xx, posy, dir, fs); + add_pixel(buf, xx, posy, dir, fs, polygon_nr); posx+=stepx; posy++; } @@ -116,17 +118,18 @@ 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); buf->height = (bbox->ymax - bbox->ymin); buf->bbox = *bbox; - buf->zoom = zoom; + 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;yheight;y++) { @@ -135,9 +138,15 @@ unsigned char* render_polygon(gfxpoly_t*polygon, intbbox_t*bbox, double zoom, wi buf->lines[y].num = 0; } - edge_t*e; - for(e=polygon;e;e=e->next) { - add_line(buf, e->a.x, e->a.y, e->b.x, e->b.y, e->style); + int polygon_nr = 0; + int s,t; + gfxpolystroke_t*stroke = polygon->strokes; + for(;stroke;stroke=stroke->next) { + for(t=0;tnum_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;yheight;y++) { @@ -147,25 +156,30 @@ 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 = 0; + + windstate_t fill = rule->start(context); for(n=0;nx - 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 && lastxadd(fill, p->fs, p->dir, polygon); + fill = rule->add(context, fill, p->fs, p->dir, p->polygon_nr); lastx = x; } - if(fill->is_filled && lastx!=buf->width) - fill_bitwise(line, lastx, buf->width); + if(fill.is_filled && 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; + } } for(y=0;yheight;y++) { @@ -174,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; } @@ -181,35 +198,58 @@ 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 ab?a:b;} +static inline double min(double a, double b) {return aa.x; - b.ymin = e->a.y; - b.xmax = e->a.x; - b.ymax = e->a.y; + double g = zoom*polygon->gridsize; + + 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;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;tnum_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)) @@ -223,12 +263,18 @@ intbbox_t get_polygon_bbox(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; return b; } +#define B11111000 0xf8 +#define B01111100 0x7c +#define B00111110 0x3e +#define B00011111 0x1f #define B11100000 0xe0 #define B01110000 0x70 #define B00111000 0x38 @@ -244,49 +290,106 @@ intbbox_t get_polygon_bbox(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;yheight;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) { - 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;ywidth+7) >> 3; + unsigned char*data = malloc(b->width*b->height*4*4); + unsigned char*p = data; + int x,y; + unsigned char*b1 = data1; + unsigned char*b2 = data2; + compare_bitmaps(b, data1, data2); +//# define MARK ((abs(x-badx)<3 && abs(y-bady)<3)*255) +#define MARK 0 + for(y=0;yheight;y++) { + for(x=0;xwidth;x++) { + unsigned char c1 = (b1[x>>3]&(0x80>>(x&7)))?255:0; + unsigned char c2 = (b2[x>>3]&(0x80>>(x&7)))?255:0; + *p++ = 255; + *p++ = c1^c2; + *p++ = c1^c2; + *p++ = MARK; + } + for(x=0;xwidth;x++) { + unsigned char c = (b2[x>>3]&(0x80>>(x&7)))?255:0; + *p++ = 255; + *p++ = c; + *p++ = c; + *p++ = MARK; + } + b1 += width8; + b2 += width8; + } + b1 = data1; + for(y=0;yheight;y++) { + for(x=0;xwidth;x++) { + unsigned char c = (b1[x>>3]&(0x80>>(x&7)))?255:0; + *p++ = 255; + *p++ = c; + *p++ = c; + *p++ = MARK; + } + for(x=0;xwidth;x++) { + *p++ = 255; + *p++ = 0; + *p++ = 0; + *p++ = 0; + } + b1 += width8; + } + writePNG(filename, data, b->width*2, b->height*2); + free(data); }