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