X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fmodules%2Fswfshape.c;h=bc972d494544ca6aabd211156e45c7adc87fb4db;hb=3d73649bf0e39778e715a07da902d0a858065a43;hp=30c57d82ea13eb29eedd785a41a1ecfd2fd06685;hpb=0953475505a56561218e6ab79d3656466270e148;p=swftools.git diff --git a/lib/modules/swfshape.c b/lib/modules/swfshape.c index 30c57d8..bc972d4 100644 --- a/lib/modules/swfshape.c +++ b/lib/modules/swfshape.c @@ -21,38 +21,36 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include "../rfxswf.h" + #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 swf_ShapeFree(SHAPE * s) -{ if (s) - { if (s->linestyle.data) free(s->linestyle.data); +{ + if(!s) + return; + if (s->linestyle.data) rfx_free(s->linestyle.data); s->linestyle.data = NULL; s->linestyle.n = 0; - if (s->fillstyle.data) free(s->fillstyle.data); + if (s->fillstyle.data) rfx_free(s->fillstyle.data); s->fillstyle.data = NULL; s->fillstyle.n = 0; - if (s->data) free(s->data); + if (s->data) rfx_free(s->data); s->data = NULL; - } - free(s); + rfx_free(s); } int swf_ShapeNew(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; +{ + SHAPE * sh; + if (!s) return -1; + sh = (SHAPE *)rfx_calloc(sizeof(SHAPE)); + *s = sh; + return 0; } int swf_GetSimpleShape(TAG * t,SHAPE * * s) // without Linestyle/Fillstyle Record @@ -135,8 +133,8 @@ int swf_GetSimpleShape(TAG * t,SHAPE * * s) // without Linestyle/Fillstyle Recor swf_SetTagPos(t,pos); len = (bitl+7)/8; - if (sh->data) free(sh->data); - sh->data = (U8*)malloc(len); + if (sh->data) rfx_free(sh->data); + sh->data = (U8*)rfx_alloc(len); if (sh->data) { sh->bitlen = bitl; @@ -169,8 +167,6 @@ int swf_SetFillStyle(TAG * t,FILLSTYLE * f) { if ((!t)||(!f)) return -1; swf_SetU8(t,f->type); - // no gradients yet! - switch (f->type) { case FILL_SOLID: if (swf_GetTagID(t)!=ST_DEFINESHAPE3) swf_SetRGB(t,&f->color); @@ -209,7 +205,7 @@ int swf_SetShapeStyleCount(TAG * t,U16 n) return 3; } else - { swf_SetU8(t,n); + { swf_SetU8(t,(U8)n); return 1; } } @@ -283,12 +279,12 @@ int swf_ShapeAddFillStyle(SHAPE * s,U8 type,MATRIX * m,RGBA * color,U16 id_bitma // 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; + { 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 *)malloc(sizeof(FILLSTYLE)); + { s->fillstyle.data = (FILLSTYLE *)rfx_alloc(sizeof(FILLSTYLE)); s->fillstyle.n = 0; if (!s->fillstyle.data) return -1; } @@ -303,6 +299,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); @@ -325,12 +325,12 @@ int swf_ShapeAddLineStyle(SHAPE * s,U16 width,RGBA * color) 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; + { 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 *)malloc(sizeof(LINESTYLE)); + { s->linestyle.data = (LINESTYLE *)rfx_alloc(sizeof(LINESTYLE)); s->linestyle.n = 0; if (!s->linestyle.data) return -1; } @@ -349,7 +349,12 @@ int swf_ShapeSetMove(TAG * t,SHAPE * s,S32 x,S32 y) b = swf_CountBits(x,0); b = swf_CountBits(y,b); - + + if(b>31) { + fprintf(stderr, "Warning: bad moveTo (%f,%f)\n", x/20.0, y/20.0); + b=31; + } + swf_SetBits(t,b,5); swf_SetBits(t,x,b); swf_SetBits(t,y,b); @@ -412,71 +417,73 @@ int swf_ShapeSetEnd(TAG * t) } int swf_ShapeSetLine(TAG * t,SHAPE * s,S32 x,S32 y) -{ U8 b; - if (!t) return -1; - swf_SetBits(t,3,2); // Straight Edge - - if ((!s)||((x!=0)&&(y!=0))) - { b = swf_CountBits(x,2); +{ + U8 b; + if (!t) return -1; + + b = swf_CountBits(x,2); b = swf_CountBits(y,b); if (b<2) b=2; - if(b-2 >= 16) { - fprintf(stderr, "Bit overflow in swf_ShapeSetLine(1)- %d (%d,%d)\n", b, x,y); - fflush(stdout); - b = 17; + if(b >= 18) { + 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 (%d bits)\n", (double)x,(double)y, b); + return -1; + } else { + /* split line */ + int x1,y1,x2,y2; + if(x>=0) { x1 = x/2;x2 = (x+1)/2;} + else { x1 = x/2;x2 = (x-1)/2;} + if(y>=0) { y1 = y/2;y2 = (y+1)/2;} + else { y1 = y/2;y2 = (y-1)/2;} + swf_ShapeSetLine(t, s, x1,y1); + swf_ShapeSetLine(t, s, x2,y2); + return 0; + } } - swf_SetBits(t, b-2, 4); - swf_SetBits(t,1,1); - swf_SetBits(t,x,b); - swf_SetBits(t,y,b); - return 0; - } - if (x==0) - { b = swf_CountBits(y,2); - if(b<2) - b=2; - if(b-2 >= 16) { - fprintf(stderr, "Bit overflow in swf_ShapeSetLine(2)- %d (%d)\n", b, y); - b = 17; - } - swf_SetBits(t, b-2, 4); - swf_SetBits(t,1,2); - swf_SetBits(t,y,b); - } - else - { b = swf_CountBits(x,2); - if(b<2) - b=2; - if(b-2 >= 16) { - fprintf(stderr, "Bit overflow in swf_ShapeSetLine(3)- %d (%d)\n", b, x); - b = 17; + if(x!=0 && y!=0) { //(!s)||((x!=0)&&(y!=0))) + swf_SetBits(t,3,2); // Straight Edge + swf_SetBits(t, b-2, 4); //Number of Bits in x/y + swf_SetBits(t,1,1); // Diagonal + swf_SetBits(t,x,b); + swf_SetBits(t,y,b); + } else if (x==0) { + swf_SetBits(t,3,2); // Straight Edge + swf_SetBits(t, b-2, 4); //Number of Bits in y + swf_SetBits(t,1,2); // Vertical + swf_SetBits(t,y,b); + } else { + swf_SetBits(t,3,2); // Straight Edge + swf_SetBits(t, b-2, 4); //Number of Bits in x + swf_SetBits(t,0,2); // Horizontal + swf_SetBits(t,x,b); } - swf_SetBits(t, b-2, 4); - swf_SetBits(t,0,2); - swf_SetBits(t,x,b); - } - return 0; + return 0; } int swf_ShapeSetCurve(TAG * t,SHAPE * s,S32 x,S32 y,S32 ax,S32 ay) -{ U8 b; - if (!t) return -1; - - swf_SetBits(t,2,2); +{ + U8 b; + if (!t) return -1; - b = swf_CountBits(ax,2); - b = swf_CountBits(ay,b); - b = swf_CountBits(x,b); - b = swf_CountBits(y,b); + b = swf_CountBits(ax,2); + b = swf_CountBits(ay,b); + b = swf_CountBits(x,b); + b = swf_CountBits(y,b); - swf_SetBits(t,b-2,4); - swf_SetBits(t,x,b); - swf_SetBits(t,y,b); - swf_SetBits(t,ax,b); - swf_SetBits(t,ay,b); + if(b >= 18) { + fprintf(stderr, "Bit overflow in swf_ShapeSetCurve- %d (%d,%d,%d,%d)\n", b, ax,ay,x,y); + return swf_ShapeSetLine(t, s, x+ax, y+ay); + } - return 0; + swf_SetBits(t,2,2); + swf_SetBits(t,b-2,4); + swf_SetBits(t,x,b); + swf_SetBits(t,y,b); + swf_SetBits(t,ax,b); + swf_SetBits(t,ay,b); + return 0; } int swf_ShapeSetCircle(TAG * t,SHAPE * s,S32 x,S32 y,S32 rx,S32 ry) @@ -499,8 +506,148 @@ 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 void parseFillStyle(FILLSTYLE*dest, TAG*tag, int num) +{ + int type = swf_GetU8(tag); //type + dest->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_GetU16(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:swfshape.c Unknown fillstyle:0x%02x in tag %02d\n",type, tag->id); + } +} +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;tnumfillstyles;t++) { + parseFillStyle(&shape->fillstyles[t], tag, num); + } + } + + 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;tnumlinestyles;t++) + { + char fill = 0; + shape->linestyles[t].width = swf_GetU16(tag); + + if(num >= 4) { + U16 flags = swf_GetU16(tag); + if((flags & 0x30) == 0x20) + swf_GetU16(tag); // miter limit + if(flags & 0x08) { + fprintf(stderr, "Warning: Filled strokes parsing not yet fully supported\n"); + fill = 1; + } + } + + if(fill) { + FILLSTYLE f; + parseFillStyle(&f, tag, num); + shape->linestyles[t].color = f.color; + } else { + if(num >= 3) + swf_GetRGBA(tag, &shape->linestyles[t].color); + else + swf_GetRGB(tag, &shape->linestyles[t].color); + } + } + } + return 1; +} + +char swf_ShapeIsEmpty(SHAPE*s) +{ + if(!s || !s->data) return 1; + TAG _tag; + TAG* tag = &_tag; + memset(tag, 0, sizeof(TAG)); + tag->data = s->data; + tag->len = tag->memsize = (s->bitlen+7)/8; + tag->pos = 0; + + while(1) { + if(!swf_GetBits(tag, 1)) { + U16 flags = swf_GetBits(tag, 5); + if(!flags) break; + if(flags&1) { //move + int n = swf_GetBits(tag, 5); + swf_GetSBits(tag, n); //x + swf_GetSBits(tag, n); //y + } + if(flags&2) swf_GetBits(tag, s->bits.fill); + if(flags&4) swf_GetBits(tag, s->bits.fill); + if(flags&8) swf_GetBits(tag, s->bits.line); + if(flags&16) {return 0;} + } else { + return 0; + } + } + 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; @@ -511,11 +658,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:(version==3?ST_DEFINESHAPE3:ST_DEFINESHAPE4)); lines->next = 0; while(1) { @@ -531,20 +681,26 @@ 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); } if(flags&1) { //move - lines->next = (SHAPELINE*)malloc(sizeof(SHAPELINE)); + lines->next = (SHAPELINE*)rfx_alloc(sizeof(SHAPELINE)); lines = lines->next; lines->type = moveTo; lines->x = x; @@ -569,7 +725,7 @@ SHAPELINE* swf_ParseShapeData(U8*data, int bits, int fillbits, int linebits) if(v) y += d; else x += d; } - lines->next = (SHAPELINE*)malloc(sizeof(SHAPELINE)); + lines->next = (SHAPELINE*)rfx_alloc(sizeof(SHAPELINE)); lines = lines->next; lines->type = lineTo; lines->x = x; @@ -589,7 +745,7 @@ SHAPELINE* swf_ParseShapeData(U8*data, int bits, int fillbits, int linebits) x += swf_GetSBits(tag, n); y += swf_GetSBits(tag, n); - lines->next = (SHAPELINE*)malloc(sizeof(SHAPELINE)); + lines->next = (SHAPELINE*)rfx_alloc(sizeof(SHAPELINE)); lines = lines->next; lines->type = splineTo; lines->sx = x1; @@ -652,32 +808,74 @@ SRECT swf_GetShapeBoundingBox(SHAPE2*shape2) void swf_Shape2Free(SHAPE2 * s) { SHAPELINE*line = s->lines; + s->lines = 0; while(line) { SHAPELINE*next = line->next; - free(line); + line->next = 0; + rfx_free(line); line = next; } - if(s->linestyles) - free(s->linestyles); - if(s->fillstyles) - free(s->fillstyles); - if(s->bbox) - free(s->bbox); + + if(s->linestyles) { + rfx_free(s->linestyles); + s->linestyles = 0; + } + if(s->fillstyles) { + rfx_free(s->fillstyles); + 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 = (SHAPE2*)rfx_alloc(sizeof(SHAPE2)); + memcpy(s2,s,sizeof(SHAPE2)); + s2->linestyles = (LINESTYLE*)rfx_alloc(sizeof(LINESTYLE)*s->numlinestyles); + memcpy(s2->linestyles, s->linestyles, sizeof(LINESTYLE)*s->numlinestyles); + s2->fillstyles = (FILLSTYLE*)rfx_alloc(sizeof(FILLSTYLE)*s->numfillstyles); + memcpy(s2->fillstyles, s->fillstyles, sizeof(FILLSTYLE)*s->numfillstyles); + + while(line) { + SHAPELINE*line2 = (SHAPELINE*)rfx_alloc(sizeof(SHAPELINE)); + memcpy(line2, line, sizeof(SHAPELINE)); + line2->next = 0; + if(prev) + prev->next = line2; + else + s2->lines = line2; + prev = line2; + line = line->next; + } + if(s->bbox) { + s2->bbox = (SRECT*)rfx_alloc(sizeof(SRECT)); + memcpy(s2->bbox, s->bbox, sizeof(SRECT)); + } + return s2; } SHAPE2* swf_ShapeToShape2(SHAPE*shape) { - SHAPE2*shape2 = (SHAPE2*)malloc(sizeof(SHAPE2)); + SHAPE2*shape2 = (SHAPE2*)rfx_calloc(sizeof(SHAPE2)); shape2->numlinestyles = shape->linestyle.n; - shape2->linestyles = (LINESTYLE*)malloc(sizeof(LINESTYLE)*shape->linestyle.n); - memcpy(shape2->linestyles, shape->linestyle.data, sizeof(LINESTYLE)*shape->linestyle.n); + if(shape2->numlinestyles) { + shape2->linestyles = (LINESTYLE*)rfx_alloc(sizeof(LINESTYLE)*shape->linestyle.n); + memcpy(shape2->linestyles, shape->linestyle.data, sizeof(LINESTYLE)*shape->linestyle.n); + } shape2->numfillstyles = shape->fillstyle.n; - shape2->fillstyles = (FILLSTYLE*)malloc(sizeof(FILLSTYLE)*shape->fillstyle.n); - memcpy(shape2->fillstyles, shape->fillstyle.data, sizeof(FILLSTYLE)*shape->fillstyle.n); + if(shape2->numfillstyles) { + shape2->fillstyles = (FILLSTYLE*)rfx_alloc(sizeof(FILLSTYLE)*shape->fillstyle.n); + 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; }; @@ -719,20 +917,73 @@ void swf_ShapeSetBitmapRect(TAG*tag, U16 gfxid, int width, int height) swf_ShapeFree(shape); } +void swf_ShapeSetRectangle(TAG*tag, U16 shapeid, int width, int height, RGBA*rgba) +{ + RGBA white={255,255,255,255}; + if(!rgba) { + rgba = &white; + } + SHAPE* s; + swf_ShapeNew(&s); + int fs = swf_ShapeAddSolidFillStyle(s, rgba); + swf_SetU16(tag,shapeid); + SRECT r; + r.xmin = 0; + r.xmax = 0; + r.ymin = width; + r.ymax = height; + swf_SetRect(tag,&r); + swf_SetShapeHeader(tag,s); + swf_ShapeSetAll(tag,s,0,0,0,fs,0); + swf_ShapeSetLine(tag,s,width,0); + swf_ShapeSetLine(tag,s,0,height); + swf_ShapeSetLine(tag,s,-width,0); + swf_ShapeSetLine(tag,s,0,-height); + swf_ShapeSetEnd(tag); + swf_ShapeFree(s); +} + +void swf_ShapeSetRectangleWithBorder(TAG*tag, U16 shapeid, int width, int height, RGBA*rgba, int linewidth, RGBA*linecolor) +{ + RGBA white={255,255,255,255}; + if(!rgba) { + rgba = &white; + } + SHAPE* s; + swf_ShapeNew(&s); + int fs = swf_ShapeAddSolidFillStyle(s, rgba); + int ls = swf_ShapeAddLineStyle(s, linewidth, linecolor); + swf_SetU16(tag,shapeid); + SRECT r; + r.xmin = 0; + r.xmax = 0; + r.ymin = width; + r.ymax = height; + swf_SetRect(tag,&r); + swf_SetShapeHeader(tag,s); + swf_ShapeSetAll(tag,s,0,0,ls,fs,0); + swf_ShapeSetLine(tag,s,width,0); + swf_ShapeSetLine(tag,s,0,height); + swf_ShapeSetLine(tag,s,-width,0); + swf_ShapeSetLine(tag,s,0,-height); + swf_ShapeSetEnd(tag); + swf_ShapeFree(s); +} + 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)); shape->linestyle.n = shape2->numlinestyles; - shape->linestyle.data = (LINESTYLE*)malloc(sizeof(LINESTYLE)*shape->linestyle.n); + shape->linestyle.data = (LINESTYLE*)rfx_alloc(sizeof(LINESTYLE)*shape->linestyle.n); memcpy(shape->linestyle.data, shape2->linestyles, sizeof(LINESTYLE)*shape->linestyle.n); shape->fillstyle.n = shape2->numfillstyles; - shape->fillstyle.data = (FILLSTYLE*)malloc(sizeof(FILLSTYLE)*shape->fillstyle.n); + shape->fillstyle.data = (FILLSTYLE*)rfx_alloc(sizeof(FILLSTYLE)*shape->fillstyle.n); memcpy(shape->fillstyle.data, shape2->fillstyles, sizeof(FILLSTYLE)*shape->fillstyle.n); swf_ShapeCountBits(shape,NULL,NULL); @@ -771,6 +1022,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) @@ -780,93 +1032,16 @@ void swf_SetShape2(TAG*tag, SHAPE2*shape2) swf_SetRect(tag,shape2->bbox); swf_SetShapeStyles(tag, &shape); - swf_ShapeCountBits(&shape,NULL,NULL); + //swf_ShapeCountBits(&shape,NULL,NULL); // done in swf_Shape2ToShape() swf_SetShapeBits(tag,&shape); 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; - shape->fillstyles = malloc(sizeof(FILLSTYLE)*count); - - for(t=0;tfillstyles[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; - shape->linestyles = malloc(sizeof(LINESTYLE)*count); - /* TODO: should we start with 1 and insert a correct definition of the - "built in" linestyle 0? */ - for(t=0;tlinestyles[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; @@ -874,24 +1049,76 @@ 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 = malloc(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); + if(!fill && !line) { + fprintf(stderr, "fill/line bits are both zero\n"); + } - 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, num, 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) +{ + SHAPE2 s2; + SHAPE s; + SHAPELINE*line; + memset(&s2, 0, sizeof(s2)); + 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 = (FILLSTYLE*)rfx_calloc(sizeof(FILLSTYLE)*s2.numfillstyles); + s2.linestyles = (LINESTYLE*)rfx_calloc(sizeof(LINESTYLE)*s2.numlinestyles); + + line = s2.lines; + while(line) { + if(line->fillstyle0 > s2.numfillstyles) line->fillstyle0 = 0; + if(line->fillstyle1 > s2.numfillstyles) line->fillstyle1 = 0; + if(line->linestyle > s2.numlinestyles) line->linestyle = 0; + line = line->next; + } + + swf_Shape2ToShape(&s2,&s); + + free_lines(s2.lines); + free(s2.fillstyles); + free(s2.linestyles); + free(s.fillstyle.data); + free(s.linestyle.data); + *destdata = s.data; + *destbitlen = s.bitlen; +} +