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