moved swf_ResetReadBits from rfxswf.c to rfxswf.h.
[swftools.git] / lib / rfxswf.c
index 94049b2..e7cb0d8 100644 (file)
@@ -65,11 +65,6 @@ U32   swf_GetTagLen(TAG * t) { return t->len; }
 U8*   swf_GetTagLenPtr(TAG * t) { return &(t->data[t->len]); }
 U32   swf_GetTagPos(TAG * t)   { return t->pos; }
 
-// Basic Data Access Functions
-
-#define swf_ResetReadBits(tag)   if (tag->readBit)  { tag->pos++; tag->readBit = 0; }
-#define swf_ResetWriteBits(tag)  if (tag->writeBit) { tag->writeBit = 0; }
-
 // for future purpose: avoid high level lib functions to change tagpos/bitpos
 
 #define swf_SaveTagPos(tag)
@@ -78,9 +73,11 @@ U32   swf_GetTagPos(TAG * t)   { return t->pos; }
 void swf_SetTagPos(TAG * t,U32 pos)
 { swf_ResetReadBits(t);
   if (pos<=t->len) t->pos = pos;
-  #ifdef DEBUG_RFXSWF
-  else fprintf(stderr,"SetTagPos() out of bounds: TagID = %i\n",t->id);
-  #endif
+  else { 
+#ifdef DEBUG_RFXSWF
+    fprintf(stderr,"SetTagPos(%d) out of bounds: TagID = %i\n",pos, t->id);
+#endif
+  }
 }
 
 char* swf_GetString(TAG*t)
