1 // swfdraw.c
2
3 #include "../rfxswf.h"
4
5 typedef struct _SWFSHAPEDRAWER
6 {
7 SHAPE*shape;
8 TAG*tag;
9 int tagfree;
10 SCOORD firstx;
11 SCOORD firsty;
12 SCOORD lastx;
13 SCOORD lasty;
14 SRECT bbox;
15 char isfinished;
16 } SWFSHAPEDRAWER;
17
18 static void swf_ShapeDrawerSetLineStyle(drawer_t*draw, void*style);
19 static void swf_ShapeDrawerSetFillStyle(drawer_t*draw, void*style);
20 static void swf_ShapeDrawerMoveTo(drawer_t*draw, FPOINT * to);
21 static void swf_ShapeDrawerLineTo(drawer_t*draw, FPOINT * to);
22 static void swf_ShapeDrawerSplineTo(drawer_t*draw, FPOINT * c1, FPOINT* to);
23 static void swf_ShapeDrawerFinish(drawer_t*draw);
24 static void swf_ShapeDrawerClear(drawer_t*draw);
25
swf_ShapeDrawerInit(drawer_t * draw,TAG * tag,int fillstylebits,int linestylebits)26 static void swf_ShapeDrawerInit(drawer_t*draw, TAG*tag, int fillstylebits, int linestylebits)
27 {
28 SWFSHAPEDRAWER*sdraw = (SWFSHAPEDRAWER*)rfx_calloc(sizeof(SWFSHAPEDRAWER));
29 draw->internal = sdraw;
30
31 draw->setLineStyle = swf_ShapeDrawerSetLineStyle;
32 draw->setFillStyle = swf_ShapeDrawerSetFillStyle;
33 draw->moveTo = swf_ShapeDrawerMoveTo;
34 draw->lineTo = swf_ShapeDrawerLineTo;
35 draw->splineTo = swf_ShapeDrawerSplineTo;
36 draw->finish = swf_ShapeDrawerFinish;
37 draw->dealloc = swf_ShapeDrawerClear;
38
39 sdraw->tagfree = 0;
40 if(tag == 0) {
41 tag = swf_InsertTag(0, ST_DEFINESHAPE);
42 sdraw->tagfree = 1;
43 }
44 sdraw->tag = tag;
45 swf_ShapeNew(&sdraw->shape);
46 draw->pos.x = 0;
47 draw->pos.y = 0;
48
49 swf_SetU8(sdraw->tag,0);
50 sdraw->shape->bits.fill = fillstylebits;
51 sdraw->shape->bits.line = linestylebits;
52
53 sdraw->bbox.xmin = sdraw->bbox.ymin = SCOORD_MAX;
54 sdraw->bbox.xmax = sdraw->bbox.ymax = SCOORD_MIN;
55
56 sdraw->isfinished = 0;
57
58 swf_ShapeSetStyle(sdraw->tag,sdraw->shape,linestylebits?1:0,fillstylebits?1:0,0/*?*/);
59 }
60
swf_Shape10DrawerInit(drawer_t * draw,TAG * tag)61 void swf_Shape10DrawerInit(drawer_t*draw, TAG*tag)
62 {
63 swf_ShapeDrawerInit(draw, tag, 0, 1);
64 }
65
swf_Shape01DrawerInit(drawer_t * draw,TAG * tag)66 void swf_Shape01DrawerInit(drawer_t*draw, TAG*tag)
67 {
68 swf_ShapeDrawerInit(draw, tag, 1, 0);
69 }
70
swf_Shape11DrawerInit(drawer_t * draw,TAG * tag)71 void swf_Shape11DrawerInit(drawer_t*draw, TAG*tag)
72 {
73 swf_ShapeDrawerInit(draw, tag, 1, 1);
74 }
75
swf_ShapeDrawerSetLineStyle(drawer_t * draw,void * style)76 static void swf_ShapeDrawerSetLineStyle(drawer_t*draw, void*style)
77 {
78 SWFSHAPEDRAWER*sdraw = (SWFSHAPEDRAWER*)draw->internal;
79 }
swf_ShapeDrawerSetFillStyle(drawer_t * draw,void * style)80 static void swf_ShapeDrawerSetFillStyle(drawer_t*draw, void*style)
81 {
82 SWFSHAPEDRAWER*sdraw = (SWFSHAPEDRAWER*)draw->internal;
83 }
fixEndPoint(drawer_t * draw)84 static void fixEndPoint(drawer_t*draw)
85 {
86 SWFSHAPEDRAWER*sdraw = (SWFSHAPEDRAWER*)draw->internal;
87 if( sdraw->firstx != sdraw->lastx
88 || sdraw->firsty != sdraw->lasty) {
89 /* fix non-closing shapes */
90 FPOINT to;
91 to.x = sdraw->firstx/20.0;
92 to.y = sdraw->firsty/20.0;
93 if(sdraw->shape->bits.fill) // do this only if the shape is filled
94 draw->lineTo(draw, &to);
95 }
96 }
swf_ShapeDrawerMoveTo(drawer_t * draw,FPOINT * to)97 static void swf_ShapeDrawerMoveTo(drawer_t*draw, FPOINT * to)
98 {
99 SWFSHAPEDRAWER*sdraw = (SWFSHAPEDRAWER*)draw->internal;
100 int x = floor(to->x*20);
101 int y = floor(to->y*20);
102
103 /* Flash will ignore a moveto (0,0) in glyphs. Hence, we map
104 all (0,0)s to (0.05,0)s in moveto,lineto and splineto. */
105
106 if(!x&&!y)
107 x++;
108
109 /* we need to write moveto always- it
110 might be that it signals the end of a polygon, otherwise
111 we would end up connecting two polygons which should
112 be seperate
113 TODO: check if the last operation was a moveTo- if
114 yes we *can* skip it.
115 */
116
117 //if(sdraw->lastx != x || sdraw->lasty != y) {
118 fixEndPoint(draw);
119 swf_ShapeSetMove(sdraw->tag,sdraw->shape,x,y);
120 sdraw->firstx = sdraw->lastx = x;
121 sdraw->firsty = sdraw->lasty = y;
122 draw->pos = *to;
123 //}
124 }
swf_ShapeDrawerLineTo(drawer_t * draw,FPOINT * to)125 static void swf_ShapeDrawerLineTo(drawer_t*draw, FPOINT * to)
126 {
127 SWFSHAPEDRAWER*sdraw = (SWFSHAPEDRAWER*)draw->internal;
128 int x = floor(to->x*20);
129 int y = floor(to->y*20);
130 if(!x&&!y)
131 x++;
132 if(sdraw->lastx < sdraw->bbox.xmin) sdraw->bbox.xmin = sdraw->lastx;
133 if(sdraw->lasty < sdraw->bbox.ymin) sdraw->bbox.ymin = sdraw->lasty;
134 if(sdraw->lastx > sdraw->bbox.xmax) sdraw->bbox.xmax = sdraw->lastx;
135 if(sdraw->lasty > sdraw->bbox.ymax) sdraw->bbox.ymax = sdraw->lasty;
136 if(x < sdraw->bbox.xmin) sdraw->bbox.xmin = x;
137 if(y < sdraw->bbox.ymin) sdraw->bbox.ymin = y;
138 if(x > sdraw->bbox.xmax) sdraw->bbox.xmax = x;
139 if(y > sdraw->bbox.ymax) sdraw->bbox.ymax = y;
140 swf_ShapeSetLine(sdraw->tag,sdraw->shape,x-sdraw->lastx,y-sdraw->lasty);
141 sdraw->lastx = x;
142 sdraw->lasty = y;
143 draw->pos = *to;
144 }
swf_ShapeDrawerSplineTo(drawer_t * draw,FPOINT * c1,FPOINT * to)145 static void swf_ShapeDrawerSplineTo(drawer_t*draw, FPOINT * c1, FPOINT* to)
146 {
147 SWFSHAPEDRAWER*sdraw = (SWFSHAPEDRAWER*)draw->internal;
148 int tx = floor(c1->x*20);
149 int ty = floor(c1->y*20);
150 int x = floor(to->x*20);
151 int y = floor(to->y*20);
152 if(!x&&!y)
153 x++;
154 if(sdraw->lastx < sdraw->bbox.xmin) sdraw->bbox.xmin = sdraw->lastx;
155 if(sdraw->lasty < sdraw->bbox.ymin) sdraw->bbox.ymin = sdraw->lasty;
156 if(sdraw->lastx > sdraw->bbox.xmax) sdraw->bbox.xmax = sdraw->lastx;
157 if(sdraw->lasty > sdraw->bbox.ymax) sdraw->bbox.ymax = sdraw->lasty;
158 if(x < sdraw->bbox.xmin) sdraw->bbox.xmin = x;
159 if(y < sdraw->bbox.ymin) sdraw->bbox.ymin = y;
160 if(x > sdraw->bbox.xmax) sdraw->bbox.xmax = x;
161 if(y > sdraw->bbox.ymax) sdraw->bbox.ymax = y;
162 if(tx < sdraw->bbox.xmin) sdraw->bbox.xmin = tx;
163 if(ty < sdraw->bbox.ymin) sdraw->bbox.ymin = ty;
164 if(tx > sdraw->bbox.xmax) sdraw->bbox.xmax = tx;
165 if(ty > sdraw->bbox.ymax) sdraw->bbox.ymax = ty;
166 swf_ShapeSetCurve(sdraw->tag,sdraw->shape, tx-sdraw->lastx,ty-sdraw->lasty, x-tx,y-ty);
167 sdraw->lastx = x;
168 sdraw->lasty = y;
169 draw->pos = *to;
170 }
swf_ShapeDrawerFinish(drawer_t * draw)171 static void swf_ShapeDrawerFinish(drawer_t*draw)
172 {
173 SWFSHAPEDRAWER*sdraw = (SWFSHAPEDRAWER*)draw->internal;
174 if(sdraw->isfinished)
175 return;
176
177 fixEndPoint(draw);
178
179 if(sdraw->bbox.xmin == SCOORD_MAX) {
180 /* no points at all -> empty bounding box */
181 sdraw->bbox.xmin = sdraw->bbox.ymin =
182 sdraw->bbox.xmax = sdraw->bbox.ymax = 0;
183 }
184 sdraw->isfinished = 1;
185 swf_ShapeSetEnd(sdraw->tag);
186 }
187
swf_ShapeDrawerClear(drawer_t * draw)188 static void swf_ShapeDrawerClear(drawer_t*draw)
189 {
190 SWFSHAPEDRAWER*sdraw = (SWFSHAPEDRAWER*)draw->internal;
191 if(sdraw->tagfree) {
192 swf_DeleteTag(0, sdraw->tag);
193 sdraw->tag = 0;
194 }
195 swf_ShapeFree(sdraw->shape);
196 sdraw->shape = 0;
197
198 rfx_free(draw->internal);
199 draw->internal = 0;
200 }
201
swf_ShapeDrawerGetBBox(drawer_t * draw)202 SRECT swf_ShapeDrawerGetBBox(drawer_t*draw)
203 {
204 SWFSHAPEDRAWER*sdraw = (SWFSHAPEDRAWER*)draw->internal;
205 return sdraw->bbox;
206 }
207
swf_ShapeDrawerToShape(drawer_t * draw)208 SHAPE* swf_ShapeDrawerToShape(drawer_t*draw)
209 {
210 SWFSHAPEDRAWER*sdraw = (SWFSHAPEDRAWER*)draw->internal;
211 SHAPE* shape = (SHAPE*)rfx_alloc(sizeof(SHAPE));
212 if(!sdraw->isfinished) {
213 fprintf(stderr, "Warning: you should Finish() your drawer before calling DrawerToShape");
214 swf_ShapeDrawerFinish(draw);
215 }
216 memcpy(shape, sdraw->shape, sizeof(SHAPE));
217 shape->bitlen = (sdraw->tag->len-1)*8;
218 shape->data = (U8*)rfx_alloc(sdraw->tag->len-1);
219 memcpy(shape->data, &sdraw->tag->data[1], sdraw->tag->len-1);
220 return shape;
221 }
222