improved intersector horizontal line support
[swftools.git] / lib / gfxpoly / convert.c
1 #include <stdlib.h>
2 #include <math.h>
3 #include <assert.h>
4 #include "../gfxdevice.h"
5 #include "poly.h"
6
7 static edge_t*edge_new(int x1, int y1, int x2, int y2)
8 {
9     edge_t*s = malloc(sizeof(edge_t));
10     s->a.x = x1;
11     s->a.y = y1;
12     s->b.x = x2;
13     s->b.y = y2;
14     s->next = 0;
15     return s;
16 }
17
18 static inline void gfxpoly_add_edge(edge_t**list, 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 = *list;
27         *list = s;
28     }
29 }
30
31 gfxpoly_t* gfxpoly_fillToPoly(gfxline_t*line)
32 {
33     edge_t*s = 0;
34
35     /* factor that determines into how many line fragments a spline is converted */
36     double subfraction = 2.4;//0.3
37
38     double lastx=0, lasty=0;
39     assert(!line || line[0].type == gfx_moveTo);
40     while(line) {
41         if(line->type == gfx_moveTo) {
42         } else if(line->type == gfx_lineTo) {
43             gfxpoly_add_edge(&s, lastx, lasty, line->x, line->y);
44         } else if(line->type == gfx_splineTo) {
45             int parts = (int)(sqrt(fabs(line->x-2*line->sx+lastx) + 
46                                    fabs(line->y-2*line->sy+lasty))*subfraction);
47             if(!parts) parts = 1;
48             double stepsize = 1.0/parts;
49             int i;
50             for(i=0;i<parts;i++) {
51                 double t = (double)i*stepsize;
52                 double x = line->x*t*t + 2*line->sx*t*(1-t) + x*(1-t)*(1-t);
53                 double y = line->y*t*t + 2*line->sy*t*(1-t) + y*(1-t)*(1-t);
54                 gfxpoly_add_edge(&s, lastx, lasty, x, y);
55                 lastx = x;
56                 lasty = y;
57             }
58             gfxpoly_add_edge(&s, lastx, lasty, line->x, line->y);
59         }
60         lastx = line->x;
61         lasty = line->y;
62         line = line->next;
63     }
64
65     gfxline_free(line);
66     return s;
67 }
68