LCOV - code coverage report
Current view: top level - scene_manager - swf_bifs.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 1105 1246 88.7 %
Date: 2021-04-29 23:48:07 Functions: 39 42 92.9 %

          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*/

Generated by: LCOV version 1.13