{
double x;
segment_dir_t dir;
- fillstyle_t*fs;
- edge_t*e; //only for debugging
+ edgestyle_t*fs;
int polygon_nr;
} renderpoint_t;
renderline_t*lines;
} renderbuf_t;
-static inline void add_pixel(renderbuf_t*buf, double x, int y, segment_dir_t dir, fillstyle_t*fs, int polygon_nr, edge_t*e)
+static inline void add_pixel(renderbuf_t*buf, double x, int y, segment_dir_t dir, edgestyle_t*fs, int polygon_nr)
{
renderpoint_t p;
p.x = x;
p.dir = dir;
p.fs = fs;
- p.e = e;
p.polygon_nr = polygon_nr;
-
- if(x >= buf->bbox.xmax || y >= buf->bbox.ymax || y < buf->bbox.ymin)
- return;
+ if(y >= buf->bbox.ymax || y < buf->bbox.ymin)
+ return;
+
renderline_t*l = &buf->lines[y-buf->bbox.ymin];
if(l->num == l->size) {
l->num++;
}
#define CUT 0.5
-static void add_line(renderbuf_t*buf, double x1, double y1, double x2, double y2, fillstyle_t*fs, int polygon_nr, edge_t*e)
+static void add_line(renderbuf_t*buf, double x1, double y1, double x2, double y2, edgestyle_t*fs, segment_dir_t dir, int polygon_nr)
{
x1 *= buf->zoom;
y1 *= buf->zoom;
y2 *= buf->zoom;
double diffx, diffy;
double ny1, ny2, stepx;
- segment_dir_t dir = DIR_DOWN;
+
if(y2 < y1) {
- dir = DIR_UP;
+ dir ^= DIR_UP^DIR_DOWN;
double x,y;
x = x1;x1 = x2;x2=x;
y = y1;y1 = y2;y2=y;
}
+
diffx = x2 - x1;
diffy = y2 - y1;
ny1 = floor(y1)+CUT;
double posx=0;
double startx = x1;
+ //printf("line %d from %f to %f dir=%s\n", polygon_nr, y1, y2, dir==DIR_UP?"up":"down");
+
while(posy<=endy) {
double xx = startx + posx;
- add_pixel(buf, xx, posy, dir, fs, polygon_nr, e);
+ add_pixel(buf, xx, posy, dir, fs, polygon_nr);
posx+=stepx;
posy++;
}
}
}
-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->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++) {
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, e);
+ 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, stroke->dir, polygon_nr);
+ }
}
for(y=0;y<buf->height;y++) {
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) {
/* we're bleeding, fill over padding, too. */
- fprintf(stderr, "Polygon %08x is bleeding in line %d\n", polygon, y);
+ fprintf(stderr, "Polygon %p is bleeding in line %d\n", polygon, y);
fill_bitwise(line, lastx, width8*8);
+ assert(line[width8-1]&0x01);
+ bleeding = 1;
+ exit(1);
+
}
}
}
memset(&buf->lines[y], 0, sizeof(renderline_t));
}
+ if(bleeding) {
+ assert(!bitmap_ok(bbox, image));
+ }
free(buf->lines);buf->lines=0;
return image;
}
#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)
{
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;
double g = zoom*polygon->gridsize;
- if(e) {
- b.xmin = e->a.x*g;
- b.ymin = e->a.y*g;
- b.xmax = e->a.x*g;
- b.ymax = e->a.y*g;
+ 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)*g;
- double y_min = min(e->a.y,e->b.y)*g;
- double x_max = max(e->a.x,e->b.x)*g;
- double y_max = max(e->a.y,e->b.y)*g;
- 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.ymax) 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))
b.xmin = b.xmax;
if(b.ymin > b.ymax)
b.ymin = b.ymax;
-
- b.xmax += 8;
- while(((b.xmax - b.xmin)&0x07) != 0x04)
- b.xmax++;
+
+ b.xmax = adjust_x(b.xmin, b.xmax);
b.width = b.xmax - b.xmin;
b.height = b.ymax - b.ymin;
{
int y;
int width8 = (bbox->width+7) >> 3;
- if((bbox->width&7) == 0)
- return 1;
for(y=0;y<bbox->height;y++) {
if(data[width8-1]&0x01)
return 0; //bleeding
}
b1 += width8;
}
- writePNG(filename, data, b->width*2, b->height*2);
+ png_write(filename, data, b->width*2, b->height*2);
free(data);
}