Line data Source code
1 : /*
2 : * GPAC - Multimedia Framework C SDK
3 : *
4 : * Authors: Jean Le Feuvre
5 : * Copyright (c) Telecom ParisTech 2000-2012
6 : * All rights reserved
7 : *
8 : * This file is part of GPAC / Scene Management sub-project
9 : *
10 : * GPAC is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU Lesser General Public License as published by
12 : * the Free Software Foundation; either version 2, or (at your option)
13 : * any later version.
14 : *
15 : * GPAC 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 Lesser General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU Lesser General Public
21 : * License along with this library; see the file COPYING. If not, write to
22 : * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
23 : *
24 : */
25 : #include <gpac/nodes_mpeg4.h>
26 : #include <gpac/utf.h>
27 : #include <gpac/xml.h>
28 : #include <gpac/internal/swf_dev.h>
29 : #include <gpac/internal/scenegraph_dev.h>
30 :
31 :
32 : #ifndef GPAC_DISABLE_VRML
33 :
34 : #ifndef GPAC_DISABLE_SWF_IMPORT
35 :
36 : #define SWF_TEXT_SCALE (1/1024.0f)
37 :
38 : typedef struct
39 : {
40 : u32 btn_id;
41 : u32 sprite_up_id;
42 : } S2BBtnRec;
43 :
44 980 : static GF_Err s2b_insert_symbol(SWFReader *read, GF_Node *n)
45 : {
46 : GF_CommandField *f;
47 :
48 980 : if (read->flags & GF_SM_SWF_STATIC_DICT) {
49 572 : M_Switch *par = (M_Switch *)gf_sg_find_node_by_name(read->load->scene_graph, "DICTIONARY");
50 572 : gf_node_list_add_child(&par->choice, n);
51 572 : gf_node_register((GF_Node *)n, (GF_Node *)par);
52 : } else {
53 408 : GF_Command *com = gf_sg_command_new(read->load->scene_graph, GF_SG_INDEXED_INSERT);
54 408 : com->node = gf_sg_find_node_by_name(read->load->scene_graph, "DICTIONARY");
55 408 : gf_node_register(com->node, NULL);
56 408 : f = gf_sg_command_field_new(com);
57 408 : f->field_ptr = &f->new_node;
58 408 : f->fieldType = GF_SG_VRML_SFNODE;
59 408 : f->fieldIndex = 0; /*choice index*/
60 408 : f->pos = -1;
61 408 : f->new_node = n;
62 408 : gf_node_register(f->new_node, NULL);
63 408 : if (read->bifs_dict_au)
64 408 : gf_list_add(read->bifs_dict_au->commands, com);
65 : else
66 0 : gf_list_add(read->bifs_au->commands, com);
67 : }
68 980 : return GF_OK;
69 : }
70 :
71 3163 : static GF_Node *s2b_get_node(SWFReader *read, u32 ID)
72 : {
73 : GF_Node *n;
74 : char szDEF[1024];
75 : sprintf(szDEF, "Shape%d", ID);
76 3163 : n = gf_sg_find_node_by_name(read->load->scene_graph, szDEF);
77 3163 : if (n) return n;
78 : sprintf(szDEF, "Text%d", ID);
79 120 : n = gf_sg_find_node_by_name(read->load->scene_graph, szDEF);
80 120 : if (n) return n;
81 : sprintf(szDEF, "Button%d", ID);
82 19 : n = gf_sg_find_node_by_name(read->load->scene_graph, szDEF);
83 19 : if (n) return n;
84 : return NULL;
85 : }
86 :
87 12737 : static GF_Node *s2b_new_node(SWFReader *read, u32 tag)
88 : {
89 12737 : GF_Node *n = gf_node_new(read->load->scene_graph, tag);
90 12737 : if (n) gf_node_init(n);
91 12737 : return n;
92 : }
93 :
94 :
95 3146 : static GF_Node *s2b_get_matrix(SWFReader *read, GF_Matrix2D *mat)
96 : {
97 3146 : M_TransformMatrix2D *tm = (M_TransformMatrix2D *)s2b_new_node(read, TAG_MPEG4_TransformMatrix2D);
98 3146 : tm->mxx = mat->m[0];
99 3146 : tm->mxy = mat->m[1];
100 3146 : tm->tx = mat->m[2];
101 3146 : tm->myx = mat->m[3];
102 3146 : tm->myy = mat->m[4];
103 3146 : tm->ty = mat->m[5];
104 3146 : return (GF_Node *) tm;
105 : }
106 :
107 67 : static GF_Node *s2b_get_color_matrix(SWFReader *read, GF_ColorMatrix *cmat)
108 : {
109 67 : M_ColorTransform *ct = (M_ColorTransform*)s2b_new_node(read, TAG_MPEG4_ColorTransform);
110 67 : ct->mrr = cmat->m[0];
111 67 : ct->mrg = cmat->m[1];
112 67 : ct->mrb = cmat->m[2];
113 67 : ct->mra = cmat->m[3];
114 67 : ct->tr = cmat->m[4];
115 67 : ct->mgr = cmat->m[5];
116 67 : ct->mgg = cmat->m[6];
117 67 : ct->mgb = cmat->m[7];
118 67 : ct->mga = cmat->m[8];
119 67 : ct->tg = cmat->m[9];
120 67 : ct->mbr = cmat->m[10];
121 67 : ct->mbg = cmat->m[11];
122 67 : ct->mbb = cmat->m[12];
123 67 : ct->mba = cmat->m[13];
124 67 : ct->tb = cmat->m[14];
125 67 : ct->mar = cmat->m[15];
126 67 : ct->mag = cmat->m[16];
127 67 : ct->mab = cmat->m[17];
128 67 : ct->maa = cmat->m[18];
129 67 : ct->ta = cmat->m[19];
130 67 : return (GF_Node *) ct;
131 : }
132 :
133 :
134 : static SFColor s2b_get_color(u32 ARGB)
135 : {
136 : SFColor val;
137 5072 : val.red = INT2FIX((ARGB>>16)&0xFF) / 255;
138 5072 : val.green = INT2FIX((ARGB>>8)&0xFF) / 255;
139 5072 : val.blue = INT2FIX((ARGB)&0xFF) / 255;
140 : return val;
141 : }
142 :
143 : static Fixed s2b_get_alpha(u32 ARGB)
144 : {
145 5078 : return INT2FIX((ARGB>>24)&0xFF) / 255;
146 : }
147 :
148 58 : static void s2b_insert_appearance(SWFReader *read, GF_Node *app)
149 : {
150 58 : M_Shape *s = (M_Shape *) s2b_new_node(read, TAG_MPEG4_Shape);
151 58 : s->appearance = app;
152 58 : gf_node_register(app, (GF_Node *) s);
153 :
154 58 : s2b_insert_symbol(read, (GF_Node *)s);
155 58 : }
156 :
157 : static Bool s2b_same_color(SFColor c1, SFColor c2)
158 : {
159 7316 : if (c1.red != c2.red) return 0;
160 1710 : if (c1.green != c2.green) return 0;
161 1596 : if (c1.blue != c2.blue) return 0;
162 : return 1;
163 : }
164 :
165 2332 : static GF_Node *s2b_get_appearance(SWFReader *read, GF_Node *parent, u32 fill_col, Fixed line_width, u32 l_col)
166 : {
167 : u32 ID, i;
168 : SFColor fc, lc;
169 : Fixed fill_transp, line_transp;
170 : M_Appearance *app;
171 :
172 : fc = s2b_get_color(fill_col);
173 2332 : fill_transp = FIX_ONE - s2b_get_alpha(fill_col);
174 2332 : if (fill_transp<0) fill_transp=0;
175 : lc = s2b_get_color(l_col);
176 2332 : line_transp = FIX_ONE - s2b_get_alpha(l_col);
177 2332 : if (line_transp<0) line_transp=0;
178 :
179 2332 : i=0;
180 17934 : while ((app = (M_Appearance*)gf_list_enum(read->apps, &i))) {
181 14466 : M_Material2D *mat = (M_Material2D *)app->material;
182 14466 : if (!line_width) {
183 11230 : if (mat->lineProps || !mat->filled) continue;
184 : } else {
185 3236 : if (!mat->lineProps) continue;
186 614 : if (!s2b_same_color(((M_LineProperties *)mat->lineProps)->lineColor, lc)) continue;
187 1078 : if (((M_LineProperties *)mat->lineProps)->width != line_width) continue;
188 : }
189 7842 : if (!mat->filled && fill_col) continue;
190 7842 : if (mat->filled) {
191 7544 : if (!fill_col) continue;
192 7544 : if (mat->transparency != fill_transp) continue;
193 5116 : if (!s2b_same_color(mat->emissiveColor, fc)) continue;
194 : }
195 : /*OK same appearance let's go*/
196 1196 : gf_node_register((GF_Node *)app, parent);
197 1196 : return (GF_Node *)app;
198 : }
199 :
200 1136 : app = (M_Appearance *) s2b_new_node(read, TAG_MPEG4_Appearance);
201 1136 : app->material = s2b_new_node(read, TAG_MPEG4_Material2D);
202 1136 : gf_node_register(app->material, (GF_Node *)app);
203 1136 : ((M_Material2D *)app->material)->filled = 0;
204 :
205 1136 : if (fill_col) {
206 933 : ((M_Material2D *)app->material)->filled = 1;
207 933 : ((M_Material2D *)app->material)->emissiveColor = fc;
208 933 : ((M_Material2D *)app->material)->transparency = fill_transp;
209 : }
210 1136 : if (line_width && l_col) {
211 203 : if (read->flags & GF_SM_SWF_SCALABLE_LINE) {
212 0 : M_XLineProperties *lp = (M_XLineProperties *) s2b_new_node(read, TAG_MPEG4_XLineProperties);
213 0 : ((M_Material2D *)app->material)->lineProps = (GF_Node *) lp;
214 0 : lp->width = line_width;
215 0 : lp->lineColor = lc;
216 0 : lp->isScalable = 1;
217 0 : lp->transparency = line_transp;
218 0 : gf_node_register((GF_Node *)lp, app->material);
219 : } else {
220 203 : M_LineProperties *lp = (M_LineProperties *) s2b_new_node(read, TAG_MPEG4_LineProperties);
221 203 : ((M_Material2D *)app->material)->lineProps = (GF_Node *) lp;
222 203 : lp->width = line_width;
223 203 : lp->lineColor = lc;
224 203 : gf_node_register((GF_Node *)lp, app->material);
225 : }
226 : }
227 :
228 1136 : gf_node_register((GF_Node *)app, parent);
229 :
230 1136 : if (read->load->swf_import_flags & GF_SM_SWF_REUSE_APPEARANCE) {
231 : char szDEF[1024];
232 58 : sprintf(szDEF, "FILLAPP_%d", gf_list_count(read->apps));
233 58 : read->load->ctx->max_node_id++;
234 58 : ID = read->load->ctx->max_node_id;
235 :
236 58 : gf_node_set_id((GF_Node *)app, ID, szDEF);
237 58 : s2b_insert_appearance(read, (GF_Node *)app);
238 58 : gf_list_add(read->apps, app);
239 : }
240 : return (GF_Node *) app;
241 : }
242 :
243 :
244 103 : static GF_Rect s2b_get_center_bounds(SWFShape *shape, SWFShapeRec *srec)
245 : {
246 : GF_Rect rc;
247 : u32 i;
248 : Fixed xm, ym, xM, yM;
249 : xM = yM = FIX_MIN;
250 : xm = ym = FIX_MAX;
251 :
252 829 : for (i=0; i<srec->path->nbPts; i++) {
253 829 : if (srec->path->pts[i].x<=xm) xm = srec->path->pts[i].x;
254 829 : if (srec->path->pts[i].x>=xM) xM = srec->path->pts[i].x;
255 829 : if (srec->path->pts[i].y<=ym) ym = srec->path->pts[i].y;
256 829 : if (srec->path->pts[i].y>=yM) yM = srec->path->pts[i].y;
257 : }
258 103 : rc.width = xM-xm;
259 103 : rc.height = yM-ym;
260 : rc.x = xm;
261 : rc.y = yM;
262 103 : return rc;
263 : }
264 :
265 103 : static GF_Node *s2b_get_gradient(SWFReader *read, GF_Node *parent, SWFShape *shape, SWFShapeRec *srec)
266 : {
267 : Bool is_radial, has_alpha;
268 : GF_Rect rc;
269 : GF_Matrix2D mx;
270 : u32 i;
271 : MFFloat *keys;
272 : MFColor *values;
273 : GF_FieldInfo info;
274 103 : M_Appearance *app = (M_Appearance *) s2b_new_node(read, TAG_MPEG4_Appearance);
275 103 : gf_node_register((GF_Node *)app, parent);
276 103 : app->material = s2b_new_node(read, TAG_MPEG4_Material2D);
277 103 : gf_node_register(app->material, (GF_Node *)app);
278 103 : ((M_Material2D *)app->material)->filled = 1;
279 :
280 103 : is_radial = (srec->type==0x12) ? 1 : 0;
281 103 : app->texture = s2b_new_node(read, is_radial ? TAG_MPEG4_RadialGradient : TAG_MPEG4_LinearGradient);
282 103 : gf_node_register((GF_Node *) app->texture, (GF_Node *) app);
283 :
284 : /*set keys*/
285 103 : gf_node_get_field_by_name(app->texture, "key", &info);
286 103 : gf_sg_vrml_mf_alloc(info.far_ptr, info.fieldType, srec->nbGrad);
287 103 : keys = (MFFloat *)info.far_ptr;
288 408 : for (i=0; i<srec->nbGrad; i++) {
289 408 : keys->vals[i] = INT2FIX(srec->grad_ratio[i])/255;
290 : }
291 :
292 : /*set colors*/
293 103 : gf_node_get_field_by_name(app->texture, "keyValue", &info);
294 103 : gf_sg_vrml_mf_alloc(info.far_ptr, info.fieldType, srec->nbGrad);
295 103 : values = (MFColor *)info.far_ptr;
296 : has_alpha = 0;
297 408 : for (i=0; i<srec->nbGrad; i++) {
298 816 : values->vals[i] = s2b_get_color(srec->grad_col[i]);
299 816 : if (s2b_get_alpha(srec->grad_col[i]) != FIX_ONE) has_alpha = 1;
300 : }
301 : /*set opacity*/
302 103 : if (has_alpha) {
303 2 : gf_node_get_field_by_name(app->texture, "opacity", &info);
304 2 : gf_sg_vrml_mf_alloc(info.far_ptr, info.fieldType, srec->nbGrad);
305 2 : keys = (MFFloat *)info.far_ptr;
306 6 : for (i=0; i<srec->nbGrad; i++) {
307 12 : keys->vals[i] = s2b_get_alpha(srec->grad_col[i]);
308 : }
309 : /*and remove material !!*/
310 2 : ((M_Material2D *)app->material)->filled = 0;
311 2 : ((M_Material2D *)app->material)->lineProps = s2b_new_node(read, TAG_MPEG4_LineProperties);
312 2 : ((M_LineProperties *)((M_Material2D *)app->material)->lineProps)->width = 0;
313 2 : gf_node_register(((M_Material2D *)app->material)->lineProps, app->material);
314 : }
315 :
316 103 : rc = s2b_get_center_bounds(shape, srec);
317 :
318 : gf_mx2d_init(mx);
319 103 : mx.m[0] = gf_invfix(rc.width);
320 103 : mx.m[2] = - gf_divfix(rc.x, rc.width);
321 103 : mx.m[4] = gf_invfix(rc.height);
322 103 : mx.m[5] = FIX_ONE - gf_divfix(rc.y, rc.height);
323 :
324 103 : gf_mx2d_pre_multiply(&mx, &srec->mat);
325 :
326 : /*define gradient in SWF pixel coordinates*/
327 103 : if (is_radial ) {
328 1 : gf_node_get_field_by_name(app->texture, "center", &info);
329 1 : ((SFVec2f*)info.far_ptr)->x = 0;
330 1 : ((SFVec2f*)info.far_ptr)->y = 0;
331 :
332 1 : gf_node_get_field_by_name(app->texture, "radius", &info);
333 1 : *((SFFloat*)info.far_ptr) = FLT2FIX(819.20);
334 : } else {
335 102 : gf_node_get_field_by_name(app->texture, "startPoint", &info);
336 102 : ((SFVec2f*)info.far_ptr)->x = FLT2FIX(-819.20);
337 :
338 102 : gf_node_get_field_by_name(app->texture, "endPoint", &info);
339 102 : ((SFVec2f*)info.far_ptr)->x = FLT2FIX(819.20);
340 : }
341 :
342 : /*matrix from local coordinates to texture coordiantes (Y-flip for BIFS texture coordinates)*/
343 : gf_mx2d_init(mx);
344 103 : mx.m[0] = gf_invfix(rc.width);
345 103 : mx.m[2] = - gf_divfix(rc.x, rc.width);
346 103 : mx.m[4] = gf_invfix(rc.height);
347 103 : mx.m[5] = FIX_ONE - gf_divfix(rc.y, rc.height);
348 : /*pre-multiply SWF->local coords matrix*/
349 103 : gf_mx2d_pre_multiply(&mx, &srec->mat);
350 :
351 103 : gf_node_get_field_by_name(app->texture, "transform", &info);
352 103 : *((GF_Node **)info.far_ptr) = s2b_get_matrix(read, &mx);
353 103 : gf_node_register(*((GF_Node **)info.far_ptr), app->texture);
354 103 : return (GF_Node *) app;
355 : }
356 :
357 1 : static GF_Node *s2b_get_bitmap(SWFReader *read, GF_Node *parent, SWFShape *shape, SWFShapeRec *srec)
358 : {
359 : GF_Matrix2D mx;
360 : GF_Node *bmp;
361 : GF_FieldInfo info;
362 : M_Appearance *app;
363 : char szDEF[100];
364 :
365 1 : sprintf(szDEF, "Bitmap%d", srec->img_id);
366 1 : bmp = gf_sg_find_node_by_name(read->load->scene_graph, szDEF);
367 1 : if (!bmp) return NULL;
368 1 : app = (M_Appearance *) s2b_new_node(read, TAG_MPEG4_Appearance);
369 1 : gf_node_register((GF_Node *)app, parent);
370 1 : app->material = s2b_new_node(read, TAG_MPEG4_Material2D);
371 1 : gf_node_register(app->material, (GF_Node *)app);
372 1 : ((M_Material2D *)app->material)->filled = 1;
373 :
374 1 : app->texture = bmp;
375 1 : gf_node_register(bmp, (GF_Node *)app);
376 :
377 1 : gf_mx2d_init(mx);
378 1 : gf_mx2d_add_scale(&mx, FIX_ONE, -FIX_ONE);
379 : // gf_mx2d_add_scale(&mx, SWF_TWIP_SCALE, -SWF_TWIP_SCALE);
380 : // gf_mx2d_pre_multiply(&mx, &srec->mat);
381 :
382 1 : gf_node_get_field_by_name((GF_Node*)app, "textureTransform", &info);
383 1 : *((GF_Node **)info.far_ptr) = s2b_get_matrix(read, &mx);
384 1 : gf_node_register(*((GF_Node **)info.far_ptr), (GF_Node*)app);
385 : return (GF_Node *) app;
386 : }
387 :
388 1578 : static void s2b_set_appearance(SWFReader *read, SWFShape *shape, M_Shape *n, SWFShapeRec *srec, Bool is_fill)
389 : {
390 : /*get regular appearance reuse*/
391 1578 : if (is_fill) {
392 1077 : switch (srec->type) {
393 : /*solid/alpha fill*/
394 973 : case 0x00:
395 973 : n->appearance = s2b_get_appearance(read, (GF_Node *) n, srec->solid_col, 0, 0);
396 : break;
397 103 : case 0x10:
398 : case 0x12:
399 103 : if (read->flags & GF_SM_SWF_NO_GRADIENT) {
400 0 : u32 col = srec->grad_col[srec->nbGrad/2];
401 0 : col |= 0xFF000000;
402 0 : n->appearance = s2b_get_appearance(read, (GF_Node *) n, col, 0, 0);
403 : } else {
404 103 : n->appearance = s2b_get_gradient(read, (GF_Node *) n, shape, srec);
405 : }
406 : break;
407 1 : case 0x40:
408 : case 0x41:
409 : case 0x42:
410 : case 0x43:
411 1 : n->appearance = s2b_get_bitmap(read, (GF_Node *) n, shape, srec);
412 : break;
413 0 : default:
414 0 : swf_report(read, GF_NOT_SUPPORTED, "fill_style %x not supported", srec->type);
415 : break;
416 : }
417 : } else {
418 501 : n->appearance = s2b_get_appearance(read, (GF_Node *) n, 0, srec->width, srec->solid_col);
419 : }
420 1578 : }
421 :
422 : /*translate a flash sub shape with only one path (eg one looking style) to a BIFS Shape node*/
423 1578 : static GF_Node *s2b_shape_to_curve2d(SWFReader *read, SWFShape *shape, SWFShapeRec *srec, Bool is_fill, M_Coordinate2D *c)
424 : {
425 : u32 pt_idx, i;
426 : Bool use_xcurve;
427 : void *fptr;
428 : SFVec2f ct1, ct2, ct, pt;
429 : MFInt32 *types, *idx;
430 : M_Coordinate2D *points;
431 : GF_Node *ic2d = NULL;
432 1578 : M_Shape *n = (M_Shape *) s2b_new_node(read, TAG_MPEG4_Shape);
433 :
434 1578 : s2b_set_appearance(read, shape, n, srec, is_fill);
435 :
436 1578 : use_xcurve = (read->flags & GF_SM_SWF_QUAD_CURVE) ? 1 : 0;
437 1578 : if (c) {
438 : GF_FieldInfo info;
439 263 : ic2d = gf_sg_proto_create_instance(read->load->scene_graph, gf_sg_find_proto(read->load->scene_graph, 0, "IndexedCurve2D"));
440 : points = c;
441 :
442 263 : gf_node_get_field_by_name(ic2d, "type", &info);
443 263 : types = (MFInt32 *)info.far_ptr;
444 :
445 263 : gf_node_get_field_by_name(ic2d, "coordIndex", &info);
446 263 : idx = (MFInt32 *)info.far_ptr;
447 :
448 263 : gf_node_get_field_by_name(ic2d, "coord", &info);
449 263 : *(GF_Node **)info.far_ptr = (GF_Node *)c;
450 263 : gf_node_register((GF_Node *)c, ic2d);
451 :
452 263 : n->geometry = ic2d;
453 263 : gf_node_register(ic2d, (GF_Node *)n);
454 : } else {
455 : M_Curve2D *curve;
456 1315 : if (use_xcurve) {
457 405 : curve = (M_Curve2D *) s2b_new_node(read, TAG_MPEG4_XCurve2D);
458 : } else {
459 910 : curve = (M_Curve2D *) s2b_new_node(read, TAG_MPEG4_Curve2D);
460 : }
461 1315 : points = (M_Coordinate2D *) s2b_new_node(read, TAG_MPEG4_Coordinate2D);
462 1315 : curve->point = (GF_Node *) points;
463 :
464 1315 : gf_node_register((GF_Node *) points, (GF_Node *) curve);
465 1315 : curve->fineness = FIX_ONE;
466 1315 : types = &curve->type;
467 : idx = NULL;
468 1315 : n->geometry = (GF_Node *) curve;
469 1315 : gf_node_register((GF_Node *) curve, (GF_Node *)n);
470 : }
471 :
472 :
473 : assert(srec->path->nbType);
474 :
475 : pt_idx = 0;
476 44962 : for (i=0; i<srec->path->nbType; i++) {
477 44962 : switch (srec->path->types[i]) {
478 : /*moveTo*/
479 2933 : case 0:
480 : /*first moveTo implicit in BIFS*/
481 2933 : if (i) {
482 1355 : gf_sg_vrml_mf_append(types, GF_SG_VRML_MFINT32, &fptr);
483 1355 : *((SFInt32 *)fptr) = 0;
484 : }
485 2933 : if (c) {
486 550 : gf_sg_vrml_mf_append(idx, GF_SG_VRML_MFINT32, &fptr);
487 550 : *((SFInt32 *)fptr) = srec->path->idx[pt_idx];
488 : } else {
489 2383 : gf_sg_vrml_mf_append(&points->point, GF_SG_VRML_MFVEC2F, &fptr);
490 2383 : ((SFVec2f *)fptr)->x = srec->path->pts[pt_idx].x;
491 2383 : ((SFVec2f *)fptr)->y = srec->path->pts[pt_idx].y;
492 : }
493 2933 : pt_idx++;
494 : break;
495 : /*lineTo*/
496 32060 : case 1:
497 32060 : gf_sg_vrml_mf_append(types, GF_SG_VRML_MFINT32, &fptr);
498 32060 : *((SFInt32 *)fptr) = 1;
499 32060 : if (c) {
500 4846 : gf_sg_vrml_mf_append(idx, GF_SG_VRML_MFINT32, &fptr);
501 4846 : *((SFInt32 *)fptr) = srec->path->idx[pt_idx];
502 : } else {
503 27214 : gf_sg_vrml_mf_append(&points->point, GF_SG_VRML_MFVEC2F, &fptr);
504 27214 : ((SFVec2f *)fptr)->x = srec->path->pts[pt_idx].x;
505 27214 : ((SFVec2f *)fptr)->y = srec->path->pts[pt_idx].y;
506 : }
507 32060 : pt_idx++;
508 : break;
509 : /*curveTo*/
510 9969 : case 2:
511 : /*XCurve2D has quad arcs*/
512 9969 : if (c || use_xcurve) {
513 4848 : gf_sg_vrml_mf_append(types, GF_SG_VRML_MFINT32, &fptr);
514 4848 : *((SFInt32 *)fptr) = 7;
515 :
516 4848 : if (c) {
517 2080 : gf_sg_vrml_mf_append(idx, GF_SG_VRML_MFINT32, &fptr);
518 2080 : *((SFInt32 *)fptr) = srec->path->idx[pt_idx];
519 2080 : gf_sg_vrml_mf_append(idx, GF_SG_VRML_MFINT32, &fptr);
520 2080 : *((SFInt32 *)fptr) = srec->path->idx[pt_idx+1];
521 : } else {
522 2768 : gf_sg_vrml_mf_append(&points->point, GF_SG_VRML_MFVEC2F, &fptr);
523 2768 : ((SFVec2f *)fptr)->x = srec->path->pts[pt_idx].x;
524 2768 : ((SFVec2f *)fptr)->y = srec->path->pts[pt_idx].y;
525 2768 : gf_sg_vrml_mf_append(&points->point, GF_SG_VRML_MFVEC2F, &fptr);
526 2768 : ((SFVec2f *)fptr)->x = srec->path->pts[pt_idx+1].x;
527 2768 : ((SFVec2f *)fptr)->y = srec->path->pts[pt_idx+1].y;
528 : }
529 :
530 4848 : pt_idx+=2;
531 : } else {
532 5121 : gf_sg_vrml_mf_append(types, GF_SG_VRML_MFINT32, &fptr);
533 5121 : *((SFInt32 *)fptr) = 2;
534 : /*recompute cubic from quad*/
535 5121 : ct.x = srec->path->pts[pt_idx].x;
536 5121 : ct.y = srec->path->pts[pt_idx].y;
537 5121 : pt.x = srec->path->pts[pt_idx-1].x;
538 5121 : pt.y = srec->path->pts[pt_idx-1].y;
539 5121 : ct1.x = pt.x + 2*(ct.x - pt.x)/3;
540 5121 : ct1.y = pt.y + 2*(ct.y - pt.y)/3;
541 5121 : ct.x = srec->path->pts[pt_idx+1].x;
542 5121 : ct.y = srec->path->pts[pt_idx+1].y;
543 5121 : ct2.x = ct1.x + (ct.x - pt.x) / 3;
544 5121 : ct2.y = ct1.y + (ct.y - pt.y) / 3;
545 :
546 5121 : gf_sg_vrml_mf_append(&points->point, GF_SG_VRML_MFVEC2F, &fptr);
547 5121 : ((SFVec2f *)fptr)->x = ct1.x;
548 5121 : ((SFVec2f *)fptr)->y = ct1.y;
549 5121 : gf_sg_vrml_mf_append(&points->point, GF_SG_VRML_MFVEC2F, &fptr);
550 5121 : ((SFVec2f *)fptr)->x = ct2.x;
551 5121 : ((SFVec2f *)fptr)->y = ct2.y;
552 5121 : gf_sg_vrml_mf_append(&points->point, GF_SG_VRML_MFVEC2F, &fptr);
553 5121 : ((SFVec2f *)fptr)->x = ct.x;
554 5121 : ((SFVec2f *)fptr)->y = ct.y;
555 5121 : pt_idx+=2;
556 : }
557 : break;
558 : }
559 : }
560 :
561 1578 : if (ic2d) gf_node_init(ic2d);
562 :
563 1578 : return (GF_Node *) n;
564 : }
565 :
566 48 : static void s2b_merge_curve2d(M_Curve2D *s, M_Curve2D *tomerge)
567 : {
568 : u32 i, pt_idx, j;
569 : SFVec2f pt;
570 : void *ptr;
571 : M_Coordinate2D *dest, *orig;
572 48 : dest = (M_Coordinate2D *) s->point;
573 48 : orig = (M_Coordinate2D *) tomerge->point;
574 :
575 48 : if (!tomerge->type.count) return;
576 48 : if (!orig->point.count) return;
577 48 : pt = orig->point.vals[0];
578 :
579 48 : if (s->type.vals[s->type.count - 1] == 0) {
580 0 : dest->point.vals[dest->point.count - 1] = pt;
581 : } else {
582 48 : gf_sg_vrml_mf_append(&s->type, GF_SG_VRML_MFINT32, &ptr);
583 48 : *((SFInt32 *)ptr) = 0;
584 48 : gf_sg_vrml_mf_append(&dest->point, GF_SG_VRML_MFVEC2F, &ptr);
585 48 : *((SFVec2f *)ptr) = pt;
586 : }
587 :
588 : i = 0;
589 48 : if (tomerge->type.vals[0] == 0) i=1;
590 : pt_idx = 1;
591 :
592 639 : for (; i<tomerge->type.count; i++) {
593 639 : switch (tomerge->type.vals[i]) {
594 14 : case 0:
595 14 : if (s->type.vals[s->type.count - 1] == 0) {
596 0 : dest->point.vals[dest->point.count - 1] = pt;
597 : } else {
598 14 : gf_sg_vrml_mf_append(&s->type, GF_SG_VRML_MFINT32, &ptr);
599 14 : *((SFInt32 *)ptr) = 0;
600 14 : gf_sg_vrml_mf_append(&dest->point, GF_SG_VRML_MFVEC2F, &ptr);
601 14 : *((SFVec2f *)ptr) = orig->point.vals[pt_idx];
602 : }
603 14 : pt_idx++;
604 14 : break;
605 436 : case 1:
606 436 : gf_sg_vrml_mf_append(&s->type, GF_SG_VRML_MFINT32, &ptr);
607 436 : *((SFInt32 *)ptr) = 1;
608 436 : gf_sg_vrml_mf_append(&dest->point, GF_SG_VRML_MFVEC2F, &ptr);
609 436 : *((SFVec2f *)ptr) = orig->point.vals[pt_idx];
610 436 : pt_idx++;
611 436 : break;
612 0 : case 2:
613 0 : gf_sg_vrml_mf_append(&s->type, GF_SG_VRML_MFINT32, &ptr);
614 0 : *((SFInt32 *)ptr) = 2;
615 0 : for (j=0; j<3; j++) {
616 0 : gf_sg_vrml_mf_append(&dest->point, GF_SG_VRML_MFVEC2F, &ptr);
617 0 : *((SFVec2f *)ptr) = orig->point.vals[pt_idx];
618 0 : pt_idx++;
619 : }
620 : break;
621 189 : case 7:
622 189 : gf_sg_vrml_mf_append(&s->type, GF_SG_VRML_MFINT32, &ptr);
623 189 : *((SFInt32 *)ptr) = 7;
624 567 : for (j=0; j<2; j++) {
625 378 : gf_sg_vrml_mf_append(&dest->point, GF_SG_VRML_MFVEC2F, &ptr);
626 378 : *((SFVec2f *)ptr) = orig->point.vals[pt_idx];
627 378 : pt_idx++;
628 : }
629 : break;
630 : }
631 : }
632 : }
633 :
634 1053 : static void s2b_insert_shape(M_OrderedGroup *og, M_Shape *n, Bool is_proto)
635 : {
636 1053 : GF_ChildNodeItem *l = og->children;
637 1053 : if (!is_proto) {
638 2789 : while (l) {
639 2047 : M_Shape *prev = (M_Shape*)l->node;
640 2047 : if (prev->appearance == n->appearance) {
641 48 : s2b_merge_curve2d( (M_Curve2D *)prev->geometry, (M_Curve2D *)n->geometry);
642 48 : gf_node_register((GF_Node *)n, NULL);
643 48 : gf_node_unregister((GF_Node *)n, NULL);
644 48 : return;
645 : }
646 1999 : l = l->next;
647 : }
648 : }
649 1005 : gf_node_insert_child((GF_Node *)og, (GF_Node *)n, -1);
650 1005 : gf_node_register((GF_Node *) n, (GF_Node *) og);
651 : }
652 :
653 263 : static void s2b_insert_rec_in_coord(M_Coordinate2D *c, SWFShapeRec *srec)
654 : {
655 : u32 i, j;
656 263 : srec->path->idx = gf_malloc(sizeof(u32)*srec->path->nbPts);
657 :
658 9556 : for (i=0; i<srec->path->nbPts; i++) {
659 401703 : for (j=0; j<c->point.count; j++) {
660 405397 : if ( (c->point.vals[j].x == srec->path->pts[i].x) && (c->point.vals[j].y == srec->path->pts[i].y)) {
661 : break;
662 : }
663 : }
664 9556 : if (j==c->point.count) {
665 5862 : c->point.count++;
666 5862 : c->point.vals = gf_realloc(c->point.vals, sizeof(SFVec2f)*c->point.count);
667 5862 : c->point.vals[j] = srec->path->pts[i];
668 : }
669 9556 : srec->path->idx[i] = j;
670 : }
671 263 : }
672 :
673 : /*translates flash to BIFS shapes*/
674 1072 : static GF_Err swf_bifs_define_shape(SWFReader *read, SWFShape *shape, SWFFont *parent_font, Bool last_sub_shape)
675 : {
676 : GF_Node *n;
677 : GF_Node *og;
678 : M_Coordinate2D *c;
679 : char szDEF[1024];
680 : u32 ID;
681 : u32 i;
682 : SWFShapeRec *srec;
683 :
684 1072 : og = read->cur_shape;
685 : /*we need a grouping node*/
686 1072 : if (!read->cur_shape) {
687 :
688 : /*empty shape - for fonts, not a mistake, that's likely space char*/
689 880 : if (!shape) {
690 0 : if (!parent_font)
691 : return GF_OK;
692 0 : n = s2b_new_node(read, TAG_MPEG4_Shape);
693 : }
694 : /*direct match, no top group*/
695 880 : else if (last_sub_shape && (gf_list_count(shape->fill_left) + gf_list_count(shape->lines)<=1)) {
696 : Bool is_fill = 1;
697 534 : srec = (SWFShapeRec*)gf_list_get(shape->fill_left, 0);
698 534 : if (!srec) {
699 192 : srec = (SWFShapeRec*)gf_list_get(shape->lines, 0);
700 : is_fill = 0;
701 : }
702 534 : if (!srec) {
703 9 : n = s2b_new_node(read, TAG_MPEG4_Shape);
704 : } else {
705 525 : n = s2b_shape_to_curve2d(read, shape, srec, is_fill, NULL);
706 : }
707 : } else {
708 346 : og = s2b_new_node(read, TAG_MPEG4_OrderedGroup);
709 : n = og;
710 : }
711 : /*register*/
712 :
713 880 : if (n) {
714 880 : if (parent_font) {
715 224 : gf_list_add(parent_font->glyphs, n);
716 224 : gf_node_register(n, NULL);
717 : } else {
718 656 : sprintf(szDEF, "Shape%d", shape->ID);
719 656 : read->load->ctx->max_node_id++;
720 656 : ID = read->load->ctx->max_node_id;
721 656 : gf_node_set_id(n, ID, szDEF);
722 :
723 656 : s2b_insert_symbol(read, n);
724 : }
725 : }
726 880 : if (!og) return GF_OK;
727 : }
728 :
729 : c = NULL;
730 538 : if (read->flags & GF_SM_SWF_USE_IC2D) {
731 167 : c = (M_Coordinate2D *)gf_node_new(read->load->scene_graph, TAG_MPEG4_Coordinate2D);
732 167 : sprintf(szDEF, "ShapePts%d", shape->ID);
733 167 : read->load->ctx->max_node_id++;
734 167 : ID = read->load->ctx->max_node_id;
735 167 : gf_node_set_id((GF_Node*)c, ID, szDEF);
736 : }
737 :
738 538 : i=0;
739 1811 : while ((srec = (SWFShapeRec*)gf_list_enum(shape->fill_left, &i))) {
740 735 : if (c)
741 168 : s2b_insert_rec_in_coord(c, srec);
742 :
743 735 : n = s2b_shape_to_curve2d(read, shape, srec, 1, c);
744 735 : if (n) s2b_insert_shape((M_OrderedGroup*)og, (M_Shape *)n, c ? 1 : 0);
745 : }
746 538 : i=0;
747 1394 : while ((srec = (SWFShapeRec*)gf_list_enum(shape->lines, &i))) {
748 318 : if (c)
749 95 : s2b_insert_rec_in_coord(c, srec);
750 :
751 318 : n = s2b_shape_to_curve2d(read, shape, srec, 0, c);
752 318 : if (n) s2b_insert_shape((M_OrderedGroup*)og, (M_Shape *)n, c ? 1 : 0);
753 : }
754 :
755 538 : if (last_sub_shape) read->cur_shape = NULL;
756 192 : else read->cur_shape = og;
757 : return GF_OK;
758 : }
759 :
760 :
761 1015 : static GF_Node *s2b_get_glyph(SWFReader *read, u32 fontID, u32 gl_index, GF_Node *par)
762 : {
763 : char szDEF[1024];
764 : u32 ID;
765 : GF_Node *n, *glyph;
766 : SWFFont *ft;
767 :
768 : sprintf(szDEF, "FT%d_GL%d", fontID, gl_index);
769 1015 : n = gf_sg_find_node_by_name(read->load->scene_graph, szDEF);
770 1015 : if (n) {
771 642 : gf_node_register(n, par);
772 642 : return n;
773 : }
774 :
775 : /*first use of glyph in file*/
776 373 : ft = swf_find_font(read, fontID);
777 373 : if (!ft) {
778 0 : swf_report(read, GF_BAD_PARAM, "Cannot find font %d - skipping glyph", fontID);
779 0 : return NULL;
780 : }
781 373 : if (ft->nbGlyphs <= gl_index) {
782 0 : swf_report(read, GF_BAD_PARAM, "Glyph #%d not found in font %d - skipping", gl_index, fontID);
783 0 : return NULL;
784 : }
785 373 : n = (GF_Node*)gf_list_get(ft->glyphs, gl_index);
786 373 : if (gf_node_get_tag(n) != TAG_MPEG4_Shape) {
787 0 : swf_report(read, GF_BAD_PARAM, "Glyph #%d in font %d not a shape (translated in %s) - skipping", gl_index, fontID, gf_node_get_class_name(n));
788 0 : return NULL;
789 : }
790 373 : glyph = ((M_Shape *)n)->geometry;
791 : /*space*/
792 373 : if (!glyph) return NULL;
793 :
794 214 : read->load->ctx->max_node_id++;
795 214 : ID = read->load->ctx->max_node_id;
796 214 : gf_node_set_id(glyph, ID, szDEF);
797 214 : gf_node_register(glyph, par);
798 :
799 : /*also insert glyph*/
800 214 : s2b_insert_symbol(read, n);
801 :
802 214 : return glyph;
803 : }
804 :
805 45 : static GF_Err swf_bifs_define_text(SWFReader *read, SWFText *text)
806 : {
807 : u32 i, j;
808 : Bool use_text;
809 : Fixed dx;
810 : SWFGlyphRec *gr;
811 : SWFFont *ft;
812 : M_Transform2D *par, *gl_par;
813 : M_Shape *gl;
814 : M_TransformMatrix2D *tr;
815 :
816 45 : use_text = (read->flags & GF_SM_SWF_NO_FONT) ? 1 : 0;
817 45 : tr = (M_TransformMatrix2D *) s2b_new_node(read, TAG_MPEG4_TransformMatrix2D);
818 45 : tr->mxx = text->mat.m[0];
819 45 : tr->mxy = text->mat.m[1];
820 45 : tr->tx = text->mat.m[2];
821 45 : tr->myx = text->mat.m[3];
822 45 : tr->myy = text->mat.m[4];
823 45 : tr->ty = text->mat.m[5];
824 :
825 :
826 45 : i=0;
827 144 : while ((gr = (SWFGlyphRec*)gf_list_enum(text->text, &i))) {
828 54 : par = (M_Transform2D *) s2b_new_node(read, TAG_MPEG4_Transform2D);
829 54 : par->translation.x = gr->orig_x;
830 54 : par->translation.y = gr->orig_y;
831 :
832 : ft = NULL;
833 54 : if (use_text) {
834 0 : ft = swf_find_font(read, gr->fontID);
835 0 : if (!ft->glyph_codes) {
836 : use_text = 0;
837 0 : swf_report(read, GF_BAD_PARAM, "Font glyphs are not defined, cannot reference extern font - Forcing glyph embedding");
838 : }
839 : }
840 :
841 54 : if (!use_text) {
842 54 : par->scale.y = par->scale.x = FLT2FIX(gr->fontSize * SWF_TEXT_SCALE);
843 : } else {
844 : /*don't forget we're flipped at top level...*/
845 0 : par->scale.y = -FIX_ONE;
846 : }
847 54 : gf_node_insert_child((GF_Node *)tr, (GF_Node *) par, -1);
848 54 : gf_node_register((GF_Node *) par, (GF_Node *)tr);
849 :
850 54 : if (use_text) {
851 : size_t _len;
852 : u16 *str_w, *widestr;
853 : char *str;
854 : void *ptr;
855 0 : M_Text *t = (M_Text *) s2b_new_node(read, TAG_MPEG4_Text);
856 0 : M_FontStyle *f = (M_FontStyle *) s2b_new_node(read, TAG_MPEG4_FontStyle);
857 0 : t->fontStyle = (GF_Node *) f;
858 0 : gf_node_register(t->fontStyle, (GF_Node *) t);
859 :
860 : /*restore back the font height in pixels (it's currently in SWF glyph design units)*/
861 0 : f->size = FLT2FIX(gr->fontSize * SWF_TWIP_SCALE);
862 :
863 0 : if (ft->fontName) {
864 0 : gf_sg_vrml_mf_reset(&f->family, GF_SG_VRML_MFSTRING);
865 0 : gf_sg_vrml_mf_append(&f->family, GF_SG_VRML_MFSTRING, &ptr);
866 0 : ((SFString*)ptr)->buffer = gf_strdup(ft->fontName);
867 : }
868 0 : gf_sg_vrml_mf_reset(&f->justify, GF_SG_VRML_MFSTRING);
869 0 : gf_sg_vrml_mf_append(&f->justify, GF_SG_VRML_MFSTRING, &ptr);
870 0 : ((SFString*)ptr)->buffer = gf_strdup("BEGIN");
871 :
872 0 : if (f->style.buffer) gf_free(f->style.buffer);
873 0 : if (ft->is_italic && ft->is_bold) f->style.buffer = gf_strdup("BOLDITALIC");
874 0 : else if (ft->is_bold) f->style.buffer = gf_strdup("BOLD");
875 0 : else if (ft->is_italic) f->style.buffer = gf_strdup("ITALIC");
876 0 : else f->style.buffer = gf_strdup("PLAIN");
877 :
878 : /*convert to UTF-8*/
879 0 : str_w = (u16*)gf_malloc(sizeof(u16) * (gr->nbGlyphs+1));
880 0 : for (j=0; j<gr->nbGlyphs; j++) str_w[j] = ft->glyph_codes[gr->indexes[j]];
881 0 : str_w[j] = 0;
882 0 : str = (char*)gf_malloc(sizeof(char) * (gr->nbGlyphs+2));
883 0 : widestr = str_w;
884 0 : _len = gf_utf8_wcstombs(str, sizeof(u8) * (gr->nbGlyphs+1), (const unsigned short **) &widestr);
885 0 : if (_len != (size_t) -1) {
886 0 : j=(u32) _len;
887 0 : str[j] = 0;
888 0 : gf_sg_vrml_mf_reset(&t->string, GF_SG_VRML_MFSTRING);
889 0 : gf_sg_vrml_mf_append(&t->string, GF_SG_VRML_MFSTRING, &ptr);
890 0 : ((SFString*)ptr)->buffer = (char*)gf_malloc(sizeof(char) * (j+1));
891 0 : memcpy(((SFString*)ptr)->buffer, str, sizeof(char) * (j+1));
892 : }
893 :
894 0 : gf_free(str);
895 0 : gf_free(str_w);
896 :
897 0 : gl = (M_Shape *) s2b_new_node(read, TAG_MPEG4_Shape);
898 0 : gl->appearance = s2b_get_appearance(read, (GF_Node *) gl, gr->col, 0, 0);
899 0 : gl->geometry = (GF_Node *) t;
900 0 : gf_node_register(gl->geometry, (GF_Node *) gl);
901 0 : gf_node_insert_child((GF_Node *) par, (GF_Node *)gl, -1);
902 0 : gf_node_register((GF_Node *) gl, (GF_Node *) par);
903 : } else {
904 :
905 : /*convert glyphs*/
906 : dx = 0;
907 1015 : for (j=0; j<gr->nbGlyphs; j++) {
908 1015 : gl = (M_Shape *) s2b_new_node(read, TAG_MPEG4_Shape);
909 1015 : gl->geometry = s2b_get_glyph(read, gr->fontID, gr->indexes[j], (GF_Node *) gl);
910 :
911 1015 : if (!gl->geometry) {
912 159 : gf_node_register((GF_Node *) gl, NULL);
913 159 : gf_node_unregister((GF_Node *) gl, NULL);
914 159 : dx += gr->dx[j];
915 159 : continue;
916 : }
917 : assert((gf_node_get_tag(gl->geometry)==TAG_MPEG4_Curve2D) || (gf_node_get_tag(gl->geometry)==TAG_MPEG4_XCurve2D));
918 :
919 856 : gl_par = (M_Transform2D *) s2b_new_node(read, TAG_MPEG4_Transform2D);
920 856 : gl->appearance = s2b_get_appearance(read, (GF_Node *) gl, gr->col, 0, 0);
921 :
922 856 : gl_par->translation.x = gf_divfix(dx, FLT2FIX(gr->fontSize * SWF_TEXT_SCALE) );
923 856 : dx += gr->dx[j];
924 :
925 856 : gf_node_insert_child((GF_Node *) gl_par, (GF_Node *)gl, -1);
926 856 : gf_node_register((GF_Node *) gl, (GF_Node *) gl_par);
927 856 : gf_node_insert_child((GF_Node *) par, (GF_Node *)gl_par, -1);
928 856 : gf_node_register((GF_Node *) gl_par, (GF_Node *) par);
929 : }
930 : }
931 : }
932 :
933 : if (tr) {
934 : char szDEF[1024];
935 : u32 ID;
936 45 : sprintf(szDEF, "Text%d", text->ID);
937 45 : read->load->ctx->max_node_id++;
938 45 : ID = read->load->ctx->max_node_id;
939 45 : gf_node_set_id((GF_Node *)tr, ID, szDEF);
940 45 : s2b_insert_symbol(read, (GF_Node *)tr);
941 : }
942 45 : return GF_OK;
943 : }
944 :
945 :
946 : typedef struct
947 : {
948 : char *final;
949 : u32 len;
950 : } SWFFlatText;
951 :
952 0 : static void swf_nstart(void *sax_cbck, const char *node_name, const char *name_space, const GF_XMLAttribute *attributes, u32 nb_attributes)
953 : {
954 0 : }
955 0 : static void swf_nend(void *sax_cbck, const char *node_name, const char *name_space)
956 : {
957 0 : }
958 0 : static void swf_ntext(void *sax_cbck, const char *content, Bool is_cdata)
959 : {
960 : u32 len;
961 : SWFFlatText *t;
962 0 : if (!content || is_cdata || !sax_cbck) return;
963 : t = (SWFFlatText *)sax_cbck;
964 0 : len = (u32) strlen(content);
965 0 : if (!len) return;
966 0 : t->final = gf_realloc(t->final, sizeof(char)*(t->len+len+1));
967 0 : t->final [t->len] = 0;
968 0 : strcat(t->final, content);
969 0 : t->len = (u32) strlen(t->final)+1;
970 : }
971 :
972 :
973 2 : static GF_Err swf_bifs_define_edit_text(SWFReader *read, SWFEditText *text)
974 : {
975 : char styles[1024];
976 : char *ptr;
977 : Bool use_layout;
978 : M_Layout *layout = NULL;
979 : M_Shape *txt;
980 : M_Text *t;
981 : M_FontStyle *f;
982 : M_Transform2D *tr;
983 :
984 2 : tr = (M_Transform2D *) s2b_new_node(read, TAG_MPEG4_Transform2D);
985 2 : tr->scale.y = -FIX_ONE;
986 :
987 : use_layout = 0;
988 2 : if (text->align==3) use_layout = 1;
989 2 : else if (text->multiline) use_layout = 1;
990 :
991 : if (use_layout) {
992 0 : layout = (M_Layout *) s2b_new_node(read, TAG_MPEG4_Layout);
993 0 : tr->translation.x = read->width/2;
994 0 : tr->translation.y = read->height/2;
995 : }
996 :
997 2 : t = (M_Text *) s2b_new_node(read, TAG_MPEG4_Text);
998 2 : f = (M_FontStyle *) s2b_new_node(read, TAG_MPEG4_FontStyle);
999 2 : t->fontStyle = (GF_Node *) f;
1000 2 : gf_node_register(t->fontStyle, (GF_Node *) t);
1001 :
1002 : /*restore back the font height in pixels (it's currently in SWF glyph design units)*/
1003 2 : f->size = text->font_height;
1004 2 : f->spacing = text->font_height + text->leading;
1005 :
1006 2 : gf_sg_vrml_mf_reset(&f->justify, GF_SG_VRML_MFSTRING);
1007 2 : gf_sg_vrml_mf_append(&f->justify, GF_SG_VRML_MFSTRING, (void**)&ptr);
1008 2 : switch (text->align) {
1009 1 : case 0:
1010 1 : ((SFString*)ptr)->buffer = gf_strdup("BEGIN");
1011 1 : break;
1012 0 : case 1:
1013 0 : ((SFString*)ptr)->buffer = gf_strdup("END");
1014 0 : break;
1015 0 : case 3:
1016 0 : ((SFString*)ptr)->buffer = gf_strdup("JUSTIFY");
1017 0 : break;
1018 1 : default:
1019 1 : ((SFString*)ptr)->buffer = gf_strdup("MIDDLE");
1020 1 : break;
1021 : }
1022 :
1023 : strcpy(styles, "");
1024 2 : if (!text->read_only) strcat(styles, "EDITABLE");
1025 2 : if (text->password) strcat(styles, "PASSWORD");
1026 :
1027 2 : if (f->style.buffer) gf_free(f->style.buffer);
1028 2 : f->style.buffer = gf_strdup(styles);
1029 :
1030 2 : if (text->init_value) {
1031 2 : gf_sg_vrml_mf_reset(&t->string, GF_SG_VRML_MFSTRING);
1032 2 : gf_sg_vrml_mf_append(&t->string, GF_SG_VRML_MFSTRING, (void**)&ptr);
1033 :
1034 2 : if (text->html) {
1035 : GF_SAXParser *xml;
1036 : SWFFlatText flat;
1037 0 : flat.final = 0;
1038 0 : flat.len = 0;
1039 0 : xml = gf_xml_sax_new(swf_nstart, swf_nend, swf_ntext, &flat);
1040 0 : gf_xml_sax_init(xml, NULL);
1041 0 : gf_xml_sax_parse(xml, text->init_value);
1042 0 : gf_xml_sax_del(xml);
1043 :
1044 0 : if (flat.final) {
1045 0 : ((SFString*)ptr)->buffer = gf_strdup(flat.final);
1046 0 : gf_free(flat.final);
1047 : }
1048 : } else {
1049 2 : ((SFString*)ptr)->buffer = gf_strdup(text->init_value);
1050 : }
1051 : }
1052 :
1053 :
1054 2 : txt = (M_Shape *) s2b_new_node(read, TAG_MPEG4_Shape);
1055 2 : txt->appearance = s2b_get_appearance(read, (GF_Node *) txt, text->color, 0, 0);
1056 2 : txt->geometry = (GF_Node *) t;
1057 2 : gf_node_register(txt->geometry, (GF_Node *) txt);
1058 :
1059 2 : if (layout) {
1060 0 : gf_sg_vrml_mf_reset(&layout->justify, GF_SG_VRML_MFSTRING);
1061 0 : gf_sg_vrml_mf_append(&layout->justify, GF_SG_VRML_MFSTRING, NULL);
1062 0 : switch (text->align) {
1063 0 : case 0:
1064 0 : layout->justify.vals[0] = gf_strdup("BEGIN");
1065 0 : break;
1066 0 : case 1:
1067 0 : layout->justify.vals[0] = gf_strdup("END");
1068 0 : break;
1069 0 : case 3:
1070 0 : layout->justify.vals[0] = gf_strdup("JUSTIFY");
1071 0 : break;
1072 0 : default:
1073 0 : layout->justify.vals[0] = gf_strdup("MIDDLE");
1074 0 : break;
1075 : }
1076 0 : if (text->multiline || text->word_wrap) layout->wrap = 1;
1077 :
1078 0 : gf_node_insert_child((GF_Node *) layout, (GF_Node *)txt, -1);
1079 0 : gf_node_register((GF_Node *) txt, (GF_Node *) layout);
1080 :
1081 0 : gf_node_insert_child((GF_Node *) tr, (GF_Node *)layout, -1);
1082 0 : gf_node_register((GF_Node *) layout, (GF_Node *) tr);
1083 : } else {
1084 2 : gf_node_insert_child((GF_Node *) tr, (GF_Node *)txt, -1);
1085 2 : gf_node_register((GF_Node *) txt, (GF_Node *) tr);
1086 : }
1087 : if (tr) {
1088 : char szDEF[1024];
1089 : u32 ID;
1090 2 : sprintf(szDEF, "Text%d", text->ID);
1091 2 : read->load->ctx->max_node_id++;
1092 2 : ID = read->load->ctx->max_node_id;
1093 2 : gf_node_set_id((GF_Node*)tr, ID, szDEF);
1094 2 : s2b_insert_symbol(read, (GF_Node*)tr);
1095 : }
1096 2 : return GF_OK;
1097 : }
1098 :
1099 :
1100 : /*called upon end of sprite or clip*/
1101 : static void swf_bifs_end_of_clip(SWFReader *read)
1102 : {
1103 : #if 0
1104 : char szDEF[1024];
1105 : u32 i;
1106 : GF_AUContext *au;
1107 : GF_Command *com;
1108 : GF_CommandField *f;
1109 : GF_Node *empty;
1110 :
1111 : empty = gf_sg_find_node_by_name(read->load->scene_graph, "Shape0");
1112 :
1113 : au = gf_list_get(read->bifs_es->AUs, 0);
1114 : for (i=0; i<read->max_depth; i++) {
1115 : /*and write command*/
1116 : com = gf_sg_command_new(read->load->scene_graph, GF_SG_INDEXED_REPLACE);
1117 : sprintf(szDEF, "CLIP%d_DL", read->current_sprite_id);
1118 : com->node = gf_sg_find_node_by_name(read->load->scene_graph, szDEF);
1119 :
1120 : gf_node_register(com->node, NULL);
1121 : f = gf_sg_command_field_new(com);
1122 : f->field_ptr = &f->new_node;
1123 : f->fieldType = GF_SG_VRML_SFNODE;
1124 : f->pos = i;
1125 : f->fieldIndex = 2; /*children index*/
1126 : f->new_node = empty;
1127 : gf_node_register(f->new_node, com->node);
1128 :
1129 : gf_list_insert(au->commands, com, i);
1130 : }
1131 : #endif
1132 :
1133 : }
1134 :
1135 3141 : static Bool swf_bifs_allocate_depth(SWFReader *read, u32 depth)
1136 : {
1137 : char szDEF[100];
1138 : GF_Node *disp, *empty;
1139 3141 : if (read->max_depth > depth) return 1;
1140 :
1141 81 : sprintf(szDEF, "CLIP%d_DL", read->current_sprite_id);
1142 81 : disp = gf_sg_find_node_by_name(read->load->scene_graph, szDEF);
1143 :
1144 81 : empty = gf_sg_find_node_by_name(read->load->scene_graph, "Shape0");
1145 403 : while (read->max_depth<=depth) {
1146 241 : gf_node_insert_child(disp, empty, -1);
1147 241 : gf_node_register(empty, disp);
1148 241 : read->max_depth++;
1149 : }
1150 : return 0;
1151 : }
1152 :
1153 24 : static GF_Err swf_init_od(SWFReader *read, Bool root_only)
1154 : {
1155 : GF_ESD *esd;
1156 :
1157 24 : if (!read->load->ctx->root_od) {
1158 : GF_BIFSConfig *bc;
1159 7 : read->load->ctx->root_od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_IOD_TAG);
1160 : /*add BIFS stream*/
1161 7 : esd = (GF_ESD *) gf_odf_desc_esd_new(0);
1162 7 : if (!esd) return GF_OUT_OF_MEM;
1163 7 : esd->decoderConfig->streamType = GF_STREAM_SCENE;
1164 7 : esd->decoderConfig->objectTypeIndication = GF_CODECID_BIFS;
1165 7 : esd->slConfig->timestampResolution = read->bifs_es->timeScale;
1166 7 : esd->ESID = 1;
1167 7 : gf_list_add(read->load->ctx->root_od->ESDescriptors, esd);
1168 7 : read->load->ctx->root_od->objectDescriptorID = 1;
1169 7 : gf_odf_desc_del((GF_Descriptor *) esd->decoderConfig->decoderSpecificInfo);
1170 7 : bc = (GF_BIFSConfig *) gf_odf_desc_new(GF_ODF_BIFS_CFG_TAG);
1171 7 : bc->pixelMetrics = 1;
1172 7 : bc->pixelWidth = (u16) read->width;
1173 7 : bc->pixelHeight = (u16) read->height;
1174 7 : esd->decoderConfig->decoderSpecificInfo = (GF_DefaultDescriptor *) bc;
1175 : }
1176 24 : if (!read->load->ctx->root_od) return GF_OUT_OF_MEM;
1177 24 : if (root_only) return GF_OK;
1178 :
1179 17 : if (read->od_es) return GF_OK;
1180 5 : read->od_es = gf_sm_stream_new(read->load->ctx, 2, GF_STREAM_OD, GF_CODECID_OD_V1);
1181 5 : if (!read->od_es) return GF_OUT_OF_MEM;
1182 :
1183 5 : esd = (GF_ESD *) gf_odf_desc_esd_new(0);
1184 5 : if (!esd) return GF_OUT_OF_MEM;
1185 5 : esd->decoderConfig->streamType = GF_STREAM_OD;
1186 5 : esd->decoderConfig->objectTypeIndication = GF_CODECID_BIFS;
1187 5 : esd->slConfig->timestampResolution = read->od_es->timeScale = read->bifs_es->timeScale;
1188 5 : esd->ESID = 2;
1189 5 : esd->OCRESID = 1;
1190 5 : gf_odf_desc_del((GF_Descriptor *) esd->decoderConfig->decoderSpecificInfo);
1191 5 : esd->decoderConfig->decoderSpecificInfo = NULL;
1192 5 : return gf_list_add(read->load->ctx->root_od->ESDescriptors, esd);
1193 : }
1194 :
1195 17 : static GF_Err swf_insert_od(SWFReader *read, u32 at_time, GF_ObjectDescriptor *od)
1196 : {
1197 : u32 i;
1198 : GF_ODUpdate *com;
1199 17 : read->od_au = gf_sm_stream_au_new(read->od_es, at_time, 0, 1);
1200 17 : if (!read->od_au) return GF_OUT_OF_MEM;
1201 :
1202 17 : i=0;
1203 17 : while ((com = (GF_ODUpdate *)gf_list_enum(read->od_au->commands, &i))) {
1204 12 : if (com->tag == GF_ODF_OD_UPDATE_TAG) {
1205 12 : gf_list_add(com->objectDescriptors, od);
1206 : return GF_OK;
1207 : }
1208 : }
1209 5 : com = (GF_ODUpdate *) gf_odf_com_new(GF_ODF_OD_UPDATE_TAG);
1210 5 : gf_list_add(com->objectDescriptors, od);
1211 5 : return gf_list_add(read->od_au->commands, com);
1212 : }
1213 :
1214 : static u16 swf_get_od_id(SWFReader *read)
1215 : {
1216 12 : return ++read->prev_od_id;
1217 : }
1218 :
1219 : static u16 swf_get_es_id(SWFReader *read)
1220 : {
1221 12 : return ++read->prev_es_id;
1222 : }
1223 :
1224 :
1225 9 : static GF_Err swf_bifs_define_sprite(SWFReader *read, u32 nb_frames)
1226 : {
1227 : GF_Err e;
1228 : GF_ObjectDescriptor *od;
1229 : GF_ESD *esd;
1230 : u32 ID;
1231 : GF_Node *n, *par;
1232 : GF_FieldInfo info;
1233 : char szDEF[100];
1234 : GF_StreamContext *prev_sc;
1235 : GF_AUContext *prev_au;
1236 :
1237 : /*init OD*/
1238 9 : e = swf_init_od(read, 0);
1239 9 : if (e) return e;
1240 :
1241 : /*create animationStream object*/
1242 9 : od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG);
1243 9 : if (!od) return GF_OUT_OF_MEM;
1244 :
1245 9 : od->objectDescriptorID = swf_get_od_id(read);
1246 9 : esd = (GF_ESD *) gf_odf_desc_esd_new(0);
1247 9 : if (!esd) return GF_OUT_OF_MEM;
1248 9 : esd->ESID = swf_get_es_id(read);
1249 : /*sprite runs on its own timeline*/
1250 9 : esd->OCRESID = esd->ESID;
1251 : /*always depends on main scene*/
1252 9 : esd->dependsOnESID = 1;
1253 9 : esd->decoderConfig->streamType = GF_STREAM_SCENE;
1254 9 : esd->decoderConfig->objectTypeIndication = GF_CODECID_BIFS;
1255 9 : esd->slConfig->timestampResolution = read->bifs_es->timeScale;
1256 9 : gf_odf_desc_del((GF_Descriptor *) esd->decoderConfig->decoderSpecificInfo);
1257 9 : esd->decoderConfig->decoderSpecificInfo = NULL;
1258 9 : gf_list_add(od->ESDescriptors, esd);
1259 :
1260 : /*by default insert OD at beginning*/
1261 9 : e = swf_insert_od(read, 0, od);
1262 9 : if (e) {
1263 0 : gf_odf_desc_del((GF_Descriptor *) od);
1264 0 : return e;
1265 : }
1266 :
1267 : /*create AS for sprite - all AS are created in initial scene replace*/
1268 9 : n = s2b_new_node(read, TAG_MPEG4_AnimationStream);
1269 9 : gf_node_insert_child(read->root, n, 0);
1270 9 : gf_node_register(n, read->root);
1271 : /*assign URL*/
1272 9 : gf_node_get_field_by_name(n, "url", &info);
1273 9 : gf_sg_vrml_mf_alloc(info.far_ptr, info.fieldType, 1);
1274 9 : ((MFURL*)info.far_ptr)->vals[0].OD_ID = od->objectDescriptorID;
1275 9 : ((M_AnimationStream *)n)->startTime = 0;
1276 :
1277 9 : n = s2b_new_node(read, TAG_MPEG4_MediaControl);
1278 9 : sprintf(szDEF, "CLIP%d_CTRL", read->current_sprite_id);
1279 9 : read->load->ctx->max_node_id++;
1280 9 : ID = read->load->ctx->max_node_id;
1281 9 : gf_node_set_id(n, ID, szDEF);
1282 :
1283 9 : gf_node_insert_child(read->root, n, 0);
1284 9 : gf_node_register(n, read->root);
1285 : /*assign URL*/
1286 9 : gf_node_get_field_by_name(n, "url", &info);
1287 9 : gf_sg_vrml_mf_alloc(info.far_ptr, info.fieldType, 1);
1288 9 : ((MFURL*)info.far_ptr)->vals[0].OD_ID = od->objectDescriptorID;
1289 : /*inactive by default (until inserted)*/
1290 9 : ((M_MediaControl *)n)->mediaSpeed = 0;
1291 9 : ((M_MediaControl *)n)->loop = 1;
1292 :
1293 : /*create sprite grouping node*/
1294 9 : n = s2b_new_node(read, TAG_MPEG4_Group);
1295 9 : sprintf(szDEF, "CLIP%d_DL", read->current_sprite_id);
1296 :
1297 9 : read->load->ctx->max_node_id++;
1298 9 : ID = read->load->ctx->max_node_id;
1299 9 : gf_node_set_id(n, ID, szDEF);
1300 9 : par = gf_sg_find_node_by_name(read->load->scene_graph, "DICTIONARY");
1301 : assert(par);
1302 9 : gf_node_list_add_child(&((M_Switch *)par)->choice, n);
1303 9 : gf_node_register(n, par);
1304 9 : par = gf_sg_find_node_by_name(read->load->scene_graph, "Shape0");
1305 9 : gf_node_insert_child(n, par, -1);
1306 9 : gf_node_register(par, n);
1307 :
1308 : /*store BIFS context*/
1309 9 : prev_sc = read->bifs_es;
1310 9 : prev_au = read->bifs_au;
1311 : /*create new BIFS stream*/
1312 9 : read->bifs_es = gf_sm_stream_new(read->load->ctx, esd->ESID, GF_STREAM_SCENE, GF_CODECID_BIFS);
1313 9 : read->bifs_es->timeScale = prev_sc->timeScale;
1314 9 : read->bifs_es->imp_exp_time = prev_sc->imp_exp_time + prev_au->timing;
1315 :
1316 : /*create first AU*/
1317 9 : read->bifs_au = gf_sm_stream_au_new(read->bifs_es, 0, 0, 1);
1318 :
1319 9 : e = swf_parse_sprite(read);
1320 9 : if (e) return e;
1321 :
1322 : swf_bifs_end_of_clip(read);
1323 :
1324 : /*restore BIFS context*/
1325 9 : read->bifs_es = prev_sc;
1326 9 : read->bifs_au = prev_au;
1327 :
1328 9 : return GF_OK;
1329 : }
1330 :
1331 3 : static GF_Err swf_bifs_setup_sound(SWFReader *read, SWFSound *snd, Bool soundstream_first_block)
1332 : {
1333 : GF_Err e;
1334 : GF_ObjectDescriptor *od;
1335 : GF_ESD *esd;
1336 : GF_MuxInfo *mux;
1337 : GF_Node *n, *par;
1338 : GF_FieldInfo info;
1339 : u32 ID;
1340 : char szDEF[100];
1341 :
1342 : /*soundstream header, only declare the associated MediaControl node for later actions*/
1343 3 : if (!snd->ID && !soundstream_first_block) {
1344 1 : n = s2b_new_node(read, TAG_MPEG4_MediaControl);
1345 1 : sprintf(szDEF, "CLIP%d_SND", read->current_sprite_id);
1346 1 : read->load->ctx->max_node_id++;
1347 1 : ID = read->load->ctx->max_node_id;
1348 1 : gf_node_set_id(n, ID, szDEF);
1349 :
1350 1 : gf_node_insert_child(read->root, n, 0);
1351 1 : gf_node_register(n, read->root);
1352 1 : return GF_OK;
1353 : }
1354 :
1355 2 : e = swf_init_od(read, 0);
1356 2 : if (e) return e;
1357 :
1358 : /*create audio object*/
1359 2 : od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG);
1360 2 : if (!od) return GF_OUT_OF_MEM;
1361 2 : od->objectDescriptorID = swf_get_od_id(read);
1362 2 : esd = (GF_ESD *) gf_odf_desc_new(GF_ODF_ESD_TAG);
1363 2 : if (!esd) return GF_OUT_OF_MEM;
1364 2 : esd->ESID = swf_get_es_id(read);
1365 2 : if (snd->ID) {
1366 : /*sound runs on its own timeline*/
1367 1 : esd->OCRESID = esd->ESID;
1368 : } else {
1369 : /*soundstream runs on movie/sprite timeline*/
1370 1 : esd->OCRESID = read->bifs_es ? read->bifs_es->ESID : esd->ESID;
1371 : }
1372 2 : gf_list_add(od->ESDescriptors, esd);
1373 :
1374 : /*setup mux info*/
1375 2 : mux = (GF_MuxInfo*)gf_odf_desc_new(GF_ODF_MUXINFO_TAG);
1376 2 : mux->file_name = gf_strdup(snd->szFileName);
1377 : // mux->startTime = snd->frame_delay_ms;
1378 2 : mux->startTime = 0;
1379 : /*MP3 in, destroy file once done*/
1380 2 : if (snd->format==2) mux->delete_file = 1;
1381 2 : gf_list_add(esd->extensionDescriptors, mux);
1382 :
1383 :
1384 : /*by default insert OD at beginning*/
1385 2 : e = swf_insert_od(read, 0, od);
1386 2 : if (e) {
1387 0 : gf_odf_desc_del((GF_Descriptor *) od);
1388 0 : return e;
1389 : }
1390 : /*create sound & audio clip*/
1391 2 : n = s2b_new_node(read, TAG_MPEG4_Sound2D);
1392 2 : gf_node_insert_child(read->root, n, 0);
1393 2 : gf_node_register(n, read->root);
1394 : par = n;
1395 2 : n = s2b_new_node(read, TAG_MPEG4_AudioClip);
1396 2 : ((M_Sound2D *)par)->source = n;
1397 2 : gf_node_register(n, par);
1398 : /*assign URL*/
1399 2 : gf_node_get_field_by_name(n, "url", &info);
1400 2 : gf_sg_vrml_mf_alloc(info.far_ptr, info.fieldType, 1);
1401 2 : ((MFURL *)info.far_ptr)->vals[0].OD_ID = od->objectDescriptorID;
1402 :
1403 2 : ((M_AudioClip*)n)->startTime = -1.0;
1404 :
1405 : /*regular sound: set an ID to do play/stop*/
1406 2 : if (snd->ID) {
1407 : sprintf(szDEF, "Sound%d", snd->ID);
1408 1 : read->load->ctx->max_node_id++;
1409 1 : ID = read->load->ctx->max_node_id;
1410 1 : gf_node_set_id(n, ID, szDEF);
1411 : }
1412 : /*soundStream - add a MediaControl*/
1413 : else {
1414 : /*if sprite always have the media active but controled by its mediaControl*/
1415 1 : if (read->current_sprite_id) {
1416 0 : ((M_AudioClip*)n)->startTime = 0;
1417 : }
1418 : /*otherwise start the media at the first soundstream block*/
1419 : else {
1420 1 : ((M_AudioClip*)n)->startTime = snd->frame_delay_ms/1000.0;
1421 : }
1422 :
1423 1 : sprintf(szDEF, "CLIP%d_SND", read->current_sprite_id);
1424 1 : n = gf_sg_find_node_by_name(read->load->scene_graph, szDEF);
1425 :
1426 : /*assign URL*/
1427 1 : gf_node_get_field_by_name(n, "url", &info);
1428 1 : gf_sg_vrml_mf_alloc(info.far_ptr, info.fieldType, 1);
1429 1 : ((MFURL*)info.far_ptr)->vals[0].OD_ID = od->objectDescriptorID;
1430 1 : ((M_MediaControl *)n)->loop = 0;
1431 :
1432 : /*inactive by default (until inserted)*/
1433 1 : if (read->current_sprite_id) {
1434 0 : ((M_MediaControl *)n)->mediaSpeed = 0;
1435 : } else {
1436 1 : ((M_MediaControl *)n)->mediaSpeed = FIX_ONE;
1437 : }
1438 : }
1439 : return GF_OK;
1440 : }
1441 :
1442 1 : static GF_Err swf_bifs_setup_image(SWFReader *read, u32 ID, char *fileName)
1443 : {
1444 :
1445 : GF_Err e;
1446 : GF_ObjectDescriptor *od;
1447 : GF_ESD *esd;
1448 : GF_MuxInfo *mux;
1449 : GF_Node *n, *par;
1450 : GF_FieldInfo info;
1451 : char szDEF[100];
1452 :
1453 1 : e = swf_init_od(read, 0);
1454 1 : if (e) return e;
1455 :
1456 : /*create visual object*/
1457 1 : od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG);
1458 1 : if (!od) return GF_OUT_OF_MEM;
1459 1 : od->objectDescriptorID = swf_get_od_id(read);
1460 1 : esd = (GF_ESD *) gf_odf_desc_new(GF_ODF_ESD_TAG);
1461 1 : if (!esd) return GF_OUT_OF_MEM;
1462 1 : esd->ESID = swf_get_es_id(read);
1463 1 : esd->OCRESID = esd->ESID;
1464 1 : gf_list_add(od->ESDescriptors, esd);
1465 :
1466 : /*setup mux info*/
1467 1 : mux = (GF_MuxInfo*)gf_odf_desc_new(GF_ODF_MUXINFO_TAG);
1468 :
1469 1 : mux->file_name = gf_strdup(fileName);
1470 : /*destroy file once done*/
1471 : //mux->delete_file = 1;
1472 1 : gf_list_add(esd->extensionDescriptors, mux);
1473 :
1474 :
1475 : /*by default insert OD at beginning*/
1476 1 : e = swf_insert_od(read, 0, od);
1477 1 : if (e) {
1478 0 : gf_odf_desc_del((GF_Descriptor *) od);
1479 0 : return e;
1480 : }
1481 : /*create appearance clip*/
1482 1 : par = s2b_new_node(read, TAG_MPEG4_Shape);
1483 1 : s2b_insert_symbol(read, par);
1484 1 : n = s2b_new_node(read, TAG_MPEG4_Appearance);
1485 1 : ((M_Shape *)par)->appearance = n;
1486 1 : gf_node_register(n, par);
1487 :
1488 : par = n;
1489 1 : n = s2b_new_node(read, TAG_MPEG4_ImageTexture);
1490 1 : ((M_Appearance *)par)->texture = n;
1491 1 : gf_node_register(n, par);
1492 :
1493 : sprintf(szDEF, "Bitmap%d", ID);
1494 1 : read->load->ctx->max_node_id++;
1495 1 : ID = read->load->ctx->max_node_id;
1496 1 : gf_node_set_id(n, ID, szDEF);
1497 :
1498 : /*assign URL*/
1499 1 : gf_node_get_field_by_name(n, "url", &info);
1500 1 : gf_sg_vrml_mf_alloc(info.far_ptr, info.fieldType, 1);
1501 1 : ((MFURL *)info.far_ptr)->vals[0].OD_ID = od->objectDescriptorID;
1502 :
1503 1 : return GF_OK;
1504 : }
1505 :
1506 :
1507 3156 : static GF_Node *s2b_wrap_node(SWFReader *read, GF_Node *node, GF_Matrix2D *mat, GF_ColorMatrix *cmat)
1508 : {
1509 : GF_Node *par;
1510 3156 : if (mat && gf_mx2d_is_identity(*mat)) mat = NULL;
1511 3156 : if (cmat && cmat->identity) cmat = NULL;
1512 :
1513 : /*then add cmat/mat and node*/
1514 : par = NULL;
1515 3156 : if (!mat && !cmat) {
1516 : par = node;
1517 : } else {
1518 3107 : if (mat) par = s2b_get_matrix(read, mat);
1519 3107 : if (cmat) {
1520 67 : GF_Node *cm = s2b_get_color_matrix(read, cmat);
1521 67 : if (!par) {
1522 : par = cm;
1523 65 : gf_node_insert_child(par, node, -1);
1524 65 : gf_node_register(node, par);
1525 : } else {
1526 2 : gf_node_insert_child(par, cm, -1);
1527 2 : gf_node_register(cm, par);
1528 2 : gf_node_insert_child(cm, node, -1);
1529 2 : gf_node_register(node, cm);
1530 : }
1531 : } else {
1532 3040 : gf_node_insert_child(par, node, -1);
1533 3040 : gf_node_register(node, par);
1534 : }
1535 : }
1536 3156 : return par;
1537 : }
1538 :
1539 :
1540 :
1541 150 : static void s2b_set_field(SWFReader *read, GF_List *dst, GF_Node *n, char *fieldName, s32 pos, u32 type, void *val, Bool insert)
1542 : {
1543 : u32 i, count;
1544 : GF_FieldInfo info;
1545 : GF_Command *com = NULL;
1546 : GF_CommandField *f;
1547 :
1548 150 : gf_node_get_field_by_name(n, fieldName, &info);
1549 :
1550 150 : count = gf_list_count(dst);
1551 450 : for (i=0; i<count; i++) {
1552 457 : com = gf_list_get(dst, i);
1553 457 : if (com->node!=n) continue;
1554 37 : f = gf_list_get(com->command_fields, 0);
1555 37 : if (f->fieldIndex != info.fieldIndex) continue;
1556 7 : if (f->pos != pos) continue;
1557 :
1558 14 : if (insert) return;
1559 :
1560 3 : if (type==GF_SG_VRML_SFSTRING) {
1561 0 : if (((SFString*)f->field_ptr)->buffer)
1562 0 : gf_free(((SFString*)f->field_ptr)->buffer);
1563 0 : ((SFString*)f->field_ptr)->buffer = gf_strdup( (char *) val);
1564 : } else {
1565 3 : gf_sg_vrml_field_copy(f->field_ptr, val, type);
1566 : }
1567 3 : gf_list_rem(dst, i);
1568 3 : gf_list_add(dst, com);
1569 : return;
1570 : }
1571 :
1572 143 : com = gf_sg_command_new(read->load->scene_graph, (pos<0) ? GF_SG_FIELD_REPLACE : GF_SG_INDEXED_REPLACE);
1573 143 : com->node = n;
1574 143 : gf_node_register(com->node, NULL);
1575 143 : f = gf_sg_command_field_new(com);
1576 143 : f->field_ptr = gf_sg_vrml_field_pointer_new(type);
1577 143 : if (type==GF_SG_VRML_SFSTRING) {
1578 0 : ((SFString*)f->field_ptr)->buffer = gf_strdup( (char *) val);
1579 : } else {
1580 143 : gf_sg_vrml_field_copy(f->field_ptr, val, type);
1581 : }
1582 143 : f->fieldType = type;
1583 143 : f->pos = pos;
1584 143 : f->fieldIndex = info.fieldIndex;
1585 :
1586 143 : if (insert)
1587 3 : gf_list_insert(dst, com, 0);
1588 : else
1589 140 : gf_list_add(dst, com);
1590 : }
1591 :
1592 7 : static GF_Err swf_bifs_set_backcol(SWFReader *read, u32 xrgb)
1593 : {
1594 : SFColor rgb;
1595 7 : GF_Node *bck = gf_sg_find_node_by_name(read->load->scene_graph, "BACKGROUND");
1596 :
1597 7 : rgb.red = INT2FIX((xrgb>>16) & 0xFF) / 255;
1598 7 : rgb.green = INT2FIX((xrgb>>8) & 0xFF) / 255;
1599 7 : rgb.blue = INT2FIX((xrgb) & 0xFF) / 255;
1600 7 : s2b_set_field(read, read->bifs_au->commands, bck, "backColor", -1, GF_SG_VRML_SFCOLOR, &rgb, 0);
1601 7 : return GF_OK;
1602 : }
1603 :
1604 1 : static GF_Err swf_bifs_start_sound(SWFReader *read, SWFSound *snd, Bool stop)
1605 : {
1606 : GF_Node *sound2D;
1607 1 : SFTime t = 0;
1608 : char szDEF[100];
1609 :
1610 1 : sprintf(szDEF, "Sound%d", snd->ID);
1611 1 : sound2D = gf_sg_find_node_by_name(read->load->scene_graph, szDEF);
1612 : /*check flags*/
1613 1 : if (sound2D)
1614 1 : s2b_set_field(read, read->bifs_au->commands, sound2D, stop ? "stopTime" : "startTime", -1, GF_SG_VRML_SFTIME, &t, 0);
1615 :
1616 1 : return GF_OK;
1617 : }
1618 :
1619 390 : static void s2b_control_sprite(SWFReader *read, GF_List *dst, u32 ID, Bool stop, Bool set_time, SFTime mediaStartTime, Bool rev_order)
1620 : {
1621 : u32 i;
1622 : GF_Node *obj;
1623 : char szDEF[100];
1624 : SFFloat t;
1625 : sprintf(szDEF, "CLIP%d_CTRL", ID);
1626 390 : obj = gf_sg_find_node_by_name(read->load->scene_graph, szDEF);
1627 774 : if (!obj) return;
1628 :
1629 : /*filter the current control sequence: if the sprite is marked as started, skip the control. This happens
1630 : when a sprite is used in the different states of a button*/
1631 175 : for (i=0; i<gf_list_count(dst); i++) {
1632 179 : GF_Command *com = gf_list_get(dst, i);
1633 179 : if (com->node==obj) {
1634 13 : GF_CommandField *f = gf_list_get(com->command_fields, 0);
1635 13 : if ((f->fieldIndex == 3) && (*((SFFloat*)f->field_ptr) != 0))
1636 : return;
1637 : }
1638 : }
1639 :
1640 :
1641 45 : if (set_time)
1642 26 : s2b_set_field(read, dst, obj, "mediaStartTime", -1, GF_SG_VRML_SFTIME, &mediaStartTime, rev_order);
1643 45 : t = stop ? 0 : FIX_ONE;
1644 45 : s2b_set_field(read, dst, obj, "mediaSpeed", -1, GF_SG_VRML_SFFLOAT, &t, rev_order);
1645 :
1646 : sprintf(szDEF, "CLIP%d_SND", ID);
1647 45 : obj = gf_sg_find_node_by_name(read->load->scene_graph, szDEF);
1648 45 : if (!obj) return;
1649 6 : if (set_time) {
1650 3 : mediaStartTime -= read->sound_stream->frame_delay_ms/1000.0;
1651 3 : if (mediaStartTime<0) mediaStartTime = 0;
1652 3 : s2b_set_field(read, dst, obj, "mediaStartTime", -1, GF_SG_VRML_SFTIME, &mediaStartTime, rev_order);
1653 : }
1654 6 : t = stop ? 0 : FIX_ONE;
1655 6 : s2b_set_field(read, dst, obj, "mediaSpeed", -1, GF_SG_VRML_SFFLOAT, &t, rev_order);
1656 : }
1657 :
1658 3141 : static GF_Err swf_bifs_place_obj(SWFReader *read, u32 depth, u32 ID, u32 prev_id, u32 type, GF_Matrix2D *mat, GF_ColorMatrix *cmat, GF_Matrix2D *prev_mat, GF_ColorMatrix *prev_cmat)
1659 : {
1660 : GF_Command *com;
1661 : GF_CommandField *f;
1662 : GF_Node *obj, *par;
1663 : char szDEF[100];
1664 : Bool is_sprite;
1665 :
1666 3141 : obj = s2b_get_node(read, ID);
1667 : is_sprite = 0;
1668 3141 : if (!obj) {
1669 : sprintf(szDEF, "CLIP%d_DL", ID);
1670 12 : obj = gf_sg_find_node_by_name(read->load->scene_graph, szDEF);
1671 12 : if (obj) is_sprite = 1;
1672 : }
1673 3141 : if (!obj) return GF_BAD_PARAM;
1674 :
1675 : /*then add cmat/mat and node*/
1676 3141 : par = s2b_wrap_node(read, obj, mat, cmat);
1677 :
1678 : /*and write command*/
1679 3141 : com = gf_sg_command_new(read->load->scene_graph, GF_SG_INDEXED_REPLACE);
1680 3141 : sprintf(szDEF, "CLIP%d_DL", read->current_sprite_id);
1681 3141 : com->node = gf_sg_find_node_by_name(read->load->scene_graph, szDEF);
1682 3141 : gf_node_register(com->node, NULL);
1683 3141 : f = gf_sg_command_field_new(com);
1684 3141 : f->field_ptr = &f->new_node;
1685 3141 : f->fieldType = GF_SG_VRML_SFNODE;
1686 3141 : f->pos = depth;
1687 3141 : f->fieldIndex = 2; /*children index*/
1688 3141 : f->new_node = par;
1689 3141 : gf_node_register(f->new_node, NULL);
1690 3141 : gf_list_add(read->bifs_au->commands, com);
1691 :
1692 3141 : if (ID==prev_id) return GF_OK;
1693 :
1694 1236 : strcpy(szDEF, gf_node_get_name(obj));
1695 : /*when inserting a button, trigger a pause*/
1696 1236 : if (!strnicmp(szDEF, "Button", 6)) {
1697 : u32 i, count;
1698 4 : s2b_control_sprite(read, read->bifs_au->commands, read->current_sprite_id, 1, 0, 0, 1);
1699 :
1700 4 : count = gf_list_count(read->buttons);
1701 5 : for (i=0; i<count; i++) {
1702 1 : S2BBtnRec *btnrec = gf_list_get(read->buttons, i);
1703 1 : if (btnrec->btn_id==ID) {
1704 1 : s2b_control_sprite(read, read->bifs_au->commands, btnrec->sprite_up_id, 0, 0, 0, 1);
1705 : }
1706 : }
1707 : }
1708 : /*starts anim*/
1709 1232 : else if (is_sprite) {
1710 12 : s2b_control_sprite(read, read->bifs_au->commands, ID, 0, 1, 0, 0);
1711 12 : if (prev_id) {
1712 0 : s2b_control_sprite(read, read->bifs_au->commands, prev_id, 1, 0, 0, 0);
1713 : }
1714 : }
1715 : return GF_OK;
1716 : }
1717 :
1718 352 : static GF_Err swf_bifs_remove_obj(SWFReader *read, u32 depth, u32 ID)
1719 : {
1720 : char szDEF[100];
1721 : GF_Command *com;
1722 : GF_CommandField *f;
1723 :
1724 352 : com = gf_sg_command_new(read->load->scene_graph, GF_SG_INDEXED_REPLACE);
1725 352 : sprintf(szDEF, "CLIP%d_DL", read->current_sprite_id);
1726 352 : com->node = gf_sg_find_node_by_name(read->load->scene_graph, szDEF);
1727 352 : gf_node_register(com->node, NULL);
1728 352 : f = gf_sg_command_field_new(com);
1729 352 : f->field_ptr = &f->new_node;
1730 352 : f->fieldType = GF_SG_VRML_SFNODE;
1731 352 : f->pos = depth;
1732 352 : f->fieldIndex = 2; /*children index*/
1733 352 : f->new_node = gf_sg_find_node_by_name(read->load->scene_graph, "Shape0");
1734 352 : gf_node_register(f->new_node, NULL);
1735 352 : gf_list_add(read->bifs_au->commands, com);
1736 : /*check if this is a sprite*/
1737 352 : if (ID)
1738 352 : s2b_control_sprite(read, read->bifs_au->commands, ID, 1, 0, 0, 0);
1739 352 : return GF_OK;
1740 : }
1741 :
1742 1927 : static GF_Err swf_bifs_show_frame(SWFReader *read)
1743 : {
1744 : u32 ts;
1745 : Bool is_rap;
1746 :
1747 : /*hack to allow for empty BIFS AU to be encoded in order to keep the frame-rate (this reduces MP4 table size...)
1748 : todo: make this an option - commented for now in both master and filters*/
1749 : #if 0
1750 : if (!gf_list_count(read->bifs_au->commands)) {
1751 : GF_Command *com;
1752 : GF_CommandField *f;
1753 : com = gf_sg_command_new(read->load->scene_graph, GF_SG_FIELD_REPLACE);
1754 : com->node = gf_sg_find_node_by_name(read->load->scene_graph, "DICTIONARY");
1755 : gf_node_register(com->node, NULL);
1756 : f = gf_sg_command_field_new(com);
1757 : f->field_ptr = gf_sg_vrml_field_pointer_new(GF_SG_VRML_SFINT32);
1758 : f->fieldType = GF_SG_VRML_SFINT32;
1759 : f->fieldIndex = 1; /*whichCoice index*/
1760 : /*replace by same value*/
1761 : *((SFInt32 *)f->field_ptr) = -1;
1762 : gf_list_add(read->bifs_au->commands, com);
1763 : }
1764 : #endif
1765 :
1766 : /*create a new AU for next frame*/
1767 1927 : ts = (read->current_frame + 1) * 100;
1768 :
1769 : #if 1
1770 : /*all frames in sprites are RAP (define is not allowed in sprites)
1771 : if we use a ctrl stream, all AUs are RAP (defines are placed in a static dictionary)
1772 : */
1773 1927 : is_rap = (read->current_sprite_id || (read->flags & GF_SM_SWF_SPLIT_TIMELINE)) ? 1 : 0;
1774 : #else
1775 : /*"The contents of the second frame are the cumulative effect of performing all the control tag operations from
1776 : the beginning of the file to the second ShowFrame tag, and so on"
1777 : using RAP=0 forces reprocessing of previous frames when seeking/jumping*/
1778 : is_rap = 0;
1779 : #endif
1780 : /*if we use ctrl stream, same thing*/
1781 1927 : read->bifs_au = gf_sm_stream_au_new(read->bifs_es, ts, 0, is_rap);
1782 :
1783 : /*not in a sprite def, using a control stream and no wait_frame: create a new AU for new symbols
1784 : */
1785 1927 : if (!read->current_sprite_id) {
1786 1865 : if (read->bifs_dict_au && !read->wait_frame) {
1787 869 : read->bifs_dict_au = gf_sm_stream_au_new(read->bifs_dict_es, ts, 0, 0);
1788 : }
1789 : /*if wait_frame is specified, aggregate all dictionary commands until frame is reached*/
1790 1865 : if (read->wait_frame && read->wait_frame<=read->current_frame)
1791 1 : read->wait_frame = 0;
1792 : }
1793 :
1794 1927 : return GF_OK;
1795 : }
1796 :
1797 :
1798 39 : static GF_Node *s2b_button_add_child(SWFReader *read, GF_Node *button, u32 tag, char *def_name, s32 pos)
1799 : {
1800 39 : GF_Node *n = s2b_new_node(read, tag);
1801 :
1802 39 : if (def_name) {
1803 : u32 ID;
1804 35 : read->load->ctx->max_node_id++;
1805 35 : ID = read->load->ctx->max_node_id;
1806 35 : gf_node_set_id((GF_Node *)n, ID, def_name);
1807 : }
1808 :
1809 39 : gf_node_insert_child((GF_Node *)button, (GF_Node *)n, pos);
1810 39 : gf_node_register((GF_Node *) n, (GF_Node *) button);
1811 39 : return n;
1812 : }
1813 :
1814 16 : static void s2b_button_add_route(SWFReader *read, GF_Node *fromNode, u32 fromField, GF_Node *toNode, u32 toField)
1815 : {
1816 16 : GF_Command *com = gf_sg_command_new(read->load->scene_graph, GF_SG_ROUTE_INSERT);
1817 16 : com->fromNodeID = gf_node_get_id(fromNode);
1818 16 : com->fromFieldIndex = fromField;
1819 16 : com->toNodeID = gf_node_get_id(toNode);
1820 16 : com->toFieldIndex = toField;
1821 :
1822 16 : if (read->bifs_dict_au)
1823 16 : gf_list_add(read->bifs_dict_au->commands, com);
1824 : else
1825 0 : gf_list_add(read->bifs_au->commands, com);
1826 16 : }
1827 :
1828 :
1829 8 : static GF_Err swf_bifs_define_button(SWFReader *read, SWF_Button *btn)
1830 : {
1831 : char szName[1024];
1832 : M_Switch *button;
1833 : SWF_ButtonRecord *br;
1834 : GF_Node *btn_root, *n, *btn_ts;
1835 : u32 i, ID, pos;
1836 :
1837 8 : if (!btn) {
1838 4 : read->btn = NULL;
1839 4 : read->btn_over = read->btn_not_over = read->btn_active = read->btn_not_active = NULL;
1840 4 : return GF_OK;
1841 : }
1842 :
1843 4 : read->btn = btn;
1844 :
1845 4 : btn_root = s2b_new_node(read, TAG_MPEG4_Transform2D);
1846 4 : sprintf(szName, "Button%d", btn->ID);
1847 4 : read->load->ctx->max_node_id++;
1848 4 : ID = read->load->ctx->max_node_id;
1849 4 : gf_node_set_id((GF_Node *)btn_root, ID, szName);
1850 :
1851 4 : n = s2b_button_add_child(read, btn_root, TAG_MPEG4_ColorTransform, NULL, -1);
1852 4 : ((M_ColorTransform*)n)->maa = ((M_ColorTransform*)n)->mab = ((M_ColorTransform*)n)->mar = ((M_ColorTransform*)n)->mag = ((M_ColorTransform*)n)->ta = 0;
1853 :
1854 : /*locate hit buttons and add them to the color transform*/
1855 26 : for (i=0; i<btn->count; i++) {
1856 : GF_Node *character;
1857 : br = &btn->buttons[i];
1858 22 : if (!br->hitTest) continue;
1859 7 : character = s2b_get_node(read, br->character_id);
1860 7 : if (!character) {
1861 0 : sprintf(szName, "CLIP%d_DL", br->character_id);
1862 0 : character = gf_sg_find_node_by_name(read->load->scene_graph, szName);
1863 : }
1864 7 : if (character) {
1865 7 : gf_node_list_add_child(&((GF_ParentNode*)n)->children, character);
1866 7 : gf_node_register(character, (GF_Node *)n);
1867 : }
1868 : }
1869 : /*add touch sensor to the color transform*/
1870 4 : sprintf(szName, "BTN%d_TS", read->btn->ID);
1871 4 : btn_ts = s2b_button_add_child(read, n, TAG_MPEG4_TouchSensor, szName, -1);
1872 :
1873 4 : s2b_insert_symbol(read, (GF_Node *)btn_root);
1874 :
1875 : /*isActive handler*/
1876 4 : sprintf(szName, "BTN%d_CA", read->btn->ID);
1877 4 : n = s2b_button_add_child(read, btn_root, TAG_MPEG4_Conditional, szName, -1);
1878 4 : read->btn_active = ((M_Conditional*)n)->buffer.commandList;
1879 4 : s2b_button_add_route(read, btn_ts, 4, n, 0);
1880 :
1881 : /*!isActive handler*/
1882 4 : sprintf(szName, "BTN%d_CNA", read->btn->ID);
1883 4 : n = s2b_button_add_child(read, btn_root, TAG_MPEG4_Conditional, szName, -1);
1884 4 : read->btn_not_active = ((M_Conditional*)n)->buffer.commandList;
1885 4 : s2b_button_add_route(read, btn_ts, 4, n, 1);
1886 :
1887 : /*isOver handler*/
1888 4 : sprintf(szName, "BTN%d_CO", read->btn->ID);
1889 4 : n = s2b_button_add_child(read, btn_root, TAG_MPEG4_Conditional, szName, -1);
1890 4 : read->btn_over = ((M_Conditional*)n)->buffer.commandList;
1891 4 : s2b_button_add_route(read, btn_ts, 5, n, 0);
1892 :
1893 : /*!isOver handler*/
1894 4 : sprintf(szName, "BTN%d_CNO", read->btn->ID);
1895 4 : n = s2b_button_add_child(read, btn_root, TAG_MPEG4_Conditional, szName, -1);
1896 4 : read->btn_not_over = ((M_Conditional*)n)->buffer.commandList;
1897 4 : s2b_button_add_route(read, btn_ts, 5, n, 1);
1898 :
1899 : /*by default show first character*/
1900 : pos = 0;
1901 26 : for (i=0; i<btn->count; i++) {
1902 : GF_Node *sprite_ctrl = NULL;
1903 : GF_Node *character;
1904 : br = &btn->buttons[i];
1905 22 : if (!br->up && !br->down && !br->over) continue;
1906 :
1907 15 : character = s2b_get_node(read, br->character_id);
1908 :
1909 15 : if (!character) {
1910 3 : sprintf(szName, "CLIP%d_DL", br->character_id);
1911 3 : character = gf_sg_find_node_by_name(read->load->scene_graph, szName);
1912 3 : if (character) {
1913 3 : sprintf(szName, "CLIP%d_CTRL", br->character_id);
1914 3 : sprite_ctrl = gf_sg_find_node_by_name(read->load->scene_graph, szName);
1915 : }
1916 : }
1917 15 : if (character) {
1918 15 : SFInt32 choice = 0;
1919 15 : n = s2b_wrap_node(read, character, &br->mx, &br->cmx);
1920 :
1921 15 : sprintf(szName, "BTN%d_R%d", btn->ID, i+1);
1922 15 : button = (M_Switch *) s2b_button_add_child(read, btn_root, TAG_MPEG4_Switch, szName, pos);
1923 15 : pos++;
1924 :
1925 15 : gf_node_list_add_child(&button->choice, n);
1926 15 : gf_node_register(n, (GF_Node *)button);
1927 : /*initial state*/
1928 15 : if (br->up) {
1929 5 : button->whichChoice = 0;
1930 : /*register this button for sprite start upon place_obj*/
1931 5 : if (sprite_ctrl) {
1932 : S2BBtnRec *btnrec;
1933 1 : if (!read->buttons) read->buttons = gf_list_new();
1934 1 : btnrec = gf_malloc(sizeof(S2BBtnRec));
1935 1 : btnrec->btn_id = btn->ID;
1936 1 : btnrec->sprite_up_id = br->character_id;
1937 1 : gf_list_add(read->buttons, btnrec);
1938 : }
1939 :
1940 : } else {
1941 10 : button->whichChoice = -1;
1942 : }
1943 :
1944 15 : choice = br->up ? 0 : -1;
1945 15 : s2b_set_field(read, read->btn_not_over, (GF_Node *)button, "whichChoice", -1, GF_SG_VRML_SFINT32, &choice, 0);
1946 : /*start or stop sprite if button is up or not*/
1947 15 : if (sprite_ctrl) {
1948 3 : s2b_control_sprite(read, read->btn_not_over, br->character_id, choice, 1, 0, 0);
1949 : }
1950 :
1951 15 : choice = br->down ? 0 : -1;
1952 15 : s2b_set_field(read, read->btn_active, (GF_Node *)button, "whichChoice", -1, GF_SG_VRML_SFINT32, &choice, 0);
1953 15 : if (sprite_ctrl && !br->over) {
1954 2 : s2b_control_sprite(read, read->btn_active, br->character_id, choice, 1, 0, 0);
1955 : }
1956 :
1957 15 : choice = br->over ? 0 : -1;
1958 15 : s2b_set_field(read, read->btn_not_active, (GF_Node *)button, "whichChoice", -1, GF_SG_VRML_SFINT32, &choice, 0);
1959 15 : s2b_set_field(read, read->btn_over, (GF_Node *)button, "whichChoice", -1, GF_SG_VRML_SFINT32, &choice, 0);
1960 15 : if (sprite_ctrl) {
1961 3 : s2b_control_sprite(read, read->btn_over, br->character_id, choice, 1, 0, 0);
1962 3 : if (!br->down)
1963 2 : s2b_control_sprite(read, read->btn_not_active, br->character_id, choice, 1, 0, 0);
1964 : }
1965 : }
1966 : }
1967 :
1968 : return GF_OK;
1969 : }
1970 :
1971 7 : static void swf_bifs_finalize(SWFReader *read)
1972 : {
1973 : u32 i, count;
1974 :
1975 : swf_bifs_end_of_clip(read);
1976 :
1977 8 : while (gf_list_count(read->buttons)) {
1978 1 : S2BBtnRec *btnrec = gf_list_get(read->buttons, 0);
1979 1 : gf_list_rem(read->buttons, 0);
1980 1 : gf_free(btnrec);
1981 : }
1982 7 : gf_list_del(read->buttons);
1983 7 : read->buttons = NULL;
1984 :
1985 7 : count = gf_list_count(read->fonts);
1986 20 : for (i=0; i<count; i++) {
1987 13 : SWFFont *ft = (SWFFont *)gf_list_get(read->fonts, i);
1988 250 : while (gf_list_count(ft->glyphs)) {
1989 224 : GF_Node *gl = (GF_Node *)gf_list_get(ft->glyphs, 0);
1990 224 : gf_list_rem(ft->glyphs, 0);
1991 224 : gf_node_unregister(gl, NULL);
1992 : }
1993 : }
1994 7 : }
1995 :
1996 13 : Bool swf_bifs_action(SWFReader *read, SWFAction *act)
1997 : {
1998 : GF_List *dst;
1999 : MFURL url;
2000 : SFURL sfurl;
2001 : Bool bval;
2002 : GF_Node *n;
2003 : Double time;
2004 :
2005 13 : dst = read->bifs_au->commands;
2006 13 : if (read->btn) {
2007 3 : if (act->button_mask & GF_SWF_COND_OVERUP_TO_OVERDOWN) dst = read->btn_active;
2008 3 : else if (act->button_mask & GF_SWF_COND_IDLE_TO_OVERUP) dst = read->btn_over;
2009 3 : else if (act->button_mask & GF_SWF_COND_OVERUP_TO_IDLE) dst = read->btn_not_over;
2010 3 : else dst = read->btn_not_active;
2011 : }
2012 :
2013 13 : switch (act->type) {
2014 : case GF_SWF_AS3_WAIT_FOR_FRAME:
2015 : /*while correct, this is not optimal, we set the wait-frame upon GOTO frame*/
2016 : // read->wait_frame = act->frame_number;
2017 : break;
2018 4 : case GF_SWF_AS3_GOTO_FRAME:
2019 4 : if (act->frame_number>read->current_frame)
2020 1 : read->wait_frame = act->frame_number;
2021 :
2022 4 : time = act->frame_number ? act->frame_number +1: 0;
2023 4 : time /= read->frame_rate;
2024 4 : s2b_control_sprite(read, dst, read->current_sprite_id, 0, 1, time, 0);
2025 4 : break;
2026 1 : case GF_SWF_AS3_GET_URL:
2027 1 : n = gf_sg_find_node_by_name(read->load->scene_graph, "MOVIE_URL");
2028 1 : sfurl.OD_ID = 0;
2029 1 : sfurl.url = act->url;
2030 1 : url.count = 1;
2031 1 : url.vals = &sfurl;
2032 1 : s2b_set_field(read, dst, n, "url", -1, GF_SG_VRML_MFURL, &url, 0);
2033 1 : bval = 1;
2034 1 : s2b_set_field(read, dst, n, "activate", -1, GF_SG_VRML_SFBOOL, &bval, 0);
2035 1 : break;
2036 4 : case GF_SWF_AS3_PLAY:
2037 4 : s2b_control_sprite(read, dst, read->current_sprite_id, 0, 1, -1, 0);
2038 4 : break;
2039 3 : case GF_SWF_AS3_STOP:
2040 3 : s2b_control_sprite(read, dst, read->current_sprite_id, 1, 0, 0, 0);
2041 3 : break;
2042 : default:
2043 : return 0;
2044 : }
2045 :
2046 : return 1;
2047 : }
2048 :
2049 7 : GF_Err swf_to_bifs_init(SWFReader *read)
2050 : {
2051 : GF_Err e;
2052 : char szMsg[1000];
2053 : GF_ObjectDescriptor *od;
2054 : GF_ESD *esd;
2055 : u32 ID;
2056 : GF_FieldInfo info;
2057 : GF_StreamContext *prev_sc;
2058 : GF_Command *com;
2059 : GF_Node *n, *n2;
2060 :
2061 : /*init callbacks*/
2062 7 : read->show_frame = swf_bifs_show_frame;
2063 7 : read->allocate_depth = swf_bifs_allocate_depth;
2064 7 : read->place_obj = swf_bifs_place_obj;
2065 7 : read->remove_obj = swf_bifs_remove_obj;
2066 7 : read->define_shape = swf_bifs_define_shape;
2067 7 : read->define_sprite = swf_bifs_define_sprite;
2068 7 : read->set_backcol = swf_bifs_set_backcol;
2069 7 : read->define_button = swf_bifs_define_button;
2070 7 : read->define_text = swf_bifs_define_text;
2071 7 : read->define_edit_text = swf_bifs_define_edit_text;
2072 7 : read->setup_sound = swf_bifs_setup_sound;
2073 7 : read->start_sound = swf_bifs_start_sound;
2074 7 : read->setup_image = swf_bifs_setup_image;
2075 7 : read->action = swf_bifs_action;
2076 7 : read->finalize = swf_bifs_finalize;
2077 :
2078 : #ifdef GPAC_ENABLE_COVERAGE
2079 7 : if (gf_sys_is_cov_mode()) {
2080 : swf_nstart(NULL, NULL, NULL, NULL, 0);
2081 : swf_nend(NULL, NULL, NULL);
2082 : swf_ntext(NULL, NULL, GF_FALSE);
2083 : }
2084 : #endif
2085 :
2086 : /*create BIFS stream*/
2087 7 : read->bifs_es = gf_sm_stream_new(read->load->ctx, 1, GF_STREAM_SCENE, GF_CODECID_BIFS);
2088 7 : read->bifs_es->timeScale = read->frame_rate*100;
2089 :
2090 7 : read->bifs_au = gf_sm_stream_au_new(read->bifs_es, 0, 0.0, 1);
2091 : /*create scene replace command*/
2092 7 : com = gf_sg_command_new(read->load->scene_graph, GF_SG_SCENE_REPLACE);
2093 7 : read->load->ctx->scene_width = FIX2INT(read->width);
2094 7 : read->load->ctx->scene_height = FIX2INT(read->height);
2095 7 : read->load->ctx->is_pixel_metrics = 1;
2096 :
2097 7 : gf_list_add(read->bifs_au->commands, com);
2098 :
2099 : /*create base tree*/
2100 7 : com->node = read->root = s2b_new_node(read, TAG_MPEG4_OrderedGroup);
2101 7 : gf_node_register(read->root, NULL);
2102 :
2103 : /*hehehe*/
2104 7 : n = s2b_new_node(read, TAG_MPEG4_WorldInfo);
2105 7 : gf_node_insert_child(read->root, n, -1);
2106 7 : gf_node_register(n, read->root);
2107 7 : ((M_WorldInfo *)n)->title.buffer = gf_strdup("GPAC SWF CONVERTION DISCLAIMER");
2108 7 : gf_sg_vrml_mf_alloc( & ((M_WorldInfo *)n)->info, GF_SG_VRML_MFSTRING, 2);
2109 :
2110 7 : sprintf(szMsg, "%s file converted to MPEG-4 Systems", read->load->fileName);
2111 7 : ((M_WorldInfo *)n)->info.vals[0] = gf_strdup(szMsg);
2112 7 : if (gf_sys_is_test_mode()) {
2113 : sprintf(szMsg, "Conversion done using GPAC");
2114 : } else {
2115 0 : sprintf(szMsg, "Conversion done using GPAC version %s - %s", gf_gpac_version(), gf_gpac_copyright() );
2116 : }
2117 7 : ((M_WorldInfo *)n)->info.vals[1] = gf_strdup(szMsg);
2118 :
2119 : /*background*/
2120 7 : n = s2b_new_node(read, TAG_MPEG4_Background2D);
2121 7 : ((M_Background2D *)n)->backColor.red = FIX_ONE;
2122 7 : ((M_Background2D *)n)->backColor.green = FIX_ONE;
2123 7 : ((M_Background2D *)n)->backColor.blue = FIX_ONE;
2124 7 : gf_node_set_id(n, 1, "BACKGROUND");
2125 7 : gf_node_insert_child(read->root, n, -1);
2126 7 : gf_node_register(n, read->root);
2127 :
2128 : /*movie anchor*/
2129 7 : n = s2b_new_node(read, TAG_MPEG4_Anchor);
2130 7 : gf_node_set_id(n, 2, "MOVIE_URL");
2131 7 : gf_node_insert_child(read->root, n, -1);
2132 7 : gf_node_register(n, read->root);
2133 :
2134 : /*dictionary*/
2135 7 : n = s2b_new_node(read, TAG_MPEG4_Switch);
2136 7 : gf_node_set_id(n, 3, "DICTIONARY");
2137 7 : gf_node_insert_child(read->root, n, -1);
2138 7 : gf_node_register(n, read->root);
2139 : /*empty shape to fill depth levels & sprites roots*/
2140 7 : n2 = s2b_new_node(read, TAG_MPEG4_Shape);
2141 7 : gf_node_set_id(n2, 4, "Shape0");
2142 7 : gf_node_list_add_child( &((M_Switch *)n)->choice, n2);
2143 7 : gf_node_register(n2, n);
2144 :
2145 : /*display list*/
2146 7 : n = s2b_new_node(read, TAG_MPEG4_Transform2D);
2147 7 : gf_node_set_id(n, 5, "CLIP0_DL");
2148 7 : gf_node_insert_child(read->root, n, -1);
2149 7 : gf_node_register(n, read->root);
2150 : /*update w/h transform*/
2151 7 : ((M_Transform2D *)n)->scale.y = -FIX_ONE;
2152 7 : ((M_Transform2D *)n)->translation.x = -read->width/2;
2153 7 : ((M_Transform2D *)n)->translation.y = read->height/2;
2154 :
2155 7 : read->load->ctx->max_node_id = 5;
2156 :
2157 :
2158 7 : swf_init_od(read, 1);
2159 :
2160 : /*always reserve ES_ID=2 for OD stream, 3 for main ctrl stream if any*/
2161 7 : read->prev_es_id = 3;
2162 : /*always reserve OD_ID=1 for main ctrl stream if any - use same IDs are ESs*/
2163 7 : read->prev_od_id = 3;
2164 :
2165 :
2166 : /*setup IndexedCurve2D proto*/
2167 7 : if (read->flags & GF_SM_SWF_USE_IC2D) {
2168 : GF_ProtoFieldInterface *pfield;
2169 : SFURL *url;
2170 : Fixed ftMin, ftMax;
2171 1 : GF_Proto *proto = gf_sg_proto_new(read->load->scene_graph, 1, "IndexedCurve2D", 0);
2172 1 : if (read->load->ctx) read->load->ctx->max_proto_id = 1;
2173 1 : gf_sg_vrml_mf_reset(&proto->ExternProto, GF_SG_VRML_MFURL);
2174 1 : gf_sg_vrml_mf_append(&proto->ExternProto, GF_SG_VRML_MFURL, (void **) &url);
2175 1 : url->url = gf_strdup("urn:inet:gpac:builtin:IndexedCurve2D");
2176 :
2177 1 : gf_sg_proto_field_new(proto, GF_SG_VRML_SFNODE, GF_SG_EVENT_EXPOSED_FIELD, "coord");
2178 :
2179 1 : pfield = gf_sg_proto_field_new(proto, GF_SG_VRML_SFFLOAT, GF_SG_EVENT_EXPOSED_FIELD, "fineness");
2180 1 : gf_sg_proto_field_get_field(pfield, &info);
2181 1 : *((SFFloat*)info.far_ptr) = FIX_ONE/2;
2182 :
2183 1 : pfield = gf_sg_proto_field_new(proto, GF_SG_VRML_MFINT32, GF_SG_EVENT_EXPOSED_FIELD, "type");
2184 1 : ftMin = 0;
2185 1 : ftMax = 15*FIX_ONE;
2186 1 : gf_bifs_proto_field_set_aq_info(pfield, 13, 1, GF_SG_VRML_SFINT32, &ftMin, &ftMax, 4);
2187 :
2188 1 : pfield = gf_sg_proto_field_new(proto, GF_SG_VRML_MFINT32, GF_SG_EVENT_EXPOSED_FIELD, "coordIndex");
2189 1 : ftMin = 0;
2190 1 : ftMax = FIX_MAX;
2191 1 : gf_bifs_proto_field_set_aq_info(pfield, 14, 1, GF_SG_VRML_SFINT32, &ftMin, &ftMax, 0);
2192 : }
2193 :
2194 : /*no control stream*/
2195 7 : if (!(read->flags & GF_SM_SWF_SPLIT_TIMELINE)) return GF_OK;
2196 :
2197 : /*init OD*/
2198 5 : e = swf_init_od(read, 0);
2199 5 : if (e) return e;
2200 :
2201 : /*we want a dynamic dictionary*/
2202 5 : if (!(read->flags & GF_SM_SWF_STATIC_DICT)) {
2203 5 : read->bifs_dict_es = read->bifs_es;
2204 5 : read->bifs_dict_au = read->bifs_au;
2205 : }
2206 :
2207 : /*create animationStream object*/
2208 5 : od = (GF_ObjectDescriptor *) gf_odf_desc_new(GF_ODF_OD_TAG);
2209 5 : if (!od) return GF_OUT_OF_MEM;
2210 5 : od->objectDescriptorID = 1;
2211 5 : esd = (GF_ESD *) gf_odf_desc_esd_new(0);
2212 5 : if (!esd) return GF_OUT_OF_MEM;
2213 5 : esd->ESID = esd->OCRESID = 3;
2214 5 : esd->dependsOnESID = 1;
2215 5 : esd->decoderConfig->streamType = GF_STREAM_SCENE;
2216 5 : esd->decoderConfig->objectTypeIndication = GF_CODECID_BIFS;
2217 5 : esd->slConfig->timestampResolution = read->bifs_es->timeScale;
2218 5 : gf_odf_desc_del((GF_Descriptor *) esd->decoderConfig->decoderSpecificInfo);
2219 5 : esd->decoderConfig->decoderSpecificInfo = NULL;
2220 5 : gf_list_add(od->ESDescriptors, esd);
2221 5 : e = swf_insert_od(read, 0, od);
2222 5 : if (e) {
2223 0 : gf_odf_desc_del((GF_Descriptor *) od);
2224 0 : return e;
2225 : }
2226 :
2227 : /*setup a new BIFS context*/
2228 5 : prev_sc = read->bifs_es;
2229 5 : read->bifs_es = gf_sm_stream_new(read->load->ctx, esd->ESID, GF_STREAM_SCENE, GF_CODECID_BIFS);
2230 5 : read->bifs_es->timeScale = prev_sc->timeScale;
2231 : /*create first AU*/
2232 5 : read->bifs_au = gf_sm_stream_au_new(read->bifs_es, 0, 0, 1);
2233 :
2234 : /*setup the animationStream node*/
2235 5 : n = s2b_new_node(read, TAG_MPEG4_AnimationStream);
2236 5 : gf_node_insert_child(read->root, n, 0);
2237 5 : gf_node_register(n, read->root);
2238 : /*assign URL*/
2239 5 : gf_node_get_field_by_name(n, "url", &info);
2240 5 : gf_sg_vrml_mf_alloc(info.far_ptr, info.fieldType, 1);
2241 5 : ((MFURL*)info.far_ptr)->vals[0].OD_ID = 1;
2242 : /*run from start*/
2243 5 : ((M_AnimationStream *)n)->startTime = 0;
2244 5 : ((M_AnimationStream *)n)->loop = 0;
2245 :
2246 : /*setup the MediaControl node*/
2247 5 : n = s2b_new_node(read, TAG_MPEG4_MediaControl);
2248 5 : read->load->ctx->max_node_id++;
2249 5 : ID = read->load->ctx->max_node_id;
2250 5 : gf_node_set_id(n, ID, "CLIP0_CTRL");
2251 5 : gf_node_insert_child(read->root, n, 0);
2252 5 : gf_node_register(n, read->root);
2253 : /*assign URL*/
2254 5 : gf_node_get_field_by_name(n, "url", &info);
2255 5 : gf_sg_vrml_mf_alloc(info.far_ptr, info.fieldType, 1);
2256 5 : ((MFURL*)info.far_ptr)->vals[0].OD_ID = 1;
2257 : /*run from start*/
2258 5 : ((M_MediaControl *)n)->loop = 0;
2259 :
2260 5 : return GF_OK;
2261 : }
2262 :
2263 : #endif /*GPAC_DISABLE_SWF_IMPORT*/
2264 :
2265 : #endif /*GPAC_DISABLE_VRML*/
|