small changes to font handling
[swftools.git] / lib / devices / artsutils.c
1 #include <assert.h>
2 #include <math.h>
3
4 static ArtVpath* gfxline_to_ArtVpath(gfxline_t*line)
5 {
6     ArtVpath *vec = NULL;
7     int pos=0,len=0;
8     gfxline_t*l2;
9     double x=0,y=0;
10
11     /* factor which determines into how many line fragments a spline is converted */
12     double subfraction = 2.4;//0.3
13
14     l2 = line;
15     while(l2) {
16         if(l2->type == gfx_moveTo) {
17             pos ++;
18         } if(l2->type == gfx_lineTo) {
19             pos ++;
20         } if(l2->type == gfx_splineTo) {
21             int parts = (int)(sqrt(fabs(l2->x-2*l2->sx+x) + fabs(l2->y-2*l2->sy+y))*subfraction);
22             if(!parts) parts = 1;
23             pos += parts + 1;
24         }
25         x = l2->x;
26         y = l2->y;
27         l2 = l2->next;
28     }
29     pos++;
30     len = pos;
31
32     vec = art_new (ArtVpath, len+1);
33
34     pos = 0;
35     l2 = line;
36     while(l2) {
37         if(l2->type == gfx_moveTo) {
38             vec[pos].code = ART_MOVETO;
39             vec[pos].x = l2->x;
40             vec[pos].y = l2->y;
41             pos++; 
42             assert(pos<=len);
43         } else if(l2->type == gfx_lineTo) {
44             vec[pos].code = ART_LINETO;
45             vec[pos].x = l2->x;
46             vec[pos].y = l2->y;
47             pos++; 
48             assert(pos<=len);
49         } else if(l2->type == gfx_splineTo) {
50             int i;
51             int parts = (int)(sqrt(fabs(l2->x-2*l2->sx+x) + fabs(l2->y-2*l2->sy+y))*subfraction);
52             if(!parts) parts = 1;
53             for(i=0;i<=parts;i++) {
54                 double t = (double)i/(double)parts;
55                 vec[pos].code = ART_LINETO;
56                 vec[pos].x = l2->x*t*t + 2*l2->sx*t*(1-t) + x*(1-t)*(1-t);
57                 vec[pos].y = l2->y*t*t + 2*l2->sy*t*(1-t) + y*(1-t)*(1-t);
58                 pos++;
59                 assert(pos<=len);
60             }
61         }
62         x = l2->x;
63         y = l2->y;
64         l2 = l2->next;
65     }
66     vec[pos].code = ART_END;
67
68     return vec;
69 }
70
71 static void show_path(ArtSVP*path)
72 {
73     int t;
74     printf("Segments: %d\n", path->n_segs);
75     for(t=0;t<path->n_segs;t++) {
76         ArtSVPSeg* seg = &path->segs[t];
77         printf("Segment %d: %d points, %s, BBox: (%f,%f,%f,%f)\n", 
78                 t, seg->n_points, seg->dir==0?"UP  ":"DOWN",
79                 seg->bbox.x0, seg->bbox.y0, seg->bbox.x1, seg->bbox.y1);
80         int p;
81         for(p=0;p<seg->n_points;p++) {
82             ArtPoint* point = &seg->points[p];
83             printf("        (%f,%f)\n", point->x, point->y);
84         }
85     }
86     printf("\n");
87 }
88
89 static ArtSVP* gfxfillToSVP(gfxline_t*line, int perturb)
90 {
91     ArtVpath* vec = gfxline_to_ArtVpath(line);
92     if(perturb) {
93         ArtVpath* vec2 = art_vpath_perturb(vec);
94         free(vec);
95         vec = vec2;
96     }
97     ArtSVP *svp = art_svp_from_vpath(vec);
98     free(vec);
99     return svp;
100 }
101 static ArtSVP* boxToSVP(double x1, double y1,double x2, double y2)
102 {
103     ArtVpath *vec = art_new (ArtVpath, 5+1);
104     vec[0].code = ART_MOVETO;
105     vec[0].x = x1;
106     vec[0].y = y1;
107     vec[1].code = ART_LINETO;
108     vec[1].x = x1;
109     vec[1].y = y2;
110     vec[2].code = ART_LINETO;
111     vec[2].x = x2;
112     vec[2].y = y2;
113     vec[3].code = ART_LINETO;
114     vec[3].x = x2;
115     vec[3].y = y1;
116     vec[4].code = ART_LINETO;
117     vec[4].x = x1;
118     vec[4].y = y1;
119     vec[5].code = ART_END;
120     vec[5].x = 0;
121     vec[5].y = 0;
122     ArtSVP *svp = art_svp_from_vpath(vec);
123     free(vec);
124     return svp;
125 }
126
127 static ArtSVP* gfxstrokeToSVP(gfxline_t*line, gfxcoord_t width, gfx_capType cap_style, gfx_joinType joint_style, double miterLimit)
128 {
129     ArtVpath* vec = gfxline_to_ArtVpath(line);
130     ArtSVP *svp = art_svp_vpath_stroke (vec,
131                         (joint_style==gfx_joinMiter)?ART_PATH_STROKE_JOIN_MITER:
132                         ((joint_style==gfx_joinRound)?ART_PATH_STROKE_JOIN_ROUND:
133                          ((joint_style==gfx_joinBevel)?ART_PATH_STROKE_JOIN_BEVEL:ART_PATH_STROKE_JOIN_BEVEL)),
134                         (cap_style==gfx_capButt)?ART_PATH_STROKE_CAP_BUTT:
135                         ((cap_style==gfx_capRound)?ART_PATH_STROKE_CAP_ROUND:
136                          ((cap_style==gfx_capSquare)?ART_PATH_STROKE_CAP_SQUARE:ART_PATH_STROKE_CAP_SQUARE)),
137                         width, //line_width
138                         miterLimit, //miter_limit
139                         0.05 //flatness
140                         );
141     free(vec);
142     return svp;
143 }
144
145 static gfxline_t* SVPtogfxline(ArtSVP*svp)
146 {
147     int size = 0;
148     int t;
149     int pos = 0;
150     for(t=0;t<svp->n_segs;t++) {
151         size += svp->segs[t].n_points + 1;
152     }
153     gfxline_t* lines = (gfxline_t*)rfx_alloc(sizeof(gfxline_t)*size);
154
155     for(t=0;t<svp->n_segs;t++) {
156         ArtSVPSeg* seg = &svp->segs[t];
157         int p;
158         for(p=0;p<seg->n_points;p++) {
159             lines[pos].type = p==0?gfx_moveTo:gfx_lineTo;
160             ArtPoint* point = &seg->points[p];
161             lines[pos].x = point->x;
162             lines[pos].y = point->y;
163             lines[pos].next = &lines[pos+1];
164             pos++;
165         }
166     }
167     if(pos) {
168         lines[pos-1].next = 0;
169         return lines;
170     } else {
171         return 0;
172     }
173 }
174