X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fmodules%2Fswfshape.c;h=fe4d3a2c0a25fd4880f20ce7d665d1f9bd349f96;hb=8526dcf3a698c688e2cc4430ae106b5ecf70677f;hp=459db83ab65d9a61777d2515764a5877fe5e37ce;hpb=2fc61b512b22b9e155195bb25eed1d706a33a179;p=swftools.git diff --git a/lib/modules/swfshape.c b/lib/modules/swfshape.c index 459db83..fe4d3a2 100644 --- a/lib/modules/swfshape.c +++ b/lib/modules/swfshape.c @@ -27,32 +27,28 @@ #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 +131,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 +165,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); @@ -182,6 +176,11 @@ int swf_SetFillStyle(TAG * t,FILLSTYLE * f) swf_SetU16(t,f->id_bitmap); swf_SetMatrix(t,&f->m); break; + case FILL_LINEAR: + case FILL_RADIAL: + swf_SetMatrix(t,&f->m); + swf_SetGradient(t,&f->gradient,/*alpha?*/t->id==ST_DEFINESHAPE3?1:0); + break; } return 0; @@ -252,63 +251,10 @@ int swf_SetShapeHeader(TAG * t,SHAPE * s) return res; } -int swf_ShapeExport(int handle,SHAPE * s) // without Linestyle/Fillstyle Record -{ int l; - if (!s) return 0; - - l = sizeof(SHAPE); - - if (handle>=0) - if (write(handle,s,sizeof(SHAPE))!=sizeof(SHAPE)) return -1; - - // Fillstyle, Linestyle ... - - if (s->data) - { int ll = (s->bitlen+7)/8; - l+=ll; - if (handle>=0) - if (write(handle,s->data,ll)!=ll) return -1; - } - - return l; -} - -int swf_ShapeImport(int handle,SHAPE * * shape) -{ SHAPE * s; - - if (handle<0) return -1; - - s = (SHAPE *)malloc(sizeof(SHAPE)); shape[0] = s; - if (!s) return -1; - - if (read(handle,s,sizeof(SHAPE))!=sizeof(SHAPE)) - { shape[0] = NULL; - free(s); - return -1; - } - - if (s->data) - { int ll = (s->bitlen+7)/8; - s->data = (U8*)malloc(ll); - if (!s->data) - { shape[0] = NULL; - free(s); - return -1; - } - if (read(handle,s->data,ll)!=ll) - { free(s->data); - free(s); - shape[0] = NULL; - return -1; - } - } - - return 0; -} - -int swf_ShapeAddFillStyle(SHAPE * s,U8 type,MATRIX * m,RGBA * color,U16 id_bitmap) +int swf_ShapeAddFillStyle(SHAPE * s,U8 type,MATRIX * m,RGBA * color,U16 id_bitmap, GRADIENT*gradient) { RGBA def_c; MATRIX def_m; + GRADIENT def_g; // handle defaults @@ -322,36 +268,46 @@ int swf_ShapeAddFillStyle(SHAPE * s,U8 type,MATRIX * m,RGBA * color,U16 id_bitma { m = &def_m; swf_GetMatrix(NULL,m); } + if(!gradient) + { + gradient = &def_g; + swf_GetGradient(NULL, gradient, 1); + } // handle memory if (s->fillstyle.data) - { FILLSTYLE * new = (FILLSTYLE *)realloc(s->fillstyle.data,(s->fillstyle.n+1)*sizeof(FILLSTYLE)); + { FILLSTYLE * new = (FILLSTYLE *)rfx_realloc(s->fillstyle.data,(s->fillstyle.n+1)*sizeof(FILLSTYLE)); if (!new) return -1; s->fillstyle.data = new; } 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; } - // set fillstyle (no gradients yet!) + // set fillstyle s->fillstyle.data[s->fillstyle.n].type = type; s->fillstyle.data[s->fillstyle.n].id_bitmap = id_bitmap; memcpy(&s->fillstyle.data[s->fillstyle.n].m,m,sizeof(MATRIX)); memcpy(&s->fillstyle.data[s->fillstyle.n].color,color,sizeof(RGBA)); + memcpy(&s->fillstyle.data[s->fillstyle.n].gradient,gradient,sizeof(GRADIENT)); return (++s->fillstyle.n); } int swf_ShapeAddSolidFillStyle(SHAPE * s,RGBA * color) -{ return swf_ShapeAddFillStyle(s,FILL_SOLID,NULL,color,0); +{ return swf_ShapeAddFillStyle(s,FILL_SOLID,NULL,color,0,0); } int swf_ShapeAddBitmapFillStyle(SHAPE * s,MATRIX * m,U16 id_bitmap,int clip) -{ return swf_ShapeAddFillStyle(s,clip?FILL_CLIPPED:FILL_TILED,m,NULL,id_bitmap); +{ return swf_ShapeAddFillStyle(s,clip?FILL_CLIPPED:FILL_TILED,m,NULL,id_bitmap,0); +} + +int swf_ShapeAddGradientFillStyle(SHAPE * s,MATRIX * m,GRADIENT* gradient,int radial) +{ return swf_ShapeAddFillStyle(s,radial?FILL_RADIAL:FILL_LINEAR,m,NULL,0,gradient); } int swf_ShapeAddLineStyle(SHAPE * s,U16 width,RGBA * color) @@ -363,12 +319,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)); + { LINESTYLE * new = (LINESTYLE *)rfx_realloc(s->linestyle.data,(s->linestyle.n+1)*sizeof(LINESTYLE)); if (!new) return -1; s->linestyle.data = new; } 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; } @@ -450,72 +406,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\n", b); - fflush(stdout); - *(int*)0 = 0xdead; - b = 17; + if(b >= 18) { + if(b >= 18 + 4) { + /* do not split into more than 16 segments. If the line is *that* long, something's broken */ + fprintf(stderr, "Warning: Line to %.2f,%.2f is too long", (double)x,(double)y); + 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\n", b); - 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\n", b); - 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; +{ + U8 b; + if (!t) return -1; - swf_SetBits(t,2,2); - - 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); + b = 17; + } - 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) @@ -583,7 +540,7 @@ SHAPELINE* swf_ParseShapeData(U8*data, int bits, int fillbits, int linebits) 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; @@ -608,7 +565,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; @@ -628,7 +585,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; @@ -649,8 +606,6 @@ SRECT swf_GetShapeBoundingBox(SHAPE2*shape2) { SRECT r; SHAPELINE*l = shape2->lines; - int SCOORD_MAX = 0x7fffffff; - int SCOORD_MIN = -0x80000000; int lastx=0,lasty=0; int valid = 0; r.xmin = r.ymin = SCOORD_MAX; @@ -695,27 +650,27 @@ void swf_Shape2Free(SHAPE2 * s) SHAPELINE*line = s->lines; while(line) { SHAPELINE*next = line->next; - free(line); + rfx_free(line); line = next; } if(s->linestyles) - free(s->linestyles); + rfx_free(s->linestyles); if(s->fillstyles) - free(s->fillstyles); + rfx_free(s->fillstyles); if(s->bbox) - free(s->bbox); + rfx_free(s->bbox); } SHAPE2* swf_ShapeToShape2(SHAPE*shape) { - SHAPE2*shape2 = (SHAPE2*)malloc(sizeof(SHAPE2)); + SHAPE2*shape2 = (SHAPE2*)rfx_alloc(sizeof(SHAPE2)); shape2->numlinestyles = shape->linestyle.n; - shape2->linestyles = (LINESTYLE*)malloc(sizeof(LINESTYLE)*shape->linestyle.n); + 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); + 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); @@ -730,7 +685,7 @@ void swf_ShapeSetBitmapRect(TAG*tag, U16 gfxid, int width, int height) RGBA rgb; SRECT r; int lines = 0; - int ls,fs; + int ls=0,fs; swf_ShapeNew(&shape); rgb.b = rgb.g = rgb.r = 0xff; if(lines) @@ -760,3 +715,185 @@ void swf_ShapeSetBitmapRect(TAG*tag, U16 gfxid, int width, int height) swf_ShapeFree(shape); } +void swf_Shape2ToShape(SHAPE2*shape2, SHAPE*shape) +{ + TAG*tag = swf_InsertTag(0,0); + SHAPELINE*l,*next; + 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*)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*)rfx_alloc(sizeof(FILLSTYLE)*shape->fillstyle.n); + memcpy(shape->fillstyle.data, shape2->fillstyles, sizeof(FILLSTYLE)*shape->fillstyle.n); + + swf_ShapeCountBits(shape,NULL,NULL); + + l = shape2->lines; + + while(l) { + int ls=0,fs0=0,fs1=0; + + if(l->type != moveTo) { + if(oldls != l->linestyle) {oldls = ls = l->linestyle;if(!ls) ls=0x8000;} + if(oldfs0 != l->fillstyle0) {oldfs0 = fs0 = l->fillstyle0;if(!fs0) fs0=0x8000;} + if(oldfs1 != l->fillstyle1) {oldfs1 = fs1 = l->fillstyle1;if(!fs1) fs1=0x8000;} + + if(ls || fs0 || fs1 || newx!=0x7fffffff || newy!=0x7fffffff) { + swf_ShapeSetAll(tag,shape,newx,newy,ls,fs0,fs1); + newx = 0x7fffffff; + newy = 0x7fffffff; + } + } + + if(l->type == lineTo) { + swf_ShapeSetLine(tag,shape,l->x-lastx,l->y-lasty); + } else if(l->type == splineTo) { + swf_ShapeSetCurve(tag,shape, l->sx-lastx,l->sy-lasty, l->x-l->sx,l->y-l->sy); + } + if(l->type == moveTo) { + newx = l->x; + newy = l->y; + } + + lastx = l->x; + lasty = l->y; + l = l->next; + } + swf_ShapeSetEnd(tag); + shape->data = tag->data; + shape->bitlen = tag->len*8; +} + +void swf_SetShape2(TAG*tag, SHAPE2*shape2) +{ + SHAPE shape; + swf_Shape2ToShape(shape2, &shape); + + swf_SetRect(tag,shape2->bbox); + swf_SetShapeStyles(tag, &shape); + swf_ShapeCountBits(&shape,NULL,NULL); + 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; + + if(shape->numfillstyles) { + shape->fillstyles = rfx_alloc(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; + 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;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; + else if(tag->id == ST_DEFINESHAPE2) + num = 2; + else if(tag->id == ST_DEFINESHAPE3) + num = 3; + else { + fprintf(stderr, "parseDefineShape must be called with a shape tag"); + } + + id = swf_GetU16(tag); //id + memset(shape, 0, sizeof(SHAPE2)); + shape->bbox = rfx_alloc(sizeof(SRECT)); + swf_GetRect(tag, &r); + + memcpy(shape->bbox, &r, sizeof(SRECT)); + parseFillStyleArray(tag, shape); + + 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); + + l = shape->lines; +} +