* bugfixes in sprite handling.
[swftools.git] / lib / modules / swfobject.c
1 /* swfobject.c
2
3    Object place and move routines
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 PF_MOVE         0x01
15 #define PF_CHAR         0x02
16 #define PF_MATRIX       0x04
17 #define PF_CXFORM       0x08
18 #define PF_RATIO        0x10
19 #define PF_NAME         0x20
20 #define PF_CLIPACTION   0x40
21 #define PF_ACTIONEVENT  0x80
22
23 int swf_ObjectPlace(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,U8 * name)
24 { U8 flags;
25   if (!t) return -1;
26
27   if(cx && cx->r1==0 && cx->g1==0 && cx->b1==0 && cx->a1==0
28         && cx->r0==256 && cx->g0==256 && cx->b0==256 && cx->a0==256)
29       cx = 0;
30
31   flags = (id?PF_CHAR:0)|(m?PF_MATRIX:0)|(cx?PF_CXFORM:0)|(name?PF_NAME:0)|((m||cx)&&(!id)?PF_MOVE:0);
32
33   swf_SetU8(t,flags);
34   swf_SetU16(t,depth);
35   if (flags&PF_CHAR) swf_SetU16(t,id);
36   if (flags&PF_MATRIX) swf_SetMatrix(t,m);
37   if (flags&PF_CXFORM) swf_SetCXForm(t,cx,(cx->a0!=256)||(cx->a1));
38   if (flags&PF_RATIO) swf_SetU16(t,0);
39   if (flags&PF_NAME) swf_SetString(t,name);
40   
41   return 0; 
42 }
43
44 int swf_ObjectPlaceClip(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,U8 * name, U16 clipaction)
45 { U8 flags;
46   if (!t) return -1;
47   
48   if(cx && cx->r1==0 && cx->g1==0 && cx->b1==0 && cx->a1==0
49         && cx->r0==256 && cx->g0==256 && cx->b0==256 && cx->a0==256)
50       cx = 0;
51
52   flags = (id?PF_CHAR:0)|(m?PF_MATRIX:0)|(cx?PF_CXFORM:0)|(name?PF_NAME:0)|
53           ((m||cx)&&(!id)?PF_MOVE:0)|(clipaction?PF_CLIPACTION:0);
54
55   swf_SetU8(t,flags);
56   swf_SetU16(t,depth);
57   if (flags&PF_CHAR) swf_SetU16(t,id);
58   if (flags&PF_MATRIX) swf_SetMatrix(t,m);
59   if (flags&PF_CXFORM) swf_SetCXForm(t,cx,(cx->a0!=256)||(cx->a1));
60   if (flags&PF_RATIO) swf_SetU16(t,0);
61   if (flags&PF_NAME) swf_SetString(t,name);
62   if (flags&PF_CLIPACTION) swf_SetU16(t, clipaction);
63   return 0; 
64 }
65
66 int swf_ObjectMove(TAG * t,U16 depth,MATRIX * m,CXFORM * cx)
67 { return swf_ObjectPlace(t,0,depth,m,cx,NULL);
68 }
69
70 int isUnitMatrix(MATRIX* m)
71 {
72     /* a matrix with all zeros is also considered
73        "unit matrix", as a zeroed out MATRIX structure
74        usually means that the caller doesn't want to
75        set the matrix */
76     if((   (m->sx == 0x10000 && m->sy == 0x10000) 
77         || (m->sx == 0 && m->sy == 0))
78                 && ((m->r0|m->r1|m->tx|m->ty) == 0)
79       )
80         return 1;
81     return 0;
82 }
83
84 int isUnitCXForm(CXFORM* cx)
85 {
86     if((cx->a0==256 && cx->r0==256 && cx->g0==256 && cx->b0==256) &&
87        (cx->a1==0 && cx->r1==0 && cx->g1==0 && cx->b1==0))
88         return 1;
89     /* A CXForm of all zeros is, unfortunately, not as unlikely
90        as a matrix of all zeros. However, we still treat it
91        as non-existent/uniform transform */
92     if((cx->a0==0 && cx->r0==0 && cx->g0==0 && cx->b0==0) &&
93        (cx->a1==0 && cx->r1==0 && cx->g1==0 && cx->b1==0))
94         return 1;
95     return 0;
96 }
97
98 void swf_SetPlaceObject(TAG * t,SWFPLACEOBJECT* obj)
99
100     U8 flags;
101     if (!t) return ;
102     if(t->id == ST_PLACEOBJECT) {
103         swf_SetU16(t, obj->id);
104         swf_SetU16(t, obj->depth);      
105         swf_SetMatrix(t, &obj->matrix);
106         swf_SetCXForm(t, &obj->cxform, 0);
107     } else {
108         int m = !isUnitMatrix(&obj->matrix);
109         int cx = !isUnitCXForm(&obj->cxform);
110
111         flags = (obj->id?PF_CHAR:0)|(m?PF_MATRIX:0)|(cx?PF_CXFORM:0)|
112                 (obj->name?PF_NAME:0)|(obj->move?PF_MOVE:0)|
113                 (obj->clipdepth?PF_CLIPACTION:0);
114
115         swf_SetU8(t,flags);
116         swf_SetU16(t,obj->depth);
117         if (flags&PF_CHAR) swf_SetU16(t,obj->id);
118         if (flags&PF_MATRIX) swf_SetMatrix(t,&obj->matrix);
119         if (flags&PF_CXFORM) swf_SetCXForm(t,&obj->cxform,(obj->cxform.a0!=256)||
120                                                           (obj->cxform.a1));
121         if (flags&PF_RATIO) swf_SetU16(t,obj->ratio);
122         if (flags&PF_NAME) swf_SetString(t,obj->name);
123         if (flags&PF_CLIPACTION) swf_SetU16(t,obj->clipdepth);
124         if (flags&PF_ACTIONEVENT) {
125             // ...
126         }
127     }
128 }
129
130 void swf_GetPlaceObject(TAG * tag,SWFPLACEOBJECT* obj)
131 {
132     U8 flags = swf_GetU8(tag);
133     memset(obj,0,sizeof(SWFPLACEOBJECT));
134         
135     swf_GetMatrix(0,&obj->matrix);
136     swf_GetCXForm(0,&obj->cxform,1);
137
138     obj->depth = swf_GetU16(tag);
139     //flags&1: move
140     if(flags&2) obj->id = swf_GetU16(tag);
141     if(flags&4) swf_GetMatrix(tag, &obj->matrix);
142     if(flags&8) swf_GetCXForm(tag, &obj->cxform,1);
143     if(flags&16) obj->ratio = swf_GetU16(tag);
144     if(flags&32) {
145         int l,t;
146         U8*data;
147         swf_ResetReadBits(tag);
148         l = strlen(&tag->data[tag->pos]);
149         t = 0;
150         data = malloc(l+1);
151         obj->name = data;
152         while((data[t++] = swf_GetU8(tag))); 
153     }
154     if(flags&64) 
155         obj->clipdepth = swf_GetU16(tag); //clip
156
157     /* Actionscript ignored (for now) */
158     obj->actions = 0;
159 }
160
161 void swf_PlaceObjectFree(SWFPLACEOBJECT* obj)
162 {
163     if(obj->name)
164         free(obj->name);
165     free(obj);
166 }
167