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