typedef struct _JPEGDESTMGR
{ struct jpeg_destination_mgr mgr;
- LPTAG t;
+ TAG * t;
JOCTET * buffer;
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
// Destination manager callbacks
void swf_init_destination(j_compress_ptr cinfo)
-{ LPJPEGDESTMGR dmgr = (LPJPEGDESTMGR)cinfo->dest;
+{ JPEGDESTMGR * dmgr = (JPEGDESTMGR *)cinfo->dest;
dmgr->buffer = (JOCTET*)malloc(OUTBUFFER_SIZE);
dmgr->mgr.next_output_byte = dmgr->buffer;
dmgr->mgr.free_in_buffer = OUTBUFFER_SIZE;
}
boolean swf_empty_output_buffer(j_compress_ptr cinfo)
-{ LPJPEGDESTMGR dmgr = (LPJPEGDESTMGR)cinfo->dest;
+{ JPEGDESTMGR * dmgr = (JPEGDESTMGR *)cinfo->dest;
SetBlock(dmgr->t,(U8*)dmgr->buffer,OUTBUFFER_SIZE);
dmgr->mgr.next_output_byte = dmgr->buffer;
dmgr->mgr.free_in_buffer = OUTBUFFER_SIZE;
}
void swf_term_destination(j_compress_ptr cinfo)
-{ LPJPEGDESTMGR dmgr = (LPJPEGDESTMGR)cinfo->dest;
+{ JPEGDESTMGR * dmgr = (JPEGDESTMGR *)cinfo->dest;
SetBlock(dmgr->t,(U8*)dmgr->buffer,OUTBUFFER_SIZE-dmgr->mgr.free_in_buffer);
free(dmgr->buffer);
dmgr->mgr.free_in_buffer = 0;
}
-LPJPEGBITS SetJPEGBitsStart(LPTAG t,int width,int height,int quality)
+JPEGBITS * SetJPEGBitsStart(TAG * t,int width,int height,int quality)
{
- LPJPEGDESTMGR jpeg;
+ JPEGDESTMGR * jpeg;
// redirect compression lib output to local SWF Tag structure
- jpeg = (LPJPEGDESTMGR)malloc(sizeof(JPEGDESTMGR));
+ jpeg = (JPEGDESTMGR *)malloc(sizeof(JPEGDESTMGR));
if (!jpeg) return NULL;
memset(jpeg,0x00,sizeof(JPEGDESTMGR));
jpeg_suppress_tables(&jpeg->cinfo, TRUE);
jpeg_start_compress(&jpeg->cinfo, FALSE);
- return (LPJPEGBITS)jpeg;
+ return (JPEGBITS *)jpeg;
}
-int SetJPEGBitsLines(LPJPEGBITS jpegbits,U8 ** data,int n)
-{ LPJPEGDESTMGR jpeg = (LPJPEGDESTMGR)jpegbits;
+int SetJPEGBitsLines(JPEGBITS * jpegbits,U8 ** data,int n)
+{ JPEGDESTMGR * jpeg = (JPEGDESTMGR *)jpegbits;
if (!jpeg) return -1;
jpeg_write_scanlines(&jpeg->cinfo,data,n);
return 0;
}
-int SetJPEGBitsLine(LPJPEGBITS jpegbits,U8 * data)
+int SetJPEGBitsLine(JPEGBITS * jpegbits,U8 * data)
{ return SetJPEGBitsLines(jpegbits,&data,1);
}
-int SetJPEGBitsFinish(LPJPEGBITS jpegbits)
-{ LPJPEGDESTMGR jpeg = (LPJPEGDESTMGR)jpegbits;
+int SetJPEGBitsFinish(JPEGBITS * jpegbits)
+{ JPEGDESTMGR * jpeg = (JPEGDESTMGR *)jpegbits;
if (!jpeg) return -1;
jpeg_finish_compress(&jpeg->cinfo);
free(jpeg);
return 0;
}
-int SetJPEGBits(LPTAG t,char * fname,int quality)
+int SetJPEGBits(TAG * t,char * fname,int quality)
{ struct jpeg_decompress_struct cinfo;
struct jpeg_error_mgr jerr;
- LPJPEGBITS out;
+ JPEGBITS * out;
FILE * f;
U8 * scanline;
-/* swfbutton.c\r
-\r
- Button functions\r
-\r
- Extension module for the rfxswf library.\r
- Part of the swftools package.\r
-\r
- Copyright (c) 2000, 2001 Rainer Böhme <rfxswf@reflex-studio.de>\r
- \r
- This file is distributed under the GPL, see file COPYING for details \r
-\r
-*/\r
-\r
-int ButtonSetRecord(LPTAG t,U8 state,U16 id,U16 layer,LPMATRIX m,LPCXFORM cx)\r
-\r
-{ SetU8(t,state);\r
- SetU16(t,id);\r
- SetU16(t,layer);\r
- SetMatrix(t,m);\r
-// SetCXForm(t,cx,0);\r
- return 0;\r
-}\r
-\r
-int ButtonSetCondition(LPTAG t,U16 condition)\r
-{ SetU16(t,0); // dummy for Action Offset -> later set by ButtonPostProcess\r
- SetU16(t,condition);\r
- return 0;\r
-}\r
-\r
-int ButtonSetFlags(LPTAG t,U8 flags)\r
-{ if (GetTagID(t)==ST_DEFINEBUTTON2)\r
- { SetU8(t,flags);\r
- SetU16(t,0); // dummy for Action Offset -> later set by ButtonPostProcess\r
- }\r
- return 0;\r
-}\r
-\r
-void SetButtonOffset(LPTAG t,U32 offsetpos)\r
-{ U32 now = GetTagPos(t);\r
- U16 diff = now-offsetpos;\r
- SetTagPos(t,offsetpos);\r
- t->data[t->pos++] = (U8)(diff&0xff);\r
- t->data[t->pos++] = (U8)(diff>>8);\r
- SetTagPos(t,now);\r
-}\r
-\r
-int ButtonPostProcess(LPTAG t,int anz_action)\r
-{ if (GetTagID(t)==ST_DEFINEBUTTON2)\r
- { U32 oldTagPos;\r
- U32 offsetpos;\r
-\r
- oldTagPos = GetTagPos(t);\r
-\r
- // scan DefineButton2 Record\r
- \r
- GetU16(t); // Character ID\r
- GetU8(t); // Flags;\r
-\r
- offsetpos = GetTagPos(t); // first offset\r
- GetU16(t);\r
-\r
- while (GetU8(t)) // state -> parse ButtonRecord\r
- { GetU16(t); // id\r
- GetU16(t); // layer\r
- GetMatrix(t,NULL); // matrix\r
- // evtl.: CXForm\r
- }\r
-\r
- SetButtonOffset(t,offsetpos);\r
-\r
- while(anz_action)\r
- { U8 a;\r
- \r
- offsetpos = GetTagPos(t); // offset\r
- GetU16(t);\r
-\r
- GetU16(t); // condition\r
- \r
- while (a=GetU8(t)) // skip action records\r
- { if (a&0x80)\r
- { U16 l = GetU16(t);\r
- GetBlock(t,NULL,l);\r
- }\r
- }\r
- \r
- if (--anz_action) SetButtonOffset(t,offsetpos);\r
- }\r
- \r
- SetTagPos(t,oldTagPos);\r
- }\r
- return 0;\r
-}\r
+/* swfbutton.c
+
+ Button functions
+
+ Extension module for the rfxswf library.
+ Part of the swftools package.
+
+ Copyright (c) 2000, 2001 Rainer Böhme <rfxswf@reflex-studio.de>
+
+ This file is distributed under the GPL, see file COPYING for details
+
+*/
+
+int ButtonSetRecord(TAG * t,U8 state,U16 id,U16 layer,MATRIX * m,CXFORM * cx)
+
+{ SetU8(t,state);
+ SetU16(t,id);
+ SetU16(t,layer);
+ SetMatrix(t,m);
+// SetCXForm(t,cx,0);
+ return 0;
+}
+
+int ButtonSetCondition(TAG * t,U16 condition)
+{ SetU16(t,0); // dummy for Action Offset -> later set by ButtonPostProcess
+ SetU16(t,condition);
+ return 0;
+}
+
+int ButtonSetFlags(TAG * t,U8 flags)
+{ if (GetTagID(t)==ST_DEFINEBUTTON2)
+ { SetU8(t,flags);
+ SetU16(t,0); // dummy for Action Offset -> later set by ButtonPostProcess
+ }
+ return 0;
+}
+
+void SetButtonOffset(TAG * t,U32 offsetpos)
+{ U32 now = GetTagPos(t);
+ U16 diff = now-offsetpos;
+ SetTagPos(t,offsetpos);
+ t->data[t->pos++] = (U8)(diff&0xff);
+ t->data[t->pos++] = (U8)(diff>>8);
+ SetTagPos(t,now);
+}
+
+int ButtonPostProcess(TAG * t,int anz_action)
+{ if (GetTagID(t)==ST_DEFINEBUTTON2)
+ { U32 oldTagPos;
+ U32 offsetpos;
+
+ oldTagPos = GetTagPos(t);
+
+ // scan DefineButton2 Record
+
+ GetU16(t); // Character ID
+ GetU8(t); // Flags;
+
+ offsetpos = GetTagPos(t); // first offset
+ GetU16(t);
+
+ while (GetU8(t)) // state -> parse ButtonRecord
+ { GetU16(t); // id
+ GetU16(t); // layer
+ GetMatrix(t,NULL); // matrix
+ // evtl.: CXForm
+ }
+
+ SetButtonOffset(t,offsetpos);
+
+ while(anz_action)
+ { U8 a;
+
+ offsetpos = GetTagPos(t); // offset
+ GetU16(t);
+
+ GetU16(t); // condition
+
+ while (a=GetU8(t)) // skip action records
+ { if (a&0x80)
+ { U16 l = GetU16(t);
+ GetBlock(t,NULL,l);
+ }
+ }
+
+ if (--anz_action) SetButtonOffset(t,offsetpos);
+ }
+
+ SetTagPos(t,oldTagPos);
+ }
+ return 0;
+}
-/* swfcgi.c\r
-\r
- Parse CGI parameters\r
- \r
- Partly adopted from Steven Grimm's uncgi tool and library.\r
-\r
- Extension module for the rfxswf library.\r
- Part of the swftools package.\r
-\r
- Copyright (c) 2001 Rainer Böhme <rfxswf@reflex-studio.de>\r
- \r
- This file is distributed under the GPL, see file COPYING for details \r
-\r
-*/\r
-\r
-\r
-#define ishex(x) (((x) >= '0' && (x) <= '9') || ((x) >= 'a' && (x) <= 'f') || ((x) >= 'A' && (x) <= 'F'))\r
-\r
-#define PREFIX "WWW_"\r
-\r
-static int htoi(unsigned char * s)\r
-{ int value;\r
- char c;\r
-\r
- c = s[0];\r
- if (isupper(c)) c = tolower(c);\r
- value = (c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10) * 16;\r
-\r
- c = s[1];\r
- if (isupper(c)) c = tolower(c);\r
- value += c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10;\r
-\r
- return (value);\r
-}\r
-\r
-static void url_unescape(unsigned char * s)\r
-{ unsigned char *dest = s;\r
-\r
- while (s[0])\r
- { if (s[0] == '+') dest[0] = ' ';\r
- else\r
- { if (s[0] == '%' && ishex(s[1]) && ishex(s[2]))\r
- { dest[0] = (unsigned char) htoi(s + 1);\r
- s += 2;\r
- }\r
- else dest[0] = s[0];\r
- }\r
- s++;dest++;\r
- }\r
- dest[0] = 0;\r
-}\r
-\r
-static void cgienv(unsigned char * var)\r
-{ unsigned char *buf, *c, *s, *t, *oldval = NULL, *newval;\r
- int despace = 0, got_cr = 0;\r
-\r
- // fprintf(stderr,"%s\n",var);\r
- url_unescape(var);\r
- // fprintf(stderr,"%s\n",var);\r
-\r
- \r
- buf = (unsigned char*)malloc(strlen(var) + sizeof(PREFIX) + 2);\r
- if (!buf) return;\r
-\r
- strcpy(buf, PREFIX);\r
- if (var[0] == '_')\r
- { strcpy(&buf[sizeof(PREFIX)-1], &var[1]);\r
- despace = 1;\r
- }\r
- else strcpy(&buf[sizeof(PREFIX)-1], var);\r
-\r
- for (c = buf; c[0] ; c++)\r
- { if (c[0] == '.') c[0] = '_';\r
- if (c[0] == '=') break;\r
- }\r
- if (!c[0]) c[1] = 0;\r
- c[0] = 0;\r
-\r
- if (despace && c[1])\r
- { for (s = c+1; s[0] && isspace(s[0]); s++);\r
- t = c + 1;\r
- while (s[0])\r
- { if (s[0] == '\r')\r
- { got_cr = 1;\r
- s++;\r
- continue;\r
- }\r
- if (got_cr)\r
- { if (s[0] != '\n')\r
- *t++ = '\n';\r
- got_cr = 0;\r
- }\r
- *t++ = *s++;\r
- }\r
- while (t > c && isspace(*--t));\r
- t[1] = 0;\r
- }\r
-\r
- if ((oldval = getenv(buf)))\r
- { newval = (unsigned char*)malloc(strlen(oldval) + strlen(buf) + strlen(&c[1]) + 3);\r
- if (!newval) return;\r
-\r
- c[0] = '=';\r
- sprintf(newval, "%s#%s", buf, oldval);\r
- c[0] = 0;\r
-\r
- oldval -= strlen(buf) + 1; // skip past VAR= \r
- }\r
- else \r
- { c[0] = '=';\r
- newval = buf;\r
- }\r
- \r
- putenv(newval);\r
- \r
- if (oldval)\r
- { free(oldval);\r
- free(buf);\r
- }\r
-}\r
-\r
-static void scanquery(char * q)\r
-{ char *next = q;\r
- if (!q) return;\r
-\r
- while (next)\r
- { next = strchr(q, '&');\r
- if (next) next[0] = 0;\r
- cgienv(q);\r
- if (next)\r
- { next[0] = '&';\r
- q = next+1;\r
- }\r
- } \r
-}\r
-\r
-char * postread()\r
-{ char * buf = NULL;\r
- int size = 0, sofar = 0, got;\r
-\r
- buf = getenv("CONTENT_TYPE");\r
- if ((!buf) || strcmp(buf, "application/x-www-form-urlencoded")) return NULL;\r
-\r
- buf = getenv("CONTENT_LENGTH");\r
- if (!buf) return NULL;\r
- \r
- size = atoi(buf);\r
- buf = (unsigned char*)malloc(size + 1);\r
- if (buf)\r
- { do\r
- { got = fread(buf + sofar, 1, size - sofar, stdin);\r
- sofar += got;\r
- } while (got && sofar < size);\r
- buf[sofar] = 0;\r
- }\r
-\r
- return buf;\r
-}\r
-\r
-void uncgi()\r
-{ char *query, *dupquery, *method;\r
-\r
- query = getenv("QUERY_STRING");\r
- if ((query) && strlen(query))\r
- { dupquery = strdup(query);\r
- scanquery(dupquery);\r
- free(dupquery);\r
- }\r
-\r
- method = getenv("REQUEST_METHOD");\r
- if ((method) && ! strcmp(method, "POST"))\r
- { query = postread();\r
- if ((query)&&(query[0]!=0)) scanquery(query);\r
- free(query);\r
- }\r
- \r
-}\r
- \r
-#undef ishex\r
+/* swfcgi.c
+
+ Parse CGI parameters
+
+ Partly adopted from Steven Grimm's uncgi tool and library.
+
+ Extension module for the rfxswf library.
+ Part of the swftools package.
+
+ Copyright (c) 2001 Rainer Böhme <rfxswf@reflex-studio.de>
+
+ This file is distributed under the GPL, see file COPYING for details
+
+*/
+
+
+#define ishex(x) (((x) >= '0' && (x) <= '9') || ((x) >= 'a' && (x) <= 'f') || ((x) >= 'A' && (x) <= 'F'))
+
+#define PREFIX "WWW_"
+
+static int htoi(unsigned char * s)
+{ int value;
+ char c;
+
+ c = s[0];
+ if (isupper(c)) c = tolower(c);
+ value = (c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10) * 16;
+
+ c = s[1];
+ if (isupper(c)) c = tolower(c);
+ value += c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10;
+
+ return (value);
+}
+
+static void url_unescape(unsigned char * s)
+{ unsigned char *dest = s;
+
+ while (s[0])
+ { if (s[0] == '+') dest[0] = ' ';
+ else
+ { if (s[0] == '%' && ishex(s[1]) && ishex(s[2]))
+ { dest[0] = (unsigned char) htoi(s + 1);
+ s += 2;
+ }
+ else dest[0] = s[0];
+ }
+ s++;dest++;
+ }
+ dest[0] = 0;
+}
+
+static void cgienv(unsigned char * var)
+{ unsigned char *buf, *c, *s, *t, *oldval = NULL, *newval;
+ int despace = 0, got_cr = 0;
+
+ // fprintf(stderr,"%s\n",var);
+ url_unescape(var);
+ // fprintf(stderr,"%s\n",var);
+
+
+ buf = (unsigned char*)malloc(strlen(var) + sizeof(PREFIX) + 2);
+ if (!buf) return;
+
+ strcpy(buf, PREFIX);
+ if (var[0] == '_')
+ { strcpy(&buf[sizeof(PREFIX)-1], &var[1]);
+ despace = 1;
+ }
+ else strcpy(&buf[sizeof(PREFIX)-1], var);
+
+ for (c = buf; c[0] ; c++)
+ { if (c[0] == '.') c[0] = '_';
+ if (c[0] == '=') break;
+ }
+ if (!c[0]) c[1] = 0;
+ c[0] = 0;
+
+ if (despace && c[1])
+ { for (s = c+1; s[0] && isspace(s[0]); s++);
+ t = c + 1;
+ while (s[0])
+ { if (s[0] == '\r')
+ { got_cr = 1;
+ s++;
+ continue;
+ }
+ if (got_cr)
+ { if (s[0] != '\n')
+ *t++ = '\n';
+ got_cr = 0;
+ }
+ *t++ = *s++;
+ }
+ while (t > c && isspace(*--t));
+ t[1] = 0;
+ }
+
+ if ((oldval = getenv(buf)))
+ { newval = (unsigned char*)malloc(strlen(oldval) + strlen(buf) + strlen(&c[1]) + 3);
+ if (!newval) return;
+
+ c[0] = '=';
+ sprintf(newval, "%s#%s", buf, oldval);
+ c[0] = 0;
+
+ oldval -= strlen(buf) + 1; // skip past VAR=
+ }
+ else
+ { c[0] = '=';
+ newval = buf;
+ }
+
+ putenv(newval);
+
+ if (oldval)
+ { free(oldval);
+ free(buf);
+ }
+}
+
+static void scanquery(char * q)
+{ char *next = q;
+ if (!q) return;
+
+ while (next)
+ { next = strchr(q, '&');
+ if (next) next[0] = 0;
+ cgienv(q);
+ if (next)
+ { next[0] = '&';
+ q = next+1;
+ }
+ }
+}
+
+char * postread()
+{ char * buf = NULL;
+ int size = 0, sofar = 0, got;
+
+ buf = getenv("CONTENT_TYPE");
+ if ((!buf) || strcmp(buf, "application/x-www-form-urlencoded")) return NULL;
+
+ buf = getenv("CONTENT_LENGTH");
+ if (!buf) return NULL;
+
+ size = atoi(buf);
+ buf = (unsigned char*)malloc(size + 1);
+ if (buf)
+ { do
+ { got = fread(buf + sofar, 1, size - sofar, stdin);
+ sofar += got;
+ } while (got && sofar < size);
+ buf[sofar] = 0;
+ }
+
+ return buf;
+}
+
+void uncgi()
+{ char *query, *dupquery, *method;
+
+ query = getenv("QUERY_STRING");
+ if ((query) && strlen(query))
+ { dupquery = strdup(query);
+ scanquery(dupquery);
+ free(dupquery);
+ }
+
+ method = getenv("REQUEST_METHOD");
+ if ((method) && ! strcmp(method, "POST"))
+ { query = postread();
+ if ((query)&&(query[0]!=0)) scanquery(query);
+ free(query);
+ }
+
+}
+
+#undef ishex
-/* swfdump.c\r
-\r
- Dump / debug functions\r
- \r
- Extension module for the rfxswf library.\r
- Part of the swftools package.\r
-\r
- Copyright (c) 2001 Rainer Böhme <rfxswf@reflex-studio.de>\r
- \r
- This file is distributed under the GPL, see file COPYING for details \r
-\r
-*/\r
-\r
-void DumpHeader(FILE * f,LPSWF swf)\r
-{ if (!f) f = stderr;\r
- fprintf(f,"File size\t%u\n",swf->FileSize);\r
- fprintf(f,"Movie width\t%u\n",(swf->MovieSize.xmax - swf->MovieSize.xmin)/20);\r
- fprintf(f,"Movie height\t%u\n",(swf->MovieSize.ymax - swf->MovieSize.ymin)/20);\r
- fprintf(f,"Frame rate\t%u.%u\n",swf->FrameRate>>8,swf->FrameRate&0xff);\r
- fprintf(f,"Frame count\t%u\n",swf->FrameCount);\r
-}\r
-\r
-void DumpMatrix(FILE * f,LPMATRIX m)\r
-{ if (!f) f = stderr;\r
- fprintf(f,"[%08x][%08x]\n",m->sx,m->r1);\r
- fprintf(f,"[%08x][%08x]\n",m->r0,m->sy);\r
- fprintf(f," %08x, %08x\n",m->tx,m->ty);\r
-}\r
-\r
-void DumpTag(FILE * f,LPTAG t)\r
-{ int i;\r
- if (!f) f = stderr;\r
- for (i=0;i<t->len;i++)\r
- { if (!(i&15)) fprintf(f,"\n");\r
- fprintf(f,"%02x ",t->data[i]);\r
- }\r
- fprintf(f,"\n");\r
-}\r
-\r
-char* getTagName(TAG*tag)\r
-{\r
- switch(tag->id)\r
- {\r
- case ST_END:\r
- return "END";\r
- case ST_SHOWFRAME:\r
- return "SHOWFRAME";\r
- case ST_DEFINESHAPE:\r
- return "DEFINESHAPE";\r
- case ST_FREECHARACTER:\r
- return "FREECHARACTER";\r
- case ST_PLACEOBJECT:\r
- return "PLACEOBJECT";\r
- case ST_REMOVEOBJECT:\r
- return "REMOVEOBJECT";\r
- case ST_DEFINEBITS:\r
- return "DEFINEBITS";\r
- case ST_DEFINEBUTTON:\r
- return "DEFINEBUTTON";\r
- case ST_JPEGTABLES:\r
- return "JPEGTABLES";\r
- case ST_SETBACKGROUNDCOLOR:\r
- return "SETBACKGROUNDCOLOR";\r
- case ST_DEFINEFONT:\r
- return "DEFINEFONT";\r
- case ST_DEFINETEXT:\r
- return "DEFINETEXT";\r
- case ST_DOACTION:\r
- return "DOACTION";\r
- case ST_DEFINEFONTINFO:\r
- return "DEFINEFONTINFO";\r
- case ST_DEFINESOUND:\r
- return "DEFINESOUND";\r
- case ST_STARTSOUND:\r
- return "STARTSOUND";\r
- case ST_DEFINEBUTTONSOUND:\r
- return "DEFINEBUTTONSOUND";\r
- case ST_SOUNDSTREAMHEAD:\r
- return "SOUNDSTREAMHEAD";\r
- case ST_SOUNDSTREAMBLOCK:\r
- return "SOUNDSTREAMBLOCK";\r
- case ST_DEFINEBITSLOSSLESS:\r
- return "DEFINEBITSLOSSLESS";\r
- case ST_DEFINEBITSJPEG2:\r
- return "DEFINEBITSJPEG2";\r
- case ST_DEFINESHAPE2:\r
- return "DEFINESHAPE2";\r
- case ST_DEFINEBUTTONCXFORM:\r
- return "DEFINEBUTTONCXFORM";\r
- case ST_PROTECT:\r
- return "PROTECT";\r
- case ST_PLACEOBJECT2:\r
- return "PLACEOBJECT2";\r
- case ST_REMOVEOBJECT2:\r
- return "REMOVEOBJECT2";\r
- case ST_DEFINESHAPE3:\r
- return "DEFINESHAPE3";\r
- case ST_DEFINETEXT2:\r
- return "DEFINETEXT2";\r
- case ST_DEFINEBUTTON2:\r
- return "DEFINEBUTTON2";\r
- case ST_DEFINEBITSJPEG3:\r
- return "DEFINEBITSJPEG3";\r
- case ST_DEFINEBITSLOSSLESS2:\r
- return "DEFINEBITSLOSSLESS2";\r
- case ST_DEFINESPRITE:\r
- return "DEFINESPRITE";\r
- case ST_NAMECHARACTER:\r
- return "NAMECHARACTER";\r
- case ST_SERIALNUMBER:\r
- return "SERIALNUMBER";\r
- case ST_GENERATORTEXT:\r
- return "GENERATORTEXT";\r
- case ST_FRAMELABEL:\r
- return "FRAMELABEL";\r
- case ST_SOUNDSTREAMHEAD2:\r
- return "SOUNDSTREAMHEAD2";\r
- case ST_DEFINEMORPHSHAPE:\r
- return "DEFINEMORPHSHAPE";\r
- case ST_DEFINEFONT2:\r
- return "DEFINEFONT2";\r
- case ST_TEMPLATECOMMAND:\r
- return "TEMPLATECOMMAND";\r
- case ST_GENERATOR3:\r
- return "GENERATOR3";\r
- case ST_EXTERNALFONT:\r
- return "EXTERNALFONT";\r
- case ST_REFLEX:\r
- return "REFLEX";\r
- }\r
-}\r
+/* swfdump.c
+
+ Dump / debug functions
+
+ Extension module for the rfxswf library.
+ Part of the swftools package.
+
+ Copyright (c) 2001 Rainer Böhme <rfxswf@reflex-studio.de>
+
+ This file is distributed under the GPL, see file COPYING for details
+
+*/
+
+void DumpHeader(FILE * f,SWF * swf)
+{ if (!f) f = stderr;
+ fprintf(f,"File size\t%u\n",swf->FileSize);
+ fprintf(f,"Movie width\t%u\n",(swf->MovieSize.xmax - swf->MovieSize.xmin)/20);
+ fprintf(f,"Movie height\t%u\n",(swf->MovieSize.ymax - swf->MovieSize.ymin)/20);
+ fprintf(f,"Frame rate\t%u.%u\n",swf->FrameRate>>8,swf->FrameRate&0xff);
+ fprintf(f,"Frame count\t%u\n",swf->FrameCount);
+}
+
+void DumpMatrix(FILE * f,MATRIX * m)
+{ if (!f) f = stderr;
+ fprintf(f,"[%08x][%08x]\n",m->sx,m->r1);
+ fprintf(f,"[%08x][%08x]\n",m->r0,m->sy);
+ fprintf(f," %08x, %08x\n",m->tx,m->ty);
+}
+
+void DumpTag(FILE * f,TAG * t)
+{ int i;
+ if (!f) f = stderr;
+ for (i=0;i<t->len;i++)
+ { if (!(i&15)) fprintf(f,"\n");
+ fprintf(f,"%02x ",t->data[i]);
+ }
+ fprintf(f,"\n");
+}
+
+char* getTagName(TAG*tag)
+{
+ switch(tag->id)
+ {
+ case ST_END:
+ return "END";
+ case ST_SHOWFRAME:
+ return "SHOWFRAME";
+ case ST_DEFINESHAPE:
+ return "DEFINESHAPE";
+ case ST_FREECHARACTER:
+ return "FREECHARACTER";
+ case ST_PLACEOBJECT:
+ return "PLACEOBJECT";
+ case ST_REMOVEOBJECT:
+ return "REMOVEOBJECT";
+ case ST_DEFINEBITS:
+ return "DEFINEBITS";
+ case ST_DEFINEBUTTON:
+ return "DEFINEBUTTON";
+ case ST_JPEGTABLES:
+ return "JPEGTABLES";
+ case ST_SETBACKGROUNDCOLOR:
+ return "SETBACKGROUNDCOLOR";
+ case ST_DEFINEFONT:
+ return "DEFINEFONT";
+ case ST_DEFINETEXT:
+ return "DEFINETEXT";
+ case ST_DOACTION:
+ return "DOACTION";
+ case ST_DEFINEFONTINFO:
+ return "DEFINEFONTINFO";
+ case ST_DEFINESOUND:
+ return "DEFINESOUND";
+ case ST_STARTSOUND:
+ return "STARTSOUND";
+ case ST_DEFINEBUTTONSOUND:
+ return "DEFINEBUTTONSOUND";
+ case ST_SOUNDSTREAMHEAD:
+ return "SOUNDSTREAMHEAD";
+ case ST_SOUNDSTREAMBLOCK:
+ return "SOUNDSTREAMBLOCK";
+ case ST_DEFINEBITSLOSSLESS:
+ return "DEFINEBITSLOSSLESS";
+ case ST_DEFINEBITSJPEG2:
+ return "DEFINEBITSJPEG2";
+ case ST_DEFINESHAPE2:
+ return "DEFINESHAPE2";
+ case ST_DEFINEBUTTONCXFORM:
+ return "DEFINEBUTTONCXFORM";
+ case ST_PROTECT:
+ return "PROTECT";
+ case ST_PLACEOBJECT2:
+ return "PLACEOBJECT2";
+ case ST_REMOVEOBJECT2:
+ return "REMOVEOBJECT2";
+ case ST_DEFINESHAPE3:
+ return "DEFINESHAPE3";
+ case ST_DEFINETEXT2:
+ return "DEFINETEXT2";
+ case ST_DEFINEBUTTON2:
+ return "DEFINEBUTTON2";
+ case ST_DEFINEBITSJPEG3:
+ return "DEFINEBITSJPEG3";
+ case ST_DEFINEBITSLOSSLESS2:
+ return "DEFINEBITSLOSSLESS2";
+ case ST_DEFINESPRITE:
+ return "DEFINESPRITE";
+ case ST_NAMECHARACTER:
+ return "NAMECHARACTER";
+ case ST_SERIALNUMBER:
+ return "SERIALNUMBER";
+ case ST_GENERATORTEXT:
+ return "GENERATORTEXT";
+ case ST_FRAMELABEL:
+ return "FRAMELABEL";
+ case ST_SOUNDSTREAMHEAD2:
+ return "SOUNDSTREAMHEAD2";
+ case ST_DEFINEMORPHSHAPE:
+ return "DEFINEMORPHSHAPE";
+ case ST_DEFINEFONT2:
+ return "DEFINEFONT2";
+ case ST_TEMPLATECOMMAND:
+ return "TEMPLATECOMMAND";
+ case ST_GENERATOR3:
+ return "GENERATOR3";
+ case ST_EXTERNALFONT:
+ return "EXTERNALFONT";
+ case ST_REFLEX:
+ return "REFLEX";
+ }
+}
-/* swfobject.c\r
-\r
- Object place and move routines\r
- \r
- Extension module for the rfxswf library.\r
- Part of the swftools package.\r
-\r
- Copyright (c) 2001 Rainer Böhme <rfxswf@reflex-studio.de>\r
- \r
- This file is distributed under the GPL, see file COPYING for details \r
-\r
-*/\r
-\r
-#define PF_MOVE 0x01\r
-#define PF_CHAR 0x02\r
-#define PF_MATRIX 0x04\r
-#define PF_CXFORM 0x08\r
-#define PF_RATIO 0x10\r
-#define PF_NAME 0x20\r
-#define PF_CLIPACTION 0x40\r
-\r
-int ObjectPlace(LPTAG t,U16 id,U16 depth,LPMATRIX m,LPCXFORM cx,U8 * name)\r
-{ U8 flags;\r
- if (!t) return -1;\r
-\r
- flags = (id?PF_CHAR:0)|(m?PF_MATRIX:0)|(cx?PF_CXFORM:0)|(name?PF_NAME:0)|((m||cx)&&(!id)?PF_MOVE:0);\r
-\r
- SetU8(t,flags);\r
- SetU16(t,depth);\r
- if (flags&PF_CHAR) SetU16(t,id);\r
- if (flags&PF_MATRIX) SetMatrix(t,m);\r
- if (flags&PF_CXFORM) SetCXForm(t,cx,(cx->a0!=256)||(cx->a1));\r
- if (flags&PF_RATIO) SetU16(t,0);\r
- if (flags&PF_NAME) SetString(t,name);\r
- \r
- return 0; \r
-}\r
-\r
-int PlaceObject(LPTAG t,U16 id,U16 depth,LPMATRIX m,LPCXFORM cx,U8 * name, U16 clipaction)\r
-{ U8 flags;\r
- if (!t) return -1;\r
-\r
- flags = (id?PF_CHAR:0)|(m?PF_MATRIX:0)|(cx?PF_CXFORM:0)|(name?PF_NAME:0)|\r
- ((m||cx)&&(!id)?PF_MOVE:0)|(clipaction?PF_CLIPACTION:0);\r
-\r
- SetU8(t,flags);\r
- SetU16(t,depth);\r
- if (flags&PF_CHAR) SetU16(t,id);\r
- if (flags&PF_MATRIX) SetMatrix(t,m);\r
- if (flags&PF_CXFORM) SetCXForm(t,cx,(cx->a0!=256)||(cx->a1));\r
- if (flags&PF_RATIO) SetU16(t,0);\r
- if (flags&PF_NAME) SetString(t,name);\r
- if (flags&PF_CLIPACTION) SetU16(t, clipaction);\r
- return 0; \r
-}\r
-\r
-int ObjectMove(LPTAG t,U16 depth,LPMATRIX m,LPCXFORM cx)\r
-{ return ObjectPlace(t,0,depth,m,cx,NULL);\r
-}\r
+/* swfobject.c
+
+ Object place and move routines
+
+ Extension module for the rfxswf library.
+ Part of the swftools package.
+
+ Copyright (c) 2001 Rainer Böhme <rfxswf@reflex-studio.de>
+
+ This file is distributed under the GPL, see file COPYING for details
+
+*/
+
+#define PF_MOVE 0x01
+#define PF_CHAR 0x02
+#define PF_MATRIX 0x04
+#define PF_CXFORM 0x08
+#define PF_RATIO 0x10
+#define PF_NAME 0x20
+#define PF_CLIPACTION 0x40
+
+int ObjectPlace(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,U8 * name)
+{ U8 flags;
+ if (!t) return -1;
+
+ flags = (id?PF_CHAR:0)|(m?PF_MATRIX:0)|(cx?PF_CXFORM:0)|(name?PF_NAME:0)|((m||cx)&&(!id)?PF_MOVE:0);
+
+ SetU8(t,flags);
+ SetU16(t,depth);
+ if (flags&PF_CHAR) SetU16(t,id);
+ if (flags&PF_MATRIX) SetMatrix(t,m);
+ if (flags&PF_CXFORM) SetCXForm(t,cx,(cx->a0!=256)||(cx->a1));
+ if (flags&PF_RATIO) SetU16(t,0);
+ if (flags&PF_NAME) SetString(t,name);
+
+ return 0;
+}
+
+int PlaceObject(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,U8 * name, U16 clipaction)
+{ U8 flags;
+ if (!t) return -1;
+
+ flags = (id?PF_CHAR:0)|(m?PF_MATRIX:0)|(cx?PF_CXFORM:0)|(name?PF_NAME:0)|
+ ((m||cx)&&(!id)?PF_MOVE:0)|(clipaction?PF_CLIPACTION:0);
+
+ SetU8(t,flags);
+ SetU16(t,depth);
+ if (flags&PF_CHAR) SetU16(t,id);
+ if (flags&PF_MATRIX) SetMatrix(t,m);
+ if (flags&PF_CXFORM) SetCXForm(t,cx,(cx->a0!=256)||(cx->a1));
+ if (flags&PF_RATIO) SetU16(t,0);
+ if (flags&PF_NAME) SetString(t,name);
+ if (flags&PF_CLIPACTION) SetU16(t, clipaction);
+ return 0;
+}
+
+int ObjectMove(TAG * t,U16 depth,MATRIX * m,CXFORM * cx)
+{ return ObjectPlace(t,0,depth,m,cx,NULL);
+}
-/* swfshape.c\r
-\r
- shape functions\r
- \r
- Extension module for the rfxswf library.\r
- Part of the swftools package.\r
-\r
- Copyright (c) 2001 Rainer Böhme <rfxswf@reflex-studio.de>\r
- \r
- This file is distributed under the GPL, see file COPYING for details \r
-\r
-*/\r
-\r
-#define SF_MOVETO 0x01\r
-#define SF_FILL0 0x02\r
-#define SF_FILL1 0x04\r
-#define SF_LINE 0x08\r
-#define SF_NEWSTYLE 0x10\r
-\r
-#define FILL_SOLID 0x00\r
-#define FILL_LINEAR 0x10 // Gradient\r
-#define FILL_RADIAL 0x12\r
-#define FILL_TILED 0x40 // Bitmap\r
-#define FILL_CLIPPED 0x41\r
-\r
-void ShapeFree(LPSHAPE s)\r
-{ if (s)\r
- { if (s->linestyle.data) free(s->linestyle.data);\r
- s->linestyle.data = NULL;\r
- s->linestyle.n = 0;\r
- if (s->fillstyle.data) free(s->fillstyle.data);\r
- s->fillstyle.data = NULL;\r
- s->fillstyle.n = 0;\r
- if (s->data) free(s->data);\r
- s->data = NULL;\r
- }\r
- free(s);\r
-}\r
-\r
-int NewShape(LPSHAPE * s)\r
-{ LPSHAPE sh;\r
- if (!s) return -1;\r
- sh = (LPSHAPE)malloc(sizeof(SHAPE)); s[0] = sh;\r
- if (sh) memset(sh,0x00,sizeof(SHAPE));\r
- return sh?0:-1;\r
-}\r
-\r
-int GetSimpleShape(LPTAG t,LPSHAPE * s) // without Linestyle/Fillstyle Record\r
-{ LPSHAPE sh;\r
- int bitl, len;\r
- int end;\r
- U32 pos;\r
- \r
- if (FAILED(NewShape(s))) return -1;\r
- sh = s[0];\r
-\r
- ResetBitmask(t); \r
- sh->bits.fill = (U16)GetBits(t,4);\r
- sh->bits.line = (U16)GetBits(t,4);\r
- bitl = 0; end = 0; pos = GetTagPos(t);\r
-\r
- while (!end)\r
- { int edge = GetBits(t,1); bitl+=1;\r
- if (edge)\r
- { bitl+=1;\r
- if (GetBits(t,1)) // Line\r
- { U16 nbits = GetBits(t,4)+2;\r
- bitl+=5;\r
-\r
- if (GetBits(t,1)) // x/y Line\r
- { GetBits(t,nbits);\r
- GetBits(t,nbits);\r
- bitl+=nbits*2;\r
- }\r
- else // hline/vline\r
- { GetBits(t,nbits+1);\r
- bitl+=nbits+1;\r
- }\r
- }\r
- else // Curve\r
- { U16 nbits = GetBits(t,4)+2;\r
- bitl+=4;\r
-\r
- GetBits(t,nbits);\r
- GetBits(t,nbits);\r
- GetBits(t,nbits);\r
- GetBits(t,nbits);\r
-\r
- bitl+=4*nbits;\r
- }\r
- }\r
- else\r
- { U16 flags = GetBits(t,5); bitl+=5;\r
- if (flags)\r
- {\r
- if (flags&SF_MOVETO)\r
- { U16 nbits = GetBits(t,5); bitl+=5;\r
- GetBits(t,nbits);\r
- GetBits(t,nbits);\r
- bitl+=2*nbits;\r
- }\r
- \r
- if (flags&SF_FILL0)\r
- { GetBits(t,sh->bits.fill);\r
- bitl+=sh->bits.fill;\r
- }\r
- \r
- if (flags&SF_FILL1)\r
- { GetBits(t,sh->bits.fill);\r
- bitl+=sh->bits.fill;\r
- }\r
-\r
- if (flags&SF_LINE)\r
- { GetBits(t,sh->bits.line);\r
- bitl+=sh->bits.line;\r
- }\r
-\r
- if (flags&SF_NEWSTYLE)\r
- { fprintf(stderr,"Can't process extended styles in shape.\n");\r
- }\r
- }\r
- else end = 1;\r
- }\r
- }\r
- SetTagPos(t,pos);\r
- len = (bitl+7)/8;\r
- \r
- if (sh->data) free(sh->data);\r
- sh->data = (U8*)malloc(len);\r
- \r
- if (sh->data)\r
- { sh->bitlen = bitl;\r
- GetBlock(t,sh->data,len);\r
- }\r
- else return -1;\r
- \r
- return len;\r
-}\r
-\r
-int SetSimpleShape(LPTAG t,LPSHAPE s) // without Linestyle/Fillstyle Record\r
-{ int l;\r
-\r
- if (!s) return -1;\r
- l = (s->bitlen+7)/8;\r
-\r
- if (t)\r
- { ResetBitcount(t);\r
-\r
- SetBits(t,s->bits.fill,4);\r
- SetBits(t,s->bits.line,4);\r
- SetBlock(t,s->data,l);\r
-\r
- ResetBitcount(t);\r
- }\r
- return l+1;\r
-}\r
-\r
-int SetFillStyle(LPTAG t,LPFILLSTYLE f)\r
-{ if ((!t)||(!f)) return -1;\r
- SetU8(t,f->type);\r
- \r
- // no gradients yet!\r
- \r
- switch (f->type)\r
- { case FILL_SOLID:\r
- if (GetTagID(t)!=ST_DEFINESHAPE3) SetRGB(t,&f->color);\r
- else SetRGBA(t,&f->color);\r
- break;\r
-\r
- case FILL_TILED:\r
- case FILL_CLIPPED:\r
- SetU16(t,f->id_bitmap);\r
- SetMatrix(t,&f->m);\r
- break;\r
- }\r
- \r
- return 0;\r
-}\r
-\r
-int SetLineStyle(LPTAG t,LPLINESTYLE l)\r
-{ if ((!l)||(!t)) return -1;\r
- SetU16(t,l->width);\r
-\r
- if (GetTagID(t)!=ST_DEFINESHAPE3) SetRGB(t,&l->color);\r
- else SetRGBA(t,&l->color);\r
- \r
- return 0;\r
-}\r
-\r
-int SetShapeStyleCount(LPTAG t,U16 n)\r
-{ if (n>254)\r
- { SetU8(t,0xff);\r
- SetU16(t,n);\r
- return 3;\r
- }\r
- else\r
- { SetU8(t,n);\r
- return 1;\r
- }\r
-}\r
-\r
-int SetShapeStyles(LPTAG t,LPSHAPE s)\r
-{ int i,l;\r
- if (!s) return -1;\r
-\r
- l = 0;\r
- l += SetShapeStyleCount(t,s->fillstyle.n);\r
-\r
- for (i=0;i<s->fillstyle.n;i++)\r
- l+=SetFillStyle(t,&s->fillstyle.data[i]);\r
-\r
- l += SetShapeStyleCount(t,s->linestyle.n);\r
-\r
- for (i=0;i<s->linestyle.n;i++)\r
- l+=SetLineStyle(t,&s->linestyle.data[i]);\r
-\r
- return l;\r
-}\r
-\r
-int ShapeCountBits(LPSHAPE s,U8 * fbits,U8 * lbits)\r
-{ if (!s) return -1;\r
- \r
- s->bits.fill = CountBits(s->fillstyle.n,0);\r
- s->bits.line = CountBits(s->linestyle.n,0);\r
-\r
- if (fbits) fbits[0] = s->bits.fill;\r
- if (lbits) lbits[0] = s->bits.line;\r
- \r
- return 0; \r
-}\r
-\r
-int SetShapeBits(LPTAG t,LPSHAPE s)\r
-{ if ((!t)||(!s)) return -1;\r
- ResetBitcount(t);\r
- SetBits(t,s->bits.fill,4);\r
- SetBits(t,s->bits.line,4);\r
- return 0;\r
-}\r
-\r
-int SetShapeHeader(LPTAG t,LPSHAPE s)\r
-{ int res;\r
- res = SetShapeStyles(t,s);\r
- if (res>=0) res = ShapeCountBits(s,NULL,NULL);\r
- if (res>=0) res = SetShapeBits(t,s);\r
- return res;\r
-}\r
-\r
-int ShapeExport(int handle,LPSHAPE s) // without Linestyle/Fillstyle Record\r
-{ int l;\r
- if (!s) return 0;\r
-\r
- l = sizeof(SHAPE);\r
-\r
- if (handle>=0)\r
- if (write(handle,s,sizeof(SHAPE))!=sizeof(SHAPE)) return -1;\r
-\r
- // Fillstyle, Linestyle ...\r
-\r
- if (s->data)\r
- { int ll = (s->bitlen+7)/8;\r
- l+=ll;\r
- if (handle>=0)\r
- if (write(handle,s->data,ll)!=ll) return -1;\r
- }\r
-\r
- return l;\r
-}\r
-\r
-int ShapeImport(int handle,LPSHAPE * shape)\r
-{ LPSHAPE s;\r
-\r
- if (handle<0) return -1;\r
-\r
- s = (LPSHAPE)malloc(sizeof(SHAPE)); shape[0] = s;\r
- if (!s) return -1;\r
-\r
- if (read(handle,s,sizeof(SHAPE))!=sizeof(SHAPE))\r
- { shape[0] = NULL;\r
- free(s);\r
- return -1;\r
- }\r
-\r
- if (s->data)\r
- { int ll = (s->bitlen+7)/8;\r
- s->data = (U8*)malloc(ll);\r
- if (!s->data)\r
- { shape[0] = NULL;\r
- free(s);\r
- return -1;\r
- }\r
- if (read(handle,s->data,ll)!=ll)\r
- { free(s->data);\r
- free(s);\r
- shape[0] = NULL;\r
- return -1;\r
- }\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-int ShapeAddFillStyle(LPSHAPE s,U8 type,LPMATRIX m,LPRGBA color,U16 id_bitmap)\r
-{ RGBA def_c;\r
- MATRIX def_m; \r
-\r
- // handle defaults\r
- \r
- if (!s) return -1;\r
- if (!color)\r
- { color = &def_c;\r
- def_c.a = 0xff;\r
- def_c.r = def_c.g = def_c.b = 0;\r
- }\r
- if (!m)\r
- { m = &def_m;\r
- GetMatrix(NULL,m);\r
- }\r
-\r
- // handle memory\r
- \r
- if (s->fillstyle.data)\r
- { LPFILLSTYLE new = (LPFILLSTYLE)realloc(s->fillstyle.data,(s->fillstyle.n+1)*sizeof(FILLSTYLE));\r
- if (!new) return -1;\r
- s->fillstyle.data = new;\r
- }\r
- else\r
- { s->fillstyle.data = (LPFILLSTYLE)malloc(sizeof(FILLSTYLE));\r
- s->fillstyle.n = 0;\r
- if (!s->fillstyle.data) return -1;\r
- }\r
-\r
- // set fillstyle (no gradients yet!)\r
- \r
- s->fillstyle.data[s->fillstyle.n].type = type; \r
- s->fillstyle.data[s->fillstyle.n].id_bitmap = id_bitmap;\r
- memcpy(&s->fillstyle.data[s->fillstyle.n].m,m,sizeof(MATRIX));\r
- memcpy(&s->fillstyle.data[s->fillstyle.n].color,color,sizeof(RGBA));\r
- \r
- return (++s->fillstyle.n);\r
-}\r
-\r
-int ShapeAddSolidFillStyle(LPSHAPE s,LPRGBA color)\r
-{ return ShapeAddFillStyle(s,FILL_SOLID,NULL,color,0);\r
-}\r
-\r
-int ShapeAddBitmapFillStyle(LPSHAPE s,LPMATRIX m,U16 id_bitmap,int clip)\r
-{ return ShapeAddFillStyle(s,clip?FILL_CLIPPED:FILL_TILED,m,NULL,id_bitmap);\r
-}\r
-\r
-int ShapeAddLineStyle(LPSHAPE s,U16 width,LPRGBA color)\r
-{ RGBA def;\r
- if (!s) return -1;\r
- if (!color)\r
- { color = &def;\r
- def.a = 0xff;\r
- def.r = def.g = def.b = 0; \r
- }\r
- if (s->linestyle.data)\r
- { LPLINESTYLE new = (LPLINESTYLE)realloc(s->linestyle.data,(s->linestyle.n+1)*sizeof(LINESTYLE));\r
- if (!new) return -1;\r
- s->linestyle.data = new;\r
- }\r
- else\r
- { s->linestyle.data = (LPLINESTYLE)malloc(sizeof(LINESTYLE));\r
- s->linestyle.n = 0;\r
- if (!s->linestyle.data) return -1;\r
- }\r
- \r
- s->linestyle.data[s->linestyle.n].width = width;\r
- memcpy(&s->linestyle.data[s->linestyle.n].color,color,sizeof(RGBA));\r
-\r
- return (++s->linestyle.n);\r
-}\r
-\r
-int ShapeSetMove(LPTAG t,LPSHAPE s,S32 x,S32 y)\r
-{ U8 b;\r
- if (!t) return -1;\r
- SetBits(t,0,1);\r
- SetBits(t,SF_MOVETO,5);\r
- \r
- b = CountBits(x,0);\r
- b = CountBits(y,b);\r
- \r
- SetBits(t,b,5);\r
- SetBits(t,x,b);\r
- SetBits(t,y,b);\r
-\r
- if (s)\r
- { s->px = x;\r
- s->py = y;\r
- }\r
- return 0;\r
-}\r
-\r
-int ShapeSetStyle(LPTAG t,LPSHAPE s,U16 line,U16 fill0,U16 fill1)\r
-{ if ((!t)||(!s)) return -1;\r
- \r
- SetBits(t,0,1);\r
- SetBits(t,(line?SF_LINE:0)|(fill0?SF_FILL0:0)|(fill1?SF_FILL1:0),5);\r
-\r
- if (fill0) SetBits(t,fill0,s->bits.fill);\r
- if (fill1) SetBits(t,fill1,s->bits.fill);\r
- if (line) SetBits(t,line ,s->bits.line);\r
- \r
- return 0;\r
-}\r
-\r
-/* TODO: sometimes we want to set fillstyle 0, as that's the empty fill\r
- used for line drawings. At the moment, we can't, as 0 fill be considered\r
- nonexistent and therefore not set.\r
- these defines are a workaround (they also reduce the maximal number of\r
- fill styles to 32768)\r
- */\r
-#define FILL_RESET 0x8000\r
-#define LINE_RESET 0x8000\r
-int ShapeSetAll(LPTAG t,LPSHAPE s,S32 x,S32 y,U16 line,U16 fill0,U16 fill1)\r
-{ U8 b;\r
- if ((!t)||(!s)) return -1;\r
-\r
- SetBits(t,0,1);\r
- SetBits(t,SF_MOVETO|(line?SF_LINE:0)|(fill0?SF_FILL0:0)|(fill1?SF_FILL1:0),5);\r
-\r
- b = CountBits(x,0);\r
- b = CountBits(y,b);\r
- SetBits(t,b,5);\r
- SetBits(t,x,b);\r
- SetBits(t,y,b);\r
- s->px = x;\r
- s->py = y;\r
-\r
- if (fill0) SetBits(t,fill0,s->bits.fill);\r
- if (fill1) SetBits(t,fill1,s->bits.fill);\r
- if (line) SetBits(t,line ,s->bits.line);\r
- \r
- return 0;\r
-}\r
-\r
-int ShapeSetEnd(LPTAG t)\r
-{ if (!t) return -1;\r
- SetBits(t,0,6);\r
- ResetBitcount(t);\r
- return 0;\r
-}\r
-\r
-int ShapeSetLine(LPTAG t,LPSHAPE s,S32 x,S32 y)\r
-{ U8 b;\r
- if (!t) return -1;\r
- SetBits(t,3,2); // Straight Edge\r
-\r
- if ((!s)||((x!=0)&&(y!=0)))\r
- { b = CountBits(x,2);\r
- b = CountBits(y,b);\r
- if(b<2) \r
- b=2;\r
- SetBits(t, b-2, 4);\r
- SetBits(t,1,1);\r
- SetBits(t,x,b);\r
- SetBits(t,y,b);\r
- if (s)\r
- { s->px += x;\r
- s->py += y;\r
- }\r
- return 0;\r
- }\r
-\r
- if (x==0)\r
- { b = CountBits(y,2);\r
- if(b<2) \r
- b=2;\r
- SetBits(t, b-2, 4);\r
- SetBits(t,1,2);\r
- SetBits(t,y,b);\r
- s->py += y;\r
- }\r
- else\r
- { b = CountBits(x,2);\r
- if(b<2) \r
- b=2;\r
- SetBits(t, b-2, 4);\r
- SetBits(t,0,2);\r
- SetBits(t,x,b);\r
- s->px += x;\r
- }\r
- return 0;\r
-}\r
-\r
-int ShapeSetCurve(LPTAG t,LPSHAPE s,S32 x,S32 y,S32 ax,S32 ay)\r
-{ U8 b;\r
- if (!t) return -1;\r
-\r
- SetBits(t,2,2);\r
-\r
- b = CountBits(ax,2);\r
- b = CountBits(ay,b);\r
- b = CountBits(x,b);\r
- b = CountBits(y,b);\r
-\r
- SetBits(t,b-2,4);\r
- SetBits(t,x,b);\r
- SetBits(t,y,b);\r
- SetBits(t,ax,b);\r
- SetBits(t,ay,b);\r
-\r
- if (s)\r
- { s->px += x+ax;\r
- s->py += y+ay;\r
- }\r
- return 0;\r
-}\r
-\r
-int ShapeSetCircle(LPTAG t,LPSHAPE s,S32 x,S32 y,S32 rx,S32 ry)\r
-{ double C1 = 0.2930; \r
- double C2 = 0.4140; \r
- double begin = 0.7070; \r
-\r
- if (!t) return -1;\r
- \r
- ShapeSetMove(t,s,x+begin*rx,y+begin*ry);\r
- ShapeSetCurve(t,s, -C1*rx, C1*ry, -C2*rx, 0);\r
- ShapeSetCurve(t,s, -C2*rx, 0, -C1*rx, -C1*ry);\r
- ShapeSetCurve(t,s, -C1*rx, -C1*ry, 0, -C2*ry);\r
- ShapeSetCurve(t,s, 0, -C2*ry, C1*rx, -C1*ry);\r
- ShapeSetCurve(t,s, C1*rx, -C1*ry, C2*rx, 0);\r
- ShapeSetCurve(t,s, C2*rx, 0, C1*rx, C1*ry);\r
- ShapeSetCurve(t,s, C1*rx, C1*ry, 0, C2*ry);\r
- ShapeSetCurve(t,s, 0, C2*ry, -C1*rx, C1*ry);\r
- \r
- return 0;\r
-}\r
-\r
+/* swfshape.c
+
+ shape functions
+
+ Extension module for the rfxswf library.
+ Part of the swftools package.
+
+ Copyright (c) 2001 Rainer Böhme <rfxswf@reflex-studio.de>
+
+ This file is distributed under the GPL, see file COPYING for details
+
+*/
+
+#define SF_MOVETO 0x01
+#define SF_FILL0 0x02
+#define SF_FILL1 0x04
+#define SF_LINE 0x08
+#define SF_NEWSTYLE 0x10
+
+#define FILL_SOLID 0x00
+#define FILL_LINEAR 0x10 // Gradient
+#define FILL_RADIAL 0x12
+#define FILL_TILED 0x40 // Bitmap
+#define FILL_CLIPPED 0x41
+
+void ShapeFree(SHAPE * s)
+{ if (s)
+ { if (s->linestyle.data) free(s->linestyle.data);
+ s->linestyle.data = NULL;
+ s->linestyle.n = 0;
+ if (s->fillstyle.data) free(s->fillstyle.data);
+ s->fillstyle.data = NULL;
+ s->fillstyle.n = 0;
+ if (s->data) free(s->data);
+ s->data = NULL;
+ }
+ free(s);
+}
+
+int NewShape(SHAPE * * s)
+{ SHAPE * sh;
+ if (!s) return -1;
+ sh = (SHAPE *)malloc(sizeof(SHAPE)); s[0] = sh;
+ if (sh) memset(sh,0x00,sizeof(SHAPE));
+ return sh?0:-1;
+}
+
+int GetSimpleShape(TAG * t,SHAPE * * s) // without Linestyle/Fillstyle Record
+{ SHAPE * sh;
+ int bitl, len;
+ int end;
+ U32 pos;
+
+ if (FAILED(NewShape(s))) return -1;
+ sh = s[0];
+
+ ResetBitmask(t);
+ sh->bits.fill = (U16)GetBits(t,4);
+ sh->bits.line = (U16)GetBits(t,4);
+ bitl = 0; end = 0; pos = GetTagPos(t);
+
+ while (!end)
+ { int edge = GetBits(t,1); bitl+=1;
+ if (edge)
+ { bitl+=1;
+ if (GetBits(t,1)) // Line
+ { U16 nbits = GetBits(t,4)+2;
+ bitl+=5;
+
+ if (GetBits(t,1)) // x/y Line
+ { GetBits(t,nbits);
+ GetBits(t,nbits);
+ bitl+=nbits*2;
+ }
+ else // hline/vline
+ { GetBits(t,nbits+1);
+ bitl+=nbits+1;
+ }
+ }
+ else // Curve
+ { U16 nbits = GetBits(t,4)+2;
+ bitl+=4;
+
+ GetBits(t,nbits);
+ GetBits(t,nbits);
+ GetBits(t,nbits);
+ GetBits(t,nbits);
+
+ bitl+=4*nbits;
+ }
+ }
+ else
+ { U16 flags = GetBits(t,5); bitl+=5;
+ if (flags)
+ {
+ if (flags&SF_MOVETO)
+ { U16 nbits = GetBits(t,5); bitl+=5;
+ GetBits(t,nbits);
+ GetBits(t,nbits);
+ bitl+=2*nbits;
+ }
+
+ if (flags&SF_FILL0)
+ { GetBits(t,sh->bits.fill);
+ bitl+=sh->bits.fill;
+ }
+
+ if (flags&SF_FILL1)
+ { GetBits(t,sh->bits.fill);
+ bitl+=sh->bits.fill;
+ }
+
+ if (flags&SF_LINE)
+ { GetBits(t,sh->bits.line);
+ bitl+=sh->bits.line;
+ }
+
+ if (flags&SF_NEWSTYLE)
+ { fprintf(stderr,"Can't process extended styles in shape.\n");
+ }
+ }
+ else end = 1;
+ }
+ }
+ SetTagPos(t,pos);
+ len = (bitl+7)/8;
+
+ if (sh->data) free(sh->data);
+ sh->data = (U8*)malloc(len);
+
+ if (sh->data)
+ { sh->bitlen = bitl;
+ GetBlock(t,sh->data,len);
+ }
+ else return -1;
+
+ return len;
+}
+
+int SetSimpleShape(TAG * t,SHAPE * s) // without Linestyle/Fillstyle Record
+{ int l;
+
+ if (!s) return -1;
+ l = (s->bitlen+7)/8;
+
+ if (t)
+ { ResetBitcount(t);
+
+ SetBits(t,s->bits.fill,4);
+ SetBits(t,s->bits.line,4);
+ SetBlock(t,s->data,l);
+
+ ResetBitcount(t);
+ }
+ return l+1;
+}
+
+int SetFillStyle(TAG * t,FILLSTYLE * f)
+{ if ((!t)||(!f)) return -1;
+ SetU8(t,f->type);
+
+ // no gradients yet!
+
+ switch (f->type)
+ { case FILL_SOLID:
+ if (GetTagID(t)!=ST_DEFINESHAPE3) SetRGB(t,&f->color);
+ else SetRGBA(t,&f->color);
+ break;
+
+ case FILL_TILED:
+ case FILL_CLIPPED:
+ SetU16(t,f->id_bitmap);
+ SetMatrix(t,&f->m);
+ break;
+ }
+
+ return 0;
+}
+
+int SetLineStyle(TAG * t,LINESTYLE * l)
+{ if ((!l)||(!t)) return -1;
+ SetU16(t,l->width);
+
+ if (GetTagID(t)!=ST_DEFINESHAPE3) SetRGB(t,&l->color);
+ else SetRGBA(t,&l->color);
+
+ return 0;
+}
+
+int SetShapeStyleCount(TAG * t,U16 n)
+{ if (n>254)
+ { SetU8(t,0xff);
+ SetU16(t,n);
+ return 3;
+ }
+ else
+ { SetU8(t,n);
+ return 1;
+ }
+}
+
+int SetShapeStyles(TAG * t,SHAPE * s)
+{ int i,l;
+ if (!s) return -1;
+
+ l = 0;
+ l += SetShapeStyleCount(t,s->fillstyle.n);
+
+ for (i=0;i<s->fillstyle.n;i++)
+ l+=SetFillStyle(t,&s->fillstyle.data[i]);
+
+ l += SetShapeStyleCount(t,s->linestyle.n);
+
+ for (i=0;i<s->linestyle.n;i++)
+ l+=SetLineStyle(t,&s->linestyle.data[i]);
+
+ return l;
+}
+
+int ShapeCountBits(SHAPE * s,U8 * fbits,U8 * lbits)
+{ if (!s) return -1;
+
+ s->bits.fill = CountBits(s->fillstyle.n,0);
+ s->bits.line = CountBits(s->linestyle.n,0);
+
+ if (fbits) fbits[0] = s->bits.fill;
+ if (lbits) lbits[0] = s->bits.line;
+
+ return 0;
+}
+
+int SetShapeBits(TAG * t,SHAPE * s)
+{ if ((!t)||(!s)) return -1;
+ ResetBitcount(t);
+ SetBits(t,s->bits.fill,4);
+ SetBits(t,s->bits.line,4);
+ return 0;
+}
+
+int SetShapeHeader(TAG * t,SHAPE * s)
+{ int res;
+ res = SetShapeStyles(t,s);
+ if (res>=0) res = ShapeCountBits(s,NULL,NULL);
+ if (res>=0) res = SetShapeBits(t,s);
+ return res;
+}
+
+int ShapeExport(int handle,SHAPE * s) // without Linestyle/Fillstyle Record
+{ int l;
+ if (!s) return 0;
+
+ l = sizeof(SHAPE);
+
+ if (handle>=0)
+ if (write(handle,s,sizeof(SHAPE))!=sizeof(SHAPE)) return -1;
+
+ // Fillstyle, Linestyle ...
+
+ if (s->data)
+ { int ll = (s->bitlen+7)/8;
+ l+=ll;
+ if (handle>=0)
+ if (write(handle,s->data,ll)!=ll) return -1;
+ }
+
+ return l;
+}
+
+int ShapeImport(int handle,SHAPE * * shape)
+{ SHAPE * s;
+
+ if (handle<0) return -1;
+
+ s = (SHAPE *)malloc(sizeof(SHAPE)); shape[0] = s;
+ if (!s) return -1;
+
+ if (read(handle,s,sizeof(SHAPE))!=sizeof(SHAPE))
+ { shape[0] = NULL;
+ free(s);
+ return -1;
+ }
+
+ if (s->data)
+ { int ll = (s->bitlen+7)/8;
+ s->data = (U8*)malloc(ll);
+ if (!s->data)
+ { shape[0] = NULL;
+ free(s);
+ return -1;
+ }
+ if (read(handle,s->data,ll)!=ll)
+ { free(s->data);
+ free(s);
+ shape[0] = NULL;
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int ShapeAddFillStyle(SHAPE * s,U8 type,MATRIX * m,RGBA * color,U16 id_bitmap)
+{ RGBA def_c;
+ MATRIX def_m;
+
+ // handle defaults
+
+ if (!s) return -1;
+ if (!color)
+ { color = &def_c;
+ def_c.a = 0xff;
+ def_c.r = def_c.g = def_c.b = 0;
+ }
+ if (!m)
+ { m = &def_m;
+ GetMatrix(NULL,m);
+ }
+
+ // handle memory
+
+ if (s->fillstyle.data)
+ { FILLSTYLE * new = (FILLSTYLE *)realloc(s->fillstyle.data,(s->fillstyle.n+1)*sizeof(FILLSTYLE));
+ if (!new) return -1;
+ s->fillstyle.data = new;
+ }
+ else
+ { s->fillstyle.data = (FILLSTYLE *)malloc(sizeof(FILLSTYLE));
+ s->fillstyle.n = 0;
+ if (!s->fillstyle.data) return -1;
+ }
+
+ // set fillstyle (no gradients yet!)
+
+ s->fillstyle.data[s->fillstyle.n].type = type;
+ s->fillstyle.data[s->fillstyle.n].id_bitmap = id_bitmap;
+ memcpy(&s->fillstyle.data[s->fillstyle.n].m,m,sizeof(MATRIX));
+ memcpy(&s->fillstyle.data[s->fillstyle.n].color,color,sizeof(RGBA));
+
+ return (++s->fillstyle.n);
+}
+
+int ShapeAddSolidFillStyle(SHAPE * s,RGBA * color)
+{ return ShapeAddFillStyle(s,FILL_SOLID,NULL,color,0);
+}
+
+int ShapeAddBitmapFillStyle(SHAPE * s,MATRIX * m,U16 id_bitmap,int clip)
+{ return ShapeAddFillStyle(s,clip?FILL_CLIPPED:FILL_TILED,m,NULL,id_bitmap);
+}
+
+int ShapeAddLineStyle(SHAPE * s,U16 width,RGBA * color)
+{ RGBA def;
+ if (!s) return -1;
+ if (!color)
+ { color = &def;
+ def.a = 0xff;
+ def.r = def.g = def.b = 0;
+ }
+ if (s->linestyle.data)
+ { LINESTYLE * new = (LINESTYLE *)realloc(s->linestyle.data,(s->linestyle.n+1)*sizeof(LINESTYLE));
+ if (!new) return -1;
+ s->linestyle.data = new;
+ }
+ else
+ { s->linestyle.data = (LINESTYLE *)malloc(sizeof(LINESTYLE));
+ s->linestyle.n = 0;
+ if (!s->linestyle.data) return -1;
+ }
+
+ s->linestyle.data[s->linestyle.n].width = width;
+ memcpy(&s->linestyle.data[s->linestyle.n].color,color,sizeof(RGBA));
+
+ return (++s->linestyle.n);
+}
+
+int ShapeSetMove(TAG * t,SHAPE * s,S32 x,S32 y)
+{ U8 b;
+ if (!t) return -1;
+ SetBits(t,0,1);
+ SetBits(t,SF_MOVETO,5);
+
+ b = CountBits(x,0);
+ b = CountBits(y,b);
+
+ SetBits(t,b,5);
+ SetBits(t,x,b);
+ SetBits(t,y,b);
+
+ if (s)
+ { s->px = x;
+ s->py = y;
+ }
+ return 0;
+}
+
+int ShapeSetStyle(TAG * t,SHAPE * s,U16 line,U16 fill0,U16 fill1)
+{ if ((!t)||(!s)) return -1;
+
+ SetBits(t,0,1);
+ SetBits(t,(line?SF_LINE:0)|(fill0?SF_FILL0:0)|(fill1?SF_FILL1:0),5);
+
+ if (fill0) SetBits(t,fill0,s->bits.fill);
+ if (fill1) SetBits(t,fill1,s->bits.fill);
+ if (line) SetBits(t,line ,s->bits.line);
+
+ return 0;
+}
+
+/* TODO: sometimes we want to set fillstyle 0, as that's the empty fill
+ used for line drawings. At the moment, we can't, as 0 fill be considered
+ nonexistent and therefore not set.
+ these defines are a workaround (they also reduce the maximal number of
+ fill styles to 32768)
+ */
+#define FILL_RESET 0x8000
+#define LINE_RESET 0x8000
+int ShapeSetAll(TAG * t,SHAPE * s,S32 x,S32 y,U16 line,U16 fill0,U16 fill1)
+{ U8 b;
+ if ((!t)||(!s)) return -1;
+
+ SetBits(t,0,1);
+ SetBits(t,SF_MOVETO|(line?SF_LINE:0)|(fill0?SF_FILL0:0)|(fill1?SF_FILL1:0),5);
+
+ b = CountBits(x,0);
+ b = CountBits(y,b);
+ SetBits(t,b,5);
+ SetBits(t,x,b);
+ SetBits(t,y,b);
+ s->px = x;
+ s->py = y;
+
+ if (fill0) SetBits(t,fill0,s->bits.fill);
+ if (fill1) SetBits(t,fill1,s->bits.fill);
+ if (line) SetBits(t,line ,s->bits.line);
+
+ return 0;
+}
+
+int ShapeSetEnd(TAG * t)
+{ if (!t) return -1;
+ SetBits(t,0,6);
+ ResetBitcount(t);
+ return 0;
+}
+
+int ShapeSetLine(TAG * t,SHAPE * s,S32 x,S32 y)
+{ U8 b;
+ if (!t) return -1;
+ SetBits(t,3,2); // Straight Edge
+
+ if ((!s)||((x!=0)&&(y!=0)))
+ { b = CountBits(x,2);
+ b = CountBits(y,b);
+ if(b<2)
+ b=2;
+ SetBits(t, b-2, 4);
+ SetBits(t,1,1);
+ SetBits(t,x,b);
+ SetBits(t,y,b);
+ if (s)
+ { s->px += x;
+ s->py += y;
+ }
+ return 0;
+ }
+
+ if (x==0)
+ { b = CountBits(y,2);
+ if(b<2)
+ b=2;
+ SetBits(t, b-2, 4);
+ SetBits(t,1,2);
+ SetBits(t,y,b);
+ s->py += y;
+ }
+ else
+ { b = CountBits(x,2);
+ if(b<2)
+ b=2;
+ SetBits(t, b-2, 4);
+ SetBits(t,0,2);
+ SetBits(t,x,b);
+ s->px += x;
+ }
+ return 0;
+}
+
+int ShapeSetCurve(TAG * t,SHAPE * s,S32 x,S32 y,S32 ax,S32 ay)
+{ U8 b;
+ if (!t) return -1;
+
+ SetBits(t,2,2);
+
+ b = CountBits(ax,2);
+ b = CountBits(ay,b);
+ b = CountBits(x,b);
+ b = CountBits(y,b);
+
+ SetBits(t,b-2,4);
+ SetBits(t,x,b);
+ SetBits(t,y,b);
+ SetBits(t,ax,b);
+ SetBits(t,ay,b);
+
+ if (s)
+ { s->px += x+ax;
+ s->py += y+ay;
+ }
+ return 0;
+}
+
+int ShapeSetCircle(TAG * t,SHAPE * s,S32 x,S32 y,S32 rx,S32 ry)
+{ double C1 = 0.2930;
+ double C2 = 0.4140;
+ double begin = 0.7070;
+
+ if (!t) return -1;
+
+ ShapeSetMove(t,s,x+begin*rx,y+begin*ry);
+ ShapeSetCurve(t,s, -C1*rx, C1*ry, -C2*rx, 0);
+ ShapeSetCurve(t,s, -C2*rx, 0, -C1*rx, -C1*ry);
+ ShapeSetCurve(t,s, -C1*rx, -C1*ry, 0, -C2*ry);
+ ShapeSetCurve(t,s, 0, -C2*ry, C1*rx, -C1*ry);
+ ShapeSetCurve(t,s, C1*rx, -C1*ry, C2*rx, 0);
+ ShapeSetCurve(t,s, C2*rx, 0, C1*rx, C1*ry);
+ ShapeSetCurve(t,s, C1*rx, C1*ry, 0, C2*ry);
+ ShapeSetCurve(t,s, 0, C2*ry, -C1*rx, C1*ry);
+
+ return 0;
+}
+
-/* swftext.c\r
-\r
- Text and font routines\r
- \r
- Extension module for the rfxswf library.\r
- Part of the swftools package.\r
-\r
- Copyright (c) 2001 Rainer Böhme <rfxswf@reflex-studio.de>\r
- \r
- This file is distributed under the GPL, see file COPYING for details \r
-\r
-*/\r
-\r
-#define TF_TEXTCONTROL 0x80\r
-#define TF_HASFONT 0x08\r
-#define TF_HASCOLOR 0x04\r
-#define TF_HASYOFFSET 0x02\r
-#define TF_HASXOFFSET 0x01\r
-\r
-#define FF_WIDECODES 0x01\r
-#define FF_BOLD 0x02\r
-#define FF_ITALIC 0x04\r
-#define FF_ANSI 0x08\r
-#define FF_SHIFTJIS 0x10\r
-#define FF_UNICODE 0x20\r
-\r
-int FontEnumerate(LPSWF swf,void (*FontCallback) (U16,U8*))\r
-{ int n;\r
- LPTAG t;\r
- if (!swf) return -1;\r
- t = swf->FirstTag;\r
- n = 0;\r
-\r
- while (t)\r
- { if (GetTagID(t)==ST_DEFINEFONTINFO)\r
- { n++;\r
- if (FontCallback)\r
- { U16 id;\r
- int l;\r
- U8 s[257];\r
- SaveTagPos(t);\r
- SetTagPos(t,0);\r
-\r
- id = GetU16(t);\r
- l = GetU8(t);\r
- GetBlock(t,s,l);\r
- s[l] = 0;\r
-\r
- (FontCallback)(id,s); \r
- \r
- RestoreTagPos(t);\r
- }\r
- }\r
- t = NextTag(t);\r
- }\r
- return n;\r
-}\r
-\r
-int FontExtract_DefineFont(int id,LPSWFFONT f,LPTAG t,LPSHAPE * shapes)\r
-{ U16 fid;\r
- SaveTagPos(t);\r
- SetTagPos(t,0);\r
-\r
- fid = GetU16(t);\r
- if ((!id)||(id==fid))\r
- { U16 ofs[MAX_CHAR_PER_FONT];\r
- int n,i;\r
- \r
- id = fid;\r
- f->id = fid;\r
-\r
- ofs[0] = GetU16(t);\r
- n = ofs[0]/2;\r
-\r
- for (i=1;i<n;i++) if (i<MAX_CHAR_PER_FONT) ofs[i] = GetU16(t); else GetU16(t);\r
- for (i=0;i<n;i++) if (i<MAX_CHAR_PER_FONT) GetSimpleShape(t,&shapes[i]);\r
- \r
- }\r
-\r
- RestoreTagPos(t);\r
- return id;\r
-}\r
-\r
-int FontExtract_DefineFontInfo(int id,LPSWFFONT f,LPTAG t,LPSHAPE * shapes)\r
-{ U16 fid;\r
- SaveTagPos(t);\r
- SetTagPos(t,0);\r
-\r
- fid = GetU16(t);\r
- if (fid==id)\r
- { U8 l = GetU8(t);\r
- int i;\r
- \r
- if (l)\r
- { if (f->name) free(f->name);\r
- f->name = (U8*)malloc(l+1);\r
- if (f->name)\r
- { GetBlock(t,f->name,l);\r
- f->name[l] = 0;\r
- }\r
- else\r
- { RestoreTagPos(t);\r
- return -1;\r
- }\r
- }\r
- f->flags = GetU8(t);\r
-\r
- i = 0;\r
- while (shapes[i])\r
- { U16 code = ((f->flags&FF_WIDECODES)?GetU16(t):GetU8(t))%MAX_CHAR_PER_FONT;\r
- \r
- f->glyph[code].shape = shapes[i];\r
- f->glyph[code].gid = i;\r
- if (i<MAX_CHAR_PER_FONT) f->codes[i] = code;\r
-\r
- i++;\r
- }\r
- }\r
-\r
- RestoreTagPos(t);\r
- return id;\r
-}\r
-\r
-#define FEDTJ_PRINT 0x01\r
-#define FEDTJ_MODIFY 0x02\r
-\r
-int FontExtract_DefineText(int id,LPSWFFONT f,LPTAG t,int jobs)\r
-{ U16 cid;\r
- SRECT r;\r
- MATRIX m;\r
- U8 gbits, abits, flags;\r
- int fid;\r
-\r
- fid = 0;\r
-\r
- SaveTagPos(t);\r
- SetTagPos(t,0);\r
-\r
- cid = GetU16(t);\r
- GetRect(t,&r);\r
- GetMatrix(t,&m);\r
- gbits = GetU8(t);\r
- abits = GetU8(t);\r
-\r
- flags = GetU8(t);\r
- \r
- while(flags)\r
- { if (flags&TF_TEXTCONTROL)\r
- { if (flags&TF_HASFONT) fid = GetU16(t);\r
- if (flags&TF_HASCOLOR)\r
- { GetU8(t); // rgb\r
- GetU8(t);\r
- GetU8(t);\r
- if (GetTagID(t)==ST_DEFINETEXT2) GetU8(t);\r
- }\r
- if (flags&TF_HASXOFFSET) GetS16(t);\r
- if (flags&TF_HASYOFFSET) GetS16(t);\r
- if (flags&TF_HASFONT) GetU16(t);\r
- }\r
- else\r
- { int i;\r
- for (i=0;i<flags;i++)\r
- { int glyph;\r
- int adv;\r
- glyph = GetBits(t,gbits);\r
- adv = GetBits(t,abits);\r
- if (id==fid) // mitlesen ?\r
- { int code = f->codes[glyph];\r
- if (jobs&FEDTJ_PRINT) printf("%c",code);\r
- if (jobs&FEDTJ_MODIFY)\r
- /*if (f->glyph[code].advance)*/ f->glyph[code].advance = adv;\r
- }\r
- }\r
- if ((id==fid)&&(jobs&FEDTJ_PRINT)) printf("\n");\r
- }\r
- flags = GetU8(t);\r
- }\r
- \r
- RestoreTagPos(t);\r
- return id;\r
-} \r
-\r
-int FontExtract(LPSWF swf,int id,LPSWFFONT * font)\r
-{ LPTAG t;\r
- LPSWFFONT f;\r
- LPSHAPE shapes[MAX_CHAR_PER_FONT];\r
- \r
- if ((!swf)||(!font)) return -1;\r
-\r
- f = (LPSWFFONT)malloc(sizeof(SWFFONT)); font[0] = f;\r
- if (!f) return -1;\r
- \r
- memset(shapes,0x00,sizeof(shapes));\r
- memset(f,0x00,sizeof(SWFFONT));\r
-\r
- t = swf->FirstTag;\r
-\r
- while (t)\r
- { int nid = 0;\r
- switch (GetTagID(t))\r
- { case ST_DEFINEFONT:\r
- nid = FontExtract_DefineFont(id,f,t,shapes);\r
- break;\r
- \r
- case ST_DEFINEFONTINFO:\r
- nid = FontExtract_DefineFontInfo(id,f,t,shapes);\r
- break;\r
- \r
- case ST_DEFINETEXT:\r
- case ST_DEFINETEXT2:\r
- nid = FontExtract_DefineText(id,f,t,FEDTJ_MODIFY);\r
- break;\r
- }\r
- if (nid>0) id = nid;\r
- t = NextTag(t);\r
- }\r
- return 0;\r
-}\r
-\r
-int FontIsItalic(LPSWFFONT f) { return f->flags&FF_ITALIC; }\r
-int FontIsBold(LPSWFFONT f) { return f->flags&FF_BOLD; }\r
-\r
-int FontSetID(LPSWFFONT f,U16 id) { if (!f) return -1; f->id = id; return 0; }\r
-\r
-int FontReduce(LPSWFFONT f,LPFONTUSAGE use)\r
-{ int i,j;\r
- if ((!f)||(!use)) return -1;\r
-\r
- memset(&f->codes,0x00,sizeof(f->codes));\r
-\r
- j = 0;\r
- for (i=0;i<MAX_CHAR_PER_FONT;i++)\r
- if (f->glyph[i].shape)\r
- { if (use->code[i])\r
- { f->glyph[i].gid = j;\r
- f->codes[j] = i;\r
- j++;\r
- }\r
- else\r
- { ShapeFree(f->glyph[i].shape);\r
- f->glyph[i].shape = 0;\r
- f->glyph[i].gid = 0;\r
- f->glyph[i].advance = 0;\r
- }\r
- } else f->glyph[i].gid = 0;\r
- \r
- return j;\r
-}\r
-\r
-int FontInitUsage(LPFONTUSAGE use)\r
-{ if (!use) return -1;\r
- memset(&use->code,0x00,sizeof(use->code));\r
- return 0;\r
-}\r
-\r
-int FontUse(LPFONTUSAGE use,U8 * s)\r
-{ if ((!use)||(!s)) return -1;\r
- while (s[0])\r
- { use->code[s[0]] = 1;\r
- s++;\r
- }\r
- return 0; \r
-}\r
-\r
-int FontSetDefine(LPTAG t,LPSWFFONT f)\r
-{ U16 ofs[MAX_CHAR_PER_FONT];\r
- int p,i,j;\r
- \r
- if ((!t)||(!f)) return -1;\r
- ResetBitcount(t);\r
- SetU16(t,f->id);\r
-\r
- p = 0; j = 0;\r
- for (i=0;i<MAX_CHAR_PER_FONT;i++)\r
- if (f->glyph[i].shape)\r
- { ofs[j++] = p;\r
- p+=SetSimpleShape(NULL,f->glyph[i].shape);\r
- }\r
-\r
- for (i=0;i<j;i++) SetU16(t,ofs[i]+j*2);\r
- \r
- for (i=0;i<MAX_CHAR_PER_FONT;i++)\r
- if (f->glyph[i].shape)\r
- SetSimpleShape(t,f->glyph[i].shape);\r
- \r
- ResetBitcount(t);\r
- return 0;\r
-}\r
-\r
-int FontSetInfo(LPTAG t,LPSWFFONT f)\r
-{ int l,i;\r
- if ((!t)||(!f)) return -1;\r
- ResetBitcount(t);\r
- SetU16(t,f->id);\r
- l = strlen(f->name); if (l>255) l = 255;\r
- SetU8(t,l);\r
- SetBlock(t,f->name,l);\r
- SetU8(t,f->flags&0xfe); // no Wide-Codes\r
-\r
- for (i=0;i<MAX_CHAR_PER_FONT;i++)\r
- if (f->glyph[i].shape)\r
- SetU8(t,i);\r
- \r
- return 0;\r
-}\r
-\r
-int FontExport(int handle,LPSWFFONT f)\r
-{ int l;\r
- int i;\r
- if (!f) return 0;\r
-\r
- l = sizeof(SWFFONT);\r
- if (handle>=0)\r
- if (write(handle,f,sizeof(SWFFONT))!=sizeof(SWFFONT)) return -1;\r
-\r
- if (f->name)\r
- { U16 ln = strlen(f->name);\r
- l+=2+ln;\r
- if (handle>=0)\r
- { if (write(handle,&ln,2)!=2) return -1;\r
- if (write(handle,f->name,ln)!=ln) return -1;\r
- }\r
- }\r
-\r
- if (f->layout)\r
- { l+=sizeof(SWFLAYOUT);\r
- if (handle>=0)\r
- if (write(handle,f->layout,sizeof(SWFLAYOUT))!=sizeof(SWFLAYOUT)) return -1;\r
- if (f->layout->kerning.data)\r
- { l+=f->layout->kerning.count*4;\r
- if (handle>=0)\r
- if (write(handle,f->layout->kerning.data,f->layout->kerning.count*4)!=f->layout->kerning.count*4) return -1;\r
- }\r
- }\r
-\r
- for (i=0;i<MAX_CHAR_PER_FONT;i++)\r
- { if (f->glyph[i].shape)\r
- { int ll = ShapeExport(handle,f->glyph[i].shape);\r
- if (ll<0) return -1;\r
- l+=ll;\r
- } \r
- }\r
-\r
- return l;\r
-}\r
-\r
-int FontImport(int handle,LPSWFFONT * font)\r
-{ LPSWFFONT f;\r
- int layout;\r
- int i = 0;\r
-\r
- if ((!font)||(handle<0)) return -1;\r
-\r
- f = (LPSWFFONT)malloc(sizeof(SWFFONT)); font[0] = f;\r
- if (!f) return -1;\r
-\r
- memset(f,0x00,sizeof(SWFFONT));\r
- \r
- if (read(handle,f,sizeof(SWFFONT))!=sizeof(SWFFONT)) goto fehler;\r
-\r
- layout = (f->layout)?1:0; // avoid illegal free()\r
- f->layout = NULL;\r
-\r
- if (f->name)\r
- { U16 ln;\r
- f->name = NULL;\r
- if (read(handle,&ln,2)!=2) goto fehler;\r
- f->name = (U8*)malloc(ln+1);\r
- if (!f->name) goto fehler;\r
- if (read(handle,f->name,ln)!=ln) goto fehler;\r
- f->name[ln] = 0;\r
- }\r
-\r
- if (f->layout)\r
- { f->layout = (LPSWFLAYOUT)malloc(sizeof(SWFLAYOUT));\r
- if (!f->layout) goto fehler;\r
- if (read(handle,f->layout,sizeof(SWFLAYOUT))!=sizeof(SWFLAYOUT)) goto fehler;\r
- if (f->layout->kerning.data)\r
- { int l = f->layout->kerning.count*4;\r
- f->layout->kerning.data = (U8*)malloc(l);\r
- if (!f->layout->kerning.data) goto fehler;\r
- if (read(handle,f->layout->kerning.data,l)!=l) goto fehler;\r
- }\r
- }\r
-\r
- for (i=0;i<MAX_CHAR_PER_FONT;i++)\r
- { if (f->glyph[i].shape)\r
- { if (ShapeImport(handle,&f->glyph[i].shape)<0) goto fehler;\r
- }\r
- }\r
-\r
- f->id = 0;\r
- \r
- return 0;\r
- \r
-fehler:\r
- if (f) for (;i<MAX_CHAR_PER_FONT;i++) f->glyph[i].shape = NULL;\r
- FontFree(f);\r
- font[0] = NULL;\r
- return -1;\r
-}\r
-\r
-int TextPrintDefineText(LPTAG t,LPSWFFONT f)\r
-{ int id = GetTagID(t);\r
- if ((id==ST_DEFINETEXT)||(id==ST_DEFINETEXT2)) FontExtract_DefineText(f->id,f,t,FEDTJ_PRINT);\r
- else return -1;\r
- return 0;\r
-}\r
-\r
-void LayoutFree(LPSWFLAYOUT l)\r
-{ if (l)\r
- { if (l->kerning.data) free(l->kerning.data);\r
- l->kerning.data = NULL;\r
- }\r
- free(l);\r
-}\r
-\r
-void FontFree(LPSWFFONT f)\r
-{ if (f)\r
- { int i;\r
- \r
- if (f->name) free(f->name);\r
- if (f->layout) LayoutFree(f->layout);\r
-\r
- f->name = NULL;\r
- f->layout = NULL;\r
-\r
- for (i=0;i<MAX_CHAR_PER_FONT;i++)\r
- if (f->glyph[i].shape)\r
- { ShapeFree(f->glyph[i].shape);\r
- f->glyph[i].shape = NULL;\r
- }\r
- }\r
- free(f);\r
-}\r
-\r
-int TextSetInfoRecord(LPTAG t,LPSWFFONT font,U16 size,LPRGBA color,S16 dx,S16 dy)\r
-{ U8 flags;\r
- if (!t) return -1;\r
-\r
- flags = TF_TEXTCONTROL|(font?TF_HASFONT:0)|(color?TF_HASCOLOR:0)|(dx?TF_HASXOFFSET:0)|(dy?TF_HASYOFFSET:0);\r
-\r
- SetU8(t,flags);\r
- if (font) SetU16(t,font->id);\r
- if (color)\r
- { if (GetTagID(t)==ST_DEFINETEXT2) SetRGBA(t,color);\r
- else SetRGB(t,color);\r
- }\r
- if (dx) SetS16(t,dx);\r
- if (dy) SetS16(t,dy);\r
- if (font) SetU16(t,size);\r
- \r
- return 0;\r
-}\r
-\r
-int TextCountBits(LPSWFFONT font,U8 * s,int scale,U8 * gbits,U8 * abits)\r
-{ U16 g,a;\r
- if ((!s)||(!font)||((!gbits)&&(!abits))) return -1;\r
- g = a = 0;\r
-\r
- while(s[0])\r
- { g = CountBits(font->glyph[s[0]].gid,g);\r
- a = CountBits((((U32)font->glyph[s[0]].advance)*scale)/100,a);\r
- s++;\r
- }\r
-\r
- if (gbits) gbits[0] = (U8)g;\r
- if (abits) abits[0] = (U8)a;\r
-\r
- return 0;\r
-}\r
-\r
-int TextSetCharRecord(LPTAG t,LPSWFFONT font,U8 * s,int scale,U8 gbits,U8 abits)\r
-{ int l,i;\r
- \r
- if ((!t)||(!font)||(!s)) return -1;\r
-\r
- l = strlen(s);\r
- if (l>0x7f) l = 0x7f;\r
- SetU8(t,l);\r
-\r
- for (i=0;i<l;i++)\r
- { SetBits(t,font->glyph[s[i]].gid,gbits);\r
- SetBits(t,(((U32)font->glyph[s[i]].advance)*scale)/100,abits);\r
- }\r
-\r
- ResetBitcount(t);\r
- return 0;\r
-}\r
-\r
-U32 TextGetWidth(LPSWFFONT font,U8 * s,int scale)\r
-{ U32 res = 0;\r
-\r
- if (font&&s)\r
- { while (s[0])\r
- { res += font->glyph[s[0]].advance;\r
- s++;\r
- }\r
- if (scale) res = (res*scale)/100;\r
- }\r
- \r
- return res;\r
-}\r
+/* swftext.c
+
+ Text and font routines
+
+ Extension module for the rfxswf library.
+ Part of the swftools package.
+
+ Copyright (c) 2001 Rainer Böhme <rfxswf@reflex-studio.de>
+
+ This file is distributed under the GPL, see file COPYING for details
+
+*/
+
+#define TF_TEXTCONTROL 0x80
+#define TF_HASFONT 0x08
+#define TF_HASCOLOR 0x04
+#define TF_HASYOFFSET 0x02
+#define TF_HASXOFFSET 0x01
+
+#define FF_WIDECODES 0x01
+#define FF_BOLD 0x02
+#define FF_ITALIC 0x04
+#define FF_ANSI 0x08
+#define FF_SHIFTJIS 0x10
+#define FF_UNICODE 0x20
+
+int FontEnumerate(SWF * swf,void (*FontCallback) (U16,U8*))
+{ int n;
+ TAG * t;
+ if (!swf) return -1;
+ t = swf->FirstTag;
+ n = 0;
+
+ while (t)
+ { if (GetTagID(t)==ST_DEFINEFONTINFO)
+ { n++;
+ if (FontCallback)
+ { U16 id;
+ int l;
+ U8 s[257];
+ SaveTagPos(t);
+ SetTagPos(t,0);
+
+ id = GetU16(t);
+ l = GetU8(t);
+ GetBlock(t,s,l);
+ s[l] = 0;
+
+ (FontCallback)(id,s);
+
+ RestoreTagPos(t);
+ }
+ }
+ t = NextTag(t);
+ }
+ return n;
+}
+
+int FontExtract_DefineFont(int id,SWFFONT * f,TAG * t,SHAPE * * shapes)
+{ U16 fid;
+ SaveTagPos(t);
+ SetTagPos(t,0);
+
+ fid = GetU16(t);
+ if ((!id)||(id==fid))
+ { U16 ofs[MAX_CHAR_PER_FONT];
+ int n,i;
+
+ id = fid;
+ f->id = fid;
+
+ ofs[0] = GetU16(t);
+ n = ofs[0]/2;
+
+ for (i=1;i<n;i++) if (i<MAX_CHAR_PER_FONT) ofs[i] = GetU16(t); else GetU16(t);
+ for (i=0;i<n;i++) if (i<MAX_CHAR_PER_FONT) GetSimpleShape(t,&shapes[i]);
+
+ }
+
+ RestoreTagPos(t);
+ return id;
+}
+
+int FontExtract_DefineFontInfo(int id,SWFFONT * f,TAG * t,SHAPE * * shapes)
+{ U16 fid;
+ SaveTagPos(t);
+ SetTagPos(t,0);
+
+ fid = GetU16(t);
+ if (fid==id)
+ { U8 l = GetU8(t);
+ int i;
+
+ if (l)
+ { if (f->name) free(f->name);
+ f->name = (U8*)malloc(l+1);
+ if (f->name)
+ { GetBlock(t,f->name,l);
+ f->name[l] = 0;
+ }
+ else
+ { RestoreTagPos(t);
+ return -1;
+ }
+ }
+ f->flags = GetU8(t);
+
+ i = 0;
+ while (shapes[i])
+ { U16 code = ((f->flags&FF_WIDECODES)?GetU16(t):GetU8(t))%MAX_CHAR_PER_FONT;
+
+ f->glyph[code].shape = shapes[i];
+ f->glyph[code].gid = i;
+ if (i<MAX_CHAR_PER_FONT) f->codes[i] = code;
+
+ i++;
+ }
+ }
+
+ RestoreTagPos(t);
+ return id;
+}
+
+#define FEDTJ_PRINT 0x01
+#define FEDTJ_MODIFY 0x02
+
+int FontExtract_DefineText(int id,SWFFONT * f,TAG * t,int jobs)
+{ U16 cid;
+ SRECT r;
+ MATRIX m;
+ U8 gbits, abits, flags;
+ int fid;
+
+ fid = 0;
+
+ SaveTagPos(t);
+ SetTagPos(t,0);
+
+ cid = GetU16(t);
+ GetRect(t,&r);
+ GetMatrix(t,&m);
+ gbits = GetU8(t);
+ abits = GetU8(t);
+
+ flags = GetU8(t);
+
+ while(flags)
+ { if (flags&TF_TEXTCONTROL)
+ { if (flags&TF_HASFONT) fid = GetU16(t);
+ if (flags&TF_HASCOLOR)
+ { GetU8(t); // rgb
+ GetU8(t);
+ GetU8(t);
+ if (GetTagID(t)==ST_DEFINETEXT2) GetU8(t);
+ }
+ if (flags&TF_HASXOFFSET) GetS16(t);
+ if (flags&TF_HASYOFFSET) GetS16(t);
+ if (flags&TF_HASFONT) GetU16(t);
+ }
+ else
+ { int i;
+ for (i=0;i<flags;i++)
+ { int glyph;
+ int adv;
+ glyph = GetBits(t,gbits);
+ adv = GetBits(t,abits);
+ if (id==fid) // mitlesen ?
+ { int code = f->codes[glyph];
+ if (jobs&FEDTJ_PRINT) printf("%c",code);
+ if (jobs&FEDTJ_MODIFY)
+ /*if (f->glyph[code].advance)*/ f->glyph[code].advance = adv;
+ }
+ }
+ if ((id==fid)&&(jobs&FEDTJ_PRINT)) printf("\n");
+ }
+ flags = GetU8(t);
+ }
+
+ RestoreTagPos(t);
+ return id;
+}
+
+int FontExtract(SWF * swf,int id,SWFFONT * * font)
+{ TAG * t;
+ SWFFONT * f;
+ SHAPE * shapes[MAX_CHAR_PER_FONT];
+
+ if ((!swf)||(!font)) return -1;
+
+ f = (SWFFONT *)malloc(sizeof(SWFFONT)); font[0] = f;
+ if (!f) return -1;
+
+ memset(shapes,0x00,sizeof(shapes));
+ memset(f,0x00,sizeof(SWFFONT));
+
+ t = swf->FirstTag;
+
+ while (t)
+ { int nid = 0;
+ switch (GetTagID(t))
+ { case ST_DEFINEFONT:
+ nid = FontExtract_DefineFont(id,f,t,shapes);
+ break;
+
+ case ST_DEFINEFONTINFO:
+ nid = FontExtract_DefineFontInfo(id,f,t,shapes);
+ break;
+
+ case ST_DEFINETEXT:
+ case ST_DEFINETEXT2:
+ nid = FontExtract_DefineText(id,f,t,FEDTJ_MODIFY);
+ break;
+ }
+ if (nid>0) id = nid;
+ t = NextTag(t);
+ }
+ return 0;
+}
+
+int FontIsItalic(SWFFONT * f) { return f->flags&FF_ITALIC; }
+int FontIsBold(SWFFONT * f) { return f->flags&FF_BOLD; }
+
+int FontSetID(SWFFONT * f,U16 id) { if (!f) return -1; f->id = id; return 0; }
+
+int FontReduce(SWFFONT * f,FONTUSAGE * use)
+{ int i,j;
+ if ((!f)||(!use)) return -1;
+
+ memset(&f->codes,0x00,sizeof(f->codes));
+
+ j = 0;
+ for (i=0;i<MAX_CHAR_PER_FONT;i++)
+ if (f->glyph[i].shape)
+ { if (use->code[i])
+ { f->glyph[i].gid = j;
+ f->codes[j] = i;
+ j++;
+ }
+ else
+ { ShapeFree(f->glyph[i].shape);
+ f->glyph[i].shape = 0;
+ f->glyph[i].gid = 0;
+ f->glyph[i].advance = 0;
+ }
+ } else f->glyph[i].gid = 0;
+
+ return j;
+}
+
+int FontInitUsage(FONTUSAGE * use)
+{ if (!use) return -1;
+ memset(&use->code,0x00,sizeof(use->code));
+ return 0;
+}
+
+int FontUse(FONTUSAGE * use,U8 * s)
+{ if ((!use)||(!s)) return -1;
+ while (s[0])
+ { use->code[s[0]] = 1;
+ s++;
+ }
+ return 0;
+}
+
+int FontSetDefine(TAG * t,SWFFONT * f)
+{ U16 ofs[MAX_CHAR_PER_FONT];
+ int p,i,j;
+
+ if ((!t)||(!f)) return -1;
+ ResetBitcount(t);
+ SetU16(t,f->id);
+
+ p = 0; j = 0;
+ for (i=0;i<MAX_CHAR_PER_FONT;i++)
+ if (f->glyph[i].shape)
+ { ofs[j++] = p;
+ p+=SetSimpleShape(NULL,f->glyph[i].shape);
+ }
+
+ for (i=0;i<j;i++) SetU16(t,ofs[i]+j*2);
+
+ for (i=0;i<MAX_CHAR_PER_FONT;i++)
+ if (f->glyph[i].shape)
+ SetSimpleShape(t,f->glyph[i].shape);
+
+ ResetBitcount(t);
+ return 0;
+}
+
+int FontSetInfo(TAG * t,SWFFONT * f)
+{ int l,i;
+ if ((!t)||(!f)) return -1;
+ ResetBitcount(t);
+ SetU16(t,f->id);
+ l = strlen(f->name); if (l>255) l = 255;
+ SetU8(t,l);
+ SetBlock(t,f->name,l);
+ SetU8(t,f->flags&0xfe); // no Wide-Codes
+
+ for (i=0;i<MAX_CHAR_PER_FONT;i++)
+ if (f->glyph[i].shape)
+ SetU8(t,i);
+
+ return 0;
+}
+
+int FontExport(int handle,SWFFONT * f)
+{ int l;
+ int i;
+ if (!f) return 0;
+
+ l = sizeof(SWFFONT);
+ if (handle>=0)
+ if (write(handle,f,sizeof(SWFFONT))!=sizeof(SWFFONT)) return -1;
+
+ if (f->name)
+ { U16 ln = strlen(f->name);
+ l+=2+ln;
+ if (handle>=0)
+ { if (write(handle,&ln,2)!=2) return -1;
+ if (write(handle,f->name,ln)!=ln) return -1;
+ }
+ }
+
+ if (f->layout)
+ { l+=sizeof(SWFLAYOUT);
+ if (handle>=0)
+ if (write(handle,f->layout,sizeof(SWFLAYOUT))!=sizeof(SWFLAYOUT)) return -1;
+ if (f->layout->kerning.data)
+ { l+=f->layout->kerning.count*4;
+ if (handle>=0)
+ if (write(handle,f->layout->kerning.data,f->layout->kerning.count*4)!=f->layout->kerning.count*4) return -1;
+ }
+ }
+
+ for (i=0;i<MAX_CHAR_PER_FONT;i++)
+ { if (f->glyph[i].shape)
+ { int ll = ShapeExport(handle,f->glyph[i].shape);
+ if (ll<0) return -1;
+ l+=ll;
+ }
+ }
+
+ return l;
+}
+
+int FontImport(int handle,SWFFONT * * font)
+{ SWFFONT * f;
+ int layout;
+ int i = 0;
+
+ if ((!font)||(handle<0)) return -1;
+
+ f = (SWFFONT *)malloc(sizeof(SWFFONT)); font[0] = f;
+ if (!f) return -1;
+
+ memset(f,0x00,sizeof(SWFFONT));
+
+ if (read(handle,f,sizeof(SWFFONT))!=sizeof(SWFFONT)) goto fehler;
+
+ layout = (f->layout)?1:0; // avoid illegal free()
+ f->layout = NULL;
+
+ if (f->name)
+ { U16 ln;
+ f->name = NULL;
+ if (read(handle,&ln,2)!=2) goto fehler;
+ f->name = (U8*)malloc(ln+1);
+ if (!f->name) goto fehler;
+ if (read(handle,f->name,ln)!=ln) goto fehler;
+ f->name[ln] = 0;
+ }
+
+ if (f->layout)
+ { f->layout = (SWFLAYOUT *)malloc(sizeof(SWFLAYOUT));
+ if (!f->layout) goto fehler;
+ if (read(handle,f->layout,sizeof(SWFLAYOUT))!=sizeof(SWFLAYOUT)) goto fehler;
+ if (f->layout->kerning.data)
+ { int l = f->layout->kerning.count*4;
+ f->layout->kerning.data = (U8*)malloc(l);
+ if (!f->layout->kerning.data) goto fehler;
+ if (read(handle,f->layout->kerning.data,l)!=l) goto fehler;
+ }
+ }
+
+ for (i=0;i<MAX_CHAR_PER_FONT;i++)
+ { if (f->glyph[i].shape)
+ { if (ShapeImport(handle,&f->glyph[i].shape)<0) goto fehler;
+ }
+ }
+
+ f->id = 0;
+
+ return 0;
+
+fehler:
+ if (f) for (;i<MAX_CHAR_PER_FONT;i++) f->glyph[i].shape = NULL;
+ FontFree(f);
+ font[0] = NULL;
+ return -1;
+}
+
+int TextPrintDefineText(TAG * t,SWFFONT * f)
+{ int id = GetTagID(t);
+ if ((id==ST_DEFINETEXT)||(id==ST_DEFINETEXT2)) FontExtract_DefineText(f->id,f,t,FEDTJ_PRINT);
+ else return -1;
+ return 0;
+}
+
+void LayoutFree(SWFLAYOUT * l)
+{ if (l)
+ { if (l->kerning.data) free(l->kerning.data);
+ l->kerning.data = NULL;
+ }
+ free(l);
+}
+
+void FontFree(SWFFONT * f)
+{ if (f)
+ { int i;
+
+ if (f->name) free(f->name);
+ if (f->layout) LayoutFree(f->layout);
+
+ f->name = NULL;
+ f->layout = NULL;
+
+ for (i=0;i<MAX_CHAR_PER_FONT;i++)
+ if (f->glyph[i].shape)
+ { ShapeFree(f->glyph[i].shape);
+ f->glyph[i].shape = NULL;
+ }
+ }
+ free(f);
+}
+
+int TextSetInfoRecord(TAG * t,SWFFONT * font,U16 size,RGBA * color,S16 dx,S16 dy)
+{ U8 flags;
+ if (!t) return -1;
+
+ flags = TF_TEXTCONTROL|(font?TF_HASFONT:0)|(color?TF_HASCOLOR:0)|(dx?TF_HASXOFFSET:0)|(dy?TF_HASYOFFSET:0);
+
+ SetU8(t,flags);
+ if (font) SetU16(t,font->id);
+ if (color)
+ { if (GetTagID(t)==ST_DEFINETEXT2) SetRGBA(t,color);
+ else SetRGB(t,color);
+ }
+ if (dx) SetS16(t,dx);
+ if (dy) SetS16(t,dy);
+ if (font) SetU16(t,size);
+
+ return 0;
+}
+
+int TextCountBits(SWFFONT * font,U8 * s,int scale,U8 * gbits,U8 * abits)
+{ U16 g,a;
+ if ((!s)||(!font)||((!gbits)&&(!abits))) return -1;
+ g = a = 0;
+
+ while(s[0])
+ { g = CountBits(font->glyph[s[0]].gid,g);
+ a = CountBits((((U32)font->glyph[s[0]].advance)*scale)/100,a);
+ s++;
+ }
+
+ if (gbits) gbits[0] = (U8)g;
+ if (abits) abits[0] = (U8)a;
+
+ return 0;
+}
+
+int TextSetCharRecord(TAG * t,SWFFONT * font,U8 * s,int scale,U8 gbits,U8 abits)
+{ int l,i;
+
+ if ((!t)||(!font)||(!s)) return -1;
+
+ l = strlen(s);
+ if (l>0x7f) l = 0x7f;
+ SetU8(t,l);
+
+ for (i=0;i<l;i++)
+ { SetBits(t,font->glyph[s[i]].gid,gbits);
+ SetBits(t,(((U32)font->glyph[s[i]].advance)*scale)/100,abits);
+ }
+
+ ResetBitcount(t);
+ return 0;
+}
+
+U32 TextGetWidth(SWFFONT * font,U8 * s,int scale)
+{ U32 res = 0;
+
+ if (font&&s)
+ { while (s[0])
+ { res += font->glyph[s[0]].advance;
+ s++;
+ }
+ if (scale) res = (res*scale)/100;
+ }
+
+ return res;
+}
-/* swftools.c\r
-\r
- Math and matrix functions, misc tools\r
-\r
- Extension module for the rfxswf library.\r
- Part of the swftools package.\r
-\r
- Copyright (c) 2000, 2001 Rainer Böhme <rfxswf@reflex-studio.de>\r
- \r
- This file is distributed under the GPL, see file COPYING for details \r
-\r
-*/\r
-\r
-// Matrix & Math tools for SWF files\r
-\r
-#define S64 long long\r
-SFIXED SP(SFIXED a1,SFIXED a2,SFIXED b1,SFIXED b2)\r
-{ S64 a;\r
- a = (S64)a1*(S64)b1+(S64)a2*(S64)b2;\r
- return (SFIXED)(a>>16);\r
-}\r
-SFIXED QFIX(int zaehler,int nenner) // bildet Quotient von zwei INTs in SFIXED\r
-{ S64 z = zaehler<<16;\r
- S64 a = z/(S64)nenner;\r
- return (SFIXED)a;\r
-}\r
-#undef S64\r
-\r
-LPMATRIX MatrixJoin(LPMATRIX d,LPMATRIX s1,LPMATRIX s2)\r
-{ \r
- if (!d) return NULL;\r
- if (!s1) return (s2)?(LPMATRIX)memcpy(d,s2,sizeof(MATRIX)):NULL;\r
- if (!s2) return (LPMATRIX)memcpy(d,s1,sizeof(MATRIX));\r
- \r
- d->tx = s1->tx + s2->tx;\r
- d->ty = s1->ty + s2->ty;\r
- \r
- d->sx = SP(s1->sx,s1->r1,s2->sx,s2->r0);\r
- d->sy = SP(s1->r0,s1->sy,s2->r1,s2->sy);\r
- d->r0 = SP(s1->r0,s1->sy,s2->sx,s2->r0);\r
- d->r1 = SP(s1->sx,s1->r1,s2->r1,s2->sy);\r
-\r
- //DumpMatrix(NULL,d);\r
- \r
- return d;\r
-}\r
-\r
-LPMATRIX MatrixMapTriangle(LPMATRIX m,int dx,int dy,int x0,int y0,\r
- int x1,int y1,int x2,int y2)\r
-{ int dx1 = x1 - x0;\r
- int dy1 = y1 - y0;\r
- int dx2 = x2 - x0;\r
- int dy2 = y2 - y0;\r
- \r
- if (!m) return NULL;\r
- if ((!dx)||(!dy)) return NULL; // check DIV by zero\r
-\r
- m->tx = x0;\r
- m->ty = y0;\r
- m->sx = QFIX(dx1,dx);\r
- m->sy = QFIX(dy2,dy);\r
- m->r0 = QFIX(dy1,dx);\r
- m->r1 = QFIX(dx2,dy);\r
- \r
- return m;\r
-}\r
-\r
-U16 GetDefineID(LPTAG t)\r
-// up to SWF 4.0\r
-{ U32 oldTagPos;\r
- U16 id = 0;\r
-\r
- oldTagPos = GetTagPos(t);\r
- SetTagPos(t,0);\r
-\r
- switch (GetTagID(t))\r
- { case ST_DEFINESHAPE:\r
- case ST_DEFINESHAPE2:\r
- case ST_DEFINESHAPE3:\r
- case ST_DEFINEMORPHSHAPE:\r
- case ST_DEFINEBITS:\r
- case ST_DEFINEBITSJPEG2:\r
- case ST_DEFINEBITSJPEG3:\r
- case ST_DEFINEBITSLOSSLESS:\r
- case ST_DEFINEBITSLOSSLESS2:\r
- case ST_DEFINEBUTTON:\r
- case ST_DEFINEBUTTON2:\r
- case ST_DEFINEBUTTONCXFORM:\r
- case ST_DEFINEBUTTONSOUND:\r
- case ST_DEFINEFONT:\r
- case ST_DEFINEFONT2:\r
- case ST_DEFINEFONTINFO:\r
- case ST_DEFINETEXT:\r
- case ST_DEFINETEXT2:\r
- case ST_DEFINESOUND:\r
- case ST_DEFINESPRITE:\r
- id = GetU16(t);\r
- break;\r
- }\r
-\r
- SetTagPos(t,oldTagPos);\r
-\r
- return id;\r
-}\r
-\r
-U16 GetPlaceID(LPTAG t)\r
-// up to SWF 4.0\r
-{ U32 oldTagPos;\r
- U16 id = 0;\r
-\r
- oldTagPos = GetTagPos(t);\r
- SetTagPos(t,0);\r
-\r
- switch (GetTagID(t))\r
- { case ST_PLACEOBJECT:\r
- case ST_REMOVEOBJECT:\r
- case ST_STARTSOUND:\r
- id = GetU16(t);\r
- break;\r
-\r
- case ST_PLACEOBJECT2:\r
- { U8 flags = GetU8(t);\r
- U16 d = GetU16(t);\r
- id = (flags&PF_CHAR)?GetU16(t):id;\r
- } break;\r
-\r
- }\r
-\r
- SetTagPos(t,oldTagPos);\r
-\r
- return id;\r
-}\r
-\r
-int definingtagids[] =\r
-{ST_DEFINESHAPE,\r
- ST_DEFINESHAPE2,\r
- ST_DEFINESHAPE3,\r
- ST_DEFINEMORPHSHAPE,\r
- ST_DEFINEFONT,\r
- ST_DEFINEFONT2,\r
- ST_DEFINETEXT,\r
- ST_DEFINETEXT2,\r
- ST_DEFINEEDITTEXT,\r
- ST_DEFINEBITS,\r
- ST_DEFINEBITSJPEG2,\r
- ST_DEFINEBITSJPEG3,\r
- ST_DEFINEBITSLOSSLESS,\r
- ST_DEFINEBITSLOSSLESS2,\r
- ST_DEFINEMOVIE,\r
- ST_DEFINESPRITE,\r
- ST_DEFINEBUTTON,\r
- ST_DEFINEBUTTON2,\r
- ST_DEFINESOUND,\r
- -1\r
-};\r
-\r
-// tags which may be used inside a sprite definition\r
-int spritetagids[] =\r
-{ST_SHOWFRAME,\r
- ST_PLACEOBJECT,\r
- ST_PLACEOBJECT2,\r
- ST_REMOVEOBJECT,\r
- ST_REMOVEOBJECT2, //?\r
- ST_DOACTION,\r
- ST_STARTSOUND,\r
- ST_FRAMELABEL,\r
- ST_SOUNDSTREAMHEAD,\r
- ST_SOUNDSTREAMHEAD2,\r
- ST_SOUNDSTREAMBLOCK,\r
- ST_END,\r
- -1\r
-};\r
-\r
-char isAllowedSpriteTag (TAG*tag)\r
-{\r
- int id = tag->id;\r
- int t=0;\r
- while(spritetagids[t]>=0)\r
- {\r
- if(spritetagids[t] == id) \r
- return 1;\r
- t++;\r
- }\r
- return 0; \r
-}\r
-\r
-char isDefiningTag (TAG*tag)\r
-{\r
- int id = tag->id;\r
- int t=0;\r
- while(definingtagids[t]>=0)\r
- {\r
- if(definingtagids[t] == id) \r
- return 1;\r
- t++;\r
- }\r
- return 0; \r
-}\r
-\r
-U16 GetDepth(LPTAG t)\r
-// up to SWF 4.0\r
-{ \r
- U16 depth = 0;\r
- U32 oldTagPos;\r
- oldTagPos = GetTagPos(t);\r
- SetTagPos(t,0);\r
-\r
- switch (GetTagID(t))\r
- { case ST_PLACEOBJECT:\r
- case ST_REMOVEOBJECT:\r
- GetU16(t); //id\r
- depth = GetU16(t);\r
- break;\r
- case ST_REMOVEOBJECT2:\r
- depth = GetU16(t);\r
- break;\r
- case ST_PLACEOBJECT2:\r
- { U8 flags = GetU8(t);\r
- depth = GetU16(t);\r
- } break;\r
- }\r
- SetTagPos(t,oldTagPos);\r
- return depth;\r
-}\r
-\r
-char* GetName(LPTAG t)\r
-{\r
- char* name = 0;\r
- U32 oldTagPos;\r
- MATRIX m;\r
- CXFORM c;\r
- oldTagPos = GetTagPos(t);\r
- SetTagPos(t,0);\r
- switch(GetTagID(t))\r
- {\r
- case ST_FRAMELABEL:\r
- name = &t->data[GetTagPos(t)];\r
- break;\r
- case ST_PLACEOBJECT2: { \r
- U8 flags = GetU8(t);\r
- GetU16(t); //depth;\r
- if(flags&PF_CHAR) \r
- GetU16(t); //id\r
- if(flags&PF_MATRIX)\r
- GetMatrix(t, &m);\r
- if(flags&PF_CXFORM)\r
- GetCXForm(t, &c, 1);\r
- if(flags&PF_RATIO)\r
- GetU16(t);\r
- if(flags&PF_NAME) {\r
- ResetBitmask(t);\r
- name = &t->data[GetTagPos(t)];\r
- }\r
- }\r
- break;\r
- }\r
- SetTagPos(t,oldTagPos);\r
- return name;\r
-}\r
-\r
+/* swftools.c
+
+ Math and matrix functions, misc tools
+
+ Extension module for the rfxswf library.
+ Part of the swftools package.
+
+ Copyright (c) 2000, 2001 Rainer Böhme <rfxswf@reflex-studio.de>
+
+ This file is distributed under the GPL, see file COPYING for details
+
+*/
+
+// Matrix & Math tools for SWF files
+
+#define S64 long long
+SFIXED SP(SFIXED a1,SFIXED a2,SFIXED b1,SFIXED b2)
+{ S64 a;
+ a = (S64)a1*(S64)b1+(S64)a2*(S64)b2;
+ return (SFIXED)(a>>16);
+}
+SFIXED QFIX(int zaehler,int nenner) // bildet Quotient von zwei INTs in SFIXED
+{ S64 z = zaehler<<16;
+ S64 a = z/(S64)nenner;
+ return (SFIXED)a;
+}
+#undef S64
+
+MATRIX * MatrixJoin(MATRIX * d,MATRIX * s1,MATRIX * s2)
+{
+ if (!d) return NULL;
+ if (!s1) return (s2)?(MATRIX *)memcpy(d,s2,sizeof(MATRIX)):NULL;
+ if (!s2) return (MATRIX *)memcpy(d,s1,sizeof(MATRIX));
+
+ d->tx = s1->tx + s2->tx;
+ d->ty = s1->ty + s2->ty;
+
+ d->sx = SP(s1->sx,s1->r1,s2->sx,s2->r0);
+ d->sy = SP(s1->r0,s1->sy,s2->r1,s2->sy);
+ d->r0 = SP(s1->r0,s1->sy,s2->sx,s2->r0);
+ d->r1 = SP(s1->sx,s1->r1,s2->r1,s2->sy);
+
+ //DumpMatrix(NULL,d);
+
+ return d;
+}
+
+MATRIX * MatrixMapTriangle(MATRIX * m,int dx,int dy,int x0,int y0,
+ int x1,int y1,int x2,int y2)
+{ int dx1 = x1 - x0;
+ int dy1 = y1 - y0;
+ int dx2 = x2 - x0;
+ int dy2 = y2 - y0;
+
+ if (!m) return NULL;
+ if ((!dx)||(!dy)) return NULL; // check DIV by zero
+
+ m->tx = x0;
+ m->ty = y0;
+ m->sx = QFIX(dx1,dx);
+ m->sy = QFIX(dy2,dy);
+ m->r0 = QFIX(dy1,dx);
+ m->r1 = QFIX(dx2,dy);
+
+ return m;
+}
+
+U16 GetDefineID(TAG * t)
+// up to SWF 4.0
+{ U32 oldTagPos;
+ U16 id = 0;
+
+ oldTagPos = GetTagPos(t);
+ SetTagPos(t,0);
+
+ switch (GetTagID(t))
+ { case ST_DEFINESHAPE:
+ case ST_DEFINESHAPE2:
+ case ST_DEFINESHAPE3:
+ case ST_DEFINEMORPHSHAPE:
+ case ST_DEFINEBITS:
+ case ST_DEFINEBITSJPEG2:
+ case ST_DEFINEBITSJPEG3:
+ case ST_DEFINEBITSLOSSLESS:
+ case ST_DEFINEBITSLOSSLESS2:
+ case ST_DEFINEBUTTON:
+ case ST_DEFINEBUTTON2:
+ case ST_DEFINEBUTTONCXFORM:
+ case ST_DEFINEBUTTONSOUND:
+ case ST_DEFINEFONT:
+ case ST_DEFINEFONT2:
+ case ST_DEFINEFONTINFO:
+ case ST_DEFINETEXT:
+ case ST_DEFINETEXT2:
+ case ST_DEFINESOUND:
+ case ST_DEFINESPRITE:
+ id = GetU16(t);
+ break;
+ }
+
+ SetTagPos(t,oldTagPos);
+
+ return id;
+}
+
+U16 GetPlaceID(TAG * t)
+// up to SWF 4.0
+{ U32 oldTagPos;
+ U16 id = 0;
+
+ oldTagPos = GetTagPos(t);
+ SetTagPos(t,0);
+
+ switch (GetTagID(t))
+ { case ST_PLACEOBJECT:
+ case ST_REMOVEOBJECT:
+ case ST_STARTSOUND:
+ id = GetU16(t);
+ break;
+
+ case ST_PLACEOBJECT2:
+ { U8 flags = GetU8(t);
+ U16 d = GetU16(t);
+ id = (flags&PF_CHAR)?GetU16(t):id;
+ } break;
+
+ }
+
+ SetTagPos(t,oldTagPos);
+
+ return id;
+}
+
+int definingtagids[] =
+{ST_DEFINESHAPE,
+ ST_DEFINESHAPE2,
+ ST_DEFINESHAPE3,
+ ST_DEFINEMORPHSHAPE,
+ ST_DEFINEFONT,
+ ST_DEFINEFONT2,
+ ST_DEFINETEXT,
+ ST_DEFINETEXT2,
+ ST_DEFINEEDITTEXT,
+ ST_DEFINEBITS,
+ ST_DEFINEBITSJPEG2,
+ ST_DEFINEBITSJPEG3,
+ ST_DEFINEBITSLOSSLESS,
+ ST_DEFINEBITSLOSSLESS2,
+ ST_DEFINEMOVIE,
+ ST_DEFINESPRITE,
+ ST_DEFINEBUTTON,
+ ST_DEFINEBUTTON2,
+ ST_DEFINESOUND,
+ -1
+};
+
+// tags which may be used inside a sprite definition
+int spritetagids[] =
+{ST_SHOWFRAME,
+ ST_PLACEOBJECT,
+ ST_PLACEOBJECT2,
+ ST_REMOVEOBJECT,
+ ST_REMOVEOBJECT2, //?
+ ST_DOACTION,
+ ST_STARTSOUND,
+ ST_FRAMELABEL,
+ ST_SOUNDSTREAMHEAD,
+ ST_SOUNDSTREAMHEAD2,
+ ST_SOUNDSTREAMBLOCK,
+ ST_END,
+ -1
+};
+
+char isAllowedSpriteTag (TAG*tag)
+{
+ int id = tag->id;
+ int t=0;
+ while(spritetagids[t]>=0)
+ {
+ if(spritetagids[t] == id)
+ return 1;
+ t++;
+ }
+ return 0;
+}
+
+char isDefiningTag (TAG*tag)
+{
+ int id = tag->id;
+ int t=0;
+ while(definingtagids[t]>=0)
+ {
+ if(definingtagids[t] == id)
+ return 1;
+ t++;
+ }
+ return 0;
+}
+
+U16 GetDepth(TAG * t)
+// up to SWF 4.0
+{
+ U16 depth = 0;
+ U32 oldTagPos;
+ oldTagPos = GetTagPos(t);
+ SetTagPos(t,0);
+
+ switch (GetTagID(t))
+ { case ST_PLACEOBJECT:
+ case ST_REMOVEOBJECT:
+ GetU16(t); //id
+ depth = GetU16(t);
+ break;
+ case ST_REMOVEOBJECT2:
+ depth = GetU16(t);
+ break;
+ case ST_PLACEOBJECT2:
+ { U8 flags = GetU8(t);
+ depth = GetU16(t);
+ } break;
+ }
+ SetTagPos(t,oldTagPos);
+ return depth;
+}
+
+char* GetName(TAG * t)
+{
+ char* name = 0;
+ U32 oldTagPos;
+ MATRIX m;
+ CXFORM c;
+ oldTagPos = GetTagPos(t);
+ SetTagPos(t,0);
+ switch(GetTagID(t))
+ {
+ case ST_FRAMELABEL:
+ name = &t->data[GetTagPos(t)];
+ break;
+ case ST_PLACEOBJECT2: {
+ U8 flags = GetU8(t);
+ GetU16(t); //depth;
+ if(flags&PF_CHAR)
+ GetU16(t); //id
+ if(flags&PF_MATRIX)
+ GetMatrix(t, &m);
+ if(flags&PF_CXFORM)
+ GetCXForm(t, &c, 1);
+ if(flags&PF_RATIO)
+ GetU16(t);
+ if(flags&PF_NAME) {
+ ResetBitmask(t);
+ name = &t->data[GetTagPos(t)];
+ }
+ }
+ break;
+ }
+ SetTagPos(t,oldTagPos);
+ return name;
+}
+
-/* rfxswf.c\r
-\r
- Library for creating and reading SWF files or parts of it.\r
- There's a module directory which provides some extended functionality.\r
- Most modules are included at the bottom of this file.\r
-\r
- Part of the swftools package.\r
-\r
- Copyright (c) 2000, 2001 Rainer Böhme <rfxswf@reflex-studio.de>\r
- \r
- This file is distributed under the GPL, see file COPYING for details \r
-\r
-*/\r
-\r
-#include "rfxswf.h"\r
-\r
-#ifdef HAVE_LIBJPEG\r
-#ifdef HAVE_JPEGLIB_H\r
-#include <jpeglib.h>\r
-#define _JPEGLIB_INCLUDED_\r
-#endif //HAVE_JPEGLIB_H\r
-#endif //HAVE_LIBJPEG\r
-\r
-// Win32 support may be broken since it was only tested in an older version for Watcom C\r
-#ifdef __NT__\r
-# include <io.h>\r
-# include <malloc.h>\r
-# include <string.h>\r
-# ifdef DEBUG_RFXSWF\r
-# include <stdio.h>\r
-# endif\r
-#else\r
-#endif\r
-\r
-// internal constants\r
-\r
-#define MALLOC_SIZE 128\r
-#define INSERT_RFX_TAG\r
-\r
-#define MEMSIZE(l) (((l/MALLOC_SIZE)+1)*MALLOC_SIZE)\r
-\r
-// inline wrapper functions\r
-\r
-LPTAG NextTag(LPTAG t) { return t->next; }\r
-LPTAG PrevTag(LPTAG t) { return t->prev; }\r
-int GetFrameNo(LPTAG t) { return t->frame; }\r
-U16 GetTagID(LPTAG t) { return t->id; }\r
-U32 GetDataSize(LPTAG t) { return t->len; }\r
-U8* GetDataSizePtr(LPTAG t) { return &(t->data[t->len]); }\r
-U32 GetTagPos(LPTAG t) { return t->pos; }\r
-\r
-// Basic Data Access Functions\r
-\r
-#define ResetBitmask(tag) if (tag->bitmask) { tag->pos++; tag->bitmask = 0; }\r
-#define ResetBitcount(tag) if (tag->bitcount) { tag->bitcount = 0; }\r
-\r
-// for future purpose: avoid high level lib functions to change tagpos/bitcount\r
-\r
-#define SaveTagPos(tag)\r
-#define RestoreTagPos(tag)\r
-\r
-void SetTagPos(LPTAG t,U32 pos)\r
-{ ResetBitmask(t);\r
- if (pos<=t->len) t->pos = pos;\r
- #ifdef DEBUG_RFXSWF\r
- else fprintf(stderr,"SetTagPos() out of bounds: TagID = %i\n",t->id);\r
- #endif\r
-}\r
-\r
-U8 GetU8(LPTAG t)\r
-{ ResetBitmask(t);\r
- #ifdef DEBUG_RFXSWF\r
- if (t->pos>=t->len) \r
- { fprintf(stderr,"GetU8() out of bounds: TagID = %i\n",t->id);\r
- return 0;\r
- }\r
- #endif\r
- return t->data[t->pos++];\r
-}\r
-\r
-U16 GetU16(LPTAG t)\r
-{ U16 res;\r
- ResetBitmask(t);\r
- #ifdef DEBUG_RFXSWF\r
- if (t->pos>(t->len-2)) \r
- { fprintf(stderr,"GetU16() out of bounds: TagID = %i\n",t->id);\r
- return 0;\r
- }\r
- #endif\r
- res = t->data[t->pos] | (t->data[t->pos+1]<<8);\r
- t->pos+=2;\r
- return res;\r
-}\r
-\r
-U32 GetU32(LPTAG t)\r
-{ U32 res;\r
- ResetBitmask(t);\r
- #ifdef DEBUG_RFXSWF\r
- if (t->pos>(t->len-4)) \r
- { fprintf(stderr,"GetU32() out of bounds: TagID = %i\n",t->id);\r
- return 0;\r
- }\r
- #endif\r
- res = t->data[t->pos] | (t->data[t->pos+1]<<8) | \r
- (t->data[t->pos+2]<<16) | (t->data[t->pos+3]<<24);\r
- t->pos+=4;\r
- return res;\r
-}\r
-\r
-int GetBlock(LPTAG t,U8 * b,int l)\r
-// returns number of bytes written (<=l)\r
-// b = NULL -> skip data\r
-{ ResetBitmask(t);\r
- if ((t->len-t->pos)<l) l=t->len-t->pos;\r
- if (b && l) memcpy(b,&t->data[t->pos],l);\r
- t->pos+=l;\r
- return l;\r
-}\r
-\r
-int SetBlock(LPTAG t,U8 * b,int l)\r
-// Appends Block to the end of Tagdata, returns size\r
-{ U32 newlen = t->len + l;\r
- ResetBitcount(t);\r
- if (newlen>t->memsize)\r
- { U32 newmem = MEMSIZE(newlen); \r
- U8 * newdata = (U8*)((t->data)?realloc(t->data,newmem):malloc(newmem));\r
- if (!newdata)\r
- {\r
- #ifdef DEBUG_RFXSWF\r
- fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n");\r
- #endif\r
- return 0;\r
- }\r
- t->memsize = newmem;\r
- t->data = newdata;\r
- }\r
- if (b) memcpy(&t->data[t->len],b,l);\r
- else memset(&t->data[t->len],0x00,l);\r
- t->len+=l;\r
- return l;\r
-}\r
-\r
-int SetU8(LPTAG t,U8 v)\r
-{ ResetBitcount(t);\r
- if ((t->len+1)>t->memsize) return (SetBlock(t,&v,1)==1)?0:-1;\r
- t->data[t->len++] = v;\r
- return 0;\r
-}\r
-\r
-int SetU16(LPTAG t,U16 v)\r
-{ U8 a[2];\r
- a[0] = v&0xff;\r
- a[1] = v>>8;\r
- \r
- ResetBitcount(t);\r
- if ((t->len+2)>t->memsize) return (SetBlock(t,a,2)==2)?0:-1;\r
- t->data[t->len++] = a[0];\r
- t->data[t->len++] = a[1];\r
- return 0;\r
-}\r
-\r
-int SetU32(LPTAG t,U32 v)\r
-{ U8 a[4];\r
- a[0] = v&0xff; // to ensure correct handling of non-intel byteorder\r
- a[1] = (v>>8)&0xff;\r
- a[2] = (v>>16)&0xff;\r
- a[3] = (v>>24)&0xff;\r
- \r
- ResetBitcount(t);\r
- if ((t->len+4)>t->memsize) return (SetBlock(t,a,4)==4)?0:-1;\r
- t->data[t->len++] = a[0];\r
- t->data[t->len++] = a[1];\r
- t->data[t->len++] = a[2];\r
- t->data[t->len++] = a[3];\r
- return 0;\r
-}\r
-\r
-U32 GetBits(LPTAG t,int nbits)\r
-{ U32 res = 0;\r
- if (!nbits) return 0;\r
- if (!t->bitmask) t->bitmask = 0x80;\r
- while (nbits)\r
- { res<<=1;\r
- if (t->data[t->pos]&t->bitmask) res|=1;\r
- t->bitmask>>=1;\r
- nbits--;\r
- if (!t->bitmask)\r
- { if (nbits) t->bitmask = 0x80;\r
- #ifdef DEBUG_RFXSWF\r
- if (t->pos>=t->len) \r
- { fprintf(stderr,"GetBits() out of bounds: TagID = %i\n",t->id);\r
- return res;\r
- }\r
- #endif\r
- t->pos++;\r
- }\r
- }\r
- return res;\r
-}\r
-\r
-S32 GetSBits(LPTAG t,int nbits)\r
-{ U32 res = GetBits(t,nbits);\r
- if (res&(1<<(nbits-1))) res|=(0xffffffff<<nbits); \r
- return (S32)res;\r
-}\r
-\r
-int SetBits(LPTAG t,U32 v,int nbits)\r
-{ U32 bm = 1<<(nbits-1);\r
-\r
- while (nbits)\r
- { if (!t->bitcount)\r
- { if (FAILED(SetU8(t,0))) return -1;\r
- t->bitcount = 0x80;\r
- }\r
- if (v&bm) t->data[t->len-1] |= t->bitcount;\r
- bm>>=1;\r
- t->bitcount>>=1;\r
- nbits--;\r
- }\r
- return 0;\r
-}\r
-\r
-// Advanced Data Access Functions\r
-\r
-int SetRGB(LPTAG t,LPRGBA col)\r
-{ if (!t) return -1;\r
- if (col)\r
- { SetU8(t,col->r);\r
- SetU8(t,col->g);\r
- SetU8(t,col->b);\r
- } else SetBlock(t,NULL,3);\r
- return 0;\r
-}\r
-\r
-int SetRGBA(LPTAG t,LPRGBA col)\r
-{ if (!t) return -1;\r
- if (col)\r
- { SetU8(t,col->r);\r
- SetU8(t,col->g);\r
- SetU8(t,col->b);\r
- SetU8(t,col->a);\r
- } else SetBlock(t,NULL,4);\r
- return 0;\r
-}\r
-\r
-int CountBits(U32 v,int nbits)\r
-{ int n = 33;\r
- U32 m = 0x80000000;\r
- if (!v) n = 0; else\r
- if (v&m)\r
- { while (v&m)\r
- { n--;\r
- m>>=1;\r
- if (!m) break;\r
- } \r
- }\r
- else\r
- { while (!(v&m))\r
- { n--;\r
- m>>=1;\r
- if (!m) break;\r
- } \r
- }\r
- return (n>nbits)?n:nbits;\r
-}\r
-\r
-int GetRect(LPTAG t,LPSRECT r)\r
-{ int nbits;\r
- SRECT dummy;\r
- if (!r) r = &dummy;\r
- nbits = (int) GetBits(t,5);\r
- r->xmin = GetSBits(t,nbits);\r
- r->xmax = GetSBits(t,nbits);\r
- r->ymin = GetSBits(t,nbits);\r
- r->ymax = GetSBits(t,nbits);\r
- return 0;\r
-}\r
-\r
-int SetRect(LPTAG t,LPSRECT r)\r
-{ int nbits;\r
- \r
- nbits = CountBits(r->xmin,0);\r
- nbits = CountBits(r->xmax,nbits);\r
- nbits = CountBits(r->ymin,nbits);\r
- nbits = CountBits(r->ymax,nbits);\r
-\r
- SetBits(t,nbits,5);\r
- SetBits(t,r->xmin,nbits);\r
- SetBits(t,r->xmax,nbits);\r
- SetBits(t,r->ymin,nbits);\r
- SetBits(t,r->ymax,nbits);\r
-\r
- return 0;\r
-}\r
-\r
-int GetMatrix(LPTAG t,LPMATRIX m)\r
-{ MATRIX dummy;\r
- int nbits;\r
- \r
- if (!m) m = &dummy;\r
- \r
- if (!t)\r
- { m->sx = m->sy = 0x10000;\r
- m->r0 = m->r1 = 0;\r
- m->tx = m->ty = 0;\r
- return -1;\r
- }\r
-\r
- ResetBitmask(t);\r
- \r
- if (GetBits(t,1))\r
- { nbits = GetBits(t,5);\r
- m->sx = GetSBits(t,nbits);\r
- m->sy = GetSBits(t,nbits);\r
- }\r
- else m->sx = m->sy = 0x10000;\r
- \r
- if (GetBits(t,1))\r
- { nbits = GetBits(t,5);\r
- m->r0 = GetSBits(t,nbits);\r
- m->r1 = GetSBits(t,nbits);\r
- }\r
- else m->r0 = m->r1 = 0x0;\r
-\r
- nbits = GetBits(t,5);\r
- m->tx = GetSBits(t,nbits);\r
- m->ty = GetSBits(t,nbits);\r
- \r
- return 0;\r
-}\r
-\r
-int SetMatrix(LPTAG t,LPMATRIX m)\r
-{ int nbits;\r
- MATRIX ma;\r
-\r
- if (!m)\r
- { m = &ma;\r
- ma.sx = ma.sy = 0x10000;\r
- ma.r0 = ma.r1 = 0;\r
- ma.tx = ma.ty = 0;\r
- }\r
-\r
- ResetBitcount(t);\r
-\r
- if ((m->sx==0x10000)&&(m->sy==0x10000)) SetBits(t,0,1);\r
- else\r
- { SetBits(t,1,1);\r
- nbits = CountBits(m->sx,0);\r
- nbits = CountBits(m->sy,nbits);\r
- SetBits(t,nbits,5);\r
- SetBits(t,m->sx,nbits);\r
- SetBits(t,m->sy,nbits);\r
- }\r
-\r
- if ((!m->r0)&&(!m->r1)) SetBits(t,0,1);\r
- else\r
- { SetBits(t,1,1);\r
- nbits = CountBits(m->r0,0);\r
- nbits = CountBits(m->r1,nbits);\r
- SetBits(t,nbits,5);\r
- SetBits(t,m->r0,nbits);\r
- SetBits(t,m->r1,nbits);\r
- }\r
-\r
- nbits = CountBits(m->tx,0);\r
- nbits = CountBits(m->ty,nbits);\r
- SetBits(t,nbits,5);\r
- SetBits(t,m->tx,nbits);\r
- SetBits(t,m->ty,nbits);\r
-\r
- return 0;\r
-}\r
-\r
-int GetCXForm(LPTAG t,LPCXFORM cx,U8 alpha) //FIXME: alpha should be type bool\r
-{ CXFORM cxf;\r
- int hasadd;\r
- int hasmul;\r
- int nbits;\r
- \r
- if (!cx) cx = &cxf;\r
- \r
- cx->a0 = cx->r0 = cx->g0 = cx->b0 = 256;\r
- cx->a1 = cx->r1 = cx->g1 = cx->b1 = 0;\r
-\r
- if (!t) return 0;\r
- \r
- ResetBitmask(t);\r
- hasadd = GetBits(t,1);\r
- hasmul = GetBits(t,1);\r
- nbits = GetBits(t,4);\r
-\r
- if (hasmul)\r
- { cx->r0 = (S16)GetSBits(t,nbits);\r
- cx->g0 = (S16)GetSBits(t,nbits);\r
- cx->b0 = (S16)GetSBits(t,nbits);\r
- if (alpha)\r
- cx->a0 = (S16)GetSBits(t,nbits);\r
- }\r
-\r
- if (hasadd)\r
- { cx->r1 = (S16)GetSBits(t,nbits);\r
- cx->g1 = (S16)GetSBits(t,nbits);\r
- cx->b1 = (S16)GetSBits(t,nbits);\r
- if (alpha)\r
- cx->a1 = (S16)GetSBits(t,nbits);\r
- }\r
- \r
- return 0;\r
-}\r
-\r
-int SetCXForm(LPTAG t,LPCXFORM cx,U8 alpha)\r
-{ CXFORM cxf;\r
- int hasadd;\r
- int hasmul;\r
- int nbits;\r
- \r
- if (!cx)\r
- { cx = &cxf;\r
- cx->a0 = cx->r0 = cx->g0 = cx->b0 = 256;\r
- cx->a1 = cx->r1 = cx->g1 = cx->b1 = 0;\r
- }\r
-\r
- if (!alpha)\r
- { cx->a0 = 256;\r
- cx->a1 = 0;\r
- }\r
-\r
- nbits = 0;\r
-\r
- hasmul = (cx->a0!=256)||(cx->r0!=256)||(cx->g0!=256)||(cx->b0!=256);\r
- hasadd = cx->a1|cx->r1|cx->g1|cx->b1;\r
-\r
- if (hasmul)\r
- { if (alpha) nbits = CountBits((S32)cx->a0,nbits);\r
- nbits = CountBits((S32)cx->r0,nbits);\r
- nbits = CountBits((S32)cx->g0,nbits);\r
- nbits = CountBits((S32)cx->b0,nbits);\r
- }\r
-\r
- if (hasadd)\r
- { if (alpha) nbits = CountBits((S32)cx->a1,nbits);\r
- nbits = CountBits((S32)cx->r1,nbits);\r
- nbits = CountBits((S32)cx->g1,nbits);\r
- nbits = CountBits((S32)cx->b1,nbits);\r
- }\r
- \r
- ResetBitcount(t);\r
- SetBits(t,hasadd?1:0,1);\r
- SetBits(t,hasmul?1:0,1);\r
- SetBits(t,nbits,4);\r
-\r
- if (hasmul)\r
- { SetBits(t,cx->r0,nbits);\r
- SetBits(t,cx->g0,nbits);\r
- SetBits(t,cx->b0,nbits);\r
- if (alpha) SetBits(t,cx->a0,nbits);\r
- }\r
-\r
- if (hasadd)\r
- { SetBits(t,cx->r1,nbits);\r
- SetBits(t,cx->g1,nbits);\r
- SetBits(t,cx->b1,nbits);\r
- if (alpha) SetBits(t,cx->a1,nbits);\r
- }\r
- \r
- return 0;\r
-}\r
-\r
-int GetPoint(LPTAG t,LPSPOINT p) { return 0; }\r
-int SetPoint(LPTAG t,LPSPOINT p) { return 0; }\r
-\r
-// Tag List Manipulating Functions\r
-\r
-int RFXSWF_UpdateFrame(LPTAG t,S8 delta)\r
-// returns number of frames\r
-{ int res = -1;\r
- while (t)\r
- { t->frame+=delta;\r
- res = t->frame;\r
- t = t->next;\r
- }\r
- return res;\r
-}\r
-\r
-#define UpdateFrame(a,b) RFXSWF_UpdateFrame(a,b)\r
-\r
-LPTAG InsertTag(LPTAG after,U16 id) // updates frames, if nescessary\r
-{ LPTAG t;\r
-\r
- t = (LPTAG)malloc(sizeof(TAG));\r
- if (t)\r
- { memset(t,0x00,sizeof(TAG));\r
- t->id = id;\r
- t->bitcount = 0x80;\r
- \r
- if (after)\r
- { t->frame = after->frame;\r
- t->prev = after;\r
- t->next = after->next;\r
- after->next = t;\r
- if (t->next) t->next->prev = t;\r
- \r
- if (id==ST_SHOWFRAME) UpdateFrame(t->next,+1);\r
- }\r
- }\r
- return t;\r
-}\r
-\r
-int DeleteTag(LPTAG t)\r
-{ if (!t) return -1;\r
-\r
- if (t->id==ST_SHOWFRAME) UpdateFrame(t->next,-1);\r
- \r
- if (t->prev) t->prev->next = t->next;\r
- if (t->next) t->next->prev = t->prev;\r
-\r
- if (t->data) free(t->data);\r
- free(t);\r
- return 0;\r
-}\r
-\r
-LPTAG RFXSWF_ReadTag(int handle,LPTAG prev)\r
-{ LPTAG t;\r
- U16 raw;\r
- U32 len;\r
- int id;\r
-\r
- if (read(handle,&raw,2)!=2) return NULL;\r
-\r
- len = raw&0x3f;\r
- id = raw>>6;\r
-\r
- if (len==0x3f)\r
- { if (read(handle,&len,4)!=4) return NULL;\r
- }\r
-\r
- if (id==ST_DEFINESPRITE) len = 2*sizeof(U16);\r
- // Sprite handling fix: Flaten sprite tree\r
-\r
- t = (LPTAG)malloc(sizeof(TAG));\r
- \r
- if (!t)\r
- {\r
- #ifdef DEBUG_RFXSWF\r
- fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n");\r
- #endif\r
- return NULL;\r
- }\r
-\r
- memset(t,0x00,sizeof(TAG));\r
- \r
- t->len = len;\r
- t->id = id;\r
-\r
- if (t->len)\r
- { t->data = (U8*)malloc(t->len);\r
- if (!t->data)\r
- {\r
- #ifdef DEBUG_RFXSWF\r
- fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n");\r
- #endif\r
- return NULL;\r
- }\r
- t->memsize = t->len;\r
- if (read(handle,t->data,t->len)!=t->len) return NULL;\r
- }\r
-\r
- if (prev)\r
- { t->frame = prev->frame+((prev->id==ST_SHOWFRAME)?1:0);\r
- t->prev = prev;\r
- prev->next = t;\r
- }\r
-\r
- return t;\r
-}\r
-\r
-int DefineSprite_GetRealSize(LPTAG t);\r
-\r
-int RFXSWF_WriteTag(int handle,LPTAG t)\r
-// returns tag length in bytes (incl. Header), -1 = Error\r
-// handle = -1 -> no output\r
-{ U16 raw[3];\r
- U32 len;\r
- int short_tag;\r
-\r
- if (!t) return -1;\r
-\r
- len = (t->id==ST_DEFINESPRITE)?DefineSprite_GetRealSize(t):t->len;\r
-\r
- short_tag = len<0x3f;\r
-\r
- if (handle>=0)\r
- { if (short_tag)\r
- { raw[0] = len|((t->id&0x3ff)<<6);\r
- if (write(handle,raw,2)!=2)\r
- {\r
- #ifdef DEBUG_RFXSWF\r
- fprintf(stderr,"WriteTag() failed: Short Header.\n");\r
- #endif\r
- return -1;\r
- }\r
- }\r
- else\r
- { raw[0] = (t->id<<6)|0x3f;\r
- raw[1] = (U16)(len&0xffff);\r
- raw[2] = (U16)(len>>16);\r
- if (write(handle,raw,6)!=6)\r
- {\r
- #ifdef DEBUG_RFXSWF\r
- fprintf(stderr,"WriteTag() failed: Long Header.\n");\r
- #endif\r
- return -1;\r
- }\r
- }\r
- \r
- if (t->data)\r
- { if (write(handle,t->data,t->len)!=t->len)\r
- {\r
- #ifdef DEBUG_RFXSWF\r
- fprintf(stderr,"WriteTag() failed: Data.\n");\r
- #endif\r
- return -1;\r
- }\r
- }\r
- #ifdef DEBUG_RFXSWF\r
- else if (t->len) fprintf(stderr,"WriteTag(): Tag Data Error, id=%i\n",t->id);\r
- #endif\r
- }\r
-\r
- return t->len+(short_tag?2:6);\r
-}\r
-\r
-int DefineSprite_GetRealSize(LPTAG t)\r
-// Sprite Handling: Helper function to pack DefineSprite-Tag\r
-{ U32 len = t->len;\r
- do\r
- { t = NextTag(t);\r
- if (t->id!=ST_DEFINESPRITE) len += RFXSWF_WriteTag(-1,t);\r
- else t = NULL;\r
- } while (t&&(t->id!=ST_END));\r
- return len;\r
-}\r
-\r
-#define ReadTag(a,b) RFXSWF_ReadTag(a,b)\r
-#define WriteTag(a,b) RFXSWF_WriteTag(a,b)\r
-\r
-// Movie Functions\r
-\r
-int ReadSWF(int handle,LPSWF swf) // Reads SWF to memory (malloc'ed), returns length or <0 if fails\r
-{ \r
- if (!swf) return -1;\r
- memset(swf,0x00,sizeof(SWF));\r
-\r
- { char b[32]; // Header lesen\r
- TAG t1;\r
- LPTAG t;\r
- \r
- memset(&t1,0x00,sizeof(TAG));\r
- \r
- if ((t1.len=read(handle,b,32))<21) return -1;\r
- t1.data = (U8*)b;\r
-\r
- if (GetU8(&t1)!=(U8)'F') return -1;\r
- if (GetU8(&t1)!=(U8)'W') return -1;\r
- if (GetU8(&t1)!=(U8)'S') return -1;\r
-\r
- swf->FileVersion = GetU8(&t1);\r
- swf->FileSize = GetU32(&t1);\r
- GetRect(&t1,&swf->MovieSize);\r
- swf->FrameRate = GetU16(&t1);\r
- swf->FrameCount = GetU16(&t1);\r
-\r
- GetU8(&t1);\r
- lseek(handle,GetTagPos(&t1)-1,SEEK_SET);\r
- \r
- // Tags lesen und verketten\r
- t = &t1;\r
- while (t) t = ReadTag(handle,t);\r
- swf->FirstTag = t1.next;\r
- t1.next->prev = NULL;\r
- }\r
- \r
- return 0;\r
-}\r
-int WriteSWF(int handle,LPSWF swf) // Writes SWF to file, returns length or <0 if fails\r
-{ U32 len;\r
- LPTAG t;\r
- \r
- if (!swf) return -1;\r
-\r
- // Insert REFLEX Tag\r
-\r
-#ifdef INSERT_RFX_TAG\r
-\r
- if (NextTag(swf->FirstTag))\r
- if (GetTagID(NextTag(swf->FirstTag))!=ST_REFLEX)\r
- SetBlock(InsertTag(swf->FirstTag,ST_REFLEX),"rfx",3);\r
-\r
-#endif // INSERT_RFX_TAG\r
-\r
- // Count Frames + File Size\r
-\r
- len = 0;\r
- t = swf->FirstTag;\r
- swf->FrameCount = 0;\r
-\r
- while(t)\r
- { len += WriteTag(-1,t);\r
- if (t->id==ST_SHOWFRAME) swf->FrameCount++;\r
- t = NextTag(t);\r
- }\r
- \r
- { TAG t1;\r
- char b[64];\r
- U32 l;\r
-\r
- memset(&t1,0x00,sizeof(TAG));\r
- t1.data = (U8*)b;\r
- t1.memsize = 64;\r
- \r
- SetU8(&t1,'F'); \r
- SetU8(&t1,'W'); \r
- SetU8(&t1,'S');\r
- SetU8(&t1,swf->FileVersion);\r
- \r
- SetU32(&t1,0); // Keep space for filesize\r
- SetRect(&t1,&swf->MovieSize);\r
- SetU16(&t1,swf->FrameRate);\r
- SetU16(&t1,swf->FrameCount);\r
-\r
- l = GetDataSize(&t1);\r
- swf->FileSize = l+len;\r
- t1.len = 4; // bad & ugly trick !\r
- SetU32(&t1,swf->FileSize);\r
-\r
- if (handle>=0)\r
- { \r
- int ret = write(handle,b,l);\r
- if (ret!=l)\r
- {\r
- #ifdef DEBUG_RFXSWF\r
- printf("ret:%d (fd:%d)\n",ret, handle);\r
- perror("write:");\r
- fprintf(stderr,"WriteSWF() failed: Header.\n");\r
- #endif\r
- return -1;\r
- }\r
-\r
- t = swf->FirstTag;\r
- while (t)\r
- { if (WriteTag(handle,t)<0) return -1;\r
- t = NextTag(t);\r
- }\r
- }\r
- }\r
- return (int)swf->FileSize;\r
-}\r
-\r
-int WriteCGI(LPSWF swf)\r
-{ int len;\r
- char s[1024];\r
- \r
- len = WriteSWF(-1,swf);\r
-\r
- if (len<0) return -1;\r
-\r
- sprintf(s,"Content-type: application/x-shockwave-flash\n"\r
- "Accept-Ranges: bytes\n"\r
- "Content-Length: %lu\n"\r
- "Expires: Thu, 13 Apr 2000 23:59:59 GMT\n"\r
- "\n",len);\r
- \r
- write(fileno(stdout),s,strlen(s));\r
- return WriteSWF(fileno(stdout),swf);\r
-}\r
-\r
-void FreeTags(LPSWF swf) // Frees all malloc'ed memory for tags\r
-{ LPTAG t = swf->FirstTag;\r
-\r
- while (t)\r
- { LPTAG tnew = t->next;\r
- if (t->data) free(t->data);\r
- free(t);\r
- t = tnew;\r
- }\r
-}\r
-\r
-// include advanced functions\r
-\r
-#ifdef __NT__\r
-\r
-#include "modules\swfdump.c"\r
-#include "modules\swfshape.c"\r
-#include "modules\swftext.c"\r
-#include "modules\swfobject.c"\r
-#include "modules\swfbutton.c"\r
-#include "modules\swftools.c"\r
-#include "modules\swfcgi.c"\r
-#include "modules\swfbits.c"\r
-\r
-#else\r
-\r
-#include "modules/swfdump.c"\r
-#include "modules/swfshape.c"\r
-#include "modules/swftext.c"\r
-#include "modules/swfobject.c"\r
-#include "modules/swfbutton.c"\r
-#include "modules/swftools.c"\r
-#include "modules/swfcgi.c"\r
-#include "modules/swfbits.c"\r
-\r
-#endif\r
-\r
-\r
+/* rfxswf.c
+
+ Library for creating and reading SWF files or parts of it.
+ There's a module directory which provides some extended functionality.
+ Most modules are included at the bottom of this file.
+
+ Part of the swftools package.
+
+ Copyright (c) 2000, 2001 Rainer Böhme <rfxswf@reflex-studio.de>
+
+ This file is distributed under the GPL, see file COPYING for details
+
+*/
+
+#include "rfxswf.h"
+
+#ifdef HAVE_LIBJPEG
+#ifdef HAVE_JPEGLIB_H
+#include <jpeglib.h>
+#define _JPEGLIB_INCLUDED_
+#endif //HAVE_JPEGLIB_H
+#endif //HAVE_LIBJPEG
+
+// Win32 support may be broken since it was only tested in an older version for Watcom C
+#ifdef __NT__
+# include <io.h>
+# include <malloc.h>
+# include <string.h>
+# ifdef DEBUG_RFXSWF
+# include <stdio.h>
+# endif
+#else
+#endif
+
+// internal constants
+
+#define MALLOC_SIZE 128
+#define INSERT_RFX_TAG
+
+#define MEMSIZE(l) (((l/MALLOC_SIZE)+1)*MALLOC_SIZE)
+
+// inline wrapper functions
+
+TAG * NextTag(TAG * t) { return t->next; }
+TAG * PrevTag(TAG * t) { return t->prev; }
+int GetFrameNo(TAG * t) { return t->frame; }
+U16 GetTagID(TAG * t) { return t->id; }
+U32 GetDataSize(TAG * t) { return t->len; }
+U8* GetDataSizePtr(TAG * t) { return &(t->data[t->len]); }
+U32 GetTagPos(TAG * t) { return t->pos; }
+
+// Basic Data Access Functions
+
+#define ResetBitmask(tag) if (tag->bitmask) { tag->pos++; tag->bitmask = 0; }
+#define ResetBitcount(tag) if (tag->bitcount) { tag->bitcount = 0; }
+
+// for future purpose: avoid high level lib functions to change tagpos/bitcount
+
+#define SaveTagPos(tag)
+#define RestoreTagPos(tag)
+
+void SetTagPos(TAG * t,U32 pos)
+{ ResetBitmask(t);
+ if (pos<=t->len) t->pos = pos;
+ #ifdef DEBUG_RFXSWF
+ else fprintf(stderr,"SetTagPos() out of bounds: TagID = %i\n",t->id);
+ #endif
+}
+
+U8 GetU8(TAG * t)
+{ ResetBitmask(t);
+ #ifdef DEBUG_RFXSWF
+ if (t->pos>=t->len)
+ { fprintf(stderr,"GetU8() out of bounds: TagID = %i\n",t->id);
+ return 0;
+ }
+ #endif
+ return t->data[t->pos++];
+}
+
+U16 GetU16(TAG * t)
+{ U16 res;
+ ResetBitmask(t);
+ #ifdef DEBUG_RFXSWF
+ if (t->pos>(t->len-2))
+ { fprintf(stderr,"GetU16() out of bounds: TagID = %i\n",t->id);
+ return 0;
+ }
+ #endif
+ res = t->data[t->pos] | (t->data[t->pos+1]<<8);
+ t->pos+=2;
+ return res;
+}
+
+U32 GetU32(TAG * t)
+{ U32 res;
+ ResetBitmask(t);
+ #ifdef DEBUG_RFXSWF
+ if (t->pos>(t->len-4))
+ { fprintf(stderr,"GetU32() out of bounds: TagID = %i\n",t->id);
+ return 0;
+ }
+ #endif
+ res = t->data[t->pos] | (t->data[t->pos+1]<<8) |
+ (t->data[t->pos+2]<<16) | (t->data[t->pos+3]<<24);
+ t->pos+=4;
+ return res;
+}
+
+int GetBlock(TAG * t,U8 * b,int l)
+// returns number of bytes written (<=l)
+// b = NULL -> skip data
+{ ResetBitmask(t);
+ if ((t->len-t->pos)<l) l=t->len-t->pos;
+ if (b && l) memcpy(b,&t->data[t->pos],l);
+ t->pos+=l;
+ return l;
+}
+
+int SetBlock(TAG * t,U8 * b,int l)
+// Appends Block to the end of Tagdata, returns size
+{ U32 newlen = t->len + l;
+ ResetBitcount(t);
+ if (newlen>t->memsize)
+ { U32 newmem = MEMSIZE(newlen);
+ U8 * newdata = (U8*)((t->data)?realloc(t->data,newmem):malloc(newmem));
+ if (!newdata)
+ {
+ #ifdef DEBUG_RFXSWF
+ fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n");
+ #endif
+ return 0;
+ }
+ t->memsize = newmem;
+ t->data = newdata;
+ }
+ if (b) memcpy(&t->data[t->len],b,l);
+ else memset(&t->data[t->len],0x00,l);
+ t->len+=l;
+ return l;
+}
+
+int SetU8(TAG * t,U8 v)
+{ ResetBitcount(t);
+ if ((t->len+1)>t->memsize) return (SetBlock(t,&v,1)==1)?0:-1;
+ t->data[t->len++] = v;
+ return 0;
+}
+
+int SetU16(TAG * t,U16 v)
+{ U8 a[2];
+ a[0] = v&0xff;
+ a[1] = v>>8;
+
+ ResetBitcount(t);
+ if ((t->len+2)>t->memsize) return (SetBlock(t,a,2)==2)?0:-1;
+ t->data[t->len++] = a[0];
+ t->data[t->len++] = a[1];
+ return 0;
+}
+
+int SetU32(TAG * t,U32 v)
+{ U8 a[4];
+ a[0] = v&0xff; // to ensure correct handling of non-intel byteorder
+ a[1] = (v>>8)&0xff;
+ a[2] = (v>>16)&0xff;
+ a[3] = (v>>24)&0xff;
+
+ ResetBitcount(t);
+ if ((t->len+4)>t->memsize) return (SetBlock(t,a,4)==4)?0:-1;
+ t->data[t->len++] = a[0];
+ t->data[t->len++] = a[1];
+ t->data[t->len++] = a[2];
+ t->data[t->len++] = a[3];
+ return 0;
+}
+
+U32 GetBits(TAG * t,int nbits)
+{ U32 res = 0;
+ if (!nbits) return 0;
+ if (!t->bitmask) t->bitmask = 0x80;
+ while (nbits)
+ { res<<=1;
+ if (t->data[t->pos]&t->bitmask) res|=1;
+ t->bitmask>>=1;
+ nbits--;
+ if (!t->bitmask)
+ { if (nbits) t->bitmask = 0x80;
+ #ifdef DEBUG_RFXSWF
+ if (t->pos>=t->len)
+ { fprintf(stderr,"GetBits() out of bounds: TagID = %i\n",t->id);
+ return res;
+ }
+ #endif
+ t->pos++;
+ }
+ }
+ return res;
+}
+
+S32 GetSBits(TAG * t,int nbits)
+{ U32 res = GetBits(t,nbits);
+ if (res&(1<<(nbits-1))) res|=(0xffffffff<<nbits);
+ return (S32)res;
+}
+
+int SetBits(TAG * t,U32 v,int nbits)
+{ U32 bm = 1<<(nbits-1);
+
+ while (nbits)
+ { if (!t->bitcount)
+ { if (FAILED(SetU8(t,0))) return -1;
+ t->bitcount = 0x80;
+ }
+ if (v&bm) t->data[t->len-1] |= t->bitcount;
+ bm>>=1;
+ t->bitcount>>=1;
+ nbits--;
+ }
+ return 0;
+}
+
+// Advanced Data Access Functions
+
+int SetRGB(TAG * t,RGBA * col)
+{ if (!t) return -1;
+ if (col)
+ { SetU8(t,col->r);
+ SetU8(t,col->g);
+ SetU8(t,col->b);
+ } else SetBlock(t,NULL,3);
+ return 0;
+}
+
+int SetRGBA(TAG * t,RGBA * col)
+{ if (!t) return -1;
+ if (col)
+ { SetU8(t,col->r);
+ SetU8(t,col->g);
+ SetU8(t,col->b);
+ SetU8(t,col->a);
+ } else SetBlock(t,NULL,4);
+ return 0;
+}
+
+int CountBits(U32 v,int nbits)
+{ int n = 33;
+ U32 m = 0x80000000;
+ if (!v) n = 0; else
+ if (v&m)
+ { while (v&m)
+ { n--;
+ m>>=1;
+ if (!m) break;
+ }
+ }
+ else
+ { while (!(v&m))
+ { n--;
+ m>>=1;
+ if (!m) break;
+ }
+ }
+ return (n>nbits)?n:nbits;
+}
+
+int GetRect(TAG * t,SRECT * r)
+{ int nbits;
+ SRECT dummy;
+ if (!r) r = &dummy;
+ nbits = (int) GetBits(t,5);
+ r->xmin = GetSBits(t,nbits);
+ r->xmax = GetSBits(t,nbits);
+ r->ymin = GetSBits(t,nbits);
+ r->ymax = GetSBits(t,nbits);
+ return 0;
+}
+
+int SetRect(TAG * t,SRECT * r)
+{ int nbits;
+
+ nbits = CountBits(r->xmin,0);
+ nbits = CountBits(r->xmax,nbits);
+ nbits = CountBits(r->ymin,nbits);
+ nbits = CountBits(r->ymax,nbits);
+
+ SetBits(t,nbits,5);
+ SetBits(t,r->xmin,nbits);
+ SetBits(t,r->xmax,nbits);
+ SetBits(t,r->ymin,nbits);
+ SetBits(t,r->ymax,nbits);
+
+ return 0;
+}
+
+int GetMatrix(TAG * t,MATRIX * m)
+{ MATRIX dummy;
+ int nbits;
+
+ if (!m) m = &dummy;
+
+ if (!t)
+ { m->sx = m->sy = 0x10000;
+ m->r0 = m->r1 = 0;
+ m->tx = m->ty = 0;
+ return -1;
+ }
+
+ ResetBitmask(t);
+
+ if (GetBits(t,1))
+ { nbits = GetBits(t,5);
+ m->sx = GetSBits(t,nbits);
+ m->sy = GetSBits(t,nbits);
+ }
+ else m->sx = m->sy = 0x10000;
+
+ if (GetBits(t,1))
+ { nbits = GetBits(t,5);
+ m->r0 = GetSBits(t,nbits);
+ m->r1 = GetSBits(t,nbits);
+ }
+ else m->r0 = m->r1 = 0x0;
+
+ nbits = GetBits(t,5);
+ m->tx = GetSBits(t,nbits);
+ m->ty = GetSBits(t,nbits);
+
+ return 0;
+}
+
+int SetMatrix(TAG * t,MATRIX * m)
+{ int nbits;
+ MATRIX ma;
+
+ if (!m)
+ { m = &ma;
+ ma.sx = ma.sy = 0x10000;
+ ma.r0 = ma.r1 = 0;
+ ma.tx = ma.ty = 0;
+ }
+
+ ResetBitcount(t);
+
+ if ((m->sx==0x10000)&&(m->sy==0x10000)) SetBits(t,0,1);
+ else
+ { SetBits(t,1,1);
+ nbits = CountBits(m->sx,0);
+ nbits = CountBits(m->sy,nbits);
+ SetBits(t,nbits,5);
+ SetBits(t,m->sx,nbits);
+ SetBits(t,m->sy,nbits);
+ }
+
+ if ((!m->r0)&&(!m->r1)) SetBits(t,0,1);
+ else
+ { SetBits(t,1,1);
+ nbits = CountBits(m->r0,0);
+ nbits = CountBits(m->r1,nbits);
+ SetBits(t,nbits,5);
+ SetBits(t,m->r0,nbits);
+ SetBits(t,m->r1,nbits);
+ }
+
+ nbits = CountBits(m->tx,0);
+ nbits = CountBits(m->ty,nbits);
+ SetBits(t,nbits,5);
+ SetBits(t,m->tx,nbits);
+ SetBits(t,m->ty,nbits);
+
+ return 0;
+}
+
+int GetCXForm(TAG * t,CXFORM * cx,U8 alpha) //FIXME: alpha should be type bool
+{ CXFORM cxf;
+ int hasadd;
+ int hasmul;
+ int nbits;
+
+ if (!cx) cx = &cxf;
+
+ cx->a0 = cx->r0 = cx->g0 = cx->b0 = 256;
+ cx->a1 = cx->r1 = cx->g1 = cx->b1 = 0;
+
+ if (!t) return 0;
+
+ ResetBitmask(t);
+ hasadd = GetBits(t,1);
+ hasmul = GetBits(t,1);
+ nbits = GetBits(t,4);
+
+ if (hasmul)
+ { cx->r0 = (S16)GetSBits(t,nbits);
+ cx->g0 = (S16)GetSBits(t,nbits);
+ cx->b0 = (S16)GetSBits(t,nbits);
+ if (alpha)
+ cx->a0 = (S16)GetSBits(t,nbits);
+ }
+
+ if (hasadd)
+ { cx->r1 = (S16)GetSBits(t,nbits);
+ cx->g1 = (S16)GetSBits(t,nbits);
+ cx->b1 = (S16)GetSBits(t,nbits);
+ if (alpha)
+ cx->a1 = (S16)GetSBits(t,nbits);
+ }
+
+ return 0;
+}
+
+int SetCXForm(TAG * t,CXFORM * cx,U8 alpha)
+{ CXFORM cxf;
+ int hasadd;
+ int hasmul;
+ int nbits;
+
+ if (!cx)
+ { cx = &cxf;
+ cx->a0 = cx->r0 = cx->g0 = cx->b0 = 256;
+ cx->a1 = cx->r1 = cx->g1 = cx->b1 = 0;
+ }
+
+ if (!alpha)
+ { cx->a0 = 256;
+ cx->a1 = 0;
+ }
+
+ nbits = 0;
+
+ hasmul = (cx->a0!=256)||(cx->r0!=256)||(cx->g0!=256)||(cx->b0!=256);
+ hasadd = cx->a1|cx->r1|cx->g1|cx->b1;
+
+ if (hasmul)
+ { if (alpha) nbits = CountBits((S32)cx->a0,nbits);
+ nbits = CountBits((S32)cx->r0,nbits);
+ nbits = CountBits((S32)cx->g0,nbits);
+ nbits = CountBits((S32)cx->b0,nbits);
+ }
+
+ if (hasadd)
+ { if (alpha) nbits = CountBits((S32)cx->a1,nbits);
+ nbits = CountBits((S32)cx->r1,nbits);
+ nbits = CountBits((S32)cx->g1,nbits);
+ nbits = CountBits((S32)cx->b1,nbits);
+ }
+
+ ResetBitcount(t);
+ SetBits(t,hasadd?1:0,1);
+ SetBits(t,hasmul?1:0,1);
+ SetBits(t,nbits,4);
+
+ if (hasmul)
+ { SetBits(t,cx->r0,nbits);
+ SetBits(t,cx->g0,nbits);
+ SetBits(t,cx->b0,nbits);
+ if (alpha) SetBits(t,cx->a0,nbits);
+ }
+
+ if (hasadd)
+ { SetBits(t,cx->r1,nbits);
+ SetBits(t,cx->g1,nbits);
+ SetBits(t,cx->b1,nbits);
+ if (alpha) SetBits(t,cx->a1,nbits);
+ }
+
+ return 0;
+}
+
+int GetPoint(TAG * t,SPOINT * p) { return 0; }
+int SetPoint(TAG * t,SPOINT * p) { return 0; }
+
+// Tag List Manipulating Functions
+
+int RFXSWF_UpdateFrame(TAG * t,S8 delta)
+// returns number of frames
+{ int res = -1;
+ while (t)
+ { t->frame+=delta;
+ res = t->frame;
+ t = t->next;
+ }
+ return res;
+}
+
+#define UpdateFrame(a,b) RFXSWF_UpdateFrame(a,b)
+
+TAG * InsertTag(TAG * after,U16 id) // updates frames, if nescessary
+{ TAG * t;
+
+ t = (TAG *)malloc(sizeof(TAG));
+ if (t)
+ { memset(t,0x00,sizeof(TAG));
+ t->id = id;
+ t->bitcount = 0x80;
+
+ if (after)
+ { t->frame = after->frame;
+ t->prev = after;
+ t->next = after->next;
+ after->next = t;
+ if (t->next) t->next->prev = t;
+
+ if (id==ST_SHOWFRAME) UpdateFrame(t->next,+1);
+ }
+ }
+ return t;
+}
+
+int DeleteTag(TAG * t)
+{ if (!t) return -1;
+
+ if (t->id==ST_SHOWFRAME) UpdateFrame(t->next,-1);
+
+ if (t->prev) t->prev->next = t->next;
+ if (t->next) t->next->prev = t->prev;
+
+ if (t->data) free(t->data);
+ free(t);
+ return 0;
+}
+
+TAG * RFXSWF_ReadTag(int handle,TAG * prev)
+{ TAG * t;
+ U16 raw;
+ U32 len;
+ int id;
+
+ if (read(handle,&raw,2)!=2) return NULL;
+
+ len = raw&0x3f;
+ id = raw>>6;
+
+ if (len==0x3f)
+ { if (read(handle,&len,4)!=4) return NULL;
+ }
+
+ if (id==ST_DEFINESPRITE) len = 2*sizeof(U16);
+ // Sprite handling fix: Flaten sprite tree
+
+ t = (TAG *)malloc(sizeof(TAG));
+
+ if (!t)
+ {
+ #ifdef DEBUG_RFXSWF
+ fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n");
+ #endif
+ return NULL;
+ }
+
+ memset(t,0x00,sizeof(TAG));
+
+ t->len = len;
+ t->id = id;
+
+ if (t->len)
+ { t->data = (U8*)malloc(t->len);
+ if (!t->data)
+ {
+ #ifdef DEBUG_RFXSWF
+ fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n");
+ #endif
+ return NULL;
+ }
+ t->memsize = t->len;
+ if (read(handle,t->data,t->len)!=t->len) return NULL;
+ }
+
+ if (prev)
+ { t->frame = prev->frame+((prev->id==ST_SHOWFRAME)?1:0);
+ t->prev = prev;
+ prev->next = t;
+ }
+
+ return t;
+}
+
+int DefineSprite_GetRealSize(TAG * t);
+
+int RFXSWF_WriteTag(int handle,TAG * t)
+// returns tag length in bytes (incl. Header), -1 = Error
+// handle = -1 -> no output
+{ U16 raw[3];
+ U32 len;
+ int short_tag;
+
+ if (!t) return -1;
+
+ len = (t->id==ST_DEFINESPRITE)?DefineSprite_GetRealSize(t):t->len;
+
+ short_tag = len<0x3f;
+
+ if (handle>=0)
+ { if (short_tag)
+ { raw[0] = len|((t->id&0x3ff)<<6);
+ if (write(handle,raw,2)!=2)
+ {
+ #ifdef DEBUG_RFXSWF
+ fprintf(stderr,"WriteTag() failed: Short Header.\n");
+ #endif
+ return -1;
+ }
+ }
+ else
+ { raw[0] = (t->id<<6)|0x3f;
+ raw[1] = (U16)(len&0xffff);
+ raw[2] = (U16)(len>>16);
+ if (write(handle,raw,6)!=6)
+ {
+ #ifdef DEBUG_RFXSWF
+ fprintf(stderr,"WriteTag() failed: Long Header.\n");
+ #endif
+ return -1;
+ }
+ }
+
+ if (t->data)
+ { if (write(handle,t->data,t->len)!=t->len)
+ {
+ #ifdef DEBUG_RFXSWF
+ fprintf(stderr,"WriteTag() failed: Data.\n");
+ #endif
+ return -1;
+ }
+ }
+ #ifdef DEBUG_RFXSWF
+ else if (t->len) fprintf(stderr,"WriteTag(): Tag Data Error, id=%i\n",t->id);
+ #endif
+ }
+
+ return t->len+(short_tag?2:6);
+}
+
+int DefineSprite_GetRealSize(TAG * t)
+// Sprite Handling: Helper function to pack DefineSprite-Tag
+{ U32 len = t->len;
+ do
+ { t = NextTag(t);
+ if (t->id!=ST_DEFINESPRITE) len += RFXSWF_WriteTag(-1,t);
+ else t = NULL;
+ } while (t&&(t->id!=ST_END));
+ return len;
+}
+
+#define ReadTag(a,b) RFXSWF_ReadTag(a,b)
+#define WriteTag(a,b) RFXSWF_WriteTag(a,b)
+
+// Movie Functions
+
+int ReadSWF(int handle,SWF * swf) // Reads SWF to memory (malloc'ed), returns length or <0 if fails
+{
+ if (!swf) return -1;
+ memset(swf,0x00,sizeof(SWF));
+
+ { char b[32]; // Header lesen
+ TAG t1;
+ TAG * t;
+
+ memset(&t1,0x00,sizeof(TAG));
+
+ if ((t1.len=read(handle,b,32))<21) return -1;
+ t1.data = (U8*)b;
+
+ if (GetU8(&t1)!=(U8)'F') return -1;
+ if (GetU8(&t1)!=(U8)'W') return -1;
+ if (GetU8(&t1)!=(U8)'S') return -1;
+
+ swf->FileVersion = GetU8(&t1);
+ swf->FileSize = GetU32(&t1);
+ GetRect(&t1,&swf->MovieSize);
+ swf->FrameRate = GetU16(&t1);
+ swf->FrameCount = GetU16(&t1);
+
+ GetU8(&t1);
+ lseek(handle,GetTagPos(&t1)-1,SEEK_SET);
+
+ // Tags lesen und verketten
+ t = &t1;
+ while (t) t = ReadTag(handle,t);
+ swf->FirstTag = t1.next;
+ t1.next->prev = NULL;
+ }
+
+ return 0;
+}
+int WriteSWF(int handle,SWF * swf) // Writes SWF to file, returns length or <0 if fails
+{ U32 len;
+ TAG * t;
+
+ if (!swf) return -1;
+
+ // Insert REFLEX Tag
+
+#ifdef INSERT_RFX_TAG
+
+ if (NextTag(swf->FirstTag))
+ if (GetTagID(NextTag(swf->FirstTag))!=ST_REFLEX)
+ SetBlock(InsertTag(swf->FirstTag,ST_REFLEX),"rfx",3);
+
+#endif // INSERT_RFX_TAG
+
+ // Count Frames + File Size
+
+ len = 0;
+ t = swf->FirstTag;
+ swf->FrameCount = 0;
+
+ while(t)
+ { len += WriteTag(-1,t);
+ if (t->id==ST_SHOWFRAME) swf->FrameCount++;
+ t = NextTag(t);
+ }
+
+ { TAG t1;
+ char b[64];
+ U32 l;
+
+ memset(&t1,0x00,sizeof(TAG));
+ t1.data = (U8*)b;
+ t1.memsize = 64;
+
+ SetU8(&t1,'F');
+ SetU8(&t1,'W');
+ SetU8(&t1,'S');
+ SetU8(&t1,swf->FileVersion);
+
+ SetU32(&t1,0); // Keep space for filesize
+ SetRect(&t1,&swf->MovieSize);
+ SetU16(&t1,swf->FrameRate);
+ SetU16(&t1,swf->FrameCount);
+
+ l = GetDataSize(&t1);
+ swf->FileSize = l+len;
+ t1.len = 4; // bad & ugly trick !
+ SetU32(&t1,swf->FileSize);
+
+ if (handle>=0)
+ {
+ int ret = write(handle,b,l);
+ if (ret!=l)
+ {
+ #ifdef DEBUG_RFXSWF
+ printf("ret:%d (fd:%d)\n",ret, handle);
+ perror("write:");
+ fprintf(stderr,"WriteSWF() failed: Header.\n");
+ #endif
+ return -1;
+ }
+
+ t = swf->FirstTag;
+ while (t)
+ { if (WriteTag(handle,t)<0) return -1;
+ t = NextTag(t);
+ }
+ }
+ }
+ return (int)swf->FileSize;
+}
+
+int WriteCGI(SWF * swf)
+{ int len;
+ char s[1024];
+
+ len = WriteSWF(-1,swf);
+
+ if (len<0) return -1;
+
+ sprintf(s,"Content-type: application/x-shockwave-flash\n"
+ "Accept-Ranges: bytes\n"
+ "Content-Length: %lu\n"
+ "Expires: Thu, 13 Apr 2000 23:59:59 GMT\n"
+ "\n",len);
+
+ write(fileno(stdout),s,strlen(s));
+ return WriteSWF(fileno(stdout),swf);
+}
+
+void FreeTags(SWF * swf) // Frees all malloc'ed memory for tags
+{ TAG * t = swf->FirstTag;
+
+ while (t)
+ { TAG * tnew = t->next;
+ if (t->data) free(t->data);
+ free(t);
+ t = tnew;
+ }
+}
+
+// include advanced functions
+
+#ifdef __NT__
+
+#include "modules\swfdump.c"
+#include "modules\swfshape.c"
+#include "modules\swftext.c"
+#include "modules\swfobject.c"
+#include "modules\swfbutton.c"
+#include "modules\swftools.c"
+#include "modules\swfcgi.c"
+#include "modules\swfbits.c"
+
+#else
+
+#include "modules/swfdump.c"
+#include "modules/swfshape.c"
+#include "modules/swftext.c"
+#include "modules/swfobject.c"
+#include "modules/swfbutton.c"
+#include "modules/swftools.c"
+#include "modules/swfcgi.c"
+#include "modules/swfbits.c"
+
+#endif
+
+
-/* rfxswf.h\r
-\r
- Headers for rfxswf.c and modules\r
-\r
- Part of the swftools package.\r
-\r
- Copyright (c) 2000, 2001 Rainer Böhme <rfxswf@reflex-studio.de>\r
- \r
- This file is distributed under the GPL, see file COPYING for details \r
-\r
-*/\r
-\r
-#ifndef __RFX_SWF_INCLUDED__\r
-#define __RFX_SWF_INCLUDED__\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include "../config.h"\r
-#include "old_rfxswf.h"\r
-\r
-#define DEBUG_RFXSWF\r
-\r
-// SWF Types\r
-\r
-typedef unsigned long U32;\r
-typedef signed long S32;\r
-typedef unsigned short U16;\r
-typedef signed short S16;\r
-typedef unsigned char U8;\r
-typedef signed char S8;\r
-typedef signed long SFIXED;\r
-typedef signed long SCOORD;\r
-\r
-// Basic Structures\r
-\r
-typedef struct _SPOINT\r
-{ SCOORD x;\r
- SCOORD y;\r
-} SPOINT, * LPSPOINT;\r
-\r
-typedef struct _RGBA\r
-{ U8 r;\r
- U8 g;\r
- U8 b;\r
- U8 a;\r
-} RGBA, * LPRGBA;\r
-\r
-typedef struct _SRECT\r
-{ SCOORD xmin;\r
- SCOORD ymin;\r
- SCOORD xmax;\r
- SCOORD ymax;\r
-} SRECT, * LPSRECT;\r
-\r
-typedef struct _MATRIX\r
-{ SFIXED sx; // factor x\r
- SFIXED sy;\r
- SFIXED r0; // rotation\r
- SFIXED r1;\r
- SCOORD tx; // delta x\r
- SCOORD ty;\r
-} MATRIX, * LPMATRIX;\r
-\r
-typedef struct _CXFORM\r
-{ S16 a0, a1;\r
- S16 r0, r1;\r
- S16 g0, g1;\r
- S16 b0, b1;\r
-} CXFORM, * LPCXFORM;\r
-\r
-typedef struct _TAG // NEVER access a Tag-Struct directly !\r
-{ U16 id;\r
- U32 len;\r
- U8 * data;\r
-\r
- int frame;\r
-\r
- struct _TAG * next;\r
- struct _TAG * prev;\r
-\r
- U32 memsize; // to minimize realloc() calls\r
- U32 pos; // for Get/Set-Access\r
- U8 bitmask; // for Bit-Manipulating Functions [read]\r
- U8 bitcount; // [write]\r
-} TAG, * LPTAG;\r
-\r
-typedef struct _SWF\r
-{ U8 FileVersion;\r
- U32 FileSize; // valid after load and save\r
- SRECT MovieSize;\r
- U16 FrameRate;\r
- U16 FrameCount; // valid after load and save\r
- LPTAG FirstTag;\r
-} SWF, * LPSWF;\r
-\r
-// Basic Functions\r
-\r
-int ReadSWF(int handle,LPSWF swf); // Reads SWF to memory (malloc'ed), returns length or <0 if fails\r
-int WriteSWF(int handle,LPSWF swf); // Writes SWF to file, returns length or <0 if fails\r
-int WriteCGI(LPSWF swf); // Outputs SWF with valid CGI header to stdout\r
-void FreeTags(LPSWF swf); // Frees all malloc'ed memory for swf\r
- \r
-LPTAG InsertTag(LPTAG after,U16 id); // updates frames, if necessary\r
-int DeleteTag(LPTAG t);\r
-\r
-void SetTagPos(LPTAG t,U32 pos); // resets Bitcount\r
-U32 GetTagPos(LPTAG t);\r
-\r
-LPTAG NextTag(LPTAG t);\r
-LPTAG PrevTag(LPTAG t);\r
-\r
-int GetFrameNo(LPTAG t);\r
-U16 GetTagID(LPTAG t);\r
-U32 GetDataSize(LPTAG t);\r
-U8* GetDataSizePtr(LPTAG t);\r
-\r
-U32 GetBits(LPTAG t,int nbits);\r
-S32 GetSBits(LPTAG t,int nbits);\r
-int SetBits(LPTAG t,U32 v,int nbits);\r
-\r
-int GetBlock(LPTAG t,U8 * b,int l); // resets Bitcount\r
-int SetBlock(LPTAG t,U8 * b,int l);\r
-\r
-U8 GetU8(LPTAG t); // resets Bitcount\r
-U16 GetU16(LPTAG t);\r
-U32 GetU32(LPTAG t);\r
-\r
-int SetU8(LPTAG t,U8 v); // resets Bitcount\r
-int SetU16(LPTAG t,U16 v);\r
-int SetU32(LPTAG t,U32 v);\r
-\r
-int GetPoint(LPTAG t,LPSPOINT p); // resets Bitcount\r
-int GetRect(LPTAG t,LPSRECT r);\r
-int GetMatrix(LPTAG t,LPMATRIX m);\r
-int GetCXForm(LPTAG t,LPCXFORM cx,U8 alpha);\r
-\r
-int SetPoint(LPTAG t,LPSPOINT p); // resets Bitcount\r
-int SetRect(LPTAG t,LPSRECT r);\r
-int SetMatrix(LPTAG t,LPMATRIX m);\r
-int SetCXForm(LPTAG t,LPCXFORM cx,U8 alpha);\r
-int SetRGB(LPTAG t,LPRGBA col);\r
-int SetRGBA(LPTAG t,LPRGBA col);\r
-\r
-// Function Macros\r
-\r
-#define GetS8(tag) ((S8)GetU8(tag))\r
-#define GetS16(tag) ((S16)GetU16(tag))\r
-#define GetS32(tag) ((S32)GetU32(tag))\r
-#define GetCoord(tag) ((SCOORD)GetU32(tag))\r
-#define GetFixed(tag) ((SFIXED)GetU32(tag))\r
-\r
-#define SetS8(tag,v) SetU8(tag,(U8)v)\r
-#define SetS16(tag,v) SetU16(tag,(U16)v)\r
-#define SetS32(tag,v) SetU32(tag,(U32)v)\r
-#define SetCoord(tag,v) SetU32(tag,(U32)v)\r
-#define SetFixed(tag,v) SetU32(tag,(U32)v)\r
-#define SetString(t,s) SetBlock(t,s,strlen(s)+1)\r
-\r
-#define FAILED(b) ((b)<0)\r
-#define SUCCEDED(b) ((b)>=0)\r
-\r
-// Tag IDs (adopted from J. C. Kessels' Form2Flash)\r
-\r
-#define ST_END 0\r
-#define ST_SHOWFRAME 1\r
-#define ST_DEFINESHAPE 2\r
-#define ST_FREECHARACTER 3\r
-#define ST_PLACEOBJECT 4\r
-#define ST_REMOVEOBJECT 5\r
-#define ST_DEFINEBITS 6\r
-#define ST_DEFINEBUTTON 7\r
-#define ST_JPEGTABLES 8\r
-#define ST_SETBACKGROUNDCOLOR 9\r
-#define ST_DEFINEFONT 10\r
-#define ST_DEFINETEXT 11\r
-#define ST_DOACTION 12\r
-#define ST_DEFINEFONTINFO 13\r
-#define ST_DEFINESOUND 14 /* Event sound tags. */\r
-#define ST_STARTSOUND 15\r
-#define ST_DEFINEBUTTONSOUND 17\r
-#define ST_SOUNDSTREAMHEAD 18\r
-#define ST_SOUNDSTREAMBLOCK 19\r
-#define ST_DEFINEBITSLOSSLESS 20 /* A bitmap using lossless zlib compression. */\r
-#define ST_DEFINEBITSJPEG2 21 /* A bitmap using an internal JPEG compression table. */\r
-#define ST_DEFINESHAPE2 22\r
-#define ST_DEFINEBUTTONCXFORM 23\r
-#define ST_PROTECT 24 /* This file should not be importable for editing. */\r
-#define ST_PLACEOBJECT2 26 /* The new style place w/ alpha color transform and name. */\r
-#define ST_REMOVEOBJECT2 28 /* A more compact remove object that omits the character tag (just depth). */\r
-#define ST_DEFINESHAPE3 32 /* A shape V3 includes alpha values. */\r
-#define ST_DEFINETEXT2 33 /* A text V2 includes alpha values. */\r
-#define ST_DEFINEBUTTON2 34 /* A button V2 includes color transform, alpha and multiple actions */\r
-#define ST_DEFINEBITSJPEG3 35 /* A JPEG bitmap with alpha info. */\r
-#define ST_DEFINEBITSLOSSLESS2 36 /* A lossless bitmap with alpha info. */\r
-#define ST_DEFINEEDITTEXT 37\r
-#define ST_DEFINEMOVIE 38\r
-#define ST_DEFINESPRITE 39 /* Define a sequence of tags that describe the behavior of a sprite. */\r
-#define ST_NAMECHARACTER 40 /* Name a character definition, character id and a string, (used for buttons, bitmaps, sprites and sounds). */\r
-#define ST_SERIALNUMBER 41\r
-#define ST_GENERATORTEXT 42 /* contains an id */\r
-#define ST_FRAMELABEL 43 /* A string label for the current frame. */\r
-#define ST_SOUNDSTREAMHEAD2 45 /* For lossless streaming sound, should not have needed this... */\r
-#define ST_DEFINEMORPHSHAPE 46 /* A morph shape definition */\r
-#define ST_DEFINEFONT2 48\r
-#define ST_TEMPLATECOMMAND 49\r
-#define ST_GENERATOR3 51\r
-#define ST_EXTERNALFONT 52\r
-\r
-#define ST_REFLEX 777 /* to identify generator software */\r
-\r
-// Advanced Funtions\r
-\r
-// swfdump.c\r
-\r
-void DumpHeader(FILE * f,LPSWF swf);\r
-void DumpMatrix(FILE * f,LPMATRIX m);\r
-void DumpTag(FILE * f,LPTAG t); \r
-char* getTagName(TAG*tag);\r
-\r
-// swfshape.c\r
-\r
-typedef struct _LINESTYLE\r
-{ U16 width;\r
- RGBA color;\r
-} LINESTYLE, * LPLINESTYLE;\r
-\r
-typedef struct _FILLSTYLE\r
-{ U8 type;\r
- RGBA color;\r
- MATRIX m; \r
- U16 id_bitmap;\r
-} FILLSTYLE, * LPFILLSTYLE;\r
- \r
-typedef struct _SHAPE // NEVER access a Shape-Struct directly !\r
-{ \r
- struct\r
- { LPLINESTYLE data;\r
- U16 n;\r
- } linestyle;\r
- // note: changes of shape structure\r
- struct // lead to incompatible .efont formats\r
- { LPFILLSTYLE data;\r
- U16 n;\r
- } fillstyle;\r
-\r
- S32 px;\r
- S32 py;\r
- \r
- struct\r
- { U16 fill;\r
- U16 line;\r
- } bits;\r
- \r
- U8 * data;\r
- U32 bitlen; // length of data in bits\r
-} SHAPE, * LPSHAPE;\r
-\r
-// Shapes\r
-\r
-int NewShape(LPSHAPE * s);\r
-void ShapeFree(LPSHAPE s);\r
-\r
-int GetSimpleShape(LPTAG t,LPSHAPE * s); // without Linestyle/Fillstyle Record\r
-int SetSimpleShape(LPTAG t,LPSHAPE s); // without Linestyle/Fillstyle Record\r
-\r
-int ShapeAddLineStyle(LPSHAPE s,U16 width,LPRGBA color);\r
-int ShapeAddSolidFillStyle(LPSHAPE s,LPRGBA color);\r
-int ShapeAddBitmapFillStyle(LPSHAPE s,LPMATRIX m,U16 id_bitmap,int clip);\r
-\r
-int SetShapeStyles(LPTAG t,LPSHAPE s);\r
-int ShapeCountBits(LPSHAPE s,U8 * fbits,U8 * lbits);\r
-int SetShapeBits(LPTAG t,LPSHAPE s);\r
-int SetShapeHeader(LPTAG t,LPSHAPE s); // one call for upper three functions\r
-\r
-int ShapeSetMove(LPTAG t,LPSHAPE s,S32 x,S32 y);\r
-int ShapeSetStyle(LPTAG t,LPSHAPE s,U16 line,U16 fill0,U16 fill1);\r
-int ShapeSetAll(LPTAG t,LPSHAPE s,S32 x,S32 y,U16 line,U16 fill0,U16 fill1);\r
-\r
-int ShapeSetLine(LPTAG t,LPSHAPE s,S32 x,S32 y);\r
-int ShapeSetCurve(LPTAG t,LPSHAPE s,S32 x,S32 y,S32 ax,S32 ay);\r
-int ShapeSetCircle(LPTAG t,LPSHAPE s,S32 x,S32 y,S32 rx,S32 ry);\r
-int ShapeSetEnd(LPTAG t);\r
-\r
-\r
-// swffont.c\r
-\r
-// does not support wide characters !\r
-\r
-#define MAX_CHAR_PER_FONT 256\r
-\r
-typedef struct _SWFLAYOUT\r
-{ S16 ascent;\r
- S16 descent;\r
- S16 leading;\r
- SRECT bounds[MAX_CHAR_PER_FONT];\r
- struct\r
- { U16 count;\r
- U8 * data; // size = count*4 bytes\r
- } kerning;\r
-} SWFLAYOUT, * LPSWFLAYOUT;\r
-\r
-typedef struct _SWFFONT\r
-{ U16 id;\r
- U8 * name;\r
- LPSWFLAYOUT layout;\r
-\r
- U8 flags; // bold/italic/unicode/ansi ...\r
-\r
- U16 codes[MAX_CHAR_PER_FONT];\r
- \r
- struct\r
- { U16 advance;\r
- U16 gid; // Glyph-ID after DefineFont\r
- LPSHAPE shape;\r
- } glyph[MAX_CHAR_PER_FONT];\r
-} SWFFONT, * LPSWFFONT;\r
-\r
-typedef struct _FONTUSAGE\r
-{ U8 code[MAX_CHAR_PER_FONT];\r
-} FONTUSAGE, * LPFONTUSAGE;\r
-\r
-int FontEnumerate(LPSWF swf,void (*FontCallback) (U16,U8*));\r
-// -> void fontcallback(U16 id,U8 * name); returns number of defined fonts\r
-\r
-int FontExtract(LPSWF swf,int id,LPSWFFONT * f);\r
-// Fetches all available information from DefineFont, DefineFontInfo, DefineText, ...\r
-// id = FontID, id=0 -> Extract first Font\r
-\r
-int FontIsItalic(LPSWFFONT f);\r
-int FontIsBold(LPSWFFONT f);\r
-\r
-int FontSetID(LPSWFFONT f,U16 id);\r
-int FontReduce(LPSWFFONT f,LPFONTUSAGE use);\r
-\r
-int FontInitUsage(LPFONTUSAGE use);\r
-int FontUse(LPFONTUSAGE use,U8 * s);\r
-\r
-int FontSetDefine(LPTAG t,LPSWFFONT f);\r
-int FontSetInfo(LPTAG t,LPSWFFONT f);\r
-\r
-int FontExport(int handle,LPSWFFONT f);\r
-int FontImport(int handle,LPSWFFONT * f);\r
-\r
-void FontFree(LPSWFFONT f);\r
-\r
-U32 TextGetWidth(LPSWFFONT font,U8 * s,int scale);\r
-int TextCountBits(LPSWFFONT font,U8 * s,int scale,U8 * gbits,U8 * abits);\r
-\r
-int TextSetInfoRecord(LPTAG t,LPSWFFONT font,U16 size,LPRGBA color,S16 dx,S16 dy);\r
-int TextSetCharRecord(LPTAG t,LPSWFFONT font,U8 * s,int scale,U8 gbits,U8 abits);\r
-\r
-int TextPrintDefineText(LPTAG t,LPSWFFONT f);\r
-// Prints text defined in tag t with font f to stdout\r
-\r
-\r
-// swfobject.c\r
-\r
-// Always use ST_PLACEOBJECT2 !!!\r
-\r
-int ObjectPlace(LPTAG t,U16 id,U16 depth,LPMATRIX m,LPCXFORM cx,U8 * name);\r
-int PlaceObject(LPTAG t,U16 id,U16 depth,LPMATRIX m,LPCXFORM cx,U8 * name, U16 clipaction);\r
-int ObjectMove(LPTAG t,U16 depth,LPMATRIX m,LPCXFORM cx);\r
-\r
-// swfbutton.c\r
-\r
-// Button States\r
-\r
-#define BS_HIT 0x08\r
-#define BS_DOWN 0x04\r
-#define BS_OVER 0x02\r
-#define BS_UP 0x01\r
-\r
-// Button Conditions\r
-\r
-#define BC_OVERDOWN_IDLE 0x0100\r
-#define BC_IDLE_OVERDOWN 0x0080\r
-#define BC_OUTDOWN_IDLE 0x0040\r
-#define BC_OUTDOWN_OVERDOWN 0x0020\r
-#define BC_OVERDOWN_OUTDOWN 0x0010\r
-#define BC_OVERDOWN_OVERUP 0x0008\r
-#define BC_OVERUP_OVERDOWN 0x0004\r
-#define BC_OVERUP_IDLE 0x0002\r
-#define BC_IDLE_OVERUP 0x0001\r
-\r
-#define BC_KEY(c) (c<<9)\r
-\r
-#define BC_CURSORLEFT 0x0200\r
-#define BC_CURSORRIGHT 0x0400\r
-#define BC_POS1 0x0600\r
-#define BC_END 0x0800\r
-#define BC_INSERT 0x0a00\r
-#define BC_DELETE 0x0c00\r
-#define BC_BACKSPACE 0x1000\r
-#define BC_ENTER 0x1a00\r
-#define BC_CURSORUP 0x1c00\r
-#define BC_CURSORDOWN 0x1e00\r
-#define BC_PAGEUP 0x2000\r
-#define BC_PAGEDOWN 0x2200\r
-#define BC_TAB 0x2400\r
-#define BC_SPACE 0x4000\r
-\r
-// Button Flag\r
-\r
-#define BF_TRACKMENU 0x01\r
-\r
-int ButtonSetRecord(LPTAG t,U8 state,U16 id,U16 layer,LPMATRIX m,LPCXFORM cx);\r
-int ButtonSetCondition(LPTAG t,U16 condition); // for DefineButton2\r
-int ButtonSetFlags(LPTAG t,U8 flags); // necessary for DefineButton2\r
-int ButtonPostProcess(LPTAG t,int anz_action); // Set all offsets in DefineButton2-Tags (how many conditions to process)\r
-\r
-// swfbits.c\r
-\r
-typedef int * LPJPEGBITS; // cover libjpeg structures\r
-\r
-LPJPEGBITS SetJPEGBitsStart(LPTAG t,int width,int height,int quality);\r
-int SetJPEGBitsLines(LPJPEGBITS jpegbits,U8 ** data,int n);\r
-int SetJPEGBitsLine(LPJPEGBITS jpegbits,U8 * data);\r
-int SetJPEGBitsFinish(LPJPEGBITS jpegbits);\r
-\r
-int SetJPEGBits(LPTAG t,char * fname,int quality); // paste jpg file into swf stream\r
-\r
-// swftools.c\r
-\r
-char isDefiningTag(LPTAG t);\r
-char isAllowedSpriteTag(LPTAG t);\r
-U16 GetDefineID(LPTAG t);\r
-U16 GetPlaceID(LPTAG t); //PLACEOBJECT, PLACEOBJECT2 (sometimes), REMOVEOBJECT\r
-U16 GetDepth(LPTAG t); //PLACEOBJECT,PLACEOBJECT2,REMOVEOBJECT,REMOVEOBJECT2\r
-char* GetName(LPTAG t); //PLACEOBJECT2, FRAMELABEL\r
-LPMATRIX MatrixJoin(LPMATRIX d,LPMATRIX s1,LPMATRIX s2);\r
-LPMATRIX MatrixMapTriangle(LPMATRIX m,int dx,int dy,\r
- int x0,int y0,int x1,int y1,int x2,int y2);\r
-\r
-\r
-// swfcgi.c\r
-\r
-void uncgi(); // same behaviour as Steven Grimm's uncgi-library\r
-\r
-#endif\r
+/* rfxswf.h
+
+ Headers for rfxswf.c and modules
+
+ Part of the swftools package.
+
+ Copyright (c) 2000, 2001 Rainer Böhme <rfxswf@reflex-studio.de>
+
+ This file is distributed under the GPL, see file COPYING for details
+
+*/
+
+#ifndef __RFX_SWF_INCLUDED__
+#define __RFX_SWF_INCLUDED__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "../config.h"
+#include "old_rfxswf.h"
+
+#define DEBUG_RFXSWF
+
+// SWF Types
+
+typedef unsigned long U32;
+typedef signed long S32;
+typedef unsigned short U16;
+typedef signed short S16;
+typedef unsigned char U8;
+typedef signed char S8;
+typedef signed long SFIXED;
+typedef signed long SCOORD;
+
+// Basic Structures
+
+typedef struct _SPOINT
+{ SCOORD x;
+ SCOORD y;
+} SPOINT, * LPSPOINT;
+
+typedef struct _RGBA
+{ U8 r;
+ U8 g;
+ U8 b;
+ U8 a;
+} RGBA, * LPRGBA;
+
+typedef struct _SRECT
+{ SCOORD xmin;
+ SCOORD ymin;
+ SCOORD xmax;
+ SCOORD ymax;
+} SRECT, * LPSRECT;
+
+typedef struct _MATRIX
+{ SFIXED sx; // factor x
+ SFIXED sy;
+ SFIXED r0; // rotation
+ SFIXED r1;
+ SCOORD tx; // delta x
+ SCOORD ty;
+} MATRIX, * LPMATRIX;
+
+typedef struct _CXFORM
+{ S16 a0, a1;
+ S16 r0, r1;
+ S16 g0, g1;
+ S16 b0, b1;
+} CXFORM, * LPCXFORM;
+
+typedef struct _TAG // NEVER access a Tag-Struct directly !
+{ U16 id;
+ U32 len;
+ U8 * data;
+
+ int frame;
+
+ struct _TAG * next;
+ struct _TAG * prev;
+
+ U32 memsize; // to minimize realloc() calls
+ U32 pos; // for Get/Set-Access
+ U8 bitmask; // for Bit-Manipulating Functions [read]
+ U8 bitcount; // [write]
+} TAG, * LPTAG;
+
+typedef struct _SWF
+{ U8 FileVersion;
+ U32 FileSize; // valid after load and save
+ SRECT MovieSize;
+ U16 FrameRate;
+ U16 FrameCount; // valid after load and save
+ TAG * FirstTag;
+} SWF, * LPSWF;
+
+// Basic Functions
+
+int ReadSWF(int handle,SWF * swf); // Reads SWF to memory (malloc'ed), returns length or <0 if fails
+int WriteSWF(int handle,SWF * swf); // Writes SWF to file, returns length or <0 if fails
+int WriteCGI(SWF * swf); // Outputs SWF with valid CGI header to stdout
+void FreeTags(SWF * swf); // Frees all malloc'ed memory for swf
+
+TAG * InsertTag(TAG * after,U16 id); // updates frames, if necessary
+int DeleteTag(TAG * t);
+
+void SetTagPos(TAG * t,U32 pos); // resets Bitcount
+U32 GetTagPos(TAG * t);
+
+TAG * NextTag(TAG * t);
+TAG * PrevTag(TAG * t);
+
+int GetFrameNo(TAG * t); // should be renamed to TagGetFrame
+U16 GetTagID(TAG * t); // ... TagGetID
+U32 GetDataSize(TAG * t); // ... TagGetDataSize
+U8* GetDataSizePtr(TAG * t);
+
+U32 GetBits(TAG * t,int nbits);
+S32 GetSBits(TAG * t,int nbits);
+int SetBits(TAG * t,U32 v,int nbits);
+
+int GetBlock(TAG * t,U8 * b,int l); // resets Bitcount
+int SetBlock(TAG * t,U8 * b,int l);
+
+U8 GetU8(TAG * t); // resets Bitcount
+U16 GetU16(TAG * t);
+U32 GetU32(TAG * t);
+
+int SetU8(TAG * t,U8 v); // resets Bitcount
+int SetU16(TAG * t,U16 v);
+int SetU32(TAG * t,U32 v);
+
+int GetPoint(TAG * t,SPOINT * p); // resets Bitcount
+int GetRect(TAG * t,SRECT * r);
+int GetMatrix(TAG * t,MATRIX * m);
+int GetCXForm(TAG * t,CXFORM * cx,U8 alpha);
+
+int SetPoint(TAG * t,SPOINT * p); // resets Bitcount
+int SetRect(TAG * t,SRECT * r);
+int SetMatrix(TAG * t,MATRIX * m);
+int SetCXForm(TAG * t,CXFORM * cx,U8 alpha);
+int SetRGB(TAG * t,RGBA * col);
+int SetRGBA(TAG * t,RGBA * col);
+
+// Function Macros
+
+#define GetS8(tag) ((S8)GetU8(tag))
+#define GetS16(tag) ((S16)GetU16(tag))
+#define GetS32(tag) ((S32)GetU32(tag))
+#define GetCoord(tag) ((SCOORD)GetU32(tag))
+#define GetFixed(tag) ((SFIXED)GetU32(tag))
+
+#define SetS8(tag,v) SetU8(tag,(U8)v)
+#define SetS16(tag,v) SetU16(tag,(U16)v)
+#define SetS32(tag,v) SetU32(tag,(U32)v)
+#define SetCoord(tag,v) SetU32(tag,(U32)v)
+#define SetFixed(tag,v) SetU32(tag,(U32)v)
+#define SetString(t,s) SetBlock(t,s,strlen(s)+1)
+
+#define FAILED(b) ((b)<0)
+#define SUCCEDED(b) ((b)>=0)
+
+// Tag IDs (adopted from J. C. Kessels' Form2Flash)
+
+#define ST_END 0
+#define ST_SHOWFRAME 1
+#define ST_DEFINESHAPE 2
+#define ST_FREECHARACTER 3
+#define ST_PLACEOBJECT 4
+#define ST_REMOVEOBJECT 5
+#define ST_DEFINEBITS 6
+#define ST_DEFINEBUTTON 7
+#define ST_JPEGTABLES 8
+#define ST_SETBACKGROUNDCOLOR 9
+#define ST_DEFINEFONT 10
+#define ST_DEFINETEXT 11
+#define ST_DOACTION 12
+#define ST_DEFINEFONTINFO 13
+#define ST_DEFINESOUND 14 /* Event sound tags. */
+#define ST_STARTSOUND 15
+#define ST_DEFINEBUTTONSOUND 17
+#define ST_SOUNDSTREAMHEAD 18
+#define ST_SOUNDSTREAMBLOCK 19
+#define ST_DEFINEBITSLOSSLESS 20 /* A bitmap using lossless zlib compression. */
+#define ST_DEFINEBITSJPEG2 21 /* A bitmap using an internal JPEG compression table. */
+#define ST_DEFINESHAPE2 22
+#define ST_DEFINEBUTTONCXFORM 23
+#define ST_PROTECT 24 /* This file should not be importable for editing. */
+#define ST_PLACEOBJECT2 26 /* The new style place w/ alpha color transform and name. */
+#define ST_REMOVEOBJECT2 28 /* A more compact remove object that omits the character tag (just depth). */
+#define ST_DEFINESHAPE3 32 /* A shape V3 includes alpha values. */
+#define ST_DEFINETEXT2 33 /* A text V2 includes alpha values. */
+#define ST_DEFINEBUTTON2 34 /* A button V2 includes color transform, alpha and multiple actions */
+#define ST_DEFINEBITSJPEG3 35 /* A JPEG bitmap with alpha info. */
+#define ST_DEFINEBITSLOSSLESS2 36 /* A lossless bitmap with alpha info. */
+#define ST_DEFINEEDITTEXT 37
+#define ST_DEFINEMOVIE 38
+#define ST_DEFINESPRITE 39 /* Define a sequence of tags that describe the behavior of a sprite. */
+#define ST_NAMECHARACTER 40 /* Name a character definition, character id and a string, (used for buttons, bitmaps, sprites and sounds). */
+#define ST_SERIALNUMBER 41
+#define ST_GENERATORTEXT 42 /* contains an id */
+#define ST_FRAMELABEL 43 /* A string label for the current frame. */
+#define ST_SOUNDSTREAMHEAD2 45 /* For lossless streaming sound, should not have needed this... */
+#define ST_DEFINEMORPHSHAPE 46 /* A morph shape definition */
+#define ST_DEFINEFONT2 48
+#define ST_TEMPLATECOMMAND 49
+#define ST_GENERATOR3 51
+#define ST_EXTERNALFONT 52
+
+#define ST_REFLEX 777 /* to identify generator software */
+
+// Advanced Funtions
+
+// swfdump.c
+
+void DumpHeader(FILE * f,SWF * swf);
+void DumpMatrix(FILE * f,MATRIX * m);
+void DumpTag(FILE * f,TAG * t);
+char* getTagName(TAG*tag);
+
+// swfshape.c
+
+typedef struct _LINESTYLE
+{ U16 width;
+ RGBA color;
+} LINESTYLE, * LPLINESTYLE;
+
+typedef struct _FILLSTYLE
+{ U8 type;
+ RGBA color;
+ MATRIX m;
+ U16 id_bitmap;
+} FILLSTYLE, * LPFILLSTYLE;
+
+typedef struct _SHAPE // NEVER access a Shape-Struct directly !
+{
+ struct
+ { LINESTYLE * data;
+ U16 n;
+ } linestyle;
+ // note: changes of shape structure
+ struct // lead to incompatible .efont formats
+ { FILLSTYLE * data;
+ U16 n;
+ } fillstyle;
+
+ S32 px;
+ S32 py;
+
+ struct
+ { U16 fill;
+ U16 line;
+ } bits;
+
+ U8 * data;
+ U32 bitlen; // length of data in bits
+} SHAPE, * LPSHAPE;
+
+// Shapes
+
+int NewShape(SHAPE ** s);
+void ShapeFree(SHAPE * s);
+
+int GetSimpleShape(TAG * t,SHAPE ** s); // without Linestyle/Fillstyle Record
+int SetSimpleShape(TAG * t,SHAPE * s); // without Linestyle/Fillstyle Record
+
+int ShapeAddLineStyle(SHAPE * s,U16 width,RGBA * color);
+int ShapeAddSolidFillStyle(SHAPE * s,RGBA * color);
+int ShapeAddBitmapFillStyle(SHAPE * s,MATRIX * m,U16 id_bitmap,int clip);
+
+int SetShapeStyles(TAG * t,SHAPE * s);
+int ShapeCountBits(SHAPE * s,U8 * fbits,U8 * lbits);
+int SetShapeBits(TAG * t,SHAPE * s);
+int SetShapeHeader(TAG * t,SHAPE * s); // one call for upper three functions
+
+int ShapeSetMove(TAG * t,SHAPE * s,S32 x,S32 y);
+int ShapeSetStyle(TAG * t,SHAPE * s,U16 line,U16 fill0,U16 fill1);
+int ShapeSetAll(TAG * t,SHAPE * s,S32 x,S32 y,U16 line,U16 fill0,U16 fill1);
+
+int ShapeSetLine(TAG * t,SHAPE * s,S32 x,S32 y);
+int ShapeSetCurve(TAG * t,SHAPE * s,S32 x,S32 y,S32 ax,S32 ay);
+int ShapeSetCircle(TAG * t,SHAPE * s,S32 x,S32 y,S32 rx,S32 ry);
+int ShapeSetEnd(TAG * t);
+
+
+// swffont.c
+
+// does not support wide characters !
+
+#define MAX_CHAR_PER_FONT 256
+
+typedef struct _SWFLAYOUT
+{ S16 ascent;
+ S16 descent;
+ S16 leading;
+ SRECT bounds[MAX_CHAR_PER_FONT];
+ struct
+ { U16 count;
+ U8 * data; // size = count*4 bytes
+ } kerning;
+} SWFLAYOUT, * LPSWFLAYOUT;
+
+typedef struct _SWFFONT
+{ U16 id;
+ U8 * name;
+ SWFLAYOUT * layout;
+
+ U8 flags; // bold/italic/unicode/ansi ...
+
+ U16 codes[MAX_CHAR_PER_FONT];
+
+ struct
+ { U16 advance;
+ U16 gid; // Glyph-ID after DefineFont
+ SHAPE * shape;
+ } glyph[MAX_CHAR_PER_FONT];
+} SWFFONT, * LPSWFFONT;
+
+typedef struct _FONTUSAGE
+{ U8 code[MAX_CHAR_PER_FONT];
+} FONTUSAGE, * LPFONTUSAGE;
+
+int FontEnumerate(SWF * swf,void (*FontCallback) (U16,U8*));
+// -> void fontcallback(U16 id,U8 * name); returns number of defined fonts
+
+int FontExtract(SWF * swf,int id,SWFFONT ** f);
+// Fetches all available information from DefineFont, DefineFontInfo, DefineText, ...
+// id = FontID, id=0 -> Extract first Font
+
+int FontIsItalic(SWFFONT * f);
+int FontIsBold(SWFFONT * f);
+
+int FontSetID(SWFFONT * f,U16 id);
+int FontReduce(SWFFONT * f,FONTUSAGE * use);
+
+int FontInitUsage(FONTUSAGE * use);
+int FontUse(FONTUSAGE * use,U8 * s);
+
+int FontSetDefine(TAG * t,SWFFONT * f);
+int FontSetInfo(TAG * t,SWFFONT * f);
+
+int FontExport(int handle,SWFFONT * f);
+int FontImport(int handle,SWFFONT * * f);
+
+void FontFree(SWFFONT * f);
+
+U32 TextGetWidth(SWFFONT * font,U8 * s,int scale);
+int TextCountBits(SWFFONT * font,U8 * s,int scale,U8 * gbits,U8 * abits);
+
+int TextSetInfoRecord(TAG * t,SWFFONT * font,U16 size,RGBA * color,S16 dx,S16 dy);
+int TextSetCharRecord(TAG * t,SWFFONT * font,U8 * s,int scale,U8 gbits,U8 abits);
+
+int TextPrintDefineText(TAG * t,SWFFONT * f);
+// Prints text defined in tag t with font f to stdout
+
+
+// swfobject.c
+
+// Always use ST_PLACEOBJECT2 !!!
+
+int ObjectPlace(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,U8 * name);
+int PlaceObject(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,U8 * name, U16 clipaction);
+int ObjectMove(TAG * t,U16 depth,MATRIX * m,CXFORM * cx);
+
+// swfbutton.c
+
+// Button States
+
+#define BS_HIT 0x08
+#define BS_DOWN 0x04
+#define BS_OVER 0x02
+#define BS_UP 0x01
+
+// Button Conditions
+
+#define BC_OVERDOWN_IDLE 0x0100
+#define BC_IDLE_OVERDOWN 0x0080
+#define BC_OUTDOWN_IDLE 0x0040
+#define BC_OUTDOWN_OVERDOWN 0x0020
+#define BC_OVERDOWN_OUTDOWN 0x0010
+#define BC_OVERDOWN_OVERUP 0x0008
+#define BC_OVERUP_OVERDOWN 0x0004
+#define BC_OVERUP_IDLE 0x0002
+#define BC_IDLE_OVERUP 0x0001
+
+#define BC_KEY(c) (c<<9)
+
+#define BC_CURSORLEFT 0x0200
+#define BC_CURSORRIGHT 0x0400
+#define BC_POS1 0x0600
+#define BC_END 0x0800
+#define BC_INSERT 0x0a00
+#define BC_DELETE 0x0c00
+#define BC_BACKSPACE 0x1000
+#define BC_ENTER 0x1a00
+#define BC_CURSORUP 0x1c00
+#define BC_CURSORDOWN 0x1e00
+#define BC_PAGEUP 0x2000
+#define BC_PAGEDOWN 0x2200
+#define BC_TAB 0x2400
+#define BC_SPACE 0x4000
+
+// Button Flag
+
+#define BF_TRACKMENU 0x01
+
+int ButtonSetRecord(TAG * t,U8 state,U16 id,U16 layer,MATRIX * m,CXFORM * cx);
+int ButtonSetCondition(TAG * t,U16 condition); // for DefineButton2
+int ButtonSetFlags(TAG * t,U8 flags); // necessary for DefineButton2
+int ButtonPostProcess(TAG * t,int anz_action); // Set all offsets in DefineButton2-Tags (how many conditions to process)
+
+// swfbits.c
+
+typedef int JPEGBITS,* LPJPEGBITS; // cover libjpeg structures
+
+JPEGBITS * SetJPEGBitsStart(TAG * t,int width,int height,int quality);
+int SetJPEGBitsLines(JPEGBITS * jpegbits,U8 ** data,int n);
+int SetJPEGBitsLine(JPEGBITS * jpegbits,U8 * data);
+int SetJPEGBitsFinish(JPEGBITS * jpegbits);
+
+int SetJPEGBits(TAG * t,char * fname,int quality); // paste jpg file into swf stream
+
+// swftools.c
+
+char isDefiningTag(TAG * t);
+char isAllowedSpriteTag(TAG * t);
+U16 GetDefineID(TAG * t);
+U16 GetPlaceID(TAG * t); //PLACEOBJECT, PLACEOBJECT2 (sometimes), REMOVEOBJECT
+U16 GetDepth(TAG * t); //PLACEOBJECT,PLACEOBJECT2,REMOVEOBJECT,REMOVEOBJECT2
+char* GetName(TAG * t); //PLACEOBJECT2, FRAMELABEL
+MATRIX * MatrixJoin(MATRIX * d,MATRIX * s1,MATRIX * s2);
+MATRIX * MatrixMapTriangle(MATRIX * m,int dx,int dy,
+ int x0,int y0,int x1,int y1,int x2,int y2);
+
+
+// swfcgi.c
+
+void uncgi(); // same behaviour as Steven Grimm's uncgi-library
+
+#endif