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 #include <stdio.h>
24 #include "blocktypes.h"
25 #include "output.h"
26 #include "matrix.h"
27 #include "fillstyle.h"
28 #include "error.h"
29 #include "gradient.h"
30 #include "character.h"
31 #include "libming.h"
32
33 struct SWFFillStyle_s
34 {
35 byte type;
36 SWFMatrix matrix;
37 union
38 {
39 struct
40 {
41 byte r;
42 byte g;
43 byte b;
44 byte a;
45 } solid;
46
47 SWFBitmap bitmap;
48 SWFGradient gradient;
49
50 } data;
51 };
52
53
destroySWFFillStyle(SWFFillStyle fill)54 void destroySWFFillStyle(SWFFillStyle fill)
55 {
56 if(fill->matrix != NULL)
57 destroySWFMatrix(fill->matrix);
58 free(fill);
59 }
60
SWFFillStyle_addDependency(SWFFillStyle fill,SWFCharacter c)61 void SWFFillStyle_addDependency(SWFFillStyle fill, SWFCharacter c)
62 {
63 if( (fill->type & SWFFILL_BITMAP) && fill->data.bitmap)
64 SWFCharacter_addDependency(c, (SWFCharacter)fill->data.bitmap);
65 }
66
67 SWFFillStyle
newSWFSolidFillStyle(byte r,byte g,byte b,byte a)68 newSWFSolidFillStyle(byte r, byte g, byte b, byte a)
69 {
70 SWFFillStyle fill = (SWFFillStyle)malloc(sizeof(struct SWFFillStyle_s));
71
72 /* If malloc failed, return NULL to signify this */
73 if (NULL == fill)
74 return NULL;
75
76 fill->type = SWFFILL_SOLID;
77 fill->data.solid.r = r;
78 fill->data.solid.g = g;
79 fill->data.solid.b = b;
80 fill->data.solid.a = a;
81 fill->matrix = NULL; /* make purify shut up */
82
83 return fill;
84 }
85
86
87 SWFFillStyle
newSWFGradientFillStyle(SWFGradient gradient,byte flags)88 newSWFGradientFillStyle(SWFGradient gradient, byte flags)
89 {
90 SWFFillStyle fill = (SWFFillStyle) malloc(sizeof(struct SWFFillStyle_s));
91
92 /* If malloc failed, return NULL to signify this */
93 if (NULL == fill)
94 return NULL;
95
96 if ( flags == SWFFILL_RADIAL_GRADIENT )
97 fill->type = SWFFILL_RADIAL_GRADIENT;
98 else if(SWFGradient_isFocalGradient(gradient))
99 fill->type = SWFFILL_FOCAL_GRADIENT;
100 else
101 fill->type = SWFFILL_LINEAR_GRADIENT;
102
103 fill->data.gradient = gradient;
104 fill->matrix = newSWFMatrix(1.0, 0, 0, 1.0, 0, 0);
105
106 /* If newSWFMatrix() failed, return NULL to signify this */
107 if (NULL == fill->matrix)
108 {
109 free(fill);
110 return NULL;
111 }
112
113 return fill;
114 }
115
116
117 SWFFillStyle
newSWFBitmapFillStyle(SWFBitmap bitmap,byte flags)118 newSWFBitmapFillStyle(SWFBitmap bitmap, byte flags)
119 {
120 SWFFillStyle fill = (SWFFillStyle) malloc(sizeof(struct SWFFillStyle_s));
121
122 /* If malloc failed, return NULL to signify this */
123 if (NULL == fill)
124 return NULL;
125
126 switch(flags)
127 {
128 case SWFFILL_CLIPPED_BITMAP:
129 case SWFFILL_TILED_BITMAP:
130 case SWFFILL_NONSMOOTHED_TILED_BITMAP:
131 case SWFFILL_NONSMOOTHED_CLIPPED_BITMAP:
132 fill->type = flags;
133 break;
134 default:
135 free(fill);
136 SWF_warn("newSWFBitmapFillStyle: not a valid Bitmap FillStyle: %x\n", flags);
137 return NULL;
138 }
139
140 fill->data.bitmap = bitmap;
141 fill->matrix = newSWFMatrix(Ming_scale, 0, 0, Ming_scale, 0, 0);
142 if (fill->matrix == NULL)
143 {
144 free(fill);
145 return NULL;
146 }
147 return fill;
148 }
149
150 SWFMatrix
SWFFillStyle_getMatrix(SWFFillStyle fill)151 SWFFillStyle_getMatrix(SWFFillStyle fill)
152 {
153 return fill->matrix;
154 }
155
156
157 int
SWFFillStyle_equals(SWFFillStyle fill1,SWFFillStyle fill2)158 SWFFillStyle_equals(SWFFillStyle fill1, SWFFillStyle fill2)
159 {
160 if ( fill1->type != fill2->type )
161 return 0;
162
163 switch ( fill1->type )
164 {
165 case SWFFILL_SOLID:
166 return (fill1->data.solid.r == fill2->data.solid.r &&
167 fill1->data.solid.g == fill2->data.solid.g &&
168 fill1->data.solid.b == fill2->data.solid.b &&
169 fill1->data.solid.a == fill2->data.solid.a);
170
171 case SWFFILL_LINEAR_GRADIENT:
172 case SWFFILL_RADIAL_GRADIENT:
173 case SWFFILL_FOCAL_GRADIENT:
174 return (fill1->data.gradient == fill2->data.gradient);
175
176 case SWFFILL_TILED_BITMAP:
177 case SWFFILL_CLIPPED_BITMAP:
178 case SWFFILL_NONSMOOTHED_TILED_BITMAP:
179 case SWFFILL_NONSMOOTHED_CLIPPED_BITMAP:
180 return (fill1->data.bitmap == fill2->data.bitmap);
181
182 default:
183 SWF_error("Unknown fill type");
184 }
185
186 return 0;
187 }
188
189 void
SWFOutput_writeFillStyle(SWFOutput out,SWFFillStyle fill,SWFBlocktype shapeType,SWFRect bounds)190 SWFOutput_writeFillStyle(SWFOutput out, SWFFillStyle fill,
191 SWFBlocktype shapeType, SWFRect bounds)
192 {
193 int type = fill->type;
194 SWFOutput_writeUInt8(out, type);
195
196 if ( type == SWFFILL_SOLID )
197 {
198 SWFOutput_writeUInt8(out, fill->data.solid.r);
199 SWFOutput_writeUInt8(out, fill->data.solid.g);
200 SWFOutput_writeUInt8(out, fill->data.solid.b);
201
202 if ( shapeType >= SWF_DEFINESHAPE3 )
203 SWFOutput_writeUInt8(out, fill->data.solid.a);
204 }
205 else if ( type & SWFFILL_GRADIENT )
206 {
207 SWFGradientMatrix_update(fill->matrix, bounds);
208 SWFOutput_writeMatrix(out, fill->matrix);
209 SWFOutput_writeGradient(out, fill->data.gradient, shapeType);
210 }
211 else if ( type & SWFFILL_BITMAP )
212 {
213 SWFOutput_writeUInt16(out, fill->data.bitmap ?
214 CHARACTERID(fill->data.bitmap) :
215 65535); /* magic number */
216 SWFOutput_writeMatrix(out, fill->matrix);
217 }
218 else
219 SWF_error("Unknown fill type: %i", type);
220 }
221
222 void
SWFOutput_writeFillStyles(SWFOutput out,SWFFillStyle * fills,int nFills,SWFBlocktype shapeType,SWFRect bounds)223 SWFOutput_writeFillStyles(SWFOutput out,
224 SWFFillStyle *fills, int nFills,
225 SWFBlocktype shapeType,
226 SWFRect bounds)
227 {
228 int i;
229
230 if ( nFills < 255 )
231 {
232 SWFOutput_writeUInt8(out, nFills);
233 }
234 else
235 {
236 SWFOutput_writeUInt8(out, 255);
237 SWFOutput_writeUInt16(out, nFills);
238 }
239
240 for ( i=0; i<nFills; ++i )
241 SWFOutput_writeFillStyle(out, fills[i], shapeType, bounds);
242 }
243
244
245 void
SWFOutput_writeMorphFillStyle(SWFOutput out,SWFFillStyle fill1,SWFRect bounds1,SWFFillStyle fill2,SWFRect bounds2)246 SWFOutput_writeMorphFillStyle(SWFOutput out, SWFFillStyle fill1, SWFRect bounds1,
247 SWFFillStyle fill2, SWFRect bounds2)
248 {
249 int type;
250 SWF_assert(fill1->type == fill2->type);
251 type = fill1->type;
252
253 SWFOutput_writeUInt8(out, type);
254
255 if ( type == SWFFILL_SOLID )
256 {
257 SWFOutput_writeUInt8(out, fill1->data.solid.r);
258 SWFOutput_writeUInt8(out, fill1->data.solid.g);
259 SWFOutput_writeUInt8(out, fill1->data.solid.b);
260 SWFOutput_writeUInt8(out, fill1->data.solid.a);
261 SWFOutput_writeUInt8(out, fill2->data.solid.r);
262 SWFOutput_writeUInt8(out, fill2->data.solid.g);
263 SWFOutput_writeUInt8(out, fill2->data.solid.b);
264 SWFOutput_writeUInt8(out, fill2->data.solid.a);
265 }
266 else if ( type & SWFFILL_GRADIENT )
267 {
268 SWFGradientMatrix_update(fill1->matrix, bounds1);
269 SWFOutput_writeMatrix(out, fill1->matrix);
270 SWFGradientMatrix_update(fill2->matrix, bounds2);
271 SWFOutput_writeMatrix(out, fill2->matrix);
272 SWFOutput_writeMorphGradient(out, fill1->data.gradient, fill2->data.gradient);
273 }
274 else if ( type & SWFFILL_BITMAP )
275 {
276 SWF_assert(CHARACTERID(fill1->data.bitmap) == CHARACTERID(fill2->data.bitmap));
277
278 SWFOutput_writeUInt16(out, CHARACTERID(fill1->data.bitmap));
279 SWFOutput_writeMatrix(out, fill1->matrix);
280 SWFOutput_writeMatrix(out, fill2->matrix);
281 }
282 else
283 SWF_assert(0);
284
285 }
286
287 void
SWFOutput_writeMorphFillStyles(SWFOutput out,SWFFillStyle * fills1,int nFills1,SWFRect bounds1,SWFFillStyle * fills2,int nFills2,SWFRect bounds2)288 SWFOutput_writeMorphFillStyles(SWFOutput out,
289 SWFFillStyle *fills1, int nFills1, SWFRect bounds1,
290 SWFFillStyle *fills2, int nFills2, SWFRect bounds2)
291 {
292 int i;
293 SWF_assert(nFills1 == nFills2);
294 if ( nFills1 < 255 )
295 {
296 SWFOutput_writeUInt8(out, nFills1);
297 }
298 else
299 {
300 SWFOutput_writeUInt8(out, 255);
301 SWFOutput_writeUInt16(out, nFills1);
302 }
303
304 for ( i=0; i<nFills1; ++i )
305 SWFOutput_writeMorphFillStyle(out, fills1[i], bounds1,
306 fills2[i], bounds2);
307 }
308
309
310 /*
311 * Local variables:
312 * tab-width: 2
313 * c-basic-offset: 2
314 * End:
315 */
316