started rewriting polygon conversion functions
[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 static windcontext_t onepolygon = {1};
120
121 int test0()
122 {
123     gfxline_t* b = mkchessboard();
124
125     gfxmatrix_t m;
126     memset(&m, 0, sizeof(gfxmatrix_t));
127     int t;
128     for(t=0;t<360;t++) {
129     m.m00 = cos(t*M_PI/180.0);
130     m.m01 = sin(t*M_PI/180.0);
131     m.m10 = -sin(t*M_PI/180.0);
132     m.m11 = cos(t*M_PI/180.0);
133     m.tx = 400*1.41/2;
134     m.ty = 400*1.41/2;
135     gfxline_transform(b, &m);
136
137     gfxpoly_t*poly = gfxpoly_from_gfxline(b, 0.05);
138     gfxline_free(b);
139     gfxpoly_t*poly2 = gfxpoly_process(poly, &windrule_evenodd, &onepolygon);
140     gfxpoly_destroy(poly2);
141     gfxpoly_destroy(poly);
142 }
143 }
144
145 int test1(int argn, char*argv[])
146 {
147     gfxline_t*box1 = gfxline_makerectangle(50,50,150,150);
148     // put box2 and box3 on top of each other *snicker*
149     gfxline_t*box2 = gfxline_makerectangle(100,100,200,200);
150     gfxline_t*box3 = gfxline_makerectangle(100,100,200,200);
151     gfxline_t*star = mkstar(50,50, 150,150);
152     gfxline_t*b = 0;
153     b = gfxline_append(b, box1);
154     b = gfxline_append(b, box2);
155     b = gfxline_append(b, box3);
156     //b = gfxline_append(b, star);
157
158     gfxmatrix_t matrix;
159     memset(&matrix, 0, sizeof(gfxmatrix_t));
160     double ua=0.1;
161     matrix.m00=cos(ua);matrix.m10=sin(ua);
162     matrix.m01=-sin(ua);matrix.m11=cos(ua);
163
164     //gfxline_transform(b, &matrix);
165
166     gfxpoly_t*poly = gfxpoly_from_gfxline(b, 0.05);
167     gfxline_free(box1);
168     gfxline_free(box2);
169     gfxline_free(box3);
170     gfxline_free(star);
171
172     gfxpoly_dump(poly);
173     gfxpoly_t*poly2 = gfxpoly_process(poly, &windrule_evenodd, &onepolygon);
174     gfxpoly_destroy(poly2);
175     gfxpoly_destroy(poly);
176 }
177
178 int test_square(int width, int height, int num, double gridsize, char bitmaptest)
179 {
180     int t;
181     gfxline_t* line = malloc(sizeof(gfxline_t)*num);
182     for(t=0;t<num;t++) {
183         line[t].type = t?gfx_lineTo:gfx_moveTo;
184         line[t].x = (lrand48()%width);
185         line[t].y = (lrand48()%height);
186         line[t].next = &line[t+1];
187     }
188     line[num-1].x = line[0].x;
189     line[num-1].y = line[0].y;
190     line[num-1].next = 0;
191     
192     gfxpoly_t*poly = gfxpoly_from_gfxline(line, gridsize);
193     gfxline_free(line);
194
195     windrule_t*rule = &windrule_circular;
196     gfxpoly_t*poly2 = gfxpoly_process(poly, rule, &onepolygon);
197     if(bitmaptest) {
198         intbbox_t bbox = intbbox_new(0, 0, width, height);
199         unsigned char*bitmap1 = render_polygon(poly, &bbox, 1.0, rule, &onepolygon);
200         unsigned char*bitmap2 = render_polygon(poly2, &bbox, 1.0, &windrule_evenodd, &onepolygon);
201         if(!compare_bitmaps(&bbox, bitmap1, bitmap2)) {
202             save_two_bitmaps(&bbox, bitmap1, bitmap2, "error.png");
203             assert(!"bitmaps don't match");
204         }
205     }
206     gfxpoly_destroy(poly2);
207     gfxpoly_destroy(poly);
208 }
209
210 int test2(int argn, char*argv[])
211 {
212     test_square(400,400, 3, 0.05, 1);
213
214     int t;
215     for(t=0;t<400;t++) {
216         test_square(400,400, 50, 0.05, 1);
217         test_square(200,3, 1000, 1.0, 0);
218         test_square(3,200, 1000, 1.0, 0);
219         test_square(10,10, 200, 1.0, 0);
220     }
221 }
222
223 #include "../rfxswf.h"
224 void test3(int argn, char*argv[])
225 {
226 #undef N
227 #undef RANGE
228 #define N 100
229 #define RANGE 400
230
231     //gfxline_t*line = mkrandomshape(RANGE, N);
232     //windrule_t*rule = &windrule_circular;
233     gfxline_t*line = mkchessboard();
234     //windrule_t*rule = &windrule_evenodd;
235     windrule_t*rule = &windrule_circular;
236
237     gfxmatrix_t m;
238     memset(&m, 0, sizeof(m));
239
240     SWF swf;
241     memset(&swf, 0, sizeof(SWF));
242     swf.movieSize.xmax = RANGE*20*1.41;
243     swf.movieSize.ymax = RANGE*20*1.41;
244     swf.fileVersion = 9;
245     swf.frameRate = 25*0x100;
246     TAG * tag = swf.firstTag = swf_InsertTag(0, ST_SETBACKGROUNDCOLOR);
247     swf_SetU8(tag, 0);
248     swf_SetU8(tag, 0);
249     swf_SetU8(tag, 0);
250
251     int t;
252     for(t=0;t<360;t++) {
253         m.m00 = cos(t*M_PI/180.0);
254         m.m01 = sin(t*M_PI/180.0);
255         m.m10 = -sin(t*M_PI/180.0);
256         m.m11 = cos(t*M_PI/180.0);
257         m.tx = RANGE*1.41/2;
258         m.ty = RANGE*1.41/2;
259
260         gfxline_t*l = gfxline_clone(line);
261         gfxline_transform(l, &m);
262         
263         gfxpoly_t*poly = gfxpoly_from_gfxline(l, 0.05);
264         gfxpoly_t*poly2 = gfxpoly_process(poly, rule, &onepolygon);
265
266         tag = swf_InsertTag(tag, ST_DEFINESHAPE);
267         SHAPE* s;
268         swf_ShapeNew(&s);
269         RGBA rgb;
270         rgb.r = rgb.g = 0x00; rgb.b = 0xff;
271         rgb.a = 255;
272         int fs = swf_ShapeAddSolidFillStyle(s,&rgb);
273         int ls = swf_ShapeAddLineStyle(s,20,&rgb);
274         swf_SetU16(tag,t+1);
275         swf_SetRect(tag,&swf.movieSize);
276         swf_SetShapeHeader(tag,s);
277
278 #define FILL
279 #ifdef FILL
280         swf_ShapeSetAll(tag,s,0,0,0,fs,0);
281         edge_t*e = poly2->edges;
282         while(e) {
283 #define ROTATE
284 #ifdef ROTATE
285             swf_ShapeSetMove(tag, s, e->a.y, e->a.x);
286             swf_ShapeSetLine(tag, s, e->b.y - e->a.y, e->b.x - e->a.x);
287 #else
288             swf_ShapeSetMove(tag, s, e->a.x, e->a.y);
289             swf_ShapeSetLine(tag, s, e->b.x - e->a.x, e->b.y - e->a.y);
290 #endif
291             e = e->next;
292         }
293 #else
294         swf_ShapeSetAll(tag,s,0,0,ls,0,0);
295         edge_t*e = poly2->edges;
296         while(e) {
297             swf_ShapeSetMove(tag, s, e->a.x, e->a.y);
298             swf_ShapeSetLine(tag, s, e->b.x - e->a.x, e->b.y - e->a.y);
299             
300             swf_ShapeSetCircle(tag, s, e->a.x, e->a.y, 5*20, 5*20);
301             swf_ShapeSetCircle(tag, s, e->b.x, e->b.y, 5*20, 5*20);
302             e = e->next;
303         }
304 #endif
305
306         swf_ShapeSetEnd(tag);
307         swf_ShapeFree(s);
308
309         gfxpoly_destroy(poly);
310         gfxpoly_destroy(poly2);
311
312         gfxline_free(l);
313    
314         if(t) {
315             tag = swf_InsertTag(tag,ST_REMOVEOBJECT2);
316             swf_SetU16(tag, t);
317         }
318         tag = swf_InsertTag(tag,ST_PLACEOBJECT2);
319         swf_ObjectPlace(tag,t+1,t+1,NULL,NULL,NULL);
320
321         tag = swf_InsertTag(tag, ST_SHOWFRAME);
322     }
323     tag = swf_InsertTag(tag, ST_END);
324
325     swf_SaveSWF(&swf, "test.swf");
326 }
327
328 void rotate90(gfxpoly_t*poly)
329 {
330     edge_t*e = poly->edges;
331     while(e) {
332         point_t a = e->a;
333         point_t b = e->b;
334         e->a.x = a.y;
335         e->a.y = a.x;
336         e->b.x = b.y;
337         e->b.y = b.x;
338         e = e->next;
339     }
340 }
341
342 #include <dirent.h>
343 void test4(int argn, char*argv[])
344 {
345     char*dir = "ps";
346     DIR*_dir = opendir(dir);
347     if(!_dir) return;
348     struct dirent*file;
349     while(1) {
350         file = readdir(_dir);
351         if (!file) 
352             break;
353         if(!strstr(file->d_name, ".ps")) 
354             continue;
355
356         char* filename;
357
358         if(argn<2)
359             filename = allocprintf("%s/%s", dir, file->d_name);
360         else
361             filename = argv[1];
362
363         windrule_t*rule = &windrule_evenodd;
364         gfxpoly_t*poly = gfxpoly_from_file(filename, 1.0);//0.01);
365
366         if(argn!=2)
367             free(filename);
368
369         double zoom = 1.0;
370
371         if(!gfxpoly_check(poly)) {
372             printf("bad polygon\n");
373             continue;
374         }
375
376         gfxpoly_t*poly2 = gfxpoly_process(poly, rule, &onepolygon);
377
378         int pass;
379         for(pass=0;pass<2;pass++) {
380             intbbox_t bbox = intbbox_from_polygon(poly, zoom);
381             unsigned char*bitmap1 = render_polygon(poly, &bbox, zoom, rule, &onepolygon);
382             unsigned char*bitmap2 = render_polygon(poly2, &bbox, zoom, &windrule_evenodd, &onepolygon);
383             if(!bitmap_ok(&bbox, bitmap1) || !bitmap_ok(&bbox, bitmap2)) {
384                 save_two_bitmaps(&bbox, bitmap1, bitmap2, "error.png");
385                 assert(!"error in bitmaps");
386             }
387             if(!compare_bitmaps(&bbox, bitmap1, bitmap2)) {
388                 save_two_bitmaps(&bbox, bitmap1, bitmap2, "error.png");
389                 assert(!"bitmaps don't match");
390             }
391             free(bitmap1);
392             free(bitmap2);
393             
394             // second pass renders the 90° rotated version
395             rotate90(poly);
396             rotate90(poly2);
397         }
398
399         gfxpoly_destroy(poly);
400         gfxpoly_destroy(poly2);
401         if(argn==2) 
402             break;
403     }
404     closedir(_dir);
405 }
406
407 #include "../gfxdevice.h"
408 #include "../pdf/pdf.h"
409
410 void extract_polygons_fill(gfxdevice_t*dev, gfxline_t*line, gfxcolor_t*color) 
411 {
412     gfxcompactpoly_t*c = gfxcompactpoly_from_gfxline(line, 0.05);
413     gfxcompactpoly_free(c);
414     gfxpoly_t*poly = gfxpoly_from_gfxline(line, 0.05);
415     if(gfxpoly_size(poly)>100000) {
416         printf("%d segments (skipping)\n", gfxpoly_size(poly));
417         return;
418     } else {
419         printf("%d segments\n", gfxpoly_size(poly));
420     }
421
422     if(!gfxpoly_check(poly)) {
423         gfxpoly_destroy(poly);
424         printf("bad polygon\n");
425         return;
426     }
427
428     windrule_t*rule = &windrule_evenodd;
429         
430     double zoom = 1.0;
431     intbbox_t bbox = intbbox_from_polygon(poly, zoom);
432     unsigned char*bitmap1 = render_polygon(poly, &bbox, zoom, rule, &onepolygon);
433     if(!bitmap_ok(&bbox, bitmap1)) {
434         printf("bad polygon or error in renderer\n");
435         return;
436     }
437     gfxpoly_t*poly2 = gfxpoly_process(poly, rule, &onepolygon);
438     unsigned char*bitmap2 = render_polygon(poly2, &bbox, zoom, &windrule_evenodd, &onepolygon);
439     if(!bitmap_ok(&bbox, bitmap2)) {
440         save_two_bitmaps(&bbox, bitmap1, bitmap2, "error.png");
441         assert(!"error in bitmap");
442     }
443     if(!compare_bitmaps(&bbox, bitmap1, bitmap2)) {
444         save_two_bitmaps(&bbox, bitmap1, bitmap2, "error.png");
445         assert(!"bitmaps don't match");
446     }
447     free(bitmap1);
448     free(bitmap2);
449
450     gfxpoly_destroy(poly);
451     gfxpoly_destroy(poly2);
452 }
453 int extract_polygons_setparameter(gfxdevice_t*dev, const char*key, const char*value) {
454     return 0;
455 }
456 void extract_polygons_startclip(gfxdevice_t*dev, gfxline_t*line) 
457 {
458     extract_polygons_fill(dev, line, 0);
459 }
460 void extract_polygons_fillbitmap(gfxdevice_t*dev, gfxline_t*line, gfximage_t*img, gfxmatrix_t*imgcoord2devcoord, gfxcxform_t*cxform)
461 {
462     extract_polygons_fill(dev, line, 0);
463 }
464 void extract_polygons_fillgradient(gfxdevice_t*dev, gfxline_t*line, gfxgradient_t*gradient, gfxgradienttype_t type, gfxmatrix_t*gradcoord2devcoord)
465 {
466     extract_polygons_fill(dev, line, 0);
467 }
468 void extract_polygons_drawlink(gfxdevice_t*dev, gfxline_t*line, const char*action)
469 {
470     extract_polygons_fill(dev, line, 0);
471 }
472 void extract_polygons_addfont(gfxdevice_t*dev, gfxfont_t*font)
473 {
474     int t;
475     for(t=0;t<font->num_glyphs;t++) {
476         //extract_polygons_fill(dev, font->glyphs[t].line, 0);
477     }
478 }
479 void extract_polygons_endclip(gfxdevice_t*dev)
480 {
481 }
482 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)
483 {
484 }
485 void extract_polygons_drawchar(gfxdevice_t*dev, gfxfont_t*font, int glyph, gfxcolor_t*color, gfxmatrix_t*matrix)
486 {
487 }
488     
489 gfxdevice_t extract_polygons = 
490 {
491 name: "extract polygons",
492 setparameter:extract_polygons_setparameter,
493 startclip: extract_polygons_startclip,
494 endclip: extract_polygons_endclip,
495 stroke: extract_polygons_stroke,
496 fill: extract_polygons_fill,
497 fillbitmap: extract_polygons_fillbitmap,
498 fillgradient: extract_polygons_fillgradient,
499 addfont: extract_polygons_addfont,
500 drawchar: extract_polygons_drawchar,
501 drawlink: extract_polygons_drawlink,
502 startpage: 0,
503 endpage: 0,
504 geterror: 0,
505 finish: 0,
506 internal: 0
507 };
508
509 void test5(int argn, char*argv[])
510 {
511     gfxsource_t*driver = gfxsource_pdf_create();
512     char*dir = "pdfs";
513     DIR*_dir = opendir(dir);
514     if(!_dir) return;
515     struct dirent*file;
516     while(1) {
517         file = readdir(_dir);
518         if (!file) 
519             break;
520         if(!strstr(file->d_name, ".pdf")) 
521             continue;
522         char* filename = allocprintf("%s/%s", dir, file->d_name);
523
524         gfxdocument_t*doc = driver->open(driver, filename);
525         gfxdevice_t*out = &extract_polygons;
526         int t;
527         for(t=1;t<=doc->num_pages;t++) {
528             printf("%s (page %d)\n", filename, t);
529             gfxpage_t* page = doc->getpage(doc, t);
530             page->render(page, out);
531             page->destroy(page);
532         }
533         doc->destroy(doc);
534         free(filename);
535     }
536     closedir(_dir);
537     driver->destroy(driver);
538 }
539
540 int main(int argn, char*argv[])
541 {
542     test5(argn, argv);
543 }