polygon intersector: performance improvements and bugfixes
[swftools.git] / lib / gfxpoly / test.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <assert.h>
4 #include <memory.h>
5 #include <math.h>
6 #include "../gfxtools.h"
7 #include "poly.h"
8 #include "convert.h"
9 #include "renderpoly.h"
10
11 gfxline_t*mkstar(int x1, int y1, int x2, int y2)
12 {
13     gfxline_t*l=0,*line = 0;
14     int x;
15     for(x=x1;x<=x2;x+=50) {
16         l = rfx_calloc(sizeof(gfxline_t));
17         l->type = gfx_moveTo;
18         l->x = x;l->y = y1;
19         line = gfxline_append(line, l);
20
21         l = rfx_calloc(sizeof(gfxline_t));
22         l->type = gfx_lineTo;
23         l->x = x2-x;l->y = y2;
24         line = gfxline_append(line, l);
25     }
26     return line;
27 }
28
29 gfxline_t* mkrandomshape(int range, int n)
30 {
31     int i;
32     gfxline_t* line = malloc(sizeof(gfxline_t)*n*2);
33     for(i=0;i<n;i++) {
34         line[i].type = i?gfx_lineTo:gfx_moveTo;
35         line[i].x = lrand48()%range - range/2;
36         line[i].y = lrand48()%range - range/2;
37         line[i].next = &line[i+1];
38         line[n*2-i-1].type = gfx_lineTo;
39         line[n*2-i-1].x = line[i].x;
40         line[n*2-i-1].y = line[i].y;
41         line[n*2-i-1].next = &line[n*2-i];
42     }
43     line[n*2-1].next = 0;
44     line[n-1].x = line[0].x;
45     line[n-1].y = line[0].y;
46     line[n-1].next = 0;
47 }
48
49 gfxline_t* mkchessboard()
50 {
51     gfxline_t*b = 0;
52     int x,y;
53     unsigned int r = 0;
54     int spacing = 20;
55
56     //int num_caros = 40;
57     //int l = 5;
58     //char do_centerpiece=1;
59
60     int num_caros = 4;
61     int l=1;
62     char do_centerpiece=0;
63
64     for(x=-l;x<=l;x++) 
65     for(y=-l;y<=l;y++) {
66         /* pseudo random */ 
67         r = crc32_add_byte(r, x);r = crc32_add_byte(r, y);
68         if(r&1) {
69             gfxline_t*box;
70             if(r&2) {
71                 box = gfxline_makerectangle(x*spacing,y*spacing,(x+1)*spacing,(y+1)*spacing);
72             } else {
73                 box = gfxline_makerectangle((x+1)*spacing,y*spacing,x*spacing,(y+1)*spacing);
74             }
75             b = gfxline_append(b, box);
76         }
77     }
78
79     int t;
80     for(t=0;t<num_caros;t++) {
81         r = crc32_add_byte(r, t);
82         int x=(r%10-5)*spacing;
83         int y=((r>>4)%10-5)*spacing;
84         int sizex = ((r>>8)%4)*spacing;
85         int sizey = sizex;
86         if(r&65536)
87             sizex = -sizex;
88         gfxline_t*l = malloc(sizeof(gfxline_t)*5);
89         l[0].type = gfx_moveTo;l[0].next = &l[1];
90         l[1].type = gfx_lineTo;l[1].next = &l[2];
91         l[2].type = gfx_lineTo;l[2].next = &l[3];
92         l[3].type = gfx_lineTo;l[3].next = &l[4];
93         l[4].type = gfx_lineTo;l[4].next = 0;
94         l[0].x = x;
95         l[0].y = y-sizey;
96         l[1].x = x+sizex;
97         l[1].y = y;
98         l[2].x = x;
99         l[2].y = y+sizey;
100         l[3].x = x-sizex;
101         l[3].y = y;
102         l[4].x = x;
103         l[4].y = y-sizey;
104         gfxline_append(b, l);
105     }
106     if(do_centerpiece)
107     for(t=0;t<5;t++) {
108         gfxline_t*l = gfxline_makerectangle(-9*spacing,-10,9*spacing,10);
109         gfxmatrix_t matrix;
110         memset(&matrix, 0, sizeof(gfxmatrix_t));
111         double ua=t*0.43;
112         matrix.m00=cos(ua);matrix.m10=sin(ua);
113         matrix.m01=-sin(ua);matrix.m11=cos(ua);
114         gfxline_transform(l, &matrix);
115         gfxline_append(b, l);
116     }
117     return b;
118 }
119
120 int test0()
121 {
122     gfxline_t* b = mkchessboard();
123
124     gfxmatrix_t m;
125     memset(&m, 0, sizeof(gfxmatrix_t));
126     int t = 28;
127     m.m00 = cos(t*M_PI/180.0);
128     m.m01 = sin(t*M_PI/180.0);
129     m.m10 = -sin(t*M_PI/180.0);
130     m.m11 = cos(t*M_PI/180.0);
131     m.tx = 400*1.41/2;
132     m.ty = 400*1.41/2;
133     gfxline_transform(b, &m);
134
135     gfxpoly_t*poly = gfxpoly_from_gfxline(b, 0.05);
136     gfxpoly_t*poly2 = gfxpoly_process(poly, &windrule_evenodd);
137     gfxpoly_destroy(poly2);
138     gfxpoly_destroy(poly);
139 }
140
141 int test1()
142 {
143     gfxline_t*box1 = gfxline_makerectangle(50,50,150,150);
144     // put box2 and box3 on top of each other *snicker*
145     gfxline_t*box2 = gfxline_makerectangle(100,100,200,200);
146     gfxline_t*box3 = gfxline_makerectangle(100,100,200,200);
147     gfxline_t*star = mkstar(50,50, 150,150);
148     gfxline_t*b = 0;
149     b = gfxline_append(b, box1);
150     b = gfxline_append(b, box2);
151     b = gfxline_append(b, box3);
152     //b = gfxline_append(b, star);
153
154     gfxmatrix_t matrix;
155     memset(&matrix, 0, sizeof(gfxmatrix_t));
156     double ua=0.1;
157     matrix.m00=cos(ua);matrix.m10=sin(ua);
158     matrix.m01=-sin(ua);matrix.m11=cos(ua);
159
160     //gfxline_transform(b, &matrix);
161
162     gfxpoly_t*poly = gfxpoly_from_gfxline(b, 0.05);
163     gfxline_free(box1);
164     gfxline_free(box2);
165     gfxline_free(box3);
166     gfxline_free(star);
167
168     gfxpoly_dump(poly);
169     gfxpoly_t*poly2 = gfxpoly_process(poly, &windrule_evenodd);
170     gfxpoly_destroy(poly2);
171     gfxpoly_destroy(poly);
172 }
173
174 int test_square(int width, int height, int num, double gridsize, char bitmaptest)
175 {
176     int t;
177     gfxline_t* line = malloc(sizeof(gfxline_t)*num);
178     for(t=0;t<num;t++) {
179         line[t].type = t?gfx_lineTo:gfx_moveTo;
180         line[t].x = (lrand48()%width);
181         line[t].y = (lrand48()%height);
182         line[t].next = &line[t+1];
183     }
184     line[num-1].x = line[0].x;
185     line[num-1].y = line[0].y;
186     line[num-1].next = 0;
187     
188     gfxpoly_t*poly = gfxpoly_from_gfxline(line, gridsize);
189     gfxline_free(line);
190
191     windrule_t*rule = &windrule_circular;
192     gfxpoly_t*poly2 = gfxpoly_process(poly, rule);
193     if(bitmaptest) {
194         intbbox_t bbox = intbbox_new(0, 0, width, height);
195         unsigned char*bitmap1 = render_polygon(poly, &bbox, 1.0, rule);
196         unsigned char*bitmap2 = render_polygon(poly2, &bbox, 1.0, &windrule_evenodd);
197         if(!compare_bitmaps(&bbox, bitmap1, bitmap2)) {
198             save_two_bitmaps(&bbox, bitmap1, bitmap2, "error.png");
199             assert(!"bitmaps don't match");
200         }
201     }
202     gfxpoly_destroy(poly2);
203     gfxpoly_destroy(poly);
204 }
205
206 int test2()
207 {
208     test_square(400,400, 3, 0.05, 1);
209
210     int t;
211     for(t=0;t<400;t++) {
212         test_square(400,400, 50, 0.05, 1);
213         test_square(200,3, 1000, 1.0, 0);
214         test_square(3,200, 1000, 1.0, 0);
215         test_square(10,10, 200, 1.0, 0);
216     }
217 }
218
219 #include "../rfxswf.h"
220 void test3()
221 {
222 #undef N
223 #undef RANGE
224 #define N 100
225 #define RANGE 400
226
227     //gfxline_t*line = mkrandomshape(RANGE, N);
228     //windrule_t*rule = &windrule_circular;
229     gfxline_t*line = mkchessboard();
230     windrule_t*rule = &windrule_evenodd;
231
232     gfxmatrix_t m;
233     memset(&m, 0, sizeof(m));
234
235     SWF swf;
236     memset(&swf, 0, sizeof(SWF));
237     swf.movieSize.xmax = RANGE*20*1.41;
238     swf.movieSize.ymax = RANGE*20*1.41;
239     swf.fileVersion = 9;
240     swf.frameRate = 25*0x100;
241     TAG * tag = swf.firstTag = swf_InsertTag(0, ST_SETBACKGROUNDCOLOR);
242     swf_SetU8(tag, 0);
243     swf_SetU8(tag, 0);
244     swf_SetU8(tag, 0);
245
246     int t;
247     for(t=0;t<360;t++) {
248         m.m00 = cos(t*M_PI/180.0);
249         m.m01 = sin(t*M_PI/180.0);
250         m.m10 = -sin(t*M_PI/180.0);
251         m.m11 = cos(t*M_PI/180.0);
252         m.tx = RANGE*1.41/2;
253         m.ty = RANGE*1.41/2;
254         printf("%d\n", t);
255
256         gfxline_t*l = gfxline_clone(line);
257         gfxline_transform(l, &m);
258         
259         gfxpoly_t*poly = gfxpoly_from_gfxline(l, 0.05);
260         gfxpoly_t*poly2 = gfxpoly_process(poly, rule);
261
262         tag = swf_InsertTag(tag, ST_DEFINESHAPE);
263         SHAPE* s;
264         swf_ShapeNew(&s);
265         RGBA rgb;
266         rgb.r = rgb.g = 0x00; rgb.b = 0xff;
267         rgb.a = 255;
268         int fs = swf_ShapeAddSolidFillStyle(s,&rgb);
269         int ls = swf_ShapeAddLineStyle(s,20,&rgb);
270         swf_SetU16(tag,t+1);
271         swf_SetRect(tag,&swf.movieSize);
272         swf_SetShapeHeader(tag,s);
273
274 #define FILL
275 #ifdef FILL
276         swf_ShapeSetAll(tag,s,0,0,0,fs,0);
277         edge_t*e = poly2->edges;
278         while(e) {
279 #define ROTATE
280 #ifdef ROTATE
281             swf_ShapeSetMove(tag, s, e->a.y, e->a.x);
282             swf_ShapeSetLine(tag, s, e->b.y - e->a.y, e->b.x - e->a.x);
283 #else
284             swf_ShapeSetMove(tag, s, e->a.x, e->a.y);
285             swf_ShapeSetLine(tag, s, e->b.x - e->a.x, e->b.y - e->a.y);
286 #endif
287             e = e->next;
288         }
289 #else
290         swf_ShapeSetAll(tag,s,0,0,ls,0,0);
291         edge_t*e = poly2->edges;
292         while(e) {
293             swf_ShapeSetMove(tag, s, e->a.x, e->a.y);
294             swf_ShapeSetLine(tag, s, e->b.x - e->a.x, e->b.y - e->a.y);
295             
296             swf_ShapeSetCircle(tag, s, e->a.x, e->a.y, 5*20, 5*20);
297             swf_ShapeSetCircle(tag, s, e->b.x, e->b.y, 5*20, 5*20);
298             e = e->next;
299         }
300 #endif
301
302         swf_ShapeSetEnd(tag);
303         swf_ShapeFree(s);
304
305         gfxpoly_destroy(poly);
306         gfxpoly_destroy(poly2);
307
308         gfxline_free(l);
309    
310         if(t) {
311             tag = swf_InsertTag(tag,ST_REMOVEOBJECT2);
312             swf_SetU16(tag, t);
313         }
314         tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
315         swf_ObjectPlace(tag,t+1,t+1,NULL,NULL,NULL);
316
317         tag = swf_InsertTag(tag, ST_SHOWFRAME);
318     }
319     tag = swf_InsertTag(tag, ST_END);
320
321     swf_SaveSWF(&swf, "test.swf");
322 }
323
324 #include <dirent.h>
325 void test4()
326 {
327     char*dir = "ps";
328     DIR*_dir = opendir(dir);
329     if(!_dir) return;
330     struct dirent*file;
331     while(1) {
332         file = readdir(_dir);
333         if (!file) 
334             break;
335         if(!strstr(file->d_name, ".ps")) 
336             continue;
337
338         char* filename = allocprintf("%s/%s", dir, file->d_name);
339         windrule_t*rule = &windrule_evenodd;
340         gfxpoly_t*poly = gfxpoly_from_file(filename, 0.01);
341         free(filename);
342
343         double zoom = 1.0;
344         intbbox_t bbox = intbbox_from_polygon(poly, zoom);
345
346         if(!gfxpoly_check(poly)) {
347             printf("bad polygon\n");
348             continue;
349         }
350
351         gfxpoly_t*poly2 = gfxpoly_process(poly, rule);
352         unsigned char*bitmap1 = render_polygon(poly, &bbox, zoom, rule);
353         unsigned char*bitmap2 = render_polygon(poly2, &bbox, zoom, &windrule_evenodd);
354         if(!bitmap_ok(&bbox, bitmap1) || !bitmap_ok(&bbox, bitmap2)) {
355             save_two_bitmaps(&bbox, bitmap1, bitmap2, "error.png");
356             assert(!"error in bitmaps");
357         }
358         if(!compare_bitmaps(&bbox, bitmap1, bitmap2)) {
359             save_two_bitmaps(&bbox, bitmap1, bitmap2, "error.png");
360             assert(!"bitmaps don't match");
361         }
362         gfxpoly_destroy(poly2);
363     }
364 }
365
366 #include "../gfxdevice.h"
367 #include "../pdf/pdf.h"
368
369 void extract_polygons_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color) 
370 {
371     gfxpoly_t*poly = gfxpoly_from_gfxline(line, 0.05);
372     printf("%d segments\n", gfxpoly_size(poly));
373
374     if(!gfxpoly_check(poly)) {
375         gfxpoly_destroy(poly);
376         printf("bad polygon\n");
377         return;
378     }
379
380     windrule_t*rule = &windrule_evenodd;
381     gfxpoly_t*poly2 = gfxpoly_process(poly, rule);
382         
383     double zoom = 1.0;
384     intbbox_t bbox = intbbox_from_polygon(poly, zoom);
385     unsigned char*bitmap1 = render_polygon(poly, &bbox, zoom, rule);
386     unsigned char*bitmap2 = render_polygon(poly2, &bbox, zoom, &windrule_evenodd);
387     if(!bitmap_ok(&bbox, bitmap1)) {
388         printf("bad polygon or error in renderer\n");
389         return;
390     }
391     if(!bitmap_ok(&bbox, bitmap2)) {
392         save_two_bitmaps(&bbox, bitmap1, bitmap2, "error.png");
393         assert(!"error in bitmap");
394     }
395     if(!compare_bitmaps(&bbox, bitmap1, bitmap2)) {
396         save_two_bitmaps(&bbox, bitmap1, bitmap2, "error.png");
397         assert(!"bitmaps don't match");
398     }
399
400     gfxpoly_destroy(poly);
401     gfxpoly_destroy(poly2);
402 }
403 int extract_polygons_setparameter(gfxdevice_t*dev, const char*key, const char*value) {
404     return 0;
405 }
406 void extract_polygons_startclip(gfxdevice_t*dev, gfxline_t*line) 
407 {
408     extract_polygons_fill(dev, line, 0);
409 }
410 void extract_polygons_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*imgcoord2devcoord, gfxcxform_t*cxform)
411 {
412     extract_polygons_fill(dev, line, 0);
413 }
414 void extract_polygons_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*gradcoord2devcoord)
415 {
416     extract_polygons_fill(dev, line, 0);
417 }
418 void extract_polygons_drawlink(gfxdevice_t*dev, gfxline_t*line, const char*action)
419 {
420     extract_polygons_fill(dev, line, 0);
421 }
422 void extract_polygons_addfont(gfxdevice_t*dev, gfxfont_t*font)
423 {
424     int t;
425     for(t=0;t<font->num_glyphs;t++) {
426         //extract_polygons_fill(dev, font->glyphs[t].line, 0);
427     }
428 }
429 void extract_polygons_endclip(gfxdevice_t*dev)
430 {
431 }
432 void extract_polygons_stroke(gfxdevice_t*dev, gfxline_t*line, gfxcoord_t width, gfxcolor_t*color, gfx_capType cap_style, gfx_joinType joint_style, gfxcoord_t miterLimit)
433 {
434 }
435 void extract_polygons_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyph, gfxcolor_t*color, gfxmatrix_t*matrix)
436 {
437 }
438     
439 gfxdevice_t extract_polygons = 
440 {
441 name: "extract polygons",
442 setparameter:extract_polygons_setparameter,
443 startclip: extract_polygons_startclip,
444 endclip: extract_polygons_endclip,
445 stroke: extract_polygons_stroke,
446 fill: extract_polygons_fill,
447 fillbitmap: extract_polygons_fillbitmap,
448 fillgradient: extract_polygons_fillgradient,
449 addfont: extract_polygons_addfont,
450 drawchar: extract_polygons_drawchar,
451 drawlink: extract_polygons_drawlink,
452 startpage: 0,
453 endpage: 0,
454 geterror: 0,
455 finish: 0,
456 internal: 0
457 };
458
459 void test5()
460 {
461     char*dir = "pdfs";
462     DIR*_dir = opendir(dir);
463     if(!_dir) return;
464     struct dirent*file;
465     while(1) {
466         file = readdir(_dir);
467         if (!file) 
468             break;
469         if(!strstr(file->d_name, ".pdf")) 
470             continue;
471         char* filename = allocprintf("%s/%s", dir, file->d_name);
472
473         gfxsource_t*driver = gfxsource_pdf_create();
474         gfxdocument_t*doc = driver->open(driver, filename);
475         gfxdevice_t*out = &extract_polygons;
476         int t;
477         for(t=1;t<=doc->num_pages;t++) {
478             printf("%s (page %d)\n", filename, t);
479             gfxpage_t* page = doc->getpage(doc, t);
480             page->render(page, out);
481             page->destroy(page);
482             break;
483         }
484         free(filename);
485     }
486 }
487
488 int main()
489 {
490     test0();
491 }