📄 fromswf.c
字号:
/* Ming, an SWF output library Copyright (C) 2002 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*//* $Id: fromswf.c,v 1.26 2008/02/24 17:38:52 krechert Exp $ */#include "ming_config.h"#include "libming.h"#include "fromswf.h"#include "method.h"#include "input.h"#include "output.h"#include "error.h"#include <stdlib.h>#include <string.h>#ifdef USE_ZLIB#include <zlib.h>#endifstatic voidwriteSWFPrebuiltClipToMethod(SWFBlock block, SWFByteOutputMethod method, void *data){ SWFPrebuiltClip clip = (SWFPrebuiltClip) block; methodWriteUInt16(CHARACTERID(clip), method, data); methodWriteUInt16(clip->frames, method, data); SWFOutput_writeToMethod(clip->display, method, data);}static intcompleteSWFPrebuiltClip(SWFBlock block){ return 4 + SWFPrebuiltClipLength(block);}intSWFPrebuiltClipLength(SWFBlock block){ SWFPrebuiltClip clip = (SWFPrebuiltClip)block; return SWFOutput_getLength(clip->display);}/* * destroys a SWFPrebuiltClip instance */voiddestroySWFPrebuiltClip(SWFPrebuiltClip clip){ destroySWFOutput(clip->display); destroySWFCharacter((SWFCharacter) clip);}SWFPrebuiltClipnewSWFPrebuiltClip(){ SWFPrebuiltClip clip = (SWFPrebuiltClip)malloc(sizeof(struct SWFPrebuiltClip_s)); SWFCharacterInit((SWFCharacter)clip); BLOCK(clip)->type = SWF_PREBUILTCLIP; BLOCK(clip)->writeBlock = writeSWFPrebuiltClipToMethod; BLOCK(clip)->complete = completeSWFPrebuiltClip; BLOCK(clip)->dtor = (destroySWFBlockMethod) destroySWFPrebuiltClip; clip->frames = 0; clip->display = newSWFOutput(); return clip;}static voidwriteSWFPrebuiltToMethod(SWFBlock block, SWFByteOutputMethod method, void *data){ SWFPrebuilt defines = (SWFPrebuilt) block; SWFOutput_writeToMethod(defines->defines, method, data);}static intcompleteSWFPrebuilt(SWFBlock block){ SWFPrebuilt defines = (SWFPrebuilt) block; return SWFOutput_getLength(defines->defines);}voiddestroySWFPrebuilt(SWFPrebuilt defines){ destroySWFOutput(defines->defines); free((SWFBlock) defines);}SWFPrebuiltnewSWFPrebuilt(){ SWFPrebuilt data = (SWFPrebuilt)malloc(sizeof(struct SWFPrebuilt_s)); SWFBlockInit((SWFBlock)data); BLOCK(data)->type = SWF_PREBUILT; BLOCK(data)->writeBlock = writeSWFPrebuiltToMethod; BLOCK(data)->complete = completeSWFPrebuilt; BLOCK(data)->dtor = (destroySWFBlockMethod) destroySWFPrebuilt; data->defines = newSWFOutput(); return data;}// functions to read swfstatic int verbose = {0};struct bitstream{ char lastch; char bitoff; unsigned char (*readc)(void *);};typedef struct bitstream *BITS;#define alignbits(x) ((BITS)x)->bitoff = 0static intgetbits(BITS bp, int nbits){ int res = 0, nb, db; for(nb = 0 ; nb < nbits ; nb += db) { if(bp->bitoff == 0) { bp->lastch = bp->readc(bp); bp->bitoff = 8; } db = nbits - nb; if(db > bp->bitoff) db = bp->bitoff; /* db bits von vorn wegnehmen */ res <<= db; res |= (bp->lastch >> (bp->bitoff -= db)) & ((1 << db) - 1); } return res;}static intgetsbits(BITS bp, int nbits){ int res = getbits(bp, nbits); if(res & (1 << (nbits-1))) res |= (-1) << nbits; return(res);}/* rectangle */static void rect(BITS bp){ int nbits, xmin, xmax, ymin, ymax; nbits = getbits(bp, 5); xmin = getbits(bp, nbits); xmax = getbits(bp, nbits); ymin = getbits(bp, nbits); ymax = getbits(bp, nbits); if(verbose) printf("rect %.2f,%.2f %.2f,%.2f\n", xmin/Ming_scale, ymin/Ming_scale, xmax/Ming_scale, ymax/Ming_scale);}/* matrix */static void matrix(BITS bp){ int hasscale, nscalebits, scalex, scaley; int hasrotate, nrotatebits, rotateskew0, rotateskew1; int ntranslatebits, translatex, translatey; if((hasscale = getbits(bp, 1))) { nscalebits = getbits(bp, 5); scalex = getbits(bp, nscalebits); scaley = getbits(bp, nscalebits); if(verbose) printf("scale %d %d\n", scalex, scaley); } if((hasrotate = getbits(bp, 1))) { nrotatebits = getbits(bp, 5); rotateskew0 = getsbits(bp, nrotatebits); rotateskew1 = getsbits(bp, nrotatebits); if(verbose) printf("skew %d %d\n", rotateskew0, rotateskew1); } ntranslatebits = getbits(bp, 5); translatex = getsbits(bp, ntranslatebits); translatey = getsbits(bp, ntranslatebits); if(verbose) printf("translate %d %d\n", translatex, translatey);}/* rgb */static void rgb(BITS bp){ int r, g, b; alignbits(bp); r = bp->readc(bp); g = bp->readc(bp); b = bp->readc(bp); if(verbose) printf("rgb %x %x %x\n", r, g, b);}static void rgba(BITS bp){ int r, g, b, a; alignbits(bp); r = bp->readc(bp); g = bp->readc(bp); b = bp->readc(bp); a = bp->readc(bp); if(verbose) printf("rgba %x %x %x %x\n", r, g, b, a);}static intreadint2(BITS bp){ int res; res = bp->readc(bp); res |= bp->readc(bp) << 8; return res;}static intreadint4(BITS bp){ int res; res = bp->readc(bp); res |= bp->readc(bp) << 8; res |= bp->readc(bp) << 16; res |= bp->readc(bp) << 24; return res;}static void putint2(unsigned char *p, int val){ *p++ = val; *p++ = val >> 8;}static void putint4(unsigned char *p, int val){ *p++ = val; *p++ = val >> 8; *p++ = val >> 16; *p++ = val >> 24;}/* open a swf file as a stream */struct swfile{ char lastch; char bitoff; unsigned char (*readc)(struct swfile *); char *name; unsigned char vers[4]; int fsize; char rect[9]; unsigned short rectlen; SWFInput input; short frames, rate; short compressed; unsigned char *zbuf, *zptr, *zend;};static unsigned char freadc(struct swfile *sp){ return SWFInput_getChar(sp->input);}static unsigned char r_readc(struct swfile *sp){ return sp->rect[sp->rectlen++] = freadc(sp);}static void swfseek(struct swfile *sp, int delta){ SWFInput_seek(sp->input, delta, 1);}static struct swfile *openswf(SWFInput input){ struct swfile *res = (struct swfile *)malloc(sizeof(struct swfile)); SWFInput_read(input, res->vers, 4); if(memcmp(res->vers, "FWS", 3) && memcmp(res->vers, "CWS", 3)) SWF_error("input not a SWF stream\n"); res->fsize = SWFInput_getUInt32(input); res->compressed = res->vers[0] == 'C'; if(res->compressed) {#if USE_ZLIB static z_stream z = {0}; int len = SWFInput_length(input); unsigned char *zbuf; z.next_in = (unsigned char *)malloc(z.avail_in = len - 8); SWFInput_read(input, z.next_in, z.avail_in); // caller will do, leave it here for double memory consumption //destroySWFInput(input); zbuf = z.next_out = (unsigned char *)malloc(z.avail_out = res->fsize - 8); inflateInit(&z); inflate(&z, Z_FINISH); inflateEnd(&z); input = newSWFInput_allocedBuffer(zbuf, z.next_out-zbuf);#else SWF_error("The SWF to be opened is compressed, but we can't uncompress it (no zlib compiled into this version of Ming).\n"); return NULL;#endif } res->input = input; // setup to read that rect... alignbits(res); res->rectlen = 0; res->readc = r_readc; rect((BITS) res); res->readc = freadc; readint2((BITS) res); // movie rate res->frames = readint2((BITS) res); return res;}/* tag */struct swftag{ char lastch; char bitoff; unsigned char (*readc)(struct swftag *sp); short type; int size; unsigned char hdr[6]; short hdrlen; unsigned char *datbuf, *datptr, *datend; short alloced;};typedef struct swftag *TAG;static unsigned char treadc(TAG tp){ return *tp->datptr++;}static TAG readtag_common(BITS bp){ TAG res = (TAG) malloc(sizeof(struct swftag)); res->type = readint2(bp); res->size = res->type & 63; putint2(res->hdr, res->type); res->type >>= 6; res->hdrlen = 2; if(res->size == 63) { res->size = readint4(bp); putint4(res->hdr+2, res->size); res->hdrlen = 6; } res->bitoff = 0; res->readc = treadc; res->alloced = 0; return res;}static TAG readtag_file(struct swfile *sp){ TAG res = (TAG) readtag_common((BITS) sp); if(res->size) { res->datbuf = res->datptr = (unsigned char *)malloc(res->size); res->datend = res->datbuf + res->size; SWFInput_read(sp->input, res->datbuf, res->size); res->alloced = 1; } return res;}static TAG readtag_sprite(TAG tp){ TAG res = readtag_common((BITS) tp); if(res->size) { res->datbuf = res->datptr = tp->datptr; res->datend = res->datbuf + res->size; tp->datptr += res->size; } return res;}static int idoffset = {0}, maxid = {0};static int change_id(TAG tp){ int val = readint2((BITS) tp); if(val != 0 && val != 65535) { val += idoffset; if(val > maxid) maxid = val; putint2(tp->datptr-2, val); } return val;}// processing functions for handle()static void defineshape(TAG tp, int lev);static void definetext(TAG tp, int lev);static void placeobject(TAG tp, int lv);static void definebutton(TAG tp);static void definebutton2(TAG tp);static void definetextfield(TAG tp);static void definesprite(TAG tp);static void definemorphshape(TAG tp,int lev);static void exportassets(TAG tp);static void definebuttonsound(TAG tp);static void fillandlinestyles(TAG tp, int lev);static void linestyle(TAG tp, int lev);static void shape(TAG tp, int lev);static void morphlinestyle2(TAG tp);static int drop_tag(TAG tp){ switch(tp->type) { case SWF_FILEATTRIBUTES: case SWF_METADATA: case SWF_DEFINESCENEANDFRAMEDATA: // only allowed in main timeline -> merge ? return 1; default: return 0; }}static int handle_tag(TAG tp){ int id; int displaylist = 0; if(verbose) { char *tagnam = "inknown"; switch(tp->type) { case SWF_END: tagnam = "stagEnd"; break; case SWF_SHOWFRAME: tagnam = "stagShowFrame"; break; case SWF_DEFINESHAPE: tagnam = "stagDefineShape"; break; case SWF_FREECHARACTER: tagnam = "stagFreeCharacter"; break; case SWF_PLACEOBJECT: tagnam = "stagPlaceObject"; break; case SWF_REMOVEOBJECT: tagnam = "stagRemoveObject"; break; case SWF_DEFINEBITS: tagnam = "stagDefineBits"; break; case SWF_DEFINEBUTTON: tagnam = "stagDefineButton"; break; case SWF_JPEGTABLES: tagnam = "stagJPEGTables"; break; case SWF_SETBACKGROUNDCOLOR: tagnam = "stagSetBackgroundColor"; break; case SWF_DEFINEFONT: tagnam = "stagDefineFont"; break; case SWF_DEFINETEXT: tagnam = "stagDefineText"; break; case SWF_DOACTION: tagnam = "stagDoAction"; break; case SWF_DEFINEFONTINFO: tagnam = "stagDefineFontInfo"; break; case SWF_DEFINESOUND: tagnam = "stagDefineSound"; break; case SWF_STARTSOUND: tagnam = "stagStartSound"; break; case SWF_DEFINEBUTTONSOUND: tagnam = "stagDefineButtonSound"; break; case SWF_SOUNDSTREAMHEAD: tagnam = "stagSoundStreamHead"; break; case SWF_SOUNDSTREAMBLOCK: tagnam = "stagSoundStreamBlock"; break; case SWF_DEFINELOSSLESS:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -