added ratio support swf_SetPlaceObject.
[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,1);
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,1);
60   if (flags&PF_RATIO) swf_SetU16(t,0);
61
62   /* ??? The spec states that name comes first? */
63   if (flags&PF_CLIPACTION) swf_SetU16(t, clipaction);
64   if (flags&PF_NAME) swf_SetString(t,name);
65   return 0; 
66 }
67
68 int swf_ObjectMove(TAG * t,U16 depth,MATRIX * m,CXFORM * cx)
69 { return swf_ObjectPlace(t,0,depth,m,cx,NULL);
70 }
71
72 int isUnitMatrix(MATRIX* m)
73 {
74     /* a matrix with all zeros is also considered
75        "unit matrix", as a zeroed out MATRIX structure
76        usually means that the caller doesn't want to
77        set the matrix */
78     if((   (m->sx == 0x10000 && m->sy == 0x10000) 
79         || (m->sx == 0 && m->sy == 0))
80                 && ((m->r0|m->r1|m->tx|m->ty) == 0)
81       )
82         return 1;
83     return 0;
84 }
85
86 int isUnitCXForm(CXFORM* cx)
87 {
88     if((cx->a0==256 && cx->r0==256 && cx->g0==256 && cx->b0==256) &&
89        (cx->a1==0 && cx->r1==0 && cx->g1==0 && cx->b1==0))
90         return 1;
91     /* A CXForm of all zeros is, unfortunately, not as unlikely
92        as a matrix of all zeros. However, we still treat it
93        as non-existent/uniform transform */
94     if((cx->a0==0 && cx->r0==0 && cx->g0==0 && cx->b0==0) &&
95        (cx->a1==0 && cx->r1==0 && cx->g1==0 && cx->b1==0))
96         return 1;
97     return 0;
98 }
99
100 void swf_SetPlaceObject(TAG * t,SWFPLACEOBJECT* obj)
101
102     U8 flags;
103     if (!t) return ;
104     if(t->id == ST_PLACEOBJECT) {
105         swf_SetU16(t, obj->id);
106         swf_SetU16(t, obj->depth);      
107         swf_SetMatrix(t, &obj->matrix);
108         swf_SetCXForm(t, &obj->cxform, 0);
109     } else {
110         int m = !isUnitMatrix(&obj->matrix);
111         int cx = !isUnitCXForm(&obj->cxform);
112
113         flags = (obj->id?PF_CHAR:0)|(m?PF_MATRIX:0)|(cx?PF_CXFORM:0)|(obj->ratio?PF_RATIO:0)|
114                 (obj->name?PF_NAME:0)|(obj->move?PF_MOVE:0)|
115                 (obj->clipdepth?PF_CLIPACTION:0);
116
117         swf_SetU8(t,flags);
118         swf_SetU16(t,obj->depth);
119         if (flags&PF_CHAR) swf_SetU16(t,obj->id);
120         if (flags&PF_MATRIX) swf_SetMatrix(t,&obj->matrix);
121         if (flags&PF_CXFORM) swf_SetCXForm(t,&obj->cxform,1);
122         if (flags&PF_RATIO) swf_SetU16(t,obj->ratio);
123   
124         /* ??? The spec states that name comes first? */
125         if (flags&PF_CLIPACTION) swf_SetU16(t,obj->clipdepth);
126         if (flags&PF_NAME) swf_SetString(t,obj->name);
127         if (flags&PF_ACTIONEVENT) {
128             // ...
129         }
130     }
131 }
132
133 void swf_GetPlaceObject(TAG * tag,SWFPLACEOBJECT* obj)
134 {
135     U8 flags;
136     if(!tag) {
137         memset(obj, 0, sizeof(SWFPLACEOBJECT));
138         swf_GetMatrix(0, &obj->matrix);
139         swf_GetCXForm(0, &obj->cxform, 1);
140         return;
141     }
142     
143     flags = swf_GetU8(tag);
144     memset(obj,0,sizeof(SWFPLACEOBJECT));
145         
146     swf_GetMatrix(0,&obj->matrix);
147     swf_GetCXForm(0,&obj->cxform,1);
148
149     obj->depth = swf_GetU16(tag);
150     //flags&1: move
151     if(flags&2) obj->id = swf_GetU16(tag);
152     if(flags&4) swf_GetMatrix(tag, &obj->matrix);
153     if(flags&8) swf_GetCXForm(tag, &obj->cxform,1);
154     if(flags&16) obj->ratio = swf_GetU16(tag);
155     if(flags&64) 
156         obj->clipdepth = swf_GetU16(tag); //clip
157     if(flags&32) {
158         int l,t;
159         U8*data;
160         swf_ResetReadBits(tag);
161         l = strlen(&tag->data[tag->pos]);
162         t = 0;
163         data = malloc(l+1);
164         obj->name = data;
165         while((data[t++] = swf_GetU8(tag))); 
166     }
167
168     /* Actionscript ignored (for now) */
169     obj->actions = 0;
170 }
171
172 void swf_PlaceObjectFree(SWFPLACEOBJECT* obj)
173 {
174     if(obj->name)
175         free(obj->name);
176     free(obj);
177 }
178