4 #include "renderpoly.h"
6 typedef struct _renderpoint
13 typedef struct _renderline
20 typedef struct _renderbuf
29 static inline void add_pixel(renderbuf_t*buf, double x, int y, segment_dir_t dir, fillstyle_t*fs)
36 if(x >= buf->bbox.xmax || y >= buf->bbox.ymax || y < buf->bbox.ymin)
38 renderline_t*l = &buf->lines[y-buf->bbox.ymin];
40 if(l->num == l->size) {
42 l->points = (renderpoint_t*)rfx_realloc(l->points, l->size * sizeof(renderpoint_t));
44 l->points[l->num] = p;
48 #define INT(x) ((int)((x)+16)-16)
49 static void add_line(renderbuf_t*buf, double x1, double y1, double x2, double y2, fillstyle_t*fs)
56 double ny1, ny2, stepx;
57 segment_dir_t dir = DIR_DOWN;
70 ny1 = INT(y1) + 1.0 + CUT;
73 ny2 = INT(y2) - 1.0 + CUT;
79 x1 = x1 + (ny1-y1)*stepx;
80 x2 = x2 + (ny2-y2)*stepx;
88 double xx = startx + posx;
89 add_pixel(buf, xx, posy, dir, fs);
95 static int compare_renderpoints(const void * _a, const void * _b)
97 renderpoint_t*a = (renderpoint_t*)_a;
98 renderpoint_t*b = (renderpoint_t*)_b;
99 if(a->x < b->x) return -1;
100 if(a->x > b->x) return 1;
104 static void fill_bitwise(unsigned char*line, int x1, int x2)
108 int b1 = 0xff >> (x1&7);
109 int b2 = 0xff << (1+7-(x2&7));
114 memset(&line[p1+1], 255, p2-(p1+1));
119 unsigned char* render_polygon(gfxpoly_t*polygon, intbbox_t*bbox, double zoom, windrule_t*rule)
121 renderbuf_t _buf, *buf=&_buf;
122 buf->width = (bbox->xmax - bbox->xmin);
123 buf->height = (bbox->ymax - bbox->ymin);
126 int width8 = (buf->width+7) >> 3;
127 unsigned char* image = (unsigned char*)malloc(width8*buf->height);
128 memset(image, 0, width8*buf->height);
130 buf->lines = (renderline_t*)rfx_alloc(buf->height*sizeof(renderline_t));
132 for(y=0;y<buf->height;y++) {
133 memset(&buf->lines[y], 0, sizeof(renderline_t));
134 buf->lines[y].points = 0;
135 buf->lines[y].num = 0;
139 for(e=polygon;e;e=e->next) {
140 add_line(buf, e->a.x, e->a.y, e->b.x, e->b.y, e->style);
143 for(y=0;y<buf->height;y++) {
144 renderpoint_t*points = buf->lines[y].points;
145 unsigned char*line = &image[width8*y];
147 int num = buf->lines[y].num;
148 qsort(points, num, sizeof(renderpoint_t), compare_renderpoints);
151 windstate_t*fill = 0;
153 renderpoint_t*p = &points[n];
154 int x = (int)(p->x - bbox->xmin);
161 if(fill->is_filled && x!=lastx) {
162 fill_bitwise(line, lastx, x);
164 fill = rule->add(fill, p->fs, p->dir, polygon);
167 if(fill->is_filled && lastx!=buf->width)
168 fill_bitwise(line, lastx, buf->width);
171 for(y=0;y<buf->height;y++) {
172 if(buf->lines[y].points) {
173 free(buf->lines[y].points);
175 memset(&buf->lines[y], 0, sizeof(renderline_t));
177 free(buf->lines);buf->lines=0;
181 #define MAX_WIDTH 8192
182 #define MAX_HEIGHT 4096
184 static inline max(double a, double b) {return a>b?a:b;}
185 static inline min(double a, double b) {return a<b?a:b;}
187 intbbox_t get_polygon_bbox(gfxpoly_t*polygon, double zoom)
190 intbbox_t b = {0,0,0,0};
199 for(e=polygon;e;e=e->next) {
200 double x_min = min(e->a.x,e->b.x)*zoom;
201 double y_min = min(e->a.y,e->b.y)*zoom;
202 double x_max = max(e->a.x,e->b.x)*zoom;
203 double y_max = max(e->a.y,e->b.y)*zoom;
204 int x1 = floor(x_min);
205 int y1 = floor(y_min);
206 int x2 = ceil(x_max);
207 int y2 = ceil(y_max);
208 if(x1 < b.xmin) b.xmin = x1;
209 if(y1 < b.ymin) b.ymin = y1;
210 if(x2 > b.xmax) b.xmax = x2;
211 if(y2 > b.xmax) b.ymax = y2;
213 if(b.xmax > (int)(MAX_WIDTH*zoom))
214 b.xmax = (int)(MAX_WIDTH*zoom);
215 if(b.ymax > (int)(MAX_HEIGHT*zoom))
216 b.ymax = (int)(MAX_HEIGHT*zoom);
217 if(b.xmin < -(int)(MAX_WIDTH*zoom))
218 b.xmin = -(int)(MAX_WIDTH*zoom);
219 if(b.ymin < -(int)(MAX_HEIGHT*zoom))
220 b.ymin = -(int)(MAX_HEIGHT*zoom);
227 b.width = b.xmax - b.xmin;
228 b.height = b.ymax - b.ymin;
232 #define B11100000 0xe0
233 #define B01110000 0x70
234 #define B00111000 0x38
235 #define B00011100 0x1c
236 #define B00001110 0x0e
237 #define B00000111 0x07
238 #define B10000000 0x80
239 #define B01000000 0x40
240 #define B00100000 0x20
241 #define B00010000 0x10
242 #define B00001000 0x08
243 #define B00000100 0x04
244 #define B00000010 0x02
245 #define B00000001 0x01
247 int compare_bitmaps(intbbox_t*bbox, unsigned char*data1, unsigned char*data2)
251 int height = bbox->height;
252 int width = bbox->width;
253 int width8 = (width+7) >> 3;
254 unsigned char*l1 = &data1[width8];
255 unsigned char*l2 = &data2[width8];
257 for(y=1;y<height-1;y++) {
258 for(x=0;x<width8;x++) {
259 unsigned a = l1[x-width8] & l1[x] & l1[x+width8];
260 unsigned b = l2[x-width8] & l2[x] & l2[x+width8];
262 if((a&B11100000) && !(l2[x]&B01000000))
264 if((a&B01110000) && !(l2[x]&B00100000))
266 if((a&B00111000) && !(l2[x]&B00010000))
268 if((a&B00011100) && !(l2[x]&B00001000))
270 if((a&B00001110) && !(l2[x]&B00000100))
272 if((a&B00000111) && !(l2[x]&B00000010))
275 if((b&B11100000) && !(l1[x]&B01000000))
277 if((b&B01110000) && !(l1[x]&B00100000))
279 if((b&B00111000) && !(l1[x]&B00010000))
281 if((b&B00011100) && !(l1[x]&B00001000))
283 if((b&B00001110) && !(l1[x]&B00000100))
285 if((b&B00000111) && !(l1[x]&B00000010))