/* Ming, an SWF output library Copyright (C) 2001 Opaque Industries - http://www.opaque.net/ This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include #include "movie.h" #include "shape_util.h" #include "ming.h" static void destroySWFExports(SWFMovie movie) { int n; for(n=0; nnExports; ++n) free(movie->exports[n].name); free(movie->exports); movie->exports = 0; movie->nExports = 0; } void destroySWFMovie(SWFMovie movie) { destroySWFBlockList(movie->blockList); destroySWFDisplayList(movie->displayList); destroySWFRect(movie->bounds); if(movie->nExports > 0) destroySWFExports(movie); free(movie); } extern int SWF_gNumCharacters; SWFMovie newSWFMovieWithVersion(int version) { SWFMovie movie = calloc(1, SWFMOVIE_SIZE); movie->version = version; movie->blockList = newSWFBlockList(); movie->displayList = newSWFDisplayList(); movie->bounds = newSWFRect(0, 320*20, 0, 240*20); movie->rate = 12.0; movie->totalFrames = 1; movie->nExports = 0; movie->exports = NULL; SWFMovie_addBlock(movie, newSWFSetBackgroundBlock(0xff,0xff,0xff)); return movie; } SWFMovie newSWFMovie() { return newSWFMovieWithVersion(SWF_versionNum); } void SWFMovie_setRate(SWFMovie movie, float rate) { movie->rate = rate; } extern float Ming_scale; void SWFMovie_setDimension(SWFMovie movie, float width, float height) { if(movie->bounds) free(movie->bounds); movie->bounds = newSWFRect(0, (int)rint(Ming_scale*width), 0, (int)rint(Ming_scale*height)); } void SWFMovie_setNumberOfFrames(SWFMovie movie, int totalFrames) { movie->totalFrames = totalFrames; } void SWFMovie_setBackground(SWFMovie movie, int r, int g, int b) { destroySWFBlock(movie->blockList->blocks[0].block); movie->blockList->blocks[0].block = newSWFSetBackgroundBlock(r,g,b); } void SWFMovie_addBlock(SWFMovie movie, SWFBlock block) { if(SWFBlock_getType(block) == SWF_SHOWFRAME) ++movie->nFrames; SWFBlockList_addBlock(movie->blockList, block); } void SWFMovie_addExport(SWFMovie movie, SWFBlock block, char *name) { if(SWFBlock_getType(block) == SWF_DEFINESPRITE) { movie->exports = realloc(movie->exports, (movie->nExports+1) * sizeof(struct swfexport)); movie->exports[movie->nExports].block = block; movie->exports[movie->nExports].name = strdup(name); ++movie->nExports; } } /* from displaylist.c */ void resolveDependencies(SWFCharacter character, SWFBlockList list); void SWFMovie_writeExports(SWFMovie movie) { int n; if(movie->nExports == 0) return; for(n=0 ; nnExports ; ++n) { SWFBlock b = movie->exports[n].block; if(!SWFBlock_isDefined(b)) { resolveDependencies(b, movie->blockList); completeSWFBlock(b); SWFMovie_addBlock(movie, b); } } SWFMovie_addBlock(movie, newSWFExportBlock(movie->exports, movie->nExports)); destroySWFExports(movie); } SWFDisplayItem SWFMovie_add(SWFMovie movie, SWFBlock block) { if(block == NULL) return NULL; /* if they're trying to add a raw bitmap, we'll be nice and turn it into a shape */ if(SWFBlock_getType(block) == SWF_DEFINEBITS || SWFBlock_getType(block) == SWF_DEFINEBITSJPEG2 || SWFBlock_getType(block) == SWF_DEFINEBITSJPEG3 || SWFBlock_getType(block) == SWF_DEFINELOSSLESS || SWFBlock_getType(block) == SWF_DEFINELOSSLESS2) { SWFShape shape = newSWFShape(); SWFFill fill = SWFShape_addBitmapFill(shape, block, SWFFILL_TILED_BITMAP); float width = SWFCharacter_getWidth((SWFCharacter)block); float height = SWFCharacter_getHeight((SWFCharacter)block); SWFShape_setRightFill(shape, fill); /* bitmap's bounds aren't scaled, so drawCharacterBounds won't work */ SWFShape_drawLine(shape, Ming_scale*width, 0); SWFShape_drawLine(shape, 0, Ming_scale*height); SWFShape_drawLine(shape, -Ming_scale*width, 0); SWFShape_drawLine(shape, 0, -Ming_scale*height); block = (SWFBlock)shape; } if(SWFBlock_isCharacter(block)) { return SWFDisplayList_add(movie->displayList, (SWFCharacter)block); } else SWFMovie_addBlock(movie, block); return NULL; } void SWFMovie_remove(SWFMovie movie, SWFDisplayItem item) { SWFDisplayItem_remove(item); } void SWFMovie_setSoundStream(SWFMovie movie, SWFSound sound) { SWFBlock block = SWFSound_getStreamHead(sound, movie->rate); if(block != NULL) { SWFMovie_addBlock(movie, block); SWFDisplayList_setSoundStream(movie->displayList, sound); } } void SWFMovie_nextFrame(SWFMovie movie) { SWFDisplayList_writeBlocks(movie->displayList, movie->blockList); SWFMovie_addBlock(movie, newSWFShowFrameBlock()); } void SWFMovie_labelFrame(SWFMovie movie, char *label) { SWFMovie_addBlock(movie, newSWFFrameLabelBlock(label)); } int SWFMovie_output(SWFMovie movie, SWFByteOutputMethod method, void *data) { int length; SWFOutput header; if(movie->nExports > 0) SWFMovie_writeExports(movie); while(movie->nFrames < movie->totalFrames) SWFMovie_nextFrame(movie); SWFMovie_addBlock(movie, newSWFEndBlock()); length = SWFBlockList_completeBlocks(movie->blockList); /* XXX - hack */ if(movie->displayList->soundStream) SWFSound_rewind(movie->displayList->soundStream); header = newSizedSWFOutput(20); /* figure size, write header */ SWFOutput_writeRect(header, movie->bounds); SWFOutput_writeUInt16(header, (int)floor(movie->rate*256)); SWFOutput_writeUInt16(header, movie->nFrames); SWFOutput_byteAlign(header); length += 8 + SWFOutput_length(header); method('F', data); method('W', data); method('S', data); method(movie->version, data); methodWriteUInt32(length, method, data); SWFOutput_writeToMethod(header, method, data); destroySWFOutput(header); SWFBlockList_writeBlocksToMethod(movie->blockList, method, data); return length; }