LCOV - code coverage report
Current view: top level - laser - lsr_dec.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2692 3637 74.0 %
Date: 2021-04-29 23:48:07 Functions: 124 132 93.9 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2005-2019
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / LASeR codec 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             : 
      26             : #include <gpac/internal/laser_dev.h>
      27             : #include <gpac/internal/scenegraph_dev.h>
      28             : #include <gpac/bitstream.h>
      29             : #include <gpac/events.h>
      30             : 
      31             : #ifndef GPAC_DISABLE_LASER
      32             : 
      33             : 
      34             : #define GF_LSR_READ_INT(_codec, _val, _nbBits, _str)    {\
      35             :         (_val) = gf_bs_read_int(_codec->bs, _nbBits);        \
      36             :         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] %s\t\t%d\t\t%d\n", _str, _nbBits, _val)); \
      37             :         }\
      38             : 
      39             : 
      40             : static void lsr_read_group_content(GF_LASeRCodec *lsr, GF_Node *elt, Bool skip_object_content);
      41             : static void lsr_read_group_content_post_init(GF_LASeRCodec *lsr, SVG_Element *elt, Bool skip_init);
      42             : static GF_Err lsr_read_command_list(GF_LASeRCodec *lsr, GF_List *comList, SVG_Element *cond, Bool first_imp);
      43             : static GF_Err lsr_decode_laser_unit(GF_LASeRCodec *lsr, GF_List *com_list);
      44             : static void lsr_read_path_type(GF_LASeRCodec *lsr, GF_Node *n, u32 tag, SVG_PathData *path, const char *name);
      45             : static void lsr_read_point_sequence(GF_LASeRCodec *lsr, GF_List *pts, const char *name);
      46             : static Bool lsr_setup_smil_anim(GF_LASeRCodec *lsr, SVG_Element *anim, SVG_Element *anim_parent);
      47             : 
      48             : GF_EXPORT
      49          19 : GF_LASeRCodec *gf_laser_decoder_new(GF_SceneGraph *graph)
      50             : {
      51             :         GF_LASeRCodec *tmp;
      52          19 :         GF_SAFEALLOC(tmp, GF_LASeRCodec);
      53          19 :         if (!tmp) return NULL;
      54          19 :         tmp->streamInfo = gf_list_new();
      55          19 :         tmp->font_table = gf_list_new();
      56          19 :         tmp->deferred_hrefs = gf_list_new();
      57          19 :         tmp->deferred_listeners = gf_list_new();
      58          19 :         tmp->deferred_anims = gf_list_new();
      59          19 :         tmp->unresolved_commands = gf_list_new();
      60          19 :         tmp->sg = graph;
      61          19 :         return tmp;
      62             : }
      63             : 
      64             : GF_EXPORT
      65          19 : void gf_laser_decoder_del(GF_LASeRCodec *codec)
      66             : {
      67             :         /*destroy all config*/
      68          41 :         while (gf_list_count(codec->streamInfo)) {
      69           3 :                 LASeRStreamInfo *p = (LASeRStreamInfo *)gf_list_last(codec->streamInfo);
      70           3 :                 gf_free(p);
      71           3 :                 gf_list_rem_last(codec->streamInfo);
      72             :         }
      73          19 :         gf_list_del(codec->streamInfo);
      74          19 :         if (codec->col_table) gf_free(codec->col_table);
      75          25 :         while (gf_list_count(codec->font_table)) {
      76           6 :                 char *ft = (char *)gf_list_last(codec->font_table);
      77           6 :                 gf_free(ft);
      78           6 :                 gf_list_rem_last(codec->font_table);
      79             :         }
      80          19 :         gf_list_del(codec->font_table);
      81             : #if 0
      82             :         while (gf_list_count(codec->deferred_hrefs)) {
      83             :                 XMLRI *iri = (XMLRI *)gf_list_last(codec->deferred_hrefs);
      84             :                 gf_list_rem_last(codec->deferred_hrefs);
      85             :                 if (iri->string) gf_free(iri->string);
      86             :                 iri->string = NULL;
      87             :         }
      88             : #endif
      89          19 :         gf_list_del(codec->deferred_hrefs);
      90          19 :         gf_list_del(codec->deferred_anims);
      91          19 :         gf_list_del(codec->deferred_listeners);
      92          19 :         gf_list_del(codec->unresolved_commands);
      93          19 :         gf_free(codec);
      94          19 : }
      95             : 
      96          12 : static LASeRStreamInfo *lsr_get_stream(GF_LASeRCodec *codec, u16 ESID)
      97             : {
      98          12 :         u32 i=0;
      99             :         LASeRStreamInfo *ptr;
     100          24 :         while ((ptr = (LASeRStreamInfo *)gf_list_enum(codec->streamInfo, &i))) {
     101           9 :                 if (!ESID || (ptr->ESID==ESID)) return ptr;
     102             :         }
     103             :         return NULL;
     104             : }
     105             : 
     106             : 
     107             : GF_EXPORT
     108           3 : GF_Err gf_laser_decoder_configure_stream(GF_LASeRCodec *codec, u16 ESID, u8 *dsi, u32 dsi_len)
     109             : {
     110             :         LASeRStreamInfo *info;
     111             :         GF_BitStream *bs;
     112           3 :         if (lsr_get_stream(codec, ESID) != NULL) return GF_BAD_PARAM;
     113           3 :         GF_SAFEALLOC(info, LASeRStreamInfo);
     114           3 :         if (!info) return GF_OUT_OF_MEM;
     115           3 :         info->ESID = ESID;
     116           3 :         bs = gf_bs_new(dsi, dsi_len, GF_BITSTREAM_READ);
     117             : 
     118           3 :         info->cfg.profile = gf_bs_read_int(bs, 8);
     119           3 :         info->cfg.level = gf_bs_read_int(bs, 8);
     120           3 :         /*info->cfg.reserved = */ gf_bs_read_int(bs, 3);
     121           3 :         info->cfg.pointsCodec = gf_bs_read_int(bs, 2);
     122           3 :         info->cfg.pathComponents = gf_bs_read_int(bs, 4);
     123           3 :         info->cfg.fullRequestHost = gf_bs_read_int(bs, 1);
     124           3 :         if (gf_bs_read_int(bs, 1)) {
     125           0 :                 info->cfg.time_resolution = gf_bs_read_int(bs, 16);
     126             :         } else {
     127           3 :                 info->cfg.time_resolution = 1000;
     128             :         }
     129           3 :         info->cfg.colorComponentBits = gf_bs_read_int(bs, 4);
     130           3 :         info->cfg.colorComponentBits += 1;
     131           3 :         info->cfg.resolution = gf_bs_read_int(bs, 4);
     132           3 :         if (info->cfg.resolution>7) info->cfg.resolution -= 16;
     133           3 :         info->cfg.coord_bits = gf_bs_read_int(bs, 5);
     134           3 :         info->cfg.scale_bits_minus_coord_bits = gf_bs_read_int(bs, 4);
     135           3 :         info->cfg.newSceneIndicator = gf_bs_read_int(bs, 1);
     136           3 :         /*reserved*/ gf_bs_read_int(bs, 3);
     137           3 :         info->cfg.extensionIDBits = gf_bs_read_int(bs, 4);
     138             :         /*we ignore the rest*/
     139           3 :         gf_list_add(codec->streamInfo, info);
     140           3 :         gf_bs_del(bs);
     141           3 :         return GF_OK;
     142             : }
     143             : 
     144             : GF_EXPORT
     145           1 : GF_Err gf_laser_decoder_remove_stream(GF_LASeRCodec *codec, u16 ESID)
     146             : {
     147             :         u32 i, count;
     148           1 :         count = gf_list_count(codec->streamInfo);
     149           1 :         for (i=0; i<count; i++) {
     150           0 :                 LASeRStreamInfo *ptr = (LASeRStreamInfo *) gf_list_get(codec->streamInfo, i);
     151           0 :                 if (ptr->ESID==ESID) {
     152           0 :                         gf_free(ptr);
     153           0 :                         gf_list_rem(codec->streamInfo, i);
     154           0 :                         return GF_OK;
     155             :                 }
     156             :         }
     157             :         return GF_BAD_PARAM;
     158             : }
     159             : 
     160             : 
     161             : void gf_bs_set_eos_callback(GF_BitStream *bs, void (*EndOfStream)(void *par), void *par);
     162             : 
     163           0 : void lsr_end_of_stream(void *co)
     164             : {
     165           0 :         GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[LASeR] memory overread - corrupted decoding\n"));
     166           0 :         ((GF_LASeRCodec *) co)->last_error = GF_NON_COMPLIANT_BITSTREAM;
     167           0 : }
     168             : 
     169             : GF_EXPORT
     170           1 : Bool gf_laser_decode_has_conditionnals(GF_LASeRCodec *codec)
     171             : {
     172           1 :         return codec && codec->has_conditionnals ? GF_TRUE : GF_FALSE;
     173             : }
     174             : 
     175             : GF_EXPORT
     176           3 : GF_Err gf_laser_decode_au(GF_LASeRCodec *codec, u16 ESID, const u8 *data, u32 data_len)
     177             : {
     178             :         GF_Err e;
     179           3 :         if (!codec || !data || !data_len) return GF_BAD_PARAM;
     180             : 
     181           3 :         codec->info = lsr_get_stream(codec, ESID);
     182           3 :         if (!codec->info) return GF_BAD_PARAM;
     183           3 :         codec->coord_bits = codec->info->cfg.coord_bits;
     184           3 :         codec->scale_bits = codec->info->cfg.scale_bits_minus_coord_bits;
     185           3 :         codec->time_resolution = codec->info->cfg.time_resolution;
     186           3 :         codec->color_scale = (1<<codec->info->cfg.colorComponentBits) - 1;
     187           3 :         if (codec->info->cfg.resolution >= 0)
     188           3 :                 codec->res_factor = INT2FIX(1<<codec->info->cfg.resolution);
     189             :         else
     190           0 :                 codec->res_factor = gf_divfix(FIX_ONE, INT2FIX(1 << (-codec->info->cfg.resolution)) );
     191             : 
     192           3 :         codec->bs = gf_bs_new(data, data_len, GF_BITSTREAM_READ);
     193           3 :         gf_bs_set_eos_callback(codec->bs, lsr_end_of_stream, codec);
     194           3 :         codec->memory_dec = GF_FALSE;
     195           3 :         e = lsr_decode_laser_unit(codec, NULL);
     196           3 :         gf_bs_del(codec->bs);
     197           3 :         codec->bs = NULL;
     198           3 :         return e;
     199             : }
     200             : 
     201             : GF_EXPORT
     202           6 : GF_Err gf_laser_decode_command_list(GF_LASeRCodec *codec, u16 ESID, u8 *data, u32 data_len, GF_List *com_list)
     203             : {
     204             :         GF_Err e;
     205             :         u32 i;
     206           6 :         if (!codec || !data || !data_len) return GF_BAD_PARAM;
     207             : 
     208           6 :         codec->info = lsr_get_stream(codec, ESID);
     209           6 :         if (!codec->info) return GF_BAD_PARAM;
     210           6 :         codec->coord_bits = codec->info->cfg.coord_bits;
     211           6 :         codec->scale_bits = codec->info->cfg.scale_bits_minus_coord_bits;
     212           6 :         codec->time_resolution = codec->info->cfg.time_resolution;
     213           6 :         codec->color_scale = (1<<codec->info->cfg.colorComponentBits) - 1;
     214           6 :         if (codec->info->cfg.resolution >= 0)
     215           6 :                 codec->res_factor = INT2FIX(1<<codec->info->cfg.resolution);
     216             :         else
     217           0 :                 codec->res_factor = gf_divfix(FIX_ONE, INT2FIX(1 << (-codec->info->cfg.resolution)) );
     218             : 
     219           6 :         codec->bs = gf_bs_new(data, data_len, GF_BITSTREAM_READ);
     220           6 :         gf_bs_set_eos_callback(codec->bs, lsr_end_of_stream, codec);
     221           6 :         codec->memory_dec = GF_TRUE;
     222           6 :         e = lsr_decode_laser_unit(codec, com_list);
     223           6 :         gf_bs_del(codec->bs);
     224           6 :         codec->bs = NULL;
     225           6 :         if (e) return e;
     226             : 
     227           6 :         for (i=0; i<gf_list_count(codec->unresolved_commands); i++) {
     228           6 :                 GF_Command *com = (GF_Command *)gf_list_get(codec->unresolved_commands, i);
     229             :                 assert(!com->node);
     230           6 :                 com->node = gf_sg_find_node(codec->sg, com->RouteID);
     231           6 :                 if (com->node) {
     232           0 :                         gf_node_register(com->node, NULL);
     233           0 :                         com->RouteID = 0;
     234           0 :                         gf_list_rem(codec->unresolved_commands, i);
     235           0 :                         i--;
     236             :                 }
     237             :         }
     238             :         return GF_OK;
     239             : }
     240             : 
     241             : GF_EXPORT
     242           1 : void gf_laser_decoder_set_clock(GF_LASeRCodec *codec, Double (*GetSceneTime)(void *st_cbk), void *st_cbk )
     243             : {
     244           1 :         codec->GetSceneTime = GetSceneTime;
     245           1 :         codec->cbk = st_cbk;
     246           1 : }
     247             : 
     248        1508 : static u32 lsr_read_vluimsbf5(GF_LASeRCodec *lsr, const char *name)
     249             : {
     250             :         u32 nb_words = 0;
     251             :         u32 nb_tot, nb_bits, val;
     252             : 
     253         732 :         while (gf_bs_read_int(lsr->bs, 1)) nb_words++;
     254        1508 :         nb_words++;
     255             :         nb_tot = nb_words;
     256        1508 :         nb_bits = nb_words*4;
     257        1508 :         nb_tot += nb_bits;
     258        1508 :         val = gf_bs_read_int(lsr->bs, nb_bits);
     259        1508 :         if (name) GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] %s\t\t%d\t\t%d\n", name, nb_tot, val));
     260        1508 :         return val;
     261             : }
     262         174 : static u32 lsr_read_vluimsbf8(GF_LASeRCodec *lsr, const char *name)
     263             : {
     264             :         u32 nb_words = 0;
     265             :         u32 nb_tot, nb_bits, val;
     266             : 
     267           0 :         while (gf_bs_read_int(lsr->bs, 1)) nb_words++;
     268         174 :         nb_words++;
     269             :         nb_tot = nb_words;
     270         174 :         nb_bits = nb_words*7;
     271         174 :         nb_tot += nb_bits;
     272         174 :         val = gf_bs_read_int(lsr->bs, nb_bits);
     273         174 :         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] %s\t\t%d\t\t%d\n", name, nb_tot, val));
     274         174 :         return val;
     275             : }
     276             : 
     277           0 : static void lsr_read_extension(GF_LASeRCodec *lsr, const char *name)
     278             : {
     279           0 :         u32 len = lsr_read_vluimsbf5(lsr, name);
     280             : #if 0
     281             :         *out_data = gf_malloc(sizeof(char)*len);
     282             :         gf_bs_read_data(lsr->bs, *out_data, len);
     283             :         *out_len = len;
     284             : #else
     285           0 :         while (len && gf_bs_available(lsr->bs) ) {
     286           0 :                 gf_bs_read_int(lsr->bs, 8);
     287           0 :                 len--;
     288             :         }
     289           0 :         if (len) lsr->last_error = GF_NON_COMPLIANT_BITSTREAM;
     290             : #endif
     291           0 : }
     292             : 
     293           0 : static void lsr_read_extend_class(GF_LASeRCodec *lsr, char **out_data, u32 *out_len, const char *name)
     294             : {
     295             :         u32 len;
     296           0 :         GF_LSR_READ_INT(lsr, len, lsr->info->cfg.extensionIDBits, "reserved");
     297           0 :         len = lsr_read_vluimsbf5(lsr, "len");
     298             : //      while (len) gf_bs_read_int(lsr->bs, 1);
     299           0 :         gf_bs_read_long_int(lsr->bs, len);
     300           0 :         if (out_data) *out_data = NULL;
     301           0 :         if (out_len) *out_len = 0;
     302           0 : }
     303             : 
     304           0 : static void lsr_read_private_element_container(GF_LASeRCodec *lsr)
     305             : {
     306             :         u32 val, len;
     307           0 :         GF_LSR_READ_INT(lsr, val, 4, "ch4");
     308           0 :         switch (val) {
     309             :         /*privateAnyXMLElement*/
     310           0 :         case 0:
     311           0 :                 len = lsr_read_vluimsbf5(lsr, "len");
     312           0 :                 gf_bs_skip_bytes(lsr->bs, len);
     313           0 :                 break;
     314             :         /*privateOpaqueElement*/
     315           0 :         case 1:
     316           0 :                 len = lsr_read_vluimsbf5(lsr, "len");
     317           0 :                 gf_bs_skip_bytes(lsr->bs, len);
     318           0 :                 break;
     319             :         /*element_any*/
     320           0 :         case 2:
     321           0 :                 lsr_read_extend_class(lsr, NULL, 0, "reserved");
     322           0 :                 break;
     323             :         /*attr_custom_extension*/
     324           0 :         default:
     325           0 :                 len = lsr_read_vluimsbf5(lsr, "len");
     326           0 :                 gf_bs_skip_bytes(lsr->bs, len);
     327           0 :                 break;
     328             :         }
     329           0 : }
     330             : 
     331           0 : static void lsr_read_private_attribute_container(GF_LASeRCodec *lsr)
     332             : {
     333             :         u32 val;
     334             :         do {
     335             :                 u32 skip_len;
     336           0 :                 GF_LSR_READ_INT(lsr, val, 2, "privateDataType");
     337           0 :                 skip_len = lsr_read_vluimsbf5(lsr, "skipLen");
     338           0 :                 gf_bs_align(lsr->bs);
     339             :                 /*just skip data*/
     340             : #if 1
     341           0 :                 if (skip_len>gf_bs_available(lsr->bs)) {
     342           0 :                         lsr->last_error = GF_NON_COMPLIANT_BITSTREAM;
     343           0 :                         return;
     344             :                 }
     345           0 :                 gf_bs_skip_bytes(lsr->bs, skip_len);
     346             : #else
     347             :                 switch (val) {
     348             :                 /*private data of type "anyXML"*/
     349             :                 case 0:
     350             :                         count = lsr_read_vluimsbf5(lsr, "count");
     351             :                         for (i=0; i<count; i++) {
     352             :                                 privateAttribute(0) attr[i];
     353             :                         }
     354             :                         break;
     355             :                 case 1:
     356             :                         /*TODO FIXME - nameSpaceIndexBits is not defined in the spec*/
     357             :                         uint(nameSpaceIndexBits) nameSpaceIndex;
     358             :                         gf_bs_align(lsr->bs);
     359             :                         byte[skipLen - ((nameSpaceIndexBits+7)%8)] data;
     360             :                         break;
     361             :                 default:
     362             :                         /*TODO - spec is wrong here (typo, "len" instead of "skipLen" )*/
     363             :                         gf_bs_skip_bytes(skipLen);
     364             :                         break;
     365             :                 }
     366             : #endif
     367           0 :                 gf_bs_align(lsr->bs);
     368           0 :                 GF_LSR_READ_INT(lsr, val, 1, "hasMorePrivateData");
     369           0 :         } while (val);
     370             : }
     371             : 
     372         701 : static void lsr_read_any_attribute(GF_LASeRCodec *lsr, GF_Node *node, Bool skippable)
     373             : {
     374             :         u32 val = 1;
     375         701 :         if (skippable) GF_LSR_READ_INT(lsr, val, 1, "has_attrs");
     376         701 :         if (val) {
     377             :                 do {
     378           0 :                         GF_LSR_READ_INT(lsr, val, lsr->info->cfg.extensionIDBits, "reserved");
     379           0 :                         val = lsr_read_vluimsbf5(lsr, "len");//len in BITS
     380           0 :                         GF_LSR_READ_INT(lsr, val, val, "reserved_val");
     381           0 :                         GF_LSR_READ_INT(lsr, val, 1, "hasNextExtension");
     382           0 :                 } while (val);
     383             :         }
     384         701 : }
     385             : 
     386         436 : static void lsr_read_object_content(GF_LASeRCodec *lsr, SVG_Element *elt)
     387             : {
     388             :         u32 val;
     389         436 :         GF_LSR_READ_INT(lsr, val, 1, "has_private_attr");
     390         436 :         if (val) lsr_read_private_attribute_container(lsr);
     391         436 : }
     392             : 
     393          77 : static void lsr_read_codec_IDREF(GF_LASeRCodec *lsr, XMLRI *href, const char *name)
     394             : {
     395             :         GF_Node *n;
     396             :         u32 flag;
     397          77 :         u32 nID = 1+lsr_read_vluimsbf5(lsr, name);
     398             : 
     399          77 :         GF_LSR_READ_INT(lsr, flag, 1, "reserved");
     400          77 :         if (flag) {
     401           0 :                 u32 len = lsr_read_vluimsbf5(lsr, "len");
     402           0 :                 GF_LSR_READ_INT(lsr, flag, len, "reserved");
     403             :         }
     404             : 
     405          77 :         n = gf_sg_find_node(lsr->sg, nID);
     406          77 :         if (!n) {
     407             :                 char NodeID[1024];
     408             :                 sprintf(NodeID, "N%d", nID-1);
     409          30 :                 href->string = gf_strdup(NodeID);
     410          30 :                 if (href->type!=0xFF)
     411          30 :                         gf_list_add(lsr->deferred_hrefs, href);
     412          30 :                 href->type = XMLRI_ELEMENTID;
     413             :                 return;
     414             :         }
     415          47 :         href->target = (SVG_Element *)n;
     416          47 :         href->type = XMLRI_ELEMENTID;
     417          47 :         gf_node_register_iri(lsr->sg, href);
     418             : }
     419             : 
     420         269 : static u32 lsr_read_codec_IDREF_command(GF_LASeRCodec *lsr, const char *name)
     421             : {
     422             :         u32 flag;
     423         269 :         u32 nID = 1+lsr_read_vluimsbf5(lsr, name);
     424             : 
     425         269 :         GF_LSR_READ_INT(lsr, flag, 1, "reserved");
     426         269 :         if (flag) {
     427           0 :                 u32 len = lsr_read_vluimsbf5(lsr, "len");
     428           0 :                 GF_LSR_READ_INT(lsr, flag, len, "reserved");
     429             :         }
     430         269 :         return nID;
     431             : }
     432             : 
     433         230 : static Fixed lsr_read_fixed_16_8(GF_LASeRCodec *lsr, const char *name)
     434             : {
     435             :         u32 val;
     436         230 :         GF_LSR_READ_INT(lsr, val, 24, name);
     437         230 :         if (val & (1<<23)) {
     438           3 :                 s32 res = val - (1<<24);
     439             : #ifdef GPAC_FIXED_POINT
     440             :                 return res*256;
     441             : #else
     442           3 :                 return INT2FIX(res) / 256;
     443             : #endif
     444             :         } else {
     445             : #ifdef GPAC_FIXED_POINT
     446             :                 return val*256;
     447             : #else
     448         227 :                 return INT2FIX(val) / 256;
     449             : #endif
     450             :         }
     451             : }
     452             : 
     453          36 : static void lsr_read_fixed_16_8i(GF_LASeRCodec *lsr, SVG_Number *n, const char *name)
     454             : {
     455             :         s32 val;
     456          36 :         GF_LSR_READ_INT(lsr, val, 1, name);
     457          36 :         if (val) {
     458           0 :                 n->type=SVG_NUMBER_INHERIT;
     459             :         } else {
     460          36 :                 n->type=SVG_NUMBER_VALUE;
     461          36 :                 n->value = lsr_read_fixed_16_8(lsr, name);
     462             :         }
     463          36 : }
     464             : 
     465             : 
     466         157 : static void lsr_get_color(GF_LASeRCodec *lsr, u32 idx, SVG_Color *color)
     467             : {
     468             :         LSRCol *c;
     469         157 :         if (idx>=lsr->nb_cols) return;
     470             : 
     471         157 :         c = &lsr->col_table[idx];
     472         157 :         color->red = INT2FIX(c->r) / lsr->color_scale;
     473         157 :         color->green = INT2FIX(c->g) / lsr->color_scale;
     474         157 :         color->blue = INT2FIX(c->b) / lsr->color_scale;
     475         157 :         color->type = SVG_COLOR_RGBCOLOR;
     476             : }
     477             : 
     478             : 
     479           9 : static void lsr_read_line_increment_type(GF_LASeRCodec *lsr, SVG_Number *li, const char *name)
     480             : {
     481             :         u32 val;
     482           9 :         GF_LSR_READ_INT(lsr, val, 1, "choice");
     483           9 :         if (val==1) {
     484           6 :                 GF_LSR_READ_INT(lsr, val, 1, "type");
     485           6 :                 if (val==1) li->type=SVG_NUMBER_INHERIT;
     486           3 :                 else li->type=SVG_NUMBER_AUTO;
     487             :         } else {
     488           3 :                 li->value = lsr_read_fixed_16_8(lsr, "line-increment-value");
     489             :         }
     490           9 : }
     491             : 
     492         174 : static void lsr_read_byte_align_string(GF_LASeRCodec *lsr, char **str, const char *name)
     493             : {
     494             :         u32 len;
     495         174 :         gf_bs_align(lsr->bs);
     496         174 :         len = lsr_read_vluimsbf8(lsr, "len");
     497         174 :         if (str) {
     498         165 :                 if (*str) gf_free(*str);
     499         165 :                 *str = NULL;
     500         165 :                 if (len) {
     501         162 :                         if (len > gf_bs_available(lsr->bs) ) {
     502           0 :                                 lsr->last_error = GF_NON_COMPLIANT_BITSTREAM;
     503           0 :                                 return;
     504             :                         }
     505         162 :                         *str = (char*)gf_malloc(sizeof(char)*(len+1));
     506         162 :                         gf_bs_read_data(lsr->bs, *str, len);
     507         162 :                         (*str) [len] = 0;
     508             :                 }
     509             :         } else {
     510          66 :                 while (len) {
     511          57 :                         gf_bs_read_int(lsr->bs, 8);
     512          57 :                         len--;
     513             :                 }
     514             :         }
     515         174 :         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] %s\t\t%d\t\t%s\n", name, 8*len, str ? *str : ""));
     516             : }
     517             : 
     518          39 : static void lsr_read_text_content(GF_LASeRCodec *lsr, GF_Node *elt)
     519             : {
     520          39 :         char *str = NULL;
     521          39 :         lsr_read_byte_align_string(lsr, &str, "textContent");
     522          42 :         if (!str) return;
     523          36 :         gf_dom_add_text_node(elt, str);
     524             : }
     525             : 
     526          12 : static void lsr_read_byte_align_string_list(GF_LASeRCodec *lsr, GF_List *l, const char *name, Bool is_iri, Bool is_font)
     527             : {
     528             :         XMLRI *iri;
     529             :         char *text, *sep, *sep2, *cur;
     530          24 :         while (gf_list_count(l)) {
     531           0 :                 char *str = (char *)gf_list_last(l);
     532           0 :                 gf_list_rem_last(l);
     533           0 :                 gf_free(str);
     534             :         }
     535          12 :         text = NULL;
     536          12 :         lsr_read_byte_align_string(lsr, &text, name);
     537          12 :         cur = text;
     538          27 :         while (cur) {
     539          15 :                 sep = strchr(cur, '\'');
     540          15 :                 if (!sep && is_font) {
     541           6 :                         sep = strchr(cur, ',');
     542           6 :                         if (!sep) sep = strchr(cur, ';');
     543             :                 }
     544          15 :                 if (!sep) {
     545          12 :                         if (is_iri) {
     546           3 :                                 GF_SAFEALLOC(iri, XMLRI);
     547           3 :                                 if (iri) {
     548           3 :                                         iri->string = gf_strdup(cur);
     549           3 :                                         iri->type = XMLRI_STRING;
     550           3 :                                         gf_list_add(l, iri);
     551             :                                 }
     552             :                         } else {
     553           9 :                                 gf_list_add(l, gf_strdup(cur));
     554             :                         }
     555             :                         break;
     556             :                 }
     557           3 :                 sep2 = strchr(sep + 1, '\'');
     558           3 :                 if (!sep2 && !is_font) {
     559           0 :                         if (is_iri) {
     560           0 :                                 GF_SAFEALLOC(iri, XMLRI);
     561           0 :                                 if (iri) {
     562           0 :                                         iri->string = gf_strdup(cur);
     563           0 :                                         iri->type = XMLRI_STRING;
     564           0 :                                         gf_list_add(l, iri);
     565             :                                 }
     566             :                         } else {
     567           0 :                                 gf_list_add(l, gf_strdup(cur));
     568             :                         }
     569             :                         break;
     570             :                 }
     571           3 :                 if (sep2)
     572           0 :                         sep2[0] = 0;
     573             :                 else
     574           3 :                         sep[0] = 0;
     575           3 :                 if (is_iri) {
     576           0 :                         GF_SAFEALLOC(iri, XMLRI);
     577           0 :                         if (iri) {
     578           0 :                                 iri->string = gf_strdup(sep+1);
     579           0 :                                 iri->type = XMLRI_STRING;
     580           0 :                                 gf_list_add(l, iri);
     581             :                         }
     582             :                 } else {
     583           3 :                         gf_list_add(l, gf_strdup(sep+1));
     584             :                 }
     585           3 :                 if (sep2) {
     586           0 :                         sep2[0] = '\'';
     587           0 :                         cur = sep2 + 1;
     588             :                 } else {
     589           3 :                         sep[0] = ';';
     590             :                         cur = sep + 1;
     591             :                 }
     592             :         }
     593          12 :         gf_free(text);
     594          12 : }
     595             : 
     596         110 : static void lsr_read_any_uri(GF_LASeRCodec *lsr, XMLRI *iri, const char *name)
     597             : {
     598             :         u32 val;
     599         110 :         GF_LSR_READ_INT(lsr, val, 1, "hasUri");
     600         110 :         if (val) {
     601          36 :                 char *s = NULL;
     602          36 :                 iri->type=XMLRI_STRING;
     603          36 :                 if (iri->string) {
     604           0 :                         gf_free(iri->string);
     605           0 :                         iri->string = NULL;
     606             :                 }
     607          36 :                 lsr_read_byte_align_string(lsr, &s, "uri");
     608          36 :                 GF_LSR_READ_INT(lsr, val, 1, "hasData");
     609          36 :                 if (!val) {
     610          33 :                         iri->string = s;
     611             :                 } else {
     612             :                         u32 len_rad, len;
     613           3 :                         len = lsr_read_vluimsbf5(lsr, "len");
     614           3 :                         len_rad = s ? (u32) strlen(s) : 0;
     615           3 :                         iri->string = (char*)gf_malloc(sizeof(char)*(len_rad+1+len+1));
     616           3 :                         iri->string[0] = 0;
     617           3 :                         if (s) {
     618           3 :                                 strcpy(iri->string, s);
     619           3 :                                 gf_free(s);
     620             :                         }
     621           3 :                         strcat(iri->string, ",");
     622           3 :                         gf_bs_read_data(lsr->bs, iri->string + len_rad + 1, len);
     623           3 :                         iri->string[len_rad + 1 + len] = 0;
     624             :                 }
     625             :         }
     626         110 :         GF_LSR_READ_INT(lsr, val, 1, "hasID");
     627         110 :         if (val) lsr_read_codec_IDREF(lsr, iri, "idref");
     628             : 
     629         110 :         GF_LSR_READ_INT(lsr, val, 1, "hasStreamID");
     630         110 :         if (val) {
     631           3 :                 iri->type = XMLRI_STREAMID;
     632           3 :                 iri->lsr_stream_id = lsr_read_vluimsbf5(lsr, name);
     633           3 :                 GF_LSR_READ_INT(lsr, val, 1, "reserved");
     634           3 :                 if (val) {
     635           0 :                         u32 len = lsr_read_vluimsbf5(lsr, "len");
     636           0 :                         GF_LSR_READ_INT(lsr, val, len, "reserved");
     637             :                 }
     638             :         }
     639         110 : }
     640             : 
     641         193 : static void lsr_read_paint(GF_LASeRCodec *lsr, SVG_Paint *paint, const char *name)
     642             : {
     643             :         u32 val;
     644         193 :         GF_LSR_READ_INT(lsr, val, 1, "hasIndex");
     645         193 :         if (val) {
     646         157 :                 GF_LSR_READ_INT(lsr, val, lsr->colorIndexBits, name);
     647         157 :                 lsr_get_color(lsr, val, &paint->color);
     648         157 :                 paint->type = SVG_PAINT_COLOR;
     649         157 :                 paint->color.type = 0;
     650             :         } else {
     651          36 :                 GF_LSR_READ_INT(lsr, val, 2, "enum");
     652          36 :                 switch (val) {
     653          27 :                 case 0:
     654          27 :                         GF_LSR_READ_INT(lsr, val, 2, "choice");
     655          27 :                         switch (val) {
     656          12 :                         case 0:
     657          12 :                                 paint->type = SVG_PAINT_INHERIT;
     658          12 :                                 break;
     659           3 :                         case 1:
     660           3 :                                 paint->type = SVG_PAINT_COLOR;
     661           3 :                                 paint->color.type = SVG_COLOR_CURRENTCOLOR;
     662           3 :                                 break;
     663          12 :                         default:
     664          12 :                                 paint->type = SVG_PAINT_NONE;
     665          12 :                                 break;
     666             :                         }
     667             :                         break;
     668             :                 case 1:
     669             :                 {
     670             :                         XMLRI iri;
     671             :                         memset(&iri, 0, sizeof(XMLRI));
     672           9 :                         iri.type = 0xFF;
     673           9 :                         lsr_read_any_uri(lsr, &iri, name);
     674           9 :                         gf_node_unregister_iri(lsr->sg, &iri);
     675           9 :                         paint->type = SVG_PAINT_URI;
     676           9 :                         if (iri.string) {
     677             :                                 paint->type = SVG_PAINT_URI;
     678           0 :                                 paint->iri.type = XMLRI_STRING;
     679           0 :                                 paint->iri.string = iri.string;
     680           9 :                         } else if (iri.target) {
     681           9 :                                 paint->iri.type = XMLRI_ELEMENTID;
     682           9 :                                 paint->iri.target = iri.target;
     683             :                         }
     684             :                 }
     685           9 :                 break;
     686           0 :                 case 2:
     687             :                 {
     688           0 :                         char *sysPaint=NULL;
     689           0 :                         lsr_read_byte_align_string(lsr, &sysPaint, "systemsPaint");
     690           0 :                         if (sysPaint) {
     691           0 :                                 paint->type = SVG_PAINT_COLOR;
     692           0 :                                 paint->color.type = gf_svg_get_system_paint_server_type(sysPaint);
     693           0 :                                 gf_free(sysPaint);
     694             :                         }
     695             :                 }
     696           0 :                 break;
     697           0 :                 case 3:
     698           0 :                         lsr_read_extension(lsr, name);
     699           0 :                         break;
     700             :                 }
     701             :         }
     702         193 : }
     703             : 
     704          15 : static void lsr_read_string_attribute(GF_LASeRCodec *lsr, GF_Node *elt, u32 tag, char *name)
     705             : {
     706             :         u32 val;
     707          15 :         GF_LSR_READ_INT(lsr, val, 1, name);
     708          15 :         if (val) {
     709             :                 GF_FieldInfo info;
     710           0 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, tag, GF_TRUE, GF_FALSE, &info);
     711           0 :                 lsr_read_byte_align_string(lsr, info.far_ptr, name);
     712             :         }
     713          15 : }
     714         492 : static void lsr_read_id(GF_LASeRCodec *lsr, GF_Node *n)
     715             : {
     716             :         GF_FieldInfo info;
     717             :         u32 val, id, i, count;
     718             :         char *name;
     719         492 :         GF_LSR_READ_INT(lsr, val, 1, "has_id");
     720         873 :         if (!val) return;
     721             : 
     722             :         name = NULL;
     723         111 :         id = 1+lsr_read_vluimsbf5(lsr, "ID");
     724         111 :         gf_node_set_id(n, id, name);
     725             : 
     726         111 :         GF_LSR_READ_INT(lsr, val, 1, "reserved");
     727             :         /*currently not used*/
     728         111 :         if (val) {
     729           0 :                 u32 len = lsr_read_vluimsbf5(lsr, "len");
     730           0 :                 GF_LSR_READ_INT(lsr, val, len, "reserved");
     731             :         }
     732             : 
     733             :         /*update all pending HREFs*/
     734         111 :         count = gf_list_count(lsr->deferred_hrefs);
     735         144 :         for (i=0; i<count; i++) {
     736          33 :                 XMLRI *href = (XMLRI *)gf_list_get(lsr->deferred_hrefs, i);
     737          33 :                 char *str_id = href->string;
     738          33 :                 if (str_id[0] == '#') str_id++;
     739             :                 /*skip 'N'*/
     740          33 :                 str_id++;
     741          33 :                 if (id == (1 + (u32) atoi(str_id))) {
     742          30 :                         href->target = (SVG_Element*) n;
     743          30 :                         gf_free(href->string);
     744          30 :                         href->string = NULL;
     745          30 :                         gf_list_rem(lsr->deferred_hrefs, i);
     746          30 :                         i--;
     747          30 :                         count--;
     748             :                 }
     749             :         }
     750             : 
     751             :         /*update unresolved listeners*/
     752         111 :         count = gf_list_count(lsr->deferred_listeners);
     753         111 :         for (i=0; i<count; i++) {
     754             :                 GF_Node *par;
     755             :                 XMLRI *observer = NULL;
     756           0 :                 GF_Node *listener = (GF_Node *)gf_list_get(lsr->deferred_listeners, i);
     757             : 
     758             :                 par = NULL;
     759           0 :                 if (gf_node_get_attribute_by_tag(listener, TAG_XMLEV_ATT_observer, GF_FALSE, GF_FALSE, &info) == GF_OK) {
     760           0 :                         observer = (XMLRI*)info.far_ptr;
     761           0 :                         if (observer->type == XMLRI_ELEMENTID) {
     762           0 :                                 if (!observer->target) continue;
     763             :                                 else par = (GF_Node*)observer->target;
     764             :                         }
     765             :                 }
     766           0 :                 if (gf_node_get_attribute_by_tag(listener, TAG_XMLEV_ATT_target, GF_FALSE, GF_FALSE, &info) == GF_OK) {
     767           0 :                         if (((XMLRI*)info.far_ptr)->type == XMLRI_ELEMENTID) {
     768           0 :                                 if (!((XMLRI*)info.far_ptr)->target) continue;
     769           0 :                                 else if (!par) par = (GF_Node*)((XMLRI*)info.far_ptr)->target;
     770             :                         }
     771             :                 }
     772             :                 /*FIXME - double check with XML events*/
     773           0 :                 if (!par && !observer) {
     774           0 :                         if (gf_node_get_attribute_by_tag(listener, TAG_XMLEV_ATT_event, GF_FALSE, GF_FALSE, &info) == GF_OK) {
     775           0 :                                 XMLEV_Event *ev = (XMLEV_Event *)info.far_ptr;
     776             :                                 /*all non-UI get attched to root*/
     777           0 :                                 if (ev && (ev->type>GF_EVENT_MOUSEWHEEL)) {
     778           0 :                                         par = (GF_Node*) lsr->current_root;
     779             :                                 }
     780             :                         }
     781             :                 }
     782             : 
     783             :                 assert(par);
     784           0 :                 gf_node_dom_listener_add(par, listener);
     785           0 :                 gf_list_rem(lsr->deferred_listeners, i);
     786           0 :                 i--;
     787           0 :                 count--;
     788             :         }
     789             : 
     790             :         /*update all pending animations*/
     791         111 :         count = gf_list_count(lsr->deferred_anims);
     792         432 :         for (i=0; i<count; i++) {
     793         321 :                 SVG_Element *elt = (SVG_Element *)gf_list_get(lsr->deferred_anims, i);
     794         321 :                 if (lsr_setup_smil_anim(lsr, elt, NULL)) {
     795          27 :                         gf_list_rem(lsr->deferred_anims, i);
     796          27 :                         i--;
     797          27 :                         count--;
     798          27 :                         gf_node_init((GF_Node*)elt);
     799             :                 }
     800             :         }
     801             : }
     802             : 
     803             : static Fixed lsr_translate_coords(GF_LASeRCodec *lsr, u32 val, u32 nb_bits)
     804             : {
     805             : #ifdef GPAC_FIXED_POINT
     806             :         if (val >> (nb_bits-1) ) {
     807             :                 s32 neg = (s32) val - (1<<nb_bits);
     808             :                 if (neg < -FIX_ONE / 2)
     809             :                         return 2 * gf_divfix(INT2FIX(neg/2), lsr->res_factor);
     810             :                 return gf_divfix(INT2FIX(neg), lsr->res_factor);
     811             :         } else {
     812             :                 if (val > FIX_ONE / 2)
     813             :                         return 2 * gf_divfix(INT2FIX(val/2), lsr->res_factor);
     814             :                 return gf_divfix(INT2FIX(val), lsr->res_factor);
     815             :         }
     816             : #else
     817        1213 :         if (val >> (nb_bits-1) ) {
     818         171 :                 s32 neg = (s32) val - (1<<nb_bits);
     819         171 :                 return gf_divfix(INT2FIX(neg), lsr->res_factor);
     820             :         } else {
     821        1042 :                 return gf_divfix(INT2FIX(val), lsr->res_factor);
     822             :         }
     823             : #endif
     824             : }
     825             : 
     826             : static Fixed lsr_translate_scale(GF_LASeRCodec *lsr, u32 val)
     827             : {
     828          30 :         if (val >> (lsr->coord_bits-1) ) {
     829           6 :                 s32 v = val - (1<<lsr->coord_bits);
     830           6 :                 return INT2FIX(v) / 256 ;
     831             :         } else {
     832          24 :                 return INT2FIX(val) / 256;
     833             :         }
     834             : }
     835          21 : static void lsr_read_matrix(GF_LASeRCodec *lsr, SVG_Transform *mx)
     836             : {
     837             :         u32 flag;
     838          42 :         gf_mx2d_init(mx->mat);
     839          21 :         mx->is_ref = 0;
     840          21 :         GF_LSR_READ_INT(lsr, flag, 1, "isNotMatrix");
     841          21 :         if (flag) {
     842           3 :                 GF_LSR_READ_INT(lsr, flag, 1, "isRef");
     843           3 :                 if (flag) {
     844           3 :                         GF_LSR_READ_INT(lsr, flag, 1, "hasXY");
     845           3 :                         if (flag) {
     846           3 :                                 mx->mat.m[2] = lsr_read_fixed_16_8(lsr, "valueX");
     847           3 :                                 mx->mat.m[5] = lsr_read_fixed_16_8(lsr, "valueY");
     848             :                         }
     849             :                 } else {
     850           0 :                         lsr_read_extension(lsr, "ext");
     851             :                 }
     852             :         } else {
     853          18 :                 lsr->coord_bits += lsr->scale_bits;
     854          18 :                 GF_LSR_READ_INT(lsr, flag, 1, "xx_yy_present");
     855          18 :                 if (flag) {
     856           9 :                         GF_LSR_READ_INT(lsr, flag, lsr->coord_bits, "xx");
     857          18 :                         mx->mat.m[0] = lsr_translate_scale(lsr, flag);
     858           9 :                         GF_LSR_READ_INT(lsr, flag, lsr->coord_bits, "yy");
     859          18 :                         mx->mat.m[4] = lsr_translate_scale(lsr, flag);
     860             :                 } else {
     861           9 :                         mx->mat.m[0] = mx->mat.m[4] = FIX_ONE;
     862             :                 }
     863          18 :                 GF_LSR_READ_INT(lsr, flag, 1, "xy_yx_present");
     864          18 :                 if (flag) {
     865           6 :                         GF_LSR_READ_INT(lsr, flag, lsr->coord_bits, "xy");
     866          12 :                         mx->mat.m[1] = lsr_translate_scale(lsr, flag);
     867           6 :                         GF_LSR_READ_INT(lsr, flag, lsr->coord_bits, "yx");
     868          12 :                         mx->mat.m[3] = lsr_translate_scale(lsr, flag);
     869             :                 }
     870             : 
     871          18 :                 GF_LSR_READ_INT(lsr, flag, 1, "xz_yz_present");
     872          18 :                 if (flag) {
     873          12 :                         GF_LSR_READ_INT(lsr, flag, lsr->coord_bits, "xz");
     874          24 :                         mx->mat.m[2] = lsr_translate_coords(lsr, flag, lsr->coord_bits);
     875          12 :                         GF_LSR_READ_INT(lsr, flag, lsr->coord_bits, "yz");
     876          24 :                         mx->mat.m[5] = lsr_translate_coords(lsr, flag, lsr->coord_bits);
     877             :                 }
     878          18 :                 lsr->coord_bits -= lsr->scale_bits;
     879             :         }
     880          21 : }
     881             : 
     882          51 : static Fixed lsr_read_fixed_clamp(GF_LASeRCodec *lsr, const char *name)
     883             : {
     884             :         s32 val;
     885          51 :         GF_LSR_READ_INT(lsr, val, 8, name);
     886          51 :         return INT2FIX(val) / 255;
     887             : }
     888             : 
     889          30 : static void lsr_read_focus(GF_LASeRCodec *lsr, SVG_Focus *foc, const char *name)
     890             : {
     891             :         u32 flag;
     892             : 
     893          30 :         if (foc->target.string) {
     894           0 :                 gf_free(foc->target.string);
     895           0 :                 foc->target.string = NULL;
     896             :         }
     897          30 :         if (foc->target.target) foc->target.target = NULL;
     898          30 :         gf_node_unregister_iri(lsr->sg, &foc->target);
     899             : 
     900          30 :         GF_LSR_READ_INT(lsr, flag, 1, "isEnum");
     901          30 :         if (flag) {
     902          27 :                 GF_LSR_READ_INT(lsr, foc->type, 1, "enum");
     903             :         } else {
     904           3 :                 foc->type = SVG_FOCUS_IRI;
     905           3 :                 lsr_read_codec_IDREF(lsr, &foc->target, "id");
     906             :         }
     907          30 : }
     908             : 
     909          54 : static void lsr_restore_base(GF_LASeRCodec *lsr, SVG_Element *elt, SVG_Element *base, Bool reset_fill, Bool reset_stroke)
     910             : {
     911             :         GF_Err e;
     912             :         GF_FieldInfo f_base, f_clone;
     913             :         SVGAttribute *att;
     914             : 
     915             :         /*clone all propertie from base*/
     916          54 :         att = base->attributes;
     917         246 :         while (att) {
     918             :                 Bool is_fill, is_stroke;
     919             :                 is_fill = is_stroke = GF_FALSE;
     920         192 :                 switch (att->tag) {
     921             :                 /*for all properties*/
     922           6 :                 case TAG_SVG_ATT_fill:
     923             :                         is_fill = GF_TRUE;
     924             :                         break;
     925           9 :                 case TAG_SVG_ATT_stroke:
     926             :                         is_stroke = GF_TRUE;
     927             :                         break;
     928             :                 case TAG_SVG_ATT_audio_level:
     929             :                 case TAG_SVG_ATT_color:
     930             :                 case TAG_SVG_ATT_color_rendering:
     931             :                 case TAG_SVG_ATT_display:
     932             :                 case TAG_SVG_ATT_display_align:
     933             :                 case TAG_SVG_ATT_fill_opacity:
     934             :                 case TAG_SVG_ATT_fill_rule:
     935             :                 case TAG_SVG_ATT_font_family:
     936             :                 case TAG_SVG_ATT_font_size:
     937             :                 case TAG_SVG_ATT_font_style:
     938             :                 case TAG_SVG_ATT_font_variant:
     939             :                 case TAG_SVG_ATT_font_weight:
     940             :                 case TAG_SVG_ATT_image_rendering:
     941             :                 case TAG_SVG_ATT_line_increment:
     942             :                 case TAG_SVG_ATT_opacity:
     943             :                 case TAG_SVG_ATT_pointer_events:
     944             :                 case TAG_SVG_ATT_shape_rendering:
     945             :                 case TAG_SVG_ATT_solid_color:
     946             :                 case TAG_SVG_ATT_solid_opacity:
     947             :                 case TAG_SVG_ATT_stop_color:
     948             :                 case TAG_SVG_ATT_stop_opacity:
     949             :                 case TAG_SVG_ATT_stroke_dasharray:
     950             :                 case TAG_SVG_ATT_stroke_dashoffset:
     951             :                 case TAG_SVG_ATT_stroke_linecap:
     952             :                 case TAG_SVG_ATT_stroke_linejoin:
     953             :                 case TAG_SVG_ATT_stroke_miterlimit:
     954             :                 case TAG_SVG_ATT_stroke_opacity:
     955             :                 case TAG_SVG_ATT_stroke_width:
     956             :                 case TAG_SVG_ATT_text_align:
     957             :                 case TAG_SVG_ATT_text_anchor:
     958             :                 case TAG_SVG_ATT_text_rendering:
     959             :                 case TAG_SVG_ATT_vector_effect:
     960             :                 case TAG_SVG_ATT_viewport_fill:
     961             :                 case TAG_SVG_ATT_viewport_fill_opacity:
     962             :                 case TAG_SVG_ATT_visibility:
     963             :                 /*and xml:_class*/
     964             :                 case TAG_SVG_ATT__class:
     965             :                 case TAG_SVG_ATT_externalResourcesRequired:
     966             :                         break;
     967             : 
     968             :                 /*pathLength for path*/
     969             :                 case TAG_SVG_ATT_pathLength:
     970             :                         break;
     971             :                 /*rx & ry for rect*/
     972           0 :                 case TAG_SVG_ATT_rx:
     973             :                 case TAG_SVG_ATT_ry:
     974           0 :                         if (base->sgprivate->tag!=TAG_SVG_rect) {
     975           0 :                                 att = att->next;
     976           0 :                                 continue;
     977             :                         }
     978             :                         break;
     979             :                 /*x & y for use*/
     980          72 :                 case TAG_SVG_ATT_x:
     981             :                 case TAG_SVG_ATT_y:
     982          72 :                         if (base->sgprivate->tag!=TAG_SVG_use) {
     983          72 :                                 att = att->next;
     984          72 :                                 continue;
     985             :                         }
     986             :                         break;
     987             :                 /*editable & rotate for text*/
     988           0 :                 case TAG_SVG_ATT_editable:
     989             :                 case TAG_SVG_ATT_rotate:
     990           0 :                         if (base->sgprivate->tag!=TAG_SVG_text) {
     991           0 :                                 att = att->next;
     992           0 :                                 continue;
     993             :                         }
     994             :                         break;
     995             :                 case TAG_SVG_ATT_transform:
     996             :                         break;
     997          90 :                 default:
     998          90 :                         att = att->next;
     999          90 :                         continue;
    1000             :                 }
    1001             :                 /*clone field*/
    1002          30 :                 e = gf_node_get_attribute_by_tag((GF_Node*)elt, att->tag, GF_TRUE, GF_FALSE, &f_clone);
    1003          30 :                 if (e) goto err_exit;
    1004          30 :                 f_base.fieldIndex = att->tag;
    1005          30 :                 f_base.fieldType = att->data_type;
    1006          30 :                 f_base.far_ptr = att->data;
    1007          30 :                 e = gf_svg_attributes_copy(&f_clone, &f_base, GF_FALSE);
    1008          30 :                 if (e) goto err_exit;
    1009             : 
    1010          30 :                 if (is_fill && reset_fill) {
    1011           3 :                         SVG_Paint*p = (SVG_Paint*)f_clone.far_ptr;
    1012           3 :                         if (p->iri.string) gf_free(p->iri.string);
    1013             :                         memset(p, 0, sizeof(SVG_Paint));
    1014             :                 }
    1015          30 :                 if (is_stroke && reset_stroke) {
    1016           0 :                         SVG_Paint*p = (SVG_Paint*)f_clone.far_ptr;
    1017           0 :                         if (p->iri.string) gf_free(p->iri.string);
    1018             :                         memset(p, 0, sizeof(SVG_Paint));
    1019             :                 }
    1020          30 :                 att = att->next;
    1021             :         }
    1022          54 :         return;
    1023             : 
    1024           0 : err_exit:
    1025           0 :         lsr->last_error = e;
    1026             : }
    1027             : 
    1028             : 
    1029             : static u32 lsr_to_dom_key(u32 lsr_k)
    1030             : {
    1031             :         switch (lsr_k) {
    1032             :         case 0:
    1033             :                 return GF_KEY_STAR;
    1034             :         case 1:
    1035             :                 return GF_KEY_0;
    1036             :         case 2:
    1037             :                 return GF_KEY_1;
    1038             :         case 3:
    1039             :                 return GF_KEY_2;
    1040             :         case 4:
    1041             :                 return GF_KEY_3;
    1042             :         case 5:
    1043             :                 return GF_KEY_4;
    1044             :         case 6:
    1045             :                 return GF_KEY_5;
    1046             :         case 7:
    1047             :                 return GF_KEY_6;
    1048             :         case 8:
    1049             :                 return GF_KEY_7;
    1050             :         case 9:
    1051             :                 return GF_KEY_8;
    1052             :         case 10:
    1053             :                 return GF_KEY_9;
    1054             :         case 12:
    1055             :                 return GF_KEY_DOWN;
    1056             :         case 14:
    1057             :                 return GF_KEY_LEFT;
    1058             :         case 16:
    1059             :                 return GF_KEY_RIGHT;
    1060             :         case 20:
    1061             :                 return GF_KEY_UP;
    1062             :         /*WHAT IS ANY_KEY (11) ??*/
    1063             :         case 13:
    1064             :                 return GF_KEY_ENTER;
    1065             :         case 15:
    1066             :                 return GF_KEY_ESCAPE;
    1067             :         case 17:
    1068             :                 return GF_KEY_NUMBER;
    1069             :         case 18:
    1070             :                 return GF_KEY_CELL_SOFT1;
    1071             :         case 19:
    1072             :                 return GF_KEY_CELL_SOFT2;
    1073             :         default:
    1074             :                 /*use '*' by default ... */
    1075             :                 return 0;
    1076             :         }
    1077             : }
    1078             : 
    1079         168 : static void lsr_read_event_type(GF_LASeRCodec *lsr, XMLEV_Event *evtType)
    1080             : {
    1081             :         u32 flag;
    1082             :         memset(evtType, 0, sizeof(XMLEV_Event));
    1083             : 
    1084         168 :         GF_LSR_READ_INT(lsr, flag, 1, "choice");
    1085         168 :         if (!flag) {
    1086             :                 char *evtName, *sep;
    1087           6 :                 evtName = NULL;
    1088           6 :                 lsr_read_byte_align_string(lsr, &evtName, "evtString");
    1089           6 :                 evtType->type = evtType->parameter = 0;
    1090           6 :                 if (evtName) {
    1091           6 :                         sep = strchr(evtName, '(');
    1092           6 :                         if (sep) {
    1093             :                                 char *param;
    1094           3 :                                 sep[0] = 0;
    1095           3 :                                 evtType->type = gf_dom_event_type_by_name(evtName);
    1096           3 :                                 sep[0] = '(';
    1097           3 :                                 param = sep+1;
    1098           3 :                                 sep = strchr(evtName, ')');
    1099           3 :                                 if (sep) sep[0]=0;
    1100           3 :                                 if (evtType->type==GF_EVENT_REPEAT) {
    1101           0 :                                         evtType->parameter = atoi(param);
    1102             :                                 } else {
    1103           3 :                                         evtType->parameter = gf_dom_get_key_type(param);
    1104             :                                 }
    1105             :                         } else {
    1106           3 :                                 evtType->type = gf_dom_event_type_by_name(evtName);
    1107             :                         }
    1108           6 :                         gf_free(evtName);
    1109             :                 }
    1110             :         } else {
    1111         162 :                 evtType->parameter = 0;
    1112         162 :                 GF_LSR_READ_INT(lsr, flag, 6, "event");
    1113         162 :                 switch (flag) {
    1114           9 :                 case LSR_EVT_abort:
    1115           9 :                         evtType->type = GF_EVENT_ABORT;
    1116           9 :                         break;
    1117           3 :                 case LSR_EVT_accessKey:
    1118           3 :                         evtType->type = GF_EVENT_KEYDOWN;
    1119           3 :                         break;
    1120           3 :                 case LSR_EVT_activate:
    1121           3 :                         evtType->type = GF_EVENT_ACTIVATE;
    1122           3 :                         break;
    1123           3 :                 case LSR_EVT_activatedEvent:
    1124           3 :                         evtType->type = GF_EVENT_ACTIVATED;
    1125           3 :                         break;
    1126           3 :                 case LSR_EVT_beginEvent:
    1127           3 :                         evtType->type = GF_EVENT_BEGIN_EVENT;
    1128           3 :                         break;
    1129           3 :                 case LSR_EVT_click:
    1130           3 :                         evtType->type = GF_EVENT_CLICK;
    1131           3 :                         break;
    1132           3 :                 case LSR_EVT_deactivatedEvent:
    1133           3 :                         evtType->type = GF_EVENT_DEACTIVATED;
    1134           3 :                         break;
    1135           3 :                 case LSR_EVT_endEvent:
    1136           3 :                         evtType->type = GF_EVENT_END_EVENT;
    1137           3 :                         break;
    1138           3 :                 case LSR_EVT_error:
    1139           3 :                         evtType->type = GF_EVENT_ERROR;
    1140           3 :                         break;
    1141           3 :                 case LSR_EVT_executionTime:
    1142           3 :                         evtType->type = GF_EVENT_EXECUTION_TIME;
    1143           3 :                         break;
    1144           3 :                 case LSR_EVT_focusin:
    1145           3 :                         evtType->type = GF_EVENT_FOCUSIN;
    1146           3 :                         break;
    1147           3 :                 case LSR_EVT_focusout:
    1148           3 :                         evtType->type = GF_EVENT_FOCUSOUT;
    1149           3 :                         break;
    1150           0 :                 case LSR_EVT_keydown:
    1151           0 :                         evtType->type = GF_EVENT_KEYDOWN;
    1152           0 :                         break;
    1153           3 :                 case LSR_EVT_keyup:
    1154           3 :                         evtType->type = GF_EVENT_KEYUP;
    1155           3 :                         break;
    1156           3 :                 case LSR_EVT_load:
    1157           3 :                         evtType->type = GF_EVENT_LOAD;
    1158           3 :                         break;
    1159          66 :                 case LSR_EVT_longAccessKey:
    1160          66 :                         evtType->type = GF_EVENT_LONGKEYPRESS;
    1161          66 :                         break;
    1162           3 :                 case LSR_EVT_mousedown:
    1163           3 :                         evtType->type = GF_EVENT_MOUSEDOWN;
    1164           3 :                         break;
    1165           3 :                 case LSR_EVT_mousemove:
    1166           3 :                         evtType->type = GF_EVENT_MOUSEMOVE;
    1167           3 :                         break;
    1168           3 :                 case LSR_EVT_mouseout:
    1169           3 :                         evtType->type = GF_EVENT_MOUSEOUT;
    1170           3 :                         break;
    1171           3 :                 case LSR_EVT_mouseover:
    1172           3 :                         evtType->type = GF_EVENT_MOUSEOVER;
    1173           3 :                         break;
    1174           3 :                 case LSR_EVT_mouseup:
    1175           3 :                         evtType->type = GF_EVENT_MOUSEUP;
    1176           3 :                         break;
    1177           3 :                 case LSR_EVT_pause:
    1178           3 :                         evtType->type = GF_EVENT_PAUSE;
    1179           3 :                         break;
    1180           3 :                 case LSR_EVT_pausedEvent:
    1181           3 :                         evtType->type = GF_EVENT_PAUSED_EVENT;
    1182           3 :                         break;
    1183           3 :                 case LSR_EVT_play:
    1184           3 :                         evtType->type = GF_EVENT_PLAY;
    1185           3 :                         break;
    1186           3 :                 case LSR_EVT_repeatEvent:
    1187           3 :                         evtType->type = GF_EVENT_REPEAT_EVENT;
    1188           3 :                         break;
    1189           3 :                 case LSR_EVT_repeatKey:
    1190           3 :                         evtType->type = GF_EVENT_REPEAT_KEY;
    1191           3 :                         break;
    1192           3 :                 case LSR_EVT_resize:
    1193           3 :                         evtType->type = GF_EVENT_RESIZE;
    1194           3 :                         break;
    1195           3 :                 case LSR_EVT_resumedEvent:
    1196           3 :                         evtType->type = GF_EVENT_RESUME_EVENT;
    1197           3 :                         break;
    1198           3 :                 case LSR_EVT_scroll:
    1199           3 :                         evtType->type = GF_EVENT_SCROLL;
    1200           3 :                         break;
    1201           0 :                 case LSR_EVT_shortAccessKey:
    1202           0 :                         evtType->type = GF_EVENT_SHORT_ACCESSKEY;
    1203           0 :                         break;
    1204           3 :                 case LSR_EVT_textinput:
    1205           3 :                         evtType->type = GF_EVENT_TEXTINPUT;
    1206           3 :                         break;
    1207           3 :                 case LSR_EVT_unload:
    1208           3 :                         evtType->type = GF_EVENT_UNLOAD;
    1209           3 :                         break;
    1210           3 :                 case LSR_EVT_zoom:
    1211           3 :                         evtType->type = GF_EVENT_ZOOM;
    1212           3 :                         break;
    1213           0 :                 default:
    1214           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[LASeR] Undefined LASeR event %d\n", flag));
    1215             :                         break;
    1216             :                 }
    1217             :                 switch (flag) {
    1218          72 :                 case LSR_EVT_accessKey:
    1219             :                 case LSR_EVT_longAccessKey:
    1220             :                 case LSR_EVT_repeatKey:
    1221             :                 case LSR_EVT_shortAccessKey:
    1222          72 :                         evtType->parameter = lsr_read_vluimsbf5(lsr, "keyCode");
    1223          72 :                         evtType->parameter  = lsr_to_dom_key(evtType->parameter);
    1224          72 :                         break;
    1225             :                 }
    1226             :         }
    1227         168 : }
    1228             : 
    1229          63 : static SMIL_Time *lsr_read_smil_time(GF_LASeRCodec *lsr, GF_Node *n)
    1230             : {
    1231             :         SMIL_Time *t;
    1232             :         u32 val;
    1233             : 
    1234          63 :         GF_SAFEALLOC(t, SMIL_Time);
    1235          63 :         if (!t) return NULL;
    1236          63 :         t->type = GF_SMIL_TIME_CLOCK;
    1237             : 
    1238          63 :         GF_LSR_READ_INT(lsr, val, 1, "hasEvent");
    1239          63 :         if (val) {
    1240           3 :                 t->type = GF_SMIL_TIME_EVENT;
    1241           3 :                 GF_LSR_READ_INT(lsr, val, 1, "hasIdentifier");
    1242           3 :                 if (val) {
    1243             :                         XMLRI iri;
    1244           3 :                         iri.type = 0xFF;
    1245           3 :                         iri.string = NULL;
    1246           3 :                         lsr_read_codec_IDREF(lsr, &iri, "idref");
    1247           3 :                         gf_node_unregister_iri(lsr->sg, &iri);
    1248           3 :                         if (iri.string) {
    1249           0 :                                 t->element_id = iri.string;
    1250             :                         } else {
    1251           3 :                                 t->element = (GF_Node *)iri.target;
    1252             :                         }
    1253             :                 }
    1254           3 :                 lsr_read_event_type(lsr, &t->event);
    1255           3 :                 if (t->event.type==GF_EVENT_EXECUTION_TIME) {
    1256           0 :                         t->type = GF_SMIL_TIME_CLOCK;
    1257           0 :                         t->clock = gf_node_get_scene_time(n);
    1258             :                 }
    1259             :         }
    1260          63 :         GF_LSR_READ_INT(lsr, val, 1, "hasClock");
    1261          63 :         if (val) {
    1262             :                 u32 now;
    1263          45 :                 GF_LSR_READ_INT(lsr, val, 1, "sign");
    1264          45 :                 now = lsr_read_vluimsbf5(lsr, "value");
    1265          45 :                 t->clock = now;
    1266          45 :                 t->clock /= lsr->time_resolution;
    1267          45 :                 if (val) t->clock *= -1;
    1268             :         }
    1269             :         return t;
    1270             : }
    1271             : 
    1272         281 : static void lsr_read_smil_times(GF_LASeRCodec *lsr, GF_Node *n, u32 tag, SMIL_Times *times, const char *name, Bool skipable)
    1273             : {
    1274             :         GF_FieldInfo info;
    1275             :         SMIL_Time *v;
    1276             :         u32 val, i, count;
    1277             : 
    1278         281 :         if (skipable) {
    1279         142 :                 GF_LSR_READ_INT(lsr, val, 1, name);
    1280         230 :                 if (!val) return;
    1281             :         }
    1282         202 :         if (!times) {
    1283          63 :                 lsr->last_error = gf_node_get_attribute_by_tag(n, tag, GF_TRUE, GF_FALSE, &info);
    1284          63 :                 times = (SMIL_Times*)info.far_ptr;
    1285             :         }
    1286             : 
    1287         202 :         while (gf_list_count(*times)) {
    1288           0 :                 v = (SMIL_Time *)gf_list_last(*times);
    1289           0 :                 gf_list_rem_last(*times);
    1290           0 :                 if (v->element_id) gf_free(v->element_id);
    1291           0 :                 gf_free(v);
    1292             :         }
    1293             : 
    1294         202 :         GF_LSR_READ_INT(lsr, val, 1, "choice");
    1295         202 :         if (val) {
    1296           9 :                 GF_SAFEALLOC(v, SMIL_Time);
    1297           9 :                 if (v) {
    1298           9 :                         v->type = GF_SMIL_TIME_INDEFINITE;
    1299           9 :                         gf_list_add(*times, v);
    1300             :                 }
    1301             :                 return;
    1302             :         }
    1303         193 :         count = lsr_read_vluimsbf5(lsr, "count");
    1304         253 :         for (i=0; i<count; i++) {
    1305          60 :                 v = lsr_read_smil_time(lsr, n);
    1306          60 :                 gf_list_add(*times, v);
    1307             :         }
    1308             : }
    1309             : 
    1310         143 : static void lsr_read_duration_ex(GF_LASeRCodec *lsr, GF_Node *n, u32 tag, SMIL_Duration *smil, const char *name, Bool skipable)
    1311             : {
    1312             :         GF_FieldInfo info;
    1313             :         u32 val = 1;
    1314             : 
    1315         143 :         if (skipable) {
    1316         137 :                 GF_LSR_READ_INT(lsr, val, 1, name);
    1317         157 :                 if (!val) return;
    1318             :         }
    1319         123 :         if (!smil) {
    1320         117 :                 lsr->last_error = gf_node_get_attribute_by_tag(n, tag, GF_TRUE, GF_FALSE, &info);
    1321         117 :                 if (lsr->last_error) return;
    1322         117 :                 smil = (SMIL_Duration *)info.far_ptr;
    1323             :         }
    1324         123 :         smil->type = 0;
    1325         123 :         smil->clock_value=0;
    1326             : 
    1327         123 :         GF_LSR_READ_INT(lsr, val, 1, "choice");
    1328         123 :         if (val) {
    1329           3 :                 GF_LSR_READ_INT(lsr, smil->type, 2, "time");
    1330             :         } else {
    1331             :                 Bool sign;
    1332             :                 u32 now;
    1333         120 :                 GF_LSR_READ_INT(lsr, sign, 1, "sign");
    1334         120 :                 now = lsr_read_vluimsbf5(lsr, "value");
    1335         120 :                 smil->clock_value = now;
    1336         120 :                 smil->clock_value /= lsr->time_resolution;
    1337         120 :                 if (sign) smil->clock_value *= -1;
    1338         120 :                 smil->type = SMIL_DURATION_DEFINED;
    1339             :         }
    1340             : }
    1341             : static void lsr_read_duration(GF_LASeRCodec *lsr, GF_Node *n)
    1342             : {
    1343         137 :         lsr_read_duration_ex(lsr, n, TAG_SVG_ATT_dur, NULL, "dur", GF_TRUE);
    1344             : }
    1345             : /*TODO Add decent error checking...*/
    1346         438 : static void lsr_read_rare_full(GF_LASeRCodec *lsr, GF_Node *n)
    1347             : {
    1348             :         GF_FieldInfo info;
    1349             :         u32 i, nb_rare, field_rare;
    1350             :         s32 field_tag;
    1351             : 
    1352         438 :         GF_LSR_READ_INT(lsr, nb_rare, 1, "has_rare");
    1353         623 :         if (!nb_rare) return;
    1354         253 :         GF_LSR_READ_INT(lsr, nb_rare, 6, "nbOfAttributes");
    1355             : 
    1356         448 :         for (i=0; i<nb_rare; i++) {
    1357         448 :                 GF_LSR_READ_INT(lsr, field_rare, 6, "attributeRARE");
    1358             : 
    1359             :                 /*lsr extend*/
    1360         448 :                 if (field_rare==49) {
    1361             :                         u32 extID, len, j;
    1362             :                         while (1) {
    1363          15 :                                 GF_LSR_READ_INT(lsr, extID, lsr->info->cfg.extensionIDBits, "extensionID");
    1364          15 :                                 len = lsr_read_vluimsbf5(lsr, "len");
    1365          15 :                                 if (extID==2) {
    1366          15 :                                         GF_LSR_READ_INT(lsr, len, 2, "nbOfAttributes");
    1367          15 :                                         for (j=0; j<len; j++) {
    1368          15 :                                                 GF_LSR_READ_INT(lsr, extID, 3, "attributeRARE");
    1369          15 :                                                 switch (extID) {
    1370           3 :                                                 case 0:
    1371           3 :                                                         lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_syncMaster, GF_TRUE, GF_FALSE, &info);
    1372           3 :                                                         GF_LSR_READ_INT(lsr, *(SVG_Boolean *)info.far_ptr, 1, "syncMaster");
    1373             :                                                         break;
    1374           3 :                                                 case 1:
    1375           3 :                                                         lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_focusHighlight, GF_TRUE, GF_FALSE, &info);
    1376           3 :                                                         GF_LSR_READ_INT(lsr, *(SVG_FocusHighlight *)info.far_ptr, 2, "focusHighlight");
    1377             :                                                         break;
    1378           3 :                                                 case 2:
    1379           3 :                                                         lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_initialVisibility, GF_TRUE, GF_FALSE, &info);
    1380           3 :                                                         GF_LSR_READ_INT(lsr, *(SVG_InitialVisibility *)info.far_ptr, 2, "initialVisibility");
    1381             :                                                         break;
    1382           3 :                                                 case 3:
    1383           3 :                                                         lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_fullscreen, GF_TRUE, GF_FALSE, &info);
    1384           3 :                                                         GF_LSR_READ_INT(lsr, *(SVG_Boolean *)info.far_ptr, 1, "fullscreen");
    1385             :                                                         break;
    1386           3 :                                                 case 4:
    1387           3 :                                                         lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_requiredFonts, GF_TRUE, GF_FALSE, &info);
    1388           3 :                                                         lsr_read_byte_align_string_list(lsr, *(GF_List **)info.far_ptr, "requiredFonts", GF_FALSE, GF_TRUE);
    1389           3 :                                                         break;
    1390             :                                                 }
    1391             :                                         }
    1392             :                                 } else {
    1393           0 :                                         gf_bs_read_int(lsr->bs, len);
    1394             :                                 }
    1395          15 :                                 GF_LSR_READ_INT(lsr, extID, 1, "hasNextExtension");
    1396          15 :                                 if (!extID) break;
    1397             :                         }
    1398          15 :                         continue;
    1399             :                 }
    1400         433 :                 field_tag = gf_lsr_rare_type_to_attribute(field_rare);
    1401         433 :                 if (field_tag==-1) {
    1402             :                         return;
    1403             :                 }
    1404         433 :                 lsr->last_error = gf_node_get_attribute_by_tag(n, field_tag, GF_TRUE, GF_FALSE, &info);
    1405         433 :                 if (!info.far_ptr) lsr->last_error = GF_NOT_SUPPORTED;
    1406         433 :                 if (lsr->last_error) return;
    1407             : 
    1408         433 :                 switch (field_tag) {
    1409           0 :                 case TAG_SVG_ATT__class:
    1410           0 :                         lsr_read_byte_align_string(lsr, info.far_ptr, "class");
    1411           0 :                         break;
    1412             :                 /*properties*/
    1413           3 :                 case TAG_SVG_ATT_audio_level:
    1414           3 :                         ((SVG_Number*)info.far_ptr)->value = lsr_read_fixed_clamp(lsr, "audio-level");
    1415           3 :                         break;
    1416           6 :                 case TAG_SVG_ATT_color:
    1417           6 :                         lsr_read_paint(lsr, (SVG_Paint *)info.far_ptr, "color");
    1418           6 :                         break;
    1419           6 :                 case TAG_SVG_ATT_color_rendering:
    1420           6 :                         GF_LSR_READ_INT(lsr, *(SVG_RenderingHint*)info.far_ptr, 2, "color-rendering");
    1421             :                         break;
    1422          12 :                 case TAG_SVG_ATT_display:
    1423          12 :                         GF_LSR_READ_INT(lsr, *(SVG_Display*)info.far_ptr, 5, "display");
    1424             :                         break;
    1425           3 :                 case TAG_SVG_ATT_display_align:
    1426           3 :                         GF_LSR_READ_INT(lsr, *(SVG_DisplayAlign*)info.far_ptr, 3, "display-align");
    1427             :                         break;
    1428           6 :                 case TAG_SVG_ATT_fill_opacity:
    1429           6 :                         ((SVG_Number*)info.far_ptr)->type = SVG_NUMBER_VALUE;
    1430           6 :                         ((SVG_Number*)info.far_ptr)->value = lsr_read_fixed_clamp(lsr, "fill-opacity");
    1431           6 :                         break;
    1432           3 :                 case TAG_SVG_ATT_fill_rule:
    1433           3 :                         GF_LSR_READ_INT(lsr, *(SVG_FillRule*)info.far_ptr, 2, "fill-rule");
    1434             :                         break;
    1435           3 :                 case TAG_SVG_ATT_image_rendering:
    1436           3 :                         GF_LSR_READ_INT(lsr, *(SVG_RenderingHint*)info.far_ptr, 2, "image-rendering");
    1437             :                         break;
    1438           9 :                 case TAG_SVG_ATT_line_increment:
    1439           9 :                         lsr_read_line_increment_type(lsr, info.far_ptr, "line-increment");
    1440           9 :                         break;
    1441           3 :                 case TAG_SVG_ATT_pointer_events:
    1442           3 :                         GF_LSR_READ_INT(lsr, *(SVG_PointerEvents*)info.far_ptr, 4, "pointer-events");
    1443             :                         break;
    1444           3 :                 case TAG_SVG_ATT_shape_rendering:
    1445           3 :                         GF_LSR_READ_INT(lsr, *(SVG_RenderingHint*)info.far_ptr, 3, "shape-rendering");
    1446             :                         break;
    1447           6 :                 case TAG_SVG_ATT_solid_color:
    1448           6 :                         lsr_read_paint(lsr, info.far_ptr, "solid-color");
    1449           6 :                         break;
    1450           3 :                 case TAG_SVG_ATT_solid_opacity:
    1451           3 :                         ((SVG_Number*)info.far_ptr)->type = SVG_NUMBER_VALUE;
    1452           3 :                         ((SVG_Number*)info.far_ptr)->value = lsr_read_fixed_clamp(lsr, "solid-opacity");
    1453           3 :                         break;
    1454          21 :                 case TAG_SVG_ATT_stop_color:
    1455          21 :                         lsr_read_paint(lsr, info.far_ptr, "stop-color");
    1456          21 :                         break;
    1457          24 :                 case TAG_SVG_ATT_stop_opacity:
    1458          24 :                         ((SVG_Number*)info.far_ptr)->type = SVG_NUMBER_VALUE;
    1459          24 :                         ((SVG_Number*)info.far_ptr)->value = lsr_read_fixed_clamp(lsr, "stop-opacity");
    1460          24 :                         break;
    1461           9 :                 case TAG_SVG_ATT_stroke_dasharray:
    1462             :                 {
    1463             :                         u32 j, flag;
    1464             :                         SVG_StrokeDashArray *da = (SVG_StrokeDashArray *)info.far_ptr;
    1465           9 :                         GF_LSR_READ_INT(lsr, flag, 1, "dashArray");
    1466           9 :                         if (flag) {
    1467           6 :                                 da->type=SVG_STROKEDASHARRAY_INHERIT;
    1468             :                         } else {
    1469           3 :                                 da->type=SVG_STROKEDASHARRAY_ARRAY;
    1470           3 :                                 da->array.count = lsr_read_vluimsbf5(lsr, "len");
    1471           3 :                                 da->array.vals = (Fixed*)gf_malloc(sizeof(Fixed)*da->array.count);
    1472           3 :                                 da->array.units = (u8*)gf_malloc(sizeof(u8)*da->array.count);
    1473          12 :                                 for (j=0; j<da->array.count; j++) {
    1474           9 :                                         da->array.vals[j] = lsr_read_fixed_16_8(lsr, "dash");
    1475           9 :                                         da->array.units[j] = 0;
    1476             :                                 }
    1477             :                         }
    1478             :                 }
    1479             :                 break;
    1480           3 :                 case TAG_SVG_ATT_stroke_dashoffset:
    1481           3 :                         lsr_read_fixed_16_8i(lsr, info.far_ptr, "dashOffset");
    1482           3 :                         break;
    1483             : 
    1484           3 :                 case TAG_SVG_ATT_stroke_linecap:
    1485           3 :                         GF_LSR_READ_INT(lsr, *(SVG_StrokeLineCap*)info.far_ptr, 2, "stroke-linecap");
    1486             :                         break;
    1487           3 :                 case TAG_SVG_ATT_stroke_linejoin:
    1488           3 :                         GF_LSR_READ_INT(lsr, *(SVG_StrokeLineJoin*)info.far_ptr, 2, "stroke-linejoin");
    1489             :                         break;
    1490           3 :                 case TAG_SVG_ATT_stroke_miterlimit:
    1491           3 :                         lsr_read_fixed_16_8i(lsr, info.far_ptr, "miterLimit");
    1492           3 :                         break;
    1493           6 :                 case TAG_SVG_ATT_stroke_opacity:
    1494           6 :                         ((SVG_Number*)info.far_ptr)->type = SVG_NUMBER_VALUE;
    1495           6 :                         ((SVG_Number*)info.far_ptr)->value = lsr_read_fixed_clamp(lsr, "stroke-opacity");
    1496           6 :                         break;
    1497          27 :                 case TAG_SVG_ATT_stroke_width:
    1498          27 :                         lsr_read_fixed_16_8i(lsr, info.far_ptr, "strokeWidth");
    1499          27 :                         break;
    1500           3 :                 case TAG_SVG_ATT_text_anchor:
    1501           3 :                         GF_LSR_READ_INT(lsr, *(SVG_TextAnchor*)info.far_ptr, 2, "text-achor");
    1502             :                         break;
    1503           3 :                 case TAG_SVG_ATT_text_rendering:
    1504           3 :                         GF_LSR_READ_INT(lsr, *(SVG_RenderingHint*)info.far_ptr, 3, "text-rendering");
    1505             :                         break;
    1506           3 :                 case TAG_SVG_ATT_viewport_fill:
    1507           3 :                         lsr_read_paint(lsr, info.far_ptr, "viewport-fill");
    1508           3 :                         break;
    1509           3 :                 case TAG_SVG_ATT_viewport_fill_opacity:
    1510           3 :                         ((SVG_Number*)info.far_ptr)->type = SVG_NUMBER_VALUE;
    1511           3 :                         ((SVG_Number*)info.far_ptr)->value = lsr_read_fixed_clamp(lsr, "viewport-fill-opacity");
    1512           3 :                         break;
    1513           3 :                 case TAG_SVG_ATT_vector_effect:
    1514           3 :                         GF_LSR_READ_INT(lsr, *(SVG_VectorEffect*)info.far_ptr, 4, "vector-effect");
    1515             :                         break;
    1516           3 :                 case TAG_SVG_ATT_visibility:
    1517           3 :                         GF_LSR_READ_INT(lsr, *(SVG_Visibility*)info.far_ptr, 2, "visibility");
    1518             :                         break;
    1519           3 :                 case TAG_SVG_ATT_requiredExtensions:
    1520           3 :                         lsr_read_byte_align_string_list(lsr, *(GF_List**)info.far_ptr, "requiredExtensions", GF_TRUE, GF_FALSE);
    1521           3 :                         break;
    1522           3 :                 case TAG_SVG_ATT_requiredFormats:
    1523           3 :                         lsr_read_byte_align_string_list(lsr, *(GF_List**)info.far_ptr, "requiredFormats", GF_FALSE, GF_FALSE);
    1524           3 :                         break;
    1525           3 :                 case TAG_SVG_ATT_requiredFeatures:
    1526             :                 {
    1527           3 :                         u32 j, fcount = lsr_read_vluimsbf5(lsr, "count");
    1528         105 :                         for (j=0; j<fcount; j++) {
    1529             :                                 u32 fval;
    1530         102 :                                 GF_LSR_READ_INT(lsr, fval, 6, "feature");
    1531             :                         }
    1532             :                 }
    1533             :                 break;
    1534           3 :                 case TAG_SVG_ATT_systemLanguage:
    1535           3 :                         lsr_read_byte_align_string_list(lsr, *(GF_List**)info.far_ptr, "systemLanguage", GF_FALSE, GF_FALSE);
    1536           3 :                         break;
    1537           3 :                 case TAG_XML_ATT_base:
    1538           3 :                         lsr_read_byte_align_string(lsr, &((XMLRI*)info.far_ptr)->string, "xml:base");
    1539           3 :                         ((XMLRI*)info.far_ptr)->type = XMLRI_STRING;
    1540           3 :                         break;
    1541           3 :                 case TAG_XML_ATT_lang:
    1542           3 :                         lsr_read_byte_align_string(lsr, info.far_ptr, "xml:lang");
    1543           3 :                         break;
    1544           3 :                 case TAG_XML_ATT_space:
    1545           3 :                         GF_LSR_READ_INT(lsr, *(XML_Space*)info.far_ptr, 1, "xml:space");
    1546             :                         break;
    1547             :                 /*focusable*/
    1548           3 :                 case TAG_SVG_ATT_nav_next:
    1549           3 :                         lsr_read_focus(lsr, (SVG_Focus*)info.far_ptr, "focusNext");
    1550           3 :                         break;
    1551           3 :                 case TAG_SVG_ATT_nav_up:
    1552           3 :                         lsr_read_focus(lsr, (SVG_Focus*)info.far_ptr, "focusNorth");
    1553           3 :                         break;
    1554           3 :                 case TAG_SVG_ATT_nav_up_left:
    1555           3 :                         lsr_read_focus(lsr, (SVG_Focus*)info.far_ptr, "focusNorthEast");
    1556           3 :                         break;
    1557           3 :                 case TAG_SVG_ATT_nav_up_right:
    1558           3 :                         lsr_read_focus(lsr, (SVG_Focus*)info.far_ptr, "focusNorthWest");
    1559           3 :                         break;
    1560           3 :                 case TAG_SVG_ATT_nav_prev:
    1561           3 :                         lsr_read_focus(lsr, (SVG_Focus*)info.far_ptr, "focusPrev");
    1562           3 :                         break;
    1563           3 :                 case TAG_SVG_ATT_nav_down:
    1564           3 :                         lsr_read_focus(lsr, (SVG_Focus*)info.far_ptr, "focusSouth");
    1565           3 :                         break;
    1566           3 :                 case TAG_SVG_ATT_nav_down_left:
    1567           3 :                         lsr_read_focus(lsr, (SVG_Focus*)info.far_ptr, "focusSouthEast");
    1568           3 :                         break;
    1569           3 :                 case TAG_SVG_ATT_nav_down_right:
    1570           3 :                         lsr_read_focus(lsr, (SVG_Focus*)info.far_ptr, "focusSouthWest");
    1571           3 :                         break;
    1572           3 :                 case TAG_SVG_ATT_nav_left:
    1573           3 :                         lsr_read_focus(lsr, (SVG_Focus*)info.far_ptr, "focusEast");
    1574           3 :                         break;
    1575           3 :                 case TAG_SVG_ATT_focusable:
    1576           3 :                         GF_LSR_READ_INT(lsr, *(SVG_Focusable*)info.far_ptr, 2, "focusable");
    1577             :                         break;
    1578           3 :                 case TAG_SVG_ATT_nav_right:
    1579           3 :                         lsr_read_focus(lsr, (SVG_Focus*)info.far_ptr, "focusWest");
    1580           3 :                         break;
    1581          18 :                 case TAG_SVG_ATT_transform:
    1582          18 :                         lsr_read_matrix(lsr, info.far_ptr);
    1583          18 :                         break;
    1584             :                 case TAG_SVG_ATT_text_decoration:
    1585             :                         /*FIXME ASAP*/
    1586             :                         assert(0);
    1587             :                         break;
    1588             : 
    1589           3 :                 case TAG_SVG_ATT_font_variant:
    1590           3 :                         GF_LSR_READ_INT(lsr, *(SVG_FontVariant*)info.far_ptr, 2, "font-variant");
    1591             :                         break;
    1592           3 :                 case TAG_SVG_ATT_font_family:
    1593             :                 {
    1594             :                         u32 flag;
    1595           3 :                         GF_LSR_READ_INT(lsr, flag, 1, "isInherit");
    1596           3 :                         if (flag) {
    1597           3 :                                 ((SVG_FontFamily*)info.far_ptr)->type = SVG_FONTFAMILY_INHERIT;
    1598             :                         } else {
    1599             :                                 char *ft;
    1600           0 :                                 ((SVG_FontFamily*)info.far_ptr)->type = SVG_FONTFAMILY_VALUE;
    1601           0 :                                 GF_LSR_READ_INT(lsr, flag, lsr->fontIndexBits, "fontIndex");
    1602           0 :                                 ft = (char*)gf_list_get(lsr->font_table, flag);
    1603           0 :                                 if (ft) ((SVG_FontFamily*)info.far_ptr)->value = gf_strdup(ft);
    1604             :                         }
    1605             :                 }
    1606             :                 break;
    1607           3 :                 case TAG_SVG_ATT_font_size:
    1608           3 :                         lsr_read_fixed_16_8i(lsr, info.far_ptr, "fontSize");
    1609           3 :                         break;
    1610           3 :                 case TAG_SVG_ATT_font_style:
    1611           3 :                         GF_LSR_READ_INT(lsr, *(SVG_FontStyle*)info.far_ptr, 3, "fontStyle");
    1612             :                         break;
    1613           3 :                 case TAG_SVG_ATT_font_weight:
    1614           3 :                         GF_LSR_READ_INT(lsr, *(SVG_FontWeight*)info.far_ptr, 4, "fontWeight");
    1615             :                         break;
    1616           3 :                 case TAG_XLINK_ATT_title:
    1617           3 :                         lsr_read_byte_align_string(lsr, info.far_ptr, "xlink:title");
    1618           3 :                         break;
    1619           3 :                 case TAG_XLINK_ATT_type:
    1620             :                         /*TODO FIXME*/
    1621           3 :                         GF_LSR_READ_INT(lsr, field_rare, 3, "xlink:type");
    1622             :                         break;
    1623           3 :                 case TAG_XLINK_ATT_role:
    1624           3 :                         lsr_read_any_uri(lsr, info.far_ptr, "xlink:role");
    1625           3 :                         break;
    1626           3 :                 case TAG_XLINK_ATT_arcrole:
    1627           3 :                         lsr_read_any_uri(lsr, info.far_ptr, "xlink:arcrole");
    1628           3 :                         break;
    1629           3 :                 case TAG_XLINK_ATT_actuate:
    1630             :                         /*TODO FIXME*/
    1631           3 :                         GF_LSR_READ_INT(lsr, field_rare, 2, "xlink:actuate");
    1632             :                         break;
    1633           3 :                 case TAG_XLINK_ATT_show:
    1634             :                         /*TODO FIXME*/
    1635           3 :                         GF_LSR_READ_INT(lsr, field_rare, 3, "xlink:show");
    1636             :                         break;
    1637         139 :                 case TAG_SVG_ATT_end:
    1638         139 :                         lsr_read_smil_times(lsr, NULL, 0, info.far_ptr, "end", 0);
    1639         139 :                         break;
    1640           3 :                 case TAG_SVG_ATT_max:
    1641           3 :                         lsr_read_duration_ex(lsr, NULL, 0, info.far_ptr, "min", 0);
    1642           3 :                         break;
    1643           3 :                 case TAG_SVG_ATT_min:
    1644           3 :                         lsr_read_duration_ex(lsr, NULL, 0, info.far_ptr, "min", 0);
    1645           3 :                         break;
    1646             :                 }
    1647         433 :                 if (lsr->last_error) break;
    1648             :         }
    1649             : }
    1650             : 
    1651             : #define lsr_read_rare(_a, _b) lsr_read_rare_full(_a, _b)
    1652             : 
    1653         239 : static void lsr_read_fill(GF_LASeRCodec *lsr, GF_Node *n)
    1654             : {
    1655             :         Bool has_fill;
    1656         239 :         GF_LSR_READ_INT(lsr, has_fill, 1, "fill");
    1657         239 :         if (has_fill) {
    1658             :                 GF_FieldInfo info;
    1659          60 :                 lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_fill, GF_TRUE, GF_FALSE, &info);
    1660          60 :                 lsr_read_paint(lsr, info.far_ptr, "fill");
    1661             :         }
    1662         239 : }
    1663             : 
    1664         230 : static void lsr_read_stroke(GF_LASeRCodec *lsr, GF_Node *n)
    1665             : {
    1666             :         Bool has_stroke;
    1667         230 :         GF_LSR_READ_INT(lsr, has_stroke, 1, "has_stroke");
    1668         230 :         if (has_stroke) {
    1669             :                 GF_FieldInfo info;
    1670          54 :                 lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_stroke, GF_TRUE, GF_FALSE, &info);
    1671          54 :                 lsr_read_paint(lsr, info.far_ptr, "stroke");
    1672             :         }
    1673         230 : }
    1674         215 : static void lsr_read_href(GF_LASeRCodec *lsr, GF_Node *n)
    1675             : {
    1676             :         Bool has_href;
    1677         215 :         GF_LSR_READ_INT(lsr, has_href, 1, "has_href");
    1678         215 :         if (has_href) {
    1679             :                 GF_FieldInfo info;
    1680          71 :                 lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_XLINK_ATT_href, GF_TRUE, GF_FALSE, &info);
    1681          71 :                 lsr_read_any_uri(lsr, info.far_ptr, "href");
    1682             :         }
    1683         215 : }
    1684             : 
    1685         125 : static void lsr_read_accumulate(GF_LASeRCodec *lsr, GF_Node *n)
    1686             : {
    1687             :         Bool v;
    1688         125 :         GF_LSR_READ_INT(lsr, v, 1, "has_accumulate");
    1689         125 :         if (v) {
    1690             :                 GF_FieldInfo info;
    1691           3 :                 lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_accumulate, GF_TRUE, GF_FALSE, &info);
    1692           3 :                 GF_LSR_READ_INT(lsr, *(SMIL_Accumulate*)info.far_ptr, 1, "accumulate");
    1693             :         }
    1694         125 : }
    1695         125 : static void lsr_read_additive(GF_LASeRCodec *lsr, GF_Node *n)
    1696             : {
    1697             :         Bool v;
    1698         125 :         GF_LSR_READ_INT(lsr, v, 1, "has_additive");
    1699         125 :         if (v) {
    1700             :                 GF_FieldInfo info;
    1701           6 :                 lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_additive, GF_TRUE, GF_FALSE, &info);
    1702           6 :                 GF_LSR_READ_INT(lsr, *(SMIL_Additive*)info.far_ptr, 1, "additive");
    1703             :         }
    1704         125 : }
    1705         125 : static void lsr_read_calc_mode(GF_LASeRCodec *lsr, GF_Node *n)
    1706             : {
    1707             :         u32 v;
    1708             :         /*SMIL_CALCMODE_LINEAR is default and 0 in our code*/
    1709         125 :         GF_LSR_READ_INT(lsr, v, 1, "has_calcMode");
    1710         125 :         if (v) {
    1711             :                 GF_FieldInfo info;
    1712          15 :                 lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_calcMode, GF_TRUE, GF_FALSE, &info);
    1713          15 :                 GF_LSR_READ_INT(lsr, *(SMIL_CalcMode*)info.far_ptr, 2, "calcMode");
    1714             :         }
    1715         125 : }
    1716             : 
    1717         119 : static void lsr_read_attribute_name_ex(GF_LASeRCodec *lsr, GF_Node *n, Bool skippable)
    1718             : {
    1719             :         u32 val = 1;
    1720         119 :         if (skippable) {
    1721         119 :                 GF_LSR_READ_INT(lsr, val, 1, "hasAttributeName");
    1722         119 :                 if (!val) return;
    1723             :         }
    1724             : 
    1725         110 :         GF_LSR_READ_INT(lsr, val, 1, "choice");
    1726         110 :         if (val) {
    1727           0 :                 lsr_read_vluimsbf5(lsr, "item[i]");
    1728           0 :                 lsr_read_vluimsbf5(lsr, "item[i]");
    1729           0 :                 return;
    1730             :         } else {
    1731             :                 GF_FieldInfo info;
    1732         110 :                 lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_attributeName, GF_TRUE, GF_FALSE, &info);
    1733         110 :                 GF_LSR_READ_INT(lsr, val, 8, "attributeType");
    1734             : 
    1735             :                 /*translate type to attribute tag*/
    1736         110 :                 ((SMIL_AttributeName*)info.far_ptr)->type = gf_lsr_anim_type_to_attribute(val);
    1737             :         }
    1738             : }
    1739             : static void lsr_read_attribute_name(GF_LASeRCodec *lsr, GF_Node *n)
    1740             : {
    1741         119 :         lsr_read_attribute_name_ex(lsr, n, GF_TRUE);
    1742             : }
    1743             : 
    1744          48 : static void lsr_translate_anim_value(SMIL_AnimateValue *val, u32 coded_type)
    1745             : {
    1746          48 :         switch (val->type) {
    1747           0 :         case SVG_StrokeDashArray_datatype:
    1748             :         {
    1749             :                 SVG_StrokeDashArray *da;
    1750           0 :                 GF_List *l = (GF_List *)val->value;
    1751             :                 u32 i;
    1752           0 :                 GF_SAFEALLOC(da, SVG_StrokeDashArray);
    1753           0 :                 if (!da) return;
    1754           0 :                 da->array.count = gf_list_count(l);
    1755           0 :                 if (!da->array.count) {
    1756           0 :                         da->type = SVG_STROKEDASHARRAY_INHERIT;
    1757             :                 } else {
    1758           0 :                         da->type = SVG_STROKEDASHARRAY_ARRAY;
    1759           0 :                         da->array.vals = (Fixed *) gf_malloc(sizeof(Fixed)*da->array.count);
    1760           0 :                         da->array.units = (u8 *) gf_malloc(sizeof(u8)*da->array.count);
    1761           0 :                         for (i=0; i<da->array.count; i++) {
    1762           0 :                                 Fixed *v = (Fixed *)gf_list_get(l, i);
    1763           0 :                                 da->array.vals[i] = *v;
    1764           0 :                                 da->array.units[i] = 0;
    1765           0 :                                 gf_free(v);
    1766             :                         }
    1767           0 :                         gf_list_del(l);
    1768           0 :                         val->value = da;
    1769             :                 }
    1770             :         }
    1771             :         break;
    1772           0 :         case SVG_ViewBox_datatype:
    1773             :         {
    1774             :                 SVG_ViewBox *vb;
    1775           0 :                 GF_List *l = (GF_List *)val->value;
    1776           0 :                 GF_SAFEALLOC(vb, SVG_ViewBox);
    1777           0 :                 if (!vb) return;
    1778           0 :                 if (gf_list_count(l)==4) {
    1779           0 :                         vb->x = * ((Fixed *)gf_list_get(l, 0));
    1780           0 :                         vb->y = * ((Fixed *)gf_list_get(l, 1));
    1781           0 :                         vb->width = * ((Fixed *)gf_list_get(l, 2));
    1782           0 :                         vb->height = * ((Fixed *)gf_list_get(l, 3));
    1783             :                 }
    1784           0 :                 while (gf_list_count(l)) {
    1785           0 :                         Fixed *v = (Fixed *)gf_list_last(l);
    1786           0 :                         gf_free(v);
    1787           0 :                         gf_list_rem_last(l);
    1788             :                 }
    1789           0 :                 gf_list_del(l);
    1790           0 :                 val->value = vb;
    1791             :         }
    1792             :         break;
    1793           0 :         case SVG_Coordinates_datatype:
    1794             :         {
    1795             :                 SVG_Coordinates *coords;
    1796           0 :                 if (coded_type==1) {
    1797           0 :                         GF_List *l = gf_list_new();
    1798             :                         /*allocated value is already an SVG number*/
    1799           0 :                         gf_list_add(l, val->value);
    1800           0 :                         coords = (SVG_Coordinates*)gf_malloc(sizeof(SVG_Coordinates));
    1801           0 :                         *coords = l;
    1802           0 :                         val->value = coords;
    1803           0 :                 } else if (coded_type==8) {
    1804           0 :                         GF_List *l = (GF_List *)val->value;
    1805           0 :                         u32 i, count = gf_list_count(l);
    1806           0 :                         for (i=0; i<count; i++) {
    1807             :                                 SVG_Coordinate *c;
    1808           0 :                                 Fixed *v = (Fixed *)gf_list_get(l, i);
    1809           0 :                                 c = (SVG_Coordinate*)gf_malloc(sizeof(SVG_Coordinate));
    1810           0 :                                 c->type = SVG_NUMBER_VALUE;
    1811           0 :                                 c->value = *v;
    1812           0 :                                 gf_free(v);
    1813           0 :                                 gf_list_rem(l, i);
    1814           0 :                                 gf_list_insert(l, c, i);
    1815             :                         }
    1816           0 :                         coords = (SVG_Coordinates*)gf_malloc(sizeof(SVG_Coordinates));
    1817           0 :                         *coords = (GF_List *) val->value;
    1818           0 :                         val->value = coords;
    1819             :                 }
    1820             :         }
    1821             :         break;
    1822           0 :         case SVG_Motion_datatype:
    1823           0 :                 if (coded_type==9) {
    1824             :                         GF_Matrix2D *mat;
    1825           0 :                         SVG_Point *pt = (SVG_Point *)val->value;
    1826           0 :                         GF_SAFEALLOC(mat, GF_Matrix2D);
    1827           0 :                         if (mat) {
    1828           0 :                                 gf_mx2d_init(*mat);
    1829           0 :                                 mat->m[2] = pt->x;
    1830           0 :                                 mat->m[5] = pt->y;
    1831           0 :                                 val->value = mat;
    1832             :                         }
    1833           0 :                         gf_free(pt);
    1834             :                 }
    1835             :                 break;
    1836             :         }
    1837             : }
    1838          57 : static void lsr_translate_anim_values(SMIL_AnimateValues *val, u32 coded_type)
    1839             : {
    1840             :         u32 i, count;
    1841             :         GF_List *list, *new_list;
    1842             : 
    1843          57 :         list = val->values;
    1844          57 :         switch (val->type) {
    1845             :         case SVG_StrokeDashArray_datatype:
    1846             :                 break;
    1847             :         case SVG_ViewBox_datatype:
    1848             :                 break;
    1849             :         case SVG_Coordinates_datatype:
    1850             :                 break;
    1851           0 :         case SVG_Motion_datatype:
    1852           0 :                 if (coded_type!=9) return;
    1853             :                 break;
    1854             :         default:
    1855             :                 return;
    1856             :         }
    1857           3 :         val->values = new_list = gf_list_new();
    1858           3 :         count = gf_list_count(list);
    1859          12 :         for (i=0; i<count; i++) {
    1860           9 :                 switch (val->type) {
    1861           9 :                 case SVG_StrokeDashArray_datatype:
    1862             :                 {
    1863             :                         SVG_StrokeDashArray *da;
    1864           9 :                         GF_List *l = (GF_List *)gf_list_get(list, i);
    1865             :                         u32 j;
    1866           9 :                         GF_SAFEALLOC(da, SVG_StrokeDashArray);
    1867           9 :                         if (!da) return;
    1868           9 :                         da->array.count = gf_list_count(l);
    1869           9 :                         if (!da->array.count) {
    1870           3 :                                 da->type = SVG_STROKEDASHARRAY_INHERIT;
    1871             :                         } else {
    1872           6 :                                 da->type = SVG_STROKEDASHARRAY_ARRAY;
    1873           6 :                                 da->array.vals = (Fixed *)gf_malloc(sizeof(Fixed)*da->array.count);
    1874           6 :                                 da->array.units = (u8 *) gf_malloc(sizeof(u8)*da->array.count);
    1875          24 :                                 for (j=0; j<da->array.count; j++) {
    1876          18 :                                         Fixed *v = (Fixed *)gf_list_get(l, j);
    1877          18 :                                         da->array.vals[j] = *v;
    1878          18 :                                         da->array.units[j] = 0;
    1879          18 :                                         gf_free(v);
    1880             :                                 }
    1881             :                         }
    1882           9 :                         gf_list_del(l);
    1883           9 :                         gf_list_add(new_list, da);
    1884             :                 }
    1885           9 :                 break;
    1886           0 :                 case SVG_ViewBox_datatype:
    1887             :                 {
    1888             :                         SVG_ViewBox *vb;
    1889           0 :                         GF_List *l = (GF_List *)gf_list_get(list, i);
    1890           0 :                         GF_SAFEALLOC(vb, SVG_ViewBox);
    1891           0 :                         if (!vb) return;
    1892           0 :                         if (gf_list_count(l)==4) {
    1893           0 :                                 vb->x = * ((Fixed *)gf_list_get(l, 0));
    1894           0 :                                 vb->y = * ((Fixed *)gf_list_get(l, 1));
    1895           0 :                                 vb->width = * ((Fixed *)gf_list_get(l, 2));
    1896           0 :                                 vb->height = * ((Fixed *)gf_list_get(l, 3));
    1897             :                         }
    1898           0 :                         while (gf_list_count(l)) {
    1899           0 :                                 Fixed *v=(Fixed *)gf_list_last(l);
    1900           0 :                                 gf_free(v);
    1901           0 :                                 gf_list_rem_last(l);
    1902             :                         }
    1903           0 :                         gf_list_del(l);
    1904           0 :                         gf_list_add(new_list, vb);
    1905             :                 }
    1906           0 :                 break;
    1907           0 :                 case SVG_Coordinates_datatype:
    1908             :                 {
    1909             :                         SVG_Coordinates *coords;
    1910           0 :                         GF_List *l = (GF_List *)gf_list_get(list, i);
    1911             :                         u32 j, count2;
    1912           0 :                         count2 = gf_list_count(l);
    1913           0 :                         for (j=0; j<count2; j++) {
    1914           0 :                                 SVG_Coordinate *c = (SVG_Coordinate *)gf_malloc(sizeof(SVG_Coordinate));
    1915           0 :                                 Fixed *v = (Fixed *)gf_list_get(l, j);
    1916           0 :                                 c->type = SVG_NUMBER_VALUE;
    1917           0 :                                 c->value = *v;
    1918           0 :                                 gf_list_rem(l, j);
    1919           0 :                                 gf_list_insert(l, c, j);
    1920           0 :                                 gf_free(v);
    1921             :                         }
    1922             : 
    1923           0 :                         coords = (SVG_Coordinates*)gf_malloc(sizeof(SVG_Coordinates));
    1924           0 :                         *coords = l;
    1925           0 :                         gf_list_add(new_list, coords);
    1926             :                 }
    1927           0 :                 break;
    1928             : 
    1929           0 :                 case SVG_Motion_datatype:
    1930             :                 {
    1931           0 :                         GF_Matrix2D *m = (GF_Matrix2D *)gf_malloc(sizeof(GF_Matrix2D ));
    1932           0 :                         GF_Point2D *pt = (GF_Point2D *)gf_list_get(list, i);
    1933           0 :                         gf_mx2d_init(*m);
    1934           0 :                         m->m[2] = pt->x;
    1935           0 :                         m->m[5] = pt->y;
    1936           0 :                         gf_free(pt);
    1937           0 :                         gf_list_add(new_list, m);
    1938             :                 }
    1939           0 :                         break;
    1940             :                 }
    1941             :         }
    1942           3 :         gf_list_del(list);
    1943             : }
    1944             : 
    1945         613 : static Bool lsr_init_smil_times(GF_LASeRCodec *lsr, SVG_Element *anim, GF_List *times, SVG_Element *parent)
    1946             : {
    1947             :         u32 i, count;
    1948         613 :         count = gf_list_count(times);
    1949         270 :         for (i=0; i<count; i++) {
    1950         270 :                 SMIL_Time *t = (SMIL_Time *)gf_list_get(times, i);
    1951         270 :                 if (t->type==GF_SMIL_TIME_EVENT) {
    1952           3 :                         if (t->element_id) {
    1953           0 :                                 if (t->element_id[0]=='N') {
    1954           0 :                                         t->element = gf_sg_find_node(lsr->sg, atoi(t->element_id+1) + 1);
    1955             :                                 } else {
    1956           0 :                                         t->element = gf_sg_find_node_by_name(lsr->sg, t->element_id);
    1957             :                                 }
    1958           0 :                                 if (!t->element) return GF_FALSE;
    1959           0 :                                 gf_free(t->element_id);
    1960           0 :                                 t->element_id = NULL;
    1961             :                         }
    1962           3 :                         else if (!t->element) {
    1963           0 :                                 if (t->event.parameter && (t->event.type==GF_EVENT_KEYDOWN) ) {
    1964           0 :                                         t->element = lsr->sg->RootNode ? lsr->sg->RootNode : lsr->current_root;
    1965             :                                 } else {
    1966           0 :                                         t->element = (GF_Node*)parent;
    1967             :                                 }
    1968             :                         }
    1969             :                 }
    1970             :         }
    1971             :         return GF_TRUE;
    1972             : }
    1973             : 
    1974         448 : static Bool lsr_setup_smil_anim(GF_LASeRCodec *lsr, SVG_Element *anim, SVG_Element *anim_parent)
    1975             : {
    1976             :         GF_FieldInfo info;
    1977             :         u32 coded_type, not_res;
    1978             :         GF_Node *target;
    1979             :         Bool is_animateMotion, is_animateTransform;
    1980             :         XMLRI *xlink;
    1981             :         SMIL_AttributeName *name = NULL;
    1982             :         SMIL_AnimateValue *value;
    1983             : 
    1984             :         /*setup smil events*/
    1985             :         not_res = 0;
    1986         448 :         if (gf_node_get_attribute_by_tag((GF_Node *)anim, TAG_SVG_ATT_begin, GF_FALSE, GF_FALSE, &info)==GF_OK) {
    1987         264 :                 if (!lsr_init_smil_times(lsr, anim, *(GF_List**)info.far_ptr, anim_parent)) not_res++;
    1988             :         }
    1989             : 
    1990         448 :         if (gf_node_get_attribute_by_tag((GF_Node *)anim, TAG_SVG_ATT_end, GF_FALSE, GF_FALSE, &info)==GF_OK) {
    1991         349 :                 if (!lsr_init_smil_times(lsr, anim, *(GF_List**)info.far_ptr, anim_parent)) not_res++;
    1992             :         }
    1993             : 
    1994             : 
    1995             :         /*get xlink*/
    1996             :         xlink = NULL;
    1997         448 :         if (gf_node_get_attribute_by_tag((GF_Node *)anim, TAG_XLINK_ATT_href, GF_FALSE, GF_FALSE, &info)==GF_OK) {
    1998         365 :                 xlink = info.far_ptr;
    1999             :         }
    2000             : 
    2001             :         /*setup target node*/
    2002         365 :         if (!xlink || !xlink->target) {
    2003             :                 /*target not received*/
    2004         110 :                 if (xlink && (xlink->type == XMLRI_ELEMENTID)) return GF_FALSE;
    2005             : 
    2006          83 :                 if (!xlink) {
    2007             :                         /*target is parent, initialize xlink (needed by anim module)*/
    2008          83 :                         if (gf_node_get_attribute_by_tag((GF_Node *)anim, TAG_XLINK_ATT_href, GF_TRUE, GF_FALSE, &info)==GF_OK) {
    2009          83 :                                 xlink = info.far_ptr;
    2010             :                         } else {
    2011             :                                 return GF_FALSE;
    2012             :                         }
    2013             :                 }
    2014             : 
    2015          83 :                 xlink->type = XMLRI_ELEMENTID;
    2016          83 :                 xlink->target = anim_parent;
    2017          83 :                 gf_node_register_iri(lsr->sg, xlink);
    2018          83 :                 target = (GF_Node *)anim_parent;
    2019             :         } else {
    2020             :                 target = (GF_Node *)xlink->target;
    2021             :         }
    2022         421 :         if (!target || not_res) return GF_FALSE;
    2023             : 
    2024             :         is_animateTransform = is_animateMotion = GF_FALSE;
    2025         421 :         if (anim->sgprivate->tag==TAG_SVG_animateMotion) is_animateMotion = GF_TRUE;
    2026         413 :         else if (anim->sgprivate->tag==TAG_SVG_animateTransform) {
    2027             :                 is_animateTransform = GF_TRUE;
    2028             :         }
    2029             :         if (is_animateMotion) goto translate_vals;
    2030             : 
    2031             :         /*for all except animateMotion, get attributeName*/
    2032         413 :         if (gf_node_get_attribute_by_tag((GF_Node *)anim, TAG_SVG_ATT_attributeName, GF_FALSE, GF_FALSE, &info)==GF_OK) {
    2033         110 :                 name = info.far_ptr;
    2034             :         }
    2035         110 :         if (!name) {
    2036             :                 return GF_FALSE;
    2037             :         }
    2038             : 
    2039         110 :         if (!name->field_ptr) {
    2040         110 :                 if (gf_node_get_attribute_by_tag((GF_Node *)target, name->type, GF_TRUE, GF_FALSE, &info)!=GF_OK) return GF_FALSE;
    2041         110 :                 name->field_ptr = info.far_ptr;
    2042         110 :                 name->type = info.fieldType;
    2043         110 :                 name->tag = info.fieldIndex;
    2044             :         }
    2045             : 
    2046             : 
    2047             :         /*browse all anim types and retranslate anim values. This must be done in 2 steps since we may not have received
    2048             :         the target node when parsing the animation node*/
    2049         118 : translate_vals:
    2050             : 
    2051             :         /*and setup anim values*/
    2052         118 :         if (gf_node_get_attribute_by_tag((GF_Node *)anim, TAG_SVG_ATT_from, GF_FALSE, GF_FALSE, &info)==GF_OK) {
    2053          27 :                 if (is_animateTransform) {
    2054           6 :                         name->type = ((SMIL_AnimateValue*)info.far_ptr)->type;
    2055             :                 } else {
    2056          21 :                         value = info.far_ptr;
    2057          21 :                         coded_type = value->type;
    2058          21 :                         value->type = is_animateMotion ? SVG_Motion_datatype : name->type;
    2059          21 :                         lsr_translate_anim_value(value, coded_type);
    2060             :                 }
    2061             :         }
    2062         118 :         if (gf_node_get_attribute_by_tag((GF_Node *)anim, TAG_SVG_ATT_by, GF_FALSE, GF_FALSE, &info)==GF_OK) {
    2063           9 :                 if (is_animateTransform) {
    2064           6 :                         name->type = ((SMIL_AnimateValue*)info.far_ptr)->type;
    2065             :                 } else {
    2066           3 :                         value = info.far_ptr;
    2067           3 :                         coded_type = value->type;
    2068           3 :                         value->type = is_animateMotion ? SVG_Motion_datatype : name->type;
    2069           3 :                         lsr_translate_anim_value(value, coded_type);
    2070             :                 }
    2071             :         }
    2072         118 :         if (gf_node_get_attribute_by_tag((GF_Node *)anim, TAG_SVG_ATT_to, GF_FALSE, GF_FALSE, &info)==GF_OK) {
    2073          30 :                 if (is_animateTransform) {
    2074           6 :                         name->type = ((SMIL_AnimateValue*)info.far_ptr)->type;
    2075             :                 } else {
    2076          24 :                         value = info.far_ptr;
    2077          24 :                         coded_type = value->type;
    2078          24 :                         value->type = is_animateMotion ? SVG_Motion_datatype : name->type;
    2079          24 :                         lsr_translate_anim_value(value, coded_type);
    2080             :                 }
    2081             :         }
    2082         118 :         if (gf_node_get_attribute_by_tag((GF_Node *)anim, TAG_SVG_ATT_values, GF_FALSE, GF_FALSE, &info)==GF_OK) {
    2083          57 :                 if (is_animateTransform) {
    2084           0 :                         name->type = ((SMIL_AnimateValues*)info.far_ptr)->type;
    2085             :                 } else {
    2086          57 :                         SMIL_AnimateValues *values = info.far_ptr;
    2087          57 :                         coded_type = values->type;
    2088          57 :                         values->type = is_animateMotion ? SVG_Motion_datatype : name->type;
    2089          57 :                         values->laser_strings = 0;
    2090          57 :                         lsr_translate_anim_values(values, coded_type);
    2091             :                 }
    2092             :         }
    2093             : 
    2094             :         return GF_TRUE;
    2095             : }
    2096             : 
    2097         127 : static void lsr_read_anim_fill(GF_LASeRCodec *lsr, GF_Node *n)
    2098             : {
    2099             :         u32 val;
    2100             : 
    2101         127 :         GF_LSR_READ_INT(lsr, val, 1, "has_smil_fill");
    2102         127 :         if (val) {
    2103             :                 GF_FieldInfo info;
    2104          24 :                 lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_smil_fill, GF_TRUE, 0, &info);
    2105             :                 /*enumeration freeze{0} remove{1}*/
    2106          24 :                 GF_LSR_READ_INT(lsr, val, 1, "smil_fill");
    2107          24 :                 *(SMIL_Fill*)info.far_ptr = val ? SMIL_FILL_REMOVE : SMIL_FILL_FREEZE;
    2108             :         }
    2109         127 : }
    2110         137 : static void lsr_read_anim_repeatCount(GF_LASeRCodec *lsr, GF_Node *n)
    2111             : {
    2112             :         u32 val;
    2113         137 :         GF_LSR_READ_INT(lsr, val, 1, "has_repeatCount");
    2114         137 :         if (val) {
    2115             :                 GF_FieldInfo info;
    2116          21 :                 lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_repeatCount, GF_TRUE, 0, &info);
    2117          21 :                 GF_LSR_READ_INT(lsr, val, 1, "repeatCount");
    2118          21 :                 if (val) ((SMIL_RepeatCount*)info.far_ptr)->type = SMIL_REPEATCOUNT_INDEFINITE;
    2119             :                 else {
    2120           9 :                         ((SMIL_RepeatCount*)info.far_ptr)->type = SMIL_REPEATCOUNT_DEFINED;
    2121           9 :                         ((SMIL_RepeatCount*)info.far_ptr)->count = lsr_read_fixed_16_8(lsr, "repeatCount");
    2122             :                 }
    2123             :         }
    2124         137 : }
    2125         137 : static void lsr_read_repeat_duration(GF_LASeRCodec *lsr, GF_Node *n)
    2126             : {
    2127             :         u32 flag;
    2128         137 :         GF_LSR_READ_INT(lsr, flag, 1, "has_repeatDur");
    2129         137 :         if (flag) {
    2130             :                 GF_FieldInfo info;
    2131           3 :                 lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_repeatDur, GF_TRUE, 0, &info);
    2132           3 :                 GF_LSR_READ_INT(lsr, flag, 1, "choice");
    2133             : 
    2134           3 :                 if (flag) {
    2135           0 :                         ((SMIL_Duration *)info.far_ptr)->type = SMIL_DURATION_INDEFINITE;
    2136             :                 } else {
    2137           3 :                         ((SMIL_Duration *)info.far_ptr)->clock_value = (Double) lsr_read_vluimsbf5(lsr, "value");
    2138           3 :                         ((SMIL_Duration *)info.far_ptr)->clock_value /= lsr->time_resolution;
    2139           3 :                         ((SMIL_Duration *)info.far_ptr)->type = SMIL_DURATION_DEFINED;
    2140             :                 }
    2141             :         }
    2142         137 : }
    2143         137 : static void lsr_read_anim_restart(GF_LASeRCodec *lsr, GF_Node *n)
    2144             : {
    2145             :         u32 val;
    2146         137 :         GF_LSR_READ_INT(lsr, val, 1, "has_restart");
    2147         137 :         if (val) {
    2148             :                 GF_FieldInfo info;
    2149           3 :                 lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_restart, GF_TRUE, 0, &info);
    2150             :                 /*enumeration always{0} never{1} whenNotActive{2}*/
    2151           3 :                 GF_LSR_READ_INT(lsr, *(SMIL_Restart*)info.far_ptr, 2, "restart");
    2152             :         }
    2153         137 : }
    2154             : 
    2155         321 : static void *lsr_read_an_anim_value(GF_LASeRCodec *lsr, u32 coded_type, const char *name)
    2156             : {
    2157             :         u32 flag;
    2158             :         u32 escapeFlag, escape_val = 0;
    2159             :         u8 *enum_val;
    2160             :         u32 *id_val;
    2161             :         char *string;
    2162             :         SVG_String *svg_string;
    2163             :         SVG_Number *num;
    2164             :         XMLRI *iri;
    2165             :         SVG_Point *pt;
    2166             :         SVG_Paint *paint;
    2167             : 
    2168         321 :         GF_LSR_READ_INT(lsr, escapeFlag, 1, "escapeFlag");
    2169         321 :         if (escapeFlag) GF_LSR_READ_INT(lsr, escape_val, 2, "escapeEnum");
    2170             : 
    2171         321 :         switch (coded_type) {
    2172          48 :         case 0:
    2173          48 :                 string = NULL;
    2174          48 :                 lsr_read_byte_align_string(lsr, &string, name);
    2175          48 :                 GF_SAFEALLOC(svg_string, SVG_String);
    2176          48 :                 if (!svg_string) return NULL;
    2177          48 :                 *svg_string = string;
    2178          48 :                 return svg_string;
    2179          81 :         case 1:
    2180          81 :                 num = (SVG_Number*)gf_malloc(sizeof(SVG_Number));
    2181          81 :                 if (escapeFlag) {
    2182           3 :                         num->type = (escape_val==1) ? SVG_NUMBER_INHERIT : SVG_NUMBER_VALUE;
    2183             :                 } else {
    2184          78 :                         num->type = SVG_NUMBER_VALUE;
    2185          78 :                         num->value = lsr_read_fixed_16_8(lsr, name);
    2186             :                 }
    2187             :                 return num;
    2188           6 :         case 2:
    2189             :         {
    2190           6 :                 SVG_PathData *pd = (SVG_PathData *)gf_svg_create_attribute_value(SVG_PathData_datatype);
    2191           6 :                 lsr_read_path_type(lsr, NULL, 0, pd, name);
    2192           6 :                 return pd;
    2193             :         }
    2194           0 :         case 3:
    2195             :         {
    2196           0 :                 SVG_Points *pts = (SVG_Points *)gf_svg_create_attribute_value(SVG_Points_datatype);
    2197           0 :                 lsr_read_point_sequence(lsr, *pts, name);
    2198           0 :                 return pts;
    2199             :         }
    2200           0 :         case 4:
    2201           0 :                 num = (SVG_Number*)gf_malloc(sizeof(SVG_Number));
    2202           0 :                 if (escapeFlag) {
    2203           0 :                         num->type = (escape_val==1) ? SVG_NUMBER_INHERIT : SVG_NUMBER_VALUE;
    2204             :                 } else {
    2205           0 :                         num->type = SVG_NUMBER_VALUE;
    2206           0 :                         num->value = lsr_read_fixed_clamp(lsr, name);
    2207             :                 }
    2208             :                 return num;
    2209          39 :         case 5:
    2210          39 :                 GF_SAFEALLOC(paint, SVG_Paint);
    2211          39 :                 if (!paint) return NULL;
    2212          39 :                 if (escapeFlag) {
    2213           0 :                         paint->type = SVG_PAINT_INHERIT;
    2214             :                 } else {
    2215          39 :                         lsr_read_paint(lsr, paint, name);
    2216             :                 }
    2217             :                 return paint;
    2218          93 :         case 6:
    2219          93 :                 enum_val = (u8*)gf_malloc(sizeof(u8));
    2220          93 :                 *enum_val = lsr_read_vluimsbf5(lsr, name);
    2221          93 :                 return enum_val;
    2222             :         /*TODO check this is correct*/
    2223           0 :         case 7:
    2224             :         {
    2225           0 :                 GF_List *l = gf_list_new();
    2226             :                 u32 i, count;
    2227           0 :                 count = lsr_read_vluimsbf5(lsr, "count");
    2228           0 :                 for (i=0; i<count; i++) {
    2229           0 :                         u8 *v = (u8 *)gf_malloc(sizeof(u8));
    2230           0 :                         *v = lsr_read_vluimsbf5(lsr, "val");
    2231           0 :                         gf_list_add(l, v);
    2232             :                 }
    2233             :                 return l;
    2234             :         }
    2235             :         /*TODO check this is correct*/
    2236          15 :         case 8: // floats
    2237             :         {
    2238          15 :                 GF_List *l = gf_list_new();
    2239             :                 u32 i, count;
    2240          15 :                 count = lsr_read_vluimsbf5(lsr, "count");
    2241          51 :                 for (i=0; i<count; i++) {
    2242          36 :                         Fixed *v = (Fixed *)gf_malloc(sizeof(Fixed));
    2243          36 :                         *v = lsr_read_fixed_16_8(lsr, "val");
    2244          36 :                         gf_list_add(l, v);
    2245             :                 }
    2246             :                 return l;
    2247             :         }
    2248             : 
    2249             :         /*point */
    2250           3 :         case 9:
    2251           3 :                 pt = (SVG_Point*)gf_malloc(sizeof(SVG_Point));
    2252           3 :                 GF_LSR_READ_INT(lsr, flag, lsr->coord_bits, "valX");
    2253           6 :                 pt->x = lsr_translate_coords(lsr, flag, lsr->coord_bits);
    2254           3 :                 GF_LSR_READ_INT(lsr, flag, lsr->coord_bits, "valY");
    2255           6 :                 pt->y = lsr_translate_coords(lsr, flag, lsr->coord_bits);
    2256           3 :                 return pt;
    2257           0 :         case 10:
    2258           0 :                 id_val = (u32*)gf_malloc(sizeof(u32));
    2259           0 :                 *id_val = lsr_read_vluimsbf5(lsr, name);
    2260           0 :                 return id_val;
    2261          15 :         case 11:
    2262             :         {
    2263             :                 SVG_FontFamily *ft;
    2264             :                 u32 idx;
    2265          15 :                 GF_SAFEALLOC(ft, SVG_FontFamily);
    2266          15 :                 if (!ft) return NULL;
    2267          15 :                 if (escapeFlag) {
    2268           0 :                         ft->type = SVG_FONTFAMILY_INHERIT;
    2269             :                 } else {
    2270          15 :                         idx = lsr_read_vluimsbf5(lsr, name);
    2271          15 :                         ft->type = SVG_FONTFAMILY_VALUE;
    2272          15 :                         ft->value = (char*)gf_list_get(lsr->font_table, idx);
    2273          15 :                         if (ft->value) ft->value = gf_strdup(ft->value);
    2274             :                 }
    2275             :                 return ft;
    2276             :         }
    2277          21 :         case 12:
    2278          21 :                 GF_SAFEALLOC(iri, XMLRI);
    2279          21 :                 if (iri)
    2280          21 :                         lsr_read_any_uri(lsr, iri, name);
    2281             :                 return iri;
    2282           0 :         default:
    2283           0 :                 lsr_read_extension(lsr, name);
    2284             :                 break;
    2285             :         }
    2286           0 :         return NULL;
    2287             : }
    2288             : 
    2289          18 : static void lsr_translate_anim_trans_value(SMIL_AnimateValue *val, u32 transform_type)
    2290             : {
    2291             :         SVG_Point_Angle *p;
    2292             :         Fixed *f;
    2293          18 :         u32 coded_type = val->type;
    2294             : 
    2295          18 :         switch(transform_type) {
    2296           3 :         case SVG_TRANSFORM_TRANSLATE:
    2297           3 :                 val->type = SVG_Transform_Translate_datatype;
    2298           3 :                 break;
    2299           0 :         case SVG_TRANSFORM_SCALE:
    2300           0 :                 val->type = SVG_Transform_Scale_datatype;
    2301           0 :                 break;
    2302           6 :         case SVG_TRANSFORM_ROTATE:
    2303           6 :                 val->type = SVG_Transform_Rotate_datatype;
    2304           6 :                 break;
    2305           3 :         case SVG_TRANSFORM_SKEWX:
    2306           3 :                 val->type = SVG_Transform_SkewX_datatype;
    2307           3 :                 break;
    2308           6 :         case SVG_TRANSFORM_SKEWY:
    2309           6 :                 val->type = SVG_Transform_SkewY_datatype;
    2310           6 :                 break;
    2311           0 :         case SVG_TRANSFORM_MATRIX:
    2312           0 :                 val->type = SVG_Transform_datatype;
    2313           0 :                 break;
    2314           0 :         default:
    2315           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[LSR Parsing] unknown datatype for animate transform.\n"));
    2316             :                 return;
    2317             :         }
    2318          18 :         if (!val->value) return;
    2319          18 :         switch (transform_type) {
    2320           6 :         case SVG_TRANSFORM_ROTATE:
    2321           6 :                 p = (SVG_Point_Angle*)gf_malloc(sizeof(SVG_Point_Angle));
    2322           6 :                 p->x = p->y = 0;
    2323           6 :                 if (coded_type==8) {
    2324           6 :                         GF_List *l = (GF_List *)val->value;
    2325           6 :                         f = (Fixed*)gf_list_get(l, 0);
    2326           6 :                         if (f) {
    2327           6 :                                 p->angle = *f;
    2328           6 :                                 gf_free(f);
    2329             :                         }
    2330           6 :                         f = (Fixed*)gf_list_get(l, 1);
    2331           6 :                         if (f) {
    2332           6 :                                 p->x = *f;
    2333           6 :                                 gf_free(f);
    2334             :                         }
    2335           6 :                         f = (Fixed*)gf_list_get(l, 2);
    2336           6 :                         if (f) {
    2337           6 :                                 p->y = *f;
    2338           6 :                                 gf_free(f);
    2339             :                         }
    2340           6 :                         gf_list_del(l);
    2341             :                 } else {
    2342           0 :                         p->angle = ((SVG_Number *)val->value)->value;
    2343           0 :                         gf_free(val->value);
    2344             :                 }
    2345           6 :                 p->angle = gf_muldiv(p->angle, GF_PI, INT2FIX(180) );
    2346           6 :                 val->value = p;
    2347           6 :                 break;
    2348           0 :         case SVG_TRANSFORM_SCALE:
    2349           0 :                 if (coded_type==8) {
    2350             :                         SVG_Point *pt;
    2351             :                         GF_List *l = (GF_List *)val->value;
    2352           0 :                         GF_SAFEALLOC(pt , SVG_Point);
    2353           0 :                         if (!pt) return;
    2354           0 :                         f = (Fixed*)gf_list_get(l, 0);
    2355           0 :                         if (f) {
    2356           0 :                                 pt->x = *f;
    2357           0 :                                 gf_free(f);
    2358             :                         }
    2359           0 :                         f = (Fixed*)gf_list_get(l, 1);
    2360           0 :                         if (f) {
    2361           0 :                                 pt->y = *f;
    2362           0 :                                 gf_free(f);
    2363             :                         }
    2364           0 :                         else pt->y = pt->x;
    2365           0 :                         gf_list_del(l);
    2366           0 :                         val->value = pt;
    2367             :                 }
    2368             :                 break;
    2369           9 :         case SVG_TRANSFORM_SKEWX:
    2370             :         case SVG_TRANSFORM_SKEWY:
    2371           9 :                 f = (Fixed*)gf_malloc(sizeof(Fixed));
    2372           9 :                 *f = ((SVG_Number *)val->value)->value;
    2373           9 :                 gf_free(val->value);
    2374           9 :                 val->value = f;
    2375           9 :                 break;
    2376             :         }
    2377             : }
    2378             : 
    2379           0 : static void lsr_translate_anim_trans_values(SMIL_AnimateValues *val, u32 transform_type)
    2380             : {
    2381             :         u32 count, i, coded_type;
    2382             :         SVG_Point_Angle *p;
    2383             :         SVG_Point *pt;
    2384             :         Fixed *f;
    2385             :         GF_List *l;
    2386             : 
    2387           0 :         coded_type = val->type;
    2388           0 :         switch(transform_type) {
    2389           0 :         case SVG_TRANSFORM_TRANSLATE:
    2390           0 :                 val->type = SVG_Transform_Translate_datatype;
    2391           0 :                 break;
    2392           0 :         case SVG_TRANSFORM_SCALE:
    2393           0 :                 val->type = SVG_Transform_Scale_datatype;
    2394           0 :                 break;
    2395           0 :         case SVG_TRANSFORM_ROTATE:
    2396           0 :                 val->type = SVG_Transform_Rotate_datatype;
    2397           0 :                 break;
    2398           0 :         case SVG_TRANSFORM_SKEWX:
    2399           0 :                 val->type = SVG_Transform_SkewX_datatype;
    2400           0 :                 break;
    2401           0 :         case SVG_TRANSFORM_SKEWY:
    2402           0 :                 val->type = SVG_Transform_SkewY_datatype;
    2403           0 :                 break;
    2404           0 :         case SVG_TRANSFORM_MATRIX:
    2405           0 :                 val->type = SVG_Transform_datatype;
    2406           0 :                 break;
    2407           0 :         default:
    2408           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[SVG Parsing] unknown datatype for animate transform.\n"));
    2409             :                 return;
    2410             :         }
    2411           0 :         count = gf_list_count(val->values);
    2412           0 :         if (!count) return;
    2413             : 
    2414           0 :         if (transform_type==SVG_TRANSFORM_TRANSLATE)
    2415             :                 return;
    2416             : 
    2417           0 :         for (i=0; i<count; i++) {
    2418           0 :                 void *a_val = gf_list_get(val->values, i);
    2419           0 :                 switch (transform_type) {
    2420           0 :                 case SVG_TRANSFORM_ROTATE:
    2421           0 :                         GF_SAFEALLOC(p, SVG_Point_Angle);
    2422           0 :                         if (!p) return;
    2423             : 
    2424           0 :                         if (coded_type==8) {
    2425             :                                 l = (GF_List*)a_val;
    2426           0 :                                 f = (Fixed*)gf_list_get(l, 0);
    2427           0 :                                 p->angle = *f;
    2428           0 :                                 f = (Fixed*)gf_list_get(l, 1);
    2429           0 :                                 if (f) p->x = *f;
    2430           0 :                                 f = (Fixed*)gf_list_get(l, 2);
    2431           0 :                                 if (f) p->y = *f;
    2432           0 :                                 while (gf_list_count(l)) {
    2433           0 :                                         f = (Fixed*)gf_list_last(l);
    2434           0 :                                         gf_list_rem_last(l);
    2435           0 :                                         gf_free(f);
    2436             :                                 }
    2437           0 :                                 gf_list_del(l);
    2438           0 :                         } else if (coded_type==1) {
    2439           0 :                                 p->angle = ((SVG_Number *)a_val)->value;
    2440           0 :                                 gf_free(a_val);
    2441             :                         }
    2442           0 :                         p->angle = gf_muldiv(p->angle, GF_PI, INT2FIX(180) );
    2443           0 :                         gf_list_rem(val->values, i);
    2444           0 :                         gf_list_insert(val->values, p, i);
    2445           0 :                         break;
    2446           0 :                 case SVG_TRANSFORM_SKEWX:
    2447             :                 case SVG_TRANSFORM_SKEWY:
    2448           0 :                         f = (Fixed*)gf_malloc(sizeof(Fixed));
    2449           0 :                         *f = ((SVG_Number *)a_val)->value;
    2450           0 :                         gf_free(a_val);
    2451           0 :                         gf_list_rem(val->values, i);
    2452           0 :                         gf_list_insert(val->values, f, i);
    2453           0 :                         break;
    2454           0 :                 case SVG_TRANSFORM_SCALE:
    2455           0 :                         pt = (SVG_Point*)gf_malloc(sizeof(SVG_Point));
    2456             :                         l = (GF_List*)a_val;
    2457           0 :                         f = (Fixed*)gf_list_get(l, 0);
    2458           0 :                         if (f) pt->x = *f;
    2459           0 :                         f = (Fixed*)gf_list_get(l, 1);
    2460           0 :                         if (f) pt->y = *f;
    2461           0 :                         else pt->y = pt->x;
    2462           0 :                         while (gf_list_count(l)) {
    2463           0 :                                 f = (Fixed*)gf_list_last(l);
    2464           0 :                                 gf_list_rem_last(l);
    2465           0 :                                 gf_free(f);
    2466             :                         }
    2467           0 :                         gf_list_del(l);
    2468           0 :                         gf_list_rem(val->values, i);
    2469           0 :                         gf_list_insert(val->values, pt, i);
    2470           0 :                         break;
    2471           0 :                 default:
    2472           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[LASeR] unknown transform type %d\n", transform_type));
    2473             :                         break;
    2474             :                 }
    2475             :         }
    2476             : }
    2477             : 
    2478         377 : static void lsr_read_anim_value_ex(GF_LASeRCodec *lsr, GF_Node *n, u32 tag, const char *name, u32 *tr_type)
    2479             : {
    2480             :         u32 val, coded_type;
    2481         377 :         GF_LSR_READ_INT(lsr, val, 1, name);
    2482         377 :         if (val) {
    2483             :                 GF_FieldInfo info;
    2484          66 :                 lsr->last_error = gf_node_get_attribute_by_tag(n, tag, GF_TRUE, 0, &info);
    2485             : 
    2486          66 :                 GF_LSR_READ_INT(lsr, coded_type, 4, "type");
    2487          66 :                 ((SMIL_AnimateValue*)info.far_ptr)->value = lsr_read_an_anim_value(lsr, coded_type, name);
    2488          66 :                 ((SMIL_AnimateValue*)info.far_ptr)->type = coded_type;
    2489             : 
    2490          66 :                 if (tr_type) {
    2491          18 :                         lsr_translate_anim_trans_value(info.far_ptr, *tr_type);
    2492             :                 }
    2493             :         }
    2494         377 : }
    2495             : 
    2496         125 : static void lsr_read_anim_values_ex(GF_LASeRCodec *lsr, GF_Node *n, u32 *tr_type)
    2497             : {
    2498             :         u32 flag, i, count = 0;
    2499             :         u32 coded_type;
    2500             :         GF_FieldInfo info;
    2501             :         SMIL_AnimateValues *values;
    2502             : 
    2503         125 :         GF_LSR_READ_INT(lsr, flag, 1, "values");
    2504         187 :         if (!flag) return;
    2505             : 
    2506          63 :         lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_values, GF_TRUE, 0, &info);
    2507          63 :         values = (SMIL_AnimateValues *)info.far_ptr;
    2508             : 
    2509          63 :         GF_LSR_READ_INT(lsr, coded_type, 4, "type");
    2510          63 :         values->type = coded_type;
    2511          63 :         values->laser_strings = 1;
    2512             : 
    2513          63 :         count = lsr_read_vluimsbf5(lsr, "count");
    2514         318 :         for (i=0; i<count; i++) {
    2515         255 :                 void *att = lsr_read_an_anim_value(lsr, coded_type, "a_value");
    2516         255 :                 if (att) gf_list_add(values->values, att);
    2517             :         }
    2518          63 :         if (tr_type) {
    2519           0 :                 lsr_translate_anim_trans_values(info.far_ptr, *tr_type);
    2520             :         }
    2521             : }
    2522             : #define lsr_read_anim_value(_a, _b, _c, _d) lsr_read_anim_value_ex(_a, _b, _c, _d, NULL)
    2523             : #define lsr_read_anim_values(_a, _b) lsr_read_anim_values_ex(_a, _b, NULL)
    2524             : 
    2525          63 : static Fixed *lsr_read_fraction_12_item(GF_LASeRCodec *lsr)
    2526             : {
    2527             :         u32 flag;
    2528             :         Fixed *f;
    2529          63 :         GF_SAFEALLOC(f, Fixed);
    2530          63 :         if (!f) {
    2531           0 :                 lsr->last_error = GF_OUT_OF_MEM;
    2532             :                 return NULL;
    2533             :         }
    2534          63 :         GF_LSR_READ_INT(lsr, flag, 1, "hasShort");
    2535          63 :         if (flag) {
    2536          45 :                 GF_LSR_READ_INT(lsr, flag, 1, "isZero");
    2537          45 :                 if (flag) *f = 0;
    2538          21 :                 else *f = FIX_ONE;
    2539             :         } else {
    2540             :                 u32 v;
    2541          18 :                 GF_LSR_READ_INT(lsr, v, 12, "val");
    2542          18 :                 *f = INT2FIX(v) / 4096/*(1<<12)*/;
    2543             :         }
    2544             :         return f;
    2545             : }
    2546             : 
    2547         250 : static void lsr_read_fraction_12(GF_LASeRCodec *lsr, GF_Node *elt, u32 tag, const char *name)
    2548             : {
    2549             :         GF_FieldInfo info;
    2550             :         u32 i, count;
    2551         250 :         GF_LSR_READ_INT(lsr, count, 1, name);
    2552         491 :         if (!count) return;
    2553             : 
    2554           9 :         lsr->last_error = gf_node_get_attribute_by_tag(elt, tag, GF_TRUE, 0, &info);
    2555             : 
    2556           9 :         count = lsr_read_vluimsbf5(lsr, "name");
    2557          66 :         for (i=0; i<count; i++) {
    2558          57 :                 Fixed *f = lsr_read_fraction_12_item(lsr);
    2559          57 :                 gf_list_add( *((SMIL_KeyTimes*)info.far_ptr), f);
    2560             :         }
    2561             : }
    2562          25 : static void lsr_read_float_list(GF_LASeRCodec *lsr, GF_Node *n, u32 tag, SVG_Coordinates*coords, const char *name)
    2563             : {
    2564             :         u32 i, count;
    2565          25 :         GF_LSR_READ_INT(lsr, count, 1, name);
    2566          25 :         if (!count) return;
    2567             : 
    2568           3 :         if (!coords) {
    2569             :                 GF_FieldInfo info;
    2570           3 :                 lsr->last_error = gf_node_get_attribute_by_tag(n, tag, GF_TRUE, 0, &info);
    2571           3 :                 coords = (SVG_Coordinates*)info.far_ptr;
    2572             :         } else {
    2573           0 :                 while (gf_list_count(*coords)) {
    2574           0 :                         Fixed *v = (Fixed *)gf_list_last(*coords);
    2575           0 :                         gf_list_rem_last(*coords);
    2576           0 :                         gf_free(v);
    2577             :                 }
    2578             :         }
    2579           3 :         count = lsr_read_vluimsbf5(lsr, "count");
    2580           3 :         if (tag == TAG_SVG_ATT_text_rotate) {
    2581           0 :                 for (i=0; i<count; i++) {
    2582           0 :                         SVG_Number *num = (SVG_Number *)gf_malloc(sizeof(SVG_Number));
    2583           0 :                         num->type = SVG_NUMBER_VALUE;
    2584           0 :                         num->value = lsr_read_fixed_16_8(lsr, "val");
    2585           0 :                         gf_list_add(*coords, num);
    2586             :                 }
    2587             :         }
    2588             :         else {
    2589           9 :                 for (i=0; i<count; i++) {
    2590           9 :                         Fixed *num = (Fixed *)gf_malloc(sizeof(Fixed));
    2591           9 :                         *num = lsr_read_fixed_16_8(lsr, "val");
    2592           9 :                         gf_list_add(*coords, num);
    2593             :                 }
    2594             :         }
    2595             : }
    2596             : 
    2597          63 : static void lsr_read_point_sequence(GF_LASeRCodec *lsr, GF_List *pts, const char *name)
    2598             : {
    2599             :         u32 flag, i, count;
    2600             : 
    2601          63 :         while (gf_list_count(pts)) {
    2602           0 :                 SVG_Point *v = (SVG_Point *)gf_list_last(pts);
    2603           0 :                 gf_list_rem_last(pts);
    2604           0 :                 gf_free(v);
    2605             :         }
    2606          63 :         count = lsr_read_vluimsbf5(lsr, "nbPoints");
    2607          63 :         if (!count) return;
    2608             :         /*TODO golomb coding*/
    2609          57 :         GF_LSR_READ_INT(lsr, flag, 1, "flag");
    2610          57 :         if (!flag) {
    2611          57 :                 if (count < 3) {
    2612             :                         u32 nb_bits, v;
    2613           6 :                         GF_LSR_READ_INT(lsr, nb_bits, 5, "bits");
    2614          12 :                         for (i=0; i<count; i++) {
    2615          12 :                                 SVG_Point *pt = (SVG_Point *)gf_malloc(sizeof(SVG_Point));
    2616          12 :                                 gf_list_add(pts, pt);
    2617          12 :                                 GF_LSR_READ_INT(lsr, v, nb_bits, "x");
    2618          24 :                                 pt->x = lsr_translate_coords(lsr, v, nb_bits);
    2619          12 :                                 GF_LSR_READ_INT(lsr, v, nb_bits, "y");
    2620          24 :                                 pt->y = lsr_translate_coords(lsr, v, nb_bits);
    2621             :                         }
    2622             :                 } else {
    2623             :                         u32 nb_dx, nb_dy, k;
    2624             :                         Fixed x, y;
    2625          51 :                         SVG_Point *pt = (SVG_Point *)gf_malloc(sizeof(SVG_Point));
    2626          51 :                         gf_list_add(pts, pt);
    2627             : 
    2628          51 :                         GF_LSR_READ_INT(lsr, nb_dx, 5, "bits");
    2629          51 :                         GF_LSR_READ_INT(lsr, k, nb_dx, "x");
    2630         102 :                         x = pt->x = lsr_translate_coords(lsr, k, nb_dx);
    2631          51 :                         GF_LSR_READ_INT(lsr, k, nb_dx, "y");
    2632         102 :                         y = pt->y = lsr_translate_coords(lsr, k, nb_dx);
    2633             : 
    2634          51 :                         GF_LSR_READ_INT(lsr, nb_dx, 5, "bitsx");
    2635          51 :                         GF_LSR_READ_INT(lsr, nb_dy, 5, "bitsy");
    2636         303 :                         for (i=1; i<count; i++) {
    2637         303 :                                 pt = (SVG_Point *)gf_malloc(sizeof(SVG_Point));
    2638         303 :                                 gf_list_add(pts, pt);
    2639         303 :                                 GF_LSR_READ_INT(lsr, k, nb_dx, "dx");
    2640         606 :                                 pt->x = x + lsr_translate_coords(lsr, k, nb_dx);
    2641             :                                 x = pt->x;
    2642         303 :                                 GF_LSR_READ_INT(lsr, k, nb_dy, "dy");
    2643         606 :                                 pt->y = y + lsr_translate_coords(lsr, k, nb_dy);
    2644             :                                 y = pt->y;
    2645             :                         }
    2646             :                 }
    2647             :         }
    2648             : }
    2649          32 : static void lsr_read_path_type(GF_LASeRCodec *lsr, GF_Node *n, u32 tag, SVG_PathData *path, const char *name)
    2650             : {
    2651             : #if USE_GF_PATH
    2652             :         GF_Point2D *pt, *ct1, *ct2, *end;
    2653             :         GF_Point2D orig, ct_orig;
    2654             :         u32 i, count, cur_pt, type;
    2655          32 :         GF_List *pts = gf_list_new();
    2656          32 :         lsr_read_point_sequence(lsr, pts, "seq");
    2657             : 
    2658          32 :         if (!path) {
    2659             :                 GF_FieldInfo info;
    2660          26 :                 gf_node_get_attribute_by_tag(n, tag, GF_TRUE, 0, &info);
    2661          26 :                 path = (SVG_PathData*)info.far_ptr;
    2662             :         } else {
    2663           6 :                 gf_path_reset(path);
    2664             :         }
    2665             :         /*first MoveTo is skipped in LASeR*/
    2666          32 :         pt = (GF_Point2D*)gf_list_get(pts, 0);
    2667          32 :         if (pt) {
    2668          30 :                 ct_orig = orig = *pt;
    2669          30 :                 gf_path_add_move_to_vec(path, pt);
    2670             :         } else {
    2671             :                 orig.x = orig.y = 0;
    2672           2 :                 ct_orig = orig;
    2673           2 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] Empty path found.\n"));
    2674             :         }
    2675             :         cur_pt = 1;
    2676          32 :         count = lsr_read_vluimsbf5(lsr, "nbOfTypes");
    2677         140 :         for (i=0; i<count; i++) {
    2678         108 :                 GF_LSR_READ_INT(lsr, type, 5, name);
    2679         108 :                 switch (type) {
    2680          30 :                 case LSR_PATH_COM_h:
    2681             :                 case LSR_PATH_COM_l:
    2682             :                 case LSR_PATH_COM_v:
    2683             :                 case LSR_PATH_COM_H:
    2684             :                 case LSR_PATH_COM_V:
    2685             :                 case LSR_PATH_COM_L:
    2686          30 :                         pt = (GF_Point2D*)gf_list_get(pts, cur_pt);
    2687          30 :                         if (!pt) goto err_exit;
    2688          30 :                         gf_path_add_line_to_vec(path, pt);
    2689          30 :                         cur_pt++;
    2690          30 :                         break;
    2691           0 :                 case LSR_PATH_COM_m:
    2692             :                 case LSR_PATH_COM_M:
    2693           0 :                         pt = (GF_Point2D*)gf_list_get(pts, cur_pt);
    2694           0 :                         if (!pt) goto err_exit;
    2695           0 :                         gf_path_add_move_to_vec(path, pt);
    2696           0 :                         cur_pt++;
    2697           0 :                         break;
    2698           3 :                 case LSR_PATH_COM_q:
    2699             :                 case LSR_PATH_COM_Q:
    2700           3 :                         ct1 = (GF_Point2D*)gf_list_get(pts, cur_pt);
    2701           3 :                         end = (GF_Point2D*)gf_list_get(pts, cur_pt+1);
    2702           3 :                         if (!ct1 || !end) goto err_exit;
    2703           3 :                         gf_path_add_quadratic_to_vec(path, ct1, end);
    2704           3 :                         orig = *end;
    2705           3 :                         cur_pt+=2;
    2706           3 :                         break;
    2707          54 :                 case LSR_PATH_COM_c:
    2708             :                 case LSR_PATH_COM_C:
    2709          54 :                         ct1 = (GF_Point2D*)gf_list_get(pts, cur_pt);
    2710          54 :                         ct2 = (GF_Point2D*)gf_list_get(pts, cur_pt+1);
    2711          54 :                         end = (GF_Point2D*)gf_list_get(pts, cur_pt+2);
    2712         108 :                         if (!ct1 || !ct2 || !end) goto err_exit;
    2713          54 :                         gf_path_add_cubic_to_vec(path, ct1, ct2, end);
    2714          54 :                         cur_pt+=3;
    2715          54 :                         ct_orig = *ct2;
    2716          54 :                         orig = *end;
    2717          54 :                         break;
    2718           0 :                 case LSR_PATH_COM_s:
    2719             :                 case LSR_PATH_COM_S:
    2720           0 :                         ct_orig.x = 2*orig.x - ct_orig.x;
    2721           0 :                         ct_orig.y = 2*orig.y - ct_orig.y;
    2722           0 :                         ct2 = (GF_Point2D*)gf_list_get(pts, cur_pt);
    2723           0 :                         end = (GF_Point2D*)gf_list_get(pts, cur_pt+1);
    2724           0 :                         if (!ct2 || !end) goto err_exit;
    2725           0 :                         gf_path_add_cubic_to_vec(path, &ct_orig, ct2, end);
    2726           0 :                         ct_orig = *ct2;
    2727           0 :                         orig = *end;
    2728           0 :                         cur_pt+=2;
    2729           0 :                         break;
    2730           0 :                 case LSR_PATH_COM_t:
    2731             :                 case LSR_PATH_COM_T:
    2732           0 :                         ct_orig.x = 2*orig.x - ct_orig.x;
    2733           0 :                         ct_orig.y = 2*orig.y - ct_orig.y;
    2734           0 :                         end = gf_list_get(pts, cur_pt);
    2735           0 :                         if (!end) goto err_exit;
    2736           0 :                         gf_path_add_quadratic_to_vec(path, &ct_orig, end);
    2737           0 :                         orig = *end;
    2738           0 :                         break;
    2739          21 :                 case LSR_PATH_COM_z:
    2740             :                 case LSR_PATH_COM_Z:
    2741          21 :                         gf_path_close(path);
    2742          21 :                         break;
    2743             :                 }
    2744             :         }
    2745             :         goto exit;
    2746             : 
    2747           0 : err_exit:
    2748           0 :         lsr->last_error = GF_NON_COMPLIANT_BITSTREAM;
    2749             : 
    2750             : exit:
    2751         260 :         while (gf_list_count(pts)) {
    2752         228 :                 end = (GF_Point2D*)gf_list_get(pts, 0);
    2753         228 :                 gf_list_rem(pts, 0);
    2754         228 :                 gf_free(end);
    2755             :         }
    2756          32 :         gf_list_del(pts);
    2757             : 
    2758             : #else
    2759             :         u32 i, count, c;
    2760             :         if (!path) {
    2761             :                 lsr->last_error = GF_BAD_PARAM;
    2762             :                 return;
    2763             :         }
    2764             :         lsr_read_point_sequence(lsr, path->points, "seq");
    2765             :         while (gf_list_count(path->commands)) {
    2766             :                 u8 *v = (u8 *)gf_list_last(path->commands);
    2767             :                 gf_list_rem_last(path->commands);
    2768             :                 gf_free(v);
    2769             :         }
    2770             : 
    2771             :         count = lsr_read_vluimsbf5(lsr, "nbOfTypes");
    2772             :         for (i=0; i<count; i++) {
    2773             :                 u8 *type = (u8 *)gf_malloc(sizeof(u8));
    2774             :                 GF_LSR_READ_INT(lsr, c, 5, name);
    2775             : 
    2776             :                 switch (c) {
    2777             :                 case LSR_PATH_COM_h:
    2778             :                 case LSR_PATH_COM_l:
    2779             :                 case LSR_PATH_COM_v:
    2780             :                 case LSR_PATH_COM_H:
    2781             :                 case LSR_PATH_COM_V:
    2782             :                 case LSR_PATH_COM_L:
    2783             :                         *type=SVG_PATHCOMMAND_L;
    2784             :                         break;
    2785             :                 case LSR_PATH_COM_m:
    2786             :                 case LSR_PATH_COM_M:
    2787             :                         *type=SVG_PATHCOMMAND_M;
    2788             :                         break;
    2789             :                 case LSR_PATH_COM_q:
    2790             :                 case LSR_PATH_COM_Q:
    2791             :                         *type=SVG_PATHCOMMAND_Q;
    2792             :                         break;
    2793             :                 case LSR_PATH_COM_c:
    2794             :                 case LSR_PATH_COM_C:
    2795             :                         *type=SVG_PATHCOMMAND_C;
    2796             :                         break;
    2797             :                 case LSR_PATH_COM_s:
    2798             :                 case LSR_PATH_COM_S:
    2799             :                         *type=SVG_PATHCOMMAND_S;
    2800             :                         break;
    2801             :                 case LSR_PATH_COM_t:
    2802             :                 case LSR_PATH_COM_T:
    2803             :                         *type=SVG_PATHCOMMAND_T;
    2804             :                         break;
    2805             :                 case LSR_PATH_COM_z:
    2806             :                 case LSR_PATH_COM_Z:
    2807             :                         *type=SVG_PATHCOMMAND_Z;
    2808             :                         break;
    2809             :                 }
    2810             :                 gf_list_add(path->commands, type);
    2811             :         }
    2812             : #endif
    2813          32 : }
    2814             : 
    2815           8 : static void lsr_read_rotate_type(GF_LASeRCodec *lsr, GF_Node *n)
    2816             : {
    2817             :         u32 flag;
    2818           8 :         GF_LSR_READ_INT(lsr, flag, 1, "rotate");
    2819           8 :         if (flag) {
    2820             :                 GF_FieldInfo info;
    2821           6 :                 lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_rotate, GF_TRUE, 0, &info);
    2822           6 :                 GF_LSR_READ_INT(lsr, flag, 1, "choice");
    2823             : 
    2824           6 :                 if (flag) {
    2825           3 :                         GF_LSR_READ_INT(lsr, flag, 1, "rotate");
    2826           3 :                         ((SVG_Number *)info.far_ptr)->type = flag ? SVG_NUMBER_AUTO_REVERSE : SVG_NUMBER_AUTO;
    2827             :                 } else {
    2828           3 :                         ((SVG_Number *)info.far_ptr)->value = lsr_read_fixed_16_8(lsr, "rotate");
    2829           3 :                         ((SVG_Number *)info.far_ptr)->type = SVG_NUMBER_VALUE;
    2830             :                 }
    2831             :         }
    2832           8 : }
    2833          10 : static void lsr_read_sync_behavior(GF_LASeRCodec *lsr, GF_Node *n)
    2834             : {
    2835             :         u32 flag;
    2836          10 :         GF_LSR_READ_INT(lsr, flag, 1, "syncBehavior");
    2837          10 :         if (flag) {
    2838             :                 GF_FieldInfo info;
    2839           3 :                 GF_LSR_READ_INT(lsr, flag, 2, "syncBehavior");
    2840           3 :                 lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_syncBehavior, GF_TRUE, 0, &info);
    2841           3 :                 *(SMIL_SyncBehavior*)info.far_ptr = flag + 1;
    2842             :         }
    2843          10 : }
    2844          10 : static void lsr_read_sync_tolerance(GF_LASeRCodec *lsr, GF_Node *n)
    2845             : {
    2846             :         u32 flag;
    2847          10 :         GF_LSR_READ_INT(lsr, flag, 1, "syncTolerance");
    2848          10 :         if (flag) {
    2849             :                 GF_FieldInfo info;
    2850           6 :                 GF_LSR_READ_INT(lsr, flag, 1, "syncTolerance");
    2851           6 :                 lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_syncTolerance, GF_TRUE, 0, &info);
    2852           6 :                 if (flag) ((SMIL_SyncTolerance *)info.far_ptr)->type = SMIL_SYNCTOLERANCE_DEFAULT;
    2853             :                 else {
    2854           3 :                         u32 v = lsr_read_vluimsbf5(lsr, "value");
    2855           3 :                         ((SMIL_SyncTolerance *)info.far_ptr)->value = INT2FIX(v);
    2856           3 :                         ((SMIL_SyncTolerance *)info.far_ptr)->value /= lsr->time_resolution;
    2857             :                 }
    2858             :         }
    2859          10 : }
    2860          10 : static void lsr_read_sync_reference(GF_LASeRCodec *lsr, GF_Node *n)
    2861             : {
    2862             :         u32 flag;
    2863          10 :         GF_LSR_READ_INT(lsr, flag, 1, "hasSyncReference");
    2864          10 :         if (flag) {
    2865             :                 GF_FieldInfo info;
    2866           0 :                 lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_syncReference, GF_TRUE, 0, &info);
    2867           0 :                 lsr_read_any_uri(lsr, info.far_ptr, "syncReference");
    2868             :         }
    2869          10 : }
    2870             : 
    2871          67 : static void lsr_read_coordinate(GF_LASeRCodec *lsr, SVG_Number *coord, Bool skipable, const char *name)
    2872             : {
    2873             :         u32 flag;
    2874          67 :         if (skipable) {
    2875           0 :                 GF_LSR_READ_INT(lsr, flag, 1, name);
    2876           0 :                 if (!flag) {
    2877             :                         //coord->type = SVG_NUMBER_UNKNOWN;
    2878             :                         //coord->value = 0;
    2879             :                         return;
    2880             :                 }
    2881             :         }
    2882          67 :         coord->type = SVG_NUMBER_VALUE;
    2883          67 :         GF_LSR_READ_INT(lsr, flag, lsr->coord_bits, name);
    2884         134 :         coord->value = lsr_translate_coords(lsr, flag, lsr->coord_bits);
    2885             : }
    2886         701 : static void lsr_read_coordinate_ptr(GF_LASeRCodec *lsr, GF_Node *n, u32 tag, Bool skipable, const char *name)
    2887             : {
    2888             :         u32 flag;
    2889             :         GF_FieldInfo info;
    2890         701 :         if (skipable) {
    2891         518 :                 GF_LSR_READ_INT(lsr, flag, 1, name);
    2892         853 :                 if (!flag) return;
    2893             :         }
    2894         366 :         lsr->last_error = gf_node_get_attribute_by_tag(n, tag, GF_TRUE, 0, &info);
    2895             : 
    2896         366 :         ((SVG_Number*)info.far_ptr)->type = SVG_NUMBER_VALUE;
    2897         366 :         GF_LSR_READ_INT(lsr, flag, lsr->coord_bits, name);
    2898         732 :         ((SVG_Number*)info.far_ptr)->value = lsr_translate_coords(lsr, flag, lsr->coord_bits);
    2899             : }
    2900             : 
    2901          34 : static void lsr_read_coord_list(GF_LASeRCodec *lsr, GF_Node *elt, u32 tag, const char *name)
    2902             : {
    2903             :         GF_FieldInfo info;
    2904             :         u32 i, count;
    2905          34 :         GF_LSR_READ_INT(lsr, count, 1, name);
    2906          50 :         if (!count) return;
    2907          18 :         count = lsr_read_vluimsbf5(lsr, "nb_coords");
    2908          18 :         if (!count) return;
    2909          18 :         if (count>1000000) {
    2910           0 :                 lsr->last_error = GF_NON_COMPLIANT_BITSTREAM;
    2911           0 :                 return;
    2912             :         }
    2913             : 
    2914          18 :         lsr->last_error = gf_node_get_attribute_by_tag(elt, tag, GF_TRUE, 0, &info);
    2915             : 
    2916          36 :         for (i=0; i<count; i++) {
    2917             :                 u32 res;
    2918             :                 SVG_Coordinate *f;
    2919          18 :                 GF_SAFEALLOC(f, SVG_Coordinate );
    2920          18 :                 if (!f) {
    2921           0 :                         lsr->last_error = GF_OUT_OF_MEM;
    2922           0 :                         return;
    2923             :                 }
    2924          18 :                 GF_LSR_READ_INT(lsr, res, lsr->coord_bits, name);
    2925          36 :                 f->value = lsr_translate_coords(lsr, res, lsr->coord_bits);
    2926          18 :                 gf_list_add(*(SVG_Coordinates*)info.far_ptr, f);
    2927             :         }
    2928             : }
    2929             : 
    2930          46 : static void lsr_read_transform_behavior(GF_LASeRCodec *lsr, GF_Node *n)
    2931             : {
    2932             :         GF_FieldInfo info;
    2933             :         u32 flag;
    2934          46 :         GF_LSR_READ_INT(lsr, flag, 1, "hasTransformBehavior");
    2935          46 :         if (flag) {
    2936           0 :                 lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_transformBehavior, GF_TRUE, 0, &info);
    2937           0 :                 GF_LSR_READ_INT(lsr, *(SVG_TransformBehavior*)info.far_ptr, 4, "transformBehavior");
    2938             :         }
    2939          46 : }
    2940             : 
    2941          51 : static void lsr_read_content_type(GF_LASeRCodec *lsr, GF_Node *n)
    2942             : {
    2943             :         u32 flag;
    2944          51 :         GF_LSR_READ_INT(lsr, flag, 1, "hasType");
    2945          51 :         if (flag) {
    2946             :                 GF_FieldInfo info;
    2947           0 :                 lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_type, GF_TRUE, 0, &info);
    2948           0 :                 lsr_read_byte_align_string(lsr, info.far_ptr, "type");
    2949             :         }
    2950          51 : }
    2951           5 : static void lsr_read_script_type(GF_LASeRCodec *lsr, GF_Node *n)
    2952             : {
    2953             :         u32 flag;
    2954           5 :         GF_LSR_READ_INT(lsr, flag, 1, "hasType");
    2955           5 :         if (flag) {
    2956             :                 GF_FieldInfo info;
    2957           3 :                 lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_XLINK_ATT_type, GF_TRUE, 0, &info);
    2958           3 :                 GF_LSR_READ_INT(lsr, flag, 1, "choice");
    2959           3 :                 if (flag) {
    2960           3 :                         GF_LSR_READ_INT(lsr, flag, 1, "script");
    2961           3 :                         switch (flag) {
    2962           3 :                         case 0:
    2963           3 :                                 *(SVG_String*)info.far_ptr = gf_strdup("application/ecmascript");
    2964           3 :                                 break;
    2965           0 :                         case 1:
    2966           0 :                                 *(SVG_String*)info.far_ptr = gf_strdup("application/jar-archive");
    2967           0 :                                 break;
    2968             :                         default:
    2969             :                                 break;
    2970             :                         }
    2971             :                 } else {
    2972           0 :                         lsr_read_byte_align_string(lsr, info.far_ptr, "type");
    2973             :                 }
    2974             :         }
    2975           5 : }
    2976          13 : static void lsr_read_value_with_units(GF_LASeRCodec *lsr, SVG_Number *n, const char *name)
    2977             : {
    2978             :         s32 val;
    2979          13 :         GF_LSR_READ_INT(lsr, val, 32, name);
    2980             : #ifdef GPAC_FIXED_POINT
    2981             :         n->value = val << 8;
    2982             : #else
    2983          13 :         n->value = INT2FIX(val) / (1<<8);
    2984             : #endif
    2985          13 :         GF_LSR_READ_INT(lsr, val, 3, "units");
    2986          13 :         switch (val) {
    2987           0 :         case 1:
    2988           0 :                 n->type = SVG_NUMBER_IN;
    2989             :                 break;
    2990           0 :         case 2:
    2991           0 :                 n->type = SVG_NUMBER_CM;
    2992             :                 break;
    2993           0 :         case 3:
    2994           0 :                 n->type = SVG_NUMBER_MM;
    2995             :                 break;
    2996           0 :         case 4:
    2997           0 :                 n->type = SVG_NUMBER_PT;
    2998             :                 break;
    2999           0 :         case 5:
    3000           0 :                 n->type = SVG_NUMBER_PC;
    3001             :                 break;
    3002           3 :         case 6:
    3003           3 :                 n->type = SVG_NUMBER_PERCENTAGE;
    3004             :                 break;
    3005          10 :         default:
    3006          10 :                 n->type = SVG_NUMBER_VALUE;
    3007             :                 break;
    3008             :         }
    3009          13 : }
    3010             : 
    3011             : 
    3012          20 : static void lsr_read_clip_time(GF_LASeRCodec *lsr, GF_Node *elt, u32 tag, const char *name)
    3013             : {
    3014             :         GF_FieldInfo info;
    3015             :         u32 flag;
    3016          20 :         GF_LSR_READ_INT(lsr, flag, 1, name);
    3017          20 :         if (flag) {
    3018           2 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, tag, 1, 0, &info);
    3019           2 :                 GF_LSR_READ_INT(lsr, flag, 1, "isEnum");
    3020           2 :                 if (!flag) {
    3021           2 :                         GF_LSR_READ_INT(lsr, flag, 1, "sign");
    3022           2 :                         flag = lsr_read_vluimsbf5(lsr, "val");
    3023           2 :                         *((SVG_Clock *)info.far_ptr) = flag;
    3024           2 :                         *((SVG_Clock *)info.far_ptr) /= lsr->time_resolution;
    3025             :                 }
    3026             :         }
    3027          20 : }
    3028             : 
    3029         127 : static void lsr_read_attribute_type(GF_LASeRCodec *lsr, GF_Node *elt)
    3030             : {
    3031             :         GF_FieldInfo info;
    3032             :         u32 flag;
    3033         127 :         GF_LSR_READ_INT(lsr, flag, 1, "hasAttributeType");
    3034         254 :         if (!flag) return;
    3035           0 :         lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_attributeType, 1, 0, &info);
    3036           0 :         GF_LSR_READ_INT(lsr, *(SMIL_AttributeType*)info.far_ptr, 2, "attributeType");
    3037             : }
    3038             : 
    3039          51 : static void lsr_read_preserve_aspect_ratio(GF_LASeRCodec *lsr, GF_Node *n)
    3040             : {
    3041             :         GF_FieldInfo info;
    3042             :         u32 flag;
    3043             :         SVG_PreserveAspectRatio *par;
    3044             : 
    3045          51 :         GF_LSR_READ_INT(lsr, flag, 1, "hasPreserveAspectRatio");
    3046          63 :         if (!flag) return;
    3047             : 
    3048          39 :         lsr->last_error = gf_node_get_attribute_by_tag(n, TAG_SVG_ATT_preserveAspectRatio, 1, 0, &info);
    3049          39 :         par = (SVG_PreserveAspectRatio *)info.far_ptr;
    3050             : 
    3051          39 :         GF_LSR_READ_INT(lsr, flag, 1, "choice (meetOrSlice)");
    3052          39 :         GF_LSR_READ_INT(lsr, par->defer, 1, "choice (defer)");
    3053          39 :         GF_LSR_READ_INT(lsr, flag, 4, "alignXandY");
    3054          39 :         switch (flag) {
    3055           3 :         case 1:
    3056           3 :                 par->align = SVG_PRESERVEASPECTRATIO_XMAXYMAX;
    3057             :                 break;
    3058           3 :         case 2:
    3059           3 :                 par->align = SVG_PRESERVEASPECTRATIO_XMAXYMID;
    3060             :                 break;
    3061           3 :         case 3:
    3062           3 :                 par->align = SVG_PRESERVEASPECTRATIO_XMAXYMIN;
    3063             :                 break;
    3064           3 :         case 4:
    3065           3 :                 par->align = SVG_PRESERVEASPECTRATIO_XMIDYMAX;
    3066             :                 break;
    3067          12 :         case 5:
    3068          12 :                 par->align = SVG_PRESERVEASPECTRATIO_XMIDYMID;
    3069             :                 break;
    3070           3 :         case 6:
    3071           3 :                 par->align = SVG_PRESERVEASPECTRATIO_XMIDYMIN;
    3072             :                 break;
    3073           3 :         case 7:
    3074           3 :                 par->align = SVG_PRESERVEASPECTRATIO_XMINYMAX;
    3075             :                 break;
    3076           3 :         case 8:
    3077           3 :                 par->align = SVG_PRESERVEASPECTRATIO_XMINYMID;
    3078             :                 break;
    3079           3 :         case 9:
    3080           3 :                 par->align = SVG_PRESERVEASPECTRATIO_XMINYMIN;
    3081             :                 break;
    3082           3 :         default:
    3083           3 :                 par->align = SVG_PRESERVEASPECTRATIO_NONE;
    3084             :                 break;
    3085             :         }
    3086             : }
    3087             : 
    3088         142 : static void lsr_read_eRR(GF_LASeRCodec *lsr, GF_Node *elt)
    3089             : {
    3090             :         u32 err;
    3091         142 :         GF_LSR_READ_INT(lsr, err, 1, "externalResourcesRequired");
    3092         142 :         if (err) {
    3093             :                 GF_FieldInfo info;
    3094           0 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_externalResourcesRequired, 1, 0, &info);
    3095           0 :                 *(SVG_Boolean*)info.far_ptr = 1;
    3096             :         }
    3097         142 : }
    3098             : 
    3099         137 : static void lsr_read_lsr_enabled(GF_LASeRCodec *lsr, GF_Node *elt)
    3100             : {
    3101             :         u32 err;
    3102         137 :         GF_LSR_READ_INT(lsr, err, 1, "enabled");
    3103         137 :         if (err) {
    3104             :                 GF_FieldInfo info;
    3105          15 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_LSR_ATT_enabled, 1, 0, &info);
    3106          15 :                 *(SVG_Boolean*)info.far_ptr = 1;
    3107             :         }
    3108         137 : }
    3109             : 
    3110          14 : static GF_Node *lsr_read_a(GF_LASeRCodec *lsr)
    3111             : {
    3112             :         Bool flag;
    3113          14 :         GF_Node *elt = (GF_Node*) gf_node_new(lsr->sg, TAG_SVG_a);
    3114          14 :         lsr_read_id(lsr, elt);
    3115          14 :         lsr_read_rare_full(lsr, elt);
    3116          14 :         lsr_read_fill(lsr, elt);
    3117          14 :         lsr_read_stroke(lsr, elt);
    3118          14 :         lsr_read_eRR(lsr, elt);
    3119          14 :         GF_LSR_READ_INT(lsr, flag, 1, "hasTarget");
    3120          14 :         if (flag) {
    3121             :                 GF_FieldInfo info;
    3122           3 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_target, 1, 0, &info);
    3123           3 :                 lsr_read_byte_align_string(lsr, info.far_ptr, "target");
    3124             :         }
    3125          14 :         lsr_read_href(lsr, elt);
    3126          14 :         lsr_read_any_attribute(lsr, elt, 1);
    3127          14 :         lsr_read_group_content(lsr, elt, 0);
    3128          14 :         return elt;
    3129             : }
    3130             : 
    3131             : 
    3132             : 
    3133         103 : static GF_Node *lsr_read_animate(GF_LASeRCodec *lsr, SVG_Element *parent, Bool is_animateColor)
    3134             : {
    3135         103 :         GF_Node *elt = gf_node_new(lsr->sg, is_animateColor ? TAG_SVG_animateColor : TAG_SVG_animate);
    3136         103 :         lsr_read_id(lsr, elt);
    3137         103 :         lsr_read_rare(lsr, elt);
    3138             :         lsr_read_attribute_name(lsr, elt);
    3139             : 
    3140         103 :         lsr_read_accumulate(lsr, elt);
    3141         103 :         lsr_read_additive(lsr, elt);
    3142         103 :         lsr_read_anim_value(lsr, elt, TAG_SVG_ATT_by, "by");
    3143         103 :         lsr_read_calc_mode(lsr, elt);
    3144         103 :         lsr_read_anim_value(lsr, elt, TAG_SVG_ATT_from, "from");
    3145         103 :         lsr_read_fraction_12(lsr, elt, TAG_SVG_ATT_keySplines, "keySplines");
    3146         103 :         lsr_read_fraction_12(lsr, elt, TAG_SVG_ATT_keyTimes, "keyTimes");
    3147         103 :         lsr_read_anim_values(lsr, elt);
    3148         103 :         lsr_read_attribute_type(lsr, elt);
    3149         103 :         lsr_read_smil_times(lsr, elt, TAG_SVG_ATT_begin, NULL, "begin", 1);
    3150             :         lsr_read_duration(lsr, elt);
    3151         103 :         lsr_read_anim_fill(lsr, elt);
    3152         103 :         lsr_read_anim_repeatCount(lsr, elt);
    3153         103 :         lsr_read_repeat_duration(lsr, elt);
    3154         103 :         lsr_read_anim_restart(lsr, elt);
    3155         103 :         lsr_read_anim_value(lsr, elt, TAG_SVG_ATT_to, "to");
    3156         103 :         lsr_read_href(lsr, elt);
    3157         103 :         lsr_read_lsr_enabled(lsr, elt);
    3158         103 :         lsr_read_any_attribute(lsr, elt, 1);
    3159             : 
    3160         103 :         if (!lsr_setup_smil_anim(lsr, (SVG_Element*)elt, parent)) {
    3161          36 :                 gf_list_add(lsr->deferred_anims, elt);
    3162          36 :                 lsr_read_group_content_post_init(lsr, (SVG_Element*)elt, 1);
    3163             :         } else {
    3164          67 :                 lsr_read_group_content(lsr, elt, 0);
    3165             :         }
    3166         103 :         return elt;
    3167             : }
    3168             : 
    3169             : 
    3170           8 : static GF_Node *lsr_read_animateMotion(GF_LASeRCodec *lsr, SVG_Element *parent)
    3171             : {
    3172             :         Bool flag;
    3173           8 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_animateMotion);
    3174           8 :         lsr_read_id(lsr, elt);
    3175           8 :         lsr_read_rare(lsr, elt);
    3176           8 :         lsr_read_accumulate(lsr, elt);
    3177           8 :         lsr_read_additive(lsr, elt);
    3178           8 :         lsr_read_anim_value(lsr, elt, TAG_SVG_ATT_by, "by");
    3179           8 :         lsr_read_calc_mode(lsr, elt);
    3180           8 :         lsr_read_anim_value(lsr, elt, TAG_SVG_ATT_from, "from");
    3181           8 :         lsr_read_fraction_12(lsr, elt, TAG_SVG_ATT_keySplines, "keySplines");
    3182           8 :         lsr_read_fraction_12(lsr, elt, TAG_SVG_ATT_keyTimes, "keyTimes");
    3183           8 :         lsr_read_anim_values(lsr, elt);
    3184           8 :         lsr_read_attribute_type(lsr, elt);
    3185           8 :         lsr_read_smil_times(lsr, elt, TAG_SVG_ATT_begin, NULL, "begin", 1);
    3186             :         lsr_read_duration(lsr, elt);
    3187           8 :         lsr_read_anim_fill(lsr, elt);
    3188           8 :         lsr_read_anim_repeatCount(lsr, elt);
    3189           8 :         lsr_read_repeat_duration(lsr, elt);
    3190           8 :         lsr_read_anim_restart(lsr, elt);
    3191           8 :         lsr_read_anim_value(lsr, elt, TAG_SVG_ATT_to, "to");
    3192           8 :         lsr_read_float_list(lsr, elt, TAG_SVG_ATT_keyPoints, NULL, "keyPoints");
    3193           8 :         GF_LSR_READ_INT(lsr, flag, 1, "hasPath");
    3194           8 :         if (flag) lsr_read_path_type(lsr, elt, TAG_SVG_ATT_path, NULL, "path");
    3195             : 
    3196           8 :         lsr_read_rotate_type(lsr, elt);
    3197           8 :         lsr_read_href(lsr, elt);
    3198           8 :         lsr_read_lsr_enabled(lsr, elt);
    3199           8 :         lsr_read_any_attribute(lsr, elt, 1);
    3200             : 
    3201           8 :         if (!lsr_setup_smil_anim(lsr, (SVG_Element*)elt, parent)) {
    3202           0 :                 gf_list_add(lsr->deferred_anims, elt);
    3203           0 :                 lsr_read_group_content_post_init(lsr, (SVG_Element*)elt, 1);
    3204             :         } else {
    3205           8 :                 lsr_read_group_content_post_init(lsr, (SVG_Element*)elt, 0);
    3206             :         }
    3207           8 :         return elt;
    3208             : }
    3209             : 
    3210             : 
    3211          14 : static GF_Node *lsr_read_animateTransform(GF_LASeRCodec *lsr, SVG_Element *parent)
    3212             : {
    3213             :         u32 type;
    3214             :         u32 flag;
    3215             :         GF_FieldInfo info;
    3216          14 :         GF_Node *elt= gf_node_new(lsr->sg, TAG_SVG_animateTransform);
    3217          14 :         lsr_read_id(lsr, elt);
    3218          14 :         lsr_read_rare(lsr, elt);
    3219             :         lsr_read_attribute_name(lsr, elt);
    3220             : 
    3221             :         /*enumeration rotate{0} scale{1} skewX{2} skewY{3} translate{4}*/
    3222          14 :         GF_LSR_READ_INT(lsr, flag, 3, "rotscatra");
    3223          14 :         switch (flag) {
    3224           3 :         case 0:
    3225           3 :                 type = SVG_TRANSFORM_ROTATE;
    3226           3 :                 break;
    3227           0 :         case 1:
    3228           0 :                 type = SVG_TRANSFORM_SCALE;
    3229           0 :                 break;
    3230           3 :         case 2:
    3231           3 :                 type = SVG_TRANSFORM_SKEWX;
    3232           3 :                 break;
    3233           3 :         case 3:
    3234           3 :                 type = SVG_TRANSFORM_SKEWY;
    3235           3 :                 break;
    3236           5 :         case 4:
    3237           5 :                 type = SVG_TRANSFORM_TRANSLATE;
    3238           5 :                 break;
    3239           0 :         default:
    3240           0 :                 type = SVG_TRANSFORM_ROTATE;
    3241           0 :                 break;
    3242             :         }
    3243          14 :         if (gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_transform_type, 1, 0, &info)==GF_OK) {
    3244          14 :                 *(SVG_TransformType *)info.far_ptr = type;
    3245             :         }
    3246             : 
    3247          14 :         lsr_read_accumulate(lsr, elt);
    3248          14 :         lsr_read_additive(lsr, elt);
    3249          14 :         lsr_read_anim_value_ex(lsr, elt, TAG_SVG_ATT_by, "by", &type);
    3250          14 :         lsr_read_calc_mode(lsr, elt);
    3251          14 :         lsr_read_anim_value_ex(lsr, elt, TAG_SVG_ATT_from, "from", &type);
    3252          14 :         lsr_read_fraction_12(lsr, elt, TAG_SVG_ATT_keySplines, "keySplines");
    3253          14 :         lsr_read_fraction_12(lsr, elt, TAG_SVG_ATT_keyTimes, "keyTimes");
    3254          14 :         lsr_read_anim_values_ex(lsr, elt, &type);
    3255          14 :         lsr_read_attribute_type(lsr, elt);
    3256             : 
    3257          14 :         lsr_read_smil_times(lsr, elt, TAG_SVG_ATT_begin, NULL, "begin", 1);
    3258             :         lsr_read_duration(lsr, elt);
    3259          14 :         lsr_read_anim_fill(lsr, elt);
    3260          14 :         lsr_read_anim_repeatCount(lsr, elt);
    3261          14 :         lsr_read_repeat_duration(lsr, elt);
    3262          14 :         lsr_read_anim_restart(lsr, elt);
    3263          14 :         lsr_read_anim_value_ex(lsr, elt, TAG_SVG_ATT_to, "to", &type);
    3264             : 
    3265          14 :         lsr_read_href(lsr, elt);
    3266          14 :         lsr_read_lsr_enabled(lsr, elt);
    3267          14 :         lsr_read_any_attribute(lsr, elt, 1);
    3268             : 
    3269          14 :         if (!lsr_setup_smil_anim(lsr, (SVG_Element*)elt, parent)) {
    3270           0 :                 gf_list_add(lsr->deferred_anims, elt);
    3271           0 :                 lsr_read_group_content_post_init(lsr, (SVG_Element*)elt, 1);
    3272             :         } else {
    3273          14 :                 lsr_read_group_content(lsr, elt, 0);
    3274             :         }
    3275          14 :         return elt;
    3276             : }
    3277             : 
    3278           5 : static GF_Node *lsr_read_audio(GF_LASeRCodec *lsr, SVG_Element *parent)
    3279             : {
    3280           5 :         GF_Node *elt= gf_node_new(lsr->sg, TAG_SVG_audio);
    3281           5 :         lsr_read_id(lsr, elt);
    3282           5 :         lsr_read_rare(lsr, elt);
    3283           5 :         lsr_read_smil_times(lsr, elt, TAG_SVG_ATT_begin, NULL, "begin", 1);
    3284             :         lsr_read_duration(lsr, elt);
    3285           5 :         lsr_read_eRR(lsr, elt);
    3286           5 :         lsr_read_anim_repeatCount(lsr, elt);
    3287           5 :         lsr_read_repeat_duration(lsr, elt);
    3288           5 :         lsr_read_anim_restart(lsr, elt);
    3289           5 :         lsr_read_sync_behavior(lsr, elt);
    3290           5 :         lsr_read_sync_tolerance(lsr, elt);
    3291           5 :         lsr_read_content_type(lsr, elt);
    3292           5 :         lsr_read_href(lsr, elt);
    3293             : 
    3294           5 :         lsr_read_clip_time(lsr, elt, TAG_SVG_ATT_clipBegin, "clipBegin");
    3295           5 :         lsr_read_clip_time(lsr, elt, TAG_SVG_ATT_clipEnd, "clipEnd");
    3296           5 :         lsr_read_sync_reference(lsr, elt);
    3297           5 :         lsr_read_any_attribute(lsr, elt, 1);
    3298           5 :         lsr_read_group_content(lsr, elt, 0);
    3299           5 :         return elt;
    3300             : }
    3301          11 : static GF_Node *lsr_read_circle(GF_LASeRCodec *lsr)
    3302             : {
    3303          11 :         GF_Node *elt= gf_node_new(lsr->sg, TAG_SVG_circle);
    3304          11 :         lsr_read_id(lsr, elt);
    3305          11 :         lsr_read_rare_full(lsr, elt);
    3306          11 :         lsr_read_fill(lsr, elt);
    3307          11 :         lsr_read_stroke(lsr, elt);
    3308          11 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_cx, 1, "cx");
    3309          11 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_cy, 1, "cy");
    3310          11 :         lsr_read_coordinate_ptr(lsr, elt,TAG_SVG_ATT_r, 0, "r");
    3311          11 :         lsr_read_any_attribute(lsr, elt, 1);
    3312          11 :         lsr_read_group_content(lsr, elt, 0);
    3313          11 :         return elt;
    3314             : }
    3315           5 : static GF_Node *lsr_read_conditional(GF_LASeRCodec *lsr)
    3316             : {
    3317           5 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_LSR_conditional);
    3318           5 :         lsr_read_id(lsr, elt);
    3319           5 :         lsr_read_rare(lsr, elt);
    3320           5 :         lsr_read_smil_times(lsr, elt, TAG_SVG_ATT_begin, NULL, "begin", 1);
    3321           5 :         lsr_read_eRR(lsr, elt);
    3322           5 :         lsr_read_lsr_enabled(lsr, elt);
    3323           5 :         lsr_read_any_attribute(lsr, elt, 1);
    3324           5 :         lsr_read_command_list(lsr, NULL, (SVG_Element*)elt, 0);
    3325             : 
    3326           5 :         lsr->has_conditionnals = GF_TRUE;
    3327           5 :         gf_node_init(elt);
    3328           5 :         return elt;
    3329             : }
    3330           2 : static GF_Node *lsr_read_cursorManager(GF_LASeRCodec *lsr)
    3331             : {
    3332           2 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_LSR_cursorManager);
    3333           2 :         lsr_read_id(lsr, elt);
    3334           2 :         lsr_read_rare(lsr, elt);
    3335           2 :         lsr_read_coordinate_ptr(lsr, elt,TAG_SVG_ATT_x, 1, "x");
    3336           2 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_y, 1, "y");
    3337           2 :         lsr_read_href(lsr, elt);
    3338           2 :         lsr_read_any_attribute(lsr, elt, 1);
    3339           2 :         lsr_read_group_content(lsr, elt, 0);
    3340           2 :         return elt;
    3341             : }
    3342             : 
    3343           8 : static GF_Node *lsr_read_data(GF_LASeRCodec *lsr, u32 node_tag)
    3344             : {
    3345           8 :         GF_Node *elt = gf_node_new(lsr->sg, node_tag);
    3346           8 :         lsr_read_id(lsr, elt);
    3347           8 :         lsr_read_rare(lsr, elt);
    3348           8 :         lsr_read_any_attribute(lsr, elt, 1);
    3349           8 :         lsr_read_group_content(lsr, elt, 0);
    3350           8 :         return elt;
    3351             : }
    3352             : 
    3353           2 : static GF_Node *lsr_read_defs(GF_LASeRCodec *lsr)
    3354             : {
    3355           2 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_defs);
    3356           2 :         lsr_read_id(lsr, elt);
    3357           2 :         lsr_read_rare(lsr, elt);
    3358           2 :         lsr_read_fill(lsr, elt);
    3359           2 :         lsr_read_stroke(lsr, elt);
    3360           2 :         lsr_read_any_attribute(lsr, elt, 1);
    3361           2 :         lsr_read_group_content(lsr, elt, 0);
    3362           2 :         return elt;
    3363             : }
    3364           2 : static GF_Node *lsr_read_ellipse(GF_LASeRCodec *lsr)
    3365             : {
    3366           2 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_ellipse);
    3367           2 :         lsr_read_id(lsr, elt);
    3368           2 :         lsr_read_rare_full(lsr, elt);
    3369           2 :         lsr_read_fill(lsr, elt);
    3370           2 :         lsr_read_stroke(lsr, elt);
    3371           2 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_cx, 1, "cx");
    3372           2 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_cy, 1, "cy");
    3373           2 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_rx, 0, "rx");
    3374           2 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_ry, 0, "ry");
    3375           2 :         lsr_read_any_attribute(lsr, elt, 1);
    3376           2 :         lsr_read_group_content(lsr, elt, 0);
    3377           2 :         return elt;
    3378             : }
    3379           2 : static GF_Node *lsr_read_foreignObject(GF_LASeRCodec *lsr)
    3380             : {
    3381             :         u32 flag;
    3382           2 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_foreignObject);
    3383           2 :         lsr_read_id(lsr, elt);
    3384           2 :         lsr_read_rare_full(lsr, elt);
    3385           2 :         lsr_read_fill(lsr, elt);
    3386           2 :         lsr_read_stroke(lsr, elt);
    3387           2 :         lsr_read_eRR(lsr, elt);
    3388           2 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_height, 0, "height");
    3389           2 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_width, 0, "width");
    3390           2 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_x, 1, "x");
    3391           2 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_y, 1, "y");
    3392             : 
    3393           2 :         lsr_read_any_attribute(lsr, elt, 1);
    3394             :         /*      TODO
    3395             :                 bit(1) opt_group;
    3396             :                 if(opt_group) {
    3397             :                         vluimsbf5 occ1;
    3398             :                         for(int t=0;t<occ1;t++) {
    3399             :                                 privateElementContainer child0[[t]];
    3400             :                         }
    3401             :                 }
    3402             :         */
    3403           2 :         GF_LSR_READ_INT(lsr, flag, 1, "opt_group");
    3404           2 :         return elt;
    3405             : }
    3406             : 
    3407             : 
    3408          29 : static GF_Node *lsr_read_g(GF_LASeRCodec *lsr, Bool is_same)
    3409             : {
    3410          29 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_g);
    3411          29 :         if (is_same) {
    3412           0 :                 if (lsr->prev_g) {
    3413           0 :                         lsr_restore_base(lsr, (SVG_Element*) elt, lsr->prev_g, 0, 0);
    3414             :                 } else {
    3415           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] sameg coded in bitstream but no g defined !\n"));
    3416             :                 }
    3417           0 :                 lsr_read_id(lsr, elt);
    3418             :         } else {
    3419          29 :                 lsr_read_id(lsr, elt);
    3420          29 :                 lsr_read_rare_full(lsr, elt);
    3421          29 :                 lsr_read_fill(lsr, elt);
    3422          29 :                 lsr_read_stroke(lsr, elt);
    3423          29 :                 lsr_read_eRR(lsr, elt);
    3424          29 :                 lsr_read_any_attribute(lsr, elt, 1);
    3425          29 :                 lsr->prev_g = (SVG_Element*)elt;
    3426             :         }
    3427          29 :         lsr_read_group_content(lsr, elt, is_same);
    3428          29 :         return elt;
    3429             : }
    3430             : 
    3431          41 : static void lsr_read_opacity(GF_LASeRCodec *lsr, GF_Node *elt)
    3432             : {
    3433             :         u32 flag;
    3434             :         GF_FieldInfo info;
    3435          41 :         GF_LSR_READ_INT(lsr, flag, 1, "opacity");
    3436          41 :         if (flag) {
    3437           0 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_opacity, 1, 0, &info);
    3438           0 :                 ((SVG_Number*)info.far_ptr)->type = SVG_NUMBER_VALUE;
    3439           0 :                 ((SVG_Number*)info.far_ptr)->value = lsr_read_fixed_clamp(lsr, "opacity");
    3440             :         }
    3441             : 
    3442          41 : }
    3443          41 : static GF_Node *lsr_read_image(GF_LASeRCodec *lsr)
    3444             : {
    3445          41 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_image);
    3446          41 :         lsr_read_id(lsr, elt);
    3447          41 :         lsr_read_rare_full(lsr, elt);
    3448          41 :         lsr_read_eRR(lsr, elt);
    3449          41 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_height, 1, "height");
    3450          41 :         lsr_read_opacity(lsr, elt);
    3451             : 
    3452          41 :         lsr_read_preserve_aspect_ratio(lsr, elt);
    3453          41 :         lsr_read_content_type(lsr, elt);
    3454          41 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_width, 1, "width");
    3455          41 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_x, 1, "x");
    3456          41 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_y, 1, "y");
    3457          41 :         lsr_read_href(lsr, elt);
    3458          41 :         lsr_read_transform_behavior(lsr, elt);
    3459          41 :         lsr_read_any_attribute(lsr, elt, 1);
    3460          41 :         lsr_read_group_content(lsr, elt, 0);
    3461          41 :         return elt;
    3462             : }
    3463           5 : static GF_Node *lsr_read_line(GF_LASeRCodec *lsr, Bool is_same)
    3464             : {
    3465           5 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_line);
    3466             : 
    3467           5 :         if (is_same) {
    3468           0 :                 if (lsr->prev_line) {
    3469           0 :                         lsr_restore_base(lsr, (SVG_Element*) elt, (SVG_Element *)lsr->prev_line, 0, 0);
    3470             :                 } else {
    3471           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] sameline coded in bitstream but no line defined !\n"));
    3472             :                 }
    3473           0 :                 lsr_read_id(lsr, elt);
    3474             :         } else {
    3475           5 :                 lsr_read_id(lsr, elt);
    3476           5 :                 lsr_read_rare_full(lsr, elt);
    3477           5 :                 lsr_read_fill(lsr, elt);
    3478           5 :                 lsr_read_stroke(lsr, elt);
    3479             :         }
    3480           5 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_x1, 1, "x1");
    3481           5 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_x2, 0, "x2");
    3482           5 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_y1, 1, "y1");
    3483           5 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_y2, 0, "y2");
    3484           5 :         if (!is_same) {
    3485           5 :                 lsr_read_any_attribute(lsr, elt, 1);
    3486           5 :                 lsr->prev_line = (SVG_Element*)elt;
    3487             :         }
    3488           5 :         lsr_read_group_content(lsr, elt, is_same);
    3489           5 :         return elt;
    3490             : }
    3491             : 
    3492          10 : static void lsr_read_gradient_units(GF_LASeRCodec *lsr, GF_Node *elt)
    3493             : {
    3494             :         u32 flag;
    3495             :         GF_FieldInfo info;
    3496          10 :         GF_LSR_READ_INT(lsr, flag, 1, "hasGradientUnits");
    3497          10 :         if (flag) {
    3498           3 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_gradientUnits, 1, 0, &info);
    3499           3 :                 GF_LSR_READ_INT(lsr, *(SVG_GradientUnit*)info.far_ptr, 1, "gradientUnits");
    3500             :         }
    3501          10 : }
    3502           8 : static GF_Node *lsr_read_linearGradient(GF_LASeRCodec *lsr)
    3503             : {
    3504           8 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_linearGradient);
    3505           8 :         lsr_read_id(lsr, elt);
    3506           8 :         lsr_read_rare(lsr, elt);
    3507           8 :         lsr_read_fill(lsr, elt);
    3508           8 :         lsr_read_stroke(lsr, elt);
    3509           8 :         lsr_read_gradient_units(lsr, elt);
    3510           8 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_x1, 1, "x1");
    3511           8 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_x2, 1, "x2");
    3512           8 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_y1, 1, "y1");
    3513           8 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_y2, 1, "y2");
    3514           8 :         lsr_read_any_attribute(lsr, elt, 1);
    3515           8 :         lsr_read_group_content(lsr, elt, 0);
    3516           8 :         return elt;
    3517             : }
    3518           5 : static GF_Node *lsr_read_mpath(GF_LASeRCodec *lsr)
    3519             : {
    3520           5 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_mpath);
    3521           5 :         lsr_read_id(lsr, elt);
    3522           5 :         lsr_read_rare(lsr, elt);
    3523           5 :         lsr_read_href(lsr, elt);
    3524           5 :         lsr_read_any_attribute(lsr, elt, 1);
    3525           5 :         lsr_read_group_content(lsr, elt, 0);
    3526           5 :         return elt;
    3527             : }
    3528          23 : static GF_Node *lsr_read_path(GF_LASeRCodec *lsr, u32 same_type)
    3529             : {
    3530             :         u32 flag;
    3531          23 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_path);
    3532             : 
    3533          23 :         if (same_type) {
    3534           6 :                 if (lsr->prev_path) {
    3535           6 :                         lsr_restore_base(lsr, (SVG_Element*)elt, (SVG_Element *)lsr->prev_path, (same_type==2) ? 1 : 0, 0);
    3536             :                 } else {
    3537           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] samepath coded in bitstream but no path defined !\n"));
    3538             :                 }
    3539           6 :                 lsr_read_id(lsr, elt);
    3540           6 :                 if (same_type==2) lsr_read_fill(lsr, elt);
    3541           6 :                 lsr_read_path_type(lsr, elt, TAG_SVG_ATT_d, NULL, "d");
    3542             :         } else {
    3543          17 :                 lsr_read_id(lsr, elt);
    3544          17 :                 lsr_read_rare_full(lsr, elt);
    3545          17 :                 lsr_read_fill(lsr, elt);
    3546          17 :                 lsr_read_stroke(lsr, elt);
    3547          17 :                 lsr_read_path_type(lsr, elt, TAG_SVG_ATT_d, NULL, "d");
    3548          17 :                 GF_LSR_READ_INT(lsr, flag, 1, "hasPathLength");
    3549          17 :                 if (flag) {
    3550             :                         GF_FieldInfo info;
    3551           0 :                         lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_pathLength, 1, 0, &info);
    3552           0 :                         ((SVG_Number*)info.far_ptr)->value = lsr_read_fixed_16_8(lsr, "pathLength");
    3553             :                 }
    3554          17 :                 lsr_read_any_attribute(lsr, elt, 1);
    3555          17 :                 lsr->prev_path = (SVG_Element*)elt;
    3556             :         }
    3557          23 :         lsr_read_group_content(lsr, elt, same_type);
    3558          23 :         return elt;
    3559             : }
    3560          31 : static GF_Node *lsr_read_polygon(GF_LASeRCodec *lsr, Bool is_polyline, u32 same_type)
    3561             : {
    3562             :         GF_FieldInfo info;
    3563          31 :         GF_Node *elt = gf_node_new(lsr->sg, is_polyline ? TAG_SVG_polyline : TAG_SVG_polygon);
    3564             : 
    3565          31 :         lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_points, 1, 0, &info);
    3566             : 
    3567          31 :         if (same_type) {
    3568           9 :                 if (lsr->prev_polygon) {
    3569           9 :                         lsr_restore_base(lsr, (SVG_Element*)elt, (SVG_Element *)lsr->prev_polygon, /*(same_type==2) ? 1 : */ 0, /*(same_type==3) ? 1 : */ 0);
    3570             :                 } else {
    3571           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] samepolyXXX coded in bitstream but no polyXXX defined !\n"));
    3572             :                 }
    3573           9 :                 lsr_read_id(lsr, elt);
    3574           9 :                 if (same_type==2) lsr_read_fill(lsr, elt);
    3575           3 :                 else if (same_type==3) lsr_read_stroke(lsr, elt);
    3576           9 :                 lsr_read_point_sequence(lsr, *(GF_List**)info.far_ptr, "points");
    3577             :         } else {
    3578          22 :                 lsr_read_id(lsr, elt);
    3579          22 :                 lsr_read_rare_full(lsr, elt);
    3580          22 :                 lsr_read_fill(lsr, elt);
    3581          22 :                 lsr_read_stroke(lsr, elt);
    3582          22 :                 lsr_read_point_sequence(lsr, *(GF_List**)info.far_ptr, "points");
    3583          22 :                 lsr_read_any_attribute(lsr, elt, 1);
    3584          22 :                 lsr->prev_polygon = (SVG_Element*)elt;
    3585             :         }
    3586          31 :         lsr_read_group_content(lsr, elt, same_type);
    3587          31 :         return elt;
    3588             : }
    3589           2 : static GF_Node *lsr_read_radialGradient(GF_LASeRCodec *lsr)
    3590             : {
    3591           2 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_radialGradient);
    3592           2 :         lsr_read_id(lsr, elt);
    3593           2 :         lsr_read_rare(lsr, elt);
    3594           2 :         lsr_read_fill(lsr, elt);
    3595           2 :         lsr_read_stroke(lsr, elt);
    3596           2 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_cx, 1, "cx");
    3597           2 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_cy, 1, "cy");
    3598           2 :         lsr_read_gradient_units(lsr, elt);
    3599           2 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_r, 1, "r");
    3600           2 :         lsr_read_any_attribute(lsr, elt, 1);
    3601           2 :         lsr_read_group_content(lsr, elt, 0);
    3602           2 :         return elt;
    3603             : }
    3604          77 : static GF_Node *lsr_read_rect(GF_LASeRCodec *lsr, u32 same_type)
    3605             : {
    3606          77 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_rect);
    3607             : 
    3608          77 :         if (same_type) {
    3609          36 :                 if (lsr->prev_rect) {
    3610          36 :                         lsr_restore_base(lsr, (SVG_Element*)elt, (SVG_Element *)lsr->prev_rect, (same_type==2) ? 1 : 0, 0);
    3611             :                 } else {
    3612           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] samerect coded in bitstream but no rect defined !\n"));
    3613             :                 }
    3614          36 :                 lsr_read_id(lsr, elt);
    3615          36 :                 if (same_type==2) lsr_read_fill(lsr, elt);
    3616          36 :                 lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_height, 0, "height");
    3617          36 :                 lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_width, 0, "width");
    3618          36 :                 lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_x, 1, "x");
    3619          36 :                 lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_y, 1, "y");
    3620             :         } else {
    3621          41 :                 lsr_read_id(lsr, elt);
    3622          41 :                 lsr_read_rare_full(lsr, elt);
    3623          41 :                 lsr_read_fill(lsr, elt);
    3624          41 :                 lsr_read_stroke(lsr, elt);
    3625          41 :                 lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_height, 0, "height");
    3626          41 :                 lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_rx, 1, "rx");
    3627          41 :                 lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_ry, 1, "ry");
    3628          41 :                 lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_width, 0, "width");
    3629          41 :                 lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_x, 1, "x");
    3630          41 :                 lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_y, 1, "y");
    3631          41 :                 lsr_read_any_attribute(lsr, elt, 1);
    3632          41 :                 lsr->prev_rect = (SVG_Element*)elt;
    3633             :         }
    3634          77 :         lsr_read_group_content(lsr, elt, same_type);
    3635          77 :         return elt;
    3636             : }
    3637             : 
    3638           5 : static GF_Node *lsr_read_rectClip(GF_LASeRCodec *lsr)
    3639             : {
    3640             :         u32 flag;
    3641           5 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_LSR_rectClip);
    3642           5 :         lsr_read_id(lsr, elt);
    3643           5 :         lsr_read_rare_full(lsr, elt);
    3644           5 :         lsr_read_fill(lsr, elt);
    3645           5 :         lsr_read_stroke(lsr, elt);
    3646           5 :         lsr_read_eRR(lsr, elt);
    3647           5 :         GF_LSR_READ_INT(lsr, flag, 1, "has_size");
    3648           5 :         if (flag) {
    3649             :                 SVG_Number num;
    3650             :                 GF_FieldInfo info;
    3651           3 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_size, 1, 0, &info);
    3652           3 :                 lsr_read_coordinate(lsr, & num, 0, "width");
    3653           3 :                 ((LASeR_Size*)info.far_ptr)->width = num.value;
    3654           3 :                 lsr_read_coordinate(lsr, & num, 0, "height");
    3655           3 :                 ((LASeR_Size*)info.far_ptr)->height = num.value;
    3656             :         }
    3657           5 :         lsr_read_any_attribute(lsr, elt, 1);
    3658           5 :         lsr_read_group_content(lsr, elt, 0);
    3659           5 :         return elt;
    3660             : }
    3661             : 
    3662           5 : static GF_Node *lsr_read_script(GF_LASeRCodec *lsr)
    3663             : {
    3664           5 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_script);
    3665           5 :         lsr_read_id(lsr, elt);
    3666           5 :         lsr_read_rare(lsr, elt);
    3667           5 :         lsr_read_eRR(lsr, elt);
    3668           5 :         lsr_read_script_type(lsr, elt);
    3669           5 :         lsr_read_href(lsr, elt);
    3670           5 :         lsr_read_any_attribute(lsr, elt, 1);
    3671           5 :         lsr_read_group_content(lsr, elt, 0);
    3672           5 :         return elt;
    3673             : }
    3674             : 
    3675          11 : static GF_Node *lsr_read_selector(GF_LASeRCodec *lsr)
    3676             : {
    3677             :         u32 flag;
    3678          11 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_LSR_selector);
    3679          11 :         lsr_read_id(lsr, elt);
    3680          11 :         lsr_read_rare_full(lsr, elt);
    3681          11 :         lsr_read_fill(lsr, elt);
    3682          11 :         lsr_read_stroke(lsr, elt);
    3683          11 :         lsr_read_eRR(lsr, elt);
    3684          11 :         GF_LSR_READ_INT(lsr, flag, 1, "hasChoice");
    3685          11 :         if (flag) {
    3686             :                 GF_FieldInfo info;
    3687           9 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_choice, 1, 0, &info);
    3688           9 :                 GF_LSR_READ_INT(lsr, flag, 1, "choice");
    3689           9 :                 if (flag) {
    3690           6 :                         GF_LSR_READ_INT(lsr, ((LASeR_Choice*)info.far_ptr)->type, 1, "type");
    3691             :                 } else {
    3692           3 :                         GF_LSR_READ_INT(lsr, ((LASeR_Choice*)info.far_ptr)->choice_index, 8, "value");
    3693           3 :                         ((LASeR_Choice*)info.far_ptr)->type = LASeR_CHOICE_N;
    3694             :                 }
    3695             :         }
    3696          11 :         lsr_read_any_attribute(lsr, elt, 1);
    3697          11 :         lsr_read_group_content(lsr, elt, 0);
    3698          11 :         return elt;
    3699             : }
    3700             : 
    3701           2 : static GF_Node *lsr_read_set(GF_LASeRCodec *lsr, SVG_Element *parent)
    3702             : {
    3703           2 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_set);
    3704           2 :         lsr_read_id(lsr, elt);
    3705           2 :         lsr_read_rare(lsr, elt);
    3706             :         lsr_read_attribute_name(lsr, elt);
    3707           2 :         lsr_read_attribute_type(lsr, elt);
    3708             : 
    3709           2 :         lsr_read_smil_times(lsr, elt, TAG_SVG_ATT_begin, NULL, "begin", 1);
    3710             :         lsr_read_duration(lsr, elt);
    3711           2 :         lsr_read_anim_fill(lsr, elt);
    3712           2 :         lsr_read_anim_repeatCount(lsr, elt);
    3713           2 :         lsr_read_repeat_duration(lsr, elt);
    3714           2 :         lsr_read_anim_restart(lsr, elt);
    3715           2 :         lsr_read_anim_value(lsr, elt, TAG_SVG_ATT_to, "to");
    3716           2 :         lsr_read_href(lsr, elt);
    3717           2 :         lsr_read_lsr_enabled(lsr, elt);
    3718           2 :         lsr_read_any_attribute(lsr, elt, 1);
    3719             : 
    3720           2 :         if (!lsr_setup_smil_anim(lsr, (SVG_Element*)elt, parent)) {
    3721           0 :                 gf_list_add(lsr->deferred_anims, elt);
    3722           0 :                 lsr_read_group_content_post_init(lsr, (SVG_Element*)elt, 1);
    3723             :         } else {
    3724           2 :                 lsr_read_group_content(lsr, elt, 0);
    3725             :         }
    3726           2 :         return elt;
    3727             : }
    3728             : 
    3729           5 : static GF_Node *lsr_read_simpleLayout(GF_LASeRCodec *lsr)
    3730             : {
    3731             :         u32 flag;
    3732           5 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_LSR_simpleLayout);
    3733           5 :         lsr_read_id(lsr, elt);
    3734           5 :         lsr_read_rare_full(lsr, elt);
    3735           5 :         lsr_read_fill(lsr, elt);
    3736           5 :         lsr_read_stroke(lsr, elt);
    3737           5 :         GF_LSR_READ_INT(lsr, flag, 1, "has_delta");
    3738           5 :         if (flag) {
    3739             :                 SVG_Number num;
    3740             :                 GF_FieldInfo info;
    3741           2 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_delta, 1, 0, &info);
    3742           2 :                 lsr_read_coordinate(lsr, & num, 0, "width");
    3743           2 :                 ((LASeR_Size*)info.far_ptr)->width = num.value;
    3744           2 :                 lsr_read_coordinate(lsr, & num, 0, "height");
    3745           2 :                 ((LASeR_Size*)info.far_ptr)->height = num.value;
    3746             :         }
    3747           5 :         lsr_read_eRR(lsr, elt);
    3748           5 :         lsr_read_any_attribute(lsr, elt, 1);
    3749           5 :         lsr_read_group_content(lsr, elt, 0);
    3750           5 :         return elt;
    3751             : }
    3752             : 
    3753          20 : static GF_Node *lsr_read_stop(GF_LASeRCodec *lsr)
    3754             : {
    3755             :         GF_FieldInfo info;
    3756          20 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_stop);
    3757          20 :         lsr_read_id(lsr, elt);
    3758          20 :         lsr_read_rare(lsr, elt);
    3759          20 :         lsr_read_fill(lsr, elt);
    3760          20 :         lsr_read_stroke(lsr, elt);
    3761             : 
    3762          20 :         lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_offset, 1, 0, &info);
    3763          20 :         ((SVG_Number*)info.far_ptr)->value = lsr_read_fixed_16_8(lsr, "offset");
    3764          20 :         lsr_read_any_attribute(lsr, elt, 1);
    3765          20 :         lsr_read_group_content(lsr, elt, 0);
    3766          20 :         return elt;
    3767             : }
    3768           5 : static GF_Node *lsr_read_svg(GF_LASeRCodec *lsr, Bool init_node)
    3769             : {
    3770             :         GF_FieldInfo info;
    3771             :         SMIL_Duration snap;
    3772             :         u32 flag;
    3773           5 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_svg);
    3774           5 :         lsr_read_id(lsr, elt);
    3775           5 :         lsr_read_rare(lsr, elt);
    3776           5 :         lsr_read_fill(lsr, elt);
    3777           5 :         lsr_read_stroke(lsr, elt);
    3778           5 :         lsr_read_string_attribute(lsr, elt, TAG_SVG_ATT_baseProfile, "baseProfile");
    3779           5 :         lsr_read_string_attribute(lsr, elt, TAG_SVG_ATT_contentScriptType, "contentScriptType");
    3780           5 :         lsr_read_eRR(lsr, elt);
    3781           5 :         lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_height, 1, 0, &info);
    3782           5 :         lsr_read_value_with_units(lsr, info.far_ptr, "height");
    3783           5 :         GF_LSR_READ_INT(lsr, flag, 1, "hasPlaybackOrder");
    3784           5 :         if (flag) {
    3785           0 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_playbackOrder, 1, 1, &info);
    3786           0 :                 GF_LSR_READ_INT(lsr, flag, 1, "playbackOrder");
    3787           0 :                 if (flag) *(SVG_PlaybackOrder*)info.far_ptr = SVG_PLAYBACKORDER_FORWARDONLY;
    3788             :         }
    3789             : 
    3790           5 :         lsr_read_preserve_aspect_ratio(lsr, elt);
    3791             : 
    3792             : 
    3793           5 :         GF_LSR_READ_INT(lsr, flag, 1, "has_snapshotTime");
    3794           5 :         if (flag) {
    3795           0 :                 lsr_read_duration_ex(lsr, NULL, 0, &snap, "snapshotTime", 0);
    3796           0 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_snapshotTime, 1, 1, &info);
    3797           0 :                 if (snap.type==SMIL_DURATION_DEFINED) *((SVG_Clock *)info.far_ptr) = snap.clock_value;
    3798             :         }
    3799             : 
    3800           5 :         GF_LSR_READ_INT(lsr, flag, 1, "hasSyncBehavior");
    3801           5 :         if (flag) {
    3802           0 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_syncBehaviorDefault, 1, 0, &info);
    3803           0 :                 GF_LSR_READ_INT(lsr, flag, 2, "syncBehaviorDefault");
    3804           0 :                 switch (flag) {
    3805           0 :                 case 0:
    3806           0 :                         *((SMIL_SyncBehavior*)info.far_ptr) = SMIL_SYNCBEHAVIOR_CANSLIP;
    3807           0 :                         break;
    3808           0 :                 case 1:
    3809           0 :                         *((SMIL_SyncBehavior*)info.far_ptr) = SMIL_SYNCBEHAVIOR_INDEPENDENT;
    3810           0 :                         break;
    3811           0 :                 case 3:
    3812           0 :                         *((SMIL_SyncBehavior*)info.far_ptr) = SMIL_SYNCBEHAVIOR_LOCKED;
    3813           0 :                         break;
    3814           0 :                 default:
    3815           0 :                         *((SMIL_SyncBehavior*)info.far_ptr) = SMIL_SYNCBEHAVIOR_INHERIT;
    3816           0 :                         break;
    3817             :                 }
    3818           5 :         }
    3819           5 :         GF_LSR_READ_INT(lsr, flag, 1, "hasSyncToleranceDefault");
    3820           5 :         if (flag) {
    3821           0 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_syncToleranceDefault, 1, 0, &info);
    3822           0 :                 ((SMIL_SyncTolerance*)info.far_ptr)->type = SMIL_SYNCTOLERANCE_VALUE;
    3823           0 :                 GF_LSR_READ_INT(lsr, flag, 1, "choice");
    3824           0 :                 ((SMIL_SyncTolerance*)info.far_ptr)->value = lsr_read_vluimsbf5(lsr, "value");
    3825           0 :                 ((SMIL_SyncTolerance*)info.far_ptr)->value /= lsr->time_resolution;
    3826             :         }
    3827           5 :         GF_LSR_READ_INT(lsr, flag, 1, "hasTimelineBegin");
    3828           5 :         if (flag) {
    3829           0 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_timelineBegin, 1, 0, &info);
    3830           0 :                 GF_LSR_READ_INT(lsr, flag, 1, "timelineBegin");
    3831           0 :                 if (flag) *(SVG_TimelineBegin*)info.far_ptr = SVG_TIMELINEBEGIN_ONLOAD;
    3832             :         }
    3833           5 :         lsr_read_string_attribute(lsr, elt, TAG_SVG_ATT_version, "version");
    3834             : 
    3835           5 :         GF_LSR_READ_INT(lsr, flag, 1, "hasViewBox");
    3836           5 :         if (flag) {
    3837           3 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_viewBox, 1, 0, &info);
    3838           3 :                 ((SVG_ViewBox*)info.far_ptr)->x = lsr_read_fixed_16_8(lsr, "viewbox.x");
    3839           3 :                 ((SVG_ViewBox*)info.far_ptr)->y = lsr_read_fixed_16_8(lsr, "viewbox.y");
    3840           3 :                 ((SVG_ViewBox*)info.far_ptr)->width = lsr_read_fixed_16_8(lsr, "viewbox.width");
    3841           3 :                 ((SVG_ViewBox*)info.far_ptr)->height = lsr_read_fixed_16_8(lsr, "viewbox.height");
    3842           3 :                 ((SVG_ViewBox*)info.far_ptr)->is_set = 1;
    3843             :         }
    3844             : 
    3845           5 :         lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_width, 1, 0, &info);
    3846           5 :         lsr_read_value_with_units(lsr, info.far_ptr, "width");
    3847             : 
    3848           5 :         GF_LSR_READ_INT(lsr, flag, 1, "hasZoomAndPan");
    3849           5 :         if (flag) {
    3850           3 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_zoomAndPan, 1, 0, &info);
    3851           3 :                 GF_LSR_READ_INT(lsr, flag, 1, "zoomAndPan");
    3852           3 :                 *((SVG_ZoomAndPan*)info.far_ptr) = flag ? SVG_ZOOMANDPAN_MAGNIFY : SVG_ZOOMANDPAN_DISABLE;
    3853             :         }
    3854           5 :         lsr_read_any_attribute(lsr, elt, 1);
    3855             :         /*store current root for listeners with no focus target*/
    3856           5 :         lsr->current_root = elt;
    3857             : 
    3858           5 :         if (init_node) {
    3859           1 :                 gf_node_register(elt, NULL);
    3860           1 :                 gf_sg_set_root_node(lsr->sg, elt);
    3861             :         }
    3862             : 
    3863           5 :         lsr_read_group_content(lsr, elt, 0);
    3864           5 :         return elt;
    3865             : }
    3866             : 
    3867           2 : static GF_Node *lsr_read_switch(GF_LASeRCodec *lsr)
    3868             : {
    3869           2 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_switch);
    3870           2 :         lsr_read_id(lsr, elt);
    3871           2 :         lsr_read_rare_full(lsr, elt);
    3872           2 :         lsr_read_fill(lsr, elt);
    3873           2 :         lsr_read_stroke(lsr, elt);
    3874           2 :         lsr_read_eRR(lsr, elt);
    3875           2 :         lsr_read_any_attribute(lsr, elt, 1);
    3876           2 :         lsr_read_group_content(lsr, elt, 0);
    3877           2 :         return elt;
    3878             : }
    3879             : 
    3880             : 
    3881          17 : static GF_Node *lsr_read_text(GF_LASeRCodec *lsr, u32 same_type)
    3882             : {
    3883             :         u32 flag;
    3884             :         GF_FieldInfo info;
    3885          17 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_text);
    3886          17 :         if (same_type) {
    3887           0 :                 if (lsr->prev_text) {
    3888           0 :                         lsr_restore_base(lsr, (SVG_Element *)elt, (SVG_Element *)lsr->prev_text, (same_type==2) ? 1 : 0, 0);
    3889             :                 } else {
    3890           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] sametext coded in bitstream but no text defined !\n"));
    3891             :                 }
    3892           0 :                 lsr_read_id(lsr, elt);
    3893           0 :                 if (same_type==2) lsr_read_fill(lsr, elt);
    3894           0 :                 lsr_read_coord_list(lsr, elt, TAG_SVG_ATT_text_x, "x");
    3895           0 :                 lsr_read_coord_list(lsr, elt, TAG_SVG_ATT_text_y, "y");
    3896             :         } else {
    3897          17 :                 lsr_read_id(lsr, elt);
    3898          17 :                 lsr_read_rare_full(lsr, elt);
    3899          17 :                 lsr_read_fill(lsr, elt);
    3900          17 :                 lsr_read_stroke(lsr, elt);
    3901             : 
    3902          17 :                 GF_LSR_READ_INT(lsr, flag, 1, "editable");
    3903          17 :                 if (flag) {
    3904           0 :                         lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_editable, 1, 0, &info);
    3905           0 :                         *(SVG_Boolean*)info.far_ptr = flag;
    3906             :                 }
    3907          17 :                 lsr_read_float_list(lsr, elt, TAG_SVG_ATT_text_rotate, NULL, "rotate");
    3908          17 :                 lsr_read_coord_list(lsr, elt, TAG_SVG_ATT_text_x, "x");
    3909          17 :                 lsr_read_coord_list(lsr, elt, TAG_SVG_ATT_text_y, "y");
    3910          17 :                 lsr_read_any_attribute(lsr, elt, 1);
    3911          17 :                 lsr->prev_text = (SVG_Element*)elt;
    3912             :         }
    3913          17 :         lsr_read_group_content(lsr, elt, same_type);
    3914          17 :         return elt;
    3915             : }
    3916             : 
    3917           2 : static GF_Node *lsr_read_tspan(GF_LASeRCodec *lsr)
    3918             : {
    3919           2 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_tspan);
    3920           2 :         lsr_read_id(lsr, elt);
    3921           2 :         lsr_read_rare(lsr, elt);
    3922           2 :         lsr_read_fill(lsr, elt);
    3923           2 :         lsr_read_stroke(lsr, elt);
    3924           2 :         lsr_read_any_attribute(lsr, elt, 1);
    3925           2 :         lsr_read_group_content(lsr, elt, 0);
    3926           2 :         return elt;
    3927             : }
    3928             : 
    3929          11 : static GF_Node *lsr_read_use(GF_LASeRCodec *lsr, Bool is_same)
    3930             : {
    3931             :         GF_FieldInfo info;
    3932             :         u32 flag;
    3933          11 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_use);
    3934          11 :         if (is_same) {
    3935           3 :                 if (lsr->prev_use) {
    3936           3 :                         lsr_restore_base(lsr, (SVG_Element *)elt, lsr->prev_use, 0, 0);
    3937             :                 } else {
    3938           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] sameuse coded in bitstream but no use defined !\n"));
    3939             :                 }
    3940           3 :                 lsr_read_id(lsr, elt);
    3941           3 :                 lsr_read_href(lsr, elt);
    3942             :         } else {
    3943           8 :                 lsr_read_id(lsr, elt);
    3944           8 :                 lsr_read_rare_full(lsr, elt);
    3945           8 :                 lsr_read_fill(lsr, elt);
    3946           8 :                 lsr_read_stroke(lsr, elt);
    3947           8 :                 lsr_read_eRR(lsr, elt);
    3948             : 
    3949           8 :                 GF_LSR_READ_INT(lsr, flag, 1, "hasOverflow");
    3950           8 :                 if (flag) {
    3951           0 :                         lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_overflow, 1, 0, &info);
    3952           0 :                         GF_LSR_READ_INT(lsr, *(SVG_Overflow*)info.far_ptr, 2, "overflow");
    3953             :                 }
    3954           8 :                 lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_x, 1, "x");
    3955           8 :                 lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_y, 1, "y");
    3956           8 :                 lsr_read_href(lsr, elt);
    3957           8 :                 lsr_read_any_attribute(lsr, elt, 1);
    3958           8 :                 lsr->prev_use = (SVG_Element*)elt;
    3959             :         }
    3960          11 :         lsr_read_group_content(lsr, elt, is_same);
    3961          11 :         return elt;
    3962             : }
    3963             : 
    3964           5 : static GF_Node *lsr_read_video(GF_LASeRCodec *lsr, SVG_Element *parent)
    3965             : {
    3966             :         GF_FieldInfo info;
    3967             :         u32 flag;
    3968           5 :         GF_Node*elt = gf_node_new(lsr->sg, TAG_SVG_video);
    3969           5 :         lsr_read_id(lsr, elt);
    3970           5 :         lsr_read_rare_full(lsr, elt);
    3971           5 :         lsr_read_smil_times(lsr, elt, TAG_SVG_ATT_begin, NULL, "begin", 1);
    3972             :         lsr_read_duration(lsr, elt);
    3973           5 :         lsr_read_eRR(lsr, elt);
    3974           5 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_height, 1, "height");
    3975           5 :         GF_LSR_READ_INT(lsr, flag, 1, "hasOverlay");
    3976           5 :         if (flag) {
    3977           0 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_overlay, 1, 1, &info);
    3978           0 :                 GF_LSR_READ_INT(lsr, flag, 1, "choice");
    3979           0 :                 if (flag) {
    3980           0 :                         GF_LSR_READ_INT(lsr, *(SVG_Overlay*)info.far_ptr, 1, "choice");
    3981             :                 } else {
    3982           0 :                         char *str = NULL;
    3983           0 :                         lsr_read_byte_align_string(lsr, & str, "overlayExt");
    3984           0 :                         if (str) gf_free(str);
    3985             :                 }
    3986             :         }
    3987           5 :         lsr_read_preserve_aspect_ratio(lsr, elt);
    3988           5 :         lsr_read_anim_repeatCount(lsr, elt);
    3989           5 :         lsr_read_repeat_duration(lsr, elt);
    3990           5 :         lsr_read_anim_restart(lsr, elt);
    3991           5 :         lsr_read_sync_behavior(lsr, elt);
    3992           5 :         lsr_read_sync_tolerance(lsr, elt);
    3993           5 :         lsr_read_transform_behavior(lsr, elt);
    3994           5 :         lsr_read_content_type(lsr, elt);
    3995           5 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_width, 1, "width");
    3996           5 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_x, 1, "x");
    3997           5 :         lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_y, 1, "y");
    3998           5 :         lsr_read_href(lsr, elt);
    3999             : 
    4000           5 :         lsr_read_clip_time(lsr, elt, TAG_SVG_ATT_clipBegin, "clipBegin");
    4001           5 :         lsr_read_clip_time(lsr, elt, TAG_SVG_ATT_clipEnd, "clipEnd");
    4002             : 
    4003           5 :         GF_LSR_READ_INT(lsr, flag, 1, "hasFullscreen");
    4004           5 :         if (flag) {
    4005           3 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_SVG_ATT_fullscreen, 1, 0, &info);
    4006           3 :                 GF_LSR_READ_INT(lsr, *(SVG_Boolean *)info.far_ptr, 1, "fullscreen");
    4007             :         }
    4008             : 
    4009           5 :         lsr_read_sync_reference(lsr, elt);
    4010           5 :         lsr_read_any_attribute(lsr, elt, 1);
    4011           5 :         lsr_read_group_content(lsr, elt, 0);
    4012           5 :         return elt;
    4013             : }
    4014             : 
    4015           5 : static GF_Node *lsr_read_listener(GF_LASeRCodec *lsr, SVG_Element *parent)
    4016             : {
    4017             :         u32 flag;
    4018             :         GF_FieldInfo info;
    4019             :         XMLEV_Event *ev = NULL;
    4020             :         XMLRI *observer, *target, *handler;
    4021           5 :         GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_listener);
    4022             : 
    4023             :         observer = target = handler = NULL;
    4024             : 
    4025           5 :         lsr_read_id(lsr, elt);
    4026           5 :         lsr_read_rare(lsr, elt);
    4027           5 :         GF_LSR_READ_INT(lsr, flag, 1, "hasDefaultAction");
    4028           5 :         if (flag) {
    4029           3 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_XMLEV_ATT_defaultAction, 1, 0, &info);
    4030           3 :                 GF_LSR_READ_INT(lsr, *(XMLEV_DefaultAction*)info.far_ptr, 1, "defaultAction");
    4031             :         }
    4032           5 :         GF_LSR_READ_INT(lsr, flag, 1, "hasEvent");
    4033           5 :         if (flag) {
    4034           3 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_XMLEV_ATT_event, 1, 0, &info);
    4035           3 :                 lsr_read_event_type(lsr, info.far_ptr);
    4036           3 :                 ev = info.far_ptr;
    4037             :         }
    4038             :         /*create default handler but UNINITIALIZED*/
    4039           5 :         lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_XMLEV_ATT_handler, 1, 0, &info);
    4040           5 :         handler = info.far_ptr;
    4041           5 :         GF_LSR_READ_INT(lsr, flag, 1, "hasHandler");
    4042           5 :         if (flag) {
    4043           3 :                 lsr_read_any_uri(lsr, info.far_ptr, "handler");
    4044             :         }
    4045           5 :         GF_LSR_READ_INT(lsr, flag, 1, "hasObserver");
    4046             :         /*TODO double check spec here*/
    4047           5 :         if (flag) {
    4048           0 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_XMLEV_ATT_observer, 1, 0, &info);
    4049           0 :                 lsr_read_codec_IDREF(lsr, info.far_ptr, "observer");
    4050           0 :                 observer = info.far_ptr;
    4051             :         }
    4052             : 
    4053           5 :         GF_LSR_READ_INT(lsr, flag, 1, "hasPhase");
    4054           5 :         if (flag) {
    4055           3 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_XMLEV_ATT_phase, 1, 0, &info);
    4056           3 :                 GF_LSR_READ_INT(lsr, *(XMLEV_Phase*)info.far_ptr, 1, "phase");
    4057             :         }
    4058           5 :         GF_LSR_READ_INT(lsr, flag, 1, "hasPropagate");
    4059           5 :         if (flag) {
    4060           3 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_XMLEV_ATT_propagate, 1, 0, &info);
    4061           3 :                 GF_LSR_READ_INT(lsr, *(XMLEV_Propagate*)info.far_ptr, 1, "propagate");
    4062             :         }
    4063           5 :         GF_LSR_READ_INT(lsr, flag, 1, "hasTarget");
    4064           5 :         if (flag) {
    4065           0 :                 lsr->last_error = gf_node_get_attribute_by_tag(elt, TAG_XMLEV_ATT_target, 1, 0, &info);
    4066           0 :                 lsr_read_codec_IDREF(lsr, info.far_ptr, "target");
    4067           0 :                 target = info.far_ptr;
    4068             :         }
    4069             : 
    4070           5 :         lsr_read_lsr_enabled(lsr, elt);
    4071           5 :         lsr_read_any_attribute(lsr, elt, 1);
    4072           5 :         lsr_read_group_content(lsr, elt, 0);
    4073             : 
    4074             :         /*register listener element*/
    4075             :         {
    4076             :                 Bool post_pone = 0;
    4077             :                 SVG_Element *par = NULL;
    4078           5 :                 if (observer && observer->type == XMLRI_ELEMENTID) {
    4079           0 :                         if (observer->target) par = observer->target;
    4080             :                 }
    4081           5 :                 if (!par && target && (target->type == XMLRI_ELEMENTID)) {
    4082           0 :                         if (!target->target) post_pone = 1;
    4083             :                         else par = target->target;
    4084             :                 }
    4085           5 :                 if (!handler->target && !handler->string) {
    4086           2 :                         handler->type = XMLRI_ELEMENTID;
    4087           2 :                         handler->target = parent;
    4088             :                 }
    4089             :                 /*FIXME - double check with XML events*/
    4090           5 :                 if (!par && !observer) {
    4091             :                         /*all non-UI get attched to root*/
    4092           5 :                         if (ev && (ev->type>GF_EVENT_MOUSEWHEEL)) {
    4093           3 :                                 par = (SVG_Element*) lsr->current_root;
    4094             :                         }
    4095           2 :                         else if (parent) par = parent;
    4096           0 :                         else par = (SVG_Element*) lsr->current_root;
    4097             :                 }
    4098           5 :                 if (!par) post_pone = 1;
    4099             : 
    4100           5 :                 if (post_pone) {
    4101           0 :                         gf_list_add(lsr->deferred_listeners, elt);
    4102             :                 } else {
    4103             :                         if (!par) par = parent;
    4104           5 :                         gf_node_dom_listener_add((GF_Node *)par, elt);
    4105             :                 }
    4106             :         }
    4107           5 :         return elt;
    4108             : }
    4109             : 
    4110         444 : static GF_Node *lsr_read_scene_content_model(GF_LASeRCodec *lsr, SVG_Element *parent)
    4111             : {
    4112             :         GF_Node *n;
    4113             :         u32 ntype;
    4114         444 :         GF_LSR_READ_INT(lsr, ntype, 6, "ch4");
    4115             :         n = NULL;
    4116         444 :         switch (ntype) {
    4117          12 :         case LSR_SCENE_CONTENT_MODEL_a:
    4118          12 :                 n = lsr_read_a(lsr);
    4119          12 :                 break;
    4120          99 :         case LSR_SCENE_CONTENT_MODEL_animate:
    4121          99 :                 n = lsr_read_animate(lsr, parent, 0);
    4122          99 :                 break;
    4123           0 :         case LSR_SCENE_CONTENT_MODEL_animateColor:
    4124           0 :                 n = lsr_read_animate(lsr, parent, 1);
    4125           0 :                 break;
    4126           6 :         case LSR_SCENE_CONTENT_MODEL_animateMotion:
    4127           6 :                 n = lsr_read_animateMotion(lsr, parent);
    4128           6 :                 break;
    4129          12 :         case LSR_SCENE_CONTENT_MODEL_animateTransform:
    4130          12 :                 n = lsr_read_animateTransform(lsr, parent);
    4131          12 :                 break;
    4132           3 :         case LSR_SCENE_CONTENT_MODEL_audio:
    4133           3 :                 n = lsr_read_audio(lsr, parent);
    4134           3 :                 break;
    4135           9 :         case LSR_SCENE_CONTENT_MODEL_circle:
    4136           9 :                 n = lsr_read_circle(lsr);
    4137           9 :                 break;
    4138           3 :         case LSR_SCENE_CONTENT_MODEL_conditional:
    4139           3 :                 n = lsr_read_conditional(lsr);
    4140           3 :                 break;
    4141           0 :         case LSR_SCENE_CONTENT_MODEL_cursorManager:
    4142           0 :                 n = lsr_read_cursorManager(lsr);
    4143           0 :                 break;
    4144           0 :         case LSR_SCENE_CONTENT_MODEL_defs:
    4145           0 :                 n = lsr_read_defs(lsr);
    4146           0 :                 break;
    4147           0 :         case LSR_SCENE_CONTENT_MODEL_desc:
    4148           0 :                 n = lsr_read_data(lsr, TAG_SVG_desc);
    4149           0 :                 break;
    4150           0 :         case LSR_SCENE_CONTENT_MODEL_ellipse:
    4151           0 :                 n = lsr_read_ellipse(lsr);
    4152           0 :                 break;
    4153           0 :         case LSR_SCENE_CONTENT_MODEL_foreignObject:
    4154           0 :                 n = lsr_read_foreignObject(lsr);
    4155           0 :                 break;
    4156          27 :         case LSR_SCENE_CONTENT_MODEL_g:
    4157          27 :                 n = lsr_read_g(lsr, 0);
    4158          27 :                 break;
    4159          39 :         case LSR_SCENE_CONTENT_MODEL_image:
    4160          39 :                 n = lsr_read_image(lsr);
    4161          39 :                 break;
    4162           3 :         case LSR_SCENE_CONTENT_MODEL_line:
    4163           3 :                 n = lsr_read_line(lsr, 0);
    4164           3 :                 break;
    4165           6 :         case LSR_SCENE_CONTENT_MODEL_linearGradient:
    4166           6 :                 n = lsr_read_linearGradient(lsr);
    4167           6 :                 break;
    4168           0 :         case LSR_SCENE_CONTENT_MODEL_metadata:
    4169           0 :                 n = lsr_read_data(lsr, TAG_SVG_metadata);
    4170           0 :                 break;
    4171           3 :         case LSR_SCENE_CONTENT_MODEL_mpath:
    4172           3 :                 n = lsr_read_mpath(lsr);
    4173           3 :                 break;
    4174          15 :         case LSR_SCENE_CONTENT_MODEL_path:
    4175          15 :                 n = lsr_read_path(lsr, 0);
    4176          15 :                 break;
    4177           9 :         case LSR_SCENE_CONTENT_MODEL_polygon:
    4178           9 :                 n = lsr_read_polygon(lsr, 0, 0);
    4179           9 :                 break;
    4180           9 :         case LSR_SCENE_CONTENT_MODEL_polyline:
    4181           9 :                 n = lsr_read_polygon(lsr, 1, 0);
    4182           9 :                 break;
    4183           0 :         case LSR_SCENE_CONTENT_MODEL_radialGradient:
    4184           0 :                 n = lsr_read_radialGradient(lsr);
    4185           0 :                 break;
    4186          36 :         case LSR_SCENE_CONTENT_MODEL_rect:
    4187          36 :                 n = lsr_read_rect(lsr, 0);
    4188          36 :                 break;
    4189           3 :         case LSR_SCENE_CONTENT_MODEL_rectClip:
    4190           3 :                 n = lsr_read_rectClip(lsr);
    4191           3 :                 break;
    4192           0 :         case LSR_SCENE_CONTENT_MODEL_sameg:
    4193           0 :                 n = lsr_read_g(lsr, 1);
    4194           0 :                 break;
    4195           0 :         case LSR_SCENE_CONTENT_MODEL_sameline:
    4196           0 :                 n = lsr_read_line(lsr, 1);
    4197           0 :                 break;
    4198           3 :         case LSR_SCENE_CONTENT_MODEL_samepath:
    4199           3 :                 n = lsr_read_path(lsr, 1);
    4200           3 :                 break;
    4201           3 :         case LSR_SCENE_CONTENT_MODEL_samepathfill:
    4202           3 :                 n = lsr_read_path(lsr, 2);
    4203           3 :                 break;
    4204           0 :         case LSR_SCENE_CONTENT_MODEL_samepolygon:
    4205           0 :                 n = lsr_read_polygon(lsr, 0, 1);
    4206           0 :                 break;
    4207           6 :         case LSR_SCENE_CONTENT_MODEL_samepolygonfill:
    4208           6 :                 n = lsr_read_polygon(lsr, 0, 2);
    4209           6 :                 break;
    4210           0 :         case LSR_SCENE_CONTENT_MODEL_samepolygonstroke:
    4211           0 :                 n = lsr_read_polygon(lsr, 0, 3);
    4212           0 :                 break;
    4213           3 :         case LSR_SCENE_CONTENT_MODEL_samepolyline:
    4214           3 :                 n = lsr_read_polygon(lsr, 1, 1);
    4215           3 :                 break;
    4216           0 :         case LSR_SCENE_CONTENT_MODEL_samepolylinefill:
    4217           0 :                 n = lsr_read_polygon(lsr, 1, 2);
    4218           0 :                 break;
    4219           0 :         case LSR_SCENE_CONTENT_MODEL_samepolylinestroke:
    4220           0 :                 n = lsr_read_polygon(lsr, 1, 3);
    4221           0 :                 break;
    4222          36 :         case LSR_SCENE_CONTENT_MODEL_samerect:
    4223          36 :                 n = lsr_read_rect(lsr, 1);
    4224          36 :                 break;
    4225           0 :         case LSR_SCENE_CONTENT_MODEL_samerectfill:
    4226           0 :                 n = lsr_read_rect(lsr, 2);
    4227           0 :                 break;
    4228           0 :         case LSR_SCENE_CONTENT_MODEL_sametext:
    4229           0 :                 n = lsr_read_text(lsr, 1);
    4230           0 :                 break;
    4231           0 :         case LSR_SCENE_CONTENT_MODEL_sametextfill:
    4232           0 :                 n = lsr_read_text(lsr, 2);
    4233           0 :                 break;
    4234           3 :         case LSR_SCENE_CONTENT_MODEL_sameuse:
    4235           3 :                 n = lsr_read_use(lsr, 1);
    4236           3 :                 break;
    4237           3 :         case LSR_SCENE_CONTENT_MODEL_script:
    4238           3 :                 n = lsr_read_script(lsr);
    4239           3 :                 break;
    4240           9 :         case LSR_SCENE_CONTENT_MODEL_selector:
    4241           9 :                 n = lsr_read_selector(lsr);
    4242           9 :                 break;
    4243           0 :         case LSR_SCENE_CONTENT_MODEL_set:
    4244           0 :                 n = lsr_read_set(lsr, parent);
    4245           0 :                 break;
    4246           3 :         case LSR_SCENE_CONTENT_MODEL_simpleLayout:
    4247           3 :                 n = lsr_read_simpleLayout(lsr);
    4248           3 :                 break;
    4249          18 :         case LSR_SCENE_CONTENT_MODEL_stop:
    4250          18 :                 n = lsr_read_stop(lsr);
    4251          18 :                 break;
    4252           0 :         case LSR_SCENE_CONTENT_MODEL_switch:
    4253           0 :                 n = lsr_read_switch(lsr);
    4254           0 :                 break;
    4255          12 :         case LSR_SCENE_CONTENT_MODEL_text:
    4256          12 :                 n = lsr_read_text(lsr, 0);
    4257          12 :                 break;
    4258           0 :         case LSR_SCENE_CONTENT_MODEL_title:
    4259           0 :                 n = lsr_read_data(lsr, TAG_SVG_title);
    4260           0 :                 break;
    4261           0 :         case LSR_SCENE_CONTENT_MODEL_tspan:
    4262           0 :                 n = lsr_read_tspan(lsr);
    4263           0 :                 break;
    4264           6 :         case LSR_SCENE_CONTENT_MODEL_use:
    4265           6 :                 n = lsr_read_use(lsr, 0);
    4266           6 :                 break;
    4267           3 :         case LSR_SCENE_CONTENT_MODEL_video:
    4268           3 :                 n = lsr_read_video(lsr, parent);
    4269           3 :                 break;
    4270           3 :         case LSR_SCENE_CONTENT_MODEL_listener:
    4271           3 :                 n = lsr_read_listener(lsr, parent);
    4272           3 :                 break;
    4273           0 :         case LSR_SCENE_CONTENT_MODEL_element_any:
    4274           0 :                 lsr_read_extend_class(lsr, NULL, 0, "node");
    4275             :                 break;
    4276           0 :         case LSR_SCENE_CONTENT_MODEL_privateContainer:
    4277           0 :                 lsr_read_private_element_container(lsr);
    4278             :                 break;
    4279          39 :         case LSR_SCENE_CONTENT_MODEL_textContent:
    4280          39 :                 lsr_read_text_content(lsr, (GF_Node*)parent);
    4281             :                 break;
    4282             :         default:
    4283             :                 break;
    4284             :         }
    4285         405 :         if (n && n->sgprivate->interact && n->sgprivate->interact->dom_evt) {
    4286             :                 GF_DOM_Event evt;
    4287             :                 memset(&evt, 0, sizeof(GF_DOM_Event));
    4288           4 :                 evt.type = GF_EVENT_LOAD;
    4289           4 :                 gf_dom_event_fire(n, &evt);
    4290             :         }
    4291         444 :         return n;
    4292             : }
    4293             : 
    4294          84 : static GF_Node *lsr_read_update_content_model(GF_LASeRCodec *lsr, SVG_Element *parent)
    4295             : {
    4296             :         u32 flag;
    4297             :         GF_Node *n=NULL;
    4298          84 :         GF_LSR_READ_INT(lsr, flag, 1, "ch4");
    4299          84 :         if (flag) {
    4300          10 :                 GF_LSR_READ_INT(lsr, flag, 3, "ch61");
    4301          10 :                 switch (flag) {
    4302           2 :                 case LSR_UPDATE_CONTENT_MODEL2_conditional:
    4303           2 :                         n = lsr_read_conditional(lsr);
    4304           2 :                         break;
    4305           2 :                 case LSR_UPDATE_CONTENT_MODEL2_cursorManager:
    4306           2 :                         n = lsr_read_cursorManager(lsr);
    4307           2 :                         break;
    4308           0 :                 case LSR_UPDATE_CONTENT_MODEL2_extend:
    4309           0 :                         lsr_read_extend_class(lsr, NULL, 0, "extend");
    4310           0 :                         return NULL;
    4311           0 :                 case LSR_UPDATE_CONTENT_MODEL2_private:
    4312           0 :                         lsr_read_private_element_container(lsr);
    4313           0 :                         return NULL;
    4314           2 :                 case LSR_UPDATE_CONTENT_MODEL2_rectClip:
    4315           2 :                         n = lsr_read_rectClip(lsr);
    4316           2 :                         break;
    4317           2 :                 case LSR_UPDATE_CONTENT_MODEL2_simpleLayout:
    4318           2 :                         n = lsr_read_simpleLayout(lsr);
    4319           2 :                         break;
    4320           2 :                 case LSR_UPDATE_CONTENT_MODEL2_selector:
    4321           2 :                         n = lsr_read_selector(lsr);
    4322           2 :                         break;
    4323             :                 }
    4324             :         } else {
    4325          74 :                 GF_LSR_READ_INT(lsr, flag, 6, "ch6");
    4326          74 :                 switch(flag) {
    4327           2 :                 case LSR_UPDATE_CONTENT_MODEL_a:
    4328           2 :                         n = lsr_read_a(lsr);
    4329           2 :                         break;
    4330           2 :                 case LSR_UPDATE_CONTENT_MODEL_animate:
    4331           2 :                         n = lsr_read_animate(lsr, parent, 0);
    4332           2 :                         break;
    4333           2 :                 case LSR_UPDATE_CONTENT_MODEL_animateColor:
    4334           2 :                         n = lsr_read_animate(lsr, parent, 1);
    4335           2 :                         break;
    4336           2 :                 case LSR_UPDATE_CONTENT_MODEL_animateMotion:
    4337           2 :                         n = lsr_read_animateMotion(lsr, parent);
    4338           2 :                         break;
    4339           2 :                 case LSR_UPDATE_CONTENT_MODEL_animateTransform:
    4340           2 :                         n = lsr_read_animateTransform(lsr, parent);
    4341           2 :                         break;
    4342           2 :                 case LSR_UPDATE_CONTENT_MODEL_audio:
    4343           2 :                         n = lsr_read_audio(lsr, parent);
    4344           2 :                         break;
    4345           2 :                 case LSR_UPDATE_CONTENT_MODEL_circle:
    4346           2 :                         n = lsr_read_circle(lsr);
    4347           2 :                         break;
    4348           2 :                 case LSR_UPDATE_CONTENT_MODEL_defs:
    4349           2 :                         n = lsr_read_defs(lsr);
    4350           2 :                         break;
    4351           4 :                 case LSR_UPDATE_CONTENT_MODEL_desc:
    4352           4 :                         n = lsr_read_data(lsr, TAG_SVG_desc);
    4353           4 :                         break;
    4354           2 :                 case LSR_UPDATE_CONTENT_MODEL_ellipse:
    4355           2 :                         n = lsr_read_ellipse(lsr);
    4356           2 :                         break;
    4357           2 :                 case LSR_UPDATE_CONTENT_MODEL_foreignObject:
    4358           2 :                         n = lsr_read_foreignObject(lsr);
    4359           2 :                         break;
    4360           2 :                 case LSR_UPDATE_CONTENT_MODEL_g:
    4361           2 :                         n = lsr_read_g(lsr, 0);
    4362           2 :                         break;
    4363           2 :                 case LSR_UPDATE_CONTENT_MODEL_image:
    4364           2 :                         n = lsr_read_image(lsr);
    4365           2 :                         break;
    4366           2 :                 case LSR_UPDATE_CONTENT_MODEL_line:
    4367           2 :                         n = lsr_read_line(lsr, 0);
    4368           2 :                         break;
    4369           2 :                 case LSR_UPDATE_CONTENT_MODEL_linearGradient:
    4370           2 :                         n = lsr_read_linearGradient(lsr);
    4371           2 :                         break;
    4372           2 :                 case LSR_UPDATE_CONTENT_MODEL_metadata:
    4373           2 :                         n = lsr_read_data(lsr, TAG_SVG_metadata);
    4374           2 :                         break;
    4375           2 :                 case LSR_UPDATE_CONTENT_MODEL_mpath:
    4376           2 :                         n = lsr_read_mpath(lsr);
    4377           2 :                         break;
    4378           2 :                 case LSR_UPDATE_CONTENT_MODEL_path:
    4379           2 :                         n = lsr_read_path(lsr, 0);
    4380           2 :                         break;
    4381           2 :                 case LSR_UPDATE_CONTENT_MODEL_polygon:
    4382           2 :                         n = lsr_read_polygon(lsr, 0, 0);
    4383           2 :                         break;
    4384           2 :                 case LSR_UPDATE_CONTENT_MODEL_polyline:
    4385           2 :                         n = lsr_read_polygon(lsr, 1, 0);
    4386           2 :                         break;
    4387           2 :                 case LSR_UPDATE_CONTENT_MODEL_radialGradient:
    4388           2 :                         n = lsr_read_radialGradient(lsr);
    4389           2 :                         break;
    4390           5 :                 case LSR_UPDATE_CONTENT_MODEL_rect:
    4391           5 :                         n = lsr_read_rect(lsr, 0);
    4392           5 :                         break;
    4393           2 :                 case LSR_UPDATE_CONTENT_MODEL_script:
    4394           2 :                         n = lsr_read_script(lsr);
    4395           2 :                         break;
    4396           2 :                 case LSR_UPDATE_CONTENT_MODEL_set:
    4397           2 :                         n = lsr_read_set(lsr, parent);
    4398           2 :                         break;
    4399           2 :                 case LSR_UPDATE_CONTENT_MODEL_stop:
    4400           2 :                         n = lsr_read_stop(lsr);
    4401           2 :                         break;
    4402           2 :                 case LSR_UPDATE_CONTENT_MODEL_svg:
    4403           2 :                         n = lsr_read_svg(lsr, 0);
    4404           2 :                         break;
    4405           2 :                 case LSR_UPDATE_CONTENT_MODEL_switch:
    4406           2 :                         n = lsr_read_switch(lsr);
    4407           2 :                         break;
    4408           5 :                 case LSR_UPDATE_CONTENT_MODEL_text:
    4409           5 :                         n = lsr_read_text(lsr, 0);
    4410           5 :                         break;
    4411           2 :                 case LSR_UPDATE_CONTENT_MODEL_title:
    4412           2 :                         n = lsr_read_data(lsr, TAG_SVG_title);
    4413           2 :                         break;
    4414           2 :                 case LSR_UPDATE_CONTENT_MODEL_tspan:
    4415           2 :                         n = lsr_read_tspan(lsr);
    4416           2 :                         break;
    4417           2 :                 case LSR_UPDATE_CONTENT_MODEL_use:
    4418           2 :                         n = lsr_read_use(lsr, 0);
    4419           2 :                         break;
    4420           2 :                 case LSR_UPDATE_CONTENT_MODEL_video:
    4421           2 :                         n = lsr_read_video(lsr, parent);
    4422           2 :                         break;
    4423           2 :                 case LSR_UPDATE_CONTENT_MODEL_listener:
    4424           2 :                         n = lsr_read_listener(lsr, parent);
    4425           2 :                         break;
    4426             :                 }
    4427             :         }
    4428          84 :         if (n && n->sgprivate->interact && n->sgprivate->interact->dom_evt) {
    4429             :                 GF_DOM_Event evt;
    4430             :                 memset(&evt, 0, sizeof(GF_DOM_Event));
    4431           0 :                 evt.type = GF_EVENT_LOAD;
    4432           0 :                 gf_dom_event_fire(n, &evt);
    4433             :         }
    4434             :         return n;
    4435             : }
    4436             : 
    4437         441 : static void lsr_read_group_content(GF_LASeRCodec *lsr, GF_Node *elt, Bool skip_object_content)
    4438             : {
    4439             :         u32 i, count;
    4440         441 :         if (lsr->last_error) return;
    4441             : 
    4442         441 :         if (!skip_object_content) lsr_read_object_content(lsr, (SVG_Element*)elt);
    4443             : 
    4444             : 
    4445             :         /*node attributes are all parsed*/
    4446         441 :         if (elt->sgprivate->tag!=TAG_SVG_script)
    4447         436 :                 gf_node_init(elt);
    4448             : 
    4449         441 :         GF_LSR_READ_INT(lsr, count, 1, "opt_group");
    4450         441 :         if (count) {
    4451          99 :                 GF_ChildNodeItem *last = NULL;
    4452          99 :                 count = lsr_read_vluimsbf5(lsr, "occ0");
    4453         540 :                 for (i=0; i<count; i++) {
    4454             :                         GF_Node *n;
    4455         441 :                         if (lsr->last_error) break;
    4456         441 :                         n = lsr_read_scene_content_model(lsr, (SVG_Element*)elt);
    4457         441 :                         if (n) {
    4458         402 :                                 gf_node_register(n, elt);
    4459         402 :                                 gf_node_list_add_child_last(& ((SVG_Element*)elt)->children, n, &last);
    4460         402 :                                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] ############## end %s ###########\n", gf_node_get_class_name(n)));
    4461             :                         } else {
    4462             :                                 /*either error or text content*/
    4463             :                         }
    4464             :                 }
    4465             :         }
    4466             : 
    4467         441 :         if (elt->sgprivate->tag==TAG_SVG_script)
    4468           5 :                 gf_node_init(elt);
    4469             : }
    4470             : 
    4471          44 : static void lsr_read_group_content_post_init(GF_LASeRCodec *lsr, SVG_Element *elt, Bool skip_init)
    4472             : {
    4473             :         u32 i, count;
    4474          44 :         if (lsr->last_error) return;
    4475          44 :         lsr_read_object_content(lsr, elt);
    4476             : 
    4477          44 :         GF_LSR_READ_INT(lsr, count, 1, "opt_group");
    4478          44 :         if (count) {
    4479           3 :                 GF_ChildNodeItem *last = NULL;
    4480           3 :                 count = lsr_read_vluimsbf5(lsr, "occ0");
    4481           6 :                 for (i=0; i<count; i++) {
    4482             :                         GF_Node *n;
    4483           3 :                         if (lsr->last_error) return;
    4484           3 :                         n = lsr_read_scene_content_model(lsr, elt);
    4485           3 :                         if (n) {
    4486           3 :                                 gf_node_register(n, (GF_Node*)elt);
    4487           3 :                                 gf_node_list_add_child_last(&elt->children, n, &last);
    4488           3 :                                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] ############## end %s ###########\n", gf_node_get_class_name(n)));
    4489             :                         } else {
    4490             :                                 /*either error or text content*/
    4491             :                         }
    4492             :                 }
    4493             :         }
    4494          44 :         if (!skip_init) gf_node_init((GF_Node*)elt);
    4495             : }
    4496             : 
    4497          18 : static void *lsr_read_update_value_indexed(GF_LASeRCodec *lsr, GF_Node*node, u32 fieldType, void *rep_val, u32 idx, Bool is_insert, Bool is_com, u32 *single_field_type)
    4498             : {
    4499             :         Fixed *f_val;
    4500             :         SVG_Number num;
    4501             : 
    4502          18 :         switch (fieldType) {
    4503           3 :         case SVG_Points_datatype/*ITYPE_point*/:
    4504             :         {
    4505             :                 SVG_Point *pt;
    4506             :                 ListOfXXX *res;
    4507           3 :                 GF_SAFEALLOC(res, ListOfXXX);
    4508           3 :                 if (!res) return NULL;
    4509           3 :                 *res = gf_list_new();
    4510           3 :                 pt = (SVG_Point*)gf_malloc(sizeof(SVG_Point));
    4511           3 :                 if (pt) {
    4512           3 :                         lsr_read_coordinate(lsr, &num, 0, "coordX");
    4513           3 :                         pt->x = num.value;
    4514           3 :                         lsr_read_coordinate(lsr, &num, 0, "coordY");
    4515           3 :                         pt->y = num.value;
    4516           3 :                         gf_list_add(*res, pt);
    4517             :                 }
    4518             :                 return res;
    4519             :         }
    4520           3 :         case SMIL_KeySplines_datatype/*ITYPE_float*/:
    4521             :         {
    4522             :                 ListOfXXX *res;
    4523           3 :                 GF_SAFEALLOC(res, ListOfXXX);
    4524           3 :                 if (!res) return NULL;
    4525           3 :                 *res = gf_list_new();
    4526           3 :                 f_val = (Fixed*)gf_malloc(sizeof(Fixed));
    4527           3 :                 if (f_val) {
    4528           3 :                         *f_val = lsr_read_fixed_16_8(lsr, "floatValue");
    4529           3 :                         gf_list_add(*res, f_val);
    4530             :                 }
    4531             :                 return res;
    4532             :         }
    4533           0 :         case SVG_StrokeDashArray_datatype:
    4534             :         case SVG_ViewBox_datatype:
    4535           0 :                 f_val = (Fixed*)gf_malloc(sizeof(Fixed));
    4536           0 :                 if (!f_val) {
    4537           0 :                         lsr->last_error = GF_OUT_OF_MEM;
    4538             :                         return NULL;
    4539             :                 }
    4540           0 :                 *f_val = lsr_read_fixed_16_8(lsr, "floatValue");
    4541             :                 return f_val;
    4542           6 :         case SMIL_KeyTimes_datatype/*ITYPE_keyTime*/:
    4543             :         {
    4544             :                 ListOfXXX *res;
    4545           6 :                 GF_SAFEALLOC(res, ListOfXXX);
    4546           6 :                 if (!res) return NULL;
    4547           6 :                 *res = gf_list_new();
    4548           6 :                 f_val = lsr_read_fraction_12_item(lsr);
    4549           6 :                 if (f_val) gf_list_add(*res, f_val);
    4550             :                 return res;
    4551             :         }
    4552           3 :         case SMIL_KeyPoints_datatype/*ITYPE_0to1 - keyPoints*/:
    4553             :         {
    4554             :                 ListOfXXX *res;
    4555           3 :                 GF_SAFEALLOC(res, ListOfXXX);
    4556           3 :                 if (!res) return NULL;
    4557           3 :                 *res = gf_list_new();
    4558           3 :                 f_val = (Fixed*)gf_malloc(sizeof(Fixed));
    4559           3 :                 if (f_val) {
    4560           3 :                         *f_val = lsr_read_fixed_clamp(lsr, "value");
    4561           3 :                         gf_list_add(*res, f_val);
    4562             :                 }
    4563             :                 return res;
    4564             :         }
    4565           3 :         case SMIL_Times_datatype/*ITYPE_smil_time*/:
    4566             :         {
    4567             :                 ListOfXXX *res;
    4568           3 :                 GF_SAFEALLOC(res, ListOfXXX);
    4569           3 :                 if (!res) return NULL;
    4570           3 :                 *res = gf_list_new();
    4571           3 :                 gf_list_add(*res, lsr_read_smil_time(lsr, node) );
    4572             :                 return res;
    4573             :         }
    4574           0 :         default:
    4575           0 :                 lsr_read_extension(lsr, "privateData");
    4576             :                 break;
    4577             :         }
    4578             :         return NULL;
    4579             : }
    4580             : 
    4581          54 : static void lsr_read_update_value(GF_LASeRCodec *lsr, GF_Node *node, u32 att_tag, u32 fieldType, void *val, u32 node_tag)
    4582             : {
    4583             :         u32 is_default, has_escape, escape_val = 0;
    4584             :         SVG_Number num, *n;
    4585             : 
    4586          54 :         switch (fieldType) {
    4587           0 :         case SVG_Boolean_datatype:
    4588           0 :                 GF_LSR_READ_INT(lsr, *(SVG_Boolean*)val, 1, "val");
    4589             :                 break;
    4590           4 :         case SVG_Paint_datatype:
    4591           4 :                 lsr_read_paint(lsr, (SVG_Paint*)val, "val");
    4592           4 :                 break;
    4593             :         /*
    4594             :                 case SVG_AudioLevel_datatype:
    4595             :                         n = val;
    4596             :                         GF_LSR_READ_INT(lsr, is_default, 1, "isDefaultValue");
    4597             :                         if (is_default) n->type=SVG_NUMBER_INHERIT;
    4598             :                         else {
    4599             :                                 n->type = SVG_NUMBER_VALUE;
    4600             :                                 n->value = lsr_read_fixed_clamp(lsr, "val");
    4601             :                         }
    4602             :                         break;
    4603             :         */
    4604           0 :         case SVG_Transform_Scale_datatype:
    4605           0 :                 ((SVG_Point *)val)->x = lsr_read_fixed_16_8(lsr, "scale_x");
    4606           0 :                 ((SVG_Point *)val)->y = lsr_read_fixed_16_8(lsr, "scale_y");
    4607           0 :                 break;
    4608           3 :         case LASeR_Size_datatype:
    4609             :         case SVG_Transform_Translate_datatype:
    4610           3 :                 lsr_read_coordinate(lsr, &num, 0, "translation_x");
    4611           3 :                 ((SVG_Point *)val)->x = num.value;
    4612           3 :                 lsr_read_coordinate(lsr, &num, 0, "translation_y");
    4613           3 :                 ((SVG_Point *)val)->y = num.value;
    4614           3 :                 break;
    4615           0 :         case SVG_Transform_Rotate_datatype:
    4616           0 :                 GF_LSR_READ_INT(lsr, is_default, 1, "isDefaultValue");
    4617           0 :                 if (is_default) ((SVG_Point_Angle*)val)->angle = 0;
    4618             :                 else {
    4619           0 :                         GF_LSR_READ_INT(lsr, has_escape, 1, "escapeFlag");
    4620           0 :                         if (has_escape) {
    4621           0 :                                 GF_LSR_READ_INT(lsr, escape_val, 2, "escapeEnum");
    4622           0 :                                 ((SVG_Point_Angle*)val)->angle = 0;
    4623             :                         }
    4624             :                         else {
    4625           0 :                                 ((SVG_Point_Angle*)val)->angle = lsr_read_fixed_16_8(lsr, "rotate");
    4626             :                         }
    4627             :                 }
    4628             :                 break;
    4629           3 :         case SVG_Transform_datatype:
    4630           3 :                 lsr_read_matrix(lsr, val);
    4631           3 :                 break;
    4632          21 :         case SVG_Number_datatype:
    4633             :         case SVG_FontSize_datatype:
    4634             :         case SVG_Length_datatype:
    4635             :                 n = (SVG_Number*)val;
    4636          21 :                 switch (att_tag) {
    4637             :                 /*fractions*/
    4638           6 :                 case TAG_SVG_ATT_audio_level:
    4639             :                 case TAG_SVG_ATT_fill_opacity:
    4640             :                 case TAG_SVG_ATT_offset:
    4641             :                 case TAG_SVG_ATT_opacity:
    4642             :                 case TAG_SVG_ATT_solid_opacity:
    4643             :                 case TAG_SVG_ATT_stop_opacity:
    4644             :                 case TAG_SVG_ATT_stroke_opacity:
    4645             :                 case TAG_SVG_ATT_viewport_fill_opacity:
    4646           6 :                         GF_LSR_READ_INT(lsr, is_default, 1, "isDefaultValue");
    4647           6 :                         if (is_default) n->type=SVG_NUMBER_INHERIT;
    4648             :                         else {
    4649           3 :                                 n->type = SVG_NUMBER_VALUE;
    4650           3 :                                 n->value = lsr_read_fixed_clamp(lsr, "val");
    4651             :                         }
    4652             :                         break;
    4653           9 :                 case TAG_SVG_ATT_width:
    4654             :                 case TAG_SVG_ATT_height:
    4655           9 :                         if (node_tag==TAG_SVG_svg) {
    4656           3 :                                 lsr_read_value_with_units(lsr, n, "val");
    4657             :                         } else {
    4658           6 :                                 lsr_read_coordinate(lsr, n, 0, "val");
    4659             :                         }
    4660             :                         break;
    4661           6 :                 default:
    4662           6 :                         GF_LSR_READ_INT(lsr, is_default, 1, "isDefaultValue");
    4663           6 :                         if (is_default) n->type=SVG_NUMBER_INHERIT;
    4664             :                         else {
    4665           3 :                                 GF_LSR_READ_INT(lsr, has_escape, 1, "escapeFlag");
    4666           3 :                                 if (has_escape) {
    4667           0 :                                         GF_LSR_READ_INT(lsr, escape_val, 2, "escapeEnum");
    4668           0 :                                         n->type = SVG_NUMBER_AUTO;//only lineIncrement
    4669             :                                 } else {
    4670           3 :                                         n->type = SVG_NUMBER_VALUE;
    4671           3 :                                         n->value = lsr_read_fixed_16_8(lsr, "val");
    4672             :                                 }
    4673             :                         }
    4674             :                         break;
    4675             :                 }
    4676             :                 break;
    4677           3 :         case SVG_Coordinate_datatype:
    4678             :                 n = (SVG_Number*)val;
    4679           3 :                 n->type = SVG_NUMBER_VALUE;
    4680           3 :                 lsr_read_coordinate(lsr, n, 0, "val");
    4681           3 :                 break;
    4682             : 
    4683           6 :         case SVG_Rotate_datatype:
    4684             :                 n = (SVG_Number*)val;
    4685           6 :                 GF_LSR_READ_INT(lsr, is_default, 1, "isDefaultValue");
    4686           6 :                 if (is_default) n->type=SVG_NUMBER_INHERIT;
    4687             :                 else {
    4688           6 :                         GF_LSR_READ_INT(lsr, has_escape, 1, "escapeFlag");
    4689           6 :                         if (has_escape) {
    4690           3 :                                 GF_LSR_READ_INT(lsr, escape_val, 2, "escapeEnum");
    4691           3 :                                 n->type = escape_val ? SVG_NUMBER_AUTO_REVERSE : SVG_NUMBER_AUTO;
    4692             :                         } else {
    4693           3 :                                 n->type = SVG_NUMBER_VALUE;
    4694           3 :                                 n->value = lsr_read_fixed_16_8(lsr, "rotate");
    4695             :                         }
    4696             :                 }
    4697             :                 break;
    4698           0 :         case SVG_Coordinates_datatype:
    4699           0 :                 lsr_read_float_list(lsr, NULL, 0, val, "val");
    4700           0 :                 break;
    4701           0 :         case SVG_ViewBox_datatype:
    4702             :         {
    4703             :                 u32 count;
    4704             :                 SVG_ViewBox *vb = (SVG_ViewBox *)val;
    4705           0 :                 GF_LSR_READ_INT(lsr, count, 1, "isDefault");
    4706           0 :                 if (count) {
    4707           0 :                         vb->is_set = 0;
    4708             :                 } else {
    4709           0 :                         vb->is_set = 1;
    4710           0 :                         GF_LSR_READ_INT(lsr, count, 1, "escapeFlag");
    4711           0 :                         count = lsr_read_vluimsbf5(lsr, "count");
    4712           0 :                         if (count) {
    4713           0 :                                 vb->x = lsr_read_fixed_16_8(lsr, "val");
    4714           0 :                                 count--;
    4715             :                         }
    4716           0 :                         if (count) {
    4717           0 :                                 vb->y = lsr_read_fixed_16_8(lsr, "val");
    4718           0 :                                 count--;
    4719             :                         }
    4720           0 :                         if (count) {
    4721           0 :                                 vb->width = lsr_read_fixed_16_8(lsr, "val");
    4722           0 :                                 count--;
    4723             :                         }
    4724           0 :                         if (count) {
    4725           0 :                                 vb->height = lsr_read_fixed_16_8(lsr, "val");
    4726             :                         }
    4727             :                 }
    4728             :         }
    4729             :         break;
    4730           9 :         case XMLRI_datatype:
    4731             :         case SVG_Focus_datatype:
    4732           9 :                 if ((att_tag==TAG_XLINK_ATT_href) || (att_tag==TAG_SVG_ATT_syncReference)) {
    4733           0 :                         lsr_read_any_uri(lsr, (XMLRI*)val, "val");
    4734             :                 } else {
    4735             :                         Bool is_escape;
    4736             :                         u32 ID;
    4737             :                         escape_val = ID = 0;
    4738             :                         is_escape = 0;
    4739           9 :                         GF_LSR_READ_INT(lsr, is_default, 1, "isDefault");
    4740           9 :                         if (!is_default) {
    4741           6 :                                 GF_LSR_READ_INT(lsr, is_escape, 1, "isEscape");
    4742           6 :                                 if (is_escape) {
    4743           3 :                                         GF_LSR_READ_INT(lsr, escape_val, 2, "escapeEnumVal");
    4744             :                                 } else {
    4745           3 :                                         ID = lsr_read_vluimsbf5(lsr, "ID");
    4746             :                                 }
    4747             :                         }
    4748           9 :                         if (att_tag==SVG_Focus_datatype) {
    4749           0 :                                 if (is_default) ((SVG_Focus*)val)->type = SVG_FOCUS_AUTO;
    4750           0 :                                 else if (is_escape) ((SVG_Focus*)val)->type = escape_val;
    4751             :                                 else {
    4752           0 :                                         ((SVG_Focus*)val)->type = SVG_FOCUS_IRI;
    4753           0 :                                         ((SVG_Focus*)val)->target.type = XMLRI_ELEMENTID;
    4754           0 :                                         ((SVG_Focus*)val)->target.node_id = ID;
    4755             :                                 }
    4756             :                         } else {
    4757           9 :                                 if (is_default) ((XMLRI*)val)->type = XMLRI_STRING;
    4758             :                                 else {
    4759           6 :                                         ((XMLRI *)val)->type = XMLRI_ELEMENTID;
    4760           6 :                                         ((XMLRI *)val)->node_id = ID;
    4761             :                                 }
    4762             :                         }
    4763             :                 }
    4764             :                 break;
    4765             : 
    4766           0 :         case DOM_String_datatype:
    4767             :         case SVG_ContentType_datatype:
    4768             :         case SVG_LanguageID_datatype:
    4769           0 :                 lsr_read_byte_align_string(lsr, (char**)val, "val");
    4770           0 :                 break;
    4771           0 :         case SVG_Motion_datatype:
    4772           0 :                 lsr_read_coordinate(lsr, &num, 0, "pointValueX");
    4773           0 :                 ((GF_Matrix2D*)val)->m[2] = num.value;
    4774           0 :                 lsr_read_coordinate(lsr, &num, 0, "pointValueY");
    4775           0 :                 ((GF_Matrix2D*)val)->m[5] = num.value;
    4776           0 :                 break;
    4777           0 :         case SVG_Points_datatype:
    4778           0 :                 lsr_read_point_sequence(lsr, *(GF_List **)val, "val");
    4779           0 :                 break;
    4780           0 :         case SVG_PathData_datatype:
    4781           0 :                 lsr_read_path_type(lsr, NULL, 0, (SVG_PathData*)val, "val");
    4782           0 :                 break;
    4783           2 :         case SVG_FontFamily_datatype:
    4784             :         {
    4785             :                 u32 idx;
    4786             :                 SVG_FontFamily *ff = (SVG_FontFamily *)val;
    4787           2 :                 GF_LSR_READ_INT(lsr, idx, 1, "isDefault");
    4788           2 :                 ff->type = SVG_FONTFAMILY_INHERIT;
    4789           2 :                 if (!idx) {
    4790             :                         char *ft;
    4791           2 :                         GF_LSR_READ_INT(lsr, idx, 1, "escapeFlag");
    4792           2 :                         idx = lsr_read_vluimsbf5(lsr, "index");
    4793           2 :                         if (ff->value) gf_free(ff->value);
    4794           2 :                         ff->value = NULL;
    4795           2 :                         ft = (char*)gf_list_get(lsr->font_table, idx);
    4796           2 :                         if (ft) {
    4797           2 :                                 ff->value = gf_strdup(ft);
    4798           2 :                                 ff->type = SVG_FONTFAMILY_VALUE;
    4799             :                         }
    4800             :                 }
    4801             :         }
    4802             :                 break;
    4803           0 :         case LASeR_Choice_datatype:
    4804           0 :                 GF_LSR_READ_INT(lsr, is_default, 1, "isDefaultValue");
    4805           0 :                 if (is_default) ((LASeR_Choice *)val)->type = LASeR_CHOICE_ALL;
    4806             :                 else {
    4807           0 :                         GF_LSR_READ_INT(lsr, has_escape, 1, "escapeFlag");
    4808           0 :                         if (has_escape) {
    4809           0 :                                 GF_LSR_READ_INT(lsr, escape_val, 2, "escapeEnum");
    4810           0 :                                 ((LASeR_Choice *)val)->type = escape_val ? LASeR_CHOICE_NONE : LASeR_CHOICE_ALL;
    4811             :                         } else {
    4812           0 :                                 ((LASeR_Choice *)val)->type = LASeR_CHOICE_N;
    4813           0 :                                 ((LASeR_Choice *)val)->choice_index = lsr_read_vluimsbf5(lsr, "value");
    4814             :                         }
    4815             :                 }
    4816             :                 break;
    4817           3 :         default:
    4818           3 :                 if ((fieldType>=SVG_FillRule_datatype) && (fieldType<=SVG_LAST_U8_PROPERTY)) {
    4819             :                         /*TODO fixme, check inherit values*/
    4820           3 :                         GF_LSR_READ_INT(lsr, is_default, 1, "isDefaultValue");
    4821           3 :                         if (is_default) *(u8 *)val = 0;
    4822           3 :                         else *(u8 *)val = lsr_read_vluimsbf5(lsr, "val");
    4823             :                 } else {
    4824           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] Warning: update value not supported: fieldType %d - attribute tag %d\n", fieldType, att_tag));
    4825             :                 }
    4826             :         }
    4827          54 :         if (node) {
    4828             :                 //gf_node_dirty_set(node, 0, 0);
    4829          16 :                 gf_node_changed(node, NULL);
    4830             :         }
    4831          54 : }
    4832             : 
    4833          98 : static u32 lsr_get_attribute_name(GF_LASeRCodec *lsr)
    4834             : {
    4835             :         u32 val = 1;
    4836          98 :         GF_LSR_READ_INT(lsr, val, 1, "has_attributeName");
    4837          98 :         if (!val) return -1;
    4838             : 
    4839          84 :         GF_LSR_READ_INT(lsr, val, 1, "choice");
    4840          84 :         if (val) {
    4841           0 :                 lsr_read_vluimsbf5(lsr, "item[i]");
    4842           0 :                 lsr_read_vluimsbf5(lsr, "item[i]");
    4843           0 :                 return -1;
    4844             :         } else {
    4845          84 :                 GF_LSR_READ_INT(lsr, val, 8, "attributeName");
    4846             :                 return val;
    4847             :         }
    4848             : }
    4849             : 
    4850          90 : static GF_Err lsr_read_add_replace_insert(GF_LASeRCodec *lsr, GF_List *com_list, u32 com_type)
    4851             : {
    4852             :         GF_FieldInfo info;
    4853             :         GF_Node *n, *operandNode;
    4854             :         GF_Command *com;
    4855             :         GF_CommandField *field;
    4856             :         s32 idx, att_type, op_att_type;
    4857             :         u32 type, idref, op_idref = 0;
    4858             : 
    4859             :         operandNode = NULL;
    4860             :         op_att_type = -1;
    4861             : 
    4862          90 :         att_type = lsr_get_attribute_name(lsr);
    4863             : 
    4864             :         idx = -1;
    4865          90 :         if (com_type) {
    4866          90 :                 GF_LSR_READ_INT(lsr, type, 1, "has_index");
    4867          90 :                 if (type) idx = lsr_read_vluimsbf5(lsr, "index");
    4868             :         }
    4869          90 :         if (com_type!=3) {
    4870          84 :                 GF_LSR_READ_INT(lsr, type, 1, "has_operandAttribute");
    4871          84 :                 if (type) GF_LSR_READ_INT(lsr, op_att_type, 8, "attributeName");
    4872          84 :                 GF_LSR_READ_INT(lsr, type, 1, "has_operandElementId");
    4873          84 :                 if (type) {
    4874           3 :                         op_idref = lsr_read_codec_IDREF_command(lsr, "operandElementId");
    4875           3 :                         operandNode = gf_sg_find_node(lsr->sg, op_idref);
    4876           3 :                         if (!operandNode)
    4877             :                                 return GF_NON_COMPLIANT_BITSTREAM;
    4878             :                 }
    4879             :         }
    4880          90 :         idref = lsr_read_codec_IDREF_command(lsr, "ref");
    4881             : 
    4882          90 :         n = gf_sg_find_node(lsr->sg, idref);
    4883          90 :         if (!n) {
    4884           0 :                 if (!com_list) {
    4885             :                         return GF_NON_COMPLIANT_BITSTREAM;
    4886             :                 }
    4887             :         }
    4888             : 
    4889          90 :         GF_LSR_READ_INT(lsr, type, 1, "has_value");
    4890          90 :         if (type) {
    4891             :                 /*node or node-list replacement*/
    4892          78 :                 if (att_type==-2) {
    4893           0 :                         lsr_read_byte_align_string(lsr, NULL, "anyXML");
    4894             :                 }
    4895          78 :                 else if (att_type<0) {
    4896             :                         GF_Node *new_node;
    4897           0 :                         if (!com_type)
    4898             :                                 return GF_NON_COMPLIANT_BITSTREAM;
    4899           0 :                         GF_LSR_READ_INT(lsr, type, 1, "isInherit");
    4900           0 :                         if (type)
    4901             :                                 return GF_NON_COMPLIANT_BITSTREAM;
    4902           0 :                         if (idx==-1) {
    4903           0 :                                 GF_LSR_READ_INT(lsr, type, 1, "escapeFlag");
    4904           0 :                                 if (type)
    4905             :                                         return GF_NON_COMPLIANT_BITSTREAM;
    4906             :                         }
    4907             : 
    4908           0 :                         new_node = lsr_read_update_content_model(lsr, (idx==-1) ? NULL : (SVG_Element *)n);
    4909           0 :                         if (com_list) {
    4910           0 :                                 com = gf_sg_command_new(lsr->sg, (com_type==3) ? GF_SG_LSR_INSERT : GF_SG_LSR_REPLACE);
    4911           0 :                                 gf_list_add(com_list, com);
    4912           0 :                                 if (n) {
    4913           0 :                                         com->node = n;
    4914           0 :                                         gf_node_register(com->node, NULL);
    4915             :                                 } else {
    4916           0 :                                         com->RouteID = idref;
    4917           0 :                                         gf_list_add(lsr->unresolved_commands, com);
    4918             :                                 }
    4919           0 :                                 field = gf_sg_command_field_new(com);
    4920           0 :                                 field->pos = idx;
    4921           0 :                                 field->new_node = new_node;
    4922           0 :                                 if (new_node) gf_node_register(new_node, NULL);
    4923           0 :                         } else if (com_type==3) {
    4924           0 :                                 gf_node_list_insert_child(& ((SVG_Element *)n)->children, new_node, idx);
    4925           0 :                                 if (new_node) gf_node_register(new_node, n);
    4926             :                         } else {
    4927             :                                 /*child replacement*/
    4928           0 :                                 if (idx!=-1) {
    4929           0 :                                         GF_Node *old = gf_node_list_get_child( ((SVG_Element *)n)->children, idx);
    4930           0 :                                         if (old)
    4931           0 :                                                 gf_node_replace(old, new_node, 0);
    4932             :                                         else {
    4933           0 :                                                 gf_node_list_add_child( & ((SVG_Element *)n)->children, new_node);
    4934           0 :                                                 if (new_node) gf_node_register(new_node, n);
    4935             :                                         }
    4936             :                                 } else {
    4937             :                                         /*node replacement*/
    4938           0 :                                         gf_node_replace(n, new_node, 0);
    4939             :                                 }
    4940             :                         }
    4941             :                 }
    4942             :                 /*value replace/add*/
    4943          78 :                 else if (com_list) {
    4944             :                         u32 field_type;
    4945             :                         Bool text_content = 0;
    4946          54 :                         com = gf_sg_command_new(lsr->sg, (com_type==0) ? GF_SG_LSR_ADD : (com_type==3) ? GF_SG_LSR_INSERT : GF_SG_LSR_REPLACE);
    4947          54 :                         field = gf_sg_command_field_new(com);
    4948          54 :                         field->pos = idx;
    4949             :                         field_type = 0;
    4950          54 :                         switch (att_type) {
    4951             :                         /*text*/
    4952             :                         case LSR_UPDATE_TYPE_TEXT_CONTENT:
    4953             :                                 text_content = 1;
    4954             :                                 break;
    4955             :                         /*matrix.translation, scale or rotate*/
    4956           0 :                         case LSR_UPDATE_TYPE_SCALE:
    4957           0 :                                 field->fieldType = field_type = SVG_Transform_Scale_datatype;
    4958           0 :                                 field->fieldIndex = gf_lsr_anim_type_to_attribute(att_type);
    4959           0 :                                 break;
    4960           0 :                         case LSR_UPDATE_TYPE_ROTATE:
    4961           0 :                                 field->fieldType = field_type = SVG_Transform_Rotate_datatype;
    4962           0 :                                 field->fieldIndex = TAG_SVG_ATT_transform;
    4963           0 :                                 break;
    4964           0 :                         case LSR_UPDATE_TYPE_TRANSLATION:
    4965           0 :                                 field->fieldType = field_type = SVG_Transform_Translate_datatype;
    4966           0 :                                 field->fieldIndex = gf_lsr_anim_type_to_attribute(att_type);
    4967           0 :                                 break;
    4968           0 :                         case LSR_UPDATE_TYPE_SVG_HEIGHT:
    4969           0 :                                 field->fieldIndex = TAG_SVG_ATT_height;
    4970           0 :                                 field_type = field->fieldType = SVG_Length_datatype;
    4971           0 :                                 break;
    4972           0 :                         case LSR_UPDATE_TYPE_SVG_WIDTH:
    4973           0 :                                 field->fieldIndex = TAG_SVG_ATT_width;
    4974           0 :                                 field_type = field->fieldType = SVG_Length_datatype;
    4975           0 :                                 break;
    4976          50 :                         default:
    4977          50 :                                 field->fieldIndex = gf_lsr_anim_type_to_attribute(att_type);
    4978          50 :                                 if (field->fieldIndex == (u32)-1) {
    4979           0 :                                         lsr->last_error = GF_NON_COMPLIANT_BITSTREAM;
    4980           0 :                                         gf_sg_command_del(com);
    4981           0 :                                         return lsr->last_error;
    4982             :                                 }
    4983          50 :                                 field_type = field->fieldType = gf_xml_get_attribute_type(field->fieldIndex);
    4984          50 :                                 break;
    4985             :                         }
    4986          54 :                         gf_list_add(com_list, com);
    4987          54 :                         if (n) {
    4988          54 :                                 com->node = n;
    4989          54 :                                 gf_node_register(com->node, NULL);
    4990             :                         } else {
    4991           0 :                                 com->RouteID = idref;
    4992           0 :                                 gf_list_add(lsr->unresolved_commands, com);
    4993             :                         }
    4994          54 :                         if (idx==-1) {
    4995          42 :                                 if (text_content) {
    4996           4 :                                         GF_DOMText *text = gf_dom_new_text_node(lsr->sg);
    4997           4 :                                         gf_node_register((GF_Node *)text, NULL);
    4998           4 :                                         lsr_read_byte_align_string(lsr, &text->textContent, "val");
    4999           4 :                                         field->new_node = (GF_Node*)text;
    5000             :                                 } else {
    5001          38 :                                         field->field_ptr = gf_svg_create_attribute_value(field_type);
    5002          38 :                                         lsr_read_update_value(lsr, NULL, field->fieldIndex, field->fieldType, field->field_ptr, n ? n->sgprivate->tag : 0);
    5003             :                                 }
    5004             :                         } else {
    5005          12 :                                 field->field_ptr = lsr_read_update_value_indexed(lsr, (GF_Node*)n, field_type, NULL, idx, com_type==LSR_UPDATE_INSERT, 1, &field->fieldType);
    5006             :                         }
    5007             :                 } else {
    5008             :                         GF_Point2D matrix_tmp;
    5009             :                         SVG_Point_Angle matrix_tmp_rot;
    5010             :                         u32 fieldIndex = 0;
    5011             :                         u32 field_type = 0;
    5012             :                         Bool text_content = 0;
    5013             :                         Bool is_lsr_transform = 0;
    5014          24 :                         switch (att_type) {
    5015             :                         /*text*/
    5016             :                         case LSR_UPDATE_TYPE_TEXT_CONTENT:
    5017             :                                 text_content = 1;
    5018             :                                 break;
    5019             :                         /*matrix.translation, scale or rotate*/
    5020           0 :                         case LSR_UPDATE_TYPE_SCALE:
    5021           0 :                                 info.far_ptr = (void *)&matrix_tmp;
    5022             :                                 field_type = SVG_Transform_Scale_datatype;
    5023             :                                 is_lsr_transform = 1;
    5024           0 :                                 break;
    5025           0 :                         case LSR_UPDATE_TYPE_ROTATE:
    5026           0 :                                 info.far_ptr = (void *)&matrix_tmp_rot;
    5027             :                                 field_type = SVG_Transform_Rotate_datatype;
    5028             :                                 is_lsr_transform = 1;
    5029           0 :                                 break;
    5030           0 :                         case LSR_UPDATE_TYPE_TRANSLATION:
    5031           0 :                                 info.far_ptr = (void *)&matrix_tmp;
    5032             :                                 field_type = SVG_Transform_Translate_datatype;
    5033             :                                 is_lsr_transform = 1;
    5034           0 :                                 break;
    5035          22 :                         default:
    5036          22 :                                 fieldIndex = gf_lsr_anim_type_to_attribute(att_type);
    5037          22 :                                 gf_node_get_attribute_by_tag(n, fieldIndex, 1, 0, &info);
    5038          22 :                                 field_type = info.fieldType;
    5039          22 :                                 break;
    5040             :                         }
    5041          24 :                         info.fieldType = field_type;
    5042          24 :                         if (is_lsr_transform) {
    5043             :                                 SVG_Transform *dest;
    5044           0 :                                 if (idx==-1) {
    5045           0 :                                         lsr_read_update_value(lsr, NULL, fieldIndex, field_type, info.far_ptr, 0);
    5046             :                                 } else {
    5047             :                                         assert(0);
    5048             :                                 }
    5049             : 
    5050             : 
    5051             : //                              fieldIndex = gf_node_get_attribute_by_tag((GF_Node*)n, TAG_SVG_ATT_transform, 1, 1, &info);
    5052           0 :                                 dest = (SVG_Transform *)info.far_ptr;
    5053           0 :                                 if (com_type) {
    5054             :                                         GF_Point2D scale, translate;
    5055             :                                         SVG_Point_Angle rotate;
    5056           0 :                                         if (gf_mx2d_decompose(&dest->mat, &scale, &rotate.angle, &translate)) {
    5057           0 :                                                 gf_mx2d_init(dest->mat);
    5058           0 :                                                 if (att_type==LSR_UPDATE_TYPE_SCALE) scale = matrix_tmp;
    5059           0 :                                                 else if (att_type==LSR_UPDATE_TYPE_TRANSLATION) translate = matrix_tmp;
    5060           0 :                                                 else if (att_type==LSR_UPDATE_TYPE_ROTATE) rotate = matrix_tmp_rot;
    5061             : 
    5062           0 :                                                 gf_mx2d_add_scale(&dest->mat, scale.x, scale.y);
    5063           0 :                                                 gf_mx2d_add_rotation(&dest->mat, 0, 0, rotate.angle);
    5064           0 :                                                 gf_mx2d_add_translation(&dest->mat, translate.x, translate.y);
    5065             :                                         }
    5066             :                                 }
    5067           0 :                                 else if (att_type==LSR_UPDATE_TYPE_SCALE) gf_mx2d_add_scale(&dest->mat, matrix_tmp.x, matrix_tmp.y);
    5068           0 :                                 else if (att_type==LSR_UPDATE_TYPE_TRANSLATION) gf_mx2d_add_translation(&dest->mat, matrix_tmp.x, matrix_tmp.y);
    5069           0 :                                 else if (att_type==LSR_UPDATE_TYPE_ROTATE) gf_mx2d_add_rotation(&dest->mat, 0, 0, matrix_tmp_rot.angle);
    5070             : 
    5071           0 :                                 gf_node_changed((GF_Node*)n, &info);
    5072             :                         }
    5073          24 :                         else if (com_type) {
    5074          24 :                                 if (text_content) {
    5075             :                                         GF_DOMText *t = NULL;
    5076           2 :                                         if (idx>=0) {
    5077           0 :                                                 if (com_type==LSR_UPDATE_INSERT) {
    5078           0 :                                                         t = gf_dom_new_text_node(n->sgprivate->scenegraph);
    5079           0 :                                                         gf_node_register((GF_Node *)t, n);
    5080           0 :                                                         gf_node_list_insert_child(&((GF_ParentNode *)n)->children, (GF_Node*)t, idx);
    5081             :                                                 } else {
    5082           0 :                                                         t = (GF_DOMText *) gf_node_list_get_child(((SVG_Element*)n)->children, idx);
    5083           0 :                                                         if (t->sgprivate->tag!=TAG_DOMText) t = NULL;
    5084             :                                                 }
    5085             :                                         } else {
    5086             :                                                 /*this is a replace, reset ALL node content*/
    5087           2 :                                                 gf_sg_parent_reset(n);
    5088           2 :                                                 t = gf_dom_add_text_node(n, NULL);
    5089             :                                         }
    5090           2 :                                         lsr_read_byte_align_string(lsr, t ? &t->textContent : NULL, "textContent");
    5091           2 :                                         gf_node_changed(n, NULL);
    5092          22 :                                 } else if (idx==-1) {
    5093          16 :                                         lsr_read_update_value(lsr, (GF_Node*)n, fieldIndex, field_type, info.far_ptr, n->sgprivate->tag);
    5094             :                                 } else {
    5095             :                                         Fixed *v1, *v2;
    5096             :                                         //SMIL_Time *t;
    5097             :                                         void *prev, *new_item;
    5098           6 :                                         void *tmp = lsr_read_update_value_indexed(lsr, (GF_Node*)n, field_type, info.far_ptr, idx, com_type==LSR_UPDATE_INSERT, 0, NULL);
    5099           6 :                                         switch (field_type) {
    5100             :                                         /*generic GF_List containers, no type translation needed*/
    5101           5 :                                         case SMIL_KeyTimes_datatype/*ITYPE_keyTime*/:
    5102             :                                         case SMIL_KeySplines_datatype/*ITYPE_float*/:
    5103             :                                         case SVG_Points_datatype/*ITYPE_point*/:
    5104             :                                         case SMIL_Times_datatype/*ITYPE_smil_time*/:
    5105           5 :                                                 new_item = gf_list_pop_front(*(GF_List **)tmp);
    5106           5 :                                                 if (com_type==LSR_UPDATE_INSERT) {
    5107           0 :                                                         gf_list_insert(*(SVG_Coordinates*)info.far_ptr, new_item, idx);
    5108             :                                                 } else {
    5109           5 :                                                         prev = gf_list_get(*(SVG_Coordinates*)info.far_ptr, idx);
    5110           5 :                                                         gf_free(prev);
    5111           5 :                                                         gf_list_rem(*(SVG_Coordinates*)info.far_ptr, idx);
    5112           5 :                                                         gf_list_insert(*(SVG_Coordinates*)info.far_ptr, new_item, idx);
    5113             :                                                 }
    5114           5 :                                                 gf_node_changed((GF_Node*)n, NULL);
    5115           5 :                                                 gf_list_del(*(GF_List **)tmp);
    5116           5 :                                                 gf_free(tmp);
    5117           5 :                                                 break;
    5118             :                                         /*list of floats - to check when implementing it...*/
    5119           1 :                                         case SMIL_KeyPoints_datatype/*ITYPE_0to1 - keyPoints*/:
    5120           1 :                                                 v1 = (Fixed *) gf_list_pop_front(*(GF_List **)tmp);
    5121           1 :                                                 v2 = (Fixed *) gf_list_pop_front(*(GF_List **)tmp);
    5122           1 :                                                 gf_list_del(*(GF_List **)tmp);
    5123           1 :                                                 gf_free(tmp);
    5124             : 
    5125           1 :                                                 if (com_type==LSR_UPDATE_INSERT) {
    5126           0 :                                                         gf_list_insert(*(SVG_Coordinates*)info.far_ptr, v1, idx);
    5127           0 :                                                         gf_list_insert(*(SVG_Coordinates*)info.far_ptr, v2, idx+1);
    5128             :                                                 } else {
    5129           1 :                                                         prev = gf_list_get(*(SVG_Coordinates*)info.far_ptr, idx);
    5130           1 :                                                         gf_free(prev);
    5131           1 :                                                         gf_list_rem(*(SVG_Coordinates*)info.far_ptr, idx);
    5132           1 :                                                         prev = gf_list_get(*(SVG_Coordinates*)info.far_ptr, idx);
    5133           1 :                                                         gf_free(prev);
    5134           1 :                                                         gf_list_rem(*(SVG_Coordinates*)info.far_ptr, idx);
    5135           1 :                                                         gf_list_insert(*(SVG_Coordinates*)info.far_ptr, v1, idx);
    5136           1 :                                                         gf_list_insert(*(SVG_Coordinates*)info.far_ptr, v2, idx);
    5137             :                                                 }
    5138           1 :                                                 gf_node_changed((GF_Node*)n, NULL);
    5139           1 :                                                 break;
    5140           0 :                                         case SVG_ViewBox_datatype:
    5141             :                                                 v1 = (Fixed*)tmp;
    5142           0 :                                                 switch (idx) {
    5143           0 :                                                 case 0:
    5144           0 :                                                         ((SVG_ViewBox*)info.far_ptr)->x = *v1;
    5145           0 :                                                         break;
    5146           0 :                                                 case 1:
    5147           0 :                                                         ((SVG_ViewBox*)info.far_ptr)->y = *v1;
    5148           0 :                                                         break;
    5149           0 :                                                 case 2:
    5150           0 :                                                         ((SVG_ViewBox*)info.far_ptr)->width = *v1;
    5151           0 :                                                         break;
    5152           0 :                                                 case 3:
    5153           0 :                                                         ((SVG_ViewBox*)info.far_ptr)->height = *v1;
    5154           0 :                                                         break;
    5155             :                                                 }
    5156           0 :                                                 gf_free(tmp);
    5157           0 :                                                 gf_node_changed((GF_Node*)n, NULL);
    5158           0 :                                                 break;
    5159           0 :                                         case SVG_StrokeDashArray_datatype:
    5160             :                                                 v1 = (Fixed*)tmp;
    5161           0 :                                                 if (com_type==LSR_UPDATE_INSERT) {
    5162           0 :                                                         SVG_StrokeDashArray*da = (SVG_StrokeDashArray*)info.far_ptr;
    5163             :                                                         /*use MFFloat for insert*/
    5164           0 :                                                         if (gf_sg_vrml_mf_insert(&da->array, GF_SG_VRML_MFFLOAT, (void*) &v2, idx)==GF_OK)
    5165           0 :                                                                 *v2 = *v1;
    5166             :                                                 } else {
    5167           0 :                                                         SVG_StrokeDashArray*da = (SVG_StrokeDashArray*)info.far_ptr;
    5168           0 :                                                         if (idx<(s32)da->array.count) da->array.vals[idx] = *v1;
    5169             :                                                 }
    5170           0 :                                                 gf_free(tmp);
    5171           0 :                                                 gf_node_changed((GF_Node*)n, NULL);
    5172           0 :                                                 break;
    5173           0 :                                         default:
    5174           0 :                                                 gf_free(tmp);
    5175           0 :                                                 break;
    5176             :                                         }
    5177             :                                 }
    5178             :                         } else {
    5179             :                                 GF_FieldInfo tmp;
    5180           0 :                                 tmp = info;
    5181           0 :                                 if (idx==-1) {
    5182           0 :                                         tmp.far_ptr = gf_svg_create_attribute_value(info.fieldType);
    5183           0 :                                         lsr_read_update_value(lsr, n, fieldIndex, field_type, tmp.far_ptr, n->sgprivate->tag);
    5184             :                                 } else {
    5185           0 :                                         tmp.far_ptr = lsr_read_update_value_indexed(lsr, n, field_type, NULL, idx, 0, 1, NULL);
    5186             :                                 }
    5187           0 :                                 gf_svg_attributes_add(&info, &tmp, &info, 0);
    5188           0 :                                 gf_svg_delete_attribute_value(info.fieldType, tmp.far_ptr, gf_node_get_graph(n));
    5189             :                         }
    5190             :                 }
    5191             :         }
    5192             :         /*copy from node*/
    5193          12 :         else if (operandNode && (op_att_type>=0)) {
    5194           3 :                 u32 opFieldIndex = gf_lsr_anim_type_to_attribute(op_att_type);
    5195           3 :                 if (com_list) {
    5196           2 :                         com = gf_sg_command_new(lsr->sg, com_type ? GF_SG_LSR_REPLACE : GF_SG_LSR_ADD);
    5197           2 :                         gf_list_add(com_list, com);
    5198           2 :                         com->node = n;
    5199           2 :                         gf_node_register(com->node, NULL);
    5200           2 :                         com->fromNodeID = op_idref;
    5201           2 :                         com->fromFieldIndex = opFieldIndex;
    5202           2 :                         field = gf_sg_command_field_new(com);
    5203           2 :                         field->pos = idx;
    5204           2 :                         field->fieldIndex = gf_lsr_anim_type_to_attribute(att_type);
    5205             :                 } else {
    5206             :                         u32 fieldIndex;
    5207             :                         GF_FieldInfo op_info;
    5208           1 :                         fieldIndex = gf_lsr_anim_type_to_attribute(att_type);
    5209           1 :                         gf_node_get_field(n, fieldIndex, &info);
    5210           1 :                         gf_node_get_field(operandNode, opFieldIndex, &op_info);
    5211           1 :                         if (com_type) {
    5212           1 :                                 gf_svg_attributes_copy(&info, &op_info, 0);
    5213             :                         } else {
    5214           0 :                                 gf_svg_attributes_add(&info, &op_info, &info, 0);
    5215             :                         }
    5216             :                 }
    5217             :         }
    5218             : 
    5219          90 :         lsr_read_any_attribute(lsr, NULL, 1);
    5220             : 
    5221             :         /*if not add*/
    5222          90 :         if (!com_type) return GF_OK;
    5223             : 
    5224             :         /*list replacement*/
    5225          90 :         GF_LSR_READ_INT(lsr, type, 1, "opt_group");
    5226          90 :         if (type) {
    5227             : 
    5228           9 :                 if (com_list) {
    5229             :                         u32 count;
    5230           6 :                         GF_ChildNodeItem *last = NULL;
    5231             : 
    5232           6 :                         if (com_type==LSR_UPDATE_INSERT) count = 1;
    5233           2 :                         else count = lsr_read_vluimsbf5(lsr, "count");
    5234             : 
    5235           6 :                         com = gf_sg_command_new(lsr->sg, (com_type==LSR_UPDATE_REPLACE) ? GF_SG_LSR_REPLACE : GF_SG_LSR_INSERT);
    5236           6 :                         gf_list_add(com_list, com);
    5237           6 :                         com->node = n;
    5238           6 :                         gf_node_register(com->node, NULL);
    5239           6 :                         field = gf_sg_command_field_new(com);
    5240           6 :                         field->pos = idx;
    5241             : 
    5242           6 :                         if (!count && (att_type==LSR_UPDATE_TYPE_TEXT_CONTENT)) {
    5243           0 :                                 field->fieldIndex = -1;
    5244           6 :                         } else if (count==1) {
    5245           4 :                                 field->new_node = lsr_read_update_content_model(lsr, (SVG_Element *) n);
    5246           4 :                                 gf_node_register(field->new_node, NULL);
    5247           4 :                                 if (att_type>=0) field->fieldIndex = gf_lsr_anim_type_to_attribute(att_type);
    5248             :                         } else {
    5249           2 :                                 field->field_ptr = &field->node_list;
    5250          82 :                                 while (count) {
    5251          78 :                                         GF_Node *new_node = lsr_read_update_content_model(lsr, (SVG_Element *) n);
    5252          78 :                                         gf_node_register(new_node, NULL);
    5253          78 :                                         gf_node_list_add_child_last(& field->node_list, new_node, &last);
    5254          78 :                                         count--;
    5255             :                                 }
    5256             :                         }
    5257             :                 } else {
    5258             :                         SVG_Element*elt = (SVG_Element*)n;
    5259           3 :                         GF_ChildNodeItem *last = NULL;
    5260             :                         u32 count;
    5261           3 :                         if (com_type==LSR_UPDATE_INSERT) count = 1;
    5262           1 :                         else count = lsr_read_vluimsbf5(lsr, "count");
    5263             : 
    5264           3 :                         if (com_type==LSR_UPDATE_REPLACE) {
    5265           1 :                                 if (idx>=0) {
    5266           0 :                                         GF_Node *new_node = gf_node_list_del_child_idx(&elt->children, idx);
    5267           0 :                                         if (new_node) gf_node_unregister(new_node, n);
    5268             :                                 } else {
    5269           1 :                                         gf_node_unregister_children(n, elt->children);
    5270           1 :                                         elt->children = NULL;
    5271             :                                 }
    5272             :                         }
    5273           3 :                         if ((com_type==LSR_UPDATE_INSERT) || (gf_lsr_anim_type_to_attribute(att_type) == TAG_LSR_ATT_children)) {
    5274           4 :                                 while (count) {
    5275           2 :                                         GF_Node *new_node = lsr_read_update_content_model(lsr, elt);
    5276           2 :                                         if (new_node) {
    5277           2 :                                                 if (idx>=0) {
    5278           2 :                                                         gf_node_list_insert_child(&elt->children, new_node, idx);
    5279             :                                                 } else {
    5280           0 :                                                         gf_node_list_add_child_last(&elt->children, new_node, &last);
    5281             :                                                 }
    5282           2 :                                                 gf_node_register(new_node, n);
    5283             :                                         }
    5284           2 :                                         count--;
    5285             :                                 }
    5286           2 :                                 gf_node_changed(n, NULL);
    5287             :                         }
    5288             :                         /*node replacement*/
    5289           1 :                         else if ((att_type==-1) && (count==1)) {
    5290           0 :                                 GF_Node *new_node = lsr_read_update_content_model(lsr, elt);
    5291           0 :                                 gf_node_replace((GF_Node*)elt, new_node, 0);
    5292             :                         }
    5293             :                 }
    5294             :         }
    5295             :         return GF_OK;
    5296             : }
    5297             : 
    5298           8 : static GF_Err lsr_read_delete(GF_LASeRCodec *lsr, GF_List *com_list)
    5299             : {
    5300             :         GF_FieldInfo info;
    5301             :         s32 idx, att_type;
    5302             :         u32 type, idref;
    5303             : 
    5304           8 :         att_type = lsr_get_attribute_name(lsr);
    5305             : 
    5306             :         idx = -2;
    5307           8 :         GF_LSR_READ_INT(lsr, type, 1, "has_index");
    5308           8 :         if (type) idx = (s32) lsr_read_vluimsbf5(lsr, "index");
    5309           8 :         idref = lsr_read_codec_IDREF_command(lsr, "ref");
    5310             : 
    5311           8 :         lsr_read_any_attribute(lsr, NULL, 1);
    5312           8 :         if (com_list) {
    5313             :                 GF_Command *com;
    5314           6 :                 com = gf_sg_command_new(lsr->sg, GF_SG_LSR_DELETE);
    5315           6 :                 gf_list_add(com_list, com);
    5316           6 :                 com->node = gf_sg_find_node(lsr->sg, idref);
    5317           6 :                 if (!com->node) {
    5318           2 :                         com->RouteID = idref;
    5319           2 :                         gf_list_add(lsr->unresolved_commands, com);
    5320             :                 } else {
    5321           4 :                         gf_node_register(com->node, NULL);
    5322             :                 }
    5323             : 
    5324           6 :                 if ((idx>=0) || (att_type>=0)) {
    5325           2 :                         GF_CommandField *field = gf_sg_command_field_new(com);
    5326           2 :                         field->pos = idx;
    5327           2 :                         if (att_type>=0) {
    5328           2 :                                 field->fieldIndex = gf_lsr_anim_type_to_attribute(att_type);
    5329           2 :                                 gf_node_get_field(com->node, field->fieldIndex, &info);
    5330           2 :                                 field->fieldType = info.fieldType;
    5331             :                         }
    5332             :                 }
    5333             :         } else {
    5334           2 :                 SVG_Element *elt = (SVG_Element *) gf_sg_find_node(lsr->sg, idref);
    5335           2 :                 if (!elt)
    5336             :                         return GF_NON_COMPLIANT_BITSTREAM;
    5337             : 
    5338           2 :                 if (att_type>=0) {
    5339           1 :                         s32 fieldIndex = gf_lsr_anim_type_to_attribute(att_type);
    5340           1 :                         gf_node_get_field((GF_Node*)elt, fieldIndex, &info);
    5341             :                         /*TODO implement*/
    5342             :                 }
    5343             :                 /*node deletion*/
    5344           1 :                 else if (idx>=0) {
    5345           0 :                         GF_Node *c = (GF_Node *)gf_node_list_get_child(elt->children, idx);
    5346           0 :                         if (c) {
    5347           0 :                                 if (!gf_node_list_del_child( & elt->children, c))
    5348             :                                         return GF_IO_ERR;
    5349           0 :                                 gf_node_unregister(c, (GF_Node*)elt);
    5350             :                         }
    5351             :                 } else {
    5352           1 :                         gf_node_replace((GF_Node*)elt, NULL, 0);
    5353             :                 }
    5354             :         }
    5355             :         return GF_OK;
    5356             : }
    5357             : 
    5358         162 : static GF_Err lsr_read_send_event(GF_LASeRCodec *lsr, GF_List *com_list)
    5359             : {
    5360             :         u32 flag, idref;
    5361             :         s32 detail;
    5362             :         SVG_Number x, y;
    5363             :         XMLEV_Event event;
    5364         162 :         lsr_read_event_type(lsr, &event);
    5365             : 
    5366             :         detail = 0;
    5367         162 :         GF_LSR_READ_INT(lsr, flag, 1, "has_intvalue");
    5368         162 :         if (flag) {
    5369          78 :                 GF_LSR_READ_INT(lsr, flag, 1, "sign");
    5370          78 :                 detail = lsr_read_vluimsbf5(lsr, "value");
    5371          78 :                 if (flag) detail = -detail;
    5372             : 
    5373          78 :                 switch (event.type) {
    5374          69 :                 case GF_EVENT_KEYDOWN:
    5375             :                 case GF_EVENT_LONGKEYPRESS:
    5376             :                 case GF_EVENT_REPEAT_KEY:
    5377             :                 case GF_EVENT_SHORT_ACCESSKEY:
    5378          69 :                         detail = lsr_to_dom_key(detail);
    5379          69 :                         break;
    5380             :                 default:
    5381             :                         break;
    5382             :                 }
    5383          84 :         }
    5384         162 :         x.value = y.value = 0;
    5385         162 :         GF_LSR_READ_INT(lsr, flag, 1, "has_pointvalue");
    5386         162 :         if (flag) {
    5387          18 :                 lsr_read_coordinate(lsr, &x, 0, "x");
    5388          18 :                 lsr_read_coordinate(lsr, &y, 0, "y");
    5389             :         }
    5390         162 :         idref = lsr_read_codec_IDREF_command(lsr, "idref");
    5391             : 
    5392         162 :         GF_LSR_READ_INT(lsr, flag, 1, "has_pointvalue");
    5393         162 :         if (flag) {
    5394           9 :                 lsr_read_byte_align_string(lsr, NULL, "string");
    5395             :         }
    5396         162 :         lsr_read_any_attribute(lsr, NULL, 1);
    5397             : 
    5398         162 :         if (!com_list) {
    5399             :                 GF_DOM_Event evt;
    5400          54 :                 GF_Node *target = gf_sg_find_node(lsr->sg, idref);
    5401          54 :                 if (!target) return GF_OK;
    5402             : 
    5403             :                 memset(&evt, 0, sizeof(GF_DOM_Event));
    5404          54 :                 evt.type = event.type;
    5405          54 :                 evt.detail = detail ? detail : (s32) event.parameter;
    5406          54 :                 evt.clientX = FIX2INT(x.value);
    5407          54 :                 evt.clientY = FIX2INT(y.value);
    5408          54 :                 gf_dom_event_fire(target, &evt);
    5409             : 
    5410             :         } else {
    5411         108 :                 GF_Command *com = gf_sg_command_new(lsr->sg, GF_SG_LSR_SEND_EVENT);
    5412         108 :                 gf_list_add(com_list, com);
    5413         108 :                 com->node = gf_sg_find_node(lsr->sg, idref);
    5414         108 :                 if (!com->node) {
    5415           0 :                         com->RouteID = idref;
    5416           0 :                         gf_list_add(lsr->unresolved_commands, com);
    5417             :                 } else {
    5418         108 :                         gf_node_register(com->node, NULL);
    5419             :                 }
    5420         108 :                 com->send_event_integer = detail ? detail : (s32) event.parameter;
    5421         108 :                 com->send_event_name = event.type;
    5422         108 :                 com->send_event_x = FIX2INT(x.value);
    5423         108 :                 com->send_event_y = FIX2INT(y.value);
    5424             :         }
    5425             :         return GF_OK;
    5426             : }
    5427             : 
    5428           0 : static GF_Err lsr_read_save(GF_LASeRCodec *lsr, GF_List *com_list)
    5429             : {
    5430             :         u32 i, count;
    5431           0 :         count = lsr_read_vluimsbf5(lsr, "nbIds");
    5432           0 :         for (i=0; i<count; i++) {
    5433             :                 u32 flag;
    5434           0 :                 lsr_read_vluimsbf5(lsr, "ref[[i]]");
    5435           0 :                 GF_LSR_READ_INT(lsr, flag, 1, "reserved");
    5436             : 
    5437           0 :                 lsr_get_attribute_name(lsr);
    5438             :         }
    5439           0 :         lsr_read_byte_align_string(lsr, NULL, "groupID");
    5440           0 :         lsr_read_any_attribute(lsr, NULL, 1);
    5441           0 :         return GF_OK;
    5442             : }
    5443             : 
    5444           0 : static GF_Err lsr_read_restore(GF_LASeRCodec *lsr, GF_List *com_list)
    5445             : {
    5446           0 :         lsr_read_byte_align_string(lsr, NULL, "groupID");
    5447           0 :         lsr_read_any_attribute(lsr, NULL, 1);
    5448           0 :         return GF_OK;
    5449             : }
    5450             : 
    5451           5 : void lsr_exec_command_list(GF_Node *node, void *par, Bool is_destroy)
    5452             : {
    5453             :         GF_DOMUpdates *up = (GF_DOMUpdates *)node;
    5454           5 :         GF_LASeRCodec *codec = (GF_LASeRCodec *)gf_node_get_private((GF_Node*)node);
    5455             : 
    5456           5 :         if (is_destroy || !up || (up->sgprivate->tag!=TAG_DOMUpdates)) return;
    5457             :         assert(!codec->bs);
    5458             : 
    5459           0 :         codec->info = lsr_get_stream(codec, 0);
    5460           0 :         if (!codec->info) return;
    5461           0 :         codec->coord_bits = codec->info->cfg.coord_bits;
    5462           0 :         codec->scale_bits = codec->info->cfg.scale_bits_minus_coord_bits;
    5463           0 :         codec->time_resolution = codec->info->cfg.time_resolution;
    5464           0 :         codec->color_scale = (1<<codec->info->cfg.colorComponentBits) - 1;
    5465           0 :         if (codec->info->cfg.resolution >= 0)
    5466           0 :                 codec->res_factor = INT2FIX(1<<codec->info->cfg.resolution);
    5467             :         else
    5468           0 :                 codec->res_factor = gf_divfix(FIX_ONE, INT2FIX(1 << (-codec->info->cfg.resolution)) );
    5469             : 
    5470           0 :         codec->bs = gf_bs_new(up->data, up->data_size, GF_BITSTREAM_READ);
    5471           0 :         codec->memory_dec = 0;
    5472           0 :         lsr_read_command_list(codec, NULL, NULL, 0);
    5473           0 :         gf_bs_del(codec->bs);
    5474           0 :         codec->bs = NULL;
    5475             : }
    5476             : 
    5477          14 : static GF_Err lsr_read_command_list(GF_LASeRCodec *lsr, GF_List *com_list, SVG_Element *cond, Bool first_imp)
    5478             : {
    5479             :         GF_Node *n;
    5480             :         GF_Command *com;
    5481             :         u32 i, type, count;
    5482             : 
    5483          14 :         if (cond) {
    5484             :                 u32 s_len;
    5485           5 :                 GF_DOMUpdates *up = gf_dom_add_updates_node((GF_Node*)cond);
    5486           5 :                 gf_node_set_callback_function((GF_Node*)up, lsr_exec_command_list);
    5487           5 :                 gf_node_set_private((GF_Node *) up, lsr);
    5488             : 
    5489           5 :                 s_len = lsr_read_vluimsbf5(lsr, NULL/*"encoding-length" - don't log to avoid corrupting the log order!!*/);
    5490           5 :                 gf_bs_align(lsr->bs);
    5491             :                 /*not in memory mode, direct decode*/
    5492           5 :                 if (!lsr->memory_dec) {
    5493             :                         com_list = NULL;
    5494           1 :                         up->data_size = s_len;
    5495           1 :                         up->data = (char*)gf_malloc(sizeof(char)*s_len);
    5496           1 :                         gf_bs_read_data(lsr->bs, up->data, s_len);
    5497           1 :                         goto exit;
    5498             :                 }
    5499             :                 /*memory mode, decode commands*/
    5500             :                 else {
    5501           4 :                         com_list = up->updates;
    5502             :                 }
    5503             :         }
    5504          13 :         count = lsr_read_vluimsbf5(lsr, "occ0");
    5505          13 :         if (first_imp) count++;
    5506             : 
    5507         282 :         for (i=0; i<count; i++) {
    5508         269 :                 GF_LSR_READ_INT(lsr, type, 4, "ch4");
    5509         269 :                 switch (type) {
    5510          90 :                 case LSR_UPDATE_ADD:
    5511             :                 case LSR_UPDATE_INSERT:
    5512             :                 case LSR_UPDATE_REPLACE:
    5513          90 :                         lsr_read_add_replace_insert(lsr, com_list, type);
    5514          90 :                         break;
    5515           8 :                 case LSR_UPDATE_DELETE:
    5516           8 :                         lsr_read_delete(lsr, com_list);
    5517           8 :                         break;
    5518           3 :                 case LSR_UPDATE_NEW_SCENE:
    5519             :                 case LSR_UPDATE_REFRESH_SCENE: /*TODO FIXME, depends on decoder state*/
    5520           3 :                         if (type==5) lsr_read_vluimsbf5(lsr, "time");
    5521           3 :                         lsr_read_any_attribute(lsr, NULL, 1);
    5522           3 :                         if (com_list) {
    5523           2 :                                 n = lsr_read_svg(lsr, 0);
    5524           2 :                                 if (!n)
    5525           0 :                                         return (lsr->last_error = GF_NON_COMPLIANT_BITSTREAM);
    5526           2 :                                 gf_node_register(n, NULL);
    5527           2 :                                 com = gf_sg_command_new(lsr->sg, (type==5) ? GF_SG_LSR_REFRESH_SCENE : GF_SG_LSR_NEW_SCENE);
    5528           2 :                                 com->node = n;
    5529           2 :                                 gf_list_add(com_list, com);
    5530             :                         } else {
    5531           1 :                                 gf_sg_reset(lsr->sg);
    5532           1 :                                 gf_sg_set_scene_size_info(lsr->sg, 0, 0, 1);
    5533           1 :                                 n = lsr_read_svg(lsr, 1);
    5534           1 :                                 if (!n)
    5535           0 :                                         return (lsr->last_error = GF_NON_COMPLIANT_BITSTREAM);
    5536             :                         }
    5537             :                         break;
    5538           0 :                 case LSR_UPDATE_TEXT_CONTENT:
    5539           0 :                         lsr_read_byte_align_string(lsr, NULL, "textContent");
    5540           0 :                         break;
    5541         162 :                 case LSR_UPDATE_SEND_EVENT:
    5542         162 :                         lsr_read_send_event(lsr, com_list);
    5543         162 :                         break;
    5544           0 :                 case LSR_UPDATE_RESTORE:
    5545           0 :                         lsr_read_restore(lsr, com_list);
    5546           0 :                         break;
    5547           0 :                 case LSR_UPDATE_SAVE:
    5548           0 :                         lsr_read_save(lsr, com_list);
    5549           0 :                         break;
    5550           6 :                 case LSR_UPDATE_EXTEND:
    5551             :                 {
    5552             :                         u32 extID;
    5553           6 :                         GF_LSR_READ_INT(lsr, extID, lsr->info->cfg.extensionIDBits, "extensionID");
    5554           6 :                         /*len = */lsr_read_vluimsbf5(lsr, "len");
    5555           6 :                         if (extID==2) {
    5556             :                                 u32 j, sub_count;
    5557           6 :                                 lsr_read_vluimsbf5(lsr, "reserved");
    5558           6 :                                 sub_count = lsr_read_vluimsbf5(lsr, "occ2");
    5559          12 :                                 for (j=0; j<sub_count; j++) {
    5560             :                                         u32 k, occ3;
    5561           6 :                                         GF_LSR_READ_INT(lsr, k, 2, "reserved");
    5562           6 :                                         occ3 = lsr_read_vluimsbf5(lsr, "occ3");
    5563          12 :                                         for (k=0; k<occ3; k++) {
    5564             :                                                 u32 sub_type, idref;
    5565           6 :                                                 GF_LSR_READ_INT(lsr, sub_type, 2, "ch5");
    5566           6 :                                                 switch (sub_type) {
    5567           6 :                                                 case 1:
    5568             :                                                 case 2:
    5569           6 :                                                         idref = lsr_read_codec_IDREF_command(lsr, "ref");
    5570             : 
    5571           6 :                                                         n = gf_sg_find_node(lsr->sg, idref);
    5572           6 :                                                         if (com_list) {
    5573           4 :                                                                 com = gf_sg_command_new(lsr->sg, (sub_type==1) ? GF_SG_LSR_ACTIVATE : GF_SG_LSR_DEACTIVATE);
    5574           4 :                                                                 if (n) {
    5575           4 :                                                                         com->node = n;
    5576           4 :                                                                         gf_node_register(n, NULL);
    5577             :                                                                 } else {
    5578           0 :                                                                         com->RouteID = idref;
    5579             :                                                                 }
    5580           4 :                                                                 gf_list_add(com_list, com);
    5581           2 :                                                         } else if (sub_type==1) {
    5582           1 :                                                                 if (!n) return GF_NON_COMPLIANT_BITSTREAM;
    5583           1 :                                                                 gf_node_activate(n);
    5584             :                                                         } else {
    5585           1 :                                                                 if (!n) return GF_NON_COMPLIANT_BITSTREAM;
    5586           1 :                                                                 gf_node_deactivate(n);
    5587             :                                                         }
    5588             :                                                         break;
    5589           0 :                                                 default:
    5590           0 :                                                         lsr_read_private_element_container(lsr);
    5591           0 :                                                         break;
    5592             :                                                 }
    5593             :                                         }
    5594             :                                 }
    5595             :                         }
    5596             :                 }
    5597             :                 break;
    5598           0 :                 default:
    5599           0 :                         return (lsr->last_error = GF_NON_COMPLIANT_BITSTREAM);
    5600             :                 }
    5601             :                 /*same-coding scope is command-based (to check in the spec)*/
    5602         269 :                 if (cond) {
    5603           8 :                         lsr->prev_g = NULL;
    5604           8 :                         lsr->prev_line = NULL;
    5605           8 :                         lsr->prev_path = NULL;
    5606           8 :                         lsr->prev_polygon = NULL;
    5607           8 :                         lsr->prev_rect = NULL;
    5608           8 :                         lsr->prev_text = NULL;
    5609           8 :                         lsr->prev_use = NULL;
    5610             :                 }
    5611             : 
    5612         269 :                 if (lsr->last_error)
    5613             :                         return lsr->last_error;
    5614             :         }
    5615          13 : exit:
    5616             :         /*script is align*/
    5617          14 :         if (cond) {
    5618           5 :                 gf_bs_align(lsr->bs);
    5619           5 :                 lsr_read_object_content(lsr, (SVG_Element*)cond);
    5620           5 :                 lsr->prev_g = NULL;
    5621           5 :                 lsr->prev_line = NULL;
    5622           5 :                 lsr->prev_path = NULL;
    5623           5 :                 lsr->prev_polygon = NULL;
    5624           5 :                 lsr->prev_rect = NULL;
    5625           5 :                 lsr->prev_text = NULL;
    5626           5 :                 lsr->prev_use = NULL;
    5627             :         }
    5628             :         return GF_OK;
    5629             : }
    5630             : 
    5631           9 : static GF_Err lsr_decode_laser_unit(GF_LASeRCodec *lsr, GF_List *com_list)
    5632             : {
    5633             :         GF_Err e;
    5634             :         Bool reset_encoding_context;
    5635             :         u32 flag, i, count = 0, privateDataIdentifierIndexBits;
    5636             : 
    5637           9 :         lsr->last_error = GF_OK;
    5638             : 
    5639             :         /*
    5640             :          *      1 - laser unit header
    5641             :          */
    5642           9 :         GF_LSR_READ_INT(lsr, reset_encoding_context, 1, "resetEncodingContext");
    5643           9 :         GF_LSR_READ_INT(lsr, flag, 1, "opt_group");
    5644           9 :         if (flag) lsr_read_extension(lsr, "ext");
    5645             : 
    5646             :         /*clean all tables*/
    5647           9 :         if (reset_encoding_context) {
    5648           0 :                 lsr->nb_cols = 0;
    5649           0 :                 if (lsr->col_table) gf_free(lsr->col_table);
    5650           0 :                 lsr->col_table = NULL;
    5651           0 :                 while (gf_list_count(lsr->font_table)) {
    5652           0 :                         char *ft = (char *)gf_list_last(lsr->font_table);
    5653           0 :                         gf_free(ft);
    5654           0 :                         gf_list_rem_last(lsr->font_table);
    5655             :                 }
    5656           0 :                 lsr->privateData_id_index = lsr->privateTag_index = 0;
    5657             :         }
    5658             : 
    5659             :         /*
    5660             :          *      2 - codecInitialisations
    5661             :          */
    5662             : 
    5663             :         /*
    5664             :          * 2.a - condecInitialization.color
    5665             :          */
    5666           9 :         GF_LSR_READ_INT(lsr, flag, 1, "colorInitialisation");
    5667             : 
    5668           9 :         if (flag) {
    5669           3 :                 count = lsr_read_vluimsbf5(lsr, "count");
    5670           3 :                 lsr->col_table = (LSRCol*)gf_realloc(lsr->col_table, sizeof(LSRCol)*(lsr->nb_cols+count));
    5671          48 :                 for (i=0; i<count; i++) {
    5672             :                         LSRCol c;
    5673          45 :                         GF_LSR_READ_INT(lsr, c.r, lsr->info->cfg.colorComponentBits, "red");
    5674          45 :                         GF_LSR_READ_INT(lsr, c.g, lsr->info->cfg.colorComponentBits, "green");
    5675          45 :                         GF_LSR_READ_INT(lsr, c.b, lsr->info->cfg.colorComponentBits, "blue");
    5676          45 :                         lsr->col_table[lsr->nb_cols+i] = c;
    5677             :                 }
    5678           3 :                 lsr->nb_cols += count;
    5679             :         }
    5680           9 :         lsr->colorIndexBits = gf_get_bit_size(lsr->nb_cols);
    5681             :         /*
    5682             :          * 2.b - condecInitialization.fonts
    5683             :          */
    5684           9 :         GF_LSR_READ_INT(lsr, flag, 1, "fontInitialisation");
    5685             :         count = 0;
    5686           9 :         if (flag) {
    5687           3 :                 count = lsr_read_vluimsbf5(lsr, "count");
    5688           9 :                 for (i=0; i<count; i++) {
    5689           6 :                         char *ft = NULL;
    5690           6 :                         lsr_read_byte_align_string(lsr, &ft, "font");
    5691           6 :                         gf_list_add(lsr->font_table, ft);
    5692             :                 }
    5693             :         }
    5694           9 :         lsr->fontIndexBits = gf_get_bit_size(count);
    5695             :         /*
    5696             :          * 2.c - condecInitialization.private
    5697             :          */
    5698           9 :         GF_LSR_READ_INT(lsr, flag, 1, "privateDataIdentifierInitialisation");
    5699             : 
    5700           9 :         if (flag) {
    5701           0 :                 count = lsr_read_vluimsbf5(lsr, "nbPrivateDataIdentifiers");
    5702           0 :                 for (i=0; i<count; i++) {
    5703           0 :                         lsr->privateData_id_index++;
    5704           0 :                         lsr_read_byte_align_string(lsr, NULL, "privateDataIdentifier");
    5705             :                 }
    5706             :         }
    5707             :         /*
    5708             :          * 2.d - condecInitialization.anyXML
    5709             :          */
    5710           9 :         GF_LSR_READ_INT(lsr, flag, 1, "anyXMLInitialisation");
    5711             : 
    5712           9 :         if (flag) {
    5713           0 :                 privateDataIdentifierIndexBits = gf_get_bit_size(lsr->privateData_id_index);
    5714           0 :                 count = lsr_read_vluimsbf5(lsr, "nbTags");
    5715           0 :                 for (i=0; i<count; i++) {
    5716           0 :                         lsr->privateTag_index++;
    5717           0 :                         if (i) {
    5718             :                                 /* uint(privateDataIdentifierIndexBits) = */
    5719           0 :                                 GF_LSR_READ_INT(lsr, flag, privateDataIdentifierIndexBits, "privateDataIdentifierIndex");
    5720           0 :                                 lsr_read_byte_align_string(lsr, NULL, "tag");
    5721             :                         }
    5722           0 :                         GF_LSR_READ_INT(lsr, flag, 1, "hasAttrs");
    5723           0 :                         if (flag) {
    5724           0 :                                 u32 k, c2 = lsr_read_vluimsbf5(lsr, "nbAttrNames");
    5725           0 :                                 for (k=0; k<c2; k++) {
    5726           0 :                                         if (!i) {
    5727             :                                                 /* uint(privateDataIdentifierIndexBits) = */
    5728           0 :                                                 GF_LSR_READ_INT(lsr, flag, privateDataIdentifierIndexBits, "privateDataIdentifierIndex");
    5729             :                                         }
    5730           0 :                                         lsr_read_byte_align_string(lsr, NULL, "tag");
    5731             :                                 }
    5732             :                         }
    5733             :                 }
    5734             :         }
    5735             :         /*
    5736             :          * 2.e - condecInitialization.extension
    5737             :          */
    5738           9 :         count = lsr_read_vluimsbf5(lsr, "countG");
    5739           9 :         for (i=0; i<count; i++) {
    5740           0 :                 /*u32 locID = */lsr_read_vluimsbf5(lsr, "binaryIdForThisStringID");
    5741           0 :                 lsr_read_byte_align_string(lsr, NULL, "stringID");
    5742             :         }
    5743           9 :         GF_LSR_READ_INT(lsr, flag, 1, "hasExtension");
    5744           9 :         if (flag) {
    5745           0 :                 u32 len = lsr_read_vluimsbf5(lsr, "len");
    5746           0 :                 u32 pos = gf_bs_get_bit_offset(lsr->bs);
    5747             : 
    5748           0 :                 count = lsr_read_vluimsbf5(lsr, "len");
    5749           0 :                 for (i=0; i<count; i++) {
    5750           0 :                         /*u32 locID = */lsr_read_vluimsbf5(lsr, "localStreamIdForThisGlobal");
    5751           0 :                         lsr_read_byte_align_string(lsr, NULL, "globalName");
    5752             :                 }
    5753           0 :                 pos = gf_bs_get_bit_offset(lsr->bs) - pos;
    5754           0 :                 if (len<pos)
    5755             :                         return GF_NON_COMPLIANT_BITSTREAM;
    5756             : 
    5757           0 :                 GF_LSR_READ_INT(lsr, flag, pos, "remainingData");
    5758             :         }
    5759             : 
    5760           9 :         e = lsr_read_command_list(lsr, com_list, NULL, 1);
    5761           9 :         GF_LSR_READ_INT(lsr, flag, 1, "opt_group");
    5762           9 :         if (flag) lsr_read_extension(lsr, "ext");
    5763             :         return e;
    5764             : }
    5765             : 
    5766             : #endif /*GPAC_DISABLE_LASER*/

Generated by: LCOV version 1.13