Initial revision
[swftools.git] / lib / rfxswf.c
1 /* rfxswf.c\r
2 \r
3    Library for creating and reading SWF files or parts of it.\r
4    There's a module directory which provides some extended functionality.\r
5    Most modules are included at the bottom of this file.\r
6 \r
7    Part of the swftools package.\r
8 \r
9    Copyright (c) 2000, 2001 Rainer Böhme <rfxswf@reflex-studio.de>\r
10  \r
11    This file is distributed under the GPL, see file COPYING for details \r
12 \r
13 */\r
14 \r
15 #include "rfxswf.h"\r
16 \r
17 #include <jpeglib.h>\r
18 #define _JPEGLIB_INCLUDED_\r
19 \r
20 // Win32 support may be broken since it was only tested in an older version for Watcom C\r
21 #ifdef __NT__\r
22 #  include <io.h>\r
23 #  include <malloc.h>\r
24 #  include <string.h>\r
25 #  ifdef DEBUG_RFXSWF\r
26 #    include <stdio.h>\r
27 #  endif\r
28 #else\r
29 #endif\r
30 \r
31 // internal constants\r
32 \r
33 #define MALLOC_SIZE     128\r
34 #define INSERT_RFX_TAG\r
35 \r
36 #define MEMSIZE(l) (((l/MALLOC_SIZE)+1)*MALLOC_SIZE)\r
37 \r
38 // inline wrapper functions\r
39 \r
40 LPTAG NextTag(LPTAG t) { return t->next; }\r
41 LPTAG PrevTag(LPTAG t) { return t->prev; }\r
42 int   GetFrameNo(LPTAG t)  { return t->frame; }\r
43 U16   GetTagID(LPTAG t)    { return t->id; }\r
44 U32   GetDataSize(LPTAG t) { return t->len; }\r
45 U32   GetTagPos(LPTAG t)   { return t->pos; }\r
46 U8*   GetTagPosPtr(LPTAG t)   { return &t->data[t->pos]; }\r
47 \r
48 // Basic Data Access Functions\r
49 \r
50 #define ResetBitmask(tag)   if (tag->bitmask)  { tag->pos++; tag->bitmask = 0; }\r
51 #define ResetBitcount(tag)  if (tag->bitcount) { tag->bitcount = 0; }\r
52 \r
53 // for future purpose: avoid high level lib functions to change tagpos/bitcount\r
54 \r
55 #define SaveTagPos(tag)\r
56 #define RestoreTagPos(tag)\r
57 \r
58 void SetTagPos(LPTAG t,U32 pos)\r
59 { ResetBitmask(t);\r
60   if (pos<=t->len) t->pos = pos;\r
61   #ifdef DEBUG_RFXSWF\r
62   else fprintf(stderr,"SetTagPos() out of bounds: TagID = %i\n",t->id);\r
63   #endif\r
64 }\r
65 \r
66 U8 GetU8(LPTAG t)\r
67 { ResetBitmask(t);\r
68   #ifdef DEBUG_RFXSWF\r
69     if (t->pos>=t->len) \r
70     { fprintf(stderr,"GetU8() out of bounds: TagID = %i\n",t->id);\r
71       return 0;\r
72     }\r
73   #endif\r
74   return t->data[t->pos++];\r
75 }\r
76 \r
77 U16 GetU16(LPTAG t)\r
78 { U16 res;\r
79   ResetBitmask(t);\r
80   #ifdef DEBUG_RFXSWF\r
81     if (t->pos>(t->len-2)) \r
82     { fprintf(stderr,"GetU16() out of bounds: TagID = %i\n",t->id);\r
83       return 0;\r
84     }\r
85   #endif\r
86   res = t->data[t->pos] | (t->data[t->pos+1]<<8);\r
87   t->pos+=2;\r
88   return res;\r
89 }\r
90 \r
91 U32 GetU32(LPTAG t)\r
92 { U32 res;\r
93   ResetBitmask(t);\r
94   #ifdef DEBUG_RFXSWF\r
95     if (t->pos>(t->len-4)) \r
96     { fprintf(stderr,"GetU32() out of bounds: TagID = %i\n",t->id);\r
97       return 0;\r
98     }\r
99   #endif\r
100   res = t->data[t->pos]        | (t->data[t->pos+1]<<8) | \r
101        (t->data[t->pos+2]<<16) | (t->data[t->pos+3]<<24);\r
102   t->pos+=4;\r
103   return res;\r
104 }\r
105 \r
106 int GetBlock(LPTAG t,U8 * b,int l)\r
107 // returns number of bytes written (<=l)\r
108 // b = NULL -> skip data\r
109 { ResetBitmask(t);\r
110   if ((t->len-t->pos)<l) l=t->len-t->pos;\r
111   if (b && l) memcpy(b,&t->data[t->pos],l);\r
112   t->pos+=l;\r
113   return l;\r
114 }\r
115 \r
116 int SetBlock(LPTAG t,U8 * b,int l)\r
117 // Appends Block to the end of Tagdata, returns size\r
118 { U32 newlen = t->len + l;\r
119   ResetBitcount(t);\r
120   if (newlen>t->memsize)\r
121   { U32  newmem  = MEMSIZE(newlen);  \r
122     U8 * newdata = (U8*)((t->data)?realloc(t->data,newmem):malloc(newmem));\r
123     if (!newdata)\r
124     {\r
125       #ifdef DEBUG_RFXSWF\r
126         fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n");\r
127       #endif\r
128       return 0;\r
129     }\r
130     t->memsize = newmem;\r
131     t->data    = newdata;\r
132   }\r
133   if (b) memcpy(&t->data[t->len],b,l);\r
134   else memset(&t->data[t->len],0x00,l);\r
135   t->len+=l;\r
136   return l;\r
137 }\r
138 \r
139 int SetU8(LPTAG t,U8 v)\r
140 { ResetBitcount(t);\r
141   if ((t->len+1)>t->memsize) return (SetBlock(t,&v,1)==1)?0:-1;\r
142   t->data[t->len++] = v;\r
143   return 0;\r
144 }\r
145 \r
146 int SetU16(LPTAG t,U16 v)\r
147 { U8 a[2];\r
148   a[0] = v&0xff;\r
149   a[1] = v>>8;\r
150   \r
151   ResetBitcount(t);\r
152   if ((t->len+2)>t->memsize) return (SetBlock(t,a,2)==2)?0:-1;\r
153   t->data[t->len++] = a[0];\r
154   t->data[t->len++] = a[1];\r
155   return 0;\r
156 }\r
157 \r
158 int SetU32(LPTAG t,U32 v)\r
159 { U8 a[4];\r
160   a[0] = v&0xff;        // to ensure correct handling of non-intel byteorder\r
161   a[1] = (v>>8)&0xff;\r
162   a[2] = (v>>16)&0xff;\r
163   a[3] = (v>>24)&0xff;\r
164   \r
165   ResetBitcount(t);\r
166   if ((t->len+4)>t->memsize) return (SetBlock(t,a,4)==4)?0:-1;\r
167   t->data[t->len++] = a[0];\r
168   t->data[t->len++] = a[1];\r
169   t->data[t->len++] = a[2];\r
170   t->data[t->len++] = a[3];\r
171   return 0;\r
172 }\r
173 \r
174 U32 GetBits(LPTAG t,int nbits)\r
175 { U32 res = 0;\r
176   if (!nbits) return 0;\r
177   if (!t->bitmask) t->bitmask = 0x80;\r
178   while (nbits)\r
179   { res<<=1;\r
180     if (t->data[t->pos]&t->bitmask) res|=1;\r
181     t->bitmask>>=1;\r
182     nbits--;\r
183     if (!t->bitmask)\r
184     { if (nbits) t->bitmask = 0x80;\r
185       #ifdef DEBUG_RFXSWF\r
186       if (t->pos>=t->len) \r
187       { fprintf(stderr,"GetBits() out of bounds: TagID = %i\n",t->id);\r
188         return res;\r
189       }\r
190       #endif\r
191       t->pos++;\r
192     }\r
193   }\r
194   return res;\r
195 }\r
196 \r
197 S32 GetSBits(LPTAG t,int nbits)\r
198 { U32 res = GetBits(t,nbits);\r
199   if (res&(1<<(nbits-1))) res|=(0xffffffff<<nbits);  \r
200   return (S32)res;\r
201 }\r
202 \r
203 int SetBits(LPTAG t,U32 v,int nbits)\r
204 { U32 bm = 1<<(nbits-1);\r
205 \r
206   while (nbits)\r
207   { if (!t->bitcount)\r
208     { if (FAILED(SetU8(t,0))) return -1;\r
209       t->bitcount = 0x80;\r
210     }\r
211     if (v&bm) t->data[t->len-1] |= t->bitcount;\r
212     bm>>=1;\r
213     t->bitcount>>=1;\r
214     nbits--;\r
215   }\r
216   return 0;\r
217 }\r
218 \r
219 // Advanced Data Access Functions\r
220 \r
221 int SetRGB(LPTAG t,LPRGBA col)\r
222 { if (!t) return -1;\r
223   if (col)\r
224   { SetU8(t,col->r);\r
225     SetU8(t,col->g);\r
226     SetU8(t,col->b);\r
227   } else SetBlock(t,NULL,3);\r
228   return 0;\r
229 }\r
230 \r
231 int SetRGBA(LPTAG t,LPRGBA col)\r
232 { if (!t) return -1;\r
233   if (col)\r
234   { SetU8(t,col->r);\r
235     SetU8(t,col->g);\r
236     SetU8(t,col->b);\r
237     SetU8(t,col->a);\r
238   } else SetBlock(t,NULL,4);\r
239   return 0;\r
240 }\r
241 \r
242 int CountBits(U32 v,int nbits)\r
243 { int n = 33;\r
244   U32 m = 0x80000000;\r
245   if (!v) n = 0; else\r
246   if (v&m)\r
247   { while (v&m)\r
248     { n--;\r
249       m>>=1;\r
250       if (!m) break;\r
251     } \r
252   }\r
253   else\r
254   { while (!(v&m))\r
255     { n--;\r
256       m>>=1;\r
257       if (!m) break;\r
258     } \r
259   }\r
260   return (n>nbits)?n:nbits;\r
261 }\r
262 \r
263 int GetRect(LPTAG t,LPSRECT r)\r
264 { int nbits;\r
265   SRECT dummy;\r
266   if (!r) r = &dummy;\r
267   nbits = (int) GetBits(t,5);\r
268   r->xmin = GetSBits(t,nbits);\r
269   r->xmax = GetSBits(t,nbits);\r
270   r->ymin = GetSBits(t,nbits);\r
271   r->ymax = GetSBits(t,nbits);\r
272   return 0;\r
273 }\r
274 \r
275 int SetRect(LPTAG t,LPSRECT r)\r
276 { int nbits;\r
277     \r
278   nbits = CountBits(r->xmin,0);\r
279   nbits = CountBits(r->xmax,nbits);\r
280   nbits = CountBits(r->ymin,nbits);\r
281   nbits = CountBits(r->ymax,nbits);\r
282 \r
283   SetBits(t,nbits,5);\r
284   SetBits(t,r->xmin,nbits);\r
285   SetBits(t,r->xmax,nbits);\r
286   SetBits(t,r->ymin,nbits);\r
287   SetBits(t,r->ymax,nbits);\r
288 \r
289   return 0;\r
290 }\r
291 \r
292 int GetMatrix(LPTAG t,LPMATRIX m)\r
293 { MATRIX dummy;\r
294   int nbits;\r
295     \r
296   if (!m) m = &dummy;\r
297   \r
298   if (!t)\r
299   { m->sx = m->sy = 0x10000;\r
300     m->r0 = m->r1 = 0;\r
301     m->tx = m->ty = 0;\r
302     return -1;\r
303   }\r
304 \r
305   ResetBitmask(t);\r
306   \r
307   if (GetBits(t,1))\r
308   { nbits = GetBits(t,5);\r
309     m->sx = GetSBits(t,nbits);\r
310     m->sy = GetSBits(t,nbits);\r
311   }\r
312   else m->sx = m->sy = 0x10000;\r
313   \r
314   if (GetBits(t,1))\r
315   { nbits = GetBits(t,5);\r
316     m->r0 = GetSBits(t,nbits);\r
317     m->r1 = GetSBits(t,nbits);\r
318   }\r
319   else m->r0 = m->r1 = 0x0;\r
320 \r
321   nbits = GetBits(t,5);\r
322   m->tx = GetSBits(t,nbits);\r
323   m->ty = GetSBits(t,nbits);\r
324   \r
325   return 0;\r
326 }\r
327 \r
328 int SetMatrix(LPTAG t,LPMATRIX m)\r
329 { int nbits;\r
330   MATRIX ma;\r
331 \r
332   if (!m)\r
333   { m = &ma;\r
334     ma.sx = ma.sy = 0x10000;\r
335     ma.r0 = ma.r1 = 0;\r
336     ma.tx = ma.ty = 0;\r
337   }\r
338 \r
339   ResetBitcount(t);\r
340 \r
341   if ((m->sx==0x10000)&&(m->sy==0x10000)) SetBits(t,0,1);\r
342   else\r
343   { SetBits(t,1,1);\r
344     nbits = CountBits(m->sx,0);\r
345     nbits = CountBits(m->sy,nbits);\r
346     SetBits(t,nbits,5);\r
347     SetBits(t,m->sx,nbits);\r
348     SetBits(t,m->sy,nbits);\r
349   }\r
350 \r
351   if ((!m->r0)&&(!m->r1)) SetBits(t,0,1);\r
352   else\r
353   { SetBits(t,1,1);\r
354     nbits = CountBits(m->r0,0);\r
355     nbits = CountBits(m->r1,nbits);\r
356     SetBits(t,nbits,5);\r
357     SetBits(t,m->r0,nbits);\r
358     SetBits(t,m->r1,nbits);\r
359   }\r
360 \r
361   nbits = CountBits(m->tx,0);\r
362   nbits = CountBits(m->ty,nbits);\r
363   SetBits(t,nbits,5);\r
364   SetBits(t,m->tx,nbits);\r
365   SetBits(t,m->ty,nbits);\r
366 \r
367   return 0;\r
368 }\r
369 \r
370 int GetCXForm(LPTAG t,LPCXFORM cx,U8 alpha) //FIXME: alpha should be type bool\r
371 { CXFORM cxf;\r
372   int hasadd;\r
373   int hasmul;\r
374   int nbits;\r
375     \r
376   if (!cx) cx = &cxf;\r
377   \r
378   cx->a0 = cx->r0 = cx->g0 = cx->b0 = 256;\r
379   cx->a1 = cx->r1 = cx->g1 = cx->b1 = 0;\r
380 \r
381   if (!t) return 0;\r
382   \r
383   ResetBitmask(t);\r
384   hasadd = GetBits(t,1);\r
385   hasmul = GetBits(t,1);\r
386   nbits  = GetBits(t,4);\r
387 \r
388   if (hasmul)\r
389   { cx->r0 = (S16)GetSBits(t,nbits);\r
390     cx->g0 = (S16)GetSBits(t,nbits);\r
391     cx->b0 = (S16)GetSBits(t,nbits);\r
392     if (alpha)\r
393       cx->a0 = (S16)GetSBits(t,nbits);\r
394   }\r
395 \r
396   if (hasadd)\r
397   { cx->r1 = (S16)GetSBits(t,nbits);\r
398     cx->g1 = (S16)GetSBits(t,nbits);\r
399     cx->b1 = (S16)GetSBits(t,nbits);\r
400     if (alpha)\r
401       cx->a1 = (S16)GetSBits(t,nbits);\r
402   }\r
403   \r
404   return 0;\r
405 }\r
406 \r
407 int SetCXForm(LPTAG t,LPCXFORM cx,U8 alpha)\r
408 { CXFORM cxf;\r
409   int hasadd;\r
410   int hasmul;\r
411   int nbits;\r
412     \r
413   if (!cx)\r
414   { cx = &cxf;\r
415     cx->a0 = cx->r0 = cx->g0 = cx->b0 = 256;\r
416     cx->a1 = cx->r1 = cx->g1 = cx->b1 = 0;\r
417   }\r
418 \r
419   if (!alpha)\r
420   { cx->a0 = 256;\r
421     cx->a1 = 0;\r
422   }\r
423 \r
424   nbits = 0;\r
425 \r
426   hasmul = (cx->a0!=256)||(cx->r0!=256)||(cx->g0!=256)||(cx->b0!=256);\r
427   hasadd = cx->a1|cx->r1|cx->g1|cx->b1;\r
428 \r
429   if (hasmul)\r
430   { if (alpha) nbits = CountBits((S32)cx->a0,nbits);\r
431     nbits = CountBits((S32)cx->r0,nbits);\r
432     nbits = CountBits((S32)cx->g0,nbits);\r
433     nbits = CountBits((S32)cx->b0,nbits);\r
434   }\r
435 \r
436   if (hasadd)\r
437   { if (alpha) nbits = CountBits((S32)cx->a1,nbits);\r
438     nbits = CountBits((S32)cx->r1,nbits);\r
439     nbits = CountBits((S32)cx->g1,nbits);\r
440     nbits = CountBits((S32)cx->b1,nbits);\r
441   }\r
442   \r
443   ResetBitcount(t);\r
444   SetBits(t,hasadd?1:0,1);\r
445   SetBits(t,hasmul?1:0,1);\r
446   SetBits(t,nbits,4);\r
447 \r
448   if (hasmul)\r
449   { SetBits(t,cx->r0,nbits);\r
450     SetBits(t,cx->g0,nbits);\r
451     SetBits(t,cx->b0,nbits);\r
452     if (alpha) SetBits(t,cx->a0,nbits);\r
453   }\r
454 \r
455   if (hasadd)\r
456   { SetBits(t,cx->r1,nbits);\r
457     SetBits(t,cx->g1,nbits);\r
458     SetBits(t,cx->b1,nbits);\r
459     if (alpha) SetBits(t,cx->a1,nbits);\r
460   }\r
461   \r
462   return 0;\r
463 }\r
464 \r
465 int GetPoint(LPTAG t,LPSPOINT p) { return 0; }\r
466 int SetPoint(LPTAG t,LPSPOINT p) { return 0; }\r
467 \r
468 // Tag List Manipulating Functions\r
469 \r
470 int RFXSWF_UpdateFrame(LPTAG t,S8 delta)\r
471 // returns number of frames\r
472 { int res = -1;\r
473   while (t)\r
474   { t->frame+=delta;\r
475     res = t->frame;\r
476     t = t->next;\r
477   }\r
478   return res;\r
479 }\r
480 \r
481 #define UpdateFrame(a,b) RFXSWF_UpdateFrame(a,b)\r
482 \r
483 LPTAG InsertTag(LPTAG after,U16 id)     // updates frames, if nescessary\r
484 { LPTAG t;\r
485 \r
486   t = (LPTAG)malloc(sizeof(TAG));\r
487   if (t)\r
488   { memset(t,0x00,sizeof(TAG));\r
489     t->id = id;\r
490     \r
491     if (after)\r
492     { t->frame = after->frame;\r
493       t->prev  = after;\r
494       t->next  = after->next;\r
495       after->next = t;\r
496       if (t->next) t->next->prev = t;\r
497       \r
498       if (id==ST_SHOWFRAME) UpdateFrame(t->next,+1);\r
499     }\r
500   }\r
501   return t;\r
502 }\r
503 \r
504 int DeleteTag(LPTAG t)\r
505 { if (!t) return -1;\r
506 \r
507   if (t->id==ST_SHOWFRAME) UpdateFrame(t->next,-1);\r
508     \r
509   if (t->prev) t->prev->next = t->next;\r
510   if (t->next) t->next->prev = t->prev;\r
511 \r
512   if (t->data) free(t->data);\r
513   free(t);\r
514   return 0;\r
515 }\r
516 \r
517 LPTAG RFXSWF_ReadTag(int handle,LPTAG prev)\r
518 { LPTAG t;\r
519   U16 raw;\r
520   U32 len;\r
521   int id;\r
522 \r
523   if (read(handle,&raw,2)!=2) return NULL;\r
524 \r
525   len = raw&0x3f;\r
526   id  = raw>>6;\r
527 \r
528   if (len==0x3f)\r
529   { if (read(handle,&len,4)!=4) return NULL;\r
530   }\r
531 \r
532   if (id==ST_DEFINESPRITE) len = 2*sizeof(U16);\r
533   // Sprite handling fix: Flaten sprite tree\r
534 \r
535   t = (LPTAG)malloc(sizeof(TAG));\r
536   \r
537   if (!t)\r
538   {\r
539     #ifdef DEBUG_RFXSWF\r
540       fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n");\r
541     #endif\r
542     return NULL;\r
543   }\r
544 \r
545   memset(t,0x00,sizeof(TAG));\r
546   \r
547   t->len = len;\r
548   t->id  = id;\r
549 \r
550   if (t->len)\r
551   { t->data = (U8*)malloc(t->len);\r
552     if (!t->data)\r
553     {\r
554       #ifdef DEBUG_RFXSWF\r
555         fprintf(stderr,"Fatal Error: malloc()/realloc() failed.\n");\r
556       #endif\r
557       return NULL;\r
558     }\r
559     t->memsize = t->len;\r
560     if (read(handle,t->data,t->len)!=t->len) return NULL;\r
561   }\r
562 \r
563   if (prev)\r
564   { t->frame = prev->frame+((prev->id==ST_SHOWFRAME)?1:0);\r
565     t->prev  = prev;\r
566     prev->next = t;\r
567   }\r
568 \r
569   return t;\r
570 }\r
571 \r
572 int DefineSprite_GetRealSize(LPTAG t);\r
573 \r
574 int RFXSWF_WriteTag(int handle,LPTAG t)\r
575 // returns tag length in bytes (incl. Header), -1 = Error\r
576 // handle = -1 -> no output\r
577 { U16 raw[3];\r
578   U32 len;\r
579   int short_tag;\r
580 \r
581   if (!t) return -1;\r
582 \r
583   len = (t->id==ST_DEFINESPRITE)?DefineSprite_GetRealSize(t):t->len;\r
584 \r
585   short_tag = len<0x3f;\r
586 \r
587   if (handle>=0)\r
588   { if (short_tag)\r
589     { raw[0] = len|((t->id&0x3ff)<<6);\r
590       if (write(handle,raw,2)!=2)\r
591       {\r
592         #ifdef DEBUG_RFXSWF\r
593           fprintf(stderr,"WriteTag() failed: Short Header.\n");\r
594         #endif\r
595         return -1;\r
596       }\r
597     }\r
598     else\r
599     { raw[0] = (t->id<<6)|0x3f;\r
600       raw[1] = (U16)(len&0xffff);\r
601       raw[2] = (U16)(len>>16);\r
602       if (write(handle,raw,6)!=6)\r
603       {\r
604         #ifdef DEBUG_RFXSWF\r
605           fprintf(stderr,"WriteTag() failed: Long Header.\n");\r
606         #endif\r
607         return -1;\r
608       }\r
609     }\r
610     \r
611     if (t->data)\r
612     { if (write(handle,t->data,t->len)!=t->len)\r
613       {\r
614         #ifdef DEBUG_RFXSWF\r
615           fprintf(stderr,"WriteTag() failed: Data.\n");\r
616         #endif\r
617         return -1;\r
618       }\r
619     }\r
620     #ifdef DEBUG_RFXSWF\r
621       else if (t->len) fprintf(stderr,"WriteTag(): Tag Data Error, id=%i\n",t->id);\r
622     #endif\r
623   }\r
624 \r
625   return t->len+(short_tag?2:6);\r
626 }\r
627 \r
628 int DefineSprite_GetRealSize(LPTAG t)\r
629 // Sprite Handling: Helper function to pack DefineSprite-Tag\r
630 { U32 len = t->len;\r
631   do\r
632   { t = NextTag(t);\r
633     if (t->id!=ST_DEFINESPRITE) len += RFXSWF_WriteTag(-1,t);\r
634     else t = NULL;\r
635   } while (t&&(t->id!=ST_END));\r
636   return len;\r
637 }\r
638 \r
639 #define ReadTag(a,b)  RFXSWF_ReadTag(a,b)\r
640 #define WriteTag(a,b) RFXSWF_WriteTag(a,b)\r
641 \r
642 // Movie Functions\r
643 \r
644 int ReadSWF(int handle,LPSWF swf)       // Reads SWF to memory (malloc'ed), returns length or <0 if fails\r
645 {     \r
646   if (!swf) return -1;\r
647   memset(swf,0x00,sizeof(SWF));\r
648 \r
649   { char b[32];                         // Header lesen\r
650     TAG t1;\r
651     LPTAG t;\r
652     \r
653     memset(&t1,0x00,sizeof(TAG));\r
654     \r
655     if ((t1.len=read(handle,b,32))<21) return -1;\r
656     t1.data = (U8*)b;\r
657 \r
658     if (GetU8(&t1)!=(U8)'F') return -1;\r
659     if (GetU8(&t1)!=(U8)'W') return -1;\r
660     if (GetU8(&t1)!=(U8)'S') return -1;\r
661 \r
662     swf->FileVersion = GetU8(&t1);\r
663     swf->FileSize    = GetU32(&t1);\r
664     GetRect(&t1,&swf->MovieSize);\r
665     swf->FrameRate   = GetU16(&t1);\r
666     swf->FrameCount  = GetU16(&t1);\r
667 \r
668     GetU8(&t1);\r
669     lseek(handle,GetTagPos(&t1)-1,SEEK_SET);\r
670   \r
671                                         // Tags lesen und verketten\r
672     t = &t1;\r
673     while (t) t = ReadTag(handle,t);\r
674     swf->FirstTag = t1.next;\r
675     t1.next->prev = NULL;\r
676   }\r
677   \r
678   return 0;\r
679 }\r
680 int  WriteSWF(int handle,LPSWF swf)     // Writes SWF to file, returns length or <0 if fails\r
681 { U32 len;\r
682   LPTAG t;\r
683     \r
684   if (!swf) return -1;\r
685 \r
686   // Insert REFLEX Tag\r
687 \r
688 #ifdef INSERT_RFX_TAG\r
689 \r
690   if (NextTag(swf->FirstTag))\r
691     if (GetTagID(NextTag(swf->FirstTag))!=ST_REFLEX)\r
692       SetBlock(InsertTag(swf->FirstTag,ST_REFLEX),"rfx",3);\r
693 \r
694 #endif // INSERT_RFX_TAG\r
695 \r
696   // Count Frames + File Size\r
697 \r
698   len = 0;\r
699   t = swf->FirstTag;\r
700   swf->FrameCount = 0;\r
701 \r
702   while(t)\r
703   { len += WriteTag(-1,t);\r
704     if (t->id==ST_SHOWFRAME) swf->FrameCount++;\r
705     t = NextTag(t);\r
706   }\r
707   \r
708   { TAG t1;\r
709     char b[64];\r
710     U32 l;\r
711 \r
712     memset(&t1,0x00,sizeof(TAG));\r
713     t1.data    = (U8*)b;\r
714     t1.memsize = 64;\r
715     \r
716     SetU8(&t1,'F');      \r
717     SetU8(&t1,'W');      \r
718     SetU8(&t1,'S');\r
719     SetU8(&t1,swf->FileVersion);\r
720     \r
721     SetU32(&t1,0);                      // Keep space for filesize\r
722     SetRect(&t1,&swf->MovieSize);\r
723     SetU16(&t1,swf->FrameRate);\r
724     SetU16(&t1,swf->FrameCount);\r
725 \r
726     l = GetDataSize(&t1);\r
727     swf->FileSize = l+len;\r
728     t1.len = 4;                         // bad & ugly trick !\r
729     SetU32(&t1,swf->FileSize);\r
730 \r
731     if (handle>=0)\r
732     { \r
733       int ret = write(handle,b,l);\r
734       if (ret!=l)\r
735       {\r
736         #ifdef DEBUG_RFXSWF\r
737           printf("ret:%d (fd:%d)\n",ret, handle);\r
738           perror("write:");\r
739           fprintf(stderr,"WriteSWF() failed: Header.\n");\r
740         #endif\r
741         return -1;\r
742       }\r
743 \r
744       t = swf->FirstTag;\r
745       while (t)\r
746       { if (WriteTag(handle,t)<0) return -1;\r
747         t = NextTag(t);\r
748       }\r
749     }\r
750   }\r
751   return (int)swf->FileSize;\r
752 }\r
753 \r
754 int WriteCGI(LPSWF swf)\r
755 { int len;\r
756   char s[1024];\r
757     \r
758   len = WriteSWF(-1,swf);\r
759 \r
760   if (len<0) return -1;\r
761 \r
762   sprintf(s,"Content-type: application/x-shockwave-flash\n"\\r
763             "Accept-Ranges: bytes\n"\\r
764             "Content-Length: %lu\n"\\r
765             "Expires: Thu, 13 Apr 2000 23:59:59 GMT\n"\\r
766             "\n",len);\r
767             \r
768   write(fileno(stdout),s,strlen(s));\r
769   return WriteSWF(fileno(stdout),swf);\r
770 }\r
771 \r
772 void FreeTags(LPSWF swf)                 // Frees all malloc'ed memory for tags\r
773 { LPTAG t = swf->FirstTag;\r
774 \r
775   while (t)\r
776   { LPTAG tnew = t->next;\r
777     if (t->data) free(t->data);\r
778     free(t);\r
779     t = tnew;\r
780   }\r
781 }\r
782 \r
783 // include advanced functions\r
784 \r
785 #ifdef __NT__\r
786 \r
787 #include "modules\swfdump.c"\r
788 #include "modules\swfshape.c"\r
789 #include "modules\swftext.c"\r
790 #include "modules\swfobject.c"\r
791 #include "modules\swfbutton.c"\r
792 #include "modules\swfbits.c"\r
793 #include "modules\swftools.c"\r
794 #include "modules\swfcgi.c"\r
795 \r
796 #else\r
797 \r
798 #include "modules/swfdump.c"\r
799 #include "modules/swfshape.c"\r
800 #include "modules/swftext.c"\r
801 #include "modules/swfobject.c"\r
802 #include "modules/swfbutton.c"\r
803 #include "modules/swfbits.c"\r
804 #include "modules/swftools.c"\r
805 #include "modules/swfcgi.c"\r
806 \r
807 #endif\r
808 \r
809 \r