@@ -288,7 +285,7 @@ int swf_SetRGBA(TAG * t,RGBA * col)
 void swf_GetRGBA(TAG * t, RGBA * col)
 {
     RGBA dummy;
-    if(!col);
+    if(!col)
        col = &dummy;
     col->r = swf_GetU8(t);
     col->g = swf_GetU8(t);
@@ -433,6 +430,8 @@ void swf_ExpandRect2(SRECT*src, SRECT*add)
 {
     if((add->xmin | add->ymin | add->xmax | add->ymax)==0)
        return;
+    if((src->xmin | src->ymin | src->xmax | src->ymax)==0)
+       *src = *add;
     if(add->xmin < src->xmin)
        src->xmin = add->xmin;
     if(add->ymin < src->ymin)
@@ -861,7 +860,7 @@ int swf_WriteTag2(struct writer_t*writer, TAG * t)
 
   len = (t->id==ST_DEFINESPRITE)?swf_DefineSprite_GetRealSize(t):t->len;
 
-  short_tag = len<0x3f;
+  short_tag = len<0x3f&&(t->id!=ST_DEFINEBITSLOSSLESS&&t->id!=ST_DEFINEBITSLOSSLESS2);
 
   if (writer)
   { if (short_tag)
@@ -915,10 +914,13 @@ int swf_WriteTag2(struct writer_t*writer, TAG * t)
 int swf_WriteTag(int handle, TAG * t)
 {
   struct writer_t writer;
+  int len = 0;
   if(handle<0)
     return swf_WriteTag2(0, t);
   writer_init_filewriter(&writer, handle);
-  return swf_WriteTag2(&writer, t);
+  len = swf_WriteTag2(&writer, t);
+  writer.finish(&writer);
+  return len;
 }
 
 int swf_DefineSprite_GetRealSize(TAG * t)
@@ -1035,7 +1037,7 @@ void swf_FoldSprite(TAG * t)
 
   do
   { 
-    if(t->len<0x3f) {
+    if(t->len<0x3f&&t->id!=ST_DEFINEBITSLOSSLESS&&t->id!=ST_DEFINEBITSLOSSLESS2) {
        swf_SetU16(sprtag,t->len|(t->id<<6));
     } else {
        swf_SetU16(sprtag,0x3f|(t->id<<6));
@@ -1077,14 +1079,6 @@ void swf_FoldAll(SWF*swf)
     }
 }
 
-void swf_FoldAllTags(TAG*tag)
-{
-    SWF swf;
-    memset(&swf, 0, sizeof(swf));
-    swf.firstTag = tag;
-    swf_FoldAll(&swf);
-}
-
 void swf_UnFoldAll(SWF*swf)
 {
     TAG*tag = swf->firstTag;
@@ -1206,8 +1200,14 @@ int  swf_WriteSWF2(struct writer_t*writer, SWF * swf)     // Writes SWF to file,
   int frameCount=0;
   struct writer_t zwriter;
   int fileSize = 0;
+  int inSprite = 0;
+  int writer_lastpos = 0;
+  int ret;
     
   if (!swf) return -1;
+  if (!writer) return -1; // the caller should provide a nullwriter, not 0, for querying SWF size
+
+  if(writer) writer_lastpos = writer->pos;
 
   // Insert REFLEX Tag
 
@@ -1215,7 +1215,7 @@ int  swf_WriteSWF2(struct writer_t*writer, SWF * swf)     // Writes SWF to file,
 
   if (swf->firstTag && swf_NextTag(swf->firstTag))
     if (swf_GetTagID(swf_NextTag(swf->firstTag))!=ST_REFLEX)
-      swf_SetBlock(swf_InsertTag(swf->firstTag,ST_REFLEX),"rfx",3);
+      swf_SetBlock(swf_InsertTagBefore(swf, swf->firstTag,ST_REFLEX),"rfx",3);
 
 #endif // INSERT_RFX_TAG
 
@@ -1225,10 +1225,12 @@ int  swf_WriteSWF2(struct writer_t*writer, SWF * swf)     // Writes SWF to file,
   t = swf->firstTag;
   frameCount = 0;
 
-  while(t)
-  { len += swf_WriteTag(-1, t);
-    if (t->id==ST_SHOWFRAME) frameCount++;
-    t = swf_NextTag(t);
+  while(t) {
+      len += swf_WriteTag(-1,t);
+      if(t->id == ST_DEFINESPRITE) inSprite++;
+      else if(t->id == ST_END && inSprite) inSprite--;
+      else if(t->id == ST_SHOWFRAME && !inSprite) frameCount++;
+      t = swf_NextTag(t);
   }
   
   { TAG t1;
@@ -1263,7 +1265,10 @@ int  swf_WriteSWF2(struct writer_t*writer, SWF * swf)     // Writes SWF to file,
     if(swf->compressed != 8) {
     /* compressed flag set to 8 means "skip first 8 
        header bytes". This is necessary if the caller wants to
-       create compressed SWFs himself */
+       create compressed SWFs himself .
+       It also means that we don't initialize our own zlib
+       writer, but assume the caller provided one.
+     */
       if(swf->compressed) {
        char*id = "CWS";
        writer->write(writer, id, 3);
@@ -1287,53 +1292,64 @@ int  swf_WriteSWF2(struct writer_t*writer, SWF * swf)     // Writes SWF to file,
     swf_SetU16(&t1,swf->frameRate);
     swf_SetU16(&t1,swf->frameCount);
 
-    if (writer)
-    { 
-      int ret = writer->write(writer,b,swf_GetTagLen(&t1));
-      if (ret!=swf_GetTagLen(&t1))
-      {
-        #ifdef DEBUG_RFXSWF
-          fprintf(stderr, "ret:%d\n",ret);
-          perror("write:");
-          fprintf(stderr,"WriteSWF() failed: Header.\n");
-        #endif
-        return -1;
-      }
+    ret = writer->write(writer,b,swf_GetTagLen(&t1));
+    if (ret!=swf_GetTagLen(&t1))
+    {
+      #ifdef DEBUG_RFXSWF
+       fprintf(stderr, "ret:%d\n",ret);
+       perror("write:");
+       fprintf(stderr,"WriteSWF() failed: Header.\n");
+      #endif
+      return -1;
+    }
 
-      t = swf->firstTag;
-      while (t)
-      { if (swf_WriteTag2(writer, t)<0) return -1;
-        t = swf_NextTag(t);
+    t = swf->firstTag;
+    while (t)
+    { if (swf_WriteTag2(writer, t)<0) return -1;
+      t = swf_NextTag(t);
+    }
+    if(swf->compressed) {
+      if(swf->compressed != 8) {
+       zwriter.finish(&zwriter);
+       return writer->pos - writer_lastpos;
       }
-      if(swf->compressed != 8)
-       writer->finish(writer); // flush zlib buffers - only if _we_ initialized that writer.
+      return (int)fileSize;
+    } else {
+      return (int)fileSize;
     }
   }
-  return (int)fileSize;
 }
 
 int  swf_WriteSWF(int handle, SWF * swf)     // Writes SWF to file, returns length or <0 if fails
 {
   struct writer_t writer;
+  int len = 0;
   swf->compressed = 0;
+  
   if(handle<0) {
     writer_init_nullwriter(&writer);
-    return swf_WriteSWF2(&writer, swf);
+    len = swf_WriteSWF2(&writer, swf);
   }
   writer_init_filewriter(&writer, handle);
-  return swf_WriteSWF2(&writer, swf);
+  len = swf_WriteSWF2(&writer, swf);
+  writer.finish(&writer);
+  return len;
 }
 
 int  swf_WriteSWC(int handle, SWF * swf)     // Writes SWF to file, returns length or <0 if fails
 {
   struct writer_t writer;
+  int len = 0;
   swf->compressed = 1;
+
   if(handle<0) {
     writer_init_nullwriter(&writer);
-    return swf_WriteSWF2(&writer, swf);
+    len = swf_WriteSWF2(&writer, swf);
   }
   writer_init_filewriter(&writer, handle);
-  return swf_WriteSWF2(&writer, swf);
+  len = swf_WriteSWF2(&writer, swf);
+  writer.finish(&writer);
+  return len;
 }
 
 int swf_WriteHeader2(struct writer_t*writer,SWF * swf)
@@ -1379,6 +1395,7 @@ void swf_FreeTags(SWF * swf)                 // Frees all malloc'ed memory for t
     free(t);
     t = tnew;
   }
+  swf->firstTag = 0;
 }
 
 // include advanced functions