added support for text boxes.
[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 program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
23
24 #define PF_MOVE         0x01
25 #define PF_CHAR         0x02
26 #define PF_MATRIX       0x04
27 #define PF_CXFORM       0x08
28 #define PF_RATIO        0x10
29 #define PF_NAME         0x20
30 #define PF_CLIPACTION   0x40
31 #define PF_ACTIONEVENT  0x80
32
33 int swf_ObjectPlace(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,U8 * name)
34 { U8 flags;
35   if (!t) return -1;
36
37   if(cx && cx->r1==0 && cx->g1==0 && cx->b1==0 && cx->a1==0
38         && cx->r0==256 && cx->g0==256 && cx->b0==256 && cx->a0==256)
39       cx = 0;
40
41   flags = (id?PF_CHAR:0)|(m?PF_MATRIX:0)|(cx?PF_CXFORM:0)|(name?PF_NAME:0)|((m||cx)&&(!id)?PF_MOVE:0);
42
43   swf_SetU8(t,flags);
44   swf_SetU16(t,depth);
45   if (flags&PF_CHAR) swf_SetU16(t,id);
46   if (flags&PF_MATRIX) swf_SetMatrix(t,m);
47   if (flags&PF_CXFORM) swf_SetCXForm(t,cx,1);
48   if (flags&PF_RATIO) swf_SetU16(t,0);
49   if (flags&PF_NAME) swf_SetString(t,name);
50   
51   return 0; 
52 }
53
54 int swf_ObjectPlaceClip(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,U8 * name, U16 clipaction)
55 { U8 flags;
56   if (!t) return -1;
57   
58   if(cx && cx->r1==0 && cx->g1==0 && cx->b1==0 && cx->a1==0
59         && cx->r0==256 && cx->g0==256 && cx->b0==256 && cx->a0==256)
60       cx = 0;
61
62   flags = (id?PF_CHAR:0)|(m?PF_MATRIX:0)|(cx?PF_CXFORM:0)|(name?PF_NAME:0)|
63           ((m||cx)&&(!id)?PF_MOVE:0)|(clipaction?PF_CLIPACTION:0);
64
65   swf_SetU8(t,flags);
66   swf_SetU16(t,depth);
67   if (flags&PF_CHAR) swf_SetU16(t,id);
68   if (flags&PF_MATRIX) swf_SetMatrix(t,m);
69   if (flags&PF_CXFORM) swf_SetCXForm(t,cx,1);
70   if (flags&PF_RATIO) swf_SetU16(t,0);
71
72   /* ??? The spec states that name comes first? */
73   if (flags&PF_CLIPACTION) swf_SetU16(t, clipaction);
74   if (flags&PF_NAME) swf_SetString(t,name);
75   return 0; 
76 }
77
78 int swf_ObjectMove(TAG * t,U16 depth,MATRIX * m,CXFORM * cx)
79 { return swf_ObjectPlace(t,0,depth,m,cx,NULL);
80 }
81
82 int isUnitMatrix(MATRIX* m)
83 {
84     /* a matrix with all zeros is also considered
85        "unit matrix", as a zeroed out MATRIX structure
86        usually means that the caller doesn't want to
87        set the matrix */
88     if((   (m->sx == 0x10000 && m->sy == 0x10000) 
89         || (m->sx == 0 && m->sy == 0))
90                 && ((m->r0|m->r1|m->tx|m->ty) == 0)
91       )
92         return 1;
93     return 0;
94 }
95
96 int isUnitCXForm(CXFORM* cx)
97 {
98     if((cx->a0==256 && cx->r0==256 && cx->g0==256 && cx->b0==256) &&
99        (cx->a1==0 && cx->r1==0 && cx->g1==0 && cx->b1==0))
100         return 1;
101     /* A CXForm of all zeros is, unfortunately, not as unlikely
102        as a matrix of all zeros. However, we still treat it
103        as non-existent/uniform transform */
104     if((cx->a0==0 && cx->r0==0 && cx->g0==0 && cx->b0==0) &&
105        (cx->a1==0 && cx->r1==0 && cx->g1==0 && cx->b1==0))
106         return 1;
107     return 0;
108 }
109
110 void swf_SetPlaceObject(TAG * t,SWFPLACEOBJECT* obj)
111
112     U8 flags;
113     if (!t) return ;
114     if(t->id == ST_PLACEOBJECT) {
115         swf_SetU16(t, obj->id);
116         swf_SetU16(t, obj->depth);      
117         swf_SetMatrix(t, &obj->matrix);
118         swf_SetCXForm(t, &obj->cxform, 0);
119     } else {
120         int m = !isUnitMatrix(&obj->matrix);
121         int cx = !isUnitCXForm(&obj->cxform);
122
123         flags = (obj->id?PF_CHAR:0)|(m?PF_MATRIX:0)|(cx?PF_CXFORM:0)|(obj->ratio?PF_RATIO:0)|
124                 (obj->name?PF_NAME:0)|(obj->move?PF_MOVE:0)|
125                 (obj->clipdepth?PF_CLIPACTION:0);
126
127         swf_SetU8(t,flags);
128         swf_SetU16(t,obj->depth);
129         if (flags&PF_CHAR) swf_SetU16(t,obj->id);
130         if (flags&PF_MATRIX) swf_SetMatrix(t,&obj->matrix);
131         if (flags&PF_CXFORM) swf_SetCXForm(t,&obj->cxform,1);
132         if (flags&PF_RATIO) swf_SetU16(t,obj->ratio);
133   
134         /* ??? The spec states that name comes first? */
135         if (flags&PF_CLIPACTION) swf_SetU16(t,obj->clipdepth);
136         if (flags&PF_NAME) swf_SetString(t,obj->name);
137         if (flags&PF_ACTIONEVENT) {
138             // ...
139         }
140     }
141 }
142
143 void swf_GetPlaceObject(TAG * tag,SWFPLACEOBJECT* obj)
144 {
145     U8 flags;
146     if(!tag) {
147         memset(obj, 0, sizeof(SWFPLACEOBJECT));
148         swf_GetMatrix(0, &obj->matrix);
149         swf_GetCXForm(0, &obj->cxform, 1);
150         return;
151     }
152     
153     flags = swf_GetU8(tag);
154     memset(obj,0,sizeof(SWFPLACEOBJECT));
155         
156     swf_GetMatrix(0,&obj->matrix);
157     swf_GetCXForm(0,&obj->cxform,1);
158
159     obj->depth = swf_GetU16(tag);
160     //flags&1: move
161     if(flags&2) obj->id = swf_GetU16(tag);
162     if(flags&4) swf_GetMatrix(tag, &obj->matrix);
163     if(flags&8) swf_GetCXForm(tag, &obj->cxform,1);
164     if(flags&16) obj->ratio = swf_GetU16(tag);
165     if(flags&64) 
166         obj->clipdepth = swf_GetU16(tag); //clip
167     if(flags&32) {
168         int l,t;
169         U8*data;
170         swf_ResetReadBits(tag);
171         l = strlen(&tag->data[tag->pos]);
172         t = 0;
173         data = malloc(l+1);
174         obj->name = data;
175         while((data[t++] = swf_GetU8(tag))); 
176     }
177
178     /* Actionscript ignored (for now) */
179     obj->actions = 0;
180 }
181
182 void swf_PlaceObjectFree(SWFPLACEOBJECT* obj)
183 {
184     if(obj->name)
185         free(obj->name);
186     free(obj);
187 }
188