55b9b1ce075da9f632c5d04db6e9493b35770d92
[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_CLIPDEPTH    0x40
31 #define PF_ACTIONEVENT  0x80
32
33 #define PF2_FILTERS      0x01
34 #define PF2_BLENDMODE    0x02
35 #define PF2_ASBITMAP     0x04
36 //...
37
38 char*blendModeNames[] = {"normal","normal2","layer","multiply",
39                        "screen","lighten", "darken","add",
40                        "substract","difference","invert","alpha",
41                        "erase","overlay","hardlight",0};
42
43 int isUnitMatrix(MATRIX* m)
44 {
45     /* a matrix with all zeros is also considered
46        "unit matrix", as a zeroed out MATRIX structure
47        usually means that the caller doesn't want to
48        set the matrix */
49     if((   (m->sx == 0x10000 && m->sy == 0x10000) 
50         || (m->sx == 0 && m->sy == 0))
51                 && ((m->r0|m->r1|m->tx|m->ty) == 0)
52       )
53         return 1;
54     return 0;
55 }
56
57 int isUnitCXForm(CXFORM* cx)
58 {
59     if((cx->a0==256 && cx->r0==256 && cx->g0==256 && cx->b0==256) &&
60        (cx->a1==0 && cx->r1==0 && cx->g1==0 && cx->b1==0))
61         return 1;
62     /* A CXForm of all zeros is, unfortunately, not as unlikely
63        as a matrix of all zeros. However, we still treat it
64        as non-existent/uniform transform */
65     if((cx->a0==0 && cx->r0==0 && cx->g0==0 && cx->b0==0) &&
66        (cx->a1==0 && cx->r1==0 && cx->g1==0 && cx->b1==0))
67         return 1;
68     return 0;
69 }
70
71 static int objectplace(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,U8 * name, U16 clipaction, U8 blendmode, FILTERLIST*filters)
72 { U8 flags,flags2;
73   if (!t) return -1;
74
75   if(cx && id && cx->r1==0 && cx->g1==0 && cx->b1==0 && cx->a1==0
76               && cx->r0==256 && cx->g0==256 && cx->b0==256 && cx->a0==256)
77       cx = 0;
78
79   if(m && id && isUnitMatrix(m)) 
80       m = 0;
81
82   flags = (id?PF_CHAR:0)|(m?PF_MATRIX:0)|(cx?PF_CXFORM:0)|(name?PF_NAME:0)|((m||cx)&&(!id)?PF_MOVE:0)|(clipaction?PF_CLIPDEPTH:0);
83   flags2 = (0?PF2_ASBITMAP:0)|(blendmode?PF2_BLENDMODE:0)|(filters?PF2_FILTERS:0);
84
85   swf_SetU8(t,flags);
86   if(t->id == ST_PLACEOBJECT3)
87       swf_SetU8(t, flags2);
88   swf_SetU16(t,depth);
89   if (flags&PF_CHAR) swf_SetU16(t,id);
90   if (flags&PF_MATRIX) swf_SetMatrix(t,m);
91   if (flags&PF_CXFORM) swf_SetCXForm(t,cx,1);
92   if (flags&PF_RATIO) swf_SetU16(t,0);
93   /* ??? The spec states that name comes first? */
94   if (flags&PF_CLIPDEPTH) swf_SetU16(t, clipaction);
95   if (flags&PF_NAME) swf_SetString(t,name);
96         
97   if (flags2&PF2_BLENDMODE)
98     swf_SetU8(t,blendmode);
99   return 0; 
100 }
101 int swf_ObjectPlace(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,U8 * name)
102 {
103     return objectplace(t,id,depth,m,cx,name,0,0,0);
104 }
105 int swf_ObjectPlaceClip(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,U8 * name, U16 clipaction)
106
107     return objectplace(t,id,depth,m,cx,name,clipaction,0,0);
108 }
109 int swf_ObjectPlaceBlend(TAG * t,U16 id,U16 depth,MATRIX * m,CXFORM * cx,U8 * name, U8 blend)
110
111     if(t->id != ST_PLACEOBJECT3)
112         fprintf(stderr, "wrong tag- ignoring blend mode\n");
113     return objectplace(t,id,depth,m,cx,name,0,blend,0);
114 }
115 int swf_ObjectMove(TAG * t,U16 depth,MATRIX * m,CXFORM * cx)
116 {
117     return objectplace(t,0,depth,m,cx,0,0,0,0);
118 }
119
120 void swf_SetPlaceObject(TAG * t,SWFPLACEOBJECT* obj)
121
122     if (!t) return ;
123     if(t->id == ST_PLACEOBJECT) {
124         swf_SetU16(t, obj->id);
125         swf_SetU16(t, obj->depth);      
126         swf_SetMatrix(t, &obj->matrix);
127         swf_SetCXForm(t, &obj->cxform, 0);
128     } else {
129         U8 flags,flags2;
130         int m = !isUnitMatrix(&obj->matrix);
131         int cx = !isUnitCXForm(&obj->cxform);
132
133         flags = (obj->id?PF_CHAR:0)|(m?PF_MATRIX:0)|(cx?PF_CXFORM:0)|(obj->ratio?PF_RATIO:0)|
134                 (obj->name?PF_NAME:0)|(obj->move?PF_MOVE:0)|
135                 (obj->clipdepth?PF_CLIPDEPTH:0);
136         flags2 = (0?PF2_ASBITMAP:0)|(obj->blendmode?PF2_BLENDMODE:0)|(obj->filters?PF2_FILTERS:0);
137
138         swf_SetU8(t,flags);
139         if(t->id == ST_PLACEOBJECT2) 
140             swf_SetU8(t,flags2);
141         swf_SetU16(t,obj->depth);
142         if (flags&PF_CHAR) swf_SetU16(t,obj->id);
143         if (flags&PF_MATRIX) swf_SetMatrix(t,&obj->matrix);
144         if (flags&PF_CXFORM) swf_SetCXForm(t,&obj->cxform,1);
145         if (flags&PF_RATIO) swf_SetU16(t,obj->ratio);
146   
147         /* ??? The spec states that name comes first? */
148         if (flags&PF_CLIPDEPTH) swf_SetU16(t,obj->clipdepth);
149         if (flags&PF_NAME) swf_SetString(t,obj->name);
150
151         if (flags2&PF2_FILTERS) {
152             // ...
153         }
154         if (flags2&PF2_BLENDMODE)
155             swf_SetU8(t,obj->blendmode);
156         if (flags&PF_ACTIONEVENT) {
157             // ...
158         }
159     }
160 }
161
162 void swf_GetPlaceObject(TAG * tag,SWFPLACEOBJECT* obj)
163 {
164     if(!tag) {
165         memset(obj, 0, sizeof(SWFPLACEOBJECT));
166         swf_GetMatrix(0, &obj->matrix);
167         swf_GetCXForm(0, &obj->cxform, 1);
168         //obj->internal = PF_CHAR|PF_MATRIX|PF_CXFORM;
169         return;
170     }
171     swf_SetTagPos(tag, 0);
172     
173     if(tag->id == ST_PLACEOBJECT) {
174         obj->id = swf_GetU16(tag);
175         obj->depth = swf_GetU16(tag);
176         swf_GetMatrix(tag, &obj->matrix);
177         swf_GetCXForm(tag, &obj->cxform, 0);
178         //obj->internal = PF_CHAR|PF_MATRIX|PF_CXFORM;
179     } else if(tag->id == ST_PLACEOBJECT2 || tag->id == ST_PLACEOBJECT3) {
180         U8 flags,flags2=0;
181         flags = swf_GetU8(tag);
182         if(tag->id == ST_PLACEOBJECT3)
183             flags2 = swf_GetU8(tag);
184         memset(obj,0,sizeof(SWFPLACEOBJECT));
185             
186         swf_GetMatrix(0,&obj->matrix);
187         swf_GetCXForm(0,&obj->cxform,1);
188
189         obj->depth = swf_GetU16(tag);
190         //obj->internal = flags;
191         if(flags&PF_MOVE) obj->move = 1;
192         if(flags&PF_CHAR) obj->id = swf_GetU16(tag);
193         if(flags&PF_MATRIX) swf_GetMatrix(tag, &obj->matrix);
194         if(flags&PF_CXFORM) swf_GetCXForm(tag, &obj->cxform,1);
195         if(flags&PF_RATIO) obj->ratio = swf_GetU16(tag);
196         /* if you modify the order of these operations, also
197            modify it in ../src/swfcombine.c */
198         if(flags&PF_CLIPDEPTH) 
199             obj->clipdepth = swf_GetU16(tag); //clip
200         if(flags&PF_NAME) {
201             int l,t;
202             U8*data;
203             swf_ResetReadBits(tag);
204             l = strlen(&tag->data[tag->pos]);
205             t = 0;
206             data = rfx_alloc(l+1);
207             obj->name = data;
208             while((data[t++] = swf_GetU8(tag))); 
209         }
210         if(flags2&PF2_BLENDMODE) {
211             obj->blendmode = swf_GetU8(tag);
212         }
213
214         /* Actionscript ignored (for now) */
215         obj->actions = 0;
216     } else {
217         fprintf(stderr, "rfxswf: Bad Tag: %d not a placeobject\n", tag->id);
218     }
219 }
220
221 void swf_PlaceObjectFree(SWFPLACEOBJECT* obj)
222 {
223     if(obj->name)
224         rfx_free(obj->name);
225 }
226