4 #include "renderpoly.h"
6 typedef struct _renderpoint
14 typedef struct _renderline
21 typedef struct _renderbuf
30 static inline void add_pixel(renderbuf_t*buf, double x, int y, segment_dir_t dir, fillstyle_t*fs, int polygon_nr)
36 p.polygon_nr = polygon_nr;
38 if(x >= buf->bbox.xmax || y >= buf->bbox.ymax || y < buf->bbox.ymin)
40 renderline_t*l = &buf->lines[y-buf->bbox.ymin];
42 if(l->num == l->size) {
44 l->points = (renderpoint_t*)rfx_realloc(l->points, l->size * sizeof(renderpoint_t));
46 l->points[l->num] = p;
50 #define INT(x) ((int)((x)+16)-16)
51 static void add_line(renderbuf_t*buf, double x1, double y1, double x2, double y2, fillstyle_t*fs, int polygon_nr)
58 double ny1, ny2, stepx;
59 segment_dir_t dir = DIR_DOWN;
72 ny1 = INT(y1) + 1.0 + CUT;
75 ny2 = INT(y2) - 1.0 + CUT;
81 x1 = x1 + (ny1-y1)*stepx;
82 x2 = x2 + (ny2-y2)*stepx;
90 double xx = startx + posx;
91 add_pixel(buf, xx, posy, dir, fs, polygon_nr);
97 static int compare_renderpoints(const void * _a, const void * _b)
99 renderpoint_t*a = (renderpoint_t*)_a;
100 renderpoint_t*b = (renderpoint_t*)_b;
101 if(a->x < b->x) return -1;
102 if(a->x > b->x) return 1;
106 static void fill_bitwise(unsigned char*line, int x1, int x2)
110 int b1 = 0xff >> (x1&7);
111 int b2 = 0xff << (1+7-(x2&7));
116 memset(&line[p1+1], 255, p2-(p1+1));
121 unsigned char* render_polygon(gfxpoly_t*polygon, intbbox_t*bbox, double zoom, windrule_t*rule)
123 renderbuf_t _buf, *buf=&_buf;
124 buf->width = (bbox->xmax - bbox->xmin);
125 buf->height = (bbox->ymax - bbox->ymin);
127 buf->zoom = zoom * polygon->gridsize;
128 int width8 = (buf->width+7) >> 3;
129 unsigned char* image = (unsigned char*)malloc(width8*buf->height);
130 memset(image, 0, width8*buf->height);
132 buf->lines = (renderline_t*)rfx_alloc(buf->height*sizeof(renderline_t));
134 for(y=0;y<buf->height;y++) {
135 memset(&buf->lines[y], 0, sizeof(renderline_t));
136 buf->lines[y].points = 0;
137 buf->lines[y].num = 0;
142 for(e=polygon->edges;e;e=e->next) {
143 add_line(buf, e->a.x, e->a.y, e->b.x, e->b.y, e->style, polygon_nr);
146 for(y=0;y<buf->height;y++) {
147 renderpoint_t*points = buf->lines[y].points;
148 unsigned char*line = &image[width8*y];
150 int num = buf->lines[y].num;
151 qsort(points, num, sizeof(renderpoint_t), compare_renderpoints);
154 windstate_t fill = rule->start(1);
156 renderpoint_t*p = &points[n];
157 int x = (int)(p->x - bbox->xmin);
164 if(fill.is_filled && x!=lastx) {
165 fill_bitwise(line, lastx, x);
167 fill = rule->add(fill, p->fs, p->dir, p->polygon_nr);
170 if(fill.is_filled && lastx!=buf->width) {
172 return 0;// return an error, we're bleeding
174 fill_bitwise(line, lastx, buf->width);
178 for(y=0;y<buf->height;y++) {
179 if(buf->lines[y].points) {
180 free(buf->lines[y].points);
182 memset(&buf->lines[y], 0, sizeof(renderline_t));
184 free(buf->lines);buf->lines=0;
188 #define MAX_WIDTH 8192
189 #define MAX_HEIGHT 4096
191 static inline max(double a, double b) {return a>b?a:b;}
192 static inline min(double a, double b) {return a<b?a:b;}
194 intbbox_t intbbox_new(int x1, int y1, int x2, int y2)
206 intbbox_t intbbox_from_polygon(gfxpoly_t*polygon, double zoom)
209 intbbox_t b = {0,0,0,0};
210 edge_t*e = polygon->edges;
212 zoom *= polygon->gridsize;
215 b.xmin = e->a.x*zoom;
216 b.ymin = e->a.y*zoom;
217 b.xmax = e->a.x*zoom;
218 b.ymax = e->a.y*zoom;
220 for(e=polygon->edges;e;e=e->next) {
221 double x_min = min(e->a.x,e->b.x)*zoom;
222 double y_min = min(e->a.y,e->b.y)*zoom;
223 double x_max = max(e->a.x,e->b.x)*zoom;
224 double y_max = max(e->a.y,e->b.y)*zoom;
225 int x1 = floor(x_min);
226 int y1 = floor(y_min);
227 int x2 = ceil(x_max);
228 int y2 = ceil(y_max);
229 if(x1 < b.xmin) b.xmin = x1;
230 if(y1 < b.ymin) b.ymin = y1;
231 if(x2 > b.xmax) b.xmax = x2;
232 if(y2 > b.xmax) b.ymax = y2;
234 if(b.xmax > (int)(MAX_WIDTH*zoom))
235 b.xmax = (int)(MAX_WIDTH*zoom);
236 if(b.ymax > (int)(MAX_HEIGHT*zoom))
237 b.ymax = (int)(MAX_HEIGHT*zoom);
238 if(b.xmin < -(int)(MAX_WIDTH*zoom))
239 b.xmin = -(int)(MAX_WIDTH*zoom);
240 if(b.ymin < -(int)(MAX_HEIGHT*zoom))
241 b.ymin = -(int)(MAX_HEIGHT*zoom);
248 b.width = b.xmax - b.xmin;
249 b.height = b.ymax - b.ymin;
253 #define B11111000 0xf8
254 #define B01111100 0x7c
255 #define B00111110 0x3e
256 #define B00011111 0x1f
257 #define B11100000 0xe0
258 #define B01110000 0x70
259 #define B00111000 0x38
260 #define B00011100 0x1c
261 #define B00001110 0x0e
262 #define B00000111 0x07
263 #define B10000000 0x80
264 #define B01000000 0x40
265 #define B00100000 0x20
266 #define B00010000 0x10
267 #define B00001000 0x08
268 #define B00000100 0x04
269 #define B00000010 0x02
270 #define B00000001 0x01
272 int compare_bitmaps(intbbox_t*bbox, unsigned char*data1, unsigned char*data2)
275 int height = bbox->height;
276 int width = bbox->width;
277 int width8 = (width+7) >> 3;
278 unsigned char*l1 = &data1[width8*2];
279 unsigned char*l2 = &data2[width8*2];
280 for(y=2;y<height-2;y++) {
281 for(x=0;x<width8;x++) {
282 unsigned char a1 = l1[x-width8*2] & l1[x-width8] & l1[x] &
283 l1[x+width8] & l1[x+width8*2];
284 unsigned char b1 = l2[x-width8*2] & l2[x-width8] & l2[x] &
285 l2[x+width8] & l2[x+width8*2];
286 unsigned char a2 = l1[x-width8*2] | l1[x-width8] | l1[x] |
287 l1[x+width8] | l1[x+width8*2];
288 unsigned char b2 = l2[x-width8*2] | l2[x-width8] | l2[x] |
289 l2[x+width8] | l2[x+width8*2];
292 if((a1&B11111000)==B11111000 && (b2&B11111000)==0) fail=2;
293 if((a1&B01111100)==B01111100 && (b2&B01111100)==0) fail=3;
294 if((a1&B00111110)==B00111110 && (b2&B00111110)==0) fail=4;
295 if((a1&B00011111)==B00011111 && (b2&B00011111)==0) fail=5;
296 if((b1&B11111000)==B11111000 && (a2&B11111000)==0) fail=2;
297 if((b1&B01111100)==B01111100 && (a2&B01111100)==0) fail=3;
298 if((b1&B00111110)==B00111110 && (a2&B00111110)==0) fail=4;
299 if((b1&B00011111)==B00011111 && (a2&B00011111)==0) fail=5;
311 void save_two_bitmaps(intbbox_t*b, unsigned char*data1, unsigned char*data2, char*filename)
313 int width8 = (b->width+7) >> 3;
314 unsigned char*data = malloc(b->width*b->height*4*4);
315 unsigned char*p = data;
317 unsigned char*b1 = data1;
318 unsigned char*b2 = data2;
319 compare_bitmaps(b, data1, data2);
320 //# define MARK ((abs(x-badx)<3 && abs(y-bady)<3)*255)
322 for(y=0;y<b->height;y++) {
323 for(x=0;x<b->width;x++) {
324 unsigned char c1 = (b1[x>>3]&(0x80>>(x&7)))?255:0;
325 unsigned char c2 = (b2[x>>3]&(0x80>>(x&7)))?255:0;
331 for(x=0;x<b->width;x++) {
332 unsigned char c = (b2[x>>3]&(0x80>>(x&7)))?255:0;
342 for(y=0;y<b->height;y++) {
343 for(x=0;x<b->width;x++) {
344 unsigned char c = (b1[x>>3]&(0x80>>(x&7)))?255:0;
350 for(x=0;x<b->width;x++) {
358 writePNG(filename, data, b->width*2, b->height*2);