1 /*
2 Ming, an SWF output library
3 Copyright (C) 2002 Opaque Industries - http://www.opaque.net/
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 /* $Id$ */
21
22 #include <stdlib.h>
23
24 #include "libming.h"
25 #include "linestyle.h"
26 #include "fillstyle.h"
27 #include "error.h"
28
29 #define SWF_LINESTYLE_FLAG_FILL (1<<11)
30
31 struct SWFLineStyle_s
32 {
33 unsigned short width;
34 byte r;
35 byte g;
36 byte b;
37 byte a;
38
39 /* LINESTYLE2 extensions */
40 // 16 bit flags
41 int flags;
42 float miterLimit;
43 SWFFillStyle fill;
44 };
45
46
47 /*
48 * sets simple linestyle
49 * width is set in TWIPS
50 */
newSWFLineStyle(unsigned short width,byte r,byte g,byte b,byte a)51 SWFLineStyle newSWFLineStyle(unsigned short width,
52 byte r, byte g, byte b, byte a)
53 {
54 SWFLineStyle line = (SWFLineStyle)malloc(sizeof(struct SWFLineStyle_s));
55
56 line->width = width;
57 line->r = r;
58 line->g = g;
59 line->b = b;
60 line->a = a;
61 line->flags = 0;
62
63 return line;
64 }
65
66 /*
67 * create Linestyle2 introduce with SWF 8.
68 * Linestyle2 extends Linestyle1 with some extra flags:
69 *
70 * Line cap style: select one of the following flags (default is round cap style)
71 * SWF_LINESTYLE_CAP_ROUND
72 * SWF_LINESTYLE_CAP_NONE
73 * SWF_LINESTYLE_CAP_SQUARE
74 *
75 * Line join style: select one of the following flags (default is round join style)
76 * SWF_LINESTYLE_JOIN_ROUND
77 * SWF_LINESTYLE_JOIN_BEVEL
78 * SWF_LINESTYLE_JOIN_MITER
79 *
80 * Scaling flags: disable horizontal / vertical scaling
81 * SWF_LINESTYLE_FLAG_NOHSCALE
82 * SWF_LINESTYLE_FLAG_NOVSCALE
83 *
84 * Enable pixel hinting to correct blurry vertical / horizontal lines
85 * -> all anchors will be aligned to full pixels
86 * SWF_LINESTYLE_FLAG_HINTING
87 *
88 * Disable stroke closure: if no-close flag is set caps will be applied
89 * instead of joins
90 * SWF_LINESTYLE_FLAG_NOCLOSE
91 *
92 * End-cap style: default round
93 * SWF_LINESTYLE_FLAG_ENDCAP_ROUND
94 * SWF_LINESTYLE_FLAG_ENDCAP_NONE
95 * SWF_LINESTYLE_FLAG_ENDCAP_SQUARE
96 *
97 * If join style is SWF_LINESTYLE_JOIN_MITER a miter limit factor
98 * must be set. Miter max length is then calculated as:
99 * max miter len = miter limit * width.
100 * If join style is not miter, this value will be ignored.
101 */
newSWFLineStyle2(unsigned short width,byte r,byte g,byte b,byte a,int flags,float miterLimit)102 SWFLineStyle newSWFLineStyle2(unsigned short width, byte r, byte g, byte b, byte a,
103 int flags, float miterLimit)
104 {
105 SWFLineStyle line = (SWFLineStyle)malloc(sizeof(struct SWFLineStyle_s));
106
107 line->width = width;
108 line->r = r;
109 line->g = g;
110 line->b = b;
111 line->a = a;
112
113 line->flags = 0 | flags;
114 line->miterLimit = miterLimit;
115 line->fill = NULL;
116 return line;
117 }
118
119
120 /*
121 * create Linestyle2 introduce with SWF 8.
122 *
123 * Instead of providing a fill color, a FillStyle can be applied
124 * to a line.
125 *
126 * Linestyle2 also extends Linestyle1 with some extra flags:
127 *
128 * Line cap style: select one of the following flags (default is round cap style)
129 * SWF_LINESTYLE_CAP_ROUND
130 * SWF_LINESTYLE_CAP_NONE
131 * SWF_LINESTYLE_CAP_SQUARE
132 *
133 * Line join style: select one of the following flags (default is round join style)
134 * SWF_LINESTYLE_JOIN_ROUND
135 * SWF_LINESTYLE_JOIN_BEVEL
136 * SWF_LINESTYLE_JOIN_MITER
137 *
138 * Scaling flags: disable horizontal / vertical scaling
139 * SWF_LINESTYLE_FLAG_NOHSCALE
140 * SWF_LINESTYLE_FLAG_NOVSCALE
141 *
142 * Enable pixel hinting to correct blurry vertical / horizontal lines
143 * -> all anchors will be aligned to full pixels
144 * SWF_LINESTYLE_FLAG_HINTING
145 *
146 * Disable stroke closure: if no-close flag is set caps will be applied
147 * instead of joins
148 * SWF_LINESTYLE_FLAG_NOCLOSE
149 *
150 * End-cap style: default round
151 * SWF_LINESTYLE_FLAG_ENDCAP_ROUND
152 * SWF_LINESTYLE_FLAG_ENDCAP_NONE
153 * SWF_LINESTYLE_FLAG_ENDCAP_SQUARE
154 *
155 * If join style is SWF_LINESTYLE_JOIN_MITER a miter limit factor
156 * must be set. Miter max length is then calculated as:
157 * max miter len = miter limit * width.
158 * If join style is not miter, this value will be ignored.
159 */
newSWFLineStyle2_filled(unsigned short width,SWFFillStyle fill,int flags,float miterLimit)160 SWFLineStyle newSWFLineStyle2_filled(unsigned short width, SWFFillStyle fill,
161 int flags, float miterLimit)
162 {
163 SWFLineStyle line;
164
165 if(fill == NULL)
166 return NULL;
167
168 line = (SWFLineStyle)malloc(sizeof(struct SWFLineStyle_s));
169 line->width = width;
170 line->flags = SWF_LINESTYLE_FLAG_FILL | flags;
171 line->miterLimit = miterLimit;
172 line->fill = fill;
173 return line;
174 }
175
SWFLineStyle_equals(SWFLineStyle line,unsigned short width,byte r,byte g,byte b,byte a,int flags)176 byte SWFLineStyle_equals(SWFLineStyle line, unsigned short width,
177 byte r, byte g, byte b, byte a, int flags)
178 {
179 // if(line->width == 0 && width == 0)
180 // return TRUE;
181
182 if(line->width == width &&
183 line->r == r &&
184 line->g == g &&
185 line->b == b &&
186 line->a == a &&
187 line->flags == flags)
188 {
189 return TRUE;
190 }
191
192 return FALSE;
193 }
194
SWFLineStyle_equals2filled(SWFLineStyle line,unsigned short width,SWFFillStyle fill,int flags)195 byte SWFLineStyle_equals2filled(SWFLineStyle line, unsigned short width,
196 SWFFillStyle fill, int flags)
197 {
198 if(line->width == width &&
199 line->flags == flags &&
200 SWFFillStyle_equals(line->fill, fill))
201 {
202 return TRUE;
203 }
204 return FALSE;
205 }
206
207
SWFLineStyle_getWidth(SWFLineStyle line)208 unsigned short SWFLineStyle_getWidth(SWFLineStyle line)
209 {
210 return line->width;
211 }
212
213
writeLineStyle1(SWFOutput out,SWFLineStyle line,int shapeType)214 static inline void writeLineStyle1(SWFOutput out, SWFLineStyle line, int shapeType)
215 {
216 SWFOutput_writeUInt16(out, line->width);
217 SWFOutput_writeUInt8(out, line->r);
218 SWFOutput_writeUInt8(out, line->g);
219 SWFOutput_writeUInt8(out, line->b);
220
221 if(shapeType >= SWF_DEFINESHAPE3)
222 SWFOutput_writeUInt8(out, line->a);
223 }
224
writeLineStyle2(SWFOutput out,SWFLineStyle line,SWFBlocktype shapeType,SWFRect bounds)225 static inline void writeLineStyle2(SWFOutput out, SWFLineStyle line, SWFBlocktype shapeType, SWFRect bounds)
226 {
227 SWFOutput_writeUInt16(out, line->width);
228 SWFOutput_writeUInt8(out, (line->flags >> 8));
229 SWFOutput_writeUInt8(out, line->flags);
230 if(line->flags & SWF_LINESTYLE_JOIN_MITER)
231 SWFOutput_writeFixed8(out, line->miterLimit);
232 if(line->flags & SWF_LINESTYLE_FLAG_FILL)
233 SWFOutput_writeFillStyle(out, line->fill, shapeType, bounds);
234 else
235 {
236 SWFOutput_writeUInt8(out, line->r);
237 SWFOutput_writeUInt8(out, line->g);
238 SWFOutput_writeUInt8(out, line->b);
239 SWFOutput_writeUInt8(out, line->a);
240 }
241 }
242
SWFOutput_writeLineStyles(SWFOutput out,SWFLineStyle * lines,int nLines,SWFBlocktype shapeType,SWFRect bounds)243 void SWFOutput_writeLineStyles(SWFOutput out,
244 SWFLineStyle *lines, int nLines,
245 SWFBlocktype shapeType,
246 SWFRect bounds)
247 {
248 SWFLineStyle line;
249 int i;
250
251 if(nLines<255)
252 SWFOutput_writeUInt8(out, nLines);
253 else
254 {
255 SWFOutput_writeUInt8(out, 255);
256 SWFOutput_writeUInt16(out, nLines);
257 }
258
259 for(i=0; i<nLines; ++i)
260 {
261 line = lines[i];
262 if(shapeType == SWF_DEFINESHAPE4)
263 writeLineStyle2(out, line, shapeType, bounds);
264 else
265 writeLineStyle1(out, line, shapeType);
266 }
267 }
268
269
SWFOutput_writeMorphLineStyles2(SWFOutput out,SWFLineStyle * lines1,int nLines1,SWFLineStyle * lines2,int nLines2)270 void SWFOutput_writeMorphLineStyles2(SWFOutput out,
271 SWFLineStyle *lines1, int nLines1,
272 SWFLineStyle *lines2, int nLines2)
273 {
274 SWFLineStyle line1, line2;
275 int i;
276
277 SWF_assert(nLines1 == nLines2);
278
279 if(nLines1<255)
280 SWFOutput_writeUInt8(out, nLines1);
281 else
282 {
283 SWFOutput_writeUInt8(out, 255);
284 SWFOutput_writeUInt16(out, nLines1);
285 }
286
287 for(i=0; i<nLines1; ++i)
288 {
289 line1 = lines1[i];
290 line2 = lines2[i];
291
292 SWFOutput_writeUInt16(out, line1->width);
293 SWFOutput_writeUInt16(out, line2->width);
294
295 if(line1->flags != line2->flags)
296 SWF_warnOnce("Morph: shapes _must_ us equal line flags\n");
297 SWFOutput_writeUInt8(out, (line1->flags >> 8));
298 SWFOutput_writeUInt8(out, line1->flags);
299
300 if(line1->flags & SWF_LINESTYLE_JOIN_MITER)
301 SWFOutput_writeFixed8(out, line1->miterLimit);
302 if(line1->flags & SWF_LINESTYLE_FLAG_FILL)
303 SWFOutput_writeMorphFillStyle(out, line1->fill, NULL, line2->fill, NULL);
304 else
305 {
306
307 SWFOutput_writeUInt8(out, line1->r);
308 SWFOutput_writeUInt8(out, line1->g);
309 SWFOutput_writeUInt8(out, line1->b);
310 SWFOutput_writeUInt8(out, line1->a);
311 SWFOutput_writeUInt8(out, line2->r);
312 SWFOutput_writeUInt8(out, line2->g);
313 SWFOutput_writeUInt8(out, line2->b);
314 SWFOutput_writeUInt8(out, line2->a);
315 }
316 }
317 }
318
319
SWFOutput_writeMorphLineStyles(SWFOutput out,SWFLineStyle * lines1,int nLines1,SWFLineStyle * lines2,int nLines2)320 void SWFOutput_writeMorphLineStyles(SWFOutput out,
321 SWFLineStyle *lines1, int nLines1,
322 SWFLineStyle *lines2, int nLines2)
323 {
324 SWFLineStyle line1, line2;
325 int i;
326
327 SWF_assert(nLines1 == nLines2);
328
329 if(nLines1<255)
330 SWFOutput_writeUInt8(out, nLines1);
331 else
332 {
333 SWFOutput_writeUInt8(out, 255);
334 SWFOutput_writeUInt16(out, nLines1);
335 }
336
337 for(i=0; i<nLines1; ++i)
338 {
339 line1 = lines1[i];
340 line2 = lines2[i];
341
342 SWFOutput_writeUInt16(out, line1->width);
343 SWFOutput_writeUInt16(out, line2->width);
344 SWFOutput_writeUInt8(out, line1->r);
345 SWFOutput_writeUInt8(out, line1->g);
346 SWFOutput_writeUInt8(out, line1->b);
347 SWFOutput_writeUInt8(out, line1->a);
348 SWFOutput_writeUInt8(out, line2->r);
349 SWFOutput_writeUInt8(out, line2->g);
350 SWFOutput_writeUInt8(out, line2->b);
351 SWFOutput_writeUInt8(out, line2->a);
352 }
353 }
354
355
356 /*
357 * Local variables:
358 * tab-width: 2
359 * c-basic-offset: 2
360 * End:
361 */
362