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 #ifndef __C2MAN__
23 #include <stdlib.h>
24 #include <string.h>
25 #endif
26 
27 #include "placeobject.h"
28 #include "method.h"
29 #include "block.h"
30 #include "output.h"
31 #include "browserfont.h"
32 #include "outputblock.h"
33 #include "character.h"
34 #include "matrix.h"
35 #include "cxform.h"
36 #include "filter.h"
37 #include "action.h"
38 
39 #include "libming.h"
40 
41 struct SWFPlaceObject2Block_s
42 {
43 	struct SWFBlock_s block;
44 
45 	SWFOutput out;
46 
47 	// PlaceObject - version
48 	// default is 2
49 	// 3 if with SWF_versiom >= 8 and V3 extensions were used
50 	int version;
51 
52 	SWFCharacter character;
53 	SWFMatrix matrix;
54 	SWFCXform cXform;
55 	int ratio;
56 	int masklevel;
57 	char *name;
58 	int depth;
59 	int move;
60 
61 	int nActions;
62 	int actionORFlags;
63 	SWFAction *actions;
64 	int *actionFlags;
65 //	char *actionChars;
66 
67 	// V3 extension SWF_version >= 8
68 	char hasCacheFlag;
69 	char hasBlendFlag;
70 	char hasFilterFlag;
71 
72 	SWFFilterList filterList;
73 	int blendMode;
74 
75 #if TRACK_ALLOCS
76 	mem_node *gcnode;
77 #endif
78 };
79 
80 
writeActions(SWFPlaceObject2Block place)81 static void writeActions(SWFPlaceObject2Block place)
82 {
83 	int i;
84 	SWFBlock block = BLOCK(place);
85 
86 	if ( place->nActions > 0 )
87 	{
88 		SWFOutput_writeUInt16(place->out, 0);
89 
90 		if(block->swfVersion >= 6)
91 			SWFOutput_writeUInt32(place->out, place->actionORFlags);
92 		else
93 			SWFOutput_writeUInt16(place->out, place->actionORFlags);
94 
95 		for ( i=0; i<place->nActions; ++i )
96 		{
97 			int length;
98 			SWFAction_compile(place->actions[i], block->swfVersion, &length);
99 			if(block->swfVersion >= 6)
100 				SWFOutput_writeUInt32(place->out, place->actionFlags[i]);
101 			else
102 				SWFOutput_writeUInt16(place->out, place->actionFlags[i]);
103 
104 			// SWF6: extra char if(place->actionFlags[i] & 0x20000)
105 			if((block->swfVersion >= 6) && (place->actionFlags[i] & 0x20000)) {
106 				SWFOutput_writeUInt32(place->out, length + 1);
107 				SWFOutput_writeUInt8(place->out, 0);
108 			}
109 			else
110 				SWFOutput_writeUInt32(place->out, length);
111 
112 			SWFOutput_writeAction(place->out, place->actions[i]);
113 		}
114 
115 		/* trailing 0 for end of actions */
116 		if(block->swfVersion >= 6)
117 			SWFOutput_writeUInt32(place->out, 0);
118 		else
119 			SWFOutput_writeUInt16(place->out, 0);
120 	}
121 }
122 
123 void
writeSWFPlaceObject2BlockToStream(SWFBlock block,SWFByteOutputMethod method,void * data)124 writeSWFPlaceObject2BlockToStream(SWFBlock block, SWFByteOutputMethod method, void *data)
125 {
126 	SWFPlaceObject2Block place = (SWFPlaceObject2Block)block;
127 	SWFOutput_writeToMethod(place->out, method, data);
128 }
129 
130 
131 int
completeSWFPlaceObject2Block(SWFBlock block)132 completeSWFPlaceObject2Block(SWFBlock block)
133 {
134 	SWFPlaceObject2Block place = (SWFPlaceObject2Block)block;
135 	SWFOutput out = newSizedSWFOutput(42);
136 
137 	int flags =
138 		((place->name != NULL)			? SWF_PLACE_HAS_NAME : 0) |
139 		((place->ratio != -1)				? SWF_PLACE_HAS_RATIO : 0) |
140 		((place->masklevel != -1)		? SWF_PLACE_HAS_MASK : 0) |
141 		((place->cXform != NULL)		? SWF_PLACE_HAS_CXFORM : 0) |
142 		((place->matrix != NULL)		? SWF_PLACE_HAS_MATRIX : 0) |
143 		((place->character != NULL) ? SWF_PLACE_HAS_CHARACTER : 0) |
144 		((place->move != 0)					? SWF_PLACE_MOVE : 0) |
145 		((place->nActions != 0)			? SWF_PLACE_HAS_ACTIONS : 0);
146 
147 	SWFOutput_writeUInt8(out, flags);
148 	if(place->version == 3)
149 	{
150 		flags = 0;
151 		if(place->hasCacheFlag) flags |= SWF_PLACE_CACHE;
152 		if(place->hasBlendFlag) flags |= SWF_PLACE_HAS_BLEND;
153 		if(place->hasFilterFlag) flags |= SWF_PLACE_HAS_FILTER;
154 		SWFOutput_writeUInt8(out, flags);
155 	}
156 	SWFOutput_writeUInt16(out, place->depth);
157 
158 	if ( place->character != NULL )
159 		SWFOutput_writeUInt16(out, CHARACTERID(place->character));
160 
161 	if ( place->matrix != NULL )
162 		SWFOutput_writeMatrix(out, place->matrix);
163 
164 	if ( place->cXform != NULL )
165 		SWFOutput_writeCXform(out, place->cXform, SWF_PLACEOBJECT2);
166 
167 	if ( place->ratio != -1 )
168 		SWFOutput_writeUInt16(out, place->ratio);
169 
170 	if ( place->name != NULL )
171 		SWFOutput_writeString(out, (byte*)place->name);
172 
173 	if ( place->masklevel != -1 )
174 		SWFOutput_writeUInt16(out, place->masklevel);
175 
176 	if( place->version == 3 && place->hasFilterFlag)
177 		SWFOutput_writeFilterList(out, place->filterList);
178 
179 	if( place->version == 3 && place->hasBlendFlag)
180 		SWFOutput_writeUInt8(out, place->blendMode);
181 
182 	place->out = out;
183 	writeActions(place);
184 
185 	return SWFOutput_getLength(out);
186 }
187 
188 
189 void
destroySWFPlaceObject2Block(SWFPlaceObject2Block place)190 destroySWFPlaceObject2Block(SWFPlaceObject2Block place)
191 {
192 	if ( place->actions != NULL )
193 		free(place->actions);
194 
195 	if ( place->actionFlags != NULL )
196 //	{	free(place->actionChars);
197 		free(place->actionFlags);
198 //	}
199 
200 	if( place->filterList != NULL )
201 		destroySWFFilterList(place->filterList);
202 
203 	if ( place->name != NULL )
204 		free(place->name);
205 
206 	if ( place->out != NULL )
207 		destroySWFOutput(place->out);
208 
209 	if ( place->matrix != NULL )
210 		destroySWFMatrix(place->matrix);
211 
212 	if ( place->cXform != NULL )
213 		destroySWFCXform(place->cXform);
214 
215 #if TRACK_ALLOCS
216 	ming_gc_remove_node(place->gcnode);
217 #endif
218 
219 	free(place);
220 }
221 
222 
223 static inline void
setPlaceObjectVersion(SWFPlaceObject2Block block,int version)224 setPlaceObjectVersion(SWFPlaceObject2Block block, int version)
225 {
226 	switch(version)
227 	{
228 		case 2:
229 			block->version = version;
230 			BLOCK(block)->type = SWF_PLACEOBJECT2;
231 			break;
232 		case 3:
233 			block->version = version;
234 			BLOCK(block)->type = SWF_PLACEOBJECT3;
235 			break;
236 		default:
237 			SWF_error("setPlaceObjectVersion: invalid version %i\n",
238                                   version);
239 	}
240 }
241 
242 SWFPlaceObject2Block
newSWFPlaceObject2Block(int depth)243 newSWFPlaceObject2Block(int depth)
244 {
245 	SWFPlaceObject2Block place = (SWFPlaceObject2Block)malloc(sizeof(struct SWFPlaceObject2Block_s));
246 
247 	/* If malloc failed, return NULL to signify this */
248 	if (NULL == place)
249 		return NULL;
250 
251 	SWFBlockInit((SWFBlock)place);
252 
253 	BLOCK(place)->type = SWF_PLACEOBJECT2;
254 	BLOCK(place)->writeBlock = writeSWFPlaceObject2BlockToStream;
255 	BLOCK(place)->complete = completeSWFPlaceObject2Block;
256 	BLOCK(place)->dtor = (destroySWFBlockMethod) destroySWFPlaceObject2Block;
257 
258 	place->version = 2;
259 	place->out = NULL;
260 	place->name = NULL;
261 
262 	place->move = 0;
263 	place->matrix = NULL;
264 	place->cXform = NULL;
265 	place->character = NULL;
266 	place->masklevel = -1;
267 	place->ratio = -1;
268 	place->depth = depth;
269 
270 	place->nActions = 0;
271 	place->actionORFlags = 0;
272 	place->actionFlags = NULL;
273 //	place->actionChars = NULL;
274 	place->actions = NULL;
275 
276 	place->hasCacheFlag = 0;
277 	place->hasBlendFlag = 0;
278 	place->hasFilterFlag = 0;
279 	place->filterList = NULL;
280 #if TRACK_ALLOCS
281 	place->gcnode = ming_gc_add_node(place, (dtorfunctype) destroySWFPlaceObject2Block);
282 #endif
283 	return place;
284 }
285 
286 
287 void
SWFPlaceObject2Block_setName(SWFPlaceObject2Block block,const char * name)288 SWFPlaceObject2Block_setName(SWFPlaceObject2Block block, const char *name)
289 {
290 	if ( block->name != NULL )
291 		free(block->name);
292 
293 	block->name = strdup(name);
294 }
295 
296 
297 void
SWFPlaceObject2Block_setRatio(SWFPlaceObject2Block block,int ratio)298 SWFPlaceObject2Block_setRatio(SWFPlaceObject2Block block, int ratio)
299 {
300 	block->ratio = ratio;
301 }
302 
303 
304 void
SWFPlaceObject2Block_setDepth(SWFPlaceObject2Block block,int depth)305 SWFPlaceObject2Block_setDepth(SWFPlaceObject2Block block, int depth)
306 {
307 	block->depth = depth;
308 }
309 
310 
311 void
SWFPlaceObject2Block_setMaskLevel(SWFPlaceObject2Block block,int masklevel)312 SWFPlaceObject2Block_setMaskLevel(SWFPlaceObject2Block block, int masklevel)
313 {
314 	block->masklevel = masklevel;
315 }
316 
317 
318 void
SWFPlaceObject2Block_setCXform(SWFPlaceObject2Block block,SWFCXform cXform)319 SWFPlaceObject2Block_setCXform(SWFPlaceObject2Block block, SWFCXform cXform)
320 {
321 	block->cXform = cXform;
322 }
323 
324 
325 void
SWFPlaceObject2Block_setColorAdd(SWFPlaceObject2Block block,int r,int g,int b,int a)326 SWFPlaceObject2Block_setColorAdd(SWFPlaceObject2Block block,
327 																 int r, int g, int b, int a)
328 {
329 	if ( block->cXform == NULL )
330 		block->cXform = newSWFAddCXform(r, g, b, a);
331 	else
332 		SWFCXform_setColorAdd(block->cXform, r, g, b, a);
333 }
334 
335 
336 void
SWFPlaceObject2Block_setColorMult(SWFPlaceObject2Block block,float r,float g,float b,float a)337 SWFPlaceObject2Block_setColorMult(SWFPlaceObject2Block block,
338 																	float r, float g, float b, float a)
339 {
340 	if ( block->cXform == NULL )
341 		block->cXform = newSWFMultCXform(r, g, b, a);
342 	else
343 		SWFCXform_setColorMult(block->cXform, r, g, b, a);
344 }
345 
346 
347 void
SWFPlaceObject2Block_setMatrix(SWFPlaceObject2Block block,SWFMatrix matrix)348 SWFPlaceObject2Block_setMatrix(SWFPlaceObject2Block block, SWFMatrix matrix)
349 {
350 	if ( block->matrix != NULL )
351 		free(block->matrix);
352 
353 	block->matrix = SWFMatrix_dup(matrix);
354 }
355 
356 
357 void
SWFPlaceObject2Block_setCharacter(SWFPlaceObject2Block block,SWFCharacter character)358 SWFPlaceObject2Block_setCharacter(SWFPlaceObject2Block block,
359 																	SWFCharacter character)
360 {
361 	block->character = character;
362 }
363 
364 
365 void
SWFPlaceObject2Block_setMove(SWFPlaceObject2Block block)366 SWFPlaceObject2Block_setMove(SWFPlaceObject2Block block)
367 {
368 	block->move = 1;
369 }
370 
371 
372 void
SWFPlaceObject2Block_addAction(SWFPlaceObject2Block block,SWFAction action,int flags)373 SWFPlaceObject2Block_addAction(SWFPlaceObject2Block block,
374 															 SWFAction action, int flags)
375 {
376 	block->actions =
377 		(SWFAction*)realloc(block->actions, (block->nActions+1) * sizeof(SWFAction));
378 
379 	block->actionFlags =
380 		(int*)realloc(block->actionFlags, (block->nActions+1) * sizeof(int));
381 
382 //	block->actionChars =
383 //		realloc(block->actionChars, (block->nActions+1));
384 
385 	block->actions[block->nActions] = action;
386 	block->actionFlags[block->nActions] = flags;
387 //	block->actionChars[block->nActions] = actChar;
388 	block->actionORFlags |= flags;
389 
390 	++block->nActions;
391 }
392 
393 
394 /*
395  * set Cache as BitmapFlag
396  * Only if SWF Version >= 8. Sets PlaceObject version to 3
397  */
398 void
SWFPlaceObject2Block_setCacheFlag(SWFPlaceObject2Block block,int flag)399 SWFPlaceObject2Block_setCacheFlag(SWFPlaceObject2Block block, int flag)
400 {
401 	setPlaceObjectVersion(block, 3);
402 	block->hasCacheFlag = 1;
403 }
404 
405 /*
406  * set blend mode.
407  * See ming.h for possible blend modes
408  * Only if SWF Version >= 8. Sets PlaceObject version to 3
409  */
410 void
SWFPlaceObject2Block_setBlendMode(SWFPlaceObject2Block block,int mode)411 SWFPlaceObject2Block_setBlendMode(SWFPlaceObject2Block block, int mode)
412 {
413 	if(mode < 0 || mode > 255)
414 	{
415 		SWF_warn("SWFPlaceObject2Block_setBlendMode: mode must be in between [0...255]");
416 		return;
417 	}
418 
419 	setPlaceObjectVersion(block, 3);
420 	block->hasBlendFlag = 1;
421 	block->blendMode = mode;
422 }
423 
424 
425 /*
426  * add filter
427  * see ming.h for filtertypes
428  * Only if SWF Version >= 8. Sets PlaceObject version to 3
429  */
430 void
SWFPlaceObject2Block_addFilter(SWFPlaceObject2Block block,SWFFilter filter)431 SWFPlaceObject2Block_addFilter(SWFPlaceObject2Block block, SWFFilter filter)
432 {
433 	if(block->filterList == NULL)
434 	{
435 		setPlaceObjectVersion(block, 3);
436 		block->filterList = newSWFFilterList();
437 		block->hasFilterFlag = 1;
438 	}
439 	SWFFilterList_add(block->filterList, filter);
440 }
441 
442 /*
443  * Local variables:
444  * tab-width: 2
445  * c-basic-offset: 2
446  * End:
447  */
448