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