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 file is distributed under the GPL, see file COPYING for details
14 #define SF_MOVETO 0x01
18 #define SF_NEWSTYLE 0x10
20 #define FILL_SOLID 0x00
21 #define FILL_LINEAR 0x10 // Gradient
22 #define FILL_RADIAL 0x12
23 #define FILL_TILED 0x40 // Bitmap
24 #define FILL_CLIPPED 0x41
26 void swf_ShapeFree(SHAPE * s)
28 { if (s->linestyle.data) free(s->linestyle.data);
29 s->linestyle.data = NULL;
31 if (s->fillstyle.data) free(s->fillstyle.data);
32 s->fillstyle.data = NULL;
34 if (s->data) free(s->data);
40 int swf_ShapeNew(SHAPE * * s)
43 sh = (SHAPE *)malloc(sizeof(SHAPE)); s[0] = sh;
44 if (sh) memset(sh,0x00,sizeof(SHAPE));
48 int swf_GetSimpleShape(TAG * t,SHAPE * * s) // without Linestyle/Fillstyle Record
54 if (FAILED(swf_ShapeNew(s))) return -1;
58 sh->bits.fill = (U16)swf_GetBits(t,4);
59 sh->bits.line = (U16)swf_GetBits(t,4);
60 bitl = 0; end = 0; pos = swf_GetTagPos(t);
63 { int edge = swf_GetBits(t,1); bitl+=1;
66 if (swf_GetBits(t,1)) // Line
67 { U16 nbits = swf_GetBits(t,4)+2;
70 if (swf_GetBits(t,1)) // x/y Line
71 { swf_GetBits(t,nbits);
76 { swf_GetBits(t,nbits+1);
81 { U16 nbits = swf_GetBits(t,4)+2;
93 { U16 flags = swf_GetBits(t,5); bitl+=5;
97 { U16 nbits = swf_GetBits(t,5); bitl+=5;
104 { swf_GetBits(t,sh->bits.fill);
109 { swf_GetBits(t,sh->bits.fill);
114 { swf_GetBits(t,sh->bits.line);
118 if (flags&SF_NEWSTYLE)
119 { fprintf(stderr,"RFXSWF: Can't process extended styles in shape.\n");
125 swf_SetTagPos(t,pos);
128 if (sh->data) free(sh->data);
129 sh->data = (U8*)malloc(len);
133 swf_GetBlock(t,sh->data,len);
140 int swf_SetSimpleShape(TAG * t,SHAPE * s) // without Linestyle/Fillstyle Record
147 { swf_ResetWriteBits(t);
149 swf_SetBits(t,s->bits.fill,4);
150 swf_SetBits(t,s->bits.line,4);
151 swf_SetBlock(t,s->data,l);
153 swf_ResetWriteBits(t);
158 int swf_SetFillStyle(TAG * t,FILLSTYLE * f)
159 { if ((!t)||(!f)) return -1;
160 swf_SetU8(t,f->type);
166 if (swf_GetTagID(t)!=ST_DEFINESHAPE3) swf_SetRGB(t,&f->color);
167 else swf_SetRGBA(t,&f->color);
172 swf_SetU16(t,f->id_bitmap);
173 swf_SetMatrix(t,&f->m);
180 int swf_SetLineStyle(TAG * t,LINESTYLE * l)
181 { if ((!l)||(!t)) return -1;
182 swf_SetU16(t,l->width);
184 if (swf_GetTagID(t)!=ST_DEFINESHAPE3) swf_SetRGB(t,&l->color);
185 else swf_SetRGBA(t,&l->color);
190 int swf_SetShapeStyleCount(TAG * t,U16 n)
202 int swf_SetShapeStyles(TAG * t,SHAPE * s)
207 l += swf_SetShapeStyleCount(t,s->fillstyle.n);
209 for (i=0;i<s->fillstyle.n;i++)
210 l+=swf_SetFillStyle(t,&s->fillstyle.data[i]);
212 l += swf_SetShapeStyleCount(t,s->linestyle.n);
214 for (i=0;i<s->linestyle.n;i++)
215 l+=swf_SetLineStyle(t,&s->linestyle.data[i]);
220 int swf_ShapeCountBits(SHAPE * s,U8 * fbits,U8 * lbits)
222 s->bits.fill = swf_CountUBits(s->fillstyle.n, 0);
223 s->bits.line = swf_CountUBits(s->linestyle.n, 0);
224 if (fbits) fbits[0] = s->bits.fill;
225 if (lbits) lbits[0] = s->bits.line;
229 int swf_SetShapeBits(TAG * t,SHAPE * s)
230 { if ((!t)||(!s)) return -1;
231 swf_ResetWriteBits(t);
232 swf_SetBits(t,s->bits.fill,4);
233 swf_SetBits(t,s->bits.line,4);
237 int swf_SetShapeHeader(TAG * t,SHAPE * s)
239 res = swf_SetShapeStyles(t,s);
240 if (res>=0) res = swf_ShapeCountBits(s,NULL,NULL);
241 if (res>=0) res = swf_SetShapeBits(t,s);
245 int swf_ShapeExport(int handle,SHAPE * s) // without Linestyle/Fillstyle Record
252 if (write(handle,s,sizeof(SHAPE))!=sizeof(SHAPE)) return -1;
254 // Fillstyle, Linestyle ...
257 { int ll = (s->bitlen+7)/8;
260 if (write(handle,s->data,ll)!=ll) return -1;
266 int swf_ShapeImport(int handle,SHAPE * * shape)
269 if (handle<0) return -1;
271 s = (SHAPE *)malloc(sizeof(SHAPE)); shape[0] = s;
274 if (read(handle,s,sizeof(SHAPE))!=sizeof(SHAPE))
281 { int ll = (s->bitlen+7)/8;
282 s->data = (U8*)malloc(ll);
288 if (read(handle,s->data,ll)!=ll)
299 int swf_ShapeAddFillStyle(SHAPE * s,U8 type,MATRIX * m,RGBA * color,U16 id_bitmap)
309 def_c.r = def_c.g = def_c.b = 0;
313 swf_GetMatrix(NULL,m);
318 if (s->fillstyle.data)
319 { FILLSTYLE * new = (FILLSTYLE *)realloc(s->fillstyle.data,(s->fillstyle.n+1)*sizeof(FILLSTYLE));
321 s->fillstyle.data = new;
324 { s->fillstyle.data = (FILLSTYLE *)malloc(sizeof(FILLSTYLE));
326 if (!s->fillstyle.data) return -1;
329 // set fillstyle (no gradients yet!)
331 s->fillstyle.data[s->fillstyle.n].type = type;
332 s->fillstyle.data[s->fillstyle.n].id_bitmap = id_bitmap;
333 memcpy(&s->fillstyle.data[s->fillstyle.n].m,m,sizeof(MATRIX));
334 memcpy(&s->fillstyle.data[s->fillstyle.n].color,color,sizeof(RGBA));
336 return (++s->fillstyle.n);
339 int swf_ShapeAddSolidFillStyle(SHAPE * s,RGBA * color)
340 { return swf_ShapeAddFillStyle(s,FILL_SOLID,NULL,color,0);
343 int swf_ShapeAddBitmapFillStyle(SHAPE * s,MATRIX * m,U16 id_bitmap,int clip)
344 { return swf_ShapeAddFillStyle(s,clip?FILL_CLIPPED:FILL_TILED,m,NULL,id_bitmap);
347 int swf_ShapeAddLineStyle(SHAPE * s,U16 width,RGBA * color)
353 def.r = def.g = def.b = 0;
355 if (s->linestyle.data)
356 { LINESTYLE * new = (LINESTYLE *)realloc(s->linestyle.data,(s->linestyle.n+1)*sizeof(LINESTYLE));
358 s->linestyle.data = new;
361 { s->linestyle.data = (LINESTYLE *)malloc(sizeof(LINESTYLE));
363 if (!s->linestyle.data) return -1;
366 s->linestyle.data[s->linestyle.n].width = width;
367 memcpy(&s->linestyle.data[s->linestyle.n].color,color,sizeof(RGBA));
369 return (++s->linestyle.n);
372 int swf_ShapeSetMove(TAG * t,SHAPE * s,S32 x,S32 y)
376 swf_SetBits(t,SF_MOVETO,5);
378 b = swf_CountBits(x,0);
379 b = swf_CountBits(y,b);
388 int swf_ShapeSetStyle(TAG * t,SHAPE * s,U16 line,U16 fill0,U16 fill1)
389 { if ((!t)||(!s)) return -1;
392 swf_SetBits(t,(line?SF_LINE:0)|(fill0?SF_FILL0:0)|(fill1?SF_FILL1:0),5);
394 if (fill0) swf_SetBits(t,fill0,s->bits.fill);
395 if (fill1) swf_SetBits(t,fill1,s->bits.fill);
396 if (line) swf_SetBits(t,line ,s->bits.line);
401 /* TODO: sometimes we want to set fillstyle 0, as that's the empty fill
402 used for line drawings. At the moment, we can't, as 0 fill be considered
403 nonexistent and therefore not set.
404 these defines are a workaround (they also reduce the maximal number of
405 fill styles to 32768)
407 #define FILL_RESET 0x8000
408 #define LINE_RESET 0x8000
409 #define UNDEFINED_COORD 0x7fffffff
411 int swf_ShapeSetAll(TAG * t,SHAPE * s,S32 x,S32 y,U16 line,U16 fill0,U16 fill1)
414 if ((!t)||(!s)) return -1;
416 if(x!=UNDEFINED_COORD || y!=UNDEFINED_COORD)
420 swf_SetBits(t,(hasmove?SF_MOVETO:0)|(line?SF_LINE:0)|(fill0?SF_FILL0:0)|(fill1?SF_FILL1:0),5);
423 b = swf_CountBits(x,0);
424 b = swf_CountBits(y,b);
430 if (fill0) swf_SetBits(t,fill0,s->bits.fill);
431 if (fill1) swf_SetBits(t,fill1,s->bits.fill);
432 if (line) swf_SetBits(t,line ,s->bits.line);
437 int swf_ShapeSetEnd(TAG * t)
440 swf_ResetWriteBits(t);
444 int swf_ShapeSetLine(TAG * t,SHAPE * s,S32 x,S32 y)
447 swf_SetBits(t,3,2); // Straight Edge
449 if ((!s)||((x!=0)&&(y!=0)))
450 { b = swf_CountBits(x,2);
451 b = swf_CountBits(y,b);
454 fprintf(stderr, "Bit overflow in swf_ShapeSetLine(1)- %d\n", b);
459 swf_SetBits(t, b-2, 4);
467 { b = swf_CountBits(y,2);
471 fprintf(stderr, "Bit overflow in swf_ShapeSetLine(2)- %d\n", b);
474 swf_SetBits(t, b-2, 4);
479 { b = swf_CountBits(x,2);
483 fprintf(stderr, "Bit overflow in swf_ShapeSetLine(3)- %d\n", b);
486 swf_SetBits(t, b-2, 4);
493 int swf_ShapeSetCurve(TAG * t,SHAPE * s,S32 x,S32 y,S32 ax,S32 ay)
499 b = swf_CountBits(ax,2);
500 b = swf_CountBits(ay,b);
501 b = swf_CountBits(x,b);
502 b = swf_CountBits(y,b);
504 swf_SetBits(t,b-2,4);
513 int swf_ShapeSetCircle(TAG * t,SHAPE * s,S32 x,S32 y,S32 rx,S32 ry)
514 { double C1 = 0.2930;
516 double begin = 0.7070;
520 swf_ShapeSetMove(t,s,x+begin*rx,y+begin*ry);
521 swf_ShapeSetCurve(t,s, -C1*rx, C1*ry, -C2*rx, 0);
522 swf_ShapeSetCurve(t,s, -C2*rx, 0, -C1*rx, -C1*ry);
523 swf_ShapeSetCurve(t,s, -C1*rx, -C1*ry, 0, -C2*ry);
524 swf_ShapeSetCurve(t,s, 0, -C2*ry, C1*rx, -C1*ry);
525 swf_ShapeSetCurve(t,s, C1*rx, -C1*ry, C2*rx, 0);
526 swf_ShapeSetCurve(t,s, C2*rx, 0, C1*rx, C1*ry);
527 swf_ShapeSetCurve(t,s, C1*rx, C1*ry, 0, C2*ry);
528 swf_ShapeSetCurve(t,s, 0, C2*ry, -C1*rx, C1*ry);
533 /* todo: merge this with swf_GetSimpleShape */
534 SHAPELINE* swf_ParseShapeData(U8*data, int bits, int fillbits, int linebits)
537 SHAPELINE*lines = &_lines;
546 memset(tag, 0, sizeof(TAG));
548 tag->len = tag->memsize = (bits+7)/8;
554 flags = swf_GetBits(tag, 1);
555 if(!flags) { //style change
556 flags = swf_GetBits(tag, 5);
560 int n = swf_GetBits(tag, 5);
561 x = swf_GetSBits(tag, n); //x
562 y = swf_GetSBits(tag, n); //y
565 fill0 = swf_GetBits(tag, fillbits);
567 fill1 = swf_GetBits(tag, fillbits);
569 line = swf_GetBits(tag, linebits);
571 fprintf(stderr, "Additional file styles style change not yet supported\n");
573 //enumerateUsedIDs_styles(tag, callback, callback_data, num);
574 fillbits = swf_GetBits(tag, 4);
575 linebits = swf_GetBits(tag, 4);
578 lines->next = (SHAPELINE*)malloc(sizeof(SHAPELINE));
580 lines->type = moveTo;
583 lines->sx = lines->sy = 0;
584 lines->fillstyle0 = fill0;
585 lines->fillstyle1 = fill1;
586 lines->linestyle = line;
590 flags = swf_GetBits(tag, 1);
591 if(flags) { //straight edge
592 int n = swf_GetBits(tag, 4) + 2;
593 if(swf_GetBits(tag, 1)) { //line flag
594 x += swf_GetSBits(tag, n); //delta x
595 y += swf_GetSBits(tag, n); //delta y
597 int v=swf_GetBits(tag, 1);
599 d = swf_GetSBits(tag, n); //vert/horz
603 lines->next = (SHAPELINE*)malloc(sizeof(SHAPELINE));
605 lines->type = lineTo;
608 lines->sx = lines->sy = 0;
609 lines->fillstyle0 = fill0;
610 lines->fillstyle1 = fill1;
611 lines->linestyle = line;
613 } else { //curved edge
614 int n = swf_GetBits(tag, 4) + 2;
616 x += swf_GetSBits(tag, n);
617 y += swf_GetSBits(tag, n);
620 x += swf_GetSBits(tag, n);
621 y += swf_GetSBits(tag, n);
623 lines->next = (SHAPELINE*)malloc(sizeof(SHAPELINE));
625 lines->type = splineTo;
630 lines->fillstyle0 = fill0;
631 lines->fillstyle1 = fill1;
632 lines->linestyle = line;
640 SRECT swf_GetShapeBoundingBox(SHAPE2*shape2)
643 SHAPELINE*l = shape2->lines;
644 int SCOORD_MAX = 0x7fffffff;
645 int SCOORD_MIN = -0x80000000;
648 r.xmin = r.ymin = SCOORD_MAX;
649 r.xmax = r.ymax = SCOORD_MIN;
654 t1 = shape2->linestyles[l->linestyle - 1].width*3/2;
659 if(l->type == lineTo || l->type == splineTo)
662 if(lastx - t1 < r.xmin) r.xmin = lastx - t1;
663 if(lasty - t1 < r.ymin) r.ymin = lasty - t1;
664 if(lastx + t1 > r.xmax) r.xmax = lastx + t1;
665 if(lasty + t1 > r.ymax) r.ymax = lasty + t1;
666 if(l->x - t1 < r.xmin) r.xmin = l->x - t1;
667 if(l->y - t1 < r.ymin) r.ymin = l->y - t1;
668 if(l->x + t1 > r.xmax) r.xmax = l->x + t1;
669 if(l->y + t1 > r.ymax) r.ymax = l->y + t1;
670 if(l->type == splineTo) {
671 if(l->sx - t1 < r.xmin) r.xmin = l->sx - t1;
672 if(l->sy - t1 < r.ymin) r.ymin = l->sy - t1;
673 if(l->sx + t1 > r.xmax) r.xmax = l->sx + t1;
674 if(l->sy + t1 > r.ymax) r.ymax = l->sy + t1;
681 if(!valid) memset(&r, 0, sizeof(SRECT));
685 void swf_Shape2Free(SHAPE2 * s)
687 SHAPELINE*line = s->lines;
689 SHAPELINE*next = line->next;
701 SHAPE2* swf_ShapeToShape2(SHAPE*shape) {
703 SHAPE2*shape2 = (SHAPE2*)malloc(sizeof(SHAPE2));
705 shape2->numlinestyles = shape->linestyle.n;
706 shape2->linestyles = (LINESTYLE*)malloc(sizeof(LINESTYLE)*shape->linestyle.n);
707 memcpy(shape2->linestyles, shape->linestyle.data, sizeof(LINESTYLE)*shape->linestyle.n);
709 shape2->numfillstyles = shape->fillstyle.n;
710 shape2->fillstyles = (FILLSTYLE*)malloc(sizeof(FILLSTYLE)*shape->fillstyle.n);
711 memcpy(shape2->fillstyles, shape->fillstyle.data, sizeof(FILLSTYLE)*shape->fillstyle.n);
713 shape2->lines = swf_ParseShapeData(shape->data, shape->bitlen, shape->bits.fill, shape->bits.line);
718 void swf_ShapeSetBitmapRect(TAG*tag, U16 gfxid, int width, int height)
726 swf_ShapeNew(&shape);
727 rgb.b = rgb.g = rgb.r = 0xff;
729 ls = swf_ShapeAddLineStyle(shape,20,&rgb);
730 swf_GetMatrix(NULL,&m);
734 fs = swf_ShapeAddBitmapFillStyle(shape,&m,gfxid,0);
741 swf_SetShapeStyles(tag,shape);
742 swf_ShapeCountBits(shape,NULL,NULL);
743 swf_SetShapeBits(tag,shape);
745 swf_ShapeSetAll(tag,shape,0,0,lines?ls:0,fs,0);
747 swf_ShapeSetLine(tag,shape,width*20,0);
748 swf_ShapeSetLine(tag,shape,0,height*20);
749 swf_ShapeSetLine(tag,shape,-width*20,0);
750 swf_ShapeSetLine(tag,shape,0,-height*20);
751 swf_ShapeSetEnd(tag);
752 swf_ShapeFree(shape);