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