5 Extension module for the rfxswf library.
6 Part of the swftools package.
8 Copyright (c) 2001 Rainer Böhme <rfxswf@reflex-studio.de>
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
24 #define SF_MOVETO 0x01
28 #define SF_NEWSTYLE 0x10
30 #define FILL_SOLID 0x00
31 #define FILL_LINEAR 0x10 // Gradient
32 #define FILL_RADIAL 0x12
33 #define FILL_TILED 0x40 // Bitmap
34 #define FILL_CLIPPED 0x41
36 void swf_ShapeFree(SHAPE * s)
38 { if (s->linestyle.data) free(s->linestyle.data);
39 s->linestyle.data = NULL;
41 if (s->fillstyle.data) free(s->fillstyle.data);
42 s->fillstyle.data = NULL;
44 if (s->data) free(s->data);
50 int swf_ShapeNew(SHAPE * * s)
53 sh = (SHAPE *)malloc(sizeof(SHAPE)); s[0] = sh;
54 if (sh) memset(sh,0x00,sizeof(SHAPE));
58 int swf_GetSimpleShape(TAG * t,SHAPE * * s) // without Linestyle/Fillstyle Record
64 if (FAILED(swf_ShapeNew(s))) return -1;
68 sh->bits.fill = (U16)swf_GetBits(t,4);
69 sh->bits.line = (U16)swf_GetBits(t,4);
70 bitl = 0; end = 0; pos = swf_GetTagPos(t);
73 { int edge = swf_GetBits(t,1); bitl+=1;
76 if (swf_GetBits(t,1)) // Line
77 { U16 nbits = swf_GetBits(t,4)+2;
80 if (swf_GetBits(t,1)) // x/y Line
81 { swf_GetBits(t,nbits);
86 { swf_GetBits(t,nbits+1);
91 { U16 nbits = swf_GetBits(t,4)+2;
103 { U16 flags = swf_GetBits(t,5); bitl+=5;
107 { U16 nbits = swf_GetBits(t,5); bitl+=5;
108 swf_GetBits(t,nbits);
109 swf_GetBits(t,nbits);
114 { swf_GetBits(t,sh->bits.fill);
119 { swf_GetBits(t,sh->bits.fill);
124 { swf_GetBits(t,sh->bits.line);
128 if (flags&SF_NEWSTYLE)
129 { fprintf(stderr,"RFXSWF: Can't process extended styles in shape.\n");
135 swf_SetTagPos(t,pos);
138 if (sh->data) free(sh->data);
139 sh->data = (U8*)malloc(len);
143 swf_GetBlock(t,sh->data,len);
150 int swf_SetSimpleShape(TAG * t,SHAPE * s) // without Linestyle/Fillstyle Record
157 { swf_ResetWriteBits(t);
159 swf_SetBits(t,s->bits.fill,4);
160 swf_SetBits(t,s->bits.line,4);
161 swf_SetBlock(t,s->data,l);
163 swf_ResetWriteBits(t);
168 int swf_SetFillStyle(TAG * t,FILLSTYLE * f)
169 { if ((!t)||(!f)) return -1;
170 swf_SetU8(t,f->type);
176 if (swf_GetTagID(t)!=ST_DEFINESHAPE3) swf_SetRGB(t,&f->color);
177 else swf_SetRGBA(t,&f->color);
182 swf_SetU16(t,f->id_bitmap);
183 swf_SetMatrix(t,&f->m);
190 int swf_SetLineStyle(TAG * t,LINESTYLE * l)
191 { if ((!l)||(!t)) return -1;
192 swf_SetU16(t,l->width);
194 if (swf_GetTagID(t)!=ST_DEFINESHAPE3) swf_SetRGB(t,&l->color);
195 else swf_SetRGBA(t,&l->color);
200 int swf_SetShapeStyleCount(TAG * t,U16 n)
212 int swf_SetShapeStyles(TAG * t,SHAPE * s)
217 l += swf_SetShapeStyleCount(t,s->fillstyle.n);
219 for (i=0;i<s->fillstyle.n;i++)
220 l+=swf_SetFillStyle(t,&s->fillstyle.data[i]);
222 l += swf_SetShapeStyleCount(t,s->linestyle.n);
224 for (i=0;i<s->linestyle.n;i++)
225 l+=swf_SetLineStyle(t,&s->linestyle.data[i]);
230 int swf_ShapeCountBits(SHAPE * s,U8 * fbits,U8 * lbits)
232 s->bits.fill = swf_CountUBits(s->fillstyle.n, 0);
233 s->bits.line = swf_CountUBits(s->linestyle.n, 0);
234 if (fbits) fbits[0] = s->bits.fill;
235 if (lbits) lbits[0] = s->bits.line;
239 int swf_SetShapeBits(TAG * t,SHAPE * s)
240 { if ((!t)||(!s)) return -1;
241 swf_ResetWriteBits(t);
242 swf_SetBits(t,s->bits.fill,4);
243 swf_SetBits(t,s->bits.line,4);
247 int swf_SetShapeHeader(TAG * t,SHAPE * s)
249 res = swf_SetShapeStyles(t,s);
250 if (res>=0) res = swf_ShapeCountBits(s,NULL,NULL);
251 if (res>=0) res = swf_SetShapeBits(t,s);
255 int swf_ShapeExport(int handle,SHAPE * s) // without Linestyle/Fillstyle Record
262 if (write(handle,s,sizeof(SHAPE))!=sizeof(SHAPE)) return -1;
264 // Fillstyle, Linestyle ...
267 { int ll = (s->bitlen+7)/8;
270 if (write(handle,s->data,ll)!=ll) return -1;
276 int swf_ShapeImport(int handle,SHAPE * * shape)
279 if (handle<0) return -1;
281 s = (SHAPE *)malloc(sizeof(SHAPE)); shape[0] = s;
284 if (read(handle,s,sizeof(SHAPE))!=sizeof(SHAPE))
291 { int ll = (s->bitlen+7)/8;
292 s->data = (U8*)malloc(ll);
298 if (read(handle,s->data,ll)!=ll)
309 int swf_ShapeAddFillStyle(SHAPE * s,U8 type,MATRIX * m,RGBA * color,U16 id_bitmap)
319 def_c.r = def_c.g = def_c.b = 0;
323 swf_GetMatrix(NULL,m);
328 if (s->fillstyle.data)
329 { FILLSTYLE * new = (FILLSTYLE *)realloc(s->fillstyle.data,(s->fillstyle.n+1)*sizeof(FILLSTYLE));
331 s->fillstyle.data = new;
334 { s->fillstyle.data = (FILLSTYLE *)malloc(sizeof(FILLSTYLE));
336 if (!s->fillstyle.data) return -1;
339 // set fillstyle (no gradients yet!)
341 s->fillstyle.data[s->fillstyle.n].type = type;
342 s->fillstyle.data[s->fillstyle.n].id_bitmap = id_bitmap;
343 memcpy(&s->fillstyle.data[s->fillstyle.n].m,m,sizeof(MATRIX));
344 memcpy(&s->fillstyle.data[s->fillstyle.n].color,color,sizeof(RGBA));
346 return (++s->fillstyle.n);
349 int swf_ShapeAddSolidFillStyle(SHAPE * s,RGBA * color)
350 { return swf_ShapeAddFillStyle(s,FILL_SOLID,NULL,color,0);
353 int swf_ShapeAddBitmapFillStyle(SHAPE * s,MATRIX * m,U16 id_bitmap,int clip)
354 { return swf_ShapeAddFillStyle(s,clip?FILL_CLIPPED:FILL_TILED,m,NULL,id_bitmap);
357 int swf_ShapeAddLineStyle(SHAPE * s,U16 width,RGBA * color)
363 def.r = def.g = def.b = 0;
365 if (s->linestyle.data)
366 { LINESTYLE * new = (LINESTYLE *)realloc(s->linestyle.data,(s->linestyle.n+1)*sizeof(LINESTYLE));
368 s->linestyle.data = new;
371 { s->linestyle.data = (LINESTYLE *)malloc(sizeof(LINESTYLE));
373 if (!s->linestyle.data) return -1;
376 s->linestyle.data[s->linestyle.n].width = width;
377 memcpy(&s->linestyle.data[s->linestyle.n].color,color,sizeof(RGBA));
379 return (++s->linestyle.n);
382 int swf_ShapeSetMove(TAG * t,SHAPE * s,S32 x,S32 y)
386 swf_SetBits(t,SF_MOVETO,5);
388 b = swf_CountBits(x,0);
389 b = swf_CountBits(y,b);
398 int swf_ShapeSetStyle(TAG * t,SHAPE * s,int line,int fill0,int fill1)
399 { if ((!t)||(!s)) return -1;
402 swf_SetBits(t,(line?SF_LINE:0)|(fill0?SF_FILL0:0)|(fill1?SF_FILL1:0),5);
404 if (fill0) swf_SetBits(t,fill0,s->bits.fill);
405 if (fill1) swf_SetBits(t,fill1,s->bits.fill);
406 if (line) swf_SetBits(t,line ,s->bits.line);
411 /* TODO: sometimes we want to set fillstyle 0, as that's the empty fill
412 used for line drawings. At the moment, we can't, as 0 fill be considered
413 nonexistent and therefore not set.
414 these defines are a workaround (they also reduce the maximal number of
415 fill styles to 32768)
417 #define UNDEFINED_COORD 0x7fffffff
419 int swf_ShapeSetAll(TAG * t,SHAPE * s,S32 x,S32 y,int line,int fill0,int fill1)
422 if ((!t)||(!s)) return -1;
424 if(x!=UNDEFINED_COORD || y!=UNDEFINED_COORD)
428 swf_SetBits(t,(hasmove?SF_MOVETO:0)|(line?SF_LINE:0)|(fill0?SF_FILL0:0)|(fill1?SF_FILL1:0),5);
431 b = swf_CountBits(x,0);
432 b = swf_CountBits(y,b);
438 if (fill0) swf_SetBits(t,fill0,s->bits.fill);
439 if (fill1) swf_SetBits(t,fill1,s->bits.fill);
440 if (line) swf_SetBits(t,line ,s->bits.line);
445 int swf_ShapeSetEnd(TAG * t)
448 swf_ResetWriteBits(t);
452 int swf_ShapeSetLine(TAG * t,SHAPE * s,S32 x,S32 y)
455 swf_SetBits(t,3,2); // Straight Edge
457 if ((!s)||((x!=0)&&(y!=0)))
458 { b = swf_CountBits(x,2);
459 b = swf_CountBits(y,b);
462 fprintf(stderr, "Bit overflow in swf_ShapeSetLine(1)- %d\n", b);
467 swf_SetBits(t, b-2, 4);
475 { b = swf_CountBits(y,2);
479 fprintf(stderr, "Bit overflow in swf_ShapeSetLine(2)- %d\n", b);
482 swf_SetBits(t, b-2, 4);
487 { b = swf_CountBits(x,2);
491 fprintf(stderr, "Bit overflow in swf_ShapeSetLine(3)- %d\n", b);
494 swf_SetBits(t, b-2, 4);
501 int swf_ShapeSetCurve(TAG * t,SHAPE * s,S32 x,S32 y,S32 ax,S32 ay)
507 b = swf_CountBits(ax,2);
508 b = swf_CountBits(ay,b);
509 b = swf_CountBits(x,b);
510 b = swf_CountBits(y,b);
512 swf_SetBits(t,b-2,4);
521 int swf_ShapeSetCircle(TAG * t,SHAPE * s,S32 x,S32 y,S32 rx,S32 ry)
522 { double C1 = 0.2930;
524 double begin = 0.7070;
528 swf_ShapeSetMove(t,s,x+begin*rx,y+begin*ry);
529 swf_ShapeSetCurve(t,s, -C1*rx, C1*ry, -C2*rx, 0);
530 swf_ShapeSetCurve(t,s, -C2*rx, 0, -C1*rx, -C1*ry);
531 swf_ShapeSetCurve(t,s, -C1*rx, -C1*ry, 0, -C2*ry);
532 swf_ShapeSetCurve(t,s, 0, -C2*ry, C1*rx, -C1*ry);
533 swf_ShapeSetCurve(t,s, C1*rx, -C1*ry, C2*rx, 0);
534 swf_ShapeSetCurve(t,s, C2*rx, 0, C1*rx, C1*ry);
535 swf_ShapeSetCurve(t,s, C1*rx, C1*ry, 0, C2*ry);
536 swf_ShapeSetCurve(t,s, 0, C2*ry, -C1*rx, C1*ry);
541 /* todo: merge this with swf_GetSimpleShape */
542 SHAPELINE* swf_ParseShapeData(U8*data, int bits, int fillbits, int linebits)
545 SHAPELINE*lines = &_lines;
554 memset(tag, 0, sizeof(TAG));
556 tag->len = tag->memsize = (bits+7)/8;
562 flags = swf_GetBits(tag, 1);
563 if(!flags) { //style change
564 flags = swf_GetBits(tag, 5);
568 int n = swf_GetBits(tag, 5);
569 x = swf_GetSBits(tag, n); //x
570 y = swf_GetSBits(tag, n); //y
573 fill0 = swf_GetBits(tag, fillbits);
575 fill1 = swf_GetBits(tag, fillbits);
577 line = swf_GetBits(tag, linebits);
579 fprintf(stderr, "Additional file styles style change not yet supported\n");
581 //enumerateUsedIDs_styles(tag, callback, callback_data, num);
582 fillbits = swf_GetBits(tag, 4);
583 linebits = swf_GetBits(tag, 4);
586 lines->next = (SHAPELINE*)malloc(sizeof(SHAPELINE));
588 lines->type = moveTo;
591 lines->sx = lines->sy = 0;
592 lines->fillstyle0 = fill0;
593 lines->fillstyle1 = fill1;
594 lines->linestyle = line;
598 flags = swf_GetBits(tag, 1);
599 if(flags) { //straight edge
600 int n = swf_GetBits(tag, 4) + 2;
601 if(swf_GetBits(tag, 1)) { //line flag
602 x += swf_GetSBits(tag, n); //delta x
603 y += swf_GetSBits(tag, n); //delta y
605 int v=swf_GetBits(tag, 1);
607 d = swf_GetSBits(tag, n); //vert/horz
611 lines->next = (SHAPELINE*)malloc(sizeof(SHAPELINE));
613 lines->type = lineTo;
616 lines->sx = lines->sy = 0;
617 lines->fillstyle0 = fill0;
618 lines->fillstyle1 = fill1;
619 lines->linestyle = line;
621 } else { //curved edge
622 int n = swf_GetBits(tag, 4) + 2;
624 x += swf_GetSBits(tag, n);
625 y += swf_GetSBits(tag, n);
628 x += swf_GetSBits(tag, n);
629 y += swf_GetSBits(tag, n);
631 lines->next = (SHAPELINE*)malloc(sizeof(SHAPELINE));
633 lines->type = splineTo;
638 lines->fillstyle0 = fill0;
639 lines->fillstyle1 = fill1;
640 lines->linestyle = line;
648 SRECT swf_GetShapeBoundingBox(SHAPE2*shape2)
651 SHAPELINE*l = shape2->lines;
652 int SCOORD_MAX = 0x7fffffff;
653 int SCOORD_MIN = -0x80000000;
656 r.xmin = r.ymin = SCOORD_MAX;
657 r.xmax = r.ymax = SCOORD_MIN;
662 t1 = shape2->linestyles[l->linestyle - 1].width*3/2;
667 if(l->type == lineTo || l->type == splineTo)
670 if(lastx - t1 < r.xmin) r.xmin = lastx - t1;
671 if(lasty - t1 < r.ymin) r.ymin = lasty - t1;
672 if(lastx + t1 > r.xmax) r.xmax = lastx + t1;
673 if(lasty + t1 > r.ymax) r.ymax = lasty + t1;
674 if(l->x - t1 < r.xmin) r.xmin = l->x - t1;
675 if(l->y - t1 < r.ymin) r.ymin = l->y - t1;
676 if(l->x + t1 > r.xmax) r.xmax = l->x + t1;
677 if(l->y + t1 > r.ymax) r.ymax = l->y + t1;
678 if(l->type == splineTo) {
679 if(l->sx - t1 < r.xmin) r.xmin = l->sx - t1;
680 if(l->sy - t1 < r.ymin) r.ymin = l->sy - t1;
681 if(l->sx + t1 > r.xmax) r.xmax = l->sx + t1;
682 if(l->sy + t1 > r.ymax) r.ymax = l->sy + t1;
689 if(!valid) memset(&r, 0, sizeof(SRECT));
693 void swf_Shape2Free(SHAPE2 * s)
695 SHAPELINE*line = s->lines;
697 SHAPELINE*next = line->next;
709 SHAPE2* swf_ShapeToShape2(SHAPE*shape) {
711 SHAPE2*shape2 = (SHAPE2*)malloc(sizeof(SHAPE2));
713 shape2->numlinestyles = shape->linestyle.n;
714 shape2->linestyles = (LINESTYLE*)malloc(sizeof(LINESTYLE)*shape->linestyle.n);
715 memcpy(shape2->linestyles, shape->linestyle.data, sizeof(LINESTYLE)*shape->linestyle.n);
717 shape2->numfillstyles = shape->fillstyle.n;
718 shape2->fillstyles = (FILLSTYLE*)malloc(sizeof(FILLSTYLE)*shape->fillstyle.n);
719 memcpy(shape2->fillstyles, shape->fillstyle.data, sizeof(FILLSTYLE)*shape->fillstyle.n);
721 shape2->lines = swf_ParseShapeData(shape->data, shape->bitlen, shape->bits.fill, shape->bits.line);
726 void swf_ShapeSetBitmapRect(TAG*tag, U16 gfxid, int width, int height)
734 swf_ShapeNew(&shape);
735 rgb.b = rgb.g = rgb.r = 0xff;
737 ls = swf_ShapeAddLineStyle(shape,20,&rgb);
738 swf_GetMatrix(NULL,&m);
742 fs = swf_ShapeAddBitmapFillStyle(shape,&m,gfxid,0);
749 swf_SetShapeStyles(tag,shape);
750 swf_ShapeCountBits(shape,NULL,NULL);
751 swf_SetShapeBits(tag,shape);
753 swf_ShapeSetAll(tag,shape,0,0,lines?ls:0,fs,0);
755 swf_ShapeSetLine(tag,shape,width*20,0);
756 swf_ShapeSetLine(tag,shape,0,height*20);
757 swf_ShapeSetLine(tag,shape,-width*20,0);
758 swf_ShapeSetLine(tag,shape,0,-height*20);
759 swf_ShapeSetEnd(tag);
760 swf_ShapeFree(shape);