www.pudn.com > sswf-1.7.4-src.zip > libsswf.h
/* libsswf.h -- written by Alexis WILKE for Made to Order Software, Ltd. (c) 2002-2006 */ #ifndef LIBSSWF_H #define LIBSSWF_H /* Copyright (c) 2002-2006 Made to Order Software, Ltd. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include#include #include #ifndef _MSVC #include #endif #include #include #include #include #include #include #include #ifdef STATIC_ICONV #include #else #include #endif #if IRIX #include #endif #include "sswf/libsswf-config.h" /* wint_t is an "equivalent" to wchar_t without being limited to 16 bits as on MS-Windows */ #ifndef _MSVC #ifndef __APPLE_CC__ #ifndef _WINT_T #define _WINT_T typedef unsigned int wint_t; #endif #endif #endif #ifndef M_PI #define M_PI 3.14159265358979323846 #endif #ifdef _MSVC #define strcasecmp stricmp #define rint(x) ((double) (long) floor(x + 0.5)) #endif #ifdef _LIBICONV_H #define ICONV_INPUT_CAST #else /* older versions of iconv() were broken in regard to the * input buffer which wasn't const; newer versions have the * _LIBICONV_H #define at the start so this is good to know * whether we have to cast or not. */ #define ICONV_INPUT_CAST (char**) #endif namespace sswf { void assert(int cond, const char *format, ...) #ifndef _MSVC __attribute__ ((format (printf, 2, 3))) #endif ; #if DEBUG inline void assert(int cond, const char *format, ...) { va_list ap; // if the condition is true then we have no problem! if(cond) { return; } fflush(stdout); fflush(stderr); fprintf(stderr, "\n"); va_start(ap, format); vfprintf(stderr, format, ap); va_end(ap); fprintf(stderr, ".\n"); fflush(stderr); // some systems don't do this inside the abort()! abort(); } #else inline void assert(int /*cond*/, const char * /*format*/, ...) {} #endif typedef unsigned short sswf_id_t; // object ID reference typedef unsigned short sswf_frame_t; // frame counter typedef signed long sswf_ucs4_t; // a wide character (must be at least 32 bits) #define SSWF_ID_NONE ((sswf_id_t) -1) // this is an invalid ID (it seems) extern void swap(void *s1, void *s2, size_t size); extern int wctomb(const sswf_ucs4_t *wc, size_t wc_len, char *mb, size_t& mb_size); extern int mbtowc(const char *mb, size_t mb_len, sswf_ucs4_t *& wc, size_t& wc_len); extern char * wcname(sswf_ucs4_t wc, char *result); extern long wcslen(sswf_ucs4_t *wcstr); inline unsigned short swap_short(unsigned short s) { return (s >> 8) | (s << 8); } inline unsigned int swap_int(unsigned int l) { return (l >> 24) | (l << 24) | ((l >> 8) & 0x0000FF00) | ((l << 8) & 0x00FF0000); } extern const char * sswf_version(void); class Buffer; class MemBuffer { public: MemBuffer(void); virtual ~MemBuffer(); void AttachBuffer(Buffer *buffer); Buffer * GetBuffer(void) const; private: Buffer * f_buffer; }; class Buffer { public: Buffer(Buffer **head, size_t size, const char *info); Buffer(Buffer **head, MemBuffer *ptr, size_t size, const char *info); //Buffer(Buffer **head, void *ptr, size_t size, const char *info); ~Buffer(); void * Realloc(size_t size); void * Data(void) const { return f_data; } Buffer * Next(void) const { return (Buffer *) f_next; } Buffer * Previous(void) const { return (Buffer *) f_previous; } size_t Size(void) const { return f_size; } const char * Info(void) const { return f_info; } static Buffer * FindBuffer(void *ptr); #if 0 // this is totally wrong and it simply can't be used safely static bool IsBuffer(void *ptr); #endif private: struct mem_buffer_t { unsigned long f_magic; // to make sure we have indead a valid buffer Buffer * f_buffer; // reference back to 'this' buffer }; enum { DMAGIC = (unsigned long) 0x53535746, // direct (malloc) OMAGIC = (unsigned long) 0x5353574F // object (new/delete) }; #define SSWF_ALIGN(value, modulo) (((value) + ((modulo) - 1)) & - (long) (modulo)) #define SSWF_SPACE SSWF_ALIGN(sizeof(mem_buffer_t), sizeof(double)) #if DEBUG void Test(void); #define SSWF_SAFE (sizeof(double) * 32) #define SSWF_TEST ((long)0xBADC0FFE) #else #define SSWF_SAFE 0 #endif Buffer ** f_head; // header for this list of buffers Buffer * f_next; Buffer * f_previous; const char * f_info; size_t f_size; mutable void * f_data; }; class MemoryManager { public: MemoryManager(void); virtual ~MemoryManager(); void MemAttach(MemBuffer *ptr, size_t size, const char *info); // used when you require the use of a ::new ... call void * MemAlloc(size_t size, const char *info); void * MemRealloc(void *ptr, size_t size, const char *info); // info used ONLY if ptr == 0 void MemFree(void *ptr); void MemClean(void *ptr); char * StrDup(const char *string); char * StrCat(const char *s1, const char *s2); #if DEBUG void MemTest(void *ptr); #endif unsigned long Size(void *ptr); private: Buffer * f_head; }; class ItemBase : public MemBuffer { public: ItemBase(void) {} virtual ~ItemBase() {} }; class Vectors : public MemoryManager, public MemBuffer { public: Vectors(void); Vectors(const Vectors& vector); ~Vectors(); ItemBase * Get(int index) const; void Set(int index, ItemBase *vector); void Insert(int index, ItemBase *vector); void SetSize(int size); int Count(void) const { return f_count; } void Empty(void) { f_count = 0; } // currently we keep the f_vectors buffer Vectors& operator = (const Vectors& vectors); private: int f_count; // # of valid pointers int f_max; // max. # of pointers until realloc ItemBase ** f_vectors; // an array of pointers }; class Data : public MemoryManager { public: Data(void); ~Data(); void Empty(void) { f_pos = 0; } // make the buffer empty (reset/restart) void Align(void); // align to the next byte void Overwrite(size_t offset, const void *ptr, size_t size); void OverwriteByte(size_t offset, char c); void OverwriteShort(size_t offset, short s); void OverwriteLong(size_t offset, long l); void Write(const void *ptr, size_t size); // write bytes void WriteBits(long value, size_t bits); // write the 'bits' lower bits of value void PutByte(char c); // write one byte void PutShort(short s); // write one short (auto-swap) void PutLong(long l); // write one long (auto-swap) void PutString(const char *string); // write a null terminated string (including the terminator) void Append(const Data& data); // append another data buffer in here void Read(void *& ptr, size_t& size); // retrieve the buffer and its size rounded up to the next byte (Align() is called once) // if you want the size in bits, use the Size() function call unsigned long ByteSize(void) const { return (f_pos + CHAR_BIT - 1) / CHAR_BIT; } unsigned long Size(void) const { return f_pos; } // total size in bits void Size(unsigned long size); private: void SetSize(size_t size); unsigned long f_pos; unsigned long f_size; char * f_data; }; // the following are structures used within the tags defined afterward class SRectangle { public: SRectangle(void); void Reset(void); void Set(long xmin, long xmax, long ymin, long ymax); void SetReorder(long xmin, long xmax, long ymin, long ymax); long XMin(void) const; long XMax(void) const; long YMin(void) const; long YMax(void) const; bool IsEmpty(void) const; void Save(Data& data) const; private: long f_xmin; long f_xmax; long f_ymin; long f_ymax; }; class Color { public: Color(void) { Reset(); } void Reset(void); void Set(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha = 255); unsigned char Red(void) const { return f_red; } unsigned char Green(void) const { return f_green; } unsigned char Blue(void) const { return f_blue; } unsigned char Alpha(void) const { return f_alpha; } void Save(Data& data, bool save_alpha = true); bool operator == (const Color& color) const; bool operator != (const Color& color) const; bool IsSolid(void) const { return f_alpha == 255; } bool IsInvisible(void) const { return f_alpha == 0; } private: unsigned char f_red; unsigned char f_green; unsigned char f_blue; unsigned char f_alpha; }; class ColorTransform { public: ColorTransform(void) { Reset(); } void Reset(void); void SetAdd(double red, double green, double blue, double alpha = 0.0); void SetMult(double red, double green, double blue, double alpha = 1.0); double AddRed(void) const { return f_add_red; } double AddGreen(void) const { return f_add_green; } double AddBlue(void) const { return f_add_blue; } double AddAlpha(void) const { return f_add_alpha; } double MultRed(void) const { return f_add_red; } double MultGreen(void) const { return f_add_green; } double MultBlue(void) const { return f_add_blue; } double MultAlpha(void) const { return f_add_alpha; } void Save(Data& data, bool save_alpha = true); bool IsNull(bool with_alpha) const; // if true we can ignore this transformation! bool IsSolidCompatible(void) const { return f_add_alpha == 0.0 && f_mult_alpha == 1.0; } private: double f_add_red; double f_add_green; double f_add_blue; double f_add_alpha; double f_mult_red; double f_mult_green; double f_mult_blue; double f_mult_alpha; }; class Matrix { public: Matrix(void); void Reset(void); void SetScale(double x, double y) { f_scale_x = x; f_scale_y = y; } void SetScale(double scale) { f_scale_x = scale; f_scale_y = scale; } void SetRotate(double rotate); void SetSkew(double skew0, double skew1) { f_skew_0 = skew0; f_skew_1 = skew1; } void SetTranslate(long x, long y) { f_translate_x = x; f_translate_y = y; } void Save(Data& data); bool IsNull(void) const; bool operator == (const Matrix& matrix) const; bool operator != (const Matrix& matrix) const; private: double f_scale_x; double f_scale_y; double f_rotate; long f_translate_x; long f_translate_y; double f_skew_0; double f_skew_1; }; class Envelope : public ItemBase { public: Envelope(unsigned long p, unsigned short l, unsigned short r); Envelope(const Envelope& envelope); unsigned long Position(void) const; unsigned short Left(void) const; unsigned short Right(void) const; void Save(Data& data) const; private: unsigned long f_position; unsigned short f_left; unsigned short f_right; }; class SoundInfo : public MemoryManager { public: SoundInfo(void); void SetSoundID(sswf_id_t id); void StopSound(bool stop = true); void NoMultiple(bool no_multiple = true); void SetRange(unsigned long start, unsigned long end); void SetLoop(unsigned short loop); void AddEnvelope(const Envelope& envelope); void Save(Data& data) const; private: sswf_id_t f_sound_id; bool f_stop; // if true, ignore all the other info bool f_no_multiple; // never play this sound more than once unsigned long f_start_position; // start playing from this sample unsigned long f_end_position; // stop playing at this sample unsigned short f_loop; // repeat the sound this many times Vectors f_envelopes; // a list of position + volume information }; class State : public ItemBase { public: State(void); void Reset(void); void SetObjectID(sswf_id_t id); void SetFlags(unsigned char flags); void SetLayer(unsigned short layer); void SetMatrix(const Matrix& matrix); void SetColorTransform(const ColorTransform& color_transform); bool HasColorTransform(void) const; void Save(Data& data, bool color_transform = false); private: sswf_id_t f_id; bool f_id_defined; bool f_has_color_transform; unsigned char f_flags; unsigned short f_layer; Matrix f_matrix; ColorTransform f_color_transform; }; class Action; class Event : public MemoryManager, public ItemBase { public: Event(void); void Reset(void); void SetEvents(unsigned long events); void SetKey(unsigned char key); unsigned long Events(void) const; // PlaceObject2 flags unsigned long Conditions(void) const; // DefineButton2 flags unsigned char Key(void) const; Vectors& Actions(void); static unsigned long StringToEvents(const char *s); static unsigned char StringToKeyCode(const char *s); // the flags are saved with the following bits // in a PlaceObject2 // these have to be converted when saved in a // DefineButton2 tag enum event_flag_t { EVENT_COND_MENU_LEAVE = 0x80000000, // for DefineButton2 EVENT_COND_MENU_ENTER = 0x40000000, // for DefineButton2 EVENT_CONSTRUCT = 0x00040000, // V7.x EVENT_KEY_PRESS = 0x00020000, // V6.x EVENT_POINTER_DRAG_LEAVE = 0x00010000, // V6.x shared with DefineButton2 EVENT_POINTER_DRAG_ENTER = 0x00008000, // V5.x shared with DefineButton2 EVENT_POINTER_LEAVE = 0x00004000, // V5.x shared with DefineButton2 EVENT_POINTER_ENTER = 0x00002000, // V5.x shared with DefineButton2 EVENT_POINTER_RELEASE_OUTSIDE = 0x00001000, // V5.x shared with DefineButton2 EVENT_POINTER_RELEASE_INSIDE = 0x00000800, // V5.x shared with DefineButton2 EVENT_POINTER_PUSH = 0x00000400, // V5.x shared with DefineButton2 EVENT_INITIALIZE = 0x00000200, // V5.x EVENT_DATA = 0x00000100, // V5.x EVENT_KEY_UP = 0x00000080, // V6.x EVENT_KEY_DOWN = 0x00000040, // V6.x EVENT_POINTER_UP = 0x00000020, // V6.x EVENT_POINTER_DOWN = 0x00000010, // V6.x EVENT_POINTER_MOVE = 0x00000008, // V6.x EVENT_UNLOAD = 0x00000004, // V6.x EVENT_ENTER_FRAME = 0x00000002, // V6.x EVENT_ONLOAD = 0x00000001 // V5.x }; #define SSWF_EVENT_V5 0x0000FF01 // flags present in V5 #define SSWF_EVENT_V6 0x000300FE // flags added in V6 #define SSWF_EVENT_V7 0x00040000 // flag added in V7 #define SSWF_EVENT_CONDITIONS 0xC001FC00 // flags used by conditions in DefineButton2 #define SSWF_EVENT_COUNT 20 struct event_names_t { event_flag_t f_flag; const char * f_name; }; static const event_names_t f_event_names[SSWF_EVENT_COUNT]; enum condition_flag_t { CONDITION_KEY_MASK = 0xFE00, CONDITION_MENU_LEAVE = 0x0100, // OVER_DOWN_TO_IDLE CONDITION_MENU_ENTER = 0x0080, // IDLE_TO_OVER_DOWN CONDITION_POINTER_RELEASE_OUTSIDE = 0x0040, // OUT_DOWN_TO_IDLE CONDITION_POINTER_DRAG_ENTER = 0x0020, // OUT_DOWN_TO_OVER_DOWN CONDITION_POINTER_DRAG_LEAVE = 0x0010, // OVER_DOWN_TO_OUT_DOWN CONDITION_POINTER_RELEASE_INSIDE = 0x0008, // OVER_DOWN_TO_OVER_UP CONDITION_POINTER_PUSH = 0x0004, // OVER_UP_TO_OVER_DOWN CONDITION_POINTER_LEAVE = 0x0002, // OVER_UP_TO_IDLE CONDITION_POINTER_ENTER = 0x0001 // IDLE_TO_OVER_UP }; enum key_code_t { KEY_CODE_NONE = 0, KEY_CODE_LEFT_ARROW = 1, KEY_CODE_RIGHT_ARROW = 2, KEY_CODE_HOME = 3, KEY_CODE_END = 4, KEY_CODE_INSERT = 5, KEY_CODE_DELETE = 6, KEY_CODE_BACKSPACE = 8, KEY_CODE_ENTER = 13, KEY_CODE_UP_ARROW = 14, KEY_CODE_DOWN_ARROW = 15, KEY_CODE_PAGE_UP = 16, KEY_CODE_PAGE_DOWN = 17, KEY_CODE_TAB = 18, KEY_CODE_ESCAPE = 19, KEY_CODE_SPACE = 20, // equal to ' ' // and also all the ASCII codes from 32 to 126 }; #define SSWF_KEY_COUNT 15 struct key_names_t { key_code_t f_code; const char * f_name; }; static const key_names_t f_key_names[SSWF_KEY_COUNT]; private: unsigned long f_events; unsigned char f_key; Vectors f_actions; }; class Style : public ItemBase { public: enum style_t { STYLE_TYPE_UNKNOWN = 0, STYLE_TYPE_NO_LINE, STYLE_TYPE_NO_FILL, STYLE_TYPE_LINE, STYLE_TYPE_SOLID, STYLE_TYPE_GRADIENT_LINEAR, STYLE_TYPE_GRADIENT_RADIAL, STYLE_TYPE_BITMAP_TILLED, STYLE_TYPE_BITMAP_CLIPPED, STYLE_TYPE_BITMAP_HARDEDGE_TILLED, STYLE_TYPE_BITMAP_HARDEDGE_CLIPPED, STYLE_TYPE_MATRIX, // intermediate type used when a matrix is defined before // a gradient or bitmap info (or the SetType() is called) STYLE_TYPE_max }; Style(void); void Reset(void); style_t Type(void) const { return f_style; } bool HasMorph(void) const { return f_morph; } bool HasAlpha(void) const { return f_use_alpha; } bool HasHardEdges(void) const { return f_style == STYLE_TYPE_BITMAP_HARDEDGE_TILLED || f_style == STYLE_TYPE_BITMAP_HARDEDGE_CLIPPED; } void SetType(style_t style); void SetLine(int index, unsigned short width, const Color& color); void SetColor(int index, const Color& color); void SetGradient(int index, int pos, const Color& color); void SetMatrix(int index, const Matrix& matrix); void SetBitmap(sswf_id_t id); void SetClipping(void); void Save(Data& data, bool save_alpha, bool save_morph); bool operator == (const Style& style) const; private: // the style style_t f_style; // whether this is for a DefineMorphShape or not bool f_morph; // whether some color alpha is not 255 bool f_use_alpha; // a line width unsigned short f_line_width[2]; // solid fill or line colors Color f_color[2]; // bitmap reference (its ID) sswf_id_t f_bitmap_ref; // matrices - 1 or 2 - regular of morph shapes Matrix f_matrix[2]; // gradient positions & colors - 8 or 16 - regular or morph shapes signed char f_gradient; // largest index used (0..7 only or -1 when no gradient) unsigned char f_gradient_pos[16]; Color f_gradient_color[16]; }; class Edges : public MemoryManager, public ItemBase { public: // This should be private by cl (from Microsoft) doesn't understand // the use of private too well... enum { // better with a power of two (we use * and / a lot with it!) EDGE_BLOCK = 64 }; struct edge_t { long f_x; long f_y; long f_ctrl_x; /* LONG_MIN if a line only */ long f_ctrl_y; edge_t(void) { f_x = 0; f_y = 0; f_ctrl_x = LONG_MIN; f_ctrl_y = LONG_MIN; } edge_t(long x, long y) { f_x = x; f_y = y; f_ctrl_x = LONG_MIN; f_ctrl_y = LONG_MIN; } edge_t(long x, long y, long ctrl_x, long ctrl_y) { f_x = x; f_y = y; f_ctrl_x = ctrl_x; f_ctrl_y = ctrl_y; } edge_t(const edge_t& edge) { f_x = edge.f_x; f_y = edge.f_y; f_ctrl_x = edge.f_ctrl_x; f_ctrl_y = edge.f_ctrl_y; } edge_t& operator = (const edge_t& edge) { f_x = edge.f_x; f_y = edge.f_y; f_ctrl_x = edge.f_ctrl_x; f_ctrl_y = edge.f_ctrl_y; return *this; } bool IsLine(void) const { return f_ctrl_x == LONG_MIN || f_ctrl_y == LONG_MIN; } }; Edges(void); virtual ~Edges() {} void Reset(void); void Set(long x, long y) { edge_t edge(x, y); Set(-1, edge); } void Set(long x, long y, long ctrl_x, long ctrl_y) { edge_t edge(x, y, ctrl_x, ctrl_y); Set(-1, edge); } void Set(int index, long x, long y, long ctrl_x, long ctrl_y) { edge_t edge(x, y, ctrl_x, ctrl_y); Set(index, edge); } void Set(const edge_t& edge) { Set(-1, edge); } void Set(int index, const edge_t& edge); void Save(Data& data, long& x, long& y); private: struct array_edge_t : public ItemBase { edge_t f_edge[EDGE_BLOCK]; }; // no copy operators at this time Edges(const Edges& edges) {} Edges& operator = (const Edges& edges) { return *this; } void SaveEdge(Data& data, const edge_t& edge, long& x, long& y); Vectors f_edges; int f_pos; /* position in the current array */ array_edge_t f_array; /* current array; when full, put in f_edges */ }; // one can't create a tag base, only full qualified // tags can be created (see below) class TagHeader; class TagBase : public MemoryManager { public: // anything in the file is represented by a tag enum swf_tag_t { SWF_TAG_UNKNOWN = -1, // undefined tag // V1.0 SWF_TAG_END = 0, // mark the end of the flash script SWF_TAG_SHOW_FRAME = 1, // show the current frame SWF_TAG_DEFINE_SHAPE = 2, // define a vector based shape SWF_TAG_PLACE_OBJECT = 4, // place an object in the current frame SWF_TAG_REMOVE_OBJECT = 5, // remove specified object SWF_TAG_DEFINE_BITS = 6, // JPEG data bit stream SWF_TAG_DEFINE_BUTTON = 7, // define an action button SWF_TAG_JPEG_TABLES = 8, // define the JPEG tables SWF_TAG_SET_BACKGROUND_COLOR = 9, // define the RGB color for the background SWF_TAG_DEFINE_FONT = 10, // links a list of shapes to characters SWF_TAG_DEFINE_TEXT = 11, // define a text to be printed with a font SWF_TAG_DO_ACTION = 12, // action to perform in this frame SWF_TAG_DEFINE_FONT_INFO = 13, // font metrics // V2.0 SWF_TAG_DEFINE_SOUND = 14, // define how a sound effect will be played SWF_TAG_START_SOUND = 15, // start playing a sound effect SWF_TAG_DEFINE_BUTTON_SOUND = 17, // sound effects attached to a button SWF_TAG_SOUND_STREAM_HEAD = 18, // define how a sound effect will be loaded & played SWF_TAG_SOUND_STREAM_BLOCK = 19,// actual sound samples to play (embedded with the rest) SWF_TAG_DEFINE_BITS_LOSSLESS = 20, // a loss less compressed image SWF_TAG_DEFINE_BITS_JPEG2 = 21, // a complete JPEG definition SWF_TAG_DEFINE_SHAPE2 = 22, // define a shape including large number of styles SWF_TAG_DEFINE_BUTTON_COLOR_TRANSFORM = 23, // how a button changes color SWF_TAG_PROTECT = 24, // whether the resulting file is protected against editing // V3.0 SWF_TAG_PLACE_OBJECT2 = 26, // extended place SWF_TAG_REMOVE_OBJECT2 = 28, // simplified remove SWF_TAG_DEFINE_SHAPE3 = 32, // define a shape including RGBA colors SWF_TAG_DEFINE_TEXT2 = 33, // define a text to draw including RGBA colors SWF_TAG_DEFINE_BUTTON2 = 34, // define an action button with RGBA colors and color transformation SWF_TAG_DEFINE_BITS_JPEG3 = 35, // define two JPEG images, one RGB and one GREY used as the alpha channel SWF_TAG_DEFINE_BITS_LOSSLESS2 = 36, // define a loss less image with an alpha channel SWF_TAG_DEFINE_SPRITE = 39, // define a movie as an object to play in another movie SWF_TAG_FRAME_LABEL = 43, // name a place holder in the movie SWF_TAG_SOUND_STREAM_HEAD2 = 45,// define a sound effect with more details for embedded playing SWF_TAG_DEFINE_MORPH_SHAPE = 46,// define a shape which can easilly be changed with a position SWF_TAG_DEFINE_FONT2 = 48, // define a set of fonts SWF_TAG_DEFINE_INFO = 49, // define a comment about the generator, etc. // V4.0 SWF_TAG_TEXT_FIELD = 37, // define an area with text which can be edited // V5.0 SWF_TAG_EXPORT = 56, // export a set of definitions to other files SWF_TAG_IMPORT = 57, // look for definitions from another file SWF_TAG_PROTECT_DEBUG = 58, // a password to protect debugging of flash movies -- use only in V5.x movies // V6.0 SWF_TAG_DO_INIT_ACTION = 59, // action to perform once on specified sprite in this frame SWF_TAG_DEFINE_FONT_INFO2 = 62, // font metrics including language reference SWF_TAG_PROTECT_DEBUG2 = 64, // a password to protect debugging of flash movies // V7.0 SWF_TAG_SCRIPT_LIMITS = 65, // the recursive depth and script timeout parameters SWF_TAG_SET_TAB_INDEX = 66, // the depth of an object to be set at the given index (next/previous Tab key positioning) // V8.0 SWF_TAG_PLACE_OBJECT3 = 70, // place an object with blend mode, filters, bitmap caching SWF_TAG_max // just end this list really }; typedef long swf_type_t; #define SWF_TYPE_DEFINE 0x00000001 // a definition tag, must be in the main movie #define SWF_TYPE_CONTROL 0x00000002 // a control tag, can be in sprites as well #define SWF_TYPE_UNIQUE 0x00000004 // a unique tag, can't be duplicated in the movie (merge if possible) #define SWF_TYPE_START 0x00000008 // if present, put it near the start of the movie #define SWF_TYPE_ONE 0x00000010 // (should) use at most one per frame #define SWF_TYPE_REFERENCE 0x00000020 // object includes references to other objects #define SWF_TYPE_HAS_ID 0x00000040 // this object was derived from TagBaseID and has an ID #define SWF_TYPE_SCRIPT 0x20000000 // object can accept action scripts #define SWF_TYPE_SPRITE 0x40000000 // this is a sprite (can include other tags) #define SWF_TYPE_HEADER 0x80000000 // the header virtual ~TagBase(); virtual int Save(Data& data) = 0; // print out a tag in a Data buffer int SaveString(Data& data, const char *string); static int SaveTag(Data& data, swf_tag_t tag, size_t size); static long SIBitSize(long value); // return the number of bits necessary to represent a signed integer static long UIBitSize(unsigned long value); // return the number of bits necessary to represent an unsigned integer static long Double2Signed(double value); // return a valid fixed value 16.16 bits from a double static double Signed2Double(long value); // return a valid double from a fixed value 16.16 bits virtual void MinimumVersion(unsigned char version); virtual unsigned char Version(void) const; virtual swf_type_t TypeFlags(void) const = 0; const char * Name(void) const; // return the name (type) of this tag const char * Label(void) const; void ResetFrames(void); void ShowFrame(void); sswf_frame_t FrameCount(void) const; sswf_frame_t WhichFrame(void) const; void SetLabel(const char *label); TagBase * FindLabelledTag(const char *label) const; TagBase * FindTagWithID(sswf_id_t id, bool search_import = true) const; TagBase * Children(void); TagBase * Next(void); TagBase * Previous(void); TagBase * Parent(void); TagHeader * Header(void) const; void * f_userdata; // anything you feel necessary! protected: // only sub-classes can create a TagBase TagBase(const char *name, TagBase *parent); virtual int PreSave(void); // called by the header Save() function virtual int PreSave2ndPass(void); // called by the header Save() function after all the PreSave() were called private: TagBase * FindLabel(const TagBase *p, const char *label) const; TagBase * FindID(const TagBase *p, sswf_id_t id, bool search_import) const; const char * f_name; char * f_label; TagBase * f_parent; TagBase * f_next; TagBase * f_previous; TagBase * f_children; sswf_frame_t f_frames; // total number of frames }; /********************* TAGS WITHOUT IDs (possibly references though) ****/ class TagHeader : public TagBase { public: TagHeader(void); virtual ~TagHeader(); virtual int Save(Data& data); int SaveEncodedString(Data& data, const char *string); virtual swf_type_t TypeFlags(void) const; sswf_id_t NextID(void); void RemoveID(sswf_id_t id); /////////////// SETUP FUNCTIONS virtual void MinimumVersion(unsigned char version); virtual unsigned char Version(void) const; void SetVersion(unsigned char version); int DefineMinimumVersion(void); void SetAutoOrder(bool auto_order = true); void SetCompress(bool compress = true); void SetFrame(const SRectangle& rect); const SRectangle& Frame(void) const; void SetOutputEncoding(const char *encoding); void SetRate(float rate); float Rate(void) const; private: // NOTE: use 0 to get a default version (a version computed from the options used) unsigned char f_version; // file version (0 to 7 at time of writing) unsigned char f_min_version; // once the whole file was saved, this is the minimum version we need to use SRectangle f_frame; // the frame rectangle float f_rate; // frames per second (8.8 fixed number in file) bool f_compress; // compress the resulting movie (v6.x upward) bool f_auto_order; // automatically order definition tags (discard unused definitions also) sswf_id_t f_next_id; // returned and then increased when NextID() is called char * f_output_encoding; // encoding used prior V6.x SWF files bool f_iconvertor_open; // whether the f_iconvertor is a valid descriptor iconv_t f_iconvertor; // to convert strings from U18N to user specified encoding #if DEBUG bool f_saving; // if true the f_min_version can't be changed ever anymore #endif }; // Actions: // // Whenever you want to create an action, you simply // create a new Action object with the proper type // unless you need to use an action which requires // some additional data. The actions which require // additional data are listed here: // // Action Name Data // // ActionBranch label // ActionCallFrame // ActionDictionary strings // ActionFunction name, registers, parameters, body (actions) // ActionGoto frame name, play flag // ActionLabel label (generates no output code) // ActionPushData strings, floats, doubles, etc. // ActionSetTarget target name // ActionStoreRegister register number // ActionTry try, catch and finally actions and identifier/register // ActionURL url, target and method // ActionWaitForFrame frame name, actions // ActionWith actions to execute with the specified object class ActionLabel; class Action : public ItemBase { public: enum action_t { ACTION_UNKNOWN = -1, /* unknown action (invalid) */ ACTION_LABEL = -2, /* used to mark a position within the actions */ ACTION_min = 0x00, /* the minimum action number */ /* all the valid Flash actions */ ACTION_END = 0x00, /* this is automatically added by the higher level Save()'s */ ACTION_NEXT_FRAME = 0x04, ACTION_PREVIOUS_FRAME = 0x05, ACTION_PLAY = 0x06, ACTION_STOP = 0x07, ACTION_TOGGLE_QUALITY = 0x08, ACTION_STOP_SOUND = 0x09, ACTION_ADD = 0x0A, ACTION_SUBSTRACT = 0x0B, /* this is the wrong spelling */ ACTION_SUBTRACT = 0x0B, ACTION_MULTIPLY = 0x0C, ACTION_DIVIDE = 0x0D, ACTION_EQUAL = 0x0E, ACTION_LESS_THAN = 0x0F, ACTION_LOGICAL_AND = 0x10, ACTION_LOGICAL_OR = 0x11, ACTION_LOGICAL_NOT = 0x12, ACTION_STRING_EQUAL = 0x13, ACTION_STRING_LENGTH = 0x14, ACTION_SUB_STRING = 0x15, ACTION_POP = 0x17, ACTION_INTEGRAL_PART = 0x18, ACTION_GET_VARIABLE = 0x1C, ACTION_SET_VARIABLE = 0x1D, ACTION_SET_TARGET2 = 0x20, ACTION_CONCATENATE = 0x21, ACTION_GET_PROPERTY = 0x22, ACTION_SET_PROPERTY = 0x23, ACTION_DUPLICATE_SPRITE = 0x24, ACTION_REMOVE_SPRITE = 0x25, ACTION_TRACE = 0x26, ACTION_START_DRAG = 0x27, ACTION_STOP_DRAG = 0x28, ACTION_STRING_LESS_THAN = 0x29, ACTION_THROW = 0x2A, ACTION_CAST_OBJECT = 0x2B, ACTION_IMPLEMENTS = 0x2C, ACTION_FSCOMMAND2 = 0x2D, ACTION_RANDOM = 0x30, ACTION_MBSTRING_LENGTH = 0x31, ACTION_ORD = 0x32, ACTION_CHR = 0x33, ACTION_GET_TIMER = 0x34, ACTION_SUB_MBSTRING = 0x35, ACTION_MBORD = 0x36, ACTION_MBCHR = 0x37, ACTION_DELETE = 0x3A, ACTION_SET_LOCAL_VAR = 0x3C, ACTION_SET_LOCAL_VARIABLE = 0x3C, ACTION_CALL_FUNCTION = 0x3D, ACTION_RETURN = 0x3E, ACTION_MODULO = 0x3F, ACTION_NEW = 0x40, ACTION_DECLARE_LOCAL_VAR = 0x41, ACTION_DECLARE_LOCAL_VARIABLE = 0x41, ACTION_DECLARE_ARRAY = 0x42, ACTION_DECLARE_OBJECT = 0x43, ACTION_TYPE_OF = 0x44, ACTION_GET_TARGET = 0x45, ACTION_ENUMERATE = 0x46, ACTION_ADD_TYPED = 0x47, ACTION_LESS_THAN_TYPED = 0x48, ACTION_EQUAL_TYPED = 0x49, ACTION_NUMBER = 0x4A, ACTION_STRING = 0x4B, ACTION_DUPLICATE = 0x4C, ACTION_SWAP = 0x4D, ACTION_GET_MEMBER = 0x4E, ACTION_SET_MEMBER = 0x4F, ACTION_INCREMENT = 0x50, ACTION_DECREMENT = 0x51, ACTION_CALL_METHOD = 0x52, ACTION_NEW_METHOD = 0x53, ACTION_INSTANCE_OF = 0x54, ACTION_ENUMERATE_OBJECT = 0x55, ACTION_AND = 0x60, ACTION_OR = 0x61, ACTION_XOR = 0x62, ACTION_SHIFT_LEFT = 0x63, ACTION_SHIFT_RIGHT = 0x64, ACTION_SHIFT_RIGHT_UNSIGNED = 0x65, ACTION_STRICT_EQUAL = 0x66, ACTION_GREATER_THAN_TYPED = 0x67, ACTION_STRING_GREATER_THAN = 0x68, ACTION_EXTENDS = 0x69, ACTION_GOTO_FRAME = 0x81, ACTION_URL = 0x83, ACTION_STORE_REGISTER = 0x87, ACTION_DECLARE_DICTIONARY = 0x88, ACTION_STRICT_MODE = 0x89, ACTION_WAIT_FOR_FRAME = 0x8A, ACTION_SET_TARGET = 0x8B, ACTION_GOTO_LABEL = 0x8C, ACTION_WAIT_FOR_FRAME2 = 0x8D, ACTION_DECLARE_FUNCTION2 = 0x8E, ACTION_TRY = 0x8F, ACTION_WITH = 0x94, ACTION_PUSH_DATA = 0x96, ACTION_BRANCH_ALWAYS = 0x99, ACTION_URL2 = 0x9A, ACTION_DECLARE_FUNCTION = 0x9B, ACTION_BRANCH_IF_TRUE = 0x9D, ACTION_CALL_FRAME = 0x9E, ACTION_GOTO_EXPRESSION = 0x9F, ACTION_max = 0xFF /* the maximum action number */ }; Action(TagBase *tag, action_t action); virtual ~Action() {} virtual Action * Duplicate(void) const; unsigned long Offset(void) const { return f_offset; } virtual unsigned char Version(void) const { return f_min_version; } void Save(Data& data); virtual Vectors * SubList(void); static int SaveList(TagBase *parent, const Vectors *list, Data& data, const Vectors *extra = 0); static int MinimumListVersion(const Vectors& list); static int GetMaximumRegister(const Vectors& list); static ActionLabel * FindLabel(const Vectors& list, const char *label); protected: virtual void SaveData(Data& data, Data& nested_data); virtual void Save2ndPass(const Vectors& list, Data& data); virtual int GetMaxRegister(void) const { return 0; } int SaveString(Data& data, const char *string); TagBase * Tag(void) const { return const_cast (f_tag); } const action_t f_action; unsigned long f_offset; /* offset where this tag is being saved (saved for branches and with statments) */ unsigned long f_index; /* this action index in the list of actions */ private: #if DEBUG /* * Forbid copies (only in DEBUG mode so we don't have extra functions * for nothing otherwise) If you need a copy, use the Duplicate() instead */ Action(const Action& action); Action& operator = (const Action& action); #endif TagBase * f_tag; unsigned char f_min_version; /* minimum version to use this action */ }; class ActionBranch : public Action, public MemoryManager { public: /* one of: * ACTION_BRANCH_ALWAYS * ACTION_BRANCH_IF_TRUE */ ActionBranch(TagBase *tag, action_t action = ACTION_BRANCH_ALWAYS); void SetLabel(const char *label); private: virtual Action * Duplicate(void) const; virtual void SaveData(Data& data, Data& nested_data); virtual void Save2ndPass(const Vectors& list, Data& data); char * f_label; }; class ActionCallFrame : public Action, public MemoryManager { public: ActionCallFrame(TagBase *tag); private: virtual void SaveData(Data& data, Data& nested_data); }; class ActionDictionary : public Action, public MemoryManager { public: ActionDictionary(TagBase *tag); void AddString(const char *string); private: struct string_t : public ItemBase { char * f_string; }; virtual Action * Duplicate(void) const; virtual void SaveData(Data& data, Data& nested_data); Vectors f_strings; }; class ActionFunction : public Action, public MemoryManager { public: /* one of: * ACTION_DECLARE_FUNCTION * ACTION_DECLARE_FUNCTION2 */ enum action_function_t { ACTION_FUNCTION_LOAD_THIS = 0x0001, ACTION_FUNCTION_SUPPRESS_THIS = 0x0002, ACTION_FUNCTION_LOAD_ARGUMENTS = 0x0004, ACTION_FUNCTION_SUPPRESS_ARGUMENTS = 0x0008, ACTION_FUNCTION_LOAD_SUPER = 0x0010, ACTION_FUNCTION_SUPPRESS_SUPER = 0x0020, ACTION_FUNCTION_LOAD_ROOT = 0x0040, ACTION_FUNCTION_LOAD_PARENT = 0x0080, ACTION_FUNCTION_LOAD_GLOBAL = 0x0100 }; ActionFunction(TagBase *tag, action_t action = ACTION_DECLARE_FUNCTION); void SetName(const char *name); void SetRegistersCount(unsigned int count); void AddParameter(const char *name, int register_number = -1); void AddAction(Action *action); virtual Vectors * SubList(void); // flags for the ASSetPropFlags(obj, props, flags [, allow]) // (see include/sswf/scripts/global/extensions.asc) enum { PROP_FLAG_IS_HIDDEN = 1, PROP_FLAG_CAN_DELETE = 2, PROP_FLAG_CAN_OVERWRITE = 4 }; private: struct parameter_t : public ItemBase { char * f_name; int f_register_number; // if -1, use the name, if 0, auto-assign }; virtual Action * Duplicate(void) const; virtual void SaveData(Data& data, Data& nested_data); char * f_name; unsigned int f_registers_count; unsigned short f_flags; Vectors f_parameters; Vectors f_actions; }; class ActionGoto : public Action, public MemoryManager { public: /* one of: * ACTION_GOTO_FRAME * ACTION_GOTO_LABEL * ACTION_GOTO_EXPRESSION */ ActionGoto(TagBase *tag, action_t action = ACTION_GOTO_FRAME); void SetFrameName(const char *frame_name); void SetPlay(bool play) { f_play = play; } private: virtual Action * Duplicate(void) const; virtual void SaveData(Data& data, Data& nested_data); char * f_frame_name; bool f_play; }; class ActionLabel : public Action, public MemoryManager { public: ActionLabel(TagBase *tag); void SetLabel(const char *label); const char * GetLabel(void) const { return f_label; } private: virtual Action * Duplicate(void) const; // we shall never even try to save a label! so no SaveData() is necessary char * f_label; }; class ActionPushData : public Action, public MemoryManager { public: enum action_immediate_type_t { ACTION_IMMEDIATE_TYPE_UNKNOWN = -1, ACTION_IMMEDIATE_TYPE_STRING = 0x00, ACTION_IMMEDIATE_TYPE_FLOAT = 0x01, ACTION_IMMEDIATE_TYPE_NULL = 0x02, ACTION_IMMEDIATE_TYPE_UNDEFINED = 0x03, ACTION_IMMEDIATE_TYPE_REGISTER = 0x04, ACTION_IMMEDIATE_TYPE_BOOLEAN = 0x05, ACTION_IMMEDIATE_TYPE_DOUBLE = 0x06, ACTION_IMMEDIATE_TYPE_INTEGER = 0x07, ACTION_IMMEDIATE_TYPE_LOOKUP = 0x08, ACTION_IMMEDIATE_TYPE_LOOKUP_LARGE = 0x09 }; struct action_immediate_t : public ItemBase { action_immediate_type_t f_type; union { char * f_string; float f_float32; double f_float64; bool f_boolean; long f_integer32; unsigned short f_lookup; unsigned char f_register; } f_data; action_immediate_t(action_immediate_type_t type) { f_type = type; memset(&f_data, 0, sizeof(f_data)); } }; ActionPushData(TagBase *tag); void AddEmptyString(void) { AddString(0); } void AddString(const char *string); void AddTrue(void) { AddBoolean(true); } void AddFalse(void) { AddBoolean(false); } void AddBoolean(bool value); void AddInteger(long value); void AddFloat(float value); void AddDouble(double value); void AddNull(void); void AddLookup(unsigned short index); void AddRegister(unsigned char reg_index); void AddUndefined(void); private: virtual Action * Duplicate(void) const; virtual void SaveData(Data& data, Data& nested_data); virtual int GetMaxRegister(void) const; Vectors f_data; }; class ActionSetTarget : public Action, public MemoryManager { public: ActionSetTarget(TagBase *tag); void SetTarget(const char *target); private: virtual Action * Duplicate(void) const; virtual void SaveData(Data& data, Data& nested_data); char * f_target; }; class ActionStoreRegister : public Action, public MemoryManager { public: ActionStoreRegister(TagBase *tag); void SetRegister(unsigned char reg); private: virtual Action * Duplicate(void) const; virtual void SaveData(Data& data, Data& nested_data); virtual int GetMaxRegister(void) const; unsigned char f_reg; }; class ActionStrictMode : public Action, public MemoryManager { public: ActionStrictMode(TagBase *tag); void SetStrict(bool strict); private: virtual Action * Duplicate(void) const; virtual void SaveData(Data& data, Data& nested_data); bool f_strict; }; class ActionTry : public Action, public MemoryManager { public: ActionTry(TagBase *tag); void AddTryAction(Action *action); void AddCatchAction(Action *action); void AddFinallyAction(Action *action); void SetIdentifier(int register_number); // Catch(#) void SetIdentifier(const char *variable_name); // Catch(var) void StartCatch(void); void StartFinally(void); Vectors * SubListTry(void); Vectors * SubListCatch(void); Vectors * SubListFinally(void); private: virtual Action * Duplicate(void) const; virtual void SaveData(Data& data, Data& nested_data); virtual unsigned char Version(void) const; int f_register; char * f_variable_name; bool f_has_catch; bool f_has_finally; Vectors f_actions_try; Vectors f_actions_catch; Vectors f_actions_finally; }; class ActionURL : public Action, public MemoryManager { public: /* one of: * ACTION_URL * ACTION_URL2 */ enum url_method_t { URL_METHOD_UNDEFINED = -1, URL_METHOD_NOVARIABLE = 0, URL_METHOD_NOVARIABLES = URL_METHOD_NOVARIABLE, URL_METHOD_GET = 1, URL_METHOD_POST = 2 }; ActionURL(TagBase *tag, action_t action = ACTION_URL); void SetURL(const char *url, const char *target); void SetMethod(url_method_t method); private: virtual Action * Duplicate(void) const; virtual void SaveData(Data& data, Data& nested_data); char * f_url; char * f_target; url_method_t f_method; }; class ActionWaitForFrame : public Action, public MemoryManager { public: /* one of: * ACTION_WAIT_FOR_FRAME * ACTION_WAIT_FOR_FRAME2 */ ActionWaitForFrame(TagBase *tag, action_t action = ACTION_WAIT_FOR_FRAME); void SetFrameName(const char *name); void AddAction(Action *action); virtual Vectors * SubList(void); private: virtual Action * Duplicate(void) const; virtual void SaveData(Data& data, Data& nested_data); Vectors f_actions; // actions executed once frame is loaded char * f_frame_name; }; class ActionWith : public Action, public MemoryManager { public: ActionWith(TagBase *tag); void AddAction(Action *action); virtual Vectors * SubList(void); private: virtual Action * Duplicate(void) const; virtual void SaveData(Data& data, Data& nested_data); Vectors f_actions; }; class TagDoAction : public TagBase { public: /* one of: * SWF_TAG_DO_ACTION * SWF_TAG_DO_INIT_ACTION (uses this when sprite ID was defined) */ TagDoAction(TagBase *parent); virtual int Save(Data& data); virtual swf_type_t TypeFlags(void) const; /////////////// SETUP FUNCTIONS static int SaveList(const Vectors& list, Data& data); void SetAction(const Action& action); void SetSprite(sswf_id_t sprite); Vectors& Actions(void) { return f_actions; } private: virtual int PreSave(void); // called by the header Save() function sswf_id_t f_sprite; Vectors f_actions; }; class TagPlace : public TagBase { public: /* will generate one of the SWF_TAG_PLACE_OBJECT[2/3] */ enum blend_mode_t { BLEND_MODE_UNDEFINED = -1, BLEND_MODE_NORMAL = 1, BLEND_MODE_LAYER = 2, BLEND_MODE_MULTIPLY = 3, BLEND_MODE_SCREEN = 4, BLEND_MODE_LIGHTEN = 5, BLEND_MODE_DARKEN = 6, BLEND_MODE_DIFFERENCE = 7, BLEND_MODE_ADD = 8, BLEND_MODE_SUBTRACT = 9, BLEND_MODE_INVERT = 10, BLEND_MODE_ALPHA = 11, BLEND_MODE_ERASE = 12, BLEND_MODE_OVERLAY = 13, BLEND_MODE_HARDLIGHT = 14 }; TagPlace(TagBase *parent); virtual int Save(Data& data); virtual swf_type_t TypeFlags(void) const; /////////////// SETUP FUNCTIONS void SetObjectID(sswf_id_t id); void SetDepth(int depth); void SetClip(int depth); void SetMatrix(const Matrix& matrix); void SetColorTransform(const ColorTransform& color_transform); void SetName(const char *name); void SetMorphPosition(int position); void SetBlendMode(blend_mode_t blend_mode); blend_mode_t SetBlendModeName(const char *blend_mode_name); void SetBitmapCaching(int bitmap_caching); void Replace(void); void Place(void); void AddEvent(Event *event); private: virtual int PreSave(void); // called by the header Save() function bool f_id_defined; sswf_id_t f_id; int f_replace; int f_depth; int f_clip_depth; char * f_name; unsigned long f_events_all_flags; int f_position; // morph position blend_mode_t f_blend_mode; int f_bitmap_caching; bool f_has_matrix; Matrix f_matrix; ColorTransform f_color_transform; Vectors f_events; }; class TagRemove : public TagBase { public: TagRemove(TagBase *parent); virtual int Save(Data& data); virtual swf_type_t TypeFlags(void) const; /////////////// SETUP FUNCTIONS void SetDepth(int depth) { f_depth = depth; } void SetObjectID(sswf_id_t id) { f_id = id; } private: virtual int PreSave(void); // called by the header Save() function int f_depth; sswf_id_t f_id; }; class TagScriptLimits : public TagBase { public: TagScriptLimits(TagBase *parent); virtual int Save(Data& data); virtual swf_type_t TypeFlags(void) const; /////////////// SETUP FUNCTIONS void SetMaxRecursionDepth(int depth); void SetTimeoutSeconds(int timeout); int GetMaxRecursionDepth(void) const; int GetTimeoutSeconds(void) const; private: virtual int PreSave(void); int f_depth; int f_timeout; }; class TagSetTabIndex : public TagBase { public: TagSetTabIndex(TagBase *parent); virtual int Save(Data& data); virtual swf_type_t TypeFlags(void) const; /////////////// SETUP FUNCTIONS void SetDepth(int depth); void SetIndex(int timeout); int GetDepth(void) const; int GetIndex(void) const; private: virtual int PreSave(void); int f_depth; int f_index; }; class TagSetBackgroundColor : public TagBase { public: TagSetBackgroundColor(TagBase *parent); virtual int Save(Data& data); virtual swf_type_t TypeFlags(void) const; /////////////// SETUP FUNCTIONS void SetColor(Color& color); Color& GetColor(void); private: Color f_color; }; class TagShowFrame : public TagBase { public: TagShowFrame(TagBase *parent); virtual int Save(Data& data); virtual swf_type_t TypeFlags(void) const; }; class TagEnd : public TagBase { public: TagEnd(TagBase *parent); virtual int Save(Data& data); virtual swf_type_t TypeFlags(void) const; }; class TagFrameLabel : public TagBase { public: TagFrameLabel(TagBase *parent); virtual int Save(Data& data); virtual swf_type_t TypeFlags(void) const; /////////////// SETUP FUNCTIONS void SetFrameLabel(const char *label); private: virtual int PreSave(void); char * f_label; }; class TagExport : public TagBase { public: TagExport(TagBase *parent); virtual int Save(Data& data); virtual swf_type_t TypeFlags(void) const; /////////////// SETUP FUNCTIONS void SetObject(sswf_id_t id, const char *name); private: struct export_t : public ItemBase { sswf_id_t f_id; const char * f_name; }; virtual int PreSave(void); Vectors f_objects; }; class TagImport : public TagBase { public: TagImport(TagBase *parent); virtual int Save(Data& data); virtual swf_type_t TypeFlags(void) const; const char * HasID(sswf_id_t id) const; sswf_id_t HasName(const char *name) const; /////////////// SETUP FUNCTIONS void SetURL(const char *url); void SetFilename(const char *filename); void AddName(const char *name, const char *type); private: struct import_t : public ItemBase { sswf_id_t f_id; // dynamically allocated const char * f_name; // external symbol name const char * f_type; // user specified type }; virtual int PreSave(void); char * f_url; char * f_filename; Vectors f_objects; }; class TagProtect : public TagBase { public: /* one of: * SWF_TAG_PROTECT * SWF_TAG_PROTECT_DEBUG * SWF_TAG_PROTECT_DEBUG2 */ TagProtect(TagBase *parent, swf_tag_t tag = SWF_TAG_PROTECT); virtual int Save(Data& data); virtual swf_type_t TypeFlags(void) const; /////////////// SETUP FUNCTIONS void SetPassword(const char *password); void SetEncodedPassword(const char *password); private: virtual int PreSave(void); swf_tag_t f_tag; char * f_password; }; class TagInfo : public TagBase { public: TagInfo(TagBase *parent); virtual int Save(Data& data); virtual swf_type_t TypeFlags(void) const; /////////////// SETUP FUNCTIONS void SetInfo(const char *info); void SetVersion(long version); private: virtual int PreSave(void); char * f_info; long f_version; }; class TagStartSound : public TagBase { public: TagStartSound(TagBase *parent); virtual int Save(Data& data); virtual swf_type_t TypeFlags(void) const; void SetInfo(SoundInfo *sound_info); private: virtual int PreSave(void); SoundInfo * f_sound_info; }; /****************************************/ /****************************************/ /********************* TAGS WITH IDs ****/ /****************************************/ /****************************************/ class TagBaseID : public TagBase { public: TagBaseID(const char *name, TagBase *parent); virtual sswf_id_t Identification(void) const; void NoIdentification(void); int SaveID(Data& data) const; private: sswf_id_t f_id; bool f_identified; }; class TagButton : public TagBaseID { public: TagButton(TagBase *parent); virtual int Save(Data& data); virtual swf_type_t TypeFlags(void) const; /////////////// SETUP FUNCTIONS void SetState(const State& state); void SetAction(const Action& action); void SetMenu(bool menu = true); Vectors& Actions(void); void AddEvent(Event *event); private: virtual int PreSave(void); // called by the header Save() function bool f_save_button2; bool f_menu; // whether to track as a menu Vectors f_states; Vectors f_actions; Vectors f_events; }; class TagShape; class TagFont : public TagBaseID { public: enum font_type_t { FONT_TYPE_BEST = 0, // create the best possible result FONT_TYPE_ASCII, FONT_TYPE_UNICODE, FONT_TYPE_SHIFTJIS, }; enum font_language_t { FONT_LANGUAGE_UNKNOWN = -1, FONT_LANGUAGE_LOCALE = 0, FONT_LANGUAGE_LATIN = 1, FONT_LANGUAGE_JAPANESE = 2, FONT_LANGUAGE_KOREAN = 3, FONT_LANGUAGE_SIMPLIFIED_CHINESE = 4, FONT_LANGUAGE_TRADITIONAL_CHINESE = 5, FONT_LANGUAGE_max = 6 }; #define SSWF_FONT_SPACE_INDEX static_cast (-1) struct font_info_t { sswf_ucs4_t f_glyph; // the glyph name ('A', 'B', ...) unsigned short f_saved_index; // index in the SWF file (within the referenced glyphs) unsigned long f_index; // index in the memory array (of all glyphs) unsigned long f_position; // closest position or exact position in the list of glyphs long f_advance; // the advance in TWIPs bool f_is_empty; // if true, it's like a space (i.e. invisible) }; TagFont(TagBase *parent); virtual int Save(Data& data); virtual swf_type_t TypeFlags(void) const; void GlyphInfo(font_info_t& info) const; bool HasGlyph(void) const; bool FindGlyph(font_info_t& info, bool mark_empty_in_use = false) const; const char * FontName(void) const; long DefaultAscent(void) const; long DefaultDescent(void) const; long DefaultLeadingHeight(void) const; static font_language_t StringToLanguage(const char *language); static const char * LanguageToString(font_language_t language); /////////////// SETUP FUNCTIONS // WARNING: shape referenced as kept as points (the shape isn't copied in any way) // so you have to make sure that these shapes still exist at the time the Save() // is called. void AddGlyph(sswf_ucs4_t name, const TagBase *ref, long advance = LONG_MIN); void SetName(const char *font_name); void SetLayout(long ascent, long descent, long leading_height); void SetDefaultAdvance(long advance); void SetSpaceAdvance(long advance); void SetType(font_type_t type); void SetLanguage(font_language_t language); void SetBold(bool bold); void SetItalic(bool italic); void SetWide(bool wide); int SetUsedGlyphs(const sswf_ucs4_t *used_glyphs, bool mark_empty_in_use = false); void SetUsedByEditText(bool used = true); void AddKern(sswf_ucs4_t code0, sswf_ucs4_t code1, long advance); private: struct font_glyph_t : public ItemBase { sswf_ucs4_t f_name; /* "A", "B", "0", "1", etc. */ unsigned short f_index; /* index of this item when saved in the output file */ const TagShape *f_shape; /* the shape used for this glyph */ long f_advance; /* the number of TWIPs to advance */ bool f_in_use; /* if true this glyph was referenced at least once */ }; struct font_kern_t : public ItemBase { sswf_ucs4_t f_code[2]; long f_advance; }; virtual int PreSave(void); virtual int PreSave2ndPass(void); static const char * f_font_language_name[FONT_LANGUAGE_max]; char * f_font_name; font_language_t f_language; // v6.x language definition font_type_t f_type; // unused in v6.x bool f_bold; bool f_italic; bool f_wide; bool f_has_wide_char; // defined in PreSave2ndPass() bool f_has_wide_offsets; // defined in PreSave2ndPass() bool f_has_layout; // defined in PreSave2ndPass() bool f_used_by_edit_text; // reset in PreSave() used in PreSave2ndPass() bool f_define_font2; // defined in PreSave2ndPass() long f_ascent; long f_descent; long f_leading_height; long f_default_advance; long f_space_advance; long f_offsets_max; // size of the current f_offsets buffer unsigned long * f_offsets; // this is a list of unsigned shorts if f_has_wide_offset if false -- defined in PreSave2ndPass() unsigned long f_count; // the number of glyphs saved (defined in PreSave2ndPass()) Data f_save_glyphs; // defined in PreSave2ndPass() Vectors f_glyphs; Vectors f_kerns; }; class TagEditText : public TagBaseID { public: enum edit_text_alignment_t { EDIT_TEXT_ALIGNMENT_LEFT = 0, EDIT_TEXT_ALIGNMENT_RIGHT = 1, EDIT_TEXT_ALIGNMENT_CENTER = 2, EDIT_TEXT_ALIGNMENT_JUSTIFY = 3 }; TagEditText(TagBase *parent); virtual int Save(Data& data); virtual swf_type_t TypeFlags(void) const; /////////////// SETUP FUNCTIONS void SetText(const char *text); void SetVariableName(const char *name); void SetFont(const TagFont *font, long height); void SetMargins(long left, long right); void SetBounds(const SRectangle& bounds); void SetAlign(edit_text_alignment_t align); void SetIndent(long indent); void SetLeading(long leading); void SetColor(Color& color); void SetMaxLength(long length); void SetWordWrap(bool status = true); void SetMultiline(bool status = true); void SetPassword(bool status = true); void SetReadOnly(bool status = true); void SetNoSelect(bool status = true); void SetBorder(bool status = true); void SetOutline(bool status = true); void SetHTML(bool status = true); void SetAutoSize(bool status = true); void SetUsedGlyphs(const char *lists); void AddUsedString(const char *string); private: virtual int PreSave(void); SRectangle f_bounds; // where the string is drawn edit_text_alignment_t f_align; long f_left_margin; long f_right_margin; long f_indent; long f_leading; const TagFont * f_font; unsigned short f_font_height; long f_max_length; // maximum number of character, if <= 0 - undefined char * f_var_name; // required char * f_text; // if 0, no initialization text [SaveString() expects a UTF-8 so we keep it that way] sswf_ucs4_t * f_used_glyphs; // default to "*" if undefined sswf_ucs4_t * f_used_strings; // concatenation of used strings Color f_color; bool f_has_color; // if this is true then the user defined the color bool f_word_wrap; bool f_multiline; bool f_password; bool f_readonly; bool f_no_select; bool f_border; bool f_outline; bool f_html; bool f_autosize; }; class TagImage : public TagBaseID { public: enum image_format_t { IMAGE_FORMAT_UNKNOWN = 0, IMAGE_FORMAT_LOSSLESS_BEST, IMAGE_FORMAT_LOSSLESS_8, IMAGE_FORMAT_LOSSLESS_16, IMAGE_FORMAT_LOSSLESS_32, IMAGE_FORMAT_JPEG, IMAGE_FORMAT_max }; struct image_t { bool f_alpha; // whether the source had 4 components (depth = 20) long f_width; // size of the image in pixels long f_height; unsigned char * f_data; // data of the image }; TagImage(TagBase *parent); virtual int Save(Data& data); virtual swf_type_t TypeFlags(void) const; void GetImageData(image_t& image_data) { image_data = f_image; } /////////////// SETUP FUNCTIONS void SetFormat(image_format_t format) { f_format = format; } void SetQuality(int quality) { f_quality = quality; } int SetFilename(const char *image, const char *mask); void SetImage(long width, long height, unsigned char *data, bool alpha = false, long count = 0, unsigned char *colormap = 0); int LoadTGA(const char *filename, image_t& im); int LoadJPEG(const char *filename, image_t& im); int SaveJPEG(Data& encoding, Data& image); int SetAlpha(image_t& im, const image_t& mask); private: virtual int PreSave(void); image_format_t f_format; // one of the IMAGE_FORMAT_... image_t f_image; // the image int f_quality; // for JPEG, the quality level long f_count; // number of colors in the colormap unsigned char * f_colormap; // the colormap when it can be generated }; class TagShape : public TagBaseID { public: enum morph_t { MORPH_MODE_SHAPE0 = 0, MORPH_MODE_SHAPE1 = 1, MORPH_MODE_BOTH_SHAPES = 2 }; TagShape(TagBase *parent); virtual int Save(Data& data); virtual swf_type_t TypeFlags(void) const; int SaveWithoutStyles(Data& data); bool HasBounds(void) const { return !f_bounds[0].IsEmpty() || !f_bounds[1].IsEmpty(); } const SRectangle& Bounds(int index) const { assert(index == 0 || index == 1, "invalid index to query bounds"); return f_bounds[index]; } bool IsGlyph(void) const; bool IsEmpty(void) const; /////////////// SETUP FUNCTIONS void AddMove(morph_t morph_mode, long x, long y); void AddEdge(morph_t morph_mode, long x, long y) { Edges::edge_t edge(x, y); AddEdge(morph_mode, edge); } void AddEdge(morph_t morph_mode, long x, long y, long ctrl_x, long ctrl_y) { Edges::edge_t edge(x, y, ctrl_x, ctrl_y); AddEdge(morph_mode, edge); }; void AddEdge(morph_t morph_mode, const Edges::edge_t& edge); void NewStyles(void); void AddStyle(const Style& style, int fill = 0); void SetBounds(int index, const SRectangle& rect, bool show = false); void ShowBounds(bool show = true) { f_show_bounds = show; } void ShowOrigin(bool show = true) { f_show_origin = show; } void Glyph(void); private: enum what_t { SHAPE_EDGES, SHAPE_SETUP }; struct shape_what_t : public ItemBase { what_t f_what; shape_what_t(what_t what) { f_what = what; } }; struct shape_edges_t : public shape_what_t { Edges f_edges; shape_edges_t(what_t what) : shape_what_t(what) {} }; struct shape_setup_t : public shape_what_t { int f_fill_ref[2]; int f_line_ref; long f_x; long f_y; shape_setup_t(what_t what, bool origin = false) : shape_what_t(what) { f_fill_ref[0] = f_fill_ref[1] = f_line_ref = -1; if(origin) { f_x = f_y = 0; } else { f_x = f_y = LONG_MIN; } } }; struct shape_record_t : public ItemBase { // used to save in f_shapes Vectors * f_fill_styles; Vectors * f_line_styles; Vectors * f_record; }; struct save_info_t { shape_record_t f_sr; bool f_save_alpha; bool f_ext_size; bool f_first; bool f_save_styles; Data f_data; // we save it all here (we need to have the size before to create the tag data) int f_fill_bits_count; int f_line_bits_count; }; void RecordEdges(void); void RecordSetup(void); void NewEdges(void); void NewSetup(void); void SetMorph(void); // save sub-functions int SaveShape(save_info_t& info, shape_setup_t& last_setup); int SaveMorph(Data& data); int SaveSetup(save_info_t& info, const shape_setup_t& setup, shape_setup_t& last); int SaveStyles(save_info_t& info); int SaveStylesCount(save_info_t& info, long count); unsigned char f_version; // the minimum version necessary to save this shape (determines the tag) bool f_morph; // this is a morph shape bool f_is_glyph; // used only as a glyph (font character) bool f_show_bounds; // draw the bounding rectangle around the shape bool f_show_origin; // draw lines showing the origin SRectangle f_bounds[2]; // where the shape is drawn Vectors f_shapes; // each shape saved here has its own set of fill & line style shape_edges_t * f_edges; // if not NULL that's the current Edges to fill shape_edges_t * f_morph_edges; // if not NULL that's the current Edges to fill the morph (2nd shape) shape_setup_t * f_setup; // if not NULL that's the current Setup to define Vectors f_fill_styles; Vectors f_line_styles; Vectors f_record; // the current shape being built Vectors f_morph_record; // the current morph shape being built }; class TagSound : public TagBaseID { public: enum sound_format_t { SOUND_FORMAT_UNKNOWN = -1, SOUND_FORMAT_RAW = 0, SOUND_FORMAT_ADPCM = 1, SOUND_FORMAT_MP3 = 2, SOUND_FORMAT_UNCOMPRESSED = 3, SOUND_FORMAT_NELLYMOSER = 6 }; enum sound_endian_t { SOUND_ENDIAN_LITTLE = 0, // the user data is in little endian SOUND_ENDIAN_BIG, // the user data is in big endian SOUND_ENDIAN_SAME, // accept processor endianess as the data endianess SOUND_ENDIAN_DONTUSE, // use this for 8bits data SOUND_ENDIAN_UNKNOWN // undefined endianess -- the SetData() will always fail with this value }; static const int g_sound_rates[4]; TagSound(TagBase *parent); virtual int Save(Data& data); virtual swf_type_t TypeFlags(void) const; size_t GetSamplesCount(void) const; /////////////// SETUP FUNCTIONS int SetFilename(const char *filename); void SetFormat(sound_format_t format); int SetData(const void *data, size_t size, sound_endian_t endian, int width, unsigned int rate, bool stereo); void SetMono(void); void Set8Bits(void); private: struct sound_wave_t { short format; // the data format (we only support PCM) short channels; // number of channels (1 - mono, 2 - stereo) int rate; // exact sample rate to play the sound at int average_rate; // average rate for the entire set of samples (this may vary in compressed files) short align; // byte alignment of the samples (every char, short, long...) /* the following is format dependent, but at this time doesn't vary for us */ short width; // width of the samples (8 or 16) }; virtual int PreSave(void); short ReadSample(const unsigned char *data, unsigned short adjust, int in_fmt); void Resample(unsigned char *snd, unsigned int out_bytes, const unsigned char *src, size_t size, unsigned int in_bytes, size_t max, double fix, unsigned short adjust, int in_fmt); int LoadWaveFile(FILE *f); int LoadMP3File(FILE *f); int CheckMP3Header(FILE *f, unsigned char *header, int& frame_size); int ReadMP3Header(FILE *f, unsigned char *header); static const int g_bitrates[2][16]; static const int g_frequencies[4][4]; sound_format_t f_format; bool f_stereo; int f_rate; int f_width; size_t f_samples; int f_data_size; int f_data_maxsize; unsigned char * f_data; int f_latency_seek; }; class TagSprite : public TagBaseID { public: TagSprite(TagBase *parent); virtual int Save(Data& data); virtual swf_type_t TypeFlags(void) const; /////////////// SETUP FUNCTIONS // There aren't any (yet). // Add objects to a sprite by defining the sprite tag as // the parent of these objects. // The parent of a sprite must be a TagHeader object. private: virtual int PreSave(void); }; class TagText : public TagBaseID { public: TagText(TagBase *parent); virtual int Save(Data& data); virtual swf_type_t TypeFlags(void) const; /////////////// SETUP FUNCTIONS void SetMatrix(const Matrix& matrix); void SetBounds(const SRectangle& bounds); void AddText(const char *string, long advance = LONG_MIN); void AddFont(const TagFont *font, long height); void AddOffsets(long x, long y); void AddColor(Color& color); private: enum text_type_t { TEXT_ENTRY_TEXT = 0, TEXT_ENTRY_SETUP }; struct text_define_t : public ItemBase { // used to save in f_shapes const text_type_t f_type; text_define_t(text_type_t type) : f_type(type) {} }; struct text_setup_t : public text_define_t { // used to save in f_shapes bool f_has_font; const TagFont * f_font; unsigned short f_font_height; bool f_has_xadjust; long f_xadjust; bool f_has_xoffset; long f_x; bool f_has_yoffset; long f_y; bool f_has_color; Color f_color; text_setup_t(void); text_setup_t(const text_setup_t& setup); void Unused(void); bool IsUsed(void) const; }; struct text_entry_t : public text_define_t { sswf_ucs4_t * f_text; long f_advance; unsigned long f_length; // length of the string unsigned long f_exact_length; // length of string without spaces TagFont::font_info_t * f_entries; // an array of entries text_entry_t(sswf_ucs4_t *string, long advance); }; virtual int PreSave(void); int DefineText(int start, text_setup_t *s, const TagFont *font, int font_height); void RecordSetup(void); void NewSetup(void); Matrix f_matrix; // a transformation matrix for this text SRectangle f_bounds; // where the string is drawn text_setup_t f_setup; // current setup definition bool f_new_text; // if true we need to recompute the text info entries int f_version; // the PreSave() defines this, Save() uses it Vectors f_records; // text records }; }; // namespace sswf #endif /* #ifndef LIBSSWF_H */