win32 compile fixes
[swftools.git] / lib / modules / swfshape.c
index 0033f40..c5a8835 100644 (file)
@@ -203,7 +203,7 @@ int swf_SetShapeStyleCount(TAG * t,U16 n)
     return 3;
   }
   else
-  { swf_SetU8(t,n);
+  { swf_SetU8(t,(U8)n);
     return 1;
   }
 }
@@ -277,9 +277,9 @@ int swf_ShapeAddFillStyle(SHAPE * s,U8 type,MATRIX * m,RGBA * color,U16 id_bitma
   // handle memory
   
   if (s->fillstyle.data)
-  { FILLSTYLE * new = (FILLSTYLE *)rfx_realloc(s->fillstyle.data,(s->fillstyle.n+1)*sizeof(FILLSTYLE));
-    if (!new) return -1;
-    s->fillstyle.data = new;
+  { FILLSTYLE * xnew = (FILLSTYLE *)rfx_realloc(s->fillstyle.data,(s->fillstyle.n+1)*sizeof(FILLSTYLE));
+    if (!xnew) return -1;
+    s->fillstyle.data = xnew;
   }
   else
   { s->fillstyle.data = (FILLSTYLE *)rfx_alloc(sizeof(FILLSTYLE));
@@ -297,6 +297,10 @@ int swf_ShapeAddFillStyle(SHAPE * s,U8 type,MATRIX * m,RGBA * color,U16 id_bitma
           
   return (++s->fillstyle.n);
 }
+int swf_ShapeAddFillStyle2(SHAPE * s,FILLSTYLE*fs)
+{
+    return swf_ShapeAddFillStyle(s, fs->type, &fs->m, &fs->color, fs->id_bitmap, &fs->gradient);
+}
 
 int swf_ShapeAddSolidFillStyle(SHAPE * s,RGBA * color)
 { return swf_ShapeAddFillStyle(s,FILL_SOLID,NULL,color,0,0);
@@ -319,9 +323,9 @@ int swf_ShapeAddLineStyle(SHAPE * s,U16 width,RGBA * color)
     def.r = def.g = def.b = 0; 
   }
   if (s->linestyle.data)
-  { LINESTYLE * new = (LINESTYLE *)rfx_realloc(s->linestyle.data,(s->linestyle.n+1)*sizeof(LINESTYLE));
-    if (!new) return -1;
-    s->linestyle.data = new;
+  { LINESTYLE * xnew = (LINESTYLE *)rfx_realloc(s->linestyle.data,(s->linestyle.n+1)*sizeof(LINESTYLE));
+    if (!xnew) return -1;
+    s->linestyle.data = xnew;
   }
   else
   { s->linestyle.data = (LINESTYLE *)rfx_alloc(sizeof(LINESTYLE));
@@ -414,8 +418,8 @@ int swf_ShapeSetLine(TAG * t,SHAPE * s,S32 x,S32 y)
     b = swf_CountBits(y,b);
     if (b<2) b=2;
     if(b >= 18) {
-        if(b >= 18 + 4) {
-            /* do not split into more than 16 segments. If the line is *that* long, something's broken */
+        if(b >= 18 + 6) {
+            /* do not split into more than 64 segments. If the line is *that* long, something's broken */
             fprintf(stderr, "Warning: Line to %.2f,%.2f is too long\n", (double)x,(double)y);
             return -1;
         } else {
@@ -495,8 +499,111 @@ int swf_ShapeSetCircle(TAG * t,SHAPE * s,S32 x,S32 y,S32 rx,S32 ry)
   return 0;
 }
 
+void dummycallback1(TAG*tag, int x, void*y)
+{
+}
+
+// from swftools.c:
+void enumerateUsedIDs_styles(TAG * tag, void (*callback)(TAG*, int, void*), void*callback_data, int num, int morph);
+
+static int parseFillStyleArray(TAG*tag, SHAPE2*shape)
+{
+    U16 count;
+    int t;
+    int num=0;
+    int fillstylestart = shape->numfillstyles;
+    int linestylestart = shape->numlinestyles;
+
+    if(tag->id == ST_DEFINESHAPE)
+       num = 1;
+    else if(tag->id == ST_DEFINESHAPE2)
+       num = 2;
+    else if(tag->id == ST_DEFINESHAPE3)
+       num = 3;
+    else if(tag->id == ST_DEFINESHAPE4)
+       num = 4;
+
+    count = swf_GetU8(tag);
+    if(count == 0xff && num>1) // defineshape2,3 only
+       count = swf_GetU16(tag);
+
+    shape->numfillstyles += count;
+    if(shape->numfillstyles) {
+       shape->fillstyles = (FILLSTYLE*)rfx_realloc(shape->fillstyles, sizeof(FILLSTYLE)*shape->numfillstyles);
+
+        for(t=fillstylestart;t<shape->numfillstyles;t++)
+        {
+            int type;
+            FILLSTYLE*dest = &shape->fillstyles[t];
+            type = swf_GetU8(tag); //type
+            shape->fillstyles[t].type = type;
+            if(type == 0) {
+                /* plain color */
+                if(num >= 3)
+                    swf_GetRGBA(tag, &dest->color);
+                else 
+                    swf_GetRGB(tag, &dest->color);
+            }
+            else if(type == 0x10 || type == 0x11 || type == 0x12 || type == 0x13)
+            {
+                /* linear/radial gradient fill */
+                swf_ResetReadBits(tag);
+                swf_GetMatrix(tag, &dest->m);
+                swf_ResetReadBits(tag);
+                swf_GetGradient(tag, &dest->gradient, num>=3?1:0);
+               if(type == 0x13)
+                   swf_GetU8(tag);
+            }
+            else if(type == 0x40 || type == 0x41 || type == 0x42 || type == 0x43)
+            {
+                /* bitmap fill */
+                swf_ResetReadBits(tag);
+                dest->id_bitmap = swf_GetU16(tag); //id
+                swf_ResetReadBits(tag); //?
+                swf_GetMatrix(tag, &dest->m);
+            }
+            else {
+                fprintf(stderr, "rfxswf:swftools.c Unknown fillstyle:0x%02x\n",type);
+            }
+        }
+    }
+
+    swf_ResetReadBits(tag);
+    count = swf_GetU8(tag); // line style array
+    if(count == 0xff)
+       count = swf_GetU16(tag);
+
+    shape->numlinestyles += count;
+    if(count) {
+       shape->linestyles = (LINESTYLE*)rfx_realloc(shape->linestyles, sizeof(LINESTYLE)*shape->numlinestyles);
+        /* TODO: should we start with 1 and insert a correct definition of the
+           "built in" linestyle 0? */
+        for(t=linestylestart;t<shape->numlinestyles;t++) 
+        {
+            shape->linestyles[t].width = swf_GetU16(tag);
+
+           if(num >= 4) {
+               U16 flags = swf_GetU16(tag);
+               if(flags & 0x2000)
+                   swf_GetU16(tag); // miter limit
+               if(flags & 0x0800) {
+                   fprintf(stderr, "Filled strokes parsing not yet supported\n");
+                   return 0;
+               }
+           }
+
+            if(num >= 3)
+                swf_GetRGBA(tag, &shape->linestyles[t].color);
+            else
+                swf_GetRGB(tag, &shape->linestyles[t].color);
+        }
+    }
+    return 1;
+}
+
+
 /* todo: merge this with swf_GetSimpleShape */
-SHAPELINE* swf_ParseShapeData(U8*data, int bits, int fillbits, int linebits)
+static SHAPELINE* swf_ParseShapeData(U8*data, int bits, int fillbits, int linebits, int version, SHAPE2*shape2)
 {
     SHAPELINE _lines;
     SHAPELINE*lines = &_lines;
@@ -507,11 +614,14 @@ SHAPELINE* swf_ParseShapeData(U8*data, int bits, int fillbits, int linebits)
     int fill1 = 0;
     int line = 0;
     int x=0,y=0;
+    int linestyleadd=0;
+    int fillstyleadd=0;
     
     memset(tag, 0, sizeof(TAG));
     tag->data = data;
     tag->len = tag->memsize = (bits+7)/8;
     tag->pos = 0;
+    tag->id = version==1?ST_DEFINESHAPE:(version==2?ST_DEFINESHAPE2:ST_DEFINESHAPE3);
 
     lines->next = 0;
     while(1) {
@@ -527,15 +637,21 @@ SHAPELINE* swf_ParseShapeData(U8*data, int bits, int fillbits, int linebits)
                y = swf_GetSBits(tag, n); //y
            }
            if(flags&2)
-               fill0 = swf_GetBits(tag, fillbits); 
+               fill0 = swf_GetBits(tag, fillbits) + fillstyleadd; 
            if(flags&4)
-               fill1 = swf_GetBits(tag, fillbits); 
+               fill1 = swf_GetBits(tag, fillbits) + fillstyleadd; 
            if(flags&8)
-               line = swf_GetBits(tag, linebits); 
+               line = swf_GetBits(tag, linebits) + linestyleadd; 
            if(flags&16) {
-               fprintf(stderr, "Additional file styles style change not yet supported\n");
-               exit(1);
-               //enumerateUsedIDs_styles(tag, callback, callback_data, num);
+               if(!shape2) {
+                   fprintf(stderr, "rfxswf: Error: Additional fillstyles not supported\n");fflush(stderr);
+                   enumerateUsedIDs_styles(tag, dummycallback1, 0, version, 0);
+               } else {
+                   linestyleadd = shape2->numlinestyles;
+                   fillstyleadd = shape2->numfillstyles;
+                   if(!parseFillStyleArray(tag, shape2))
+                       return 0;
+               }
                fillbits = swf_GetBits(tag, 4);
                linebits = swf_GetBits(tag, 4);
            }
@@ -648,32 +764,41 @@ SRECT swf_GetShapeBoundingBox(SHAPE2*shape2)
 void swf_Shape2Free(SHAPE2 * s)
 {
     SHAPELINE*line = s->lines;
+    s->lines = 0;
     while(line) {
        SHAPELINE*next = line->next;
+       line->next = 0;
        rfx_free(line);
        line = next;
     }
-    if(s->linestyles)
+
+    if(s->linestyles) {
        rfx_free(s->linestyles);
-    if(s->fillstyles)
+       s->linestyles = 0;
+    }
+    if(s->fillstyles) {
        rfx_free(s->fillstyles);
-    if(s->bbox)
+       s->fillstyles = 0;
+    }
+    if(s->bbox) {
        rfx_free(s->bbox);
+       s->bbox = 0;
+    }
 }
 
 SHAPE2* swf_Shape2Clone(SHAPE2 * s)
 {
     SHAPELINE*line = s->lines;
     SHAPELINE*prev = 0;
-    SHAPE2*s2 = rfx_alloc(sizeof(SHAPE2));
+    SHAPE2*s2 = (SHAPE2*)rfx_alloc(sizeof(SHAPE2));
     memcpy(s2,s,sizeof(SHAPE2));
-    s2->linestyles = rfx_alloc(sizeof(LINESTYLE)*s->numlinestyles);
+    s2->linestyles = (LINESTYLE*)rfx_alloc(sizeof(LINESTYLE)*s->numlinestyles);
     memcpy(s2->linestyles, s->linestyles, sizeof(LINESTYLE)*s->numlinestyles);
-    s2->fillstyles = rfx_alloc(sizeof(FILLSTYLE)*s->numfillstyles);
+    s2->fillstyles = (FILLSTYLE*)rfx_alloc(sizeof(FILLSTYLE)*s->numfillstyles);
     memcpy(s2->fillstyles, s->fillstyles, sizeof(FILLSTYLE)*s->numfillstyles);
 
     while(line) {
-       SHAPELINE*line2 = rfx_alloc(sizeof(SHAPELINE));
+       SHAPELINE*line2 = (SHAPELINE*)rfx_alloc(sizeof(SHAPELINE));
         memcpy(line2, line, sizeof(SHAPELINE));
         line2->next = 0;
         if(prev)
@@ -684,7 +809,7 @@ SHAPE2* swf_Shape2Clone(SHAPE2 * s)
        line = line->next;
     }
     if(s->bbox) {
-        s2->bbox = rfx_alloc(sizeof(SRECT));
+        s2->bbox = (SRECT*)rfx_alloc(sizeof(SRECT));
         memcpy(s2->bbox, s->bbox, sizeof(SRECT));
     }
     return s2;
@@ -706,7 +831,7 @@ SHAPE2* swf_ShapeToShape2(SHAPE*shape) {
         memcpy(shape2->fillstyles, shape->fillstyle.data, sizeof(FILLSTYLE)*shape->fillstyle.n);
     }
 
-    shape2->lines = swf_ParseShapeData(shape->data, shape->bitlen, shape->bits.fill, shape->bits.line);
+    shape2->lines = swf_ParseShapeData(shape->data, shape->bitlen, shape->bits.fill, shape->bits.line, 1, 0);
     shape2->bbox = 0;
     return shape2;
 };
@@ -751,7 +876,7 @@ void swf_ShapeSetBitmapRect(TAG*tag, U16 gfxid, int width, int height)
 void swf_Shape2ToShape(SHAPE2*shape2, SHAPE*shape)
 {
     TAG*tag = swf_InsertTag(0,0);
-    SHAPELINE*l,*next;
+    SHAPELINE*l;
     int newx=0,newy=0,lastx=0,lasty=0,oldls=0,oldfs0=0,oldfs1=0;
 
     memset(shape, 0, sizeof(SHAPE));
@@ -800,6 +925,7 @@ void swf_Shape2ToShape(SHAPE2*shape2, SHAPE*shape)
     swf_ShapeSetEnd(tag);
     shape->data = tag->data;
     shape->bitlen = tag->len*8;
+    free(tag);
 }
 
 void swf_SetShape2(TAG*tag, SHAPE2*shape2)
@@ -815,93 +941,10 @@ void swf_SetShape2(TAG*tag, SHAPE2*shape2)
     swf_SetBlock(tag, shape.data, (shape.bitlen+7)/8);
 }
 
-static void parseFillStyleArray(TAG*tag, SHAPE2*shape)
-{
-    U16 count;
-    int t;
-    int num=0;
-    if(tag->id == ST_DEFINESHAPE)
-       num = 1;
-    else if(tag->id == ST_DEFINESHAPE2)
-       num = 2;
-    else if(tag->id == ST_DEFINESHAPE3)
-       num = 3;
-
-    count = swf_GetU8(tag);
-    if(count == 0xff && num>1) // defineshape2,3 only
-       count = swf_GetU16(tag);
-
-    shape->numfillstyles = count;
-
-    if(shape->numfillstyles) {
-        shape->fillstyles = rfx_alloc(sizeof(FILLSTYLE)*count);
-
-        for(t=0;t<count;t++)
-        {
-            int type;
-            U8*pos;
-            FILLSTYLE*dest = &shape->fillstyles[t];
-            type = swf_GetU8(tag); //type
-            shape->fillstyles[t].type = type;
-            if(type == 0) {
-                /* plain color */
-                if(num == 3)
-                    swf_GetRGBA(tag, &dest->color);
-                else 
-                    swf_GetRGB(tag, &dest->color);
-            }
-            else if(type == 0x10 || type == 0x12)
-            {
-                /* linear/radial gradient fill */
-                swf_ResetReadBits(tag);
-                swf_GetMatrix(tag, &dest->m);
-                swf_ResetReadBits(tag);
-                swf_GetGradient(tag, &dest->gradient, num>=3?1:0);
-            }
-            else if(type == 0x40 || type == 0x41)
-            {
-                /* bitmap fill */
-                swf_ResetReadBits(tag);
-                dest->id_bitmap = swf_GetU16(tag); //id
-                swf_ResetReadBits(tag); //?
-                swf_GetMatrix(tag, &dest->m);
-            }
-            else {
-                fprintf(stderr, "rfxswf:swftools.c Unknown fillstyle:0x%02x\n",type);
-            }
-        }
-    }
-
-    swf_ResetReadBits(tag);
-    count = swf_GetU8(tag); // line style array
-    if(count == 0xff)
-       count = swf_GetU16(tag);
-
-    //if(verbose) printf("lnum: %d\n", count);
-
-    shape->numlinestyles = count;
-    if(count) {
-        shape->linestyles = rfx_alloc(sizeof(LINESTYLE)*count);
-        /* TODO: should we start with 1 and insert a correct definition of the
-           "built in" linestyle 0? */
-        for(t=0;t<count;t++) 
-        {
-            shape->linestyles[t].width = swf_GetU16(tag);
-            if(num == 3)
-                swf_GetRGBA(tag, &shape->linestyles[t].color);
-            else
-                swf_GetRGB(tag, &shape->linestyles[t].color);
-        }
-    }
-    return;
-}
-
 void swf_ParseDefineShape(TAG*tag, SHAPE2*shape)
 {
     int num = 0, id;
     U16 fill,line;
-    SRECT r;
-    SRECT r2;
     SHAPELINE*l;
     if(tag->id == ST_DEFINESHAPE)
        num = 1;
@@ -909,27 +952,45 @@ void swf_ParseDefineShape(TAG*tag, SHAPE2*shape)
        num = 2;
     else if(tag->id == ST_DEFINESHAPE3)
        num = 3;
+    else if(tag->id == ST_DEFINESHAPE4)
+       num = 4;
     else {
        fprintf(stderr, "parseDefineShape must be called with a shape tag");
     }
+    swf_SetTagPos(tag, 0);
 
     id = swf_GetU16(tag); //id
     memset(shape, 0, sizeof(SHAPE2));
-    shape->bbox = rfx_alloc(sizeof(SRECT));
-    swf_GetRect(tag, &r);
+    shape->bbox = (SRECT*)rfx_alloc(sizeof(SRECT));
+    swf_GetRect(tag, shape->bbox);
+    if(num>=4) {
+       SRECT r2;
+       swf_ResetReadBits(tag);
+       swf_GetRect(tag, &r2); // edge bounds
+       U8 flags = swf_GetU8(tag); // flags, &1: contains scaling stroke, &2: contains non-scaling stroke
+    }
 
-    memcpy(shape->bbox, &r, sizeof(SRECT));
-    parseFillStyleArray(tag, shape);
+    if(!parseFillStyleArray(tag, shape)) {
+       return;
+    }
 
     swf_ResetReadBits(tag); 
     fill = (U16)swf_GetBits(tag,4);
     line = (U16)swf_GetBits(tag,4);
 
-    shape->lines = swf_ParseShapeData(&tag->data[tag->pos], (tag->len - tag->pos)*8, fill, line);
+    shape->lines = swf_ParseShapeData(&tag->data[tag->pos], (tag->len - tag->pos)*8, fill, line, 
+           tag->id == ST_DEFINESHAPE?1:(tag->id==ST_DEFINESHAPE2?2:3), shape);
 
     l = shape->lines;
 }
 
+static void free_lines(SHAPELINE* lines)
+{
+    if (lines->next)
+        free_lines(lines->next);
+    free(lines);
+}
+
 void swf_RecodeShapeData(U8*data, int bitlen, int in_bits_fill, int in_bits_line, 
                          U8**destdata, U32*destbitlen, int out_bits_fill, int out_bits_line)
 {
@@ -937,11 +998,11 @@ void swf_RecodeShapeData(U8*data, int bitlen, int in_bits_fill, int in_bits_line
     SHAPE s;
     SHAPELINE*line;
     memset(&s2, 0, sizeof(s2));
-    s2.lines = swf_ParseShapeData(data, bitlen, in_bits_fill, in_bits_line);
+    s2.lines = swf_ParseShapeData(data, bitlen, in_bits_fill, in_bits_line, 1, 0);
     s2.numfillstyles = out_bits_fill?1<<(out_bits_fill-1):0;
     s2.numlinestyles = out_bits_line?1<<(out_bits_line-1):0;
-    s2.fillstyles = rfx_calloc(sizeof(FILLSTYLE)*s2.numfillstyles);
-    s2.linestyles = rfx_calloc(sizeof(LINESTYLE)*s2.numlinestyles);
+    s2.fillstyles = (FILLSTYLE*)rfx_calloc(sizeof(FILLSTYLE)*s2.numfillstyles);
+    s2.linestyles = (LINESTYLE*)rfx_calloc(sizeof(LINESTYLE)*s2.numlinestyles);
 
     line = s2.lines;
     while(line) {
@@ -953,6 +1014,7 @@ void swf_RecodeShapeData(U8*data, int bitlen, int in_bits_fill, int in_bits_line
 
     swf_Shape2ToShape(&s2,&s);
 
+    free_lines(s2.lines);
     free(s2.fillstyles);
     free(s2.linestyles);
     free(s.fillstyle.data);