comment added.
[swftools.git] / lib / modules / swfshape.c
1 /* swfshape.c
2
3    shape functions
4       
5    Extension module for the rfxswf library.
6    Part of the swftools package.
7
8    Copyright (c) 2001 Rainer Böhme <rfxswf@reflex-studio.de>
9  
10    This file is distributed under the GPL, see file COPYING for details 
11
12 */
13
14 #define SF_MOVETO       0x01
15 #define SF_FILL0        0x02
16 #define SF_FILL1        0x04
17 #define SF_LINE         0x08
18 #define SF_NEWSTYLE     0x10
19
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
25
26 void swf_ShapeFree(SHAPE * s)
27 { if (s)
28   { if (s->linestyle.data) free(s->linestyle.data);
29     s->linestyle.data = NULL;
30     s->linestyle.n    = 0;
31     if (s->fillstyle.data) free(s->fillstyle.data);
32     s->fillstyle.data = NULL;
33     s->fillstyle.n    = 0;
34     if (s->data) free(s->data);
35     s->data = NULL;
36   }
37   free(s);
38 }
39
40 int swf_ShapeNew(SHAPE * * s)
41 { SHAPE * sh;
42   if (!s) return -1;
43   sh = (SHAPE *)malloc(sizeof(SHAPE)); s[0] = sh;
44   if (sh) memset(sh,0x00,sizeof(SHAPE));
45   return sh?0:-1;
46 }
47
48 int swf_GetSimpleShape(TAG * t,SHAPE * * s) // without Linestyle/Fillstyle Record
49 { SHAPE * sh;
50   int bitl, len;
51   int end;
52   U32 pos;
53   
54   if (FAILED(swf_ShapeNew(s))) return -1;
55   sh = s[0];
56
57   swf_ResetReadBits(t); 
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);
61
62   while (!end)
63   { int edge = swf_GetBits(t,1); bitl+=1;
64     if (edge)
65     { bitl+=1;
66       if (swf_GetBits(t,1))                 // Line
67       { U16 nbits = swf_GetBits(t,4)+2;
68         bitl+=5;
69
70         if (swf_GetBits(t,1))               // x/y Line
71         { swf_GetBits(t,nbits);
72           swf_GetBits(t,nbits);
73           bitl+=nbits*2;
74         }
75         else                            // hline/vline
76         { swf_GetBits(t,nbits+1);
77           bitl+=nbits+1;
78         }
79       }
80       else                              // Curve
81       { U16 nbits = swf_GetBits(t,4)+2;
82         bitl+=4;
83
84         swf_GetBits(t,nbits);
85         swf_GetBits(t,nbits);
86         swf_GetBits(t,nbits);
87         swf_GetBits(t,nbits);
88
89         bitl+=4*nbits;
90       }
91     }
92     else
93     { U16 flags = swf_GetBits(t,5); bitl+=5;
94       if (flags)
95       {
96         if (flags&SF_MOVETO)
97         { U16 nbits = swf_GetBits(t,5); bitl+=5;
98           swf_GetBits(t,nbits);
99           swf_GetBits(t,nbits);
100           bitl+=2*nbits;
101         }
102         
103         if (flags&SF_FILL0)
104         { swf_GetBits(t,sh->bits.fill);
105           bitl+=sh->bits.fill;
106         }
107         
108         if (flags&SF_FILL1)
109         { swf_GetBits(t,sh->bits.fill);
110           bitl+=sh->bits.fill;
111         }
112
113         if (flags&SF_LINE)
114         { swf_GetBits(t,sh->bits.line);
115           bitl+=sh->bits.line;
116         }
117
118         if (flags&SF_NEWSTYLE)
119         { fprintf(stderr,"RFXSWF: Can't process extended styles in shape.\n");
120         }
121       }
122       else end = 1;
123     }
124   }
125   swf_SetTagPos(t,pos);
126   len = (bitl+7)/8;
127   
128   if (sh->data) free(sh->data);
129   sh->data = (U8*)malloc(len);
130   
131   if (sh->data)
132   { sh->bitlen = bitl;
133     swf_GetBlock(t,sh->data,len);
134   }
135   else return -1;
136   
137   return len;
138 }
139
140 int swf_SetSimpleShape(TAG * t,SHAPE * s) // without Linestyle/Fillstyle Record
141 { int l;
142
143   if (!s) return -1;
144   l = (s->bitlen+7)/8;
145
146   if (t)
147   { swf_ResetWriteBits(t);
148
149     swf_SetBits(t,s->bits.fill,4);
150     swf_SetBits(t,s->bits.line,4);
151     swf_SetBlock(t,s->data,l);
152
153     swf_ResetWriteBits(t);
154   }
155   return l+1;
156 }
157
158 int swf_SetFillStyle(TAG * t,FILLSTYLE * f)
159 { if ((!t)||(!f)) return -1;
160   swf_SetU8(t,f->type);
161   
162   // no gradients yet!
163   
164   switch (f->type)
165   { case FILL_SOLID:
166       if (swf_GetTagID(t)!=ST_DEFINESHAPE3) swf_SetRGB(t,&f->color);
167       else swf_SetRGBA(t,&f->color);
168       break;
169
170     case FILL_TILED:
171     case FILL_CLIPPED:
172       swf_SetU16(t,f->id_bitmap);
173       swf_SetMatrix(t,&f->m);
174       break;
175   }
176   
177   return 0;
178 }
179
180 int swf_SetLineStyle(TAG * t,LINESTYLE * l)
181 { if ((!l)||(!t)) return -1;
182   swf_SetU16(t,l->width);
183
184   if (swf_GetTagID(t)!=ST_DEFINESHAPE3) swf_SetRGB(t,&l->color);
185   else swf_SetRGBA(t,&l->color);
186   
187   return 0;
188 }
189
190 int swf_SetShapeStyleCount(TAG * t,U16 n)
191 { if (n>254)
192   { swf_SetU8(t,0xff);
193     swf_SetU16(t,n);
194     return 3;
195   }
196   else
197   { swf_SetU8(t,n);
198     return 1;
199   }
200 }
201
202 int swf_SetShapeStyles(TAG * t,SHAPE * s)
203 { int i,l;
204   if (!s) return -1;
205
206   l = 0;
207   l += swf_SetShapeStyleCount(t,s->fillstyle.n);
208
209   for (i=0;i<s->fillstyle.n;i++)
210     l+=swf_SetFillStyle(t,&s->fillstyle.data[i]);
211
212   l += swf_SetShapeStyleCount(t,s->linestyle.n);
213
214   for (i=0;i<s->linestyle.n;i++)
215     l+=swf_SetLineStyle(t,&s->linestyle.data[i]);
216
217   return l;
218 }
219
220 int swf_ShapeCountBits(SHAPE * s,U8 * fbits,U8 * lbits)
221 { if (!s) return -1;
222     
223   s->bits.fill = swf_CountBits(s->fillstyle.n,0);
224   s->bits.line = swf_CountBits(s->linestyle.n,0);
225
226   if (fbits) fbits[0] = s->bits.fill;
227   if (lbits) lbits[0] = s->bits.line;
228   
229   return 0;    
230 }
231
232 int swf_SetShapeBits(TAG * t,SHAPE * s)
233 { if ((!t)||(!s)) return -1;
234   swf_ResetWriteBits(t);
235   swf_SetBits(t,s->bits.fill,4);
236   swf_SetBits(t,s->bits.line,4);
237   return 0;
238 }
239
240 int swf_SetShapeHeader(TAG * t,SHAPE * s)
241 { int res;
242   res = swf_SetShapeStyles(t,s);
243   if (res>=0) res = swf_ShapeCountBits(s,NULL,NULL);
244   if (res>=0) res = swf_SetShapeBits(t,s);
245   return res;
246 }
247
248 int swf_ShapeExport(int handle,SHAPE * s)  // without Linestyle/Fillstyle Record
249 { int l;
250   if (!s) return 0;
251
252   l = sizeof(SHAPE);
253
254   if (handle>=0)
255     if (write(handle,s,sizeof(SHAPE))!=sizeof(SHAPE)) return -1;
256
257   // Fillstyle, Linestyle ...
258
259   if (s->data)
260   { int ll = (s->bitlen+7)/8;
261     l+=ll;
262     if (handle>=0)
263       if (write(handle,s->data,ll)!=ll) return -1;
264   }
265
266   return l;
267 }
268
269 int swf_ShapeImport(int handle,SHAPE * * shape)
270 { SHAPE * s;
271
272   if (handle<0) return -1;
273
274   s = (SHAPE *)malloc(sizeof(SHAPE)); shape[0] = s;
275   if (!s) return -1;
276
277   if (read(handle,s,sizeof(SHAPE))!=sizeof(SHAPE))
278   { shape[0] = NULL;
279     free(s);
280     return -1;
281   }
282
283   if (s->data)
284   { int ll = (s->bitlen+7)/8;
285     s->data = (U8*)malloc(ll);
286     if (!s->data)
287     { shape[0] = NULL;
288       free(s);
289       return -1;
290     }
291     if (read(handle,s->data,ll)!=ll)
292     { free(s->data);
293       free(s);
294       shape[0] = NULL;
295       return -1;
296     }
297   }
298
299   return 0;
300 }
301
302 int swf_ShapeAddFillStyle(SHAPE * s,U8 type,MATRIX * m,RGBA * color,U16 id_bitmap)
303 { RGBA def_c;
304   MATRIX def_m;    
305
306   // handle defaults
307   
308   if (!s) return -1;
309   if (!color)
310   { color = &def_c;
311     def_c.a = 0xff;
312     def_c.r = def_c.g = def_c.b = 0;
313   }
314   if (!m)
315   { m = &def_m;
316     swf_GetMatrix(NULL,m);
317   }
318
319   // handle memory
320   
321   if (s->fillstyle.data)
322   { FILLSTYLE * new = (FILLSTYLE *)realloc(s->fillstyle.data,(s->fillstyle.n+1)*sizeof(FILLSTYLE));
323     if (!new) return -1;
324     s->fillstyle.data = new;
325   }
326   else
327   { s->fillstyle.data = (FILLSTYLE *)malloc(sizeof(FILLSTYLE));
328     s->fillstyle.n = 0;
329     if (!s->fillstyle.data) return -1;
330   }
331
332   // set fillstyle  (no gradients yet!)
333   
334   s->fillstyle.data[s->fillstyle.n].type = type; 
335   s->fillstyle.data[s->fillstyle.n].id_bitmap = id_bitmap;
336   memcpy(&s->fillstyle.data[s->fillstyle.n].m,m,sizeof(MATRIX));
337   memcpy(&s->fillstyle.data[s->fillstyle.n].color,color,sizeof(RGBA));
338           
339   return (++s->fillstyle.n);
340 }
341
342 int swf_ShapeAddSolidFillStyle(SHAPE * s,RGBA * color)
343 { return swf_ShapeAddFillStyle(s,FILL_SOLID,NULL,color,0);
344 }
345
346 int swf_ShapeAddBitmapFillStyle(SHAPE * s,MATRIX * m,U16 id_bitmap,int clip)
347 { return swf_ShapeAddFillStyle(s,clip?FILL_CLIPPED:FILL_TILED,m,NULL,id_bitmap);
348 }
349
350 int swf_ShapeAddLineStyle(SHAPE * s,U16 width,RGBA * color)
351 { RGBA def;
352   if (!s) return -1;
353   if (!color)
354   { color = &def;
355     def.a = 0xff;
356     def.r = def.g = def.b = 0; 
357   }
358   if (s->linestyle.data)
359   { LINESTYLE * new = (LINESTYLE *)realloc(s->linestyle.data,(s->linestyle.n+1)*sizeof(LINESTYLE));
360     if (!new) return -1;
361     s->linestyle.data = new;
362   }
363   else
364   { s->linestyle.data = (LINESTYLE *)malloc(sizeof(LINESTYLE));
365     s->linestyle.n = 0;
366     if (!s->linestyle.data) return -1;
367   }
368   
369   s->linestyle.data[s->linestyle.n].width = width;
370   memcpy(&s->linestyle.data[s->linestyle.n].color,color,sizeof(RGBA));
371
372   return (++s->linestyle.n);
373 }
374
375 int swf_ShapeSetMove(TAG * t,SHAPE * s,S32 x,S32 y)
376 { U8 b;
377   if (!t) return -1;
378   swf_SetBits(t,0,1);
379   swf_SetBits(t,SF_MOVETO,5);
380   
381   b = swf_CountBits(x,0);
382   b = swf_CountBits(y,b);
383   
384   swf_SetBits(t,b,5);
385   swf_SetBits(t,x,b);
386   swf_SetBits(t,y,b);
387
388   return 0;
389 }
390
391 int swf_ShapeSetStyle(TAG * t,SHAPE * s,U16 line,U16 fill0,U16 fill1)
392 { if ((!t)||(!s)) return -1;
393     
394   swf_SetBits(t,0,1);
395   swf_SetBits(t,(line?SF_LINE:0)|(fill0?SF_FILL0:0)|(fill1?SF_FILL1:0),5);
396
397   if (fill0) swf_SetBits(t,fill0,s->bits.fill);
398   if (fill1) swf_SetBits(t,fill1,s->bits.fill);
399   if (line)  swf_SetBits(t,line ,s->bits.line);
400   
401   return 0;
402 }
403
404 /* TODO: sometimes we want to set fillstyle 0, as that's the empty fill
405    used for line drawings. At the moment, we can't, as 0 fill be considered
406    nonexistent and therefore not set.
407    these defines are a workaround (they also reduce the maximal number of
408    fill styles to 32768)
409  */
410 #define FILL_RESET 0x8000
411 #define LINE_RESET 0x8000
412
413 int swf_ShapeSetAll(TAG * t,SHAPE * s,S32 x,S32 y,U16 line,U16 fill0,U16 fill1)
414 { U8 b;
415   if ((!t)||(!s)) return -1;
416
417   swf_SetBits(t,0,1);
418   swf_SetBits(t,SF_MOVETO|(line?SF_LINE:0)|(fill0?SF_FILL0:0)|(fill1?SF_FILL1:0),5);
419
420   b = swf_CountBits(x,0);
421   b = swf_CountBits(y,b);
422   swf_SetBits(t,b,5);
423   swf_SetBits(t,x,b);
424   swf_SetBits(t,y,b);
425
426   if (fill0) swf_SetBits(t,fill0,s->bits.fill);
427   if (fill1) swf_SetBits(t,fill1,s->bits.fill);
428   if (line)  swf_SetBits(t,line ,s->bits.line);
429   
430   return 0;
431 }
432
433 int swf_ShapeSetEnd(TAG * t)
434 { if (!t) return -1;
435   swf_SetBits(t,0,6);
436   swf_ResetWriteBits(t);
437   return 0;
438 }
439
440 int swf_ShapeSetLine(TAG * t,SHAPE * s,S32 x,S32 y)
441 { U8 b;
442   if (!t) return -1;
443   swf_SetBits(t,3,2); // Straight Edge
444
445   if ((!s)||((x!=0)&&(y!=0)))
446   { b = swf_CountBits(x,2);
447     b = swf_CountBits(y,b);
448     if (b<2) b=2;
449     swf_SetBits(t, b-2, 4);
450     swf_SetBits(t,1,1);
451     swf_SetBits(t,x,b);
452     swf_SetBits(t,y,b);
453     return 0;
454   }
455
456   if (x==0)
457   { b = swf_CountBits(y,2);
458     if(b<2) 
459         b=2;
460     swf_SetBits(t, b-2, 4);
461     swf_SetBits(t,1,2);
462     swf_SetBits(t,y,b);
463   } 
464   else
465   { b = swf_CountBits(x,2);
466     if(b<2) 
467         b=2;
468     swf_SetBits(t, b-2, 4);
469     swf_SetBits(t,0,2);
470     swf_SetBits(t,x,b);
471   }
472   return 0;
473 }
474
475 int swf_ShapeSetCurve(TAG * t,SHAPE * s,S32 x,S32 y,S32 ax,S32 ay)
476 { U8 b;
477   if (!t) return -1;
478
479   swf_SetBits(t,2,2);
480
481   b = swf_CountBits(ax,2);
482   b = swf_CountBits(ay,b);
483   b = swf_CountBits(x,b);
484   b = swf_CountBits(y,b);
485
486   swf_SetBits(t,b-2,4);
487   swf_SetBits(t,x,b);
488   swf_SetBits(t,y,b);
489   swf_SetBits(t,ax,b);
490   swf_SetBits(t,ay,b);
491
492   return 0;
493 }
494
495 int swf_ShapeSetCircle(TAG * t,SHAPE * s,S32 x,S32 y,S32 rx,S32 ry)
496 { double C1 = 0.2930;    
497   double C2 = 0.4140;   
498   double begin = 0.7070; 
499
500   if (!t) return -1;
501   
502   swf_ShapeSetMove(t,s,x+begin*rx,y+begin*ry);
503   swf_ShapeSetCurve(t,s, -C1*rx,  C1*ry, -C2*rx,      0);
504   swf_ShapeSetCurve(t,s, -C2*rx,      0, -C1*rx, -C1*ry);
505   swf_ShapeSetCurve(t,s, -C1*rx, -C1*ry,      0, -C2*ry);
506   swf_ShapeSetCurve(t,s,      0, -C2*ry,  C1*rx, -C1*ry);
507   swf_ShapeSetCurve(t,s,  C1*rx, -C1*ry,  C2*rx,      0);
508   swf_ShapeSetCurve(t,s,  C2*rx,      0,  C1*rx,  C1*ry);
509   swf_ShapeSetCurve(t,s,  C1*rx,  C1*ry,      0,  C2*ry);
510   swf_ShapeSetCurve(t,s,      0,  C2*ry, -C1*rx,  C1*ry);
511   
512   return 0;
513 }
514
515 /* todo: merge this with swf_GetSimpleShape */
516 SHAPELINE* swf_ParseShapeData(U8*data, int bits, int fillbits, int linebits)
517 {
518     SHAPELINE _lines;
519     SHAPELINE*lines = &_lines;
520
521     TAG _tag;
522     TAG* tag = &_tag;
523     int fill0 = 0;
524     int fill1 = 0;
525     int line = 0;
526     int x=0,y=0;
527     
528     memset(tag, 0, sizeof(TAG));
529     tag->data = data;
530     tag->len = tag->memsize = (bits+7)/8;
531     tag->pos = 0;
532
533     lines->next = 0;
534     while(1) {
535         int flags;
536         flags = swf_GetBits(tag, 1);
537         if(!flags) { //style change
538             flags = swf_GetBits(tag, 5);
539             if(!flags)
540                 break;
541             if(flags&2)
542                 fill0 = swf_GetBits(tag, fillbits); 
543             if(flags&4)
544                 fill1 = swf_GetBits(tag, fillbits); 
545             if(flags&8)
546                 line = swf_GetBits(tag, linebits); 
547             if(flags&16) {
548                 return 0;
549                 //enumerateUsedIDs_styles(tag, callback, callback_data, num);
550                 fillbits = swf_GetBits(tag, 4);
551                 linebits = swf_GetBits(tag, 4);
552             }
553             if(flags&1) { //move
554                 int n = swf_GetBits(tag, 5); 
555                 x = swf_GetSBits(tag, n); //x
556                 y = swf_GetSBits(tag, n); //y
557
558                 lines->next = (SHAPELINE*)malloc(sizeof(SHAPELINE));
559                 lines = lines->next;
560                 lines->type = moveTo;
561                 lines->x = x; 
562                 lines->y = y; 
563                 lines->sx = lines->sy = 0;
564                 lines->fillstyle0 = fill0;
565                 lines->fillstyle1 = fill1;
566                 lines->linestyle = line;
567                 lines->next = 0;
568             }
569         } else {
570             flags = swf_GetBits(tag, 1);
571             if(flags) { //straight edge
572                 int n = swf_GetBits(tag, 4) + 2;
573                 if(swf_GetBits(tag, 1)) { //line flag
574                     x += swf_GetSBits(tag, n); //delta x
575                     y += swf_GetSBits(tag, n); //delta y
576                 } else {
577                     int v=swf_GetBits(tag, 1);
578                     int d;
579                     d = swf_GetSBits(tag, n); //vert/horz
580                     if(v) y += d;
581                     else  x += d;
582                 }
583                 lines->next = (SHAPELINE*)malloc(sizeof(SHAPELINE));
584                 lines = lines->next;
585                 lines->type = lineTo;
586                 lines->x = x; 
587                 lines->y = y; 
588                 lines->sx = lines->sy = 0;
589                 lines->fillstyle0 = fill0;
590                 lines->fillstyle1 = fill1;
591                 lines->linestyle = line;
592                 lines->next = 0;
593             } else { //curved edge
594                 int n = swf_GetBits(tag, 4) + 2;
595                 int x1,y1;
596                 x += swf_GetSBits(tag, n);
597                 y += swf_GetSBits(tag, n);
598                 x1 = x;
599                 y1 = y;
600                 x += swf_GetSBits(tag, n);
601                 y += swf_GetSBits(tag, n);
602
603                 lines->next = (SHAPELINE*)malloc(sizeof(SHAPELINE));
604                 lines = lines->next;
605                 lines->type = splineTo;
606                 lines->sx = x1; 
607                 lines->sy = y1; 
608                 lines->x = x; 
609                 lines->y = y; 
610                 lines->fillstyle0 = fill0;
611                 lines->fillstyle1 = fill1;
612                 lines->linestyle = line;
613                 lines->next = 0;
614             }
615         }
616     }
617     return _lines.next;
618 }
619
620 SRECT swf_GetShapeBoundingBox(SHAPELINE*shape)
621 {
622     SRECT r;
623     int SCOORD_MAX = 0x7fffffff;
624     int SCOORD_MIN = -0x80000000;
625     r.xmin = r.ymin = SCOORD_MAX;
626     r.xmax = r.ymax = SCOORD_MIN;
627     if(!shape) {
628         memset(&r, 0, sizeof(SRECT));
629         return r;
630     }
631     while(shape) {
632         if(shape->x < r.xmin) r.xmin = shape->x;
633         if(shape->y < r.ymin) r.ymin = shape->y;
634         if(shape->x > r.xmax) r.xmax = shape->x;
635         if(shape->y > r.ymax) r.ymax = shape->y;
636         if(shape->type == splineTo) {
637             if(shape->sx < r.xmin) r.xmin = shape->sx;
638             if(shape->sy < r.ymin) r.ymin = shape->sy;
639             if(shape->sx > r.xmax) r.xmax = shape->sx;
640             if(shape->sy > r.ymax) r.ymax = shape->sy;
641         }
642         shape = shape->next;
643     }
644     return r;
645 }
646
647 void swf_Shape2Free(SHAPE2 * s)
648 {
649     SHAPELINE*line = s->lines;
650     while(line) {
651         SHAPELINE*next = line->next;
652         free(line);
653         line = next;
654     }
655     if(s->linestyles)
656         free(s->linestyles);
657     if(s->fillstyles)
658         free(s->fillstyles);
659     if(s->bbox)
660         free(s->bbox);
661 }
662
663 SHAPE2* swf_ShapeToShape2(SHAPE*shape) {
664
665     SHAPE2*shape2 = (SHAPE2*)malloc(sizeof(SHAPE2));
666     
667     shape2->numlinestyles = shape->linestyle.n;
668     shape2->linestyles = (LINESTYLE*)malloc(sizeof(LINESTYLE)*shape->linestyle.n);
669     memcpy(shape2->linestyles, shape->linestyle.data, sizeof(LINESTYLE)*shape->linestyle.n);
670     
671     shape2->numfillstyles = shape->fillstyle.n;
672     shape2->fillstyles = (FILLSTYLE*)malloc(sizeof(FILLSTYLE)*shape->fillstyle.n);
673     memcpy(shape2->fillstyles, shape->fillstyle.data, sizeof(FILLSTYLE)*shape->fillstyle.n);
674
675     shape2->lines = swf_ParseShapeData(shape->data, shape->bitlen, shape->bits.fill, shape->bits.line);
676     shape2->bbox = 0;
677     return shape2;
678 };
679
680 /*LINESTYLE* parseFillStyleArray(TAG*tag)
681 {
682     U16 count;
683     int t;
684     int num=0;
685     if(tag->id == ST_DEFINESHAPE)
686         num = 1;
687     else if(tag->id == ST_DEFINESHAPE2)
688         num = 2;
689     else if(tag->id == ST_DEFINESHAPE3)
690         num = 3;
691     else return 0;
692
693     count = swf_GetU8(tag);
694     if(count == 0xff && num>1) // defineshape2,3 only
695         count = swf_GetU16(tag);
696
697     for(t=0;t<count;t++)
698     {
699         int type;
700         U8*pos;
701         swf_ResetReadBits(tag);
702         type = swf_GetU8(tag); //type
703         if(type == 0) {
704             if(num == 3)
705                 swf_GetRGBA(tag, NULL);
706             else 
707                 swf_GetRGB(tag, NULL);
708         }
709         else if(type == 0x10 || type == 0x12)
710         {
711             swf_ResetReadBits(tag);
712             swf_GetMatrix(tag, NULL);
713             swf_ResetReadBits(tag);
714             swf_GetGradient(tag, NULL, alpha num>=3?1:0);
715         }
716         else if(type == 0x40 || type == 0x41)
717         {
718             swf_ResetReadBits(tag);
719             // we made it.
720             if(tag->data[tag->pos] != 0xff ||
721                tag->data[tag->pos+1] != 0xff)
722             //(callback)(tag, tag->pos, callback_data);
723
724             swf_GetU16(tag);
725             swf_ResetReadBits(tag);
726             swf_GetMatrix(tag, NULL);
727             swf_GetMatrix(tag, NULL);
728         }
729         else {
730             fprintf(stderr, "rfxswf:swftools.c Unknown fillstyle:0x%02x\n",type);
731         }
732     }
733     swf_ResetReadBits(tag);
734     count = swf_GetU8(tag); // line style array
735     if(count == 0xff)
736         count = swf_GetU16(tag);
737     for(t=0;t<count;t++) 
738     {
739         swf_GetU16(tag);
740         swf_GetU16(tag);
741         if(num == 3)
742             swf_GetRGBA(tag, NULL);
743         else
744             swf_GetRGB(tag, NULL);
745     }
746 }*/
747
748 /*SHAPE2* parseDefineShape(TAG*tag)
749 {
750     int num = 0;
751     SHAPE2*shape;
752     U16 fill,line;
753     if(tag->id == ST_DEFINESHAPE)
754         num = 1;
755     else if(tag->id == ST_DEFINESHAPE2)
756         num = 2;
757     else if(tag->id == ST_DEFINESHAPE3)
758         num = 3;
759     else return 0;
760
761     swf_GetU16();
762
763     shape = (SHAPE2*)malloc(sizeof(SHAPE2));
764
765 //    LINESTYLE * linestyles;
766 //    int numlinestyles;
767 //    FILLSTYLE* fillstyles;
768 //    int numfillstyles;
769 //    struct _SHAPELINE * lines;
770 //    SRECT* bbox; // may be NULL 
771
772     swf_GetRect();
773     swf_ResetReadBits(t); 
774     fill = (U16)swf_GetBits(t,4);
775     line = (U16)swf_GetBits(t,4);
776
777     swf_Get
778
779     
780
781
782
783
784     return 0;
785 }*/
786
787
788 SHAPE*     swf_Shape2ToShape(SHAPE2*shape)
789 {
790     /* todo */
791     fprintf(stderr, "Not implemented yet!\n");
792     exit(1);
793     return 0;
794 }
795
796 int        swf_SetShape2(TAG*tag, SHAPE2*shape)
797 {
798     /* todo */
799     fprintf(stderr, "Not implemented yet!\n");
800     exit(1);
801     return 0;
802 }
803