swfmill-0.3.3/0000775000175000017500000000000012234555371010204 500000000000000swfmill-0.3.3/Makefile.am0000777000175000017500000000035212234074606012162 00000000000000 ACLOCAL_AMFLAGS = -I autoconfig/m4 NULL= SUBDIRS = \ src \ test \ $(NULL) EXTRA_DIST = \ depcomp \ README.md \ $(NULL) MAINTAINERCLEANFILES = Makefile.in config.log config.status configure stamp-h.in config-h.in aclocal.m4 swfmill-0.3.3/src/0000775000175000017500000000000012234555372010774 500000000000000swfmill-0.3.3/src/SWFReader.cpp0000777000175000017500000001410312152542002013167 00000000000000#include "SWFReader.h" #include "SWFTag.h" #include "SWFAction.h" #include namespace SWF { Reader::Reader( const unsigned char *d, size_t l ) { data = d; length = l; pos = 0; buf = bits = 0; err = 0; } bool Reader::getData( void *dst, size_t len ) { if( pos+len > length ) { err = SWFR_EOF; pos = length+1; return false; } else { memcpy( dst, &data[pos], len ); pos += len; return true; } } uint8_t Reader::getByte() { if( pos+1 > length ) { err = SWFR_EOF; pos = length+1; return 0; } return data[pos++]; } uint16_t Reader::getWord() { if( pos+2 > length ) { err = SWFR_EOF; pos = length+1; return 0; } // FIXME x86-centric? int r = data[pos++]; r += data[pos++]<<8; return r; } uint32_t Reader::getInt() { if( pos+4 > length ) { err = SWFR_EOF; pos = length+1; return 0; } int r; // FIXME x86-centric? r = data[pos++]; r += data[pos++]<<8; r += data[pos++]<<16; r += data[pos++]<<24; return r; } uint64_t Reader::getInt64() { if( pos+8 > length ) { err = SWFR_EOF; pos = length+1; return 0; } uint64_t val; val = (uint64_t)getInt() << 32; val |= (uint64_t)getInt(); return( val ); } uint32_t Reader::getU30() { uint32_t r = 0; unsigned char c; for( int i = 0; i < 5; i++ ) { c = data[pos++]; r |= (c & 0x7F) << (7 * i); if( !(c & 0x80) ) { return r; } if( pos > length ) { err = SWFR_EOF; pos = length+1; return 0; } } return r; } int Reader::getS24() { if( pos+3 > length ) { err = SWFR_EOF; pos = length+1; return 0; } int r = data[pos++]; r += data[pos++]<<8; r += ((signed char)data[pos++])<<16; return r; } float Reader::getFloat() { /* if( pos+4 > length ) { err = SWFR_EOF; pos = length+1; return 0; } // FIXME x86-centric? int r = data[pos++]; r += data[pos++]<<8; r += data[pos++]<<16; r += data[pos++]<<24; return *((float*)&r); */ union { float f; uint32_t ul; } u; u.ul = getInt(); return u.f; } double Reader::getDouble() { /* if( pos+8 > length ) { err = SWFR_EOF; pos = length+1; return 0; } // FIXME x86-centric? char value[8]; value[4] = data[pos++]; value[5] = data[pos++]; value[6] = data[pos++]; value[7] = data[pos++]; value[0] = data[pos++]; value[1] = data[pos++]; value[2] = data[pos++]; value[3] = data[pos++]; return *(double*)value; */ union { double d; uint64_t ull; } u; u.ull = getInt64(); return u.d; } double Reader::getDouble2() { if( pos+8 > length ) { err = SWFR_EOF; pos = length+1; return 0; } union { double d; char c[8]; } u; // FIXME x86-centric? for( int i = 0; i < 8; i++ ) { u.c[i] = data[pos++]; } return u.d; } float Reader::getHalf() { uint16_t r = getWord(); int sign = (r & 0x8000) >> 15; int exp = (r & 0x7C00) >> 10; int man = (r & 0x3FF); if(exp == 0) { if(man != 0) { while(!(man & 0x400)) { man <<= 1; exp -= 1; } exp += 1 - 15 + 127; man &= 0x3FF; } } else if(exp == 0x1F) { exp = 0xFF; } else { exp += -15 + 127; } union { float f; uint32_t ul; } u; u.ul = (sign << 31) | (exp << 23) | (man << 13); return u.f; } unsigned int Reader::getEncodedU32() { unsigned int result = data[pos++]; if (!(result & 0x00000080)) return result; result = (result & 0x0000007f) | data[pos++] << 7; if (!(result & 0x00004000)) return result; result = (result & 0x00003fff) | data[pos++] << 14; if (!(result & 0x00200000)) return result; result = (result & 0x001fffff) | data[pos++] << 21; if (!(result & 0x10000000)) return result; result = (result & 0x0fffffff) | data[pos++] << 28; return result; } double Reader::getFixed( int bytesize, int exp ) { /* putFixed/getFixed are deprecated: they implicitly to byteAlign */ double r = 0; if( pos+bytesize > length ) { err = SWFR_EOF; pos = length+1; return 0; } for( int i=0; i bits ) { n -= bits; while( n > 8 ) { r <<= 8; r += getByte(); n-=8; } buf = getByte(); if( n > 0 ) { r <<= n; bits = 8-n; r += buf >> (8-n); buf &= (1<> (bits-n); bits -= n; buf &= (1<=0; b-- ) { printf( d[i] & (1< namespace SWF { class Action : public IdItem { protected: int getHeaderSize( int size ) { return( (type>=0x80 || size>0) ? 24 : 8 ); } void writeHeader( Writer *w, Context *ctx, size_t len ); // static stuff public: static Action* get( Reader *r, int end, Context *ctx ); }; } #endif swfmill-0.3.3/src/SWFFilter.cpp0000777000175000017500000000063112152542002013213 00000000000000#include #include "SWF.h" namespace SWF { Filter *Filter::get( Reader *r, int end, Context *ctx ) { int type = r->getByte(); int len = end - r->getPosition(); Filter* ret = getByType( type ); if( !ret ) { Filter* ret = new UnknownFilter(); } if( ret ) { ret->setType( type ); ret->setLength( len ); ret->parse( r, end, ctx ); } return ret; } } swfmill-0.3.3/src/SWFList.h0000777000175000017500000000721612152542002012354 00000000000000#ifndef F_List_H #define F_List_H #include #define WARNING printf namespace SWF { template class ListItem; /* a simple (likely non-threadsafe) LinkedList */ template class List { public: List( bool ownership = true ) : mOwnership( ownership ) { mFirst = mLast = NULL; } ~List() { ListItem *item = mFirst, *next; if( mOwnership ) { while( item ) { if( item->data() ) delete item->data(); next = item->next(); delete item; item = next; } } else { while( item ) { next = item->next(); delete item; item = next; } } } ListItem *append( T *data, void *user_data = NULL ) { if( !mLast ) { if( !mFirst ) { return mFirst = mLast = new ListItem( data, NULL, user_data ); } else { WARNING("Linked List has First but no Last item\n"); return NULL; } } else { return mLast = new ListItem( data, mLast, user_data ); } } ListItem *prepend( T *data, void *user_data = NULL ) { if( !mFirst ) { return mFirst = mLast = new ListItem( data, NULL, user_data ); } else { ListItem *item = new ListItem( data, NULL, user_data ); item->mNext = mFirst; mFirst->mPrevious = item; return mFirst = item; } } ListItem *prepend2( T *data, void *user_data = NULL ) { if( !mFirst ) { return mFirst = mLast = new ListItem( data, NULL, user_data ); } else { return new ListItem( data, mFirst, user_data ); } } T* remove( ListItem *item ) { item->remove( this ); T *ret = item->data(); if( mOwnership && item->data() ) { delete item->data(); ret = NULL; } delete item; return ret; } void moveToLast( ListItem *item ) { if( item == mLast ) return; item->remove( this ); item->mPrevious = mLast; if( mLast ) { mLast->mNext = item; } mLast = item; if( !mFirst ) mFirst = item; } ListItem *first() { return mFirst; }; ListItem *last() { return mLast; }; friend class ListItem; int size() { if (mFirst == NULL) return 0; if (mFirst == mLast) return 1; int count = 1; ListItem *item = mFirst; while(item != mLast) { count++; item = item->next(); } return count; } protected: ListItem *mFirst; ListItem *mLast; bool mOwnership; }; template class ListItem { public: ListItem( T *data, ListItem* insertAfter = NULL, void *user_data = NULL ) { mData = data; mPrevious = insertAfter; mNext = insertAfter ? insertAfter->replaceNext( this ) : NULL; if( mNext ) mNext->mPrevious = this; mUserData = user_data; } ListItem *replaceNext( ListItem *next ) { ListItem *ret = mNext; mNext = next; return ret; } void remove( List *list ) { if( !mPrevious ) list->mFirst = mNext; else mPrevious->mNext = mNext; if( !mNext ) list->mLast = mPrevious; else mNext->mPrevious = mPrevious; mPrevious = mNext = NULL; } ListItem *next() { return( mNext ); } ListItem *previous() { return( mPrevious ); } T* data() { return( mData ); } void* UserData() { return( mUserData ); } bool isLast() { return( mNext == 0 ); } bool isFirst() { return( mPrevious == 0 ); } friend class List; protected: ListItem *mPrevious; ListItem *mNext; T *mData; void *mUserData; }; } #endif swfmill-0.3.3/src/SWFAction.cpp0000777000175000017500000000153112152542002013203 00000000000000#include #include "SWF.h" #include namespace SWF { Action *Action::get( Reader *r, int end, Context *ctx ) { uint16_t h = r->getByte(); int type = h; int len = 0; if( type >= 0x80 ) { len = r->getWord(); } if( type == 0 ) return( new EndAction ); // terminator Action *ret = getByType( type ); // printf("ACTION %02X len %i: %p\n", type, len, ret ); if( !ret ) { ret = new UnknownAction; } ret->setType( type ); ret->setLength( len ); ret->parse( r, r->getPosition()+len, ctx ); return ret; } void Action::writeHeader( Writer *w, Context *ctx, size_t len ) { // printf("write action %02X, len %i, recorded %i(+header, 1 or 3), position %i\n", type, len, this->len, w->getPosition() ); w->putByte( type ); if( type >= 0x80 ) { w->putWord( len-=3 ); } } } swfmill-0.3.3/src/Geom.cpp0000777000175000017500000000657312152542002012310 00000000000000#include "Geom.h" #define TMP_STRLEN 0xff namespace SWF { Matrix::Matrix() { identity(); } Matrix::Matrix(double v11, double v12, double v13, double v21, double v22, double v23, double v31, double v32, double v33) { values[0][0] = v11; values[0][1] = v12; values[0][2] = v13; values[1][0] = v21; values[1][1] = v22; values[1][2] = v23; values[2][0] = v31; values[2][1] = v32; values[2][2] = v33; } void Matrix::identity() { values[0][0] = 1; values[0][1] = 0; values[0][2] = 0; values[1][0] = 0; values[1][1] = 1; values[1][2] = 0; values[2][0] = 0; values[2][1] = 0; values[2][2] = 1; } void Matrix::translate(double tx, double ty) { Matrix t(1, 0, tx, 0, 1, ty, 0, 0, 1); (*this) *= t; } void Matrix::scale(double sx, double sy) { Matrix t(sx, 0, 0, 0, sy, 0, 0, 0, 1); (*this) *= t; } void Matrix::scale(double s) { scale(s, s); } void Matrix::rotate(double a) { Matrix t(cos(a), -sin(a), 0, sin(a), cos(a), 0, 0, 0, 1); (*this) *= t; } void Matrix::skewX(double a) { Matrix t(1, tan(a), 0, 0, 1, 0, 0, 0, 1); (*this) *= t; } void Matrix::skewY(double a) { Matrix t( 1, 0, 0, tan(a), 1, 0, 0, 0, 1); (*this) *= t; } Matrix& Matrix::operator*=(const Matrix &m) { *this = *this * m; return *this; } Matrix Matrix::operator*(const Matrix &m) { return Matrix(values[0][0] * m.values[0][0] + values[0][1] * m.values[1][0] + values[0][2] * m.values[2][0], values[0][0] * m.values[0][1] + values[0][1] * m.values[1][1] + values[0][2] * m.values[2][1], values[0][0] * m.values[0][2] + values[0][1] * m.values[1][2] + values[0][2] * m.values[2][2], values[1][0] * m.values[0][0] + values[1][1] * m.values[1][0] + values[1][2] * m.values[2][0], values[1][0] * m.values[0][1] + values[1][1] * m.values[1][1] + values[1][2] * m.values[2][1], values[1][0] * m.values[0][2] + values[1][1] * m.values[1][2] + values[1][2] * m.values[2][2], values[2][0] * m.values[0][0] + values[2][1] * m.values[1][0] + values[2][2] * m.values[2][0], values[2][0] * m.values[0][1] + values[2][1] * m.values[1][1] + values[2][2] * m.values[2][1], values[2][0] * m.values[0][2] + values[2][1] * m.values[1][2] + values[2][2] * m.values[2][2]); } double Matrix::getValue(int row, int col) { if(row >= 0 && row <= 2 && col >=0 && col <= 2) { return values[row][col]; } else { return 0; } } void Matrix::setXMLProps(xmlNodePtr node) { char tmp[TMP_STRLEN]; snprintf(tmp,TMP_STRLEN,"%f", values[1][0]); xmlSetProp(node, (const xmlChar *)"skewX", (const xmlChar *)&tmp ); snprintf(tmp,TMP_STRLEN,"%f", values[0][1]); xmlSetProp(node, (const xmlChar *)"skewY", (const xmlChar *)&tmp ); snprintf(tmp,TMP_STRLEN,"%f", values[0][0]); xmlSetProp(node, (const xmlChar *)"scaleX", (const xmlChar *)&tmp ); snprintf(tmp,TMP_STRLEN,"%f", values[1][1]); xmlSetProp(node, (const xmlChar *)"scaleY", (const xmlChar *)&tmp ); snprintf(tmp,TMP_STRLEN,"%f", values[0][2]); xmlSetProp(node, (const xmlChar *)"transX", (const xmlChar *)&tmp ); snprintf(tmp,TMP_STRLEN,"%f", values[1][2]); xmlSetProp(node, (const xmlChar *)"transY", (const xmlChar *)&tmp ); } } swfmill-0.3.3/src/Makefile.am0000777000175000017500000000744012234241357012755 00000000000000 NULL = MAINTAINERCLEANFILES = Makefile.in bin_PROGRAMS = swfmill if IS_WINDOWS ADDCFLAGS = -DLIBXML_STATIC -DLIBXSLT_STATIC -DLIBEXSLT_STATIC ADDLDFLAGS = -all-static endif swfmill_CFLAGS = $(XML_CFLAGS) $(XSLT_CFLAGS) $(EXSLT_CFLAGS) \ $(FREETYPE_CFLAGS) $(PNG_CFLAGS) $(ADDCFLAGS) \ -I$(srcdir)/swft/ -I$(srcdir)/xslt/ swfmill_CXXFLAGS = $(swfmill_CFLAGS) swfmill_LDADD = $(XML_LIBS) $(XSLT_LIBS) $(EXSLT_LIBS) $(FREETYPE_LIBS) \ $(PNG_LIBS) $(LTLIBICONV) swfmill_LDFLAGS = $(ADDLDFLAGS) CODEGEN_GENERATEDHEADERS = \ SWF.h \ $(NULL) CODEGEN_GENERATEDSOURCES = \ gSWFParseXML.cpp \ gSWFWriteXML.cpp \ gSWFParser.cpp \ gSWFWriter.cpp \ gSWFDumper.cpp \ gSWFBasics.cpp \ gSWFSize.cpp \ $(NULL) SIMPLE_DIALECT_GENERATEDXSL = \ xslt/simple.xsl \ $(NULL) SIMPLE_DIALECT_GENERATEDSOURCES = \ xslt/simple.cpp \ $(NULL) SIMPLE_DIALECT_XSLTS = \ xslt/simple-tools.xslt \ xslt/simple-elements.xslt \ xslt/simple-import.xslt \ xslt/simple-deprecated.xslt \ xslt/simple-svg.xslt \ $(NULL) CODEGEN_SRC = \ codegen/basic.xsl \ codegen/basics.xsl \ codegen/dumper.xsl \ codegen/header.xsl \ codegen/mk.xsl \ codegen/parser.xsl \ codegen/parsexml.xsl \ codegen/size.xsl \ codegen/source.xml \ codegen/writer.xsl \ codegen/writexml.xsl \ $(NULL) EXTRA_DIST = \ $(CODEGEN_SRC) \ \ xslt/assemble.xsl \ xslt/simple.xml \ $(SIMPLE_DIALECT_XSLTS) \ $(NULL) BUILT_SOURCES = \ $(CODEGEN_GENERATEDHEADERS) \ $(NULL) $(firstword $(CODEGEN_GENERATEDSOURCES)): $(CODEGEN_SRC) $(XSLTPROC) $(srcdir)/codegen/mk.xsl $(srcdir)/codegen/source.xml $(wordlist 2,$(words $(CODEGEN_GENERATEDSOURCES)),$(CODEGEN_GENERATEDSOURCES)) $(CODEGEN_GENERATEDHEADERS): $(firstword $(CODEGEN_GENERATEDSOURCES)) : NAMESPACES = xmlns:swft=\"http:\/\/subsignal.org\/swfml\/swft\" \ xmlns:str=\"http:\/\/exslt.org\/strings\" \ xmlns:math=\"http:\/\/exslt.org\/math\" $(SIMPLE_DIALECT_GENERATEDSOURCES): $(SIMPLE_DIALECT_GENERATEDSOURCES:.cpp=.xml) xslt/assemble.xsl $(SIMPLE_DIALECT_XSLTS) $(XSLTPROC) $(srcdir)/xslt/assemble.xsl $< > $(@:.cpp=.xsl) echo "#include \"xslt/xslt.h\"" > $@ echo "const char *xslt_simple = " >> $@ $(SED) -e "s/namespaces=\\\"hack\\\"/$(NAMESPACES)/" -e "s/\"/\\\\\"/g" -e "s/\(.*\)/\"\1\\\\n\"/g" $(@:.cpp=.xsl) >> $@ echo ";" >> $@ swfmill_SOURCES = \ swft/swft.cpp \ swft/swft_document.cpp \ swft/swft_path.cpp \ swft/swft_import.cpp \ swft/swft_import_jpeg.cpp \ swft/swft_import_png.cpp \ swft/swft_import_ttf.cpp \ swft/swft_import_mp3.cpp \ swft/swft_import_wav.cpp \ swft/swft_import_binary.cpp \ swft/Parser.cpp \ swft/SVGStyle.cpp \ swft/SVGGradient.cpp \ swft/SVGColor.cpp \ swft/SVGPathParser.cpp \ swft/SVGPointsParser.cpp \ swft/SVGTransformParser.cpp \ swft/SVGAttributeParser.cpp \ swft/readpng.c \ \ base64.c \ Geom.cpp \ SWFReader.cpp \ SWFWriter.cpp \ SWFFile.cpp \ SWFItem.cpp \ SWFTag.cpp \ SWFAction.cpp \ SWFFilter.cpp \ SWFOpCode.cpp \ SWFTrait.cpp \ SWFShapeItem.cpp \ SWFGlyphList.cpp \ SWFShapeMaker.cpp \ \ swfmill.cpp \ $(NULL) nodist_swfmill_SOURCES = \ $(CODEGEN_GENERATEDSOURCES) \ $(SIMPLE_DIALECT_GENERATEDSOURCES) \ $(NULL) noinst_HEADERS = \ swft/swft.h \ swft/Parser.h \ swft/SVGStyle.h \ swft/SVGGradient.h \ swft/SVGColor.h \ swft/SVGColors.h \ swft/SVGPathParser.h \ swft/SVGPointsParser.h \ swft/SVGTransformParser.h \ swft/SVGAttributeParser.h \ swft/readpng.h \ \ xslt/xslt.h \ \ base64.h \ Geom.h \ SWFBasic.h \ SWFReader.h \ SWFWriter.h \ SWFFile.h \ SWFItem.h \ SWFIdItem.h \ SWFIdItems.h \ SWFTag.h \ SWFAction.h \ SWFFilter.h \ SWFOpCode.h \ SWFTrait.h \ SWFShapeItem.h \ SWFGlyphList.h \ SWFList.h \ SWFShapeMaker.h \ SWF.h \ $(NULL) CLEANFILES = \ $(CODEGEN_GENERATEDHEADERS) \ $(CODEGEN_GENERATEDSOURCES) \ $(SIMPLE_DIALECT_GENERATEDXSL) \ $(SIMPLE_DIALECT_GENERATEDSOURCES) \ $(NULL) swfmill-0.3.3/src/SWFItem.h0000777000175000017500000000327312234241357012350 00000000000000#ifndef SWF_ITEM_H #define SWF_ITEM_H #include #include #include namespace SWF { class Context; int SWFBitsNeeded( int32_t value, bool is_signed = false ); int SWFBitsNeeded( float value, int exp, bool is_signed = false ); long SWFMaxBitsNeeded( bool is_signed, int how_many, ... ); class Item { public: Item(); virtual ~Item() {} virtual bool parse( Reader *r, int end, Context *ctx ) = 0; virtual void dump( int indent, Context *ctx ) = 0; virtual size_t calcSize( Context *ctx, int start_at ) = 0; virtual void write( Writer *r, Context *ctx ) = 0; virtual void writeXML( xmlNodePtr xml, Context *ctx ) = 0; virtual void parseXML( xmlNodePtr xml, Context *ctx ) = 0; // wont touch the context if size is cached. size_t getSize( Context *ctx, int start_at ); protected: int getHeaderSize( int size ); void writeHeader( Writer *w, Context *ctx, size_t len ); int file_offset; // bytes after header for SWF, line for XML (NYI) int cached_size; // cached size }; // to save the rest of a tag as binary data... class Rest : public Item { public: Rest(); virtual ~Rest(); virtual bool parse( Reader *r, int end, Context *ctx ); virtual void dump( int indent, Context *ctx ); virtual size_t calcSize( Context *ctx, int start_at ); virtual void write( Writer *w, Context *ctx ); virtual void writeXML( xmlNodePtr node, Context *ctx ); virtual void parseXML( xmlNodePtr node, Context *ctx ); void getdata( unsigned char **data, int *size ); void setdata( unsigned char *data, int size ); protected: int size; unsigned char *data; }; } #endif swfmill-0.3.3/src/SWFOpCode.h0000777000175000017500000000035412152542002012606 00000000000000#ifndef SWF_OPCODE_H #define SWF_OPCODE_H #include namespace SWF { class OpCode : public IdItem { // static stuff public: static OpCode* get( Reader *r, int end, Context *ctx ); }; } #endif swfmill-0.3.3/src/SWFWriter.h0000777000175000017500000000417512152542002012716 00000000000000#ifndef SWF_Writer_H #define SWF_Writer_H #include #include #include "SWFBasic.h" namespace SWF { #define SWFW_OK 0 #define SWFW_ERROR 1 #define SWFW_FULL 2 class Writer { public: Writer( unsigned char *data, size_t length ); Writer( size_t length ); // these implicitly do byteAlign() void putData( void *src, size_t length ); void putByte(uint8_t); void putWord(uint16_t); void putInt(uint32_t); void putInt64(uint64_t); void putU30(uint32_t); void putS24(int); void putFloat(float); void putDouble(double); void putDouble2(double); void putHalf(float); void putFixed( double v, int bytesize, int decimals ); void putString( const char * ); void putPString( const char * ); void putPStringU30( const char * ); void putEncodedU32(unsigned int); // this one cares about the current bit position void putNBitInt( int64_t v, int n, bool is_signed = false ); void putNBitFixed( double v, int n, int m, bool is_signed = false ); void putNBitFixed2( double v, int n, int m, bool is_signed = false ); // set bit position to next byte. void byteAlign() { if( bits ) writeByte( buf ); buf = 0; bits=0; } int getError() { return err; } void dump( int n, int ofs ); // dumps n bytes from current position to stdout bool assure( int l, int before=-1 ) { int b = (before==-1?length:before); if( pos+l > b ) { fprintf(stderr,"Write buffer full (%i+%i > %i)\n", pos, l, b ); err = SWFW_FULL; return false; } return true; } size_t getLength() { return length; } unsigned char *getData() { return data; } int getPosition() { return pos; } int getBits() { return bits; } int getBitPosition() { return (pos*8)+( bits ); } protected: void writeByte( uint8_t value ); // the uncompressed swf data and our position within unsigned char *data; int pos, length; // buf is the current byte when in "NBit mode" // bits is the number of bits represented in buf. uint8_t buf, bits; int err; bool write( void *dst, size_t n ); }; } #endif swfmill-0.3.3/src/SWFIdItems.h0000777000175000017500000000056012152542002012772 00000000000000#ifndef SWF_IDITEMS_H #define SWF_IDITEMS_H #include namespace SWF { class StackItem : public IdItem {}; class Style : public IdItem swfmill-0.3.3/src/codegen/parser.xsl0000777000175000017500000002141612152542002014336 00000000000000 #include ".h" #include "Item.h" #include "List.h" namespace { //////////////////////////////////// bool ::parse( Reader *r, int end, Context *ctx ) { file_offset = r->getPosition(); if( ctx->debugTrace ) { fprintf( stderr, "PARSE %s @%i-%i :%i\n", "", r->getPosition(), r->getBits(), end ); } if( r->getPosition() != file_offset + len ) { fprintf( stderr, "WARNING: end of tag %s is @%i, should be @%i\n", "", r->getPosition(), file_offset+len ); r->seekTo( file_offset + len ); } return r->getError() == SWFR_OK; } } if( ! & ) { } else { = ; } if( ctx->debugTrace ) { fprintf( stderr, "PARSE IF %s - ", "" ); } if( ) { if( ctx->debugTrace ) { fprintf( stderr, "TRUE\n" ); } } else { if( ctx->debugTrace ) { fprintf( stderr, "FALSE\n" ); } = ; } = ; if( ctx->debugTrace ) { fprintf( stderr, "PARSE %s: \n", "", ); } ctx-> = ; if( && +r->getPosition() < end ) { if( ctx->debugTrace ) { fprintf(stderr, "- has next offset, setting end to current+%i\n", ); } end = r->getPosition() + + (); } r->getByte() r->getWord() r->getNBitFixed(,,true) r->getNBitFixed2(,,true) r->getInt() r->getFloat() r->getDouble() r->getDouble2() r->getHalf() r->getNBitInt(1) r->getNBitInt( + ,true) r->getU30() r->getS24() r->getEncodedU32() r->getPString() r->getPStringU30() r->getString() r->getString() = r->getByte(); if( == 0xff && ctx->tagVersion >= 2 ) { = r->getWord(); } if( ctx->debugTrace ) { fprintf( stderr, "PARSE %s: \n", "", ); } ctx-> = ; if( && +r->getPosition() < end ) { if( ctx->debugTrace ) { fprintf(stderr, "- has next offset, setting end to current+%i\n", ); } end = r->getPosition() + + (); } .parse(r,end,ctx); ( + ) ( < ? 0 : - ) { if( ctx->debugTrace ) { fprintf( stderr, "PARSE list<%s> %s: %i items, @%i-%i :%i\n", "", "", , r->getPosition(), r->getBits(), end ); } *item; for( int i=0; i<; i++ ) { item = ::get(r,end,ctx); .append( item ); } } { if( ctx->debugTrace ) { fprintf( stderr, "PARSE list<%s> %s @%i-%i :%i\n", "", "", r->getPosition(), r->getBits(), end ); } int myend = end; myend = r->getPosition() + + (); if( r->getPosition() < myend ) { *item; item = ::get(r,end,ctx); while( item && r->getPosition() <= myend ) { .append( item ); if( r->getPosition() < myend || (r->getPosition()==myend && r->getBits() )) item = ::get(r,myend,ctx); else item = NULL; if(item && ) { .append( item ); item = NULL; } } } } { int sz = ; = new unsigned char[ sz ]; r->getData( , sz ); } r->byteAlign(); ctx-> = ; swfmill-0.3.3/src/codegen/writer.xsl0000777000175000017500000001757112152542002014365 00000000000000 #include ".h" #include "Item.h" #include "List.h" namespace { //////////////////////////////////// void ::write( Writer *w, Context *ctx ) { int start=w->getBitPosition(); if( ctx->debugTrace ) { printf("WRITE %s @%i\n", "", start/8 ); dump(1,ctx); } if( !ctx->isLast ) { int r = 0; = (r/8) - (); } else { = 0; } ::writeHeader( w, ctx, getSize(ctx,w->getBitPosition())/8 ); ::writeHeader( w, ctx, (getSize(ctx,w->getBitPosition())/8) - ); int l = w->getBitPosition()-start; if( l != getSize(ctx,start)) { printf("WARNING: %s has different size than expected: %i bits instead of %i\n", "", l, getSize(ctx,start) ); } } } if( ! & ) { } if( ) { } ; ctx-> = ; w->putByte() w->putWord() w->putInt() w->putFloat() w->putDouble() w->putDouble2() w->putHalf() w->putNBitFixed(,,,true) w->putNBitFixed2(,,,true) w->putNBitInt(,1) w->putNBitInt(,+,true) w->putPString() w->putPStringU30() w->putString() w->putData(,) w->putString() w->putU30() w->putS24() w->putEncodedU32() { int v = ; if( v >= 255 && ctx->tagVersion >= 2 ) { w->putByte( 255 ); w->putWord( v ); } else { w->putByte( v ); } } ctx-> = ; .write(w,ctx); ( + ) ( < ? 0 : - ) { *item; ListItem<>* i; i = .first(); for( int j=0; j<; j++ ) { if( !i || !i->data() ) { printf("WARNING: list %s has %i items (%i expected)\n", "", j, ); } else { i->data()->write( w, ctx ); } i = i->next(); } } { int start = w->getPosition(); *item; ListItem<>* i; i = .first(); while( i ) { if( !i->data() ) { printf("WARNING: list %s has an invalid item\n", "" ); } else { ctx->isLast = i->isLast(); i->data()->write( w, ctx ); } i = i->next(); } } if( && ) { w->putData( , ); } w->byteAlign(); w->byteAlign(); ctx-> = ; swfmill-0.3.3/src/codegen/basics.xsl0000777000175000017500000002424612152542002014312 00000000000000 = ; delete[] ; *Factory() { return (*)new ; } template<> IdItem<>::Description IdItem<>::Registry[] = { { , "", Factory }, { 0, NULL } }; template<> int IdItem<>::nRegistered = ; template<> const char* IdItem<>::itemName = ""; #include ".h" #include "Tag.h" #include <cstring> namespace { // ------------ context structure Context::Context() : swf_encoding(0) { swfVersion = 0; transientPropsToXML = false; debugTrace = false; exportAssets = false; isLast = false; tagVersion = 0; quiet = false; convertEncoding = false; } // ------------ basic object functions ::() { } ::~() { } * ::get( Reader *r, int end, Context *ctx ) { * ret = new ; ret->parse( r, end, ctx ); return ret; } * ::getByName( const char *name ) { if( strcmp( name, "" ) ) return NULL; * ret = new ; return ret; } // ------------ object lists Tag tag Action action Filter filter Style fill style StackItem stack item int ::id = ; NamespaceConstant namespace constant MultinameConstant multiname constant Trait trait OpCode opcode } // Constant Size Primitive ::get() { return ; } void ::set( v ) { int b = SWFBitsNeeded( v, true ); if (b > ) { printf ("WARNING: '%s::%s' (%i) is too large to fit in %i bits\n", "", "", v, ); } = v; } // Constant Size Primitive ::get() { return ; } void ::set( v ) { int b = SWFBitsNeeded( v, , true ); if (b > ) { fprintf (stderr, "WARNING: '%s::%s' (" "" ") is too large to fit in %i bits\n", "", "", v, ); } = v; } // NBitInt ::get() { return ; } void ::set( v ) { int b = SWFBitsNeeded( v, true ); b -= ; if( b > ) set (b); = v; } ::get() { return ; } void ::set( v ) { delete ; = v; } void ::get( unsigned char **dst, int *size ) { *dst = ; *size = ; } void ::set( const unsigned char *src, int size ) { delete ; = size; = new unsigned char[ size ]; memcpy( , src, size ); } * ::get() { return &; } * ::get() { return &; } ::get() { return ; } void ::set( v ) { delete ; = v; } swfmill-0.3.3/src/codegen/dumper.xsl0000777000175000017500000000637612152542002014346 00000000000000 #include ".h" namespace { void print_indent( int n ) { for( int i=0; i<n; i++ ) printf(" "); } void ::dump( int indent, Context *ctx ) { print_indent(indent); printf("[%02X] ", type ); //); printf(""); // (sz %i)", getSize( ctx ) ); printf("\n"); indent++; } } if( ! & ) { } if( ) { } print_indent(indent); printf("%s: ", ""); printf("\n", ); printf("\n", ?:"(nil)"); printf("[%s]\n", ""); .dump( indent+1, ctx ); { printf("[list of %ss]\n", ""); *item; ListItem<>* i; i = .first(); while( i ) { item = i->data(); if( item ) { item->dump(indent+1,ctx); } i = i->next(); } } printf("(length %i)\n", ); if( && != NULL ) { int i=0; while( i< ) { print_indent( indent+1 ); for( int n=0; n<8 && i<; n++ ) { printf(" %02X", [i] ); i++; } printf("\n"); } } ctx-> = ; swfmill-0.3.3/src/codegen/parsexml.xsl0000777000175000017500000002767112234241357014720 00000000000000 #include ".h" #include <cstring> #include <cctype> #include <cstdlib> #include "base64.h" #include <errno.h> #include <iconv.h> using namespace std; namespace { char *fromXmlChar(const Context *ctx, const xmlChar *from_str) { if (ctx->convertEncoding) { size_t len = strlen((const char *)from_str); iconv_t cd = iconv_open(ctx->swf_encoding, "UTF-8"); if (cd < 0) { fprintf(stderr, "iconv_open failed.\n"); char *buf = new char[1]; buf[0] = '\0'; return buf; } size_t buf_size = (len + 1) * 2; for (;;) { char * const dst = new char[buf_size]; size_t inbytesleft = len; size_t outbytesleft = buf_size - 1; // reserve 1 byte for '\0' ICONV_CONST char *pin = (ICONV_CONST char*)from_str; char *pout = dst; bool expandbuf = false; while (inbytesleft > 0) { size_t r = iconv(cd, &pin, &inbytesleft, &pout, &outbytesleft); if (r == (size_t)-1) { if (errno == E2BIG) { expandbuf = true; } else { // bad input charctor fprintf(stderr, "iconv failed: %s\n", from_str); } break; } } if (expandbuf) { iconv(cd, 0, 0, 0, 0); delete[] dst; buf_size *= 2; continue; } *pout = '\0'; iconv_close(cd); return dst; } } else { size_t len = strlen((const char *)from_str) + 1; char *buf = new char[len]; strcpy(buf, (const char *)from_str); return buf; } } char *strdupx(const char *src) { char *t = new char[strlen(src)+1]; strcpy(t, src); return t; } void ::parseXML( xmlNodePtr node, Context *ctx ) { xmlNodePtr node2; xmlChar *tmp; // printf("::parseXML\n"); ctx-> = ; tmp = xmlGetProp( node, (const xmlChar *)"id" ); if( tmp ) { sscanf( (char *)tmp, "%X", &type ); xmlFree( (xmlChar *)tmp ); } ctx-> = ; = SWFBitsNeeded( ); if( > ctx-> ) ctx-> = ; = ctx->; } } if( !xmlHasProp( node, (const xmlChar *)"" ) ) has = true; { xmlNodePtr child = node->children; while( child && !has ) { if( !strcmp( (const char *)child->name, "" ) ) has = true; child = child->next; } } { bool has = false; if( has ) |= ; else ^= ; if( has ) = !true; if( has ) { } = ctx->; } if( ) { } tmp = xmlGetProp( node, (const xmlChar *)"" ); if( tmp ) { int tmp_int; sscanf( (char *)tmp, "", &tmp_int ); = tmp_int; xmlFree( tmp ); } tmp = xmlGetProp( node, (const xmlChar *)"" ); if( tmp ) { double tmp_float; sscanf( (char *)tmp, "%lg", &tmp_float ); = tmp_float; xmlFree( tmp ); } tmp = xmlGetProp( node, (const xmlChar *)"" ); if( tmp ) { double t; sscanf( (char *)tmp, "%lg", &t); = t; xmlFree( tmp ); int b = SWFBitsNeeded( , , true ); b -= ; if( b > ) = b; set (b); } else { fprintf(stderr,"WARNING: no %s property in %s element\n", "", (const char *)node->name ); } tmp = xmlGetProp( node, (const xmlChar *)"" ); if( tmp ) { sscanf( (char *)tmp, "", &); xmlFree( tmp ); int b = SWFBitsNeeded( , true ); b -= ; if( b > ) = b; set (b); } else { fprintf(stderr,"WARNING: no %s property in %s element\n", "", (const char *)node->name ); } tmp = xmlGetProp( node, (const xmlChar *)"" ); if( tmp ) { = fromXmlChar(ctx, (const xmlChar*)tmp); xmlFree(tmp); } else { fprintf(stderr,"WARNING: no %s property in %s element\n", "", (const char *)node->name ); = strdupx("[undefined]"); } node2 = node->children; while( node2 ) { if( !strcmp( (const char *)node2->name, "" ) ) { xmlNodePtr child = node2->children; while( child ) { if( !xmlNodeIsText( child ) ) { .parseXML( child, ctx ); node2 = child = NULL; node2 = NULL; } else { child = child->next; } } } if( node2 ) node2 = node2->next; } node2 = node->children; while( node2 ) { if( !strcmp( (const char *)node2->name, "" ) ) { =0; size_t l = 0; xmlNodePtr child = node2->children; while( child ) { if( !xmlNodeIsText( child ) ) { * item = ::getByName( (const char *)child->name ); if( item ) { item->parseXML( child, ctx ); .append( item ); ++; l += item->getSize(ctx, l); } } child = child->next; } -= ; if( > 0 ) { += ; } = (l/8) - (); node2=NULL; } else { node2 = node2->next; } } { = NULL; = 0; xmlChar *xmld = xmlNodeGetContent( node ); char *d = (char *)xmld; if( d ) { // unsure if this is neccessary for( int i=strlen(d)-1; i>0 && isspace(d[i]); i-- ) d[i]=0; while( isspace(d[0]) ) d++; int l = strlen(d); //BASE64_GET_MAX_DECODED_LEN(strlen( d )); char *dst = new char[ l ]; int lout = base64_decode( dst, (char*)d, l ); if( lout > 0 ) { = lout; = new unsigned char[ lout ]; memcpy( , dst, lout ); } delete dst; xmlFree( xmld ); } } { xmlNodePtr child = NULL; xmlNodePtr currentChild = node->children; while( currentChild && child == NULL) { if( ! strcmp( (const char *)currentChild->name, (const char *)"" ) ) { child = currentChild; } currentChild = currentChild->next; } if (child == NULL) { fprintf(stderr,"WARNING: no %s child element in %s element\n", "", (const char *)node->name ); = strdupx("[undefined]"); } else { xmlDocPtr out = xmlNewDoc((const xmlChar*)"1.0"); out->xmlRootNode = xmlCopyNode( child, 1 ); char *data; int size; xmlDocDumpFormatMemory( out, (xmlChar**)&data, &size, 1 ); = data; } } ctx-> = ; swfmill-0.3.3/src/codegen/writexml.xsl0000777000175000017500000001350212234241357014724 00000000000000 #include ".h" #include "base64.h" #include <cstring> #include <errno.h> #include <iconv.h> namespace { xmlChar *toXmlChar(const Context *ctx, const char *from_str) { if (ctx->convertEncoding) { size_t len = strlen(from_str); iconv_t cd = iconv_open("UTF-8", ctx->swf_encoding); if (cd < 0) { fprintf(stderr, "iconv_open failed.\n"); return xmlCharStrdup(""); } size_t buf_size = (len + 1) * 2; char *dst; for (;;) { dst = new char[buf_size]; size_t inbytesleft = len; size_t outbytesleft = buf_size - 1; ICONV_CONST char *pin = (ICONV_CONST char*)from_str; char *pout = dst; bool expandbuf = false; while (inbytesleft > 0) { size_t r = iconv(cd, &pin, &inbytesleft, &pout, &outbytesleft); if (r == (size_t)-1) { if (errno == E2BIG) { // buf_size shorten expandbuf = true; } else { //bad input charctor fprintf(stderr, "iconv failed: %s\n", from_str); } break; } } if (expandbuf) { delete[] dst; iconv(cd, 0, 0, 0, 0); buf_size *= 2; continue; } *pout = '\0'; break; } iconv_close(cd); xmlChar *ret = xmlCharStrdup(dst); delete[] dst; return ret; } else { return xmlCharStrdup(from_str); } } #define TMP_STRLEN 0xFF void ::writeXML( xmlNodePtr xml, Context *ctx ) { char tmp[TMP_STRLEN]; xmlNodePtr node = xml; xmlNodePtr node2; node = xmlNewChild( node, NULL, (const xmlChar *)"", NULL ); if( ctx->transientPropsToXML ) { snprintf( tmp, TMP_STRLEN, "%i", file_offset ); xmlSetProp( node, (const xmlChar *)"file_offset", (const xmlChar *)tmp ); } snprintf( tmp, TMP_STRLEN, "0x%02X", type ); xmlSetProp( node, (const xmlChar *)"id", (const xmlChar *)tmp ); } } if( ! & ) { } if( ) { } snprintf(tmp,TMP_STRLEN,"%#.*g", 16, ); xmlSetProp( node, (const xmlChar *)"", (const xmlChar *)&tmp ); snprintf(tmp,TMP_STRLEN,"", ); xmlSetProp( node, (const xmlChar *)"", (const xmlChar *)&tmp ); if( ) { xmlChar *xmlstr = toXmlChar(ctx, ); xmlSetProp(node, (const xmlChar *)"", xmlstr); } node2 = xmlNewChild( node, NULL, (const xmlChar *)"", NULL ); .writeXML( node2, ctx ); { node2 = xmlNewChild( node, NULL, (const xmlChar *)"", NULL ); *item; ListItem<>* i; i = .first(); while( i ) { item = i->data(); if( item ) { item->writeXML( node2, ctx ); } i = i->next(); } } { if( && ) { char *tmp_data = (char *); int sz = ; char *tmpstr = new char[ (sz * 3) ]; int l = base64_encode( tmpstr, tmp_data, sz ); if( l > 0 ) { tmpstr[l] = 0; xmlNewTextChild( node, NULL, (const xmlChar *)"", (const xmlChar *)tmpstr ); } delete tmpstr; } } { if( ) { xmlDocPtr doc = xmlParseMemory(, strlen()); if( doc ) { xmlNodePtr child = doc->children; child = xmlDocCopyNode(child, node->doc, 1); xmlAddChild(node, child); xmlFreeDoc(doc); } } } ctx-> = ; swfmill-0.3.3/src/codegen/mk.xsl0000777000175000017500000000150712152542002013450 00000000000000 swfmill-0.3.3/src/SWFShapeItem.h0000777000175000017500000000204112234241357013321 00000000000000#ifndef SWF_SHAPEITEM_H #define SWF_SHAPEITEM_H #include namespace SWF { class ShapeItem : public Item { public: ShapeItem(); void setType( unsigned char t ) { type = t; } unsigned char type; int getHeaderSize( int size ); void writeHeader( Writer *w, Context *ctx, size_t len ); bool isEnd(); // static stuff public: static ShapeItem* get( Reader *r, int end, Context *ctx ); static ShapeItem* getByName( const char *name ); }; class LineTo : public ShapeItem { /* plain edges are a bit hairy, so we do them manually */ public: LineTo(); virtual bool parse( Reader *r, int end, Context *ctx ); virtual void dump( int indent, Context *ctx ); virtual size_t calcSize( Context *ctx, int start_at ); virtual void write( Writer *w, Context *ctx ); virtual void writeXML( xmlNodePtr node, Context *ctx ); virtual void parseXML( xmlNodePtr node, Context *ctx ); void setx( int x ); void sety( int y ); protected: int bits; int x, y; }; } #endif swfmill-0.3.3/src/SWFTag.h0000777000175000017500000000062612152542002012152 00000000000000#ifndef SWF_TAG_H #define SWF_TAG_H #include namespace SWF { #define SWF_LONG_TAG 8 class Tag : public IdItem { protected: int getHeaderSize( int size ) { return (size/8)>=SWF_LONG_TAG ? (6*8) : (2*8); } void writeHeader( Writer *w, Context *ctx, size_t len ); // static stuff public: static Tag* get( Reader *r, int end, Context *ctx ); }; } #endif swfmill-0.3.3/src/SWFItem.cpp0000777000175000017500000001037312234241357012702 00000000000000#include "SWFItem.h" #include #include #include "base64.h" #include namespace SWF { // ------------ utility functions int swf_get_bits_needed_for_uint( uint64_t value ) { int i=0; while( value > 0 ) { value >>= 1; i++; } return i; } int swf_get_bits_needed_for_int( int64_t value ) { if (value < 0) { return swf_get_bits_needed_for_uint(~value) + 1; } else if (value > 0) { return swf_get_bits_needed_for_uint(value) + 1; } else { // The SWF Specification is a bit vague about whether we require // any bits to represent zero as a signed integer, but Flash // Player appears to fall over sometimes if we set the size to // zero so let's use one bit to be safe. return 1; } } int swf_get_bits_needed_for_fp( double value, int exp = 16 ) { return swf_get_bits_needed_for_int( (int64_t)(value * (1 << exp)) ); } int SWFBitsNeeded( float value, int exp, bool is_signed ) { if( !is_signed ) { fprintf (stderr, "FIXME: calculate bits for unsigned float\n"); } return swf_get_bits_needed_for_fp( value, exp ); } int SWFBitsNeeded( int32_t value, bool is_signed ) { if( is_signed ) { return swf_get_bits_needed_for_int( value ); } else { return swf_get_bits_needed_for_uint( value ); } } long SWFMaxBitsNeeded( bool is_signed, int how_many, ... ) { long bits = 0; va_list ap; int n; va_start( ap, how_many ); for( int i=0; i bits ) bits = b; } va_end( ap ); return bits; } Item::Item() { file_offset = -1; cached_size = -1; } size_t Item::getSize( Context *ctx, int start_at ) { if( cached_size == -1 ) { cached_size = calcSize( ctx, start_at ); } return cached_size; } int Item::getHeaderSize( int size ) { return 0; } void Item::writeHeader( Writer *w, Context *ctx, size_t len ) { } Rest::Rest() { size = 0; data = NULL; } Rest::~Rest() { delete[] data; } bool Rest::parse( Reader *r, int end, Context *ctx ) { file_offset = r->getPosition(); size = end - r->getPosition(); if( size > 0 ) { data = new unsigned char[size]; r->getData( data, size ); } return r->getError() == SWFR_OK; } void Rest::dump( int indent, Context *ctx ) { for( int i=0; iputData( data, size ); } } #define TMP_STRLEN 0xFF void Rest::writeXML( xmlNodePtr xml, Context *ctx ) { char tmp[TMP_STRLEN]; xmlNodePtr node = xml; // node = xmlNewChild( node, NULL, (const xmlChar *)"Rest", NULL ); { if( size && data ) { char *tmp_data = (char *)data; int sz = size; char *tmpstr = new char[ (sz * 3) ]; int l = base64_encode( tmpstr, tmp_data, sz ); if( l > 0 ) { tmpstr[l] = 0; xmlNewTextChild( node, NULL, (const xmlChar *)"data", (const xmlChar *)tmpstr ); } delete[] tmpstr; } } } void Rest::parseXML( xmlNodePtr node, Context *ctx ) { data = NULL; size = 0; xmlChar *xmld = xmlNodeGetContent( node ); char *d = (char *)xmld; if( d ) { // unsure if this is neccessary for( int i=strlen(d)-1; i>0 && isspace(d[i]); i-- ) d[i]=0; while( isspace(d[0]) ) d++; int l = strlen(d); char *dst = new char[ l ]; int lout = base64_decode( dst, (char*)d, l ); if( lout > 0 ) { size = lout; data = new unsigned char[ lout ]; memcpy( data, dst, lout ); } delete[] dst; xmlFree( xmld ); } } void Rest::getdata( unsigned char **d, int *s ) { *d = data; *s = size; } void Rest::setdata( unsigned char *d, int s ) { delete[] data; data = NULL; size = s; if( size ) { data = new unsigned char[ size ]; memcpy( data, d, size ); } } } swfmill-0.3.3/src/SWFBasic.h0000777000175000017500000000024712152532502012463 00000000000000#ifndef SWF_BASIC_H #define SWF_BASIC_H #define SWF_WARNING(msg) fprintf(stderr,msg,...); #define SWF_ERROR(msg) { fprintf(stderr,msg,...); abort(); } #endif swfmill-0.3.3/src/SWFTag.cpp0000777000175000017500000000207412152542002012504 00000000000000#include #include "SWF.h" #include namespace SWF { Tag *Tag::get( Reader *r, int end, Context *ctx ) { uint16_t h = r->getWord(); int type = h>>6; int len = h&0x3F; if( len == 0x3F ) { // long size len = r->getInt(); } // sanity check if( len > 100000000 ) { fprintf(stderr,"ridiculous tag size: %i, ignoring.\n", len ); // r->setEOF(); return NULL; } Tag *ret = getByType( type ); if( !ret ) { ret = new UnknownTag; } ret->setType( type ); ret->setLength( len ); ret->parse( r, r->getPosition()+len, ctx ); return ret; } void Tag::writeHeader( Writer *w, Context *ctx, size_t len ) { // printf("write tag %02X, len %i, recorded %i(+header, 2 or 6), position %i\n", type, len, this->len, w->getPosition() ); // shouldnt this be 0x3f - macromedia flash seems to use long length for > 1F... len -= (len >= SWF_LONG_TAG + 6) ? 6 : 2; uint16_t h = type<<6; if( len >= SWF_LONG_TAG ) { h |= 0x3F; w->putWord(h); w->putInt(len); } else { h |= len; w->putWord(h); } } } swfmill-0.3.3/src/SWFGlyphList.cpp0000777000175000017500000001447212234241357013727 00000000000000#include "SWFGlyphList.h" #include #include "SWF.h" #include namespace SWF { GlyphList::GlyphList() { nGlyphs = 0; glyphs = NULL; map = 0; } GlyphList::~GlyphList() { delete[] glyphs; delete[] map; } bool GlyphList::parse( Reader *r, int end, Context *ctx ) { file_offset = r->getPosition(); int nOffsets; int s=0; if( ctx->tagVersion>1 ) { nGlyphs = ctx->glyphCount; nOffsets = nGlyphs+1; } else { nGlyphs = (r->getWord()/2); nOffsets = nGlyphs; s=1; } if( ctx->debugTrace ) fprintf(stderr, "GL nGlyphs: %i, glyphs %s, map %s\n", (int)nGlyphs, ctx->wideGlyphOffsets?"wide":"narrow", ctx->wideMap?"wide":"narrow" ); int offset[ nGlyphs+1 ]; memset( offset, 0, sizeof(int)*nGlyphs+1 ); if( ctx->wideGlyphOffsets ) { for( int i=s; igetInt(); } } else { for( int i=s; igetWord(); } } if( ctx->tagVersion<=1 ) { offset[0] = r->getPosition() - file_offset; offset[nOffsets] = end-file_offset; } /* int fillBits = r->getNBitInt(4); int lineBits = r->getNBitInt(4); if( fillBits != 1 || lineBits != 0 ) { fprintf(stderr,"WARNING: GlyphList fillBits: %i, lineBits: %i, expected 1/0\n", fillBits, lineBits ); } */ if( ctx->debugTrace ) fprintf(stderr, "Glyphs @%i offset[0]: %i\n", r->getPosition(), offset[0] ); glyphs = new GlyphShape[nGlyphs]; for( int i=0; idebugTrace ) fprintf(stderr, "PARSE glyph #%i @%i should be %i-%i\n", i, r->getPosition(), file_offset + offset[i], file_offset + offset[i+1] ); if( r->getPosition() != file_offset + offset[i] ) { fprintf(stderr,"WARNING: wrong offset at glyph %i, ofs %i but pos %i\n", i, offset[i], r->getPosition()-file_offset ); } glyphs[i].parse( r, file_offset + offset[i+1], ctx ); r->byteAlign(); } /* if( ctx->debugTrace ) fprintf(stderr, "PARSE last gylph %i\n", r->getPosition() ); glyphs[nGlyphs-1].parse( r, end, ctx ); r->byteAlign(); */ if( ctx->tagVersion>1 ) { if( ctx->debugTrace ) fprintf(stderr,"- parse GlyphMap" ); map = new int[ nGlyphs ]; if( ctx->wideMap ) { for( int i=0; igetWord(); } } else { for( int i=0; igetByte(); } } } return r->getError() == SWFR_OK; } void GlyphList::dump( int n, Context *ctx ) { for( int i=0; itagVersion>1 ) { r += ( ctx->wideGlyphOffsets ? 4 : 2 ) * (nGlyphs+1) * 8; } else { r += (nGlyphs+1) * 16; } /* // fillBits/lineBits ctx->fillBits = 1; ctx->lineBits = 0; r+=8 */ for( int i=0; itagVersion>1 ) r += ( ctx->wideMap ? 2 : 1 ) * nGlyphs * 8; /* fprintf(stderr,"SIZE DefineFont-%i, %s map\n", ctx->tagVersion, ctx->wideMap ? "wide" : "narrow" ); fprintf(stderr,"GL size: %i %i %i\n", nGlyphs, r, r/8 ); */ r += Item::getHeaderSize(r-start_at); return r-start_at; } void GlyphList::write( Writer *w, Context *ctx ) { Item::writeHeader( w, ctx, 0 ); int ofs = 0; if( ctx->tagVersion>1 ) { ofs = (( ctx->wideGlyphOffsets ? 4 : 2 ) * (nGlyphs+1)); } else { ofs = (nGlyphs+1)*2; } /* // fillBits/lineBits ofs++; */ ctx->fillBits = 1; ctx->lineBits = 1; ctx->wideGlyphOffsets ? w->putInt( ofs ) : w->putWord( ofs ); for( int i=0; iwideGlyphOffsets ? w->putInt( ofs ) : w->putWord( ofs ); } /* // fillBits/lineBits w->putNBitInt( 1, 4 ); w->putNBitInt( 0, 4 ); */ ofs = w->getPosition(); for( int i=0; ibyteAlign(); } if( ctx->tagVersion>1 ) { for( int i=0; iwideMap ? w->putWord( map[i] ) : w->putByte( map[i] ); } } } void GlyphList::writeXML( xmlNodePtr xml, Context *ctx ) { char tmp[32]; /* xmlNodePtr node = xmlNewChild( xml, NULL, (const xmlChar *)"GlyphList", NULL ); for( int i=0; itagVersion>1 && map ) { snprintf( tmp, 32, "%i", map[i] ); xmlSetProp( child, (const xmlChar *)"map", (const xmlChar *)tmp ); } } } void GlyphList::parseXML( xmlNodePtr node, Context *ctx ) { { nGlyphs = 0; xmlNodePtr child = node; while( child ) { if( !strcmp( (const char *)child->name, "Glyph" ) ) { nGlyphs++; } child = child->next; } ctx->glyphCount = nGlyphs; if( ctx->tagVersion>1 ) { map = new int[ nGlyphs ]; memset( map, 0, sizeof(int)*nGlyphs ); } glyphs = new GlyphShape[ nGlyphs ]; child = node; int i=0; while( child ) { if( !strcmp( (const char *)child->name, "Glyph" ) ) { xmlNodePtr shape = child->children; while( shape ) { if( !strcmp( (const char *)shape->name, "GlyphShape" ) ) { glyphs[i].parseXML( shape, ctx ); if( ctx->tagVersion>1 ) { xmlChar *tmp; tmp = xmlGetProp( child, (const xmlChar *)"map" ); if( tmp ) { sscanf( (char*)tmp, "%i", &map[i]); xmlFree( tmp ); if( map[i] > 0xFF ) ctx->wideMap = true; } else { map[i] = 0; } } i++; shape = NULL; } else { shape = shape->next; } } } child = child->next; } if( ctx->swfVersion >= 6 ) ctx->wideMap = true; } } void GlyphList::allocate( int n ) { delete[] map; delete[] glyphs; nGlyphs = n; glyphs = new GlyphShape[ nGlyphs ]; map = new int[ nGlyphs ]; memset( map, 0, sizeof(int)*nGlyphs ); } GlyphShape *GlyphList::getShapeN( int n ) { return &glyphs[n]; } void GlyphList::setMapN( int n, int m ) { map[n] = m; } } swfmill-0.3.3/src/SWFGlyphList.h0000777000175000017500000000143312234241357013365 00000000000000#ifndef SWF_GLYPHLIST_H #define SWF_GLYPHLIST_H #include namespace SWF { class GlyphShape; class GlyphList : public Item { /* glyph lists have strange offsetting stuff, so we do them manually */ public: GlyphList(); virtual ~GlyphList(); virtual bool parse( Reader *r, int end, Context *ctx ); virtual void dump( int indent, Context *ctx ); virtual size_t calcSize( Context *ctx, int start_at ); virtual void write( Writer *w, Context *ctx ); virtual void writeXML( xmlNodePtr node, Context *ctx ); virtual void parseXML( xmlNodePtr node, Context *ctx ); void allocate( int n ); GlyphShape *getShapeN( int n ); void setMapN( int n, int m ); protected: int nGlyphs; GlyphShape *glyphs; int *map; }; } #endif swfmill-0.3.3/src/xslt/0000775000175000017500000000000012234555372011766 500000000000000swfmill-0.3.3/src/xslt/simple-deprecated.xslt0000777000175000017500000000275012152542002016203 00000000000000 "set" is deprecated, please use assignments in place swfmill-0.3.3/src/xslt/xslt.h0000777000175000017500000000020112152542002013030 00000000000000#ifndef SWF_XSLT_H #define SWF_XSLT_H // definitions for "in-memory" stylesheets extern const char *xslt_simple; #endif swfmill-0.3.3/src/xslt/simple-tools.xslt0000777000175000017500000001765612152542002015256 00000000000000 0x 200 0x 200 0x 200 0x 0 0x 0 0x 0 0x 255 #00000000 0x 0 0x 0 0x 0 0x 255 3 < > </ > =" " swfmill-0.3.3/src/xslt/simple-elements.xslt0000777000175000017500000004555012152542002015724 00000000000000 7 1 0 1 12 1 0 0 6400 4800 1 0 1 0 0 1 0
0 0 1 0 0 1 1 1 0 0x200 0 0 1 1 1 0 0 0 0 100 100 240 20 1 0 2 1 0 0 0 0 160 120 0 1 0 0 1 Main main
swfmill-0.3.3/src/xslt/simple-import.xslt0000777000175000017500000004261512234074606015434 00000000000000 all WARNING: Cannot import (unknown extension), skipping. WARNING: Cannot import (unknown extension), skipping. New ID of "" component is: swfmill-0.3.3/src/xslt/simple-svg.xslt0000777000175000017500000002742212152542002014705 00000000000000 swfmill-0.3.3/src/xslt/assemble.xsl0000777000175000017500000000201412152542002014214 00000000000000 hack swft 1.0 xml yes quiet 'false' swfmill-0.3.3/src/xslt/simple.xml0000777000175000017500000000034612152542002013712 00000000000000 swfmill-0.3.3/src/swft/0000775000175000017500000000000012234555372011757 500000000000000swfmill-0.3.3/src/swft/swft_import_binary.cpp0000777000175000017500000000442412234241357016330 00000000000000#include #include #include #include #include "swft.h" #include #include #include #include "readpng.h" #include #define TMP_STRLEN 0xff void swft_import_binary( xmlXPathParserContextPtr ctx, int nargs ) { xsltTransformContextPtr tctx; char *filename; xsltDocumentPtr xsltdoc; xmlDocPtr doc = NULL; xmlNodePtr node; xmlXPathObjectPtr obj; char tmp[TMP_STRLEN]; unsigned char *data = NULL; xmlXPathStringFunction(ctx, 1); if (ctx->value->type != XPATH_STRING) { xsltTransformError(xsltXPathGetTransformContext(ctx), NULL, NULL, "swft:import-binary() : invalid arg expecting a string\n"); ctx->error = XPATH_INVALID_TYPE; return; } obj = valuePop(ctx); if (obj->stringval == NULL) { valuePush(ctx, xmlXPathNewNodeSet(NULL)); return; } tctx = xsltXPathGetTransformContext(ctx); filename = swft_get_filename( obj->stringval, ctx->context->doc->URL ); bool quiet = true; xmlXPathObjectPtr quietObj = xsltVariableLookup( tctx, (const xmlChar*)"quiet", NULL ); if( quietObj && quietObj->stringval ) { quiet = !strcmp("true",(const char*)quietObj->stringval ); }; FILE *fp = fopen( filename, "rb" ); if( !fp ) { xsltTransformError(xsltXPathGetTransformContext(ctx), NULL, NULL, "swft:import-binary() : failed to read file '%s'\n", filename); valuePush(ctx, xmlXPathNewNodeSet(NULL)); goto fail; } doc = xmlNewDoc( (const xmlChar *)"1.0"); doc->xmlRootNode = xmlNewDocNode( doc, NULL, (const xmlChar *)"binary", NULL ); node = doc->xmlRootNode; swft_addFileName( node, filename ); // add data int size; struct stat filestat; if( stat( filename, &filestat ) ) goto fail; size = filestat.st_size; data = new unsigned char[size]; if( fread( data, 1, size, fp ) != size ) { fprintf(stderr,"WARNING: could not read enough (%i) bytes for binary %s\n", size, filename ); goto fail; } if( !quiet ) { fprintf(stderr,"Importing binary: '%s'\n", filename); } swft_addData( node, (char*)data, size ); valuePush( ctx, xmlXPathNewNodeSet( (xmlNodePtr)doc ) ); fail: if( fp ) fclose(fp); if( data ) delete data; delete filename; } swfmill-0.3.3/src/swft/swft.cpp0000777000175000017500000002466112234241357013377 00000000000000#include #include #include #include #include #include #include #include #include "swft.h" #define TMP_STRLEN 0xFF #define SWFT_MAPSIZE 32 using namespace SWF; void *swft_init( xsltTransformContextPtr ctx, const xmlChar *URI ); void swft_shutdown( xsltTransformContextPtr ctx, const xmlChar *URI, void *data ); static void swft_error( xsltTransformContextPtr ctx, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp ); static void swft_nextid( xmlXPathParserContextPtr ctx, int nargs ); static void swft_nextdepth( xmlXPathParserContextPtr ctx, int nargs ); static void swft_pushmap( xsltTransformContextPtr ctx, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp ); static void swft_popmap( xsltTransformContextPtr ctx, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp ); static void swft_mapid( xmlXPathParserContextPtr ctx, int nargs ); static void swft_setmap( xmlXPathParserContextPtr ctx, int nargs ); // in swft_import_*.cpp // FIXME why are these not static? any reason? void swft_import_jpeg( xmlXPathParserContextPtr ctx, int nargs ); void swft_import_jpega( xmlXPathParserContextPtr ctx, int nargs ); void swft_import_png( xmlXPathParserContextPtr ctx, int nargs ); void swft_import_ttf( xmlXPathParserContextPtr ctx, int nargs ); void swft_import_mp3( xmlXPathParserContextPtr ctx, int nargs ); void swft_import_wav( xmlXPathParserContextPtr ctx, int nargs ); void swft_import_binary( xmlXPathParserContextPtr ctx, int nargs ); // in swft_document void swft_document( xmlXPathParserContextPtr ctx, int nargs ); // in swft_path void swft_path( xmlXPathParserContextPtr ctx, int nargs ); void swft_bounds( xmlXPathParserContextPtr ctx, int nargs ); void swft_transform( xmlXPathParserContextPtr ctx, int nargs ); static void swft_pushgradient( xsltTransformContextPtr ctx, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr com ) { swft_ctx *c = (swft_ctx*)xsltGetExtData( ctx, SWFT_NAMESPACE ); xmlChar *id, *href; SVGGradient *gradient; id = xmlGetProp(node, (const xmlChar *)"id"); if(id) { if(!xmlStrcmp(node->name, (const xmlChar *)"linearGradient")) { gradient = new SVGLinearGradient(); } else if(!xmlStrcmp(node->name, (const xmlChar *)"radialGradient")) { gradient = new SVGRadialGradient(); } href = xmlGetProp(node, (const xmlChar *)"href"); if (href) { string hrefStr = (const char *)href; hrefStr.erase(0, 1); map::iterator i = c->gradients.find(hrefStr); if(i != c->gradients.end()) { *gradient = *((*i).second); } xmlFree(href); } gradient->parse(node); c->gradients[(char *)id] = gradient; xmlFree(id); } } static void swft_popstyle( xsltTransformContextPtr ctx, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr com ) { swft_ctx *c = (swft_ctx*)xsltGetExtData( ctx, SWFT_NAMESPACE ); c->styles.pop(); } static void swft_pushstyle( xsltTransformContextPtr ctx, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr com ) { swft_ctx *c = (swft_ctx*)xsltGetExtData( ctx, SWFT_NAMESPACE ); SVGStyle style; if(c->styles.size() > 0) { style = c->styles.top(); } style.parseNode(node, c->gradients); c->styles.push(style); } static void swft_nextid( xmlXPathParserContextPtr ctx, int nargs ) { char tmp[TMP_STRLEN]; swft_ctx *c = (swft_ctx*)xsltGetExtData( xsltXPathGetTransformContext(ctx), SWFT_NAMESPACE ); snprintf(tmp,TMP_STRLEN,"%i", c->last_id++ ); valuePush(ctx, xmlXPathNewString((const xmlChar *)tmp)); } static void swft_nextdepth( xmlXPathParserContextPtr ctx, int nargs ) { char tmp[TMP_STRLEN]; swft_ctx *c = (swft_ctx*)xsltGetExtData( xsltXPathGetTransformContext(ctx), SWFT_NAMESPACE ); snprintf(tmp,TMP_STRLEN,"%i", c->last_depth++ ); valuePush(ctx, xmlXPathNewString((const xmlChar *)tmp)); } static void swft_pushmap( xsltTransformContextPtr ctx, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp ) { swft_ctx *c = (swft_ctx*)xsltGetExtData( ctx, SWFT_NAMESPACE ); c->pushMap(); } static void swft_popmap( xsltTransformContextPtr ctx, xmlNodePtr node, xmlNodePtr inst, xsltElemPreCompPtr comp ) { swft_ctx *c = (swft_ctx*)xsltGetExtData( ctx, SWFT_NAMESPACE ); c->popMap(); } static void swft_setmap( xmlXPathParserContextPtr ctx, int nargs ) { swft_ctx *c = (swft_ctx*)xsltGetExtData( xsltXPathGetTransformContext(ctx), SWFT_NAMESPACE ); if( (nargs != 2) ) { xmlXPathSetArityError(ctx); return; } int to = (int)xmlXPathPopNumber(ctx); xmlChar *from = xmlXPathPopString(ctx); if( xmlXPathCheckError(ctx) ) return; c->setMap((const char *)from,to); xmlFree( from ); valuePush(ctx, xmlXPathNewString((const xmlChar *)"")); } static void swft_bump_id( xmlXPathParserContextPtr ctx, int nargs ) { swft_ctx *c = (swft_ctx*)xsltGetExtData( xsltXPathGetTransformContext(ctx), SWFT_NAMESPACE ); if( (nargs != 1) ) { xmlXPathSetArityError(ctx); return; } int offset = (int)xmlXPathPopNumber(ctx); if( xmlXPathCheckError(ctx) ) return; if( offset >= c->last_id ) c->last_id = offset+1; valuePush(ctx, xmlXPathNewString((const xmlChar *)"")); } static void swft_bump_depth( xmlXPathParserContextPtr ctx, int nargs ) { swft_ctx *c = (swft_ctx*)xsltGetExtData( xsltXPathGetTransformContext(ctx), SWFT_NAMESPACE ); if( (nargs != 1) ) { xmlXPathSetArityError(ctx); return; } int offset = (int)xmlXPathPopNumber(ctx); if( xmlXPathCheckError(ctx) ) return; if( offset >= c->last_depth ) c->last_depth = offset+1; valuePush(ctx, xmlXPathNewString((const xmlChar *)"")); } static void swft_mapid( xmlXPathParserContextPtr ctx, int nargs ) { char tmp[TMP_STRLEN]; xmlXPathObjectPtr obj; xmlChar *oldID; int newID; swft_ctx *c = (swft_ctx*)xsltGetExtData( xsltXPathGetTransformContext(ctx), SWFT_NAMESPACE ); xmlXPathStringFunction(ctx, 1); if (ctx->value->type != XPATH_STRING) { xsltTransformError(xsltXPathGetTransformContext(ctx), NULL, NULL, "swft:mapid() : invalid arg expecting a string (the old id)\n"); ctx->error = XPATH_INVALID_TYPE; return; } obj = valuePop(ctx); if (obj->stringval == NULL) { valuePush(ctx, xmlXPathNewNodeSet(NULL)); return; } // (int)xmlXPathStringEvalNumber() oldID = obj->stringval; newID = c->doMap((const char*)oldID); xmlFree( oldID ); snprintf(tmp,TMP_STRLEN,"%i", newID ); valuePush(ctx, xmlXPathNewString((const xmlChar *)tmp)); } char *swft_get_filename( const xmlChar *uri, const xmlChar *baseUri ) { uri = xmlBuildURI(uri, baseUri); const xmlChar *path; // very closely based on the behaviour of xmlFileOpen_real from // libxml2 if (xmlStrncasecmp(uri, BAD_CAST "file://localhost/", 17) == 0) { #if defined (_WIN32) || defined(__DJGPP__) && !defined(__CYGWIN__) path = &uri[17]; #else path = &uri[16]; #endif } else if (xmlStrncasecmp(uri, BAD_CAST "file:///", 8) == 0) { #if defined (_WIN32) || defined(__DJGPP__) && !defined(__CYGWIN__) path = &uri[7]; #else path = &uri[8]; #endif } else if (xmlStrncmp(uri, BAD_CAST "file:/", 6) == 0) { // URLs in this form are invalid but nevertheless common. #if defined (_WIN32) || defined(__DJGPP__) && !defined(__CYGWIN__) path = &uri[6]; #else path = &uri[5]; #endif } else { path = uri; } size_t input_bytes_left = xmlStrlen(path); size_t output_bytes_left = input_bytes_left*4; ICONV_CONST char *input_buffer = (ICONV_CONST char*)path; char *output_buffer = new char[output_bytes_left + 1]; char *filename = output_buffer; iconv_t cd = iconv_open("", "UTF-8"); size_t output_len = iconv(cd, &input_buffer, &input_bytes_left, &output_buffer, &output_bytes_left); iconv_close(cd); *output_buffer = '\0'; delete uri; if (output_len == -1) { fprintf(stderr, "Error converting filename from UTF-8 " "to system locale\n"); exit(1); } else { return filename; } } void swft_register() { xsltRegisterExtModule((const xmlChar *)SWFT_NAMESPACE, swft_init, swft_shutdown ); } void *swft_init( xsltTransformContextPtr ctx, const xmlChar *URI ) { xsltRegisterExtFunction( ctx, (const xmlChar *) "next-id", SWFT_NAMESPACE, swft_nextid); xsltRegisterExtFunction( ctx, (const xmlChar *) "next-depth", SWFT_NAMESPACE, swft_nextdepth); xsltRegisterExtFunction( ctx, (const xmlChar *) "map-id", SWFT_NAMESPACE, swft_mapid); xsltRegisterExtElement( ctx, (const xmlChar *) "push-map", SWFT_NAMESPACE, swft_pushmap); xsltRegisterExtElement( ctx, (const xmlChar *) "pop-map", SWFT_NAMESPACE, swft_popmap); xsltRegisterExtFunction( ctx, (const xmlChar *) "set-map", SWFT_NAMESPACE, swft_setmap); xsltRegisterExtFunction( ctx, (const xmlChar *) "bump-id", SWFT_NAMESPACE, swft_bump_id); xsltRegisterExtFunction( ctx, (const xmlChar *) "bump-depth", SWFT_NAMESPACE, swft_bump_depth); xsltRegisterExtFunction( ctx, (const xmlChar *) "document", SWFT_NAMESPACE, swft_document); xsltRegisterExtFunction( ctx, (const xmlChar *) "path", SWFT_NAMESPACE, swft_path); // xsltRegisterExtFunction( ctx, (const xmlChar *) "bounds", SWFT_NAMESPACE, swft_bounds); xsltRegisterExtFunction( ctx, (const xmlChar *) "transform", SWFT_NAMESPACE, swft_transform); xsltRegisterExtElement( ctx, (const xmlChar *) "push-style", SWFT_NAMESPACE, swft_pushstyle); xsltRegisterExtElement( ctx, (const xmlChar *) "pop-style", SWFT_NAMESPACE, swft_popstyle); xsltRegisterExtElement( ctx, (const xmlChar *) "push-gradient", SWFT_NAMESPACE, swft_pushgradient); xsltRegisterExtFunction( ctx, (const xmlChar *) "import-jpeg", SWFT_NAMESPACE, swft_import_jpeg ); xsltRegisterExtFunction( ctx, (const xmlChar *) "import-jpega", SWFT_NAMESPACE, swft_import_jpega ); xsltRegisterExtFunction( ctx, (const xmlChar *) "import-png", SWFT_NAMESPACE, swft_import_png ); xsltRegisterExtFunction( ctx, (const xmlChar *) "import-ttf", SWFT_NAMESPACE, swft_import_ttf ); xsltRegisterExtFunction( ctx, (const xmlChar *) "import-mp3", SWFT_NAMESPACE, swft_import_mp3 ); xsltRegisterExtFunction( ctx, (const xmlChar *) "import-wav", SWFT_NAMESPACE, swft_import_wav ); xsltRegisterExtFunction( ctx, (const xmlChar *) "import-binary", SWFT_NAMESPACE, swft_import_binary ); swft_ctx *c = new swft_ctx; return c; } void swft_shutdown( xsltTransformContextPtr ctx, const xmlChar *URI, void *data ) { swft_ctx *c = (swft_ctx*)data; delete c; } swfmill-0.3.3/src/swft/SVGPathParser.cpp0000777000175000017500000000652312152542002015030 00000000000000#include "SVGPathParser.h" using namespace std; namespace SWF { PathParser::PathParser(ShapeMaker *shapeMaker) { shaper = shapeMaker; } void PathParser::parse(const char *path) { char currentChar, currentCmd = 0; CharType charType; bool repeated = false; //use <= strlen() to make sure the last parameter is parsed correctly for(size_t i = 0; i <= strlen(path); i++) { currentChar = path[i]; charType = getCharType(currentChar); if(charType != OTHER) { if(params.size() != 0 && params.size() == getParameterCount(currentCmd)) { executeCommand(currentCmd, repeated); params.clear(); repeated = true; } if(charType == COMMAND_ABSOLUTE || charType == COMMAND_RELATIVE) { if(params.size() > 0) { cerr << "WARNING: too much parameters in SVG path" << endl; params.clear(); } currentCmd = currentChar; if(getParameterCount(currentCmd) == 0) { executeCommand(currentCmd, repeated); } repeated = false; } } else { char *str = (char*)path + i; char *tailPtr; params.push_back(strtod(str, &tailPtr)); i += tailPtr - str - 1; } } if(params.size() > 0) { cerr << "WARNING: too much parameters in SVG path" << endl; params.clear(); } shaper->close(false); shaper->finish(); } void PathParser::executeCommand(char command, bool repeated) { switch(command) { case 'Q': shaper->curveTo(params[0], params[1], params[2], params[3]); break; case 'q': shaper->curveToR(params[0], params[1], params[2], params[3]); break; case 'T': shaper->smoothCurveTo(params[0], params[1]); break; case 't': shaper->smoothCurveToR(params[0], params[1]); break; case 'C': shaper->cubicTo(params[0], params[1], params[2], params[3], params[4], params[5]); break; case 'c': shaper->cubicToR(params[0], params[1], params[2], params[3], params[4], params[5]); break; case 'S': shaper->smoothCubicTo(params[0], params[1], params[2], params[3]); break; case 's': shaper->smoothCubicToR(params[0], params[1], params[2], params[3]); break; case 'L': shaper->lineTo(params[0], params[1]); break; case 'l': shaper->lineToR(params[0], params[1]); break; case 'M': if(repeated) { shaper->lineTo(params[0], params[1]); } else { shaper->close(false); shaper->setup(params[0], params[1]); } break; case 'm': if(repeated) { shaper->lineToR(params[0], params[1]); } else { shaper->close(false); shaper->setupR(params[0], params[1]); } break; case 'H': shaper->lineTo(params[0], shaper->getLastY()); break; case 'h': shaper->lineToR(params[0], 0); break; case 'V': shaper->lineTo(shaper->getLastX(), params[0]); break; case 'v': shaper->lineToR(0, params[0]); break; case 'A': shaper->arcTo(params[0], params[1], params[2], (params[3] == 1), (params[4] == 1), params[5], params[6]); break; case 'a': shaper->arcToR(params[0], params[1], params[2], (params[3] == 1), (params[4] == 1), params[5], params[6]); break; case 'Z': case 'z': shaper->close(); break; default: cerr << "WARNING: SVG path command not implemented (" << command << ")" << endl; break; } } } swfmill-0.3.3/src/swft/swft_path.cpp0000777000175000017500000001212312152542002014367 00000000000000#include "swft.h" #include "SVGPathParser.h" #include "SVGTransformParser.h" #include "SVGAttributeParser.h" #include "SVGPointsParser.h" #include "SVGStyle.h" #include #include #include using namespace SWF; /* Create a complete DefineShape3 element. syntax: swft:path( , , ) */ void swft_path(xmlXPathParserContextPtr ctx, int nargs) { xmlChar *styleString, *idString, *pathString; xmlDocPtr doc; xmlNodePtr node; xmlNodeSetPtr nodeSet; double movieVersion; if(nargs != 3) { xmlXPathSetArityError(ctx); return; } movieVersion = xmlXPathPopNumber(ctx); idString = xmlXPathPopString(ctx); nodeSet = xmlXPathPopNodeSet(ctx); if(nodeSet == NULL || nodeSet->nodeNr != 1) { xmlXPathSetTypeError(ctx); return; } node = nodeSet->nodeTab[0]; swft_ctx *c = (swft_ctx*)xsltGetExtData(xsltXPathGetTransformContext(ctx), SWFT_NAMESPACE); SVGStyle style; if(c->styles.size() > 0) { style = c->styles.top(); } style.parseNode(node, c->gradients); if(!style.hasStyle()) { style.setFillColor("#000"); } Shape shape; int xOffset = 0, yOffset = 0; ShapeMaker shaper(shape.getedges(), 20, 20, xOffset, yOffset); shaper.setStyle(style.hasFill() ? 1 : -1, -1, style.hasStroke() ? 1 : -1); AttributeParser attribs; attribs.parseNode(node); if(!xmlStrcmp(node->name, (const xmlChar *)"path")) { const char* pathString = attribs["d"]; if(pathString) { PathParser parser(&shaper); parser.parse(pathString); } } else if(!xmlStrcmp(node->name, (const xmlChar *)"rect")) { double w = attribs.getDouble("width"); double h = attribs.getDouble("height"); if(w > 0 && h > 0) { double rx = attribs.getDouble("rx"); double ry = attribs.getDouble("ry"); if(attribs["rx"] == NULL && attribs["ry"] == NULL) { rx = ry = 0; } else if(attribs["rx"] == NULL && attribs["ry"] != NULL) { rx = ry; } else if(attribs["rx"] != NULL && attribs["ry"] == NULL) { ry = rx; } if(rx > w / 2) rx = w / 2; if(ry > h / 2) ry = h / 2; shaper.rect( attribs.getDouble("x"), attribs.getDouble("y"), w, h, rx, ry); } } else if(!xmlStrcmp(node->name, (const xmlChar *)"circle")) { double r = attribs.getDouble("r"); if(r > 0) shaper.ellipse(attribs.getDouble("cx"), attribs.getDouble("cy"), r, r); } else if(!xmlStrcmp(node->name, (const xmlChar *)"ellipse")) { double rx = attribs.getDouble("rx"); double ry = attribs.getDouble("ry"); if(rx > 0 && ry > 0) shaper.ellipse(attribs.getDouble("cx"), attribs.getDouble("cy"), rx, ry); } else if(!xmlStrcmp(node->name, (const xmlChar *)"line")) { shaper.setup(attribs.getDouble("x1"), attribs.getDouble("y1")); shaper.lineTo(attribs.getDouble("x2"), attribs.getDouble("y2")); } else if(!xmlStrcmp(node->name, (const xmlChar *)"polyline") || !xmlStrcmp(node->name, (const xmlChar *)"polygon")) { PointsParser parser; parser.parse(attribs["points"]); if(parser.getPointCount() >= 2) { Point point, firstPoint; firstPoint = parser.getPoint(); shaper.setup(firstPoint.x, firstPoint.y); int pointCount = parser.getPointCount(); for(int i = 0; i < pointCount; i++) { point = parser.getPoint(); shaper.lineTo(point.x, point.y); } if(!xmlStrcmp(node->name, (const xmlChar *)"polyline")) { shaper.close(false); } else { shaper.close(true); } } } xmlNodePtr shapeNode, styleNode; // make the shape xml doc = xmlNewDoc( (const xmlChar *)"1.0"); if(movieVersion > 7) { node = shapeNode = doc->xmlRootNode = xmlNewDocNode( doc, NULL, (const xmlChar *)"DefineShape5", NULL ); } else { node = shapeNode = doc->xmlRootNode = xmlNewDocNode( doc, NULL, (const xmlChar *)"DefineShape3", NULL ); } xmlSetProp( node, (const xmlChar*)"objectID", idString ); // bounds shaper.boundsWriteXML(shapeNode, (style.hasStroke() ? style.getStrokeWidth() / 2 : 0)); // stroke bounds if(movieVersion > 7) shaper.boundsWriteXML(shapeNode); // styles node = xmlNewChild(shapeNode, NULL, (const xmlChar *)"styles", NULL); style.setBounds(shaper.getBounds()); style.writeXML(node, movieVersion); // the shape itself shaper.finish(); node = xmlNewChild(shapeNode, NULL, (const xmlChar *)"shapes", NULL); Context swfctx; shape.writeXML( node, &swfctx ); valuePush( ctx, xmlXPathNewNodeSet( (xmlNodePtr)doc ) ); return; } void swft_transform( xmlXPathParserContextPtr ctx, int nargs ) { if(nargs != 1) { xmlXPathSetArityError(ctx); return; } xmlChar *transform = xmlXPathPopString(ctx); if(xmlXPathCheckError(ctx) || (transform == NULL)) { return; } TransformParser transformParser; transformParser.parse((char *)transform); xmlDocPtr doc; doc = xmlNewDoc( (const xmlChar *)"1.0"); doc->xmlRootNode = xmlNewDocNode( doc, NULL, (const xmlChar *)"Transform", NULL ); transformParser.getMatrix().setXMLProps(doc->xmlRootNode); valuePush( ctx, xmlXPathNewNodeSet( (xmlNodePtr)doc ) ); } swfmill-0.3.3/src/swft/readpng.c0000777000175000017500000002367712234345035013500 00000000000000/*--------------------------------------------------------------------------- rpng - simple PNG display program readpng.c --------------------------------------------------------------------------- Copyright (c) 1998-2000 Greg Roelofs. All rights reserved. This software is provided "as is," without warranty of any kind, express or implied. In no event shall the author or contributors be held liable for any damages arising in any way from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. Redistributions of source code must retain the above copyright notice, disclaimer, and this list of conditions. 2. Redistributions in binary form must reproduce the above copyright notice, disclaimer, and this list of conditions in the documenta- tion and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgment: This product includes software developed by Greg Roelofs and contributors for the book, "PNG: The Definitive Guide," published by O'Reilly and Associates. --------------------------------------------------------------------------- NOTE: Greg Roelofs gave explicit permission to use this code under the terms of GPLv2: Greg Roelofs , on Mon, 30 Apr 2007 09:01:24 -0700: > I have no interest in being > petty about this--and I've already been leaning toward copyleft > licensing in my other projects over the last few years--so I've > decided to go ahead and dual-license the pngbook code (readpng{,2}, > writepng, rpng{,2}-{x,win}, wpng) under the GNU GPL v2 or later. You > may take this message as explicit permission insofar as it's likely > to be a while before I actually get around to releasing a new version > of the code--I'm working on XV right now and have pngcheck and a > couple others queued up next. (I'll do my best to do so be- fore the > next version of libpng goes out, however, so the contrib code can be > updated at the same time.) ---------------------------------------------------------------------------*/ #include #include #include "zlib.h" /* Apparently png.h doesn't include this any more */ #include "png.h" #include "readpng.h" /* typedefs, common macros, public prototypes */ /* future versions of libpng will provide this macro: */ #ifndef png_jmpbuf # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) #endif static png_structp png_ptr = NULL; static png_infop info_ptr = NULL; png_uint_32 width, height; int bit_depth, color_type; uch *image_data = NULL; void readpng_version_info(void) { fprintf(stderr, " Compiled with libpng %s; using libpng %s.\n", PNG_LIBPNG_VER_STRING, png_libpng_ver); fprintf(stderr, " Compiled with zlib %s; using zlib %s.\n", ZLIB_VERSION, zlib_version); } /* return value = 0 for success, 1 for bad sig, 2 for bad IHDR, 4 for no mem */ int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight) { uch sig[8]; /* first do a quick check that the file really is a PNG image; could * have used slightly more general png_sig_cmp() function instead */ fread(sig, 1, 8, infile); if (!png_check_sig(sig, 8)) return 1; /* bad signature */ /* could pass pointers to user-defined error handlers instead of NULLs: */ png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (!png_ptr) return 4; /* out of memory */ info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) { png_destroy_read_struct(&png_ptr, NULL, NULL); return 4; /* out of memory */ } /* we could create a second info struct here (end_info), but it's only * useful if we want to keep pre- and post-IDAT chunk info separated * (mainly for PNG-aware image editors and converters) */ /* setjmp() must be called in every function that calls a PNG-reading * libpng function */ if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return 2; } png_init_io(png_ptr, infile); png_set_sig_bytes(png_ptr, 8); /* we already read the 8 signature bytes */ png_read_info(png_ptr, info_ptr); /* read all PNG info up to image data */ /* alternatively, could make separate calls to png_get_image_width(), * etc., but want bit_depth and color_type for later [don't care about * compression_type and filter_type => NULLs] */ png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, NULL, NULL, NULL); *pWidth = width; *pHeight = height; /* OK, that's all we need for now; return happy */ return 0; } /* returns 0 if succeeds, 1 if fails due to no bKGD chunk, 2 if libpng error; * scales values to 8-bit if necessary */ int readpng_get_bgcolor(uch *red, uch *green, uch *blue) { png_color_16p pBackground; /* setjmp() must be called in every function that calls a PNG-reading * libpng function */ if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return 2; } if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_bKGD)) return 1; /* it is not obvious from the libpng documentation, but this function * takes a pointer to a pointer, and it always returns valid red, green * and blue values, regardless of color_type: */ png_get_bKGD(png_ptr, info_ptr, &pBackground); /* however, it always returns the raw bKGD data, regardless of any * bit-depth transformations, so check depth and adjust if necessary */ if (bit_depth == 16) { *red = pBackground->red >> 8; *green = pBackground->green >> 8; *blue = pBackground->blue >> 8; } else if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) { if (bit_depth == 1) *red = *green = *blue = pBackground->gray? 255 : 0; else if (bit_depth == 2) *red = *green = *blue = (255/3) * pBackground->gray; else /* bit_depth == 4 */ *red = *green = *blue = (255/15) * pBackground->gray; } else { *red = (uch)pBackground->red; *green = (uch)pBackground->green; *blue = (uch)pBackground->blue; } return 0; } /* display_exponent == LUT_exponent * CRT_exponent */ uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes, png_colorp *palette, int *n_pal ) { double gamma; png_uint_32 i, rowbytes; png_bytepp row_pointers = NULL; /* setjmp() must be called in every function that calls a PNG-reading * libpng function */ if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } /* expand palette images to 8bit, low-bit-depth grayscale images to 8 bits, * transparency chunks to full alpha channel; strip 16-bit-per-sample * images to 8 bits per sample; and convert grayscale to 8bit */ *n_pal = 0; *palette = NULL; if (color_type == PNG_COLOR_TYPE_PALETTE) { png_set_packing( png_ptr ); if( png_get_valid(png_ptr, info_ptr, PNG_INFO_PLTE) ) { png_get_PLTE( png_ptr, info_ptr, palette, n_pal ); } } if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) png_set_expand(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand(png_ptr); if (bit_depth == 16) png_set_strip_16(png_ptr); if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { png_set_packing( png_ptr ); } /* unlike the example in the libpng documentation, we have *no* idea where * this file may have come from--so if it doesn't have a file gamma, don't * do any correction ("do no harm") */ if (png_get_gAMA(png_ptr, info_ptr, &gamma)) png_set_gamma(png_ptr, display_exponent, gamma); /* all transformations have been registered; now update info_ptr data, * get rowbytes and channels, and allocate image memory */ png_read_update_info(png_ptr, info_ptr); *pRowbytes = rowbytes = png_get_rowbytes(png_ptr, info_ptr); *pChannels = (int)png_get_channels(png_ptr, info_ptr); if ((image_data = (uch *)malloc(rowbytes*height)) == NULL) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); return NULL; } if ((row_pointers = (png_bytepp)malloc(height*sizeof(png_bytep))) == NULL) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); free(image_data); image_data = NULL; return NULL; } Trace((stderr, "readpng_get_image: channels = %d, rowbytes = %ld, height = %ld\n", *pChannels, rowbytes, height)); /* set the individual row_pointers to point at the correct offsets */ for (i = 0; i < height; ++i) row_pointers[i] = image_data + i*rowbytes; /* now we can go ahead and just read the whole image */ png_read_image(png_ptr, row_pointers); /* and we're done! (png_read_end() can be omitted if no processing of * post-IDAT text/time/etc. is desired) */ free(row_pointers); row_pointers = NULL; png_read_end(png_ptr, NULL); return image_data; } void readpng_cleanup(int free_image_data) { if (free_image_data && image_data) { free(image_data); image_data = NULL; } if (png_ptr && info_ptr) { png_destroy_read_struct(&png_ptr, &info_ptr, NULL); png_ptr = NULL; info_ptr = NULL; } } swfmill-0.3.3/src/swft/SVGPathParser.h0000777000175000017500000000342012152542002014466 00000000000000#ifndef SVG_PATHPARSER_H #define SVG_PATHPARSER_H #include #include #include #include #include #include #include "SWFShapeMaker.h" #include "SWF.h" namespace SWF { class PathParser { public: PathParser(ShapeMaker *shapeMaker); void parse(const char *path); private: std::vector params; ShapeMaker *shaper; enum CharType { COMMAND_ABSOLUTE, COMMAND_RELATIVE, WHITESPACE, OTHER }; void executeCommand(char command, bool repeated); CharType getCharType(char c) { switch(c) { case 'M': case 'Z': case 'L': case 'H': case 'V': case 'C': case 'S': case 'Q': case 'T': case 'A': return COMMAND_ABSOLUTE; break; case 'm': case 'z': case 'l': case 'h': case 'v': case 'c': case 's': case 'q': case 't': case 'a': return COMMAND_RELATIVE; break; case '\t': case '\n': case '\r': case ',': case ' ': case 0: return WHITESPACE; break; default: return OTHER; break; } } size_t getParameterCount(char command) { switch(command) { case 'z': case 'Z': return 0; break; case 'h': case 'H': case 'v': case 'V': return 1; break; case 'm': case 'M': case 'l': case 'L': case 't': case 'T': return 2; break; case 's': case 'S': case 'q': case 'Q': return 4; break; case 'c': case 'C': return 6; break; case 'a': case 'A': return 7; break; } return 0; } }; } #endif swfmill-0.3.3/src/swft/SVGAttributeParser.cpp0000777000175000017500000000576512234241357016120 00000000000000#include "SVGAttributeParser.h" #include #define DPI 90.0 using namespace std; namespace SWF { void AttributeParser::parseNode(xmlNodePtr node) { for(xmlAttrPtr attr = node->properties; attr != NULL; attr = attr->next) { xmlChar *tmp = xmlGetProp(node, attr->name); if(tmp) { vector values; values.push_back ((const char *) tmp); attributes[(const char *)attr->name] = values; xmlFree(tmp); } } xmlChar *tmp = xmlGetProp(node, (const xmlChar *)"style"); if(tmp) { doParse((char *)tmp); xmlFree(tmp); } } double AttributeParser::getDouble(const char* attribute, double defaultValue, double value100) { const char *tmp = getString(attribute); if(tmp) { string tmpStr = tmp; char *tailPtr; double value = strtod(tmpStr.c_str(), &tailPtr); string unit = tailPtr; trimString(unit); if(unit == "in") { value *= DPI; } else if(unit == "cm") { value *= DPI / 2.54; } else if(unit == "mm") { value *= DPI / 25.4; } else if(unit == "pt") { value *= DPI / 72.0; } else if(unit == "pc") { value *= DPI / 72.0 * 12.0; } else if(unit == "%") { value *= value100 / 100; } return value; } else { return defaultValue; } } const char *AttributeParser::getString(const char* attribute) { map >::iterator iter = attributes.find(attribute); if (iter == attributes.end ()) { return NULL; } return (*iter).second [0].c_str (); } const char *AttributeParser::operator[](const char* attribute) { return getString(attribute); } const map > &AttributeParser::getAttributes() { return attributes; } void AttributeParser::handleData(const string& attrib, const vector& value) { // Unused. } void AttributeParser::doParse(const char* str) { int ich = 0; int cch = strlen (str); char ch; while (ich < cch) { string attrib; while (ich < cch && (ch = str[ich++]) != ':') { attrib += ch; } trimString (attrib); vector params; bool fNextAttribute = false; while (ich < cch && !fNextAttribute) { // skip whitespace while (ich < cch && isWhitespace (str [ich])) { ich ++; } string value; int cParens = 0; while (ich < cch) { char ch = str [ich++]; if (cParens <= 0) { if (ch == ';') { fNextAttribute = true; break; } if (isWhitespace (ch)) { break; } } value += ch; if (ch == '(') { cParens ++; } else if (ch == ')') { cParens --; if (cParens < 0) { cerr << "WARNING: unexpected ')' in '" << str << "'" << endl; } } } if (cParens != 0) { cerr << "WARNING: unbalanced '(' in '" << str << "'" << endl; } trimString(value); if (value.length () > 0) { params.push_back (value); } } if (attrib.length () > 0 && params.size () > 0) { attributes[attrib] = params; } } } } swfmill-0.3.3/src/swft/swft_document.cpp0000777000175000017500000000304112234241357015262 00000000000000#include "SWFShapeMaker.h" #include "SWFFile.h" #include "swft.h" #include #include #include #include using namespace SWF; void swft_document( xmlXPathParserContextPtr ctx, int nargs ) { xsltTransformContextPtr tctx; char *filename; xsltDocumentPtr xsltdoc; xmlDocPtr doc = NULL; xmlXPathObjectPtr obj; xmlChar *base = NULL; char sig; File import; xmlXPathStringFunction(ctx, 1); if (ctx->value->type != XPATH_STRING) { xsltTransformError(xsltXPathGetTransformContext(ctx), NULL, NULL, "swft:document() : invalid arg expecting a string\n"); ctx->error = XPATH_INVALID_TYPE; return; } obj = valuePop(ctx); if (obj->stringval == NULL) { valuePush(ctx, xmlXPathNewNodeSet(NULL)); return; } tctx = xsltXPathGetTransformContext(ctx); filename = swft_get_filename( obj->stringval, ctx->context->doc->URL); FILE *fp = fopen( filename, "rb" ); if( !fp ) { xsltTransformError(xsltXPathGetTransformContext(ctx), NULL, NULL, "swft:document() : failed to read file '%s'\n", filename); valuePush(ctx, xmlXPathNewNodeSet(NULL)); goto fail; } import.load( fp ); doc = import.getXML(); if( !doc ) { xsltTransformError(xsltXPathGetTransformContext(ctx), NULL, NULL, "swft:document() : could not parse SWF '%s'\n", filename); valuePush(ctx, xmlXPathNewNodeSet(NULL)); goto fail; } valuePush( ctx, xmlXPathNewNodeSet( (xmlNodePtr)doc ) ); fail: delete filename; } swfmill-0.3.3/src/swft/swft_import_ttf.cpp0000777000175000017500000004014512234241357015641 00000000000000#include #include #include #include #include "swft.h" #include #include #include #include #include "SWF.h" #include #include FT_FREETYPE_H #include FT_OUTLINE_H #include "SWFShapeMaker.h" #include using namespace SWF; #define TMP_STRLEN 0xff int moveTo( const FT_Vector *to, void *shaper ) { ((ShapeMaker*)shaper)->setup( to->x, to->y ); return 0; } int lineTo( const FT_Vector *to, void *shaper ) { ((ShapeMaker*)shaper)->lineTo( to->x, to->y ); return 0; } int conicTo( const FT_Vector *control, const FT_Vector *to, void *shaper ) { ((ShapeMaker*)shaper)->curveTo( control->x, control->y, to->x, to->y ); return 0; } int cubicTo( const FT_Vector *control1, const FT_Vector *control2, const FT_Vector *to, void *shaper ) { ((ShapeMaker*)shaper)->cubicTo ( control1->x, control1->y, control2->x, control2->y, to->x, to->y ); return 0; } FT_Outline_Funcs decomposeFunctions = { (FT_Outline_MoveToFunc)moveTo, (FT_Outline_LineToFunc)lineTo, (FT_Outline_ConicToFunc)conicTo, (FT_Outline_CubicToFunc)cubicTo, 0, 0 }; bool emptyGlyph( FT_Face face, FT_ULong wc ) { return( wc != 32 && face->glyph->outline.n_points == 0 ); } int compareGlyphs( const void *a, const void *b ) { int _a = *(int*)a; int _b = *(int*)b; return( _a - _b ); } void getVerticalMetrics (FT_Face face, int &ascender, int &descender, int &lineGap) { TT_OS2 *pOS2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2); if (pOS2) { ascender = pOS2->usWinAscent; descender = pOS2->usWinDescent; lineGap = pOS2->sTypoLineGap; } else { TT_HoriHeader *pHhea = (TT_HoriHeader *)FT_Get_Sfnt_Table(face, ft_sfnt_hhea); if (pHhea) { ascender = pHhea->Ascender; descender = -pHhea->Descender; lineGap = pHhea->Line_Gap; } } } void importDefineFont2( DefineFont2 *tag, const char *filename, const char *fontname, const xmlChar *glyphs_xml, Context *ctx, swft_ctx *swftctx, int offset ) { FT_Library swfft_library; FT_Face face; int error; FT_UInt glyph_index; FT_ULong character; FT_Outline *outline; int *glyphs = NULL; int i=0; char *font_ascentmap; GlyphList *glyphList = tag->getglyphs(); List* advance = tag->getadvance(); List* bounds = tag->getbounds(); List* kernings = tag->getwideKerning(); // NYI: kerning GlyphShape *shape; int nGlyphs, glyph; const int SCALING_FACTOR = 1024; if( FT_Init_FreeType( &swfft_library ) ) { fprintf( stderr, "WARNING: could not initialize FreeType\n" ); goto fail; } error = FT_New_Face( swfft_library, filename, 0, &face ); if( error ) { fprintf( stderr, "WARNING: FreeType does not like %s\n", filename ); goto fail; } if( face->num_faces > 1 ) { fprintf(stderr, "WARNING: %s contains %li faces, but only the first is " "imported.\n", filename, face->num_faces); } FT_Set_Pixel_Sizes(face, SCALING_FACTOR, SCALING_FACTOR); // count availably glyphs, yes we have to load them to check if they're empty, sorry. nGlyphs = 0; if( !glyphs_xml ) { if( (character = FT_Get_First_Char( face, &glyph_index )) != 0 ) nGlyphs++; while( (character = FT_Get_Next_Char( face, character, &glyph_index )) != 0 ) { if( FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_BITMAP ) ) { fprintf( stderr, "WARNING: cannot load glyph %lu ('%c') from " "%s.\n", character, character, filename ); goto fail; } if( face->glyph->format != FT_GLYPH_FORMAT_OUTLINE ) { fprintf( stderr, "WARNING: %s seems to be a bitmap font.\n", filename ); goto fail; } nGlyphs++; } glyphs = new int[nGlyphs+1]; i=0; if( (character = FT_Get_First_Char( face, &glyph_index )) != 0 ) glyphs[i++] = character; while( (character = FT_Get_Next_Char( face, character, &glyph_index )) != 0 ) { //if( !emptyGlyph( face, character ) ) glyphs[i++] = character; } } else { int nGlyphs_ = xmlUTF8Strlen( glyphs_xml ); glyphs = new int[nGlyphs_]; int len=0, idx=0; const unsigned char *str; for( int i=0; iallocate( nGlyphs ); tag->setglyphCount( nGlyphs ); tag->sethasLayout( 1 ); { int ascender, descender, lineGap; getVerticalMetrics (face, ascender, descender, lineGap); tag->setascent (ascender * SCALING_FACTOR / face->units_per_EM); tag->setdescent (descender * SCALING_FACTOR / face->units_per_EM); tag->setleading (lineGap * SCALING_FACTOR / face->units_per_EM); } tag->setwideGlyphOffsets( 1 ); tag->setwideMap( 1 ); if( face->style_flags & FT_STYLE_FLAG_ITALIC ) tag->setitalic(true); if( face->style_flags & FT_STYLE_FLAG_BOLD ) tag->setbold(true); if( !fontname ) fontname = face->family_name; tag->setname( strdup(fontname) ); if( !ctx->quiet ) { fprintf( stderr, "Importing TTF: '%s' - '%s'%s%s (%i glyphs) charcode offset %i\n", filename, fontname, face->style_flags & FT_STYLE_FLAG_BOLD ? " bold" : "", face->style_flags & FT_STYLE_FLAG_ITALIC ? " italic" : "", nGlyphs, offset ); } for( glyph=0; glyphglyph->format != FT_GLYPH_FORMAT_OUTLINE ) { fprintf( stderr, "WARNING: %s seems to be a bitmap font.\n", filename ); goto fail; } outline = &face->glyph->outline; // fprintf(stderr,"%i importing glyph %i ('%c') of %s (advance %i, %i points)\n", glyph, character, character, filename, face->glyph->advance.x, outline->n_points ); Short *adv = new Short(); adv->setvalue( (short)(ceil(1+(face->glyph->advance.x >> 6))) ); advance->append(adv); glyphList->setMapN(glyph, character+offset); shape = glyphList->getShapeN(glyph); ShapeMaker shaper( shape->getedges(), (1.0/64), -(1.0/64), 0, 0 ); shaper.setStyle( 1, -1, -1 ); FT_Outline_Decompose( outline, &decomposeFunctions, &shaper ); shaper.finish(); Rectangle *r = new Rectangle(); Rect rect = shaper.getBounds(); r->setleft( (int)rect.left ); r->settop( (int)rect.top ); r->setright( (int)rect.right ); r->setbottom( (int)rect.bottom ); r->setbits( SWFMaxBitsNeeded( true, 3, r->gettop(), r->getright(), r->getbottom() ) ); bounds->append(r); } if( FT_HAS_KERNING(face) ) { FT_Vector vec; int l, r; for( int left=0; left %i: %i\n", glyphs[left], glyphs[right], vec.x ); WideKerning *kern = new WideKerning(); kern->seta( glyphs[left] ); kern->setb( glyphs[right] ); kern->setadjustment( (short)(floor(vec.x >> 6)) ); kernings->append(kern); } } } } } if( glyphs ) delete glyphs; // hacky: store the ascent in the idmap. font_ascentmap = new char[0xff]; snprintf( font_ascentmap, 0xff, "%s_ascent", fontname ); swftctx->setMap( font_ascentmap, 1+(SCALING_FACTOR * face->ascender) / face->units_per_EM ); delete font_ascentmap; // fprintf( stderr, "StoreAscent: %s %i\n", fontname, 1+(SCALING_FACTOR * face->ascender) / face->units_per_EM ); return; fail: fprintf( stderr, "WARNING: could not import %s\n", filename ); return; } void importDefineFont3( DefineFont3 *tag, const char *filename, const char *fontname, const xmlChar *glyphs_xml, Context *ctx, swft_ctx *swftctx, int offset ) { FT_Library swfft_library; FT_Face face; int error; FT_UInt glyph_index; FT_ULong character; FT_Outline *outline; int *glyphs = NULL; int i=0; char *font_ascentmap; GlyphList *glyphList = tag->getglyphs(); List* advance = tag->getadvance(); List* bounds = tag->getbounds(); List* kernings = tag->getwideKerning(); // NYI: kerning GlyphShape *shape; int nGlyphs, glyph; const int SCALING_FACTOR = 1024 * 20; if( FT_Init_FreeType( &swfft_library ) ) { fprintf( stderr, "WARNING: could not initialize FreeType\n" ); goto fail; } error = FT_New_Face( swfft_library, filename, 0, &face ); if( error ) { fprintf( stderr, "WARNING: FreeType does not like %s\n", filename ); goto fail; } if( face->num_faces > 1 ) { fprintf( stderr, "WARNING: %s contains %li faces, but only the " "first is imported.\n", filename, face->num_faces ); } FT_Set_Char_Size(face, SCALING_FACTOR << 6, SCALING_FACTOR << 6, 72, 72); // count availably glyphs, yes we have to load them to check if they're empty, sorry. nGlyphs = 0; if( !glyphs_xml ) { if( (character = FT_Get_First_Char( face, &glyph_index )) != 0 ) nGlyphs++; while( (character = FT_Get_Next_Char( face, character, &glyph_index )) != 0 ) { if( FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_BITMAP ) ) { fprintf(stderr, "WARNING: cannot load glyph %lu ('%c') " "from %s.\n", character, character, filename); goto fail; } if( face->glyph->format != FT_GLYPH_FORMAT_OUTLINE ) { fprintf( stderr, "WARNING: %s seems to be a bitmap font.\n", filename ); goto fail; } //if( !emptyGlyph( face, character ) ) nGlyphs++; } glyphs = new int[nGlyphs+1]; i=0; if( (character = FT_Get_First_Char( face, &glyph_index )) != 0 ) glyphs[i++] = character; while( (character = FT_Get_Next_Char( face, character, &glyph_index )) != 0 ) { //if( !emptyGlyph( face, character ) ) glyphs[i++] = character; } } else { int nGlyphs_ = xmlUTF8Strlen( glyphs_xml ); glyphs = new int[nGlyphs_]; int len=0, idx=0; const unsigned char *str; for( int i=0; iallocate( nGlyphs ); tag->setglyphCount( nGlyphs ); tag->sethasLayout( 1 ); { int ascender, descender, lineGap; getVerticalMetrics (face, ascender, descender, lineGap); tag->setascent (ascender * SCALING_FACTOR / face->units_per_EM); tag->setdescent (descender * SCALING_FACTOR / face->units_per_EM); tag->setleading (lineGap * SCALING_FACTOR / face->units_per_EM); } tag->setwideGlyphOffsets( 1 ); tag->setwideMap( 1 ); if( face->style_flags & FT_STYLE_FLAG_ITALIC ) tag->setitalic(true); if( face->style_flags & FT_STYLE_FLAG_BOLD ) tag->setbold(true); if( !fontname ) fontname = face->family_name; tag->setname( strdup(fontname) ); if( !ctx->quiet ) { fprintf( stderr, "Importing TTF: '%s' - '%s'%s%s (%i glyphs) charcode offset %i\n", filename, fontname, face->style_flags & FT_STYLE_FLAG_BOLD ? " bold" : "", face->style_flags & FT_STYLE_FLAG_ITALIC ? " italic" : "", nGlyphs, offset ); } for( glyph=0; glyphglyph->format != FT_GLYPH_FORMAT_OUTLINE ) { fprintf( stderr, "WARNING: %s seems to be a bitmap font.\n", filename ); goto fail; } outline = &face->glyph->outline; // fprintf(stderr,"%i importing glyph %i ('%c') of %s (advance %i, %i points)\n", glyph, character, character, filename, face->glyph->advance.x, outline->n_points ); Short *adv = new Short(); adv->setvalue( (short)(ceil(1+(face->glyph->advance.x >> 6))) ); advance->append(adv); glyphList->setMapN(glyph, character+offset); shape = glyphList->getShapeN(glyph); ShapeMaker shaper( shape->getedges(), (1.0/64), -(1.0/64), 0, 0 ); shaper.setStyle( 1, -1, -1 ); FT_Outline_Decompose( outline, &decomposeFunctions, &shaper ); shaper.finish(); Rectangle *r = new Rectangle(); Rect rect = shaper.getBounds(); r->setleft( (int)rect.left ); r->settop( (int)rect.top ); r->setright( (int)rect.right ); r->setbottom( (int)rect.bottom ); r->setbits( SWFMaxBitsNeeded( true, 3, r->gettop(), r->getright(), r->getbottom() ) ); bounds->append(r); } if( FT_HAS_KERNING(face) ) { FT_Vector vec; int l, r; for( int left=0; left %i: %i\n", glyphs[left], glyphs[right], vec.x ); WideKerning *kern = new WideKerning(); kern->seta( glyphs[left] ); kern->setb( glyphs[right] ); kern->setadjustment( (short)(floor(vec.x >> 6)) ); kernings->append(kern); } } } } } if( glyphs ) delete glyphs; // hacky: store the ascent in the idmap. font_ascentmap = new char[0xff]; snprintf( font_ascentmap, 0xff, "%s_ascent", fontname ); swftctx->setMap( font_ascentmap, 1+(SCALING_FACTOR * face->ascender) / face->units_per_EM ); delete font_ascentmap; // fprintf( stderr, "StoreAscent: %s %i\n", fontname, 1+(SCALING_FACTOR * face->ascender) / face->units_per_EM ); return; fail: fprintf( stderr, "WARNING: could not import %s\n", filename ); return; } void swft_import_ttf( xmlXPathParserContextPtr ctx, int nargs ) { xsltTransformContextPtr tctx; char *filename; xmlDocPtr doc = NULL; xmlNodePtr node; Context swfctx; xmlChar *glyphs = NULL; int offset = 0; double movieVersion; bool quiet = true; xmlXPathObjectPtr quietObj = NULL; swft_ctx *c = NULL; const char *fontname = NULL; if( (nargs < 2) || (nargs > 5) ) { xmlXPathSetArityError(ctx); return; } if( nargs >= 5 ) { offset = (int)xmlXPathPopNumber(ctx); } if( nargs >= 4 ) { fontname = (const char *)xmlXPathPopString(ctx); if( fontname[0] == 0 ) fontname = NULL; } if( nargs >= 3 ) { glyphs = xmlXPathPopString(ctx); if( glyphs[0] == 0 ) glyphs = NULL; } movieVersion = xmlXPathPopNumber(ctx); filename = swft_get_filename(xmlXPathPopString(ctx), ctx->context->doc->URL); if (xmlXPathCheckError(ctx)) { goto fail; } tctx = xsltXPathGetTransformContext(ctx); quietObj = xsltVariableLookup( tctx, (const xmlChar*)"quiet", NULL ); if( quietObj && quietObj->stringval ) { quiet = !strcmp("true",(const char*)quietObj->stringval ); }; swfctx.quiet = quiet; doc = xmlNewDoc( (const xmlChar *)"1.0"); doc->xmlRootNode = xmlNewDocNode( doc, NULL, (const xmlChar*)"ttf", NULL ); node = doc->xmlRootNode; c = (swft_ctx*)xsltGetExtData( xsltXPathGetTransformContext(ctx), SWFT_NAMESPACE ); // create the font tag if( movieVersion >= 8 ) { DefineFont3 *tag = new DefineFont3(); importDefineFont3( tag, (const char *)filename, fontname, glyphs, &swfctx, c, offset ); tag->writeXML( node, &swfctx ); } else { DefineFont2 *tag = new DefineFont2(); importDefineFont2( tag, (const char *)filename, fontname, glyphs, &swfctx, c, offset ); tag->writeXML( node, &swfctx ); } if( glyphs ) xmlFree( glyphs ); valuePush( ctx, xmlXPathNewNodeSet( (xmlNodePtr)doc ) ); goto end; fail: fprintf( stderr, "WARNING: could not import %s\n", filename ); end: delete filename; } swfmill-0.3.3/src/swft/SVGStyle.cpp0000777000175000017500000001473012152542002014056 00000000000000#include "SVGStyle.h" #include "SVGAttributeParser.h" #include #define TMP_STRLEN 0xFF using namespace std; namespace SWF { SVGStyle::SVGStyle() { _hasFill = false; _hasFillGradient = false; _hasStroke = false; _hasStrokeGradient = false; _hasStyle = false; _hasLineCap = false; lineCap = CAP_BUTT; _hasLineJoin = false; lineJoin = JOIN_MITER; miterLimit = 4; strokeWidth = 1; _opacity = 1; } void SVGStyle::parseNode(xmlNodePtr node, map &gradients) { AttributeParser parser; parser.parseNode(node); const map > &attributes = parser.getAttributes(); for(map >::const_iterator iter = attributes.begin(); iter != attributes.end(); iter++) { const string &attribute = (*iter).first; const vector &values = (*iter).second; for (vector::const_iterator iterValue = values.begin (); iterValue != values.end (); iterValue ++) { const string &valueStr = (*iterValue); const char *value = valueStr.c_str (); bool fParsed = true; if(attribute == "stroke") { SVGGradient *gradient = getGradient(valueStr, gradients); if(gradient) { strokeGradient = gradient; _hasStrokeGradient = true; _hasStroke = true; fParsed = true; } else { fParsed = setStrokeColor(value); } } else if(attribute == "stroke-width") { setStrokeWidth(atof(value)); } else if(attribute == "stroke-opacity") { setStrokeAlpha(atof(value)); } else if(attribute == "stroke-linecap") { fParsed = setLineCap(value); } else if(attribute == "stroke-linejoin") { fParsed = setLineJoin(value); } else if(attribute == "stroke-miterlimit") { setMiterLimit(atof(value)); } else if(attribute == "fill") { SVGGradient *gradient = getGradient(valueStr, gradients); if(gradient) { fillGradient = gradient; _hasFillGradient = true; _hasFill = true; fParsed = true; } else { fParsed = setFillColor(value); } } else if(attribute == "fill-opacity") { setFillAlpha(atof(value)); } else if(attribute == "opacity") { setOpacity(atof(value)); } if (fParsed) { break; } } } } SVGGradient *SVGStyle::getGradient(const string &str, map &gradients) { if(str.substr(0, 4) == "url(" && str.substr(str.length() - 1) == ")") { string strGradient = str.substr (4, str.length() - 5); if (strGradient [0] == '"' && strGradient [strGradient.length() - 1] == '"' || strGradient [0] == '\'' && strGradient [strGradient.length() - 1] == '\'') { strGradient = strGradient.substr (1, strGradient.length () - 2); } if (strGradient [0] == '#') { strGradient = strGradient.substr (1, strGradient.length() - 1); map::iterator i = gradients.find(strGradient); if(i != gradients.end()) { return (*i).second; } } } return NULL; } bool SVGStyle::setLineCap(const char *cap) { if(!strcmp(cap, "butt")) { lineCap = CAP_BUTT; _hasLineCap = true; _hasStyle = true; return true; } else if(!strcmp(cap, "round")) { lineCap = CAP_ROUND; _hasLineCap = true; _hasStyle = true; return true; } else if(!strcmp(cap, "square")) { lineCap = CAP_SQUARE; _hasLineCap = true; _hasStyle = true; return true; } return false; } bool SVGStyle::setLineJoin(const char *join) { if(!strcmp(join, "miter")) { lineJoin = JOIN_MITER; _hasLineJoin = true; _hasStyle = true; return true; } else if(!strcmp(join, "round")) { lineJoin = JOIN_ROUND; _hasLineJoin = true; _hasStyle = true; return true; } else if(!strcmp(join, "bevel")) { lineJoin = JOIN_BEVEL; _hasLineJoin = true; _hasStyle = true; return true; } return false; } void SVGStyle::writeXML(xmlNodePtr parent, double movieVersion) { xmlNodePtr node, styleNode; char tmp[TMP_STRLEN]; styleNode = xmlNewChild(parent, NULL, (const xmlChar *)"StyleList", NULL); if(_hasFill) { node = xmlNewChild(styleNode, NULL, (const xmlChar *)"fillStyles", NULL); if(_hasFillGradient) { fillGradient->writeXML(node, bounds, (movieVersion >= 8), _opacity); } else { node = xmlNewChild(node, NULL, (const xmlChar *)"Solid", NULL); node = xmlNewChild(node, NULL, (const xmlChar *)"color", NULL); fill.writeXML(node, _opacity); } } if(_hasStroke) { node = xmlNewChild(styleNode, NULL, (const xmlChar *)"lineStyles", NULL); if(movieVersion >= 8) { node = xmlNewChild(node, NULL, (const xmlChar *)"LineStyle", NULL); snprintf(tmp,TMP_STRLEN,"%f", strokeWidth * 20); xmlSetProp(node, (const xmlChar *)"width", (const xmlChar *)&tmp); snprintf(tmp, TMP_STRLEN, "%i", lineCap); xmlSetProp(node, (const xmlChar *)"startCapStyle", (const xmlChar *)&tmp); snprintf(tmp, TMP_STRLEN, "%i", lineJoin); xmlSetProp(node, (const xmlChar *)"jointStyle", (const xmlChar *)&tmp); xmlSetProp(node, (const xmlChar *)"hasFill", (const xmlChar *)(_hasStrokeGradient ? "1" : "0")); xmlSetProp(node, (const xmlChar *)"noHScale", (const xmlChar *)"0"); xmlSetProp(node, (const xmlChar *)"noVScale", (const xmlChar *)"0"); xmlSetProp(node, (const xmlChar *)"pixelHinting", (const xmlChar *)"0"); xmlSetProp(node, (const xmlChar *)"reserved", (const xmlChar *)"0"); xmlSetProp(node, (const xmlChar *)"noClose", (const xmlChar *)"0"); snprintf(tmp, TMP_STRLEN, "%i", lineCap); xmlSetProp(node, (const xmlChar *)"endCapStyle", (const xmlChar *)&tmp); if(lineJoin == JOIN_MITER) { snprintf(tmp, TMP_STRLEN, "%f", miterLimit); xmlSetProp(node, (const xmlChar *)"miterLimitFactor", (const xmlChar *)&tmp); } if(_hasStrokeGradient) { node = xmlNewChild(node, NULL, (const xmlChar *)"fillStyles", NULL); strokeGradient->writeXML(node, bounds, (movieVersion >= 8), _opacity); } else { node = xmlNewChild(node, NULL, (const xmlChar *)"fillColor", NULL); stroke.writeXML(node, _opacity); } } else { node = xmlNewChild(node, NULL, (const xmlChar *)"LineStyle", NULL); snprintf(tmp,TMP_STRLEN,"%f", strokeWidth * 20); xmlSetProp(node, (const xmlChar *)"width", (const xmlChar *)&tmp); node = xmlNewChild(node, NULL, (const xmlChar *)"color", NULL); stroke.writeXML(node, _opacity); if(_hasLineCap || _hasLineJoin) { cerr << "WARNING: some svg features aren't supported before swf version 8" << endl; } } } } } swfmill-0.3.3/src/swft/SVGColor.h0000777000175000017500000000130412152542002013472 00000000000000#ifndef SVG_COLOR_H #define SVG_COLOR_H #include #include #include #include namespace SWF { class SVGColor { public: SVGColor(); SVGColor(unsigned char _r, unsigned char _g, unsigned char _b, unsigned char _a = 255); void initColors(); void setColor(unsigned char _r, unsigned char _g, unsigned char _b, unsigned char _a = 255); void setAlpha(unsigned char _a); void setAlpha(double _a); bool parse(std::string &color); bool parse(const char *color); void writeXML(xmlNodePtr parent, double opacity); private: unsigned char r; unsigned char g; unsigned char b; unsigned char a; }; } #endif swfmill-0.3.3/src/swft/SVGGradient.cpp0000777000175000017500000001417512152542002014516 00000000000000#include "SVGGradient.h" #include "SVGTransformParser.h" #include #define TMP_STRLEN 0xFF using namespace std; namespace SWF { /* SVGGradient */ SVGGradient::SVGGradient() { spreadMethod = PAD; } void SVGGradient::parse(xmlNodePtr node) { attribs.parseNode(node); const char *tmp = attribs["gradientUnits"]; if(tmp) { if(!strcmp(tmp, "userSpaceOnUse")) { userSpace = true; } else { userSpace = false; } } else { userSpace = false; } parseGradient(); parseSpreadMethod(); parseTransform(); parseStops(node); } void SVGGradient::parseStops(xmlNodePtr parent) { for(xmlNodePtr node = parent->children; node; node = node->next) { if(!xmlStrcmp(node->name, (const xmlChar *)"stop")) parseStop(node); } } void SVGGradient::parseStop(xmlNodePtr node) { SVGGradientStop stop; AttributeParser stopAttribs; stopAttribs.parseNode(node); double offset = stopAttribs.getDouble("offset"); const char *tmp = stopAttribs["stop-color"]; if(tmp) { stop.setColor(tmp); } stop.setAlpha(stopAttribs.getDouble("stop-opacity", 1)); stops[offset] = stop; } void SVGGradient::parseTransform() { const char *tmp = attribs["gradientTransform"]; if(tmp) { TransformParser parser; parser.parse(tmp); transform = parser.getMatrix(); } } void SVGGradient::parseSpreadMethod() { const char *tmp = attribs["spreadMethod"]; if(tmp) { if(!strcmp(tmp, "pad")) { spreadMethod = PAD; } else if(!strcmp(tmp, "reflect")) { spreadMethod = REFLECT; } else if(!strcmp(tmp, "repeat")) { spreadMethod = REPEAT; } else { spreadMethod = PAD; } } } void SVGGradient::writeCommonXML(xmlNodePtr parentNode, Matrix& m, bool hasModes, double opacity) { char tmp[TMP_STRLEN]; xmlNodePtr node; if(hasModes) { xmlSetProp(parentNode, (const xmlChar *)"interpolationMode", (const xmlChar *)"0"); snprintf(tmp, TMP_STRLEN, "%i", spreadMethod); xmlSetProp(parentNode, (const xmlChar *)"spreadMode", (const xmlChar *)&tmp); } else { xmlSetProp(parentNode, (const xmlChar *)"reserved", (const xmlChar *)"0"); } node = xmlNewChild(parentNode, NULL, (const xmlChar *)"matrix", NULL); node = xmlNewChild(node, NULL, (const xmlChar *)"Transform", NULL); m.setXMLProps(node); node = xmlNewChild(parentNode, NULL, (const xmlChar *)"gradientColors", NULL); for(map::iterator i = stops.begin(); i != stops.end(); i++) { (*i).second.writeXML(node, (*i).first, opacity); } } /* SVGLinearGradient */ void SVGLinearGradient::parseGradient() { x1 = attribs.getDouble("x1", 0); y1 = attribs.getDouble("y1", 0); x2 = attribs.getDouble("x2", 1); y2 = attribs.getDouble("y2", 0); } void SVGLinearGradient::writeXML(xmlNodePtr node, Rect& bounds, bool hadModes, double opacity) { double w = bounds.right - bounds.left; double h = bounds.bottom - bounds.top; Matrix m; if(userSpace) { double lx = x2 - x1; double ly = y2 - y1; double dx = x2 - x1; double dy = y2 - y1; double d = sqrt(dx * dx + dy * dy); double a = atan2(dy, dx); m *= transform; m.translate((x1 + x2) / 2 * 20, (y1 + y2) / 2 * 20); m.rotate(a); m.scale(d * 20 / 32768); } else { double sx, sy; double _x1 = bounds.left + x1 * w; double _y1 = bounds.top + y1 * h; double _x2 = bounds.left + x2 * w; double _y2 = bounds.top + y2 * h; if(x1 != x2) { sx = (_x2 - _x1) / 32768.0; } else { sx = 1; } if(y1 != y2) { sy = (_y2 - _y1) / 32768.0; } else { sy = 1; } double dx = x2 - x1; double dy = y2 - y1; double d = sqrt(dx * dx + dy * dy); double a = atan2(dy, dx); m.translate((_x1 + _x2) / 2, (_y1 + _y2) / 2); m.scale(sx, sy); m.rotate(a); m.scale(d); } xmlNodePtr topNode = xmlNewChild(node, NULL, (const xmlChar *)"LinearGradient", NULL); writeCommonXML(topNode, m, hadModes, opacity); } /* SVGRadialGradient */ void SVGRadialGradient::parseGradient() { cx = attribs.getDouble("cx", .5); cy = attribs.getDouble("cy", .5); r = attribs.getDouble("r", .5); if(attribs["fx"] || attribs["fy"]) { hasFocalPoint = true; fx = attribs.getDouble("fx", cx); fy = attribs.getDouble("fy", cy); if(fx == cx && fy == cy) { hasFocalPoint = false; } } else { hasFocalPoint = false; } } void SVGRadialGradient::writeXML(xmlNodePtr node, Rect& bounds, bool hasModes, double opacity) { Matrix m; double w = bounds.right - bounds.left; double h = bounds.bottom - bounds.top; double shift = 0; if(userSpace) { m *= transform; m.translate(cx * 20, cy * 20); if(hasFocalPoint) { double dx = fx - cx; double dy = fy - cy; m.rotate(atan2(dy, dx)); shift = sqrt(pow(dx, 2) + pow(dy, 2)) / r; } m.scale(r * 20 / 16348.0, r * 20 / 16384.0); } else { double _cx = bounds.left + cx * w; double _cy = bounds.top + cy * h; m.translate(_cx, _cy); m.scale(r * w / 16348.0, r * h / 16384.0); if(hasFocalPoint) { double _fx = bounds.left + fx * w; double _fy = bounds.top + fy * h; double dx = _fx - _cx; double dy = _fy - _cy; m.rotate(atan2(dy, dx)); shift = sqrt(pow(dx, 2) + pow(dy, 2)) / (r * sqrt(pow(w, 2) + pow(h, 2)) / sqrt(2)); } } xmlNodePtr topNode; if(hasFocalPoint) { topNode = xmlNewChild(node, NULL, (const xmlChar *)"ShiftedRadialGradient", NULL); char tmp[TMP_STRLEN]; snprintf(tmp, TMP_STRLEN, "%f", shift); xmlSetProp(topNode, (const xmlChar *)"shift", (const xmlChar *)tmp); } else { topNode = xmlNewChild(node, NULL, (const xmlChar *)"RadialGradient", NULL); } writeCommonXML(topNode, m, hasModes, opacity); } /* SVGGradientStop */ void SVGGradientStop::writeXML(xmlNodePtr node, double offset, double opacity) { char tmp[TMP_STRLEN]; node = xmlNewChild(node, NULL, (const xmlChar *)"GradientItem", NULL); snprintf(tmp, TMP_STRLEN, "%i", (int)(offset * 255)); xmlSetProp(node, (const xmlChar *)"position", (const xmlChar *)&tmp); node = xmlNewChild(node, NULL, (const xmlChar *)"color", NULL); color.writeXML(node, opacity); } } swfmill-0.3.3/src/swft/Parser.h0000777000175000017500000000133212234074602013300 00000000000000#ifndef PARSER_H #define PARSER_H #include #include #include namespace SWF { class Parser { public: Parser(const char begin, const char end, const char parameter = 0); virtual ~Parser(); protected: virtual void handleData(const std::string& outside, const std::vector& inside) = 0; virtual void doParse(const char* str); void trimString(std::string& s); bool isWhitespace(const char c); private: void handleDelimiter(std::string& tmp); void swapDelimiters(); char expectedDelimiter; char otherDelimiter; char parameterDelimiter; bool insideParams; std::vector params; std::string outside; }; } #endif swfmill-0.3.3/src/swft/SVGTransformParser.h0000777000175000017500000000116712152542002015553 00000000000000#ifndef SVG_TRANSFORMPARSER_H #define SVG_TRANSFORMPARSER_H #include #include #include #include #include "Geom.h" #include "Parser.h" namespace SWF { class TransformParser : public Parser { public: TransformParser() : Parser('(', ')', ',') { } Matrix getMatrix() { return transformMatrix; } void parse(const char* str) { doParse(str); } private: Matrix transformMatrix; void handleData(const std::string& transformType, const std::vector& params); void printWarning(const std::string& transformType); }; } #endif swfmill-0.3.3/src/swft/SVGGradient.h0000777000175000017500000000327512152542002014162 00000000000000#ifndef SVG_GRADIENT_H #define SVG_GRADIENT_H #include #include #include #include "Geom.h" #include "SVGColor.h" #include "SVGAttributeParser.h" #include "SWFShapeMaker.h" namespace SWF { class SVGGradientStop; class SVGGradient { public: SVGGradient(); virtual void parse(xmlNodePtr node); virtual void writeXML(xmlNodePtr node, Rect &bounds, bool hadModes, double opacity) = 0; enum SpreadMethod { PAD, REFLECT, REPEAT }; protected: virtual void parseGradient() = 0; void parseStops(xmlNodePtr parent); void parseStop(xmlNodePtr node); void parseTransform(); void parseSpreadMethod(); void writeCommonXML(xmlNodePtr node, Matrix& m, bool hasModes, double opacity); std::map stops; Matrix transform; AttributeParser attribs; SpreadMethod spreadMethod; bool userSpace; }; class SVGLinearGradient : public SVGGradient { public: void writeXML(xmlNodePtr node, Rect &bounds, bool hasModes, double opacity); protected: void parseGradient(); double x1, x2, y1, y2; }; class SVGRadialGradient : public SVGGradient { public: void writeXML(xmlNodePtr node, Rect &bounds, bool hasModes, double opacity); protected: void parseGradient(); double cx, cy, fx, fy, r; bool hasFocalPoint; }; class SVGGradientStop { public: void setColor(const char *c) { color.parse(c); } void setAlpha(unsigned char alpha) { color.setAlpha(alpha); } void setAlpha(double alpha) { color.setAlpha(alpha); } void writeXML(xmlNodePtr node, double offset, double opacity); private: SVGColor color; }; } #endif swfmill-0.3.3/src/swft/SVGPointsParser.cpp0000777000175000017500000000161212152542002015402 00000000000000#include "SVGPointsParser.h" #include #include using namespace std; namespace SWF { void PointsParser::parse(const char *points) { string tmp; coords.clear(); for(int i = 0; i < strlen(points); i++) { char currentChar = points[i]; if(currentChar == ',' || currentChar == ' ') { if(tmp.length() > 0) { coords.push_back(atof(tmp.c_str())); tmp.clear(); } } else { tmp += currentChar; } } if(tmp.length() > 0) { coords.push_back(atof(tmp.c_str())); } if(coords.size() % 2) { cerr << "WARNING: odd number of coordinates in points attribute" << endl; } } int PointsParser::getPointCount() { return coords.size() / 2; } Point PointsParser::getPoint() { double x = coords.front(); coords.pop_front(); double y = coords.front(); coords.pop_front(); return Point(x, y); } } swfmill-0.3.3/src/swft/Parser.cpp0000777000175000017500000000313512234241357013641 00000000000000#include "Parser.h" #include using namespace std; namespace SWF { Parser::Parser(const char begin, const char end, const char parameter) { expectedDelimiter = begin; otherDelimiter = end; parameterDelimiter = parameter; } Parser::~Parser() { } void Parser::swapDelimiters() { char tmp = otherDelimiter; otherDelimiter = expectedDelimiter; expectedDelimiter = tmp; } bool Parser::isWhitespace(const char c) { return (c == 0 || c == '\n' || c == '\r' || c == '\t' || c == ' '); } void Parser::doParse(const char* str) { string tmp; insideParams = false; params.clear(); for (size_t i = 0; i < strlen(str); i++) { if(str[i] == expectedDelimiter) { handleDelimiter(tmp); } else if(str[i] == otherDelimiter) { cerr << "WARNING: Unexpected delimiter while parsing" << endl; } else { if(tmp.length() > 0 && (str[i] == parameterDelimiter || isWhitespace(str[i]))) { trimString(tmp); params.push_back(tmp); tmp.clear(); } else { tmp += str[i]; } } } if (tmp.length() > 0) { //cerr << "WARNING: Reached end of line while parsing" << endl; handleDelimiter(tmp); } } void Parser::handleDelimiter(string& tmp) { trimString(tmp); if(insideParams) { if(tmp.length() > 0) { params.push_back(tmp); } handleData(outside, params); params.clear(); } else { outside = tmp; } insideParams = !insideParams; tmp.clear(); swapDelimiters(); } void Parser::trimString(string& s) { s.erase(0, s.find_first_not_of(" \t\r\n")); s.erase(s.find_last_not_of(" \t\r\n") + 1); } } swfmill-0.3.3/src/swft/SVGAttributeParser.h0000777000175000017500000000150212234241357015546 00000000000000#ifndef SVG_ATTRIBUTE_PARSER_H #define SVG_ATTRIBUTE_PARSER_H #include #include #include #include #include "Parser.h" namespace SWF { class AttributeParser : public Parser { public: AttributeParser() : Parser(':', ';') { } void parseNode(xmlNodePtr node); const std::map >& getAttributes(); double getDouble(const char* attribute, double defaultValue = 0, double value100 = 1); const char *getString(const char* attribute); const char *operator[](const char* attribute); protected: void doParse(const char* str); private: std::map > attributes; void handleData(const std::string& attrib, const std::vector& value); }; } #endif swfmill-0.3.3/src/swft/swft_import_jpeg.cpp0000777000175000017500000001777412234241357016005 00000000000000#include #include #include #include #include "swft.h" #include #include #include #include "readpng.h" #include #define TMP_STRLEN 0xff const char jpeg_header[] = { 0xff, 0xd9, 0xff, 0xd8, 0 }; // defined in swft_import_png bool compress( unsigned char *inputBuffer, int inLength, unsigned char *outputBuffer, int *outLength ); int getJpegWord( FILE *fp ) { int r = fgetc(fp); r <<= 8; r += fgetc(fp); return r; } bool getJpegDimensions (FILE *infile, int &image_width, int &image_height) { image_width = image_height = 0; if (fgetc(infile) != 0xff || fgetc(infile) != 0xd8) { return false; } while (!feof(infile)) { if (fgetc(infile) != 0xff) { return false; } int marker; do { marker = fgetc(infile); } while (marker == 0xff); switch (marker) { case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc5: case 0xc6: case 0xc7: case 0xc9: case 0xca: case 0xcb: case 0xcd: case 0xce: case 0xcf: getJpegWord(infile); fgetc(infile); image_height = getJpegWord(infile); image_width = getJpegWord(infile); fgetc(infile); return true; case 0xda: case 0xd9: return false; default: int length = getJpegWord(infile); if (length < 2) { return false; } else { fseek(infile, length-2, SEEK_CUR); } break; } } return false; } void swft_import_jpeg( xmlXPathParserContextPtr ctx, int nargs ) { xsltTransformContextPtr tctx; char *filename; xsltDocumentPtr xsltdoc; xmlDocPtr doc = NULL; xmlNodePtr node; xmlXPathObjectPtr obj; char tmp[TMP_STRLEN]; unsigned char *data = NULL; xmlXPathStringFunction(ctx, 1); if (ctx->value->type != XPATH_STRING) { xsltTransformError(xsltXPathGetTransformContext(ctx), NULL, NULL, "swft:import-jpeg() : invalid arg expecting a string\n"); ctx->error = XPATH_INVALID_TYPE; return; } obj = valuePop(ctx); if (obj->stringval == NULL) { valuePush(ctx, xmlXPathNewNodeSet(NULL)); return; } tctx = xsltXPathGetTransformContext(ctx); filename = swft_get_filename( obj->stringval, ctx->context->doc->URL ); bool quiet = true; xmlXPathObjectPtr quietObj = xsltVariableLookup( tctx, (const xmlChar*)"quiet", NULL ); if( quietObj && quietObj->stringval ) { quiet = !strcmp("true",(const char*)quietObj->stringval ); }; FILE *fp = fopen( filename, "rb" ); if( !fp ) { xsltTransformError(xsltXPathGetTransformContext(ctx), NULL, NULL, "swft:import-jpeg() : failed to read file '%s'\n", filename); valuePush(ctx, xmlXPathNewNodeSet(NULL)); goto fail; } doc = xmlNewDoc( (const xmlChar *)"1.0"); doc->xmlRootNode = xmlNewDocNode( doc, NULL, (const xmlChar *)"jpeg", NULL ); node = doc->xmlRootNode; swft_addFileName( node, filename ); int width, height; if (!getJpegDimensions(fp, width, height)) { fprintf(stderr, "WARNING: could not extract dimensions for jpeg %s\n", filename); goto fail; } snprintf(tmp,TMP_STRLEN,"%i", width); xmlSetProp( node, (const xmlChar *)"width", (const xmlChar *)&tmp ); snprintf(tmp,TMP_STRLEN,"%i", height); xmlSetProp( node, (const xmlChar *)"height", (const xmlChar *)&tmp ); // add data int size, ofs; struct stat filestat; if( stat( filename, &filestat ) ) goto fail; size = filestat.st_size; ofs = strlen(jpeg_header); rewind(fp); data = new unsigned char[size+ofs]; memcpy( data, jpeg_header, ofs ); if( fread( &data[ofs], 1, size, fp ) != size ) { fprintf(stderr,"WARNING: could not read enough (%i) bytes for jpeg %s\n", size, filename ); goto fail; } if( !quiet ) { fprintf(stderr,"Importing JPG: '%s'\n",filename); } swft_addData( node, (char*)data, size+ofs ); valuePush( ctx, xmlXPathNewNodeSet( (xmlNodePtr)doc ) ); fail: if( fp ) fclose(fp); if( data ) delete data; delete filename; } void swft_import_jpega( xmlXPathParserContextPtr ctx, int nargs ) { xsltTransformContextPtr tctx; char *filename, *maskfilename; xsltDocumentPtr xsltdoc; xmlDocPtr doc = NULL; xmlNodePtr node; xmlXPathObjectPtr obj; char tmp[TMP_STRLEN]; unsigned char *jpegdata = NULL; unsigned char *data = NULL; FILE *fp = NULL; // figure width/height int width=-1, height=-1; if( (nargs != 2) ) { xmlXPathSetArityError(ctx); return; } maskfilename = swft_get_filename( xmlXPathPopString(ctx), ctx->context->doc->URL ); filename = swft_get_filename( xmlXPathPopString(ctx), ctx->context->doc->URL ); if( xmlXPathCheckError(ctx) || (filename==NULL) || (maskfilename==NULL) ) { goto fail; } tctx = xsltXPathGetTransformContext(ctx); fp = fopen( filename, "rb" ); if( !fp ) { xsltTransformError(xsltXPathGetTransformContext(ctx), NULL, NULL, "swft:import-jpega() : failed to read file '%s'\n", filename); valuePush(ctx, xmlXPathNewNodeSet(NULL)); goto fail; } doc = xmlNewDoc( BAD_CAST "1.0"); doc->xmlRootNode = xmlNewDocNode( doc, NULL, BAD_CAST "jpega", NULL ); node = doc->xmlRootNode; swft_addFileName( node, filename ); if (!getJpegDimensions (fp, width, height)) { fprintf(stderr,"WARNING: could not extract dimensions for jpeg %s\n", filename ); goto fail; } snprintf(tmp,TMP_STRLEN,"%i", width); xmlSetProp( node, (const xmlChar *)"width", (const xmlChar *)&tmp ); snprintf(tmp,TMP_STRLEN,"%i", height); xmlSetProp( node, (const xmlChar *)"height", (const xmlChar *)&tmp ); // add data int data_size, mask_size; int size, ofs; struct stat filestat; unsigned char *maskdata; unsigned long maskw, maskh, rowbytes; int channels; png_colorp palette; int n_pal; unsigned char *mask; if( stat( filename, &filestat ) ) goto fail; size = filestat.st_size; ofs = strlen(jpeg_header); rewind(fp); jpegdata = new unsigned char[size+ofs]; memcpy( jpegdata, jpeg_header, ofs ); if( fread( &jpegdata[ofs], 1, size, fp ) != size ) { fprintf(stderr,"WARNING: could not read enough (%i) bytes for jpeg %s\n", size, filename ); goto fail; } snprintf(tmp,TMP_STRLEN,"%i", size+ofs); xmlSetProp( node, (const xmlChar *)"offset_to_alpha", (const xmlChar *)&tmp ); fclose(fp); // jpegdata is filled, now read the mask png. fp = fopen( maskfilename, "rb" ); if( !fp ) { xsltTransformError(xsltXPathGetTransformContext(ctx), NULL, NULL, "swft:import-jpega() : failed to read mask file '%s'\n", maskfilename); valuePush(ctx, xmlXPathNewNodeSet(NULL)); goto fail; } data_size = size + ofs + (width*height) + 0x4000; data = new unsigned char[ data_size ]; memcpy( data, jpegdata, size+ofs ); maskdata = &data[ size+ofs ]; if( readpng_init( fp, &maskw, &maskh ) ) goto fail; if( maskw != width || maskh != height ) { xsltTransformError(xsltXPathGetTransformContext(ctx), NULL, NULL, "swft:import-jpega() : mask has different size than jpeg image: %i/%i and %i/%i\n", width, height, maskw, maskh ); valuePush(ctx, xmlXPathNewNodeSet(NULL)); goto fail; } mask = readpng_get_image( 2.2, &channels, &rowbytes, &palette, &n_pal ); if( channels != 1 || rowbytes != width ) { xsltTransformError(xsltXPathGetTransformContext(ctx), NULL, NULL, "swft:import-jpega() : mask is not 8bit grayscale\n"); valuePush(ctx, xmlXPathNewNodeSet(NULL)); goto fail; } mask_size = data_size - size - ofs; if( compress( mask, width*height, maskdata, &mask_size ) ) { data_size = size + ofs + mask_size; } else { xsltTransformError(xsltXPathGetTransformContext(ctx), NULL, NULL, "swft:import-jpega() : could not compress mask\n" ); valuePush(ctx, xmlXPathNewNodeSet(NULL)); goto fail; } swft_addData( node, (char*)data, data_size ); valuePush( ctx, xmlXPathNewNodeSet( (xmlNodePtr)doc ) ); fail: if( fp ) fclose(fp); if( data ) delete data; if( jpegdata ) delete jpegdata; delete filename; delete maskfilename; } swfmill-0.3.3/src/swft/swft_import_wav.cpp0000777000175000017500000001431012152542002015622 00000000000000#include #include #include #include #include "swft.h" #include #include #include #define TMP_STRLEN 0xff #define ERROR_NO_WAV -1 #define ERROR_WRONG_SAMPLING_RATE -2 struct WaveInfo { int samplingRate; int samples; int flashSamplingRateFlag; int stereo; int is16bit; int wave_data_size; const char *wave_data_ptr; bool valid; bool wrongSamplingRate; }; typedef enum { WAVE_INVALID, WAVE_PCM = 1, } WaveFormatCode; void getWaveInfo( WaveInfo& info, char* data, int size ) { info.stereo = 0; info.wrongSamplingRate = false; int pos = 0; info.valid = false; const char *ptr = data; if (strncmp(ptr, "RIFF", 4) != 0) { fprintf(stderr, "Error: RIFF header missing\n"); return; } ptr += 4; if ( *((unsigned int *)ptr) + 8 != size) { fprintf(stderr, "Error: File size differs from that described in RIFF header\n"); return; } ptr += 4; if (strncmp(ptr, "WAVE", 4) != 0) { fprintf(stderr, "Error: Expected WAVE chunk\n"); return; } ptr += 4; if (strncmp(ptr, "fmt ", 4) != 0) { fprintf(stderr, "Error: Expected fmt_ subchunk\n"); return; } ptr += 4; /* Look ahead a bit */ unsigned short format_code = *((unsigned short *)(ptr+4)); if (format_code != WAVE_PCM) { fprintf(stderr, "Error: Format code in WAVE file is not PCM (%d)\n", format_code); } if ( *((unsigned int *)ptr) != 16) { fprintf(stderr, "Error: fmt_ subchunk size != 16. Is format code PCM?\n"); return; } if (format_code != WAVE_PCM) { return; } /* Skip format code, already checked that */ ptr += 6; unsigned short num_channels = *((unsigned short *)ptr); if (num_channels < 1 || num_channels > 2) { fprintf(stderr, "Error: Channels should be 1 or 2 (is %d)\n", num_channels); return; } info.stereo = num_channels == 2; ptr += 2; unsigned int sample_rate = *((unsigned int *)ptr); info.samplingRate = sample_rate; switch (sample_rate) { case 5512: info.flashSamplingRateFlag = 0; break; case 11025: info.flashSamplingRateFlag = 1; break; case 22050: info.flashSamplingRateFlag = 2; break; case 44100: info.flashSamplingRateFlag = 3; break; default: fprintf(stderr, "Invalid sampling rate, please use either 5.5k, 11k, 22k or 44k (is: %d Hz)\n", sample_rate); info.wrongSamplingRate = true; return; } /* Skip some derived fields */ ptr += 10; unsigned short bits_per_sample = *((unsigned short *)ptr); if (bits_per_sample != 8 && bits_per_sample != 16) { fprintf(stderr, "Error: Bit per sample should be either 8 or 16 (is: %d)\n", bits_per_sample); return; } info.is16bit = bits_per_sample == 16; ptr += 2; if (strncmp(ptr, "data", 4) != 0) { fprintf(stderr, "Error: Expected data_ subchunk\n"); return; } ptr += 4; info.wave_data_size = *((unsigned int*)ptr); info.samples = info.wave_data_size / num_channels / (info.is16bit ? 2 : 1); info.wave_data_ptr = ptr + 4; info.valid = true; } void swft_import_wav( xmlXPathParserContextPtr ctx, int nargs ) { xsltTransformContextPtr tctx; xmlChar *filename; xsltDocumentPtr xsltdoc; xmlDocPtr doc = NULL; xmlNodePtr node; xmlXPathObjectPtr obj; char tmp[TMP_STRLEN]; //data variables unsigned char *data = NULL; int size; struct stat filestat; xmlXPathStringFunction(ctx, 1); if (ctx->value->type != XPATH_STRING) { xsltTransformError(xsltXPathGetTransformContext(ctx), NULL, NULL, "swft:import-wav() : invalid arg expecting a string\n"); ctx->error = XPATH_INVALID_TYPE; return; } obj = valuePop(ctx); if (obj->stringval == NULL) { valuePush(ctx, xmlXPathNewNodeSet(NULL)); return; } tctx = xsltXPathGetTransformContext(ctx); filename = obj->stringval; bool quiet = true; xmlXPathObjectPtr quietObj = xsltVariableLookup( tctx, (const xmlChar*)"quiet", NULL ); if( quietObj && quietObj->stringval ) { quiet = !strcmp("true",(const char*)quietObj->stringval ); }; FILE *fp = fopen( (const char *)filename, "rb" ); if( !fp ) { xsltTransformError(xsltXPathGetTransformContext(ctx), NULL, NULL, "swft:import-wav() : failed to read file '%s'\n", (const char *)filename); valuePush(ctx, xmlXPathNewNodeSet(NULL)); return; } doc = xmlNewDoc( (const xmlChar *)"1.0"); doc->xmlRootNode = xmlNewDocNode( doc, NULL, (const xmlChar *)"wav", NULL ); node = doc->xmlRootNode; swft_addFileName( node, (const char *)filename ); // get file size if( stat( (const char *)filename, &filestat ) ) { goto fail; } size = filestat.st_size; data = new unsigned char[size]; // read data if( fread( data, 1, size, fp ) != size ) { fprintf(stderr,"WARNING: could not read enough (%i) bytes from WAVE file %s\n", size, filename ); goto fail; } if( size == 0 ) { fprintf(stderr,"WARNING: WAVE file %s is empty\n", filename ); goto fail; } WaveInfo info; getWaveInfo(info, (char *)data, size); if( !info.valid ) { fprintf(stderr,"WARNING: this file is not a valid WAVE file: %s\n", filename ); goto fail; } if( info.wrongSamplingRate ) { fprintf(stderr,"WARNING: WAVE file %s has a wrong sampling rate\n", filename ); goto fail; } xmlSetProp( node, (const xmlChar *)"format", (const xmlChar *)"3" ); // uncompressed little-endian snprintf(tmp,TMP_STRLEN,"%i", info.flashSamplingRateFlag); xmlSetProp( node, (const xmlChar *)"rate", (const xmlChar *)&tmp ); snprintf(tmp,TMP_STRLEN,"%i", info.is16bit); xmlSetProp( node, (const xmlChar *)"is16bit", (const xmlChar *)&tmp ); snprintf(tmp,TMP_STRLEN,"%i", info.stereo); xmlSetProp( node, (const xmlChar *)"stereo", (const xmlChar *)&tmp ); snprintf(tmp,TMP_STRLEN,"%i", info.samples); xmlSetProp( node, (const xmlChar *)"samples", (const xmlChar *)&tmp ); if( !quiet ) { fprintf(stderr, "Importing WAVE file: '%s'\n", filename); } swft_addData( node, (char*)info.wave_data_ptr, info.wave_data_size ); valuePush( ctx, xmlXPathNewNodeSet( (xmlNodePtr)doc ) ); fail: if( fp ) fclose(fp); if( data ) delete data; } swfmill-0.3.3/src/swft/swft_import.cpp0000777000175000017500000000176212152542002014754 00000000000000#include #include #include #include "base64.h" #include void swft_addFileName( xmlNodePtr node, const char *filename ) { char *name, *n; const char *basename, *b; int l; // figure basename (filename without path) b = strrchr( filename, '/' ); basename = b ? b+1 : filename; l = strlen(basename); name = new char[l + 1]; strncpy( name, basename, l + 1 ); // copy string including null terminator // separate extension (set position of last . as end of string) n = strrchr( name, '.' ); if( n ) n[0]=0; xmlSetProp( node, (const xmlChar *)"name", (const xmlChar *)name ); delete[] name; } void swft_addData( xmlNodePtr node, char *data, int sz ) { char *tmpstr = new char[ (sz * 3) ]; int l = base64_encode( tmpstr, data, sz ); if( l > 0 ) { tmpstr[l] = 0; xmlNewTextChild( node, NULL, (const xmlChar *)"data", (const xmlChar *)tmpstr ); } delete tmpstr; } swfmill-0.3.3/src/swft/SVGTransformParser.cpp0000777000175000017500000000363212152542002016105 00000000000000#include "SVGTransformParser.h" using namespace std; namespace SWF { void TransformParser::printWarning(const string& transformType) { cerr << "WARNING: wrong number of parameters in " << transformType << " transformation" << endl; } void TransformParser::handleData(const string& transformType, const vector& params) { size_t cnt = params.size(); Matrix m; double p[cnt]; for(int i = 0; i < cnt; i++) { p[i] = atof(params[i].c_str()); } if(transformType == "matrix") { if(cnt == 6) { Matrix t = Matrix(p[0], p[2], p[4] * 20, p[1], p[3], p[5] * 20, 0, 0, 1); transformMatrix *= t; } else { printWarning(transformType); } } else if(transformType == "translate") { if(cnt == 1) { transformMatrix.translate(p[0] * 20, 0); } else if (cnt == 2) { transformMatrix.translate(p[0] * 20, p[1] * 20); } else { printWarning(transformType); } } else if(transformType == "scale") { if(cnt == 1) { transformMatrix.scale(p[0]); } else if (cnt == 2) { transformMatrix.scale(p[0], p[1]); } else { printWarning(transformType); } } else if(transformType == "rotate") { if(cnt == 1) { transformMatrix.rotate(p[0] * M_PI / 180.0); } else if(cnt == 3) { transformMatrix.translate(p[1] * 20, p[2] * 20); transformMatrix.rotate(p[0] * M_PI / 180.0); transformMatrix.translate(-p[1] * 20, -p[2] * 20); } else { printWarning(transformType); } } else if(transformType == "skewX") { if(cnt == 1) { transformMatrix.skewX(p[0] * M_PI / 180.0); } else { printWarning(transformType); } } else if(transformType == "skewY") { if(cnt == 1) { transformMatrix.skewY(p[0] * M_PI / 180.0); } else { printWarning(transformType); } } else { cerr << "WARNING: unknown SVG transformation (" << transformType << ")" << endl; } } } swfmill-0.3.3/src/swft/SVGColor.cpp0000777000175000017500000000545112234241357014046 00000000000000#include "SVGColor.h" #include "SVGColors.h" #define TMP_STRLEN 0xFF using namespace std; namespace SWF { SVGColor::SVGColor() { r = 0; g = 0; b = 0; a = 0; } SVGColor::SVGColor(unsigned char _r, unsigned char _g, unsigned char _b, unsigned char _a) { setColor(_r, _g, _b, _a); } void SVGColor::setColor(unsigned char _r, unsigned char _g, unsigned char _b, unsigned char _a) { r = _r; g = _g; b = _b; a = _a; } void SVGColor::setAlpha(unsigned char _a) { a = _a; } void SVGColor::setAlpha(double _a) { a = (unsigned char)(_a * 255.0); } bool SVGColor::parse(string &color) { if(color == "none" || color == "") { return false; } else { if(color[0] == '#') { if(color.length() == 4) { int c[3]; for(int i = 0; i < 3; i++) sscanf(color.substr(1 + i, 1).c_str(), "%x", &c[i]); r = (c[0] << 4) + c[0]; g = (c[1] << 4) + c[1]; b = (c[2] << 4) + c[2]; a = 255; } else if (color.length() == 7) { int c[3]; for(int i = 0; i < 3; i++) sscanf(color.substr(1 + i*2, 2).c_str(), "%x", &c[i]); r = c[0]; g = c[1]; b = c[2]; a = 255; } else { cerr << "WARNING: can't parse color" << endl; return false; } } else if(color.substr(0, 3) == "rgb") { double pR, pG, pB; if(sscanf(color.c_str(), "rgb(%lf%%,%lf%%,%lf%%)", &pR, &pG, &pB) == 3) { r = (unsigned char)(pR / 100.0 * 255.0); g = (unsigned char)(pG / 100.0 * 255.0); b = (unsigned char)(pB / 100.0 * 255.0); a = 255; } else if(sscanf(color.c_str(), "rgb(%hhu,%hhu,%hhu)", &r, &g, &b) == 3) { a = 255; return true; } else { cerr << "WARNING: can't parse rgb color '" << color << "' " << endl; return false; } } else { for(int i = 0; i < SVG_COLOR_COUNT; i++) { if(svgColors[i].name == color) { r = svgColors[i].r; g = svgColors[i].g; b = svgColors[i].b; a = 255; return true; } } cerr << "WARNING: color name not found (" << color << ")" << endl; return false; } } return true; } bool SVGColor::parse(const char *color) { string tmp(color); return parse(tmp); } void SVGColor::writeXML(xmlNodePtr parent, double opacity) { xmlNodePtr node; char tmp[TMP_STRLEN]; node = xmlNewChild(parent, NULL, (const xmlChar *)"Color", NULL); snprintf(tmp, TMP_STRLEN, "%i", r); xmlSetProp(node, (const xmlChar *)"red", (const xmlChar *)&tmp); snprintf(tmp, TMP_STRLEN, "%i", g); xmlSetProp(node, (const xmlChar *)"green", (const xmlChar *)&tmp); snprintf(tmp, TMP_STRLEN, "%i", b); xmlSetProp(node, (const xmlChar *)"blue", (const xmlChar *)&tmp); snprintf(tmp, TMP_STRLEN, "%i", (int) (a * opacity)); xmlSetProp(node, (const xmlChar *)"alpha", (const xmlChar *)&tmp); } } swfmill-0.3.3/src/swft/SVGPointsParser.h0000777000175000017500000000046512152542002015054 00000000000000#ifndef SVG_POINTSPARSER_H #define SVG_POINTSPARSER_H #include #include #include "Geom.h" namespace SWF { class PointsParser { public: void parse(const char *path); Point getPoint(); int getPointCount(); private: deque coords; }; } #endif swfmill-0.3.3/src/swft/swft.h0000777000175000017500000000250012234241357013030 00000000000000#ifndef SWF_SWFT_H #define SWF_SWFT_H #include #include #include #include #include "SVGGradient.h" #include "SVGStyle.h" void swft_register(); // utility functions for import (in swft_import.cpp) void swft_addFileName( xmlNodePtr node, const char *filename ); void swft_addData( xmlNodePtr node, char *data, int length ); char *swft_get_filename( const xmlChar *uri, const xmlChar *baseUri ); #define SWFT_NAMESPACE ((const xmlChar*)"http://subsignal.org/swfml/swft") class swft_ctx { public: std::stack styles; std::map gradients; int last_id; int last_depth; std::stack*> maps; bool quiet; swft_ctx() { last_id = last_depth = 1; pushMap(); } void pushMap() { maps.push( new std::map ); } void popMap() { maps.pop(); } int doMap( const char *oldID ) { int id = atoi( oldID ); if( id == 65535 ) return id; std::map& m = *(maps.top()); int r = m[oldID]; if( r == 0 ) { r = last_id++; m[oldID] = r; } return r; } void setMap( const char *oldID, int newID ) { std::map& m = *(maps.top()); m[oldID] = newID; } }; #endif swfmill-0.3.3/src/swft/SVGStyle.h0000777000175000017500000000405612152542002013523 00000000000000#ifndef SVG_STYLE_H #define SVG_STYLE_H #include #include #include #include "SVGColor.h" #include "SVGGradient.h" #include "SWFShapeMaker.h" namespace SWF { enum SVGLineCap { CAP_ROUND, CAP_BUTT, CAP_SQUARE }; enum SVGLineJoin { JOIN_ROUND, JOIN_BEVEL, JOIN_MITER }; class SVGStyle { public: SVGStyle(); bool setStrokeColor(const char *color) { _hasStroke = stroke.parse(color); _hasStyle = true; return _hasStroke; } void setStrokeWidth(const double width) { strokeWidth = width; _hasStyle = true; } void setStrokeAlpha(const double alpha) { stroke.setAlpha(alpha); _hasStyle = true; } bool setFillColor(const char *color) { _hasFill = fill.parse(color); _hasStyle = true; return _hasFill; } void setFillAlpha(const double alpha) { fill.setAlpha(alpha); _hasStyle = true; } void setOpacity(const double opacity) { _opacity = opacity; _hasStyle = true; } bool setLineCap(const char *cap); bool setLineJoin(const char *join); void setMiterLimit(const double miter) { miterLimit = miter; _hasStyle = true; } double getStrokeWidth() { return strokeWidth; } void setBounds(Rect b) { bounds = b; } bool hasFill() { return _hasFill; } bool hasStroke() { return _hasStroke; } bool hasStyle() { return _hasStyle; } void parseNode(xmlNodePtr node, std::map &gradients); void writeXML(xmlNodePtr parent, double movieVersion); private: SVGGradient *getGradient(const std::string &str, std::map &gradients); bool _hasFill; bool _hasFillGradient; SVGColor fill; SVGGradient *fillGradient; bool _hasStroke; bool _hasStrokeGradient; SVGColor stroke; SVGGradient *strokeGradient; bool _hasLineCap; SVGLineCap lineCap; bool _hasLineJoin; SVGLineJoin lineJoin; double miterLimit; bool _hasStyle; double strokeWidth; double _opacity; Rect bounds; }; } #endif swfmill-0.3.3/src/swft/SVGColors.h0000777000175000017500000001133612152542002013663 00000000000000#ifndef SVG_COLORS_H #define SVG_COLORS_H #include struct ColorStruct { std::string name; unsigned char r; unsigned char g; unsigned char b; }; ColorStruct svgColors[] = { {"aliceblue", 240, 248, 255}, {"antiquewhite", 250, 235, 215}, {"aqua", 0, 255, 255}, {"aquamarine", 127, 255, 212}, {"azure", 240, 255, 255}, {"beige", 245, 245, 220}, {"bisque", 255, 228, 196}, {"black", 0, 0, 0}, {"blanchedalmond", 255, 235, 205}, {"blue", 0, 0, 255}, {"blueviolet", 138, 43, 226}, {"brown", 165, 42, 42}, {"burlywood", 222, 184, 135}, {"cadetblue", 95, 158, 160}, {"chartreuse", 127, 255, 0}, {"chocolate", 210, 105, 30}, {"coral", 255, 127, 80}, {"cornflowerblue", 100, 149, 237}, {"cornsilk", 255, 248, 220}, {"crimson", 220, 20, 60}, {"cyan", 0, 255, 255}, {"darkblue", 0, 0, 139}, {"darkcyan", 0, 139, 139}, {"darkgoldenrod", 184, 134, 11}, {"darkgray", 169, 169, 169}, {"darkgreen", 0, 100, 0}, {"darkgrey", 169, 169, 169}, {"darkkhaki", 189, 183, 107}, {"darkmagenta", 139, 0, 139}, {"darkolivegreen", 85, 107, 47}, {"darkorange", 255, 140, 0}, {"darkorchid", 153, 50, 204}, {"darkred", 139, 0, 0}, {"darksalmon", 233, 150, 122}, {"darkseagreen", 143, 188, 143}, {"darkslateblue", 72, 61, 139}, {"darkslategray", 47, 79, 79}, {"darkslategrey", 47, 79, 79}, {"darkturquoise", 0, 206, 209}, {"darkviolet", 148, 0, 211}, {"deeppink", 255, 20, 147}, {"deepskyblue", 0, 191, 255}, {"dimgray", 105, 105, 105}, {"dimgrey", 105, 105, 105}, {"dodgerblue", 30, 144, 255}, {"firebrick", 178, 34, 34}, {"floralwhite", 255, 250, 240}, {"forestgreen", 34, 139, 34}, {"fuchsia", 255, 0, 255}, {"gainsboro", 220, 220, 220}, {"ghostwhite", 248, 248, 255}, {"gold", 255, 215, 0}, {"goldenrod", 218, 165, 32}, {"gray", 128, 128, 128}, {"green", 0, 128, 0}, {"greenyellow", 173, 255, 47}, {"grey", 128, 128, 128}, {"honeydew", 240, 255, 240}, {"hotpink", 255, 105, 180}, {"indianred", 205, 92, 92}, {"indigo", 75, 0, 130}, {"ivory", 255, 255, 240}, {"khaki", 240, 230, 140}, {"lavender", 230, 230, 250}, {"lavenderblush", 255, 240, 245}, {"lawngreen", 124, 252, 0}, {"lemonchiffon", 255, 250, 205}, {"lightblue", 173, 216, 230}, {"lightcoral", 240, 128, 128}, {"lightcyan", 224, 255, 255}, {"lightgoldenrodyellow", 250, 250, 210}, {"lightgray", 211, 211, 211}, {"lightgreen", 144, 238, 144}, {"lightgrey", 211, 211, 211}, {"lightpink", 255, 182, 193}, {"lightsalmon", 255, 160, 122}, {"lightseagreen", 32, 178, 170}, {"lightskyblue", 135, 206, 250}, {"lightslategray", 119, 136, 153}, {"lightslategrey", 119, 136, 153}, {"lightsteelblue", 176, 196, 222}, {"lightyellow", 255, 255, 224}, {"lime", 0, 255, 0}, {"limegreen", 50, 205, 50}, {"linen", 250, 240, 230}, {"magenta", 255, 0, 255}, {"maroon", 128, 0, 0}, {"mediumaquamarine", 102, 205, 170}, {"mediumblue", 0, 0, 205}, {"mediumorchid", 186, 85, 211}, {"mediumpurple", 147, 112, 219}, {"mediumseagreen", 60, 179, 113}, {"mediumslateblue", 123, 104, 238}, {"mediumspringgreen", 0, 250, 154}, {"mediumturquoise", 72, 209, 204}, {"mediumvioletred", 199, 21, 133}, {"midnightblue", 25, 25, 112}, {"mintcream", 245, 255, 250}, {"mistyrose", 255, 228, 225}, {"moccasin", 255, 228, 181}, {"navajowhite", 255, 222, 173}, {"navy", 0, 0, 128}, {"oldlace", 253, 245, 230}, {"olive", 128, 128, 0}, {"olivedrab", 107, 142, 35}, {"orange", 255, 165, 0}, {"orangered", 255, 69, 0}, {"orchid", 218, 112, 214}, {"palegoldenrod", 238, 232, 170}, {"palegreen", 152, 251, 152}, {"paleturquoise", 175, 238, 238}, {"palevioletred", 219, 112, 147}, {"papayawhip", 255, 239, 213}, {"peachpuff", 255, 218, 185}, {"peru", 205, 133, 63}, {"pink", 255, 192, 203}, {"plum", 221, 160, 221}, {"powderblue", 176, 224, 230}, {"purple", 128, 0, 128}, {"red", 255, 0, 0}, {"rosybrown", 188, 143, 143}, {"royalblue", 65, 105, 225}, {"saddlebrown", 139, 69, 19}, {"salmon", 250, 128, 114}, {"sandybrown", 244, 164, 96}, {"seagreen", 46, 139, 87}, {"seashell", 255, 245, 238}, {"sienna", 160, 82, 45}, {"silver", 192, 192, 192}, {"skyblue", 135, 206, 235}, {"slateblue", 106, 90, 205}, {"slategray", 112, 128, 144}, {"slategrey", 112, 128, 144}, {"snow", 255, 250, 250}, {"springgreen", 0, 255, 127}, {"steelblue", 70, 130, 180}, {"tan", 210, 180, 140}, {"teal", 0, 128, 128}, {"thistle", 216, 191, 216}, {"tomato", 255, 99, 71}, {"turquoise", 64, 224, 208}, {"violet", 238, 130, 238}, {"wheat", 245, 222, 179}, {"white", 255, 255, 255}, {"whitesmoke", 245, 245, 245}, {"yellow", 255, 255, 0}, {"yellowgreen", 154, 205, 50} }; #define SVG_COLOR_COUNT (sizeof(svgColors) / sizeof(ColorStruct)) #endif swfmill-0.3.3/src/swft/readpng.h0000777000175000017500000000646112152542002013465 00000000000000/*--------------------------------------------------------------------------- rpng - simple PNG display program readpng.h --------------------------------------------------------------------------- Copyright (c) 1998-2000 Greg Roelofs. All rights reserved. This software is provided "as is," without warranty of any kind, express or implied. In no event shall the author or contributors be held liable for any damages arising in any way from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. Redistributions of source code must retain the above copyright notice, disclaimer, and this list of conditions. 2. Redistributions in binary form must reproduce the above copyright notice, disclaimer, and this list of conditions in the documenta- tion and/or other materials provided with the distribution. 3. All advertising materials mentioning features or use of this software must display the following acknowledgment: This product includes software developed by Greg Roelofs and contributors for the book, "PNG: The Definitive Guide," published by O'Reilly and Associates. --------------------------------------------------------------------------- NOTE: Greg Roelofs gave explicit permission to use this code under the terms of GPLv2: Greg Roelofs , on Mon, 30 Apr 2007 09:01:24 -0700: > I have no interest in being > petty about this--and I've already been leaning toward copyleft > licensing in my other projects over the last few years--so I've > decided to go ahead and dual-license the pngbook code (readpng{,2}, > writepng, rpng{,2}-{x,win}, wpng) under the GNU GPL v2 or later. You > may take this message as explicit permission insofar as it's likely > to be a while before I actually get around to releasing a new version > of the code--I'm working on XV right now and have pngcheck and a > couple others queued up next. (I'll do my best to do so be- fore the > next version of libpng goes out, however, so the contrib code can be > updated at the same time.) ---------------------------------------------------------------------------*/ #ifndef TRUE # define TRUE 1 # define FALSE 0 #endif #ifndef MAX # define MAX(a,b) ((a) > (b)? (a) : (b)) # define MIN(a,b) ((a) < (b)? (a) : (b)) #endif #ifdef DEBUG # define Trace(x) {fprintf x ; fflush(stderr); fflush(stdout);} #else # define Trace(x) ; #endif #include typedef unsigned char uch; typedef unsigned short ush; typedef unsigned long ulg; #ifdef __cplusplus extern "C" { #endif /* prototypes for public functions in readpng.c */ void readpng_version_info(void); int readpng_init(FILE *infile, ulg *pWidth, ulg *pHeight); int readpng_get_bgcolor(uch *bg_red, uch *bg_green, uch *bg_blue); uch *readpng_get_image(double display_exponent, int *pChannels, ulg *pRowbytes, png_colorp *palette, int *n_pal ); void readpng_cleanup(int free_image_data); #ifdef __cplusplus } #endif swfmill-0.3.3/src/swft/swft_import_mp3.cpp0000777000175000017500000001564612152542002015541 00000000000000#include #include #include #include #include "swft.h" #include #include #include #define TMP_STRLEN 0xff #define ERROR_NO_MP3 -1 #define ERROR_WRONG_SAMPLING_RATE -2 enum { MPEG_V25 = 0, MPEG_RESERVED, MPEG_V2, MPEG_V1, }; const int mpegVersionBitrate[] = { 1, // V2.5, bitrates same as V2 -1, 1, // V2 0 // V1 }; // Only Layer3 is supported const int mp3Bitrates[][15] = { {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320}, // V1 {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}, // V2 & V2.5 }; /* As required in DefineSound, as a function of mpegVersion */ const int flashSamplingRates[] = { 1, // V25 -> 11025, -1, // dummy 2, // V2 -> 22050, 3, // V1 -> 44100; }; const int samplingRates[][4] = { {11025, 12000, 8000, -1}, // V2.5 { -1, -1, -1, -1}, // dummy {22050, 24000, 12000, -1}, // V2 {44100, 48000, 32000, -1}, // V1 }; struct MP3Info { int samplingRate; int samplesPerFrame; int flashSamplingRateFlag; int frames; int stereo; bool validMP3; bool wrongSamplingRate; }; int findFrame( const unsigned char* data, int size, int start ) { int pos = start; while( pos < size ) { if( data[pos] == 0xFF && (data[pos + 1] & 0xE0) == 0xE0 ) { return pos; } pos++; } return -1; } int getFrameSize( const unsigned char* data, int size, int pos, MP3Info &info) { if( pos + 2 >= size ) { return ERROR_NO_MP3; } unsigned char c = data[pos + 1]; int mpegVersion = (c & 0x18) >> 3; // 0:V2.5 1:reserved 2:V2 3:V1 int layer = (c & 0x06) >> 1; // 1 means Layer III // An MP3 file is Layer III, MPEG version any if( layer != 1) { fprintf(stderr, "Error: Layer should be III.\n"); return ERROR_NO_MP3; } if (mpegVersion == MPEG_RESERVED) { fprintf(stderr, "Error: Unknown MPEG version (reserved).\n"); return ERROR_NO_MP3; } c = data[pos + 2]; int bitrate = (c & 0xF0) >> 4; int samplingRate = (c & 0x0C) >> 2; int padding = (c & 0x02) >> 1; if (bitrate > 14) { fprintf(stderr, "MP3 bitrate field invalid. Corrupt MP3 file?"); return ERROR_NO_MP3; } info.samplingRate = samplingRates[mpegVersion][samplingRate]; info.flashSamplingRateFlag = flashSamplingRates[mpegVersion]; if( samplingRate != 0 ) { fprintf(stderr, "Sampling rate: %d\n", info.samplingRate); fprintf(stderr, "Error: Flash only supports sampling rates of 44100, 22050 and 11025 Hz\n"); return ERROR_WRONG_SAMPLING_RATE; } info.samplesPerFrame = mpegVersion == MPEG_V1 ? 1152 : 576; // Since we deal with Layer III only //Calculate the frame size in bytes int br_table = mpegVersionBitrate[mpegVersion]; int frameSize = (info.samplesPerFrame / 8) * (mp3Bitrates[br_table][bitrate] * 1000) / info.samplingRate + padding; return frameSize; } void getMP3Info( MP3Info& info, const unsigned char* data, int size ) { info.frames = 0; info.stereo = 0; info.validMP3 = true; info.wrongSamplingRate = false; int pos = 0; bool first = true; while( (pos = findFrame( data, size, pos)) >= 0 ) { int frameSize = getFrameSize( data, size, pos, info ); if( frameSize > 0 ) { if( first ) { if(pos + 3 < size) { if((data[pos + 3] & 0xC0) != 0xC0) info.stereo = 1; } first = false; } pos += frameSize; info.frames++; } else { if ( frameSize == ERROR_WRONG_SAMPLING_RATE ) { info.wrongSamplingRate = true; } else { info.validMP3 = false; } return; } } //no frames found -> no valid mp3 if( info.frames == 0 ) { info.validMP3 = false; } } void swft_import_mp3( xmlXPathParserContextPtr ctx, int nargs ) { xsltTransformContextPtr tctx; xmlChar *filename; xsltDocumentPtr xsltdoc; xmlDocPtr doc = NULL; xmlNodePtr node; xmlXPathObjectPtr obj; char tmp[TMP_STRLEN]; //data variables unsigned char *data = NULL; int size; struct stat filestat; xmlXPathStringFunction(ctx, 1); if (ctx->value->type != XPATH_STRING) { xsltTransformError(xsltXPathGetTransformContext(ctx), NULL, NULL, "swft:import-mp3() : invalid arg expecting a string\n"); ctx->error = XPATH_INVALID_TYPE; return; } obj = valuePop(ctx); if (obj->stringval == NULL) { valuePush(ctx, xmlXPathNewNodeSet(NULL)); return; } tctx = xsltXPathGetTransformContext(ctx); filename = obj->stringval; bool quiet = true; xmlXPathObjectPtr quietObj = xsltVariableLookup( tctx, (const xmlChar*)"quiet", NULL ); if( quietObj && quietObj->stringval ) { quiet = !strcmp("true",(const char*)quietObj->stringval ); }; FILE *fp = fopen( (const char *)filename, "rb" ); if( !fp ) { xsltTransformError(xsltXPathGetTransformContext(ctx), NULL, NULL, "swft:import-mp3() : failed to read file '%s'\n", (const char *)filename); valuePush(ctx, xmlXPathNewNodeSet(NULL)); return; } doc = xmlNewDoc( (const xmlChar *)"1.0"); doc->xmlRootNode = xmlNewDocNode( doc, NULL, (const xmlChar *)"mp3", NULL ); node = doc->xmlRootNode; swft_addFileName( node, (const char *)filename ); // get file size if( stat( (const char *)filename, &filestat ) ) goto fail; size = filestat.st_size; // flash requires an initial latency value in front of the mp3 data // TODO: check the meaning of this value and set it correctly data = new unsigned char[size + 2]; data[0] = 0; data[1] = 0; // read data if( fread( &data[2], 1, size, fp ) != size ) { fprintf(stderr,"WARNING: could not read enough (%i) bytes for MP3 %s\n", size, filename ); goto fail; } if( size == 0 ) { fprintf(stderr,"WARNING: MP3 %s is empty\n", filename ); goto fail; } MP3Info info; getMP3Info( info, &data[2], size ); if( !info.validMP3 ) { fprintf(stderr,"WARNING: this file is not a valid MP3 %s\n", filename ); goto fail; } if( info.wrongSamplingRate ) { fprintf(stderr,"WARNING: MP3 file %s has a wrong sampling rate\n", filename ); goto fail; } xmlSetProp( node, (const xmlChar *)"format", (const xmlChar *)"2" ); //MP3 snprintf(tmp,TMP_STRLEN,"%i", info.flashSamplingRateFlag); xmlSetProp( node, (const xmlChar *)"rate", (const xmlChar *)&tmp ); xmlSetProp( node, (const xmlChar *)"is16bit", (const xmlChar *)"1" ); //MP3 is always 16bit snprintf(tmp,TMP_STRLEN,"%i", info.stereo); xmlSetProp( node, (const xmlChar *)"stereo", (const xmlChar *)&tmp ); snprintf(tmp,TMP_STRLEN,"%i", info.frames * info.samplesPerFrame); xmlSetProp( node, (const xmlChar *)"samples", (const xmlChar *)&tmp ); if( !quiet ) { fprintf(stderr, "Importing MP3: '%s'\n", filename); } swft_addData( node, (char*)data, size + 2 ); valuePush( ctx, xmlXPathNewNodeSet( (xmlNodePtr)doc ) ); fail: if( fp ) fclose(fp); if( data ) delete data; } swfmill-0.3.3/src/swft/swft_import_png.cpp0000777000175000017500000001447312234241357015635 00000000000000#include #include #include #include #include "swft.h" #include #include #include #include "readpng.h" #include #define TMP_STRLEN 0xff // outLength should contain the allocated size, // will be updated with the actual size bool compress( unsigned char *inputBuffer, int inLength, unsigned char *outputBuffer, int *outLength ) { z_stream stream; int status, count; stream.avail_in = inLength; stream.next_in = inputBuffer; stream.next_out = outputBuffer; stream.zalloc = (alloc_func) NULL; stream.zfree = (free_func) NULL; stream.opaque = (voidpf) 0; stream.avail_out = *outLength; status = deflateInit( &stream, Z_BEST_COMPRESSION ); if( status != Z_OK ) { fprintf( stderr, "ERROR: compressing PNG (1): %s\n", stream.msg ); return false; } while( true ) { if( stream.avail_in == 0 ) break; status = deflate( &stream, Z_NO_FLUSH ); if( status != Z_OK ) { fprintf( stderr, "ERROR: compressing PNG (2): %s\n", stream.msg ); return false; } } do { status = deflate( &stream, Z_FINISH ); } while( status == Z_OK ); if( status != Z_STREAM_END ) { fprintf( stderr, "ERROR: compressing PNG (3): %i, %s\n", status, stream.msg ); return false; } status = deflateEnd(&stream); if( status != Z_OK ) { fprintf( stderr, "ERROR: compressing PNG (4): %s\n", stream.msg ); return false; } *outLength -= stream.avail_out; return true; } void swft_import_png( xmlXPathParserContextPtr ctx, int nargs ) { xsltTransformContextPtr tctx; char *filename; xsltDocumentPtr xsltdoc; xmlDocPtr doc = NULL; xmlNodePtr node; xmlXPathObjectPtr obj; char tmp[TMP_STRLEN]; png_colorp palette; int n_pal; int format = 5; int data_size = 0; xmlXPathStringFunction(ctx, 1); if (ctx->value->type != XPATH_STRING) { xsltTransformError(xsltXPathGetTransformContext(ctx), NULL, NULL, "swft:import-png() : invalid arg expecting a string\n"); ctx->error = XPATH_INVALID_TYPE; return; } obj = valuePop(ctx); if (obj->stringval == NULL) { valuePush(ctx, xmlXPathNewNodeSet(NULL)); return; } tctx = xsltXPathGetTransformContext(ctx); filename = swft_get_filename(obj->stringval, ctx->context->doc->URL); bool quiet = true; xmlXPathObjectPtr quietObj = xsltVariableLookup( tctx, (const xmlChar*)"quiet", NULL ); if (quietObj && quietObj->stringval) { quiet = !strcmp("true", (const char*)quietObj->stringval ); } FILE *fp = fopen( filename, "rb" ); if( !fp ) { xsltTransformError(xsltXPathGetTransformContext(ctx), NULL, NULL, "swft:import-png() : failed to read file '%s'\n", filename); valuePush(ctx, xmlXPathNewNodeSet(NULL)); goto fail; } doc = xmlNewDoc( (const xmlChar *)"1.0"); doc->xmlRootNode = xmlNewDocNode( doc, NULL, (const xmlChar *)"png", NULL ); node = doc->xmlRootNode; swft_addFileName( node, filename ); // add data rewind(fp); unsigned char *data, *compressed; unsigned long w, h, rowbytes; int channels; int compressed_size; if( !fp ) goto fail; if( readpng_init( fp, &w, &h ) ) goto fail; // add w/h snprintf(tmp, TMP_STRLEN, "%lu", w); xmlSetProp( node, (const xmlChar *)"width", (const xmlChar *)&tmp ); snprintf(tmp,TMP_STRLEN,"%lu", h); xmlSetProp( node, (const xmlChar *)"height", (const xmlChar *)&tmp ); data = readpng_get_image( 2.2, &channels, &rowbytes, &palette, &n_pal ); if( !quiet ) { fprintf(stderr,"Importing PNG: '%s' (%lu bit/pixel)\n", filename, (rowbytes*8)/w ); } if( channels == 4 && rowbytes == (4*w) ) { int c; float a; unsigned char r,g,b; for( int i=0; i #include #include namespace SWF { class ShapeItem; template class List; class Bezier { public: Point p0, c0, c1, p1; Bezier() { ; } Bezier( const Point& _p0, const Point& _c0, const Point& _c1, const Point& _p1 ) : p0(_p0), c0(_c0), c1(_c1), p1(_p1) { ; } Bezier &set( const Point& _p0, const Point& _c0, const Point& _c1, const Point& _p1 ) { p0 = _p0; c0 = _c0; c1 = _c1; p1 = _p1; return *this; } Bezier split (double t) { Point m1 = p0 + (c0 - p0) * t; Point m2 = c0 + (c1 - c0) * t; Point m3 = c1 + (p1 - c1) * t; Point mm1 = m1 + (m2 - m1) * t; Point mm2 = m2 + (m3 - m2) * t; Point p = mm1 + (mm2 - mm1) * t; Bezier part1 = Bezier (p0, m1, mm1, p); p0 = p; c0 = mm2; c1 = m3; //p1 = p1; return part1; } int computeInflections (double &t0, double &t1) const { Point a = c0 - p0; Point b = c1 - c0 - a; Point c = p1 - c1 - a - b - b; double A = b.x * c.y - b.y * c.x; if (A == 0) return 0; double B = a.x * c.y - a.y * c.x; double C = a.x * b.y - a.y * b.x; double disc = B * B - 4 * A * C; if (disc < 0) return 0; // no real roots if (disc == 0) { // double root t0 = -B / (2 * A); if (t0 <= 0 || t0 >= 1) return 0; // outside bounds return 1; } // sort roots if (A < 0) { A = -A; B = -B; C = -C; } double Q = sqrt (disc); t0 = (-B - Q) / (2 * A); t1 = (-B + Q) / (2 * A); int cInflections = 2; // assume 2 roots if (t1 <= 0 || t1 >= 1) cInflections--; // t1 out of bounds if (t0 <= 0 || t0 >= 1) { cInflections--; // t0 out of bounds t0 = t1; // use t1 instead } return cInflections; } Point quadraticCtrl () const { return ((c0 + c1) * 3 - (p0 + p1)) / 4; } }; class ShapeMaker { public: ShapeMaker( List* edges, double fx = 1, double fy = 1, double ofsx = 0, double ofsy = 0 ); void setStyle( int _fillStyle0=-1, int _fillStyle1=-1, int _lineStyle=-1 ) { fillStyle0 = _fillStyle0; fillStyle1 = _fillStyle1; lineStyle = _lineStyle; } void setup( double x = 0, double y = 0 ); void setupR( double x = 0, double y = 0 ); void lineTo( double x, double y ); void lineToR( double x, double y ); void curveTo( double cx, double cy, double ax, double ay ); void curveToR( double cx, double cy, double ax, double ay ); void curveTo (const Point &c, const Point &p) { curveTo (c.x, c.y, p.x, p.y); } void smoothCurveTo( double ax, double ay ); void smoothCurveToR( double ax, double ay ); void cubicTo( double x1, double y1, double x2, double y2, double ax, double ay ); void cubicToR( double x1, double y1, double x2, double y2, double ax, double ay ); void smoothCubicTo( double x2, double y2, double ax, double ay ); void smoothCubicToR( double x2, double y2, double ax, double ay ); void close(bool stroke = true); void finish(); void rect( double x, double y, double width, double height, double rx = 0, double ry = 0 ); void ellipse( double cx, double cy, double rx, double ry ); void arcTo( double rx, double ry, double rotation, bool largeArcFlag, bool sweepFlag, double x, double y ); void arcToR( double rx, double ry, double rotation, bool largeArcFlag, bool sweepFlag, double x, double y ); void boundsWriteXML( xmlNodePtr node, double border = -1 ); double getLastX() { return lastx; } double getLastY() { return lasty; } double getSmoothX() { return smoothx; } double getSmoothY() { return smoothy; } Rect getBounds() { return Rect(minx, miny, maxx, maxy); } protected: void cubicTo (const Bezier &cubic); void doSetup( double _x=0, double _y=0, bool hasMoveTo=true, int _fillStyle0=-1, int _fillStyle1=-1, int _lineStyle=-1); void ellipseSegment( double cx, double cy, double rx, double ry, double phi, double theta, double dTheta); void minmax( double x, double y ) { if( !have_first ) { have_first = true; minx = x; maxx=x; miny=y; maxy=y; } else { if( x < minx ) minx=x; if( y < miny ) miny=y; if( x > maxx ) maxx=x; if( y > maxy ) maxy=y; } } List* edges; double factorx, factory; double offsetx, offsety; double diffx, diffy; double lastx, lasty; double lastsetupx, lastsetupy; double minx, miny, maxx, maxy; double smoothx, smoothy; bool have_first; int fillStyle0, fillStyle1, lineStyle; // rounding error accumulation compensation double roundx, roundy; int roundX( double x ) { return round( x, &roundx ); } int roundY( double y ) { return round( y, &roundy ); } int round( double v, double *acc ) { int r = (int)v; *acc += v-(double)r; while( *acc >= .5 ) { *acc -= 1.0; r++; } while( *acc <= -.5 ) { *acc += 1.0; r--; } return r; } void roundReset() { roundx = roundy = 0; } }; } #endif swfmill-0.3.3/src/SWFTrait.cpp0000777000175000017500000000121112152542002013044 00000000000000#include #include "SWF.h" #include namespace SWF { Trait *Trait::get( Reader *r, int end, Context *ctx ) { int type = r->getNBitInt( 4 ); int len = end - r->getPosition(); Trait* ret = getByType( type ); if( !ret ) { ret = handleError( type ); } if( ret ) { ret->setType( type ); ret->setLength( len ); ret->parse( r, end, ctx ); } return ret; } void Trait::writeHeader( Writer *w, Context *ctx, size_t len ) { w->putNBitInt( type, 4 ); } Trait* Trait::handleError( int type ) { fprintf(stderr,"WARNING: unknown trait type 0x%02X\n", type ); return NULL; } } swfmill-0.3.3/src/SWF.h0000664000175000017500000114530112234555372011531 00000000000000 #ifndef SWF_H #define SWF_H #include #include #include #include #include #include #include #include #include #include namespace SWF { struct Context { public: Context(); int swfVersion; bool transientPropsToXML; bool debugTrace; bool exportAssets; bool quiet; bool isLast; char tagVersion; bool alpha; bool many_shapes; bool convertEncoding; const char *swf_encoding; int fillBits; int lineBits; unsigned char glyphBits; unsigned char advanceBits; bool wideGlyphOffsets; bool wideMap; unsigned short glyphCount; }; class Rectangle : public Item { public: Rectangle(); virtual ~Rectangle(); virtual bool parse( Reader *r, int end, Context *ctx ); virtual void dump( int indent, Context *ctx ); virtual size_t calcSize( Context *ctx, int start_at ); virtual void write( Writer *w, Context *ctx ); virtual void writeXML( xmlNodePtr xml, Context *ctx ); virtual void parseXML( xmlNodePtr xml, Context *ctx ); static Rectangle* get( Reader *r, int end, Context *ctx ); static Rectangle* getByName( const char *name ); int getbits(); void setbits( int ); int getleft(); void setleft( int ); int getright(); void setright( int ); int gettop(); void settop( int ); int getbottom(); void setbottom( int ); protected: int bits; // integer int left; // integer int right; // integer int top; // integer int bottom; // integer }; class Color : public Item { public: Color(); virtual ~Color(); virtual bool parse( Reader *r, int end, Context *ctx ); virtual void dump( int indent, Context *ctx ); virtual size_t calcSize( Context *ctx, int start_at ); virtual void write( Writer *w, Context *ctx ); virtual void writeXML( xmlNodePtr xml, Context *ctx ); virtual void parseXML( xmlNodePtr xml, Context *ctx ); static Color* get( Reader *r, int end, Context *ctx ); static Color* getByName( const char *name ); unsigned char getred(); void setred( unsigned char ); unsigned char getgreen(); void setgreen( unsigned char ); unsigned char getblue(); void setblue( unsigned char ); unsigned char getalpha(); void setalpha( unsigned char ); protected: unsigned char red; // byte unsigned char green; // byte unsigned char blue; // byte unsigned char alpha; // byte }; class String : public Item { public: String(); virtual ~String(); virtual bool parse( Reader *r, int end, Context *ctx ); virtual void dump( int indent, Context *ctx ); virtual size_t calcSize( Context *ctx, int start_at ); virtual void write( Writer *w, Context *ctx ); virtual void writeXML( xmlNodePtr xml, Context *ctx ); virtual void parseXML( xmlNodePtr xml, Context *ctx ); static String* get( Reader *r, int end, Context *ctx ); static String* getByName( const char *name ); char * getvalue(); void setvalue( char * ); protected: char * value; // string }; class String2 : public Item { public: String2(); virtual ~String2(); virtual bool parse( Reader *r, int end, Context *ctx ); virtual void dump( int indent, Context *ctx ); virtual size_t calcSize( Context *ctx, int start_at ); virtual void write( Writer *w, Context *ctx ); virtual void writeXML( xmlNodePtr xml, Context *ctx ); virtual void parseXML( xmlNodePtr xml, Context *ctx ); static String2* get( Reader *r, int end, Context *ctx ); static String2* getByName( const char *name ); char * getvalue(); void setvalue( char * ); protected: char * value; // string }; class Transform : public Item { public: Transform(); virtual ~Transform(); virtual bool parse( Reader *r, int end, Context *ctx ); virtual void dump( int indent, Context *ctx ); virtual size_t calcSize( Context *ctx, int start_at ); virtual void write( Writer *w, Context *ctx ); virtual void writeXML( xmlNodePtr xml, Context *ctx ); virtual void parseXML( xmlNodePtr xml, Context *ctx ); static Transform* get( Reader *r, int end, Context *ctx ); static Transform* getByName( const char *name ); bool getscaled(); void setscaled( bool ); int getbitsScale(); void setbitsScale( int ); float getscaleX(); void setscaleX( float ); float getscaleY(); void setscaleY( float ); bool getskewed(); void setskewed( bool ); int getbitsSkew(); void setbitsSkew( int ); float getskewX(); void setskewX( float ); float getskewY(); void setskewY( float ); int getbitsTranslate(); void setbitsTranslate( int ); int gettransX(); void settransX( int ); int gettransY(); void settransY( int ); protected: bool scaled; // bit int bitsScale; // integer float scaleX; // fixedpoint float scaleY; // fixedpoint bool skewed; // bit int bitsSkew; // integer float skewX; // fixedpoint float skewY; // fixedpoint int bitsTranslate; // integer int transX; // integer int transY; // integer }; class ColorTransform2 : public Item { public: ColorTransform2(); virtual ~ColorTransform2(); virtual bool parse( Reader *r, int end, Context *ctx ); virtual void dump( int indent, Context *ctx ); virtual size_t calcSize( Context *ctx, int start_at ); virtual void write( Writer *w, Context *ctx ); virtual void writeXML( xmlNodePtr xml, Context *ctx ); virtual void parseXML( xmlNodePtr xml, Context *ctx ); static ColorTransform2* get( Reader *r, int end, Context *ctx ); static ColorTransform2* getByName( const char *name ); bool gethasOffset(); void sethasOffset( bool ); bool gethasFactor(); void sethasFactor( bool ); int getbits(); void setbits( int ); int getfactorRed(); void setfactorRed( int ); int getfactorGreen(); void setfactorGreen( int ); int getfactorBlue(); void setfactorBlue( int ); int getfactorAlpha(); void setfactorAlpha( int ); int getoffsetRed(); void setoffsetRed( int ); int getoffsetGreen(); void setoffsetGreen( int ); int getoffsetBlue(); void setoffsetBlue( int ); int getoffsetAlpha(); void setoffsetAlpha( int ); protected: bool hasOffset; // bit bool hasFactor; // bit int bits; // integer int factorRed; // integer int factorGreen; // integer int factorBlue; // integer int factorAlpha; // integer int offsetRed; // integer int offsetGreen; // integer int offsetBlue; // integer int offsetAlpha; // integer }; class Header : public Item { public: Header(); virtual ~Header(); virtual bool parse( Reader *r, int end, Context *ctx ); virtual void dump( int indent, Context *ctx ); virtual size_t calcSize( Context *ctx, int start_at ); virtual void write( Writer *w, Context *ctx ); virtual void writeXML( xmlNodePtr xml, Context *ctx ); virtual void parseXML( xmlNodePtr xml, Context *ctx ); static Header* get( Reader *r, int end, Context *ctx ); static Header* getByName( const char *name ); Rectangle *getsize(); int getframerate(); void setframerate( int ); unsigned short getframes(); void setframes( unsigned short ); List *gettags(); protected: Rectangle size; // object int framerate; // integer unsigned short frames; // word List tags; // list }; class LineStyle : public Item { public: LineStyle(); virtual ~LineStyle(); virtual bool parse( Reader *r, int end, Context *ctx ); virtual void dump( int indent, Context *ctx ); virtual size_t calcSize( Context *ctx, int start_at ); virtual void write( Writer *w, Context *ctx ); virtual void writeXML( xmlNodePtr xml, Context *ctx ); virtual void parseXML( xmlNodePtr xml, Context *ctx ); static LineStyle* get( Reader *r, int end, Context *ctx ); static LineStyle* getByName( const char *name ); unsigned short getwidth(); void setwidth( unsigned short ); Color *getcolor(); int getstartCapStyle(); void setstartCapStyle( int ); int getjointStyle(); void setjointStyle( int ); bool gethasFill(); void sethasFill( bool ); bool getnoHScale(); void setnoHScale( bool ); bool getnoVScale(); void setnoVScale( bool ); bool getpixelHinting(); void setpixelHinting( bool ); int getreserved(); void setreserved( int ); bool getnoClose(); void setnoClose( bool ); int getendCapStyle(); void setendCapStyle( int ); float getmiterLimitFactor(); void setmiterLimitFactor( float ); List