25077ac24865e0fa5796ba474d5025e9d8f782ce
[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     if(b-2 >= 16) {
450         fprintf(stderr, "Bit overflow in swf_ShapeSetLine(1)- %d\n", b);
451         fflush(stdout);
452         *(int*)0 = 0xdead;
453         b = 17;
454     }
455     swf_SetBits(t, b-2, 4);
456     swf_SetBits(t,1,1);
457     swf_SetBits(t,x,b);
458     swf_SetBits(t,y,b);
459     return 0;
460   }
461
462   if (x==0)
463   { b = swf_CountBits(y,2);
464     if(b<2) 
465         b=2;
466     if(b-2 >= 16) {
467         fprintf(stderr, "Bit overflow in swf_ShapeSetLine(2)- %d\n", b);
468         b = 17;
469     }
470     swf_SetBits(t, b-2, 4);
471     swf_SetBits(t,1,2);
472     swf_SetBits(t,y,b);
473   } 
474   else
475   { b = swf_CountBits(x,2);
476     if(b<2) 
477         b=2;
478     if(b-2 >= 16) {
479         fprintf(stderr, "Bit overflow in swf_ShapeSetLine(3)- %d\n", b);
480         b = 17;
481     }
482     swf_SetBits(t, b-2, 4);
483     swf_SetBits(t,0,2);
484     swf_SetBits(t,x,b);
485   }
486   return 0;
487 }
488
489 int swf_ShapeSetCurve(TAG * t,SHAPE * s,S32 x,S32 y,S32 ax,S32 ay)
490 { U8 b;
491   if (!t) return -1;
492
493   swf_SetBits(t,2,2);
494
495   b = swf_CountBits(ax,2);
496   b = swf_CountBits(ay,b);
497   b = swf_CountBits(x,b);
498   b = swf_CountBits(y,b);
499
500   swf_SetBits(t,b-2,4);
501   swf_SetBits(t,x,b);
502   swf_SetBits(t,y,b);
503   swf_SetBits(t,ax,b);
504   swf_SetBits(t,ay,b);
505
506   return 0;
507 }
508
509 int swf_ShapeSetCircle(TAG * t,SHAPE * s,S32 x,S32 y,S32 rx,S32 ry)
510 { double C1 = 0.2930;    
511   double C2 = 0.4140;   
512   double begin = 0.7070; 
513
514   if (!t) return -1;
515   
516   swf_ShapeSetMove(t,s,x+begin*rx,y+begin*ry);
517   swf_ShapeSetCurve(t,s, -C1*rx,  C1*ry, -C2*rx,      0);
518   swf_ShapeSetCurve(t,s, -C2*rx,      0, -C1*rx, -C1*ry);
519   swf_ShapeSetCurve(t,s, -C1*rx, -C1*ry,      0, -C2*ry);
520   swf_ShapeSetCurve(t,s,      0, -C2*ry,  C1*rx, -C1*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   
526   return 0;
527 }
528
529 /* todo: merge this with swf_GetSimpleShape */
530 SHAPELINE* swf_ParseShapeData(U8*data, int bits, int fillbits, int linebits)
531 {
532     SHAPELINE _lines;
533     SHAPELINE*lines = &_lines;
534
535     TAG _tag;
536     TAG* tag = &_tag;
537     int fill0 = 0;
538     int fill1 = 0;
539     int line = 0;
540     int x=0,y=0;
541     
542     memset(tag, 0, sizeof(TAG));
543     tag->data = data;
544     tag->len = tag->memsize = (bits+7)/8;
545     tag->pos = 0;
546
547     lines->next = 0;
548     while(1) {
549         int flags;
550         flags = swf_GetBits(tag, 1);
551         if(!flags) { //style change
552             flags = swf_GetBits(tag, 5);
553             if(!flags)
554                 break;
555             if(flags&2)
556                 fill0 = swf_GetBits(tag, fillbits); 
557             if(flags&4)
558                 fill1 = swf_GetBits(tag, fillbits); 
559             if(flags&8)
560                 line = swf_GetBits(tag, linebits); 
561             if(flags&16) {
562                 return 0;
563                 //enumerateUsedIDs_styles(tag, callback, callback_data, num);
564                 fillbits = swf_GetBits(tag, 4);
565                 linebits = swf_GetBits(tag, 4);
566             }
567             if(flags&1) { //move
568                 int n = swf_GetBits(tag, 5); 
569                 x = swf_GetSBits(tag, n); //x
570                 y = swf_GetSBits(tag, n); //y
571
572                 lines->next = (SHAPELINE*)malloc(sizeof(SHAPELINE));
573                 lines = lines->next;
574                 lines->type = moveTo;
575                 lines->x = x; 
576                 lines->y = y; 
577                 lines->sx = lines->sy = 0;
578                 lines->fillstyle0 = fill0;
579                 lines->fillstyle1 = fill1;
580                 lines->linestyle = line;
581                 lines->next = 0;
582             }
583         } else {
584             flags = swf_GetBits(tag, 1);
585             if(flags) { //straight edge
586                 int n = swf_GetBits(tag, 4) + 2;
587                 if(swf_GetBits(tag, 1)) { //line flag
588                     x += swf_GetSBits(tag, n); //delta x
589                     y += swf_GetSBits(tag, n); //delta y
590                 } else {
591                     int v=swf_GetBits(tag, 1);
592                     int d;
593                     d = swf_GetSBits(tag, n); //vert/horz
594                     if(v) y += d;
595                     else  x += d;
596                 }
597                 lines->next = (SHAPELINE*)malloc(sizeof(SHAPELINE));
598                 lines = lines->next;
599                 lines->type = lineTo;
600                 lines->x = x; 
601                 lines->y = y; 
602                 lines->sx = lines->sy = 0;
603                 lines->fillstyle0 = fill0;
604                 lines->fillstyle1 = fill1;
605                 lines->linestyle = line;
606                 lines->next = 0;
607             } else { //curved edge
608                 int n = swf_GetBits(tag, 4) + 2;
609                 int x1,y1;
610                 x += swf_GetSBits(tag, n);
611                 y += swf_GetSBits(tag, n);
612                 x1 = x;
613                 y1 = y;
614                 x += swf_GetSBits(tag, n);
615                 y += swf_GetSBits(tag, n);
616
617                 lines->next = (SHAPELINE*)malloc(sizeof(SHAPELINE));
618                 lines = lines->next;
619                 lines->type = splineTo;
620                 lines->sx = x1; 
621                 lines->sy = y1; 
622                 lines->x = x; 
623                 lines->y = y; 
624                 lines->fillstyle0 = fill0;
625                 lines->fillstyle1 = fill1;
626                 lines->linestyle = line;
627                 lines->next = 0;
628             }
629         }
630     }
631     return _lines.next;
632 }
633
634 SRECT swf_GetShapeBoundingBox(SHAPELINE*shape)
635 {
636     SRECT r;
637     int SCOORD_MAX = 0x7fffffff;
638     int SCOORD_MIN = -0x80000000;
639     r.xmin = r.ymin = SCOORD_MAX;
640     r.xmax = r.ymax = SCOORD_MIN;
641     if(!shape) {
642         memset(&r, 0, sizeof(SRECT));
643         return r;
644     }
645     while(shape) {
646         if(shape->x < r.xmin) r.xmin = shape->x;
647         if(shape->y < r.ymin) r.ymin = shape->y;
648         if(shape->x > r.xmax) r.xmax = shape->x;
649         if(shape->y > r.ymax) r.ymax = shape->y;
650         if(shape->type == splineTo) {
651             if(shape->sx < r.xmin) r.xmin = shape->sx;
652             if(shape->sy < r.ymin) r.ymin = shape->sy;
653             if(shape->sx > r.xmax) r.xmax = shape->sx;
654             if(shape->sy > r.ymax) r.ymax = shape->sy;
655         }
656         shape = shape->next;
657     }
658     return r;
659 }
660
661 void swf_Shape2Free(SHAPE2 * s)
662 {
663     SHAPELINE*line = s->lines;
664     while(line) {
665         SHAPELINE*next = line->next;
666         free(line);
667         line = next;
668     }
669     if(s->linestyles)
670         free(s->linestyles);
671     if(s->fillstyles)
672         free(s->fillstyles);
673     if(s->bbox)
674         free(s->bbox);
675 }
676
677 SHAPE2* swf_ShapeToShape2(SHAPE*shape) {
678
679     SHAPE2*shape2 = (SHAPE2*)malloc(sizeof(SHAPE2));
680     
681     shape2->numlinestyles = shape->linestyle.n;
682     shape2->linestyles = (LINESTYLE*)malloc(sizeof(LINESTYLE)*shape->linestyle.n);
683     memcpy(shape2->linestyles, shape->linestyle.data, sizeof(LINESTYLE)*shape->linestyle.n);
684     
685     shape2->numfillstyles = shape->fillstyle.n;
686     shape2->fillstyles = (FILLSTYLE*)malloc(sizeof(FILLSTYLE)*shape->fillstyle.n);
687     memcpy(shape2->fillstyles, shape->fillstyle.data, sizeof(FILLSTYLE)*shape->fillstyle.n);
688
689     shape2->lines = swf_ParseShapeData(shape->data, shape->bitlen, shape->bits.fill, shape->bits.line);
690     shape2->bbox = 0;
691     return shape2;
692 };
693
694 /*LINESTYLE* parseFillStyleArray(TAG*tag)
695 {
696     U16 count;
697     int t;
698     int num=0;
699     if(tag->id == ST_DEFINESHAPE)
700         num = 1;
701     else if(tag->id == ST_DEFINESHAPE2)
702         num = 2;
703     else if(tag->id == ST_DEFINESHAPE3)
704         num = 3;
705     else return 0;
706
707     count = swf_GetU8(tag);
708     if(count == 0xff && num>1) // defineshape2,3 only
709         count = swf_GetU16(tag);
710
711     for(t=0;t<count;t++)
712     {
713         int type;
714         U8*pos;
715         swf_ResetReadBits(tag);
716         type = swf_GetU8(tag); //type
717         if(type == 0) {
718             if(num == 3)
719                 swf_GetRGBA(tag, NULL);
720             else 
721                 swf_GetRGB(tag, NULL);
722         }
723         else if(type == 0x10 || type == 0x12)
724         {
725             swf_ResetReadBits(tag);
726             swf_GetMatrix(tag, NULL);
727             swf_ResetReadBits(tag);
728             swf_GetGradient(tag, NULL, alpha num>=3?1:0);
729         }
730         else if(type == 0x40 || type == 0x41)
731         {
732             swf_ResetReadBits(tag);
733             // we made it.
734             if(tag->data[tag->pos] != 0xff ||
735                tag->data[tag->pos+1] != 0xff)
736             //(callback)(tag, tag->pos, callback_data);
737
738             swf_GetU16(tag);
739             swf_ResetReadBits(tag);
740             swf_GetMatrix(tag, NULL);
741             swf_GetMatrix(tag, NULL);
742         }
743         else {
744             fprintf(stderr, "rfxswf:swftools.c Unknown fillstyle:0x%02x\n",type);
745         }
746     }
747     swf_ResetReadBits(tag);
748     count = swf_GetU8(tag); // line style array
749     if(count == 0xff)
750         count = swf_GetU16(tag);
751     for(t=0;t<count;t++) 
752     {
753         swf_GetU16(tag);
754         swf_GetU16(tag);
755         if(num == 3)
756             swf_GetRGBA(tag, NULL);
757         else
758             swf_GetRGB(tag, NULL);
759     }
760 }*/
761
762 /*SHAPE2* parseDefineShape(TAG*tag)
763 {
764     int num = 0;
765     SHAPE2*shape;
766     U16 fill,line;
767     if(tag->id == ST_DEFINESHAPE)
768         num = 1;
769     else if(tag->id == ST_DEFINESHAPE2)
770         num = 2;
771     else if(tag->id == ST_DEFINESHAPE3)
772         num = 3;
773     else return 0;
774
775     swf_GetU16();
776
777     shape = (SHAPE2*)malloc(sizeof(SHAPE2));
778
779 //    LINESTYLE * linestyles;
780 //    int numlinestyles;
781 //    FILLSTYLE* fillstyles;
782 //    int numfillstyles;
783 //    struct _SHAPELINE * lines;
784 //    SRECT* bbox; // may be NULL 
785
786     swf_GetRect();
787     swf_ResetReadBits(t); 
788     fill = (U16)swf_GetBits(t,4);
789     line = (U16)swf_GetBits(t,4);
790
791     swf_Get
792
793     
794
795
796
797
798     return 0;
799 }*/
800
801
802 SHAPE*     swf_Shape2ToShape(SHAPE2*shape)
803 {
804     /* todo */
805     fprintf(stderr, "Not implemented yet!\n");
806     exit(1);
807     return 0;
808 }
809
810 int        swf_SetShape2(TAG*tag, SHAPE2*shape)
811 {
812     /* todo */
813     fprintf(stderr, "Not implemented yet!\n");
814     exit(1);
815     return 0;
816 }
817
818 void swf_ShapeSetBitmapRect(TAG*tag, U16 gfxid, int width, int height)
819 {
820     SHAPE*shape;
821     MATRIX m;
822     RGBA rgb;
823     SRECT r;
824     int lines = 0;
825     int ls,fs;
826     swf_ShapeNew(&shape);
827     rgb.b = rgb.g = rgb.r = 0xff;
828     if(lines)
829         ls = swf_ShapeAddLineStyle(shape,20,&rgb);  
830     swf_GetMatrix(NULL,&m);
831     m.sx = 20*65536;
832     m.sy = 20*65536;
833
834     fs = swf_ShapeAddBitmapFillStyle(shape,&m,gfxid,0);
835     r.xmin = 0;
836     r.ymin = 0;
837     r.xmax = width*20;
838     r.ymax = height*20;
839     swf_SetRect(tag,&r);
840
841     swf_SetShapeStyles(tag,shape);
842     swf_ShapeCountBits(shape,NULL,NULL);
843     swf_SetShapeBits(tag,shape);
844
845     swf_ShapeSetAll(tag,shape,0,0,lines?ls:0,fs,0);
846
847     swf_ShapeSetLine(tag,shape,width*20,0);
848     swf_ShapeSetLine(tag,shape,0,height*20);
849     swf_ShapeSetLine(tag,shape,-width*20,0);
850     swf_ShapeSetLine(tag,shape,0,-height*20);
851     swf_ShapeSetEnd(tag);
852     swf_ShapeFree(shape);
853 }
854