f293d164750cca21ac19d8cc3a9dc0c6eaf389d5
[swftools.git] / lib / gfxpoly / convert.c
1 #include <stdlib.h>
2 #include <math.h>
3 #include <string.h>
4 #include "../gfxdevice.h"
5 #include "../mem.h"
6 #include "poly.h"
7
8 static edge_t*edge_new(int x1, int y1, int x2, int y2)
9 {
10     edge_t*s = rfx_calloc(sizeof(edge_t));
11     s->a.x = x1;
12     s->a.y = y1;
13     s->b.x = x2;
14     s->b.y = y2;
15     return s;
16 }
17
18 static inline void gfxpoly_add_edge(gfxpoly_t*poly, double _x1, double _y1, double _x2, double _y2)
19 {
20     int x1 = ceil(_x1);
21     int y1 = ceil(_y1);
22     int x2 = ceil(_x2);
23     int y2 = ceil(_y2);
24     if(x1!=x2 || y1!=y2) {
25         edge_t*s = edge_new(x1, y1, x2, y2);
26         s->next = poly->edges;
27         poly->edges = s;
28     }
29 }
30
31 gfxpoly_t* gfxpoly_from_gfxline(gfxline_t*line, double gridsize)
32 {
33     gfxpoly_t*p = gfxpoly_new(gridsize);
34
35     /* factor that determines into how many line fragments a spline is converted */
36     double subfraction = 2.4;//0.3
37
38     double z = 1.0 / gridsize;
39
40     double lastx=0, lasty=0;
41     assert(!line || line[0].type == gfx_moveTo);
42     while(line) {
43         double x = line->x*z;
44         double y = line->y*z;
45         if(line->type == gfx_moveTo) {
46         } else if(line->type == gfx_lineTo) {
47             gfxpoly_add_edge(p, lastx, lasty, x, y);
48         } else if(line->type == gfx_splineTo) {
49             int parts = (int)(sqrt(fabs(line->x-2*line->sx+lastx) + 
50                                    fabs(line->y-2*line->sy+lasty))*subfraction);
51             if(!parts) parts = 1;
52             double stepsize = 1.0/parts;
53             int i;
54             for(i=0;i<parts;i++) {
55                 double t = (double)i*stepsize;
56                 double sx = (line->x*t*t + 2*line->sx*t*(1-t) + x*(1-t)*(1-t))*z;
57                 double sy = (line->y*t*t + 2*line->sy*t*(1-t) + y*(1-t)*(1-t))*z;
58                 gfxpoly_add_edge(p, lastx, lasty, sx, sy);
59                 lastx = sx;
60                 lasty = sy;
61             }
62             gfxpoly_add_edge(p, lastx, lasty, x, y);
63         }
64         lastx = x;
65         lasty = y;
66         line = line->next;
67     }
68
69     gfxline_free(line);
70     return p;
71 }
72
73 static char* readline(FILE*fi)
74 {
75     char c;
76     while(1) {
77         int l = fread(&c, 1, 1, fi);
78         if(!l)
79             return 0;
80         if(c!=10 || c!=13)
81             break;
82     }
83     char line[256];
84     int pos = 0;
85     while(1) {
86         line[pos++] = c;
87         line[pos] = 0;
88         int l = fread(&c, 1, 1, fi);
89         if(!l || c==10 || c==13) {
90             return strdup(line);
91         }
92     }
93 }
94
95 gfxpoly_t* gfxpoly_from_file(const char*filename, double gridsize)
96 {
97     gfxpoly_t*p = gfxpoly_new(gridsize);
98
99     double z = 1.0 / gridsize;
100
101     FILE*fi = fopen(filename, "rb");
102     if(!fi) {
103         perror(filename);
104         return 0;
105     }
106     int count = 0;
107     double lastx=0,lasty=0;
108     while(1) {
109         char*line = readline(fi);
110         if(!line)
111             break;
112         double x,y;
113         char s[256];
114         if(sscanf(line, "%lf %lf %s", &x, &y, &s) == 3) {
115             x*=z;
116             y*=z;
117             if(s && !strcmp(s,"moveto")) {
118                 count++;
119             } else if(s && !strcmp(s,"lineto")) {
120                 gfxpoly_add_edge(p, lastx, lasty, x, y);
121                 count++;
122             } else {
123                 printf("invalid command: %s\n", s);
124             }
125             lastx = x;
126             lasty = y;
127         }
128         free(line);
129     }
130     fclose(fi);
131     printf("loaded %d points from %s\n", count, filename);
132     return p;
133 }