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 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 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 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 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 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 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 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 298 SWFPlaceObject2Block_setRatio(SWFPlaceObject2Block block, int ratio) 299 { 300 block->ratio = ratio; 301 } 302 303 304 void 305 SWFPlaceObject2Block_setDepth(SWFPlaceObject2Block block, int depth) 306 { 307 block->depth = depth; 308 } 309 310 311 void 312 SWFPlaceObject2Block_setMaskLevel(SWFPlaceObject2Block block, int masklevel) 313 { 314 block->masklevel = masklevel; 315 } 316 317 318 void 319 SWFPlaceObject2Block_setCXform(SWFPlaceObject2Block block, SWFCXform cXform) 320 { 321 block->cXform = cXform; 322 } 323 324 325 void 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 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 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 358 SWFPlaceObject2Block_setCharacter(SWFPlaceObject2Block block, 359 SWFCharacter character) 360 { 361 block->character = character; 362 } 363 364 365 void 366 SWFPlaceObject2Block_setMove(SWFPlaceObject2Block block) 367 { 368 block->move = 1; 369 } 370 371 372 void 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 399 SWFPlaceObject2Block_setCacheFlag(SWFPlaceObject2Block block, int flag) 400 { 401 (void) flag; 402 setPlaceObjectVersion(block, 3); 403 block->hasCacheFlag = 1; 404 } 405 406 /* 407 * set blend mode. 408 * See ming.h for possible blend modes 409 * Only if SWF Version >= 8. Sets PlaceObject version to 3 410 */ 411 void 412 SWFPlaceObject2Block_setBlendMode(SWFPlaceObject2Block block, int mode) 413 { 414 if(mode < 0 || mode > 255) 415 { 416 SWF_warn("SWFPlaceObject2Block_setBlendMode: mode must be in between [0...255]"); 417 return; 418 } 419 420 setPlaceObjectVersion(block, 3); 421 block->hasBlendFlag = 1; 422 block->blendMode = mode; 423 } 424 425 426 /* 427 * add filter 428 * see ming.h for filtertypes 429 * Only if SWF Version >= 8. Sets PlaceObject version to 3 430 */ 431 void 432 SWFPlaceObject2Block_addFilter(SWFPlaceObject2Block block, SWFFilter filter) 433 { 434 if(block->filterList == NULL) 435 { 436 setPlaceObjectVersion(block, 3); 437 block->filterList = newSWFFilterList(); 438 block->hasFilterFlag = 1; 439 } 440 SWFFilterList_add(block->filterList, filter); 441 } 442 443 /* 444 * Local variables: 445 * tab-width: 2 446 * c-basic-offset: 2 447 * End: 448 */ 449