LCOV - code coverage report
Current view: top level - laser - lsr_enc.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2547 2828 90.1 %
Date: 2021-04-29 23:48:07 Functions: 117 119 98.3 %

          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             : 
      30             : #ifndef GPAC_DISABLE_LASER
      31             : 
      32             : 
      33             : #include <gpac/events.h>
      34             : 
      35             : 
      36             : #define GF_LSR_WRITE_INT(_codec, _val, _nbBits, _str)   {\
      37             :         gf_bs_write_int(_codec->bs, _val, _nbBits);  \
      38             :         assert(_str);\
      39             :         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] %s\t\t%d\t\t%d\n", _str, _nbBits, _val)); \
      40             :         }\
      41             :  
      42             : static void lsr_write_group_content(GF_LASeRCodec *lsr, SVG_Element *elt, Bool skip_object_content);
      43             : static GF_Err lsr_write_command_list(GF_LASeRCodec *lsr, GF_List *comList, SVG_Element *script, Bool first_implicit);
      44             : static GF_Err lsr_write_laser_unit(GF_LASeRCodec *lsr, GF_List *com_list, Bool reset_encoding_context);
      45             : static void lsr_write_point_sequence(GF_LASeRCodec *lsr, GF_List **pts, const char *name);
      46             : static void lsr_write_path_type(GF_LASeRCodec *lsr, SVG_PathData *path, const char *name);
      47             : 
      48             : GF_EXPORT
      49           2 : GF_LASeRCodec *gf_laser_encoder_new(GF_SceneGraph *graph)
      50             : {
      51             :         GF_LASeRCodec *tmp;
      52           2 :         GF_SAFEALLOC(tmp, GF_LASeRCodec);
      53           2 :         if (!tmp) return NULL;
      54           2 :         tmp->streamInfo = gf_list_new();
      55           2 :         tmp->font_table = gf_list_new();
      56           2 :         tmp->sg = graph;
      57           2 :         return tmp;
      58             : }
      59             : 
      60             : GF_EXPORT
      61           2 : void gf_laser_encoder_del(GF_LASeRCodec *codec)
      62             : {
      63             :         /*destroy all config*/
      64           6 :         while (gf_list_count(codec->streamInfo)) {
      65           2 :                 LASeRStreamInfo *p = (LASeRStreamInfo *)gf_list_last(codec->streamInfo);
      66           2 :                 gf_free(p);
      67           2 :                 gf_list_rem_last(codec->streamInfo);
      68             :         }
      69           2 :         gf_list_del(codec->streamInfo);
      70           2 :         if (codec->col_table) gf_free(codec->col_table);
      71           6 :         while (gf_list_count(codec->font_table)) {
      72           4 :                 char *ft = (char *)gf_list_last(codec->font_table);
      73           4 :                 gf_free(ft);
      74           4 :                 gf_list_rem_last(codec->font_table);
      75             :         }
      76           2 :         gf_list_del(codec->font_table);
      77           2 :         gf_free(codec);
      78           2 : }
      79             : 
      80             : 
      81             : static LASeRStreamInfo *lsr_get_stream(GF_LASeRCodec *codec, u16 ESID)
      82             : {
      83             :         LASeRStreamInfo *ptr;
      84          10 :         u32 i = 0;
      85          10 :         while ((ptr = (LASeRStreamInfo *)gf_list_enum(codec->streamInfo, &i))) {
      86           8 :                 if(ptr->ESID==ESID) return ptr;
      87             :         }
      88             :         return NULL;
      89             : }
      90             : 
      91             : GF_EXPORT
      92           2 : GF_Err gf_laser_encoder_new_stream(GF_LASeRCodec *codec, u16 ESID, GF_LASERConfig *cfg)
      93             : {
      94             :         LASeRStreamInfo *pInfo;
      95           2 :         if (lsr_get_stream(codec, ESID) != NULL) return GF_BAD_PARAM;
      96           2 :         GF_SAFEALLOC(pInfo, LASeRStreamInfo);
      97           2 :         if (!pInfo) return GF_OUT_OF_MEM;
      98           2 :         pInfo->ESID = ESID;
      99           2 :         memcpy(&pInfo->cfg, cfg, sizeof(GF_LASERConfig));
     100           2 :         if (!pInfo->cfg.time_resolution) pInfo->cfg.time_resolution = 1000;
     101           2 :         if (!pInfo->cfg.colorComponentBits) pInfo->cfg.colorComponentBits = 8;
     102           2 :         if (!pInfo->cfg.coord_bits) pInfo->cfg.coord_bits = 12;
     103           2 :         if (pInfo->cfg.resolution<-8) pInfo->cfg.resolution = (s8) -8;
     104           2 :         else if (pInfo->cfg.resolution>7) pInfo->cfg.resolution=7;
     105             : 
     106           2 :         gf_list_add(codec->streamInfo, pInfo);
     107           2 :         return GF_OK;
     108             : }
     109             : 
     110             : GF_EXPORT
     111           2 : GF_Err gf_laser_encoder_get_config(GF_LASeRCodec *codec, u16 ESID, u8 **out_data, u32 *out_data_length)
     112             : {
     113             :         GF_BitStream *bs;
     114           2 :         if (!codec || !out_data || !out_data_length) return GF_BAD_PARAM;
     115             : 
     116           2 :         codec->info = lsr_get_stream(codec, ESID);
     117           2 :         if (!codec->info) return GF_BAD_PARAM;
     118             : 
     119           2 :         bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     120           2 :         gf_bs_write_int(bs, codec->info->cfg.profile, 8);
     121           2 :         gf_bs_write_int(bs, codec->info->cfg.level, 8);
     122           2 :         gf_bs_write_int(bs, 0 /*codec->info->cfg.reserved*/, 3);
     123           2 :         gf_bs_write_int(bs, codec->info->cfg.pointsCodec, 2);
     124           2 :         gf_bs_write_int(bs, codec->info->cfg.pathComponents, 4);
     125           2 :         gf_bs_write_int(bs, codec->info->cfg.fullRequestHost, 1);
     126           2 :         if (codec->info->cfg.time_resolution != 1000) {
     127           0 :                 gf_bs_write_int(bs, 1, 1);
     128           0 :                 gf_bs_write_int(bs, codec->info->cfg.time_resolution , 16);
     129             :         } else {
     130           2 :                 gf_bs_write_int(bs, 0, 1);
     131             :         }
     132           2 :         gf_bs_write_int(bs, codec->info->cfg.colorComponentBits - 1, 4);
     133           2 :         if (codec->info->cfg.resolution<0)
     134           0 :                 gf_bs_write_int(bs, 16 + codec->info->cfg.resolution, 4);
     135             :         else
     136           2 :                 gf_bs_write_int(bs, codec->info->cfg.resolution, 4);
     137           2 :         gf_bs_write_int(bs, codec->info->cfg.coord_bits, 5);
     138           2 :         gf_bs_write_int(bs, codec->info->cfg.scale_bits_minus_coord_bits, 4);
     139           2 :         gf_bs_write_int(bs, codec->info->cfg.newSceneIndicator ? 1 : 0, 1);
     140           2 :         gf_bs_write_int(bs, 0, 3);
     141           2 :         gf_bs_write_int(bs, codec->info->cfg.extensionIDBits, 4);
     142             :         /*no extConfig*/
     143           2 :         gf_bs_write_int(bs, 0, 1);
     144             :         /*no extensions*/
     145           2 :         gf_bs_write_int(bs, 0, 1);
     146           2 :         gf_bs_align(bs);
     147           2 :         gf_bs_get_content(bs, out_data, out_data_length);
     148           2 :         gf_bs_del(bs);
     149           2 :         return GF_OK;
     150             : }
     151             : 
     152             : GF_EXPORT
     153           6 : GF_Err gf_laser_encode_au(GF_LASeRCodec *codec, u16 ESID, GF_List *command_list, Bool reset_context, u8 **out_data, u32 *out_data_length)
     154             : {
     155             :         GF_Err e;
     156           6 :         if (!codec || !command_list || !out_data || !out_data_length) return GF_BAD_PARAM;
     157             : 
     158           6 :         codec->info = lsr_get_stream(codec, ESID);
     159           6 :         if (!codec->info) return GF_BAD_PARAM;
     160           6 :         codec->coord_bits = codec->info->cfg.coord_bits;
     161           6 :         codec->scale_bits = codec->info->cfg.scale_bits_minus_coord_bits;
     162           6 :         codec->time_resolution = codec->info->cfg.time_resolution;
     163           6 :         codec->color_scale = (1<<codec->info->cfg.colorComponentBits) - 1;
     164           6 :         if (codec->info->cfg.resolution>=0)
     165           6 :                 codec->res_factor = gf_divfix(FIX_ONE, INT2FIX(1<<codec->info->cfg.resolution) );
     166             :         else
     167           0 :                 codec->res_factor = INT2FIX(1 << (-codec->info->cfg.resolution));
     168             : 
     169           6 :         codec->bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     170           6 :         e = lsr_write_laser_unit(codec, command_list, reset_context);
     171           6 :         if (!e) {
     172           6 :                 gf_bs_align(codec->bs);
     173           6 :                 gf_bs_get_content(codec->bs, out_data, out_data_length);
     174             :         }
     175           6 :         gf_bs_del(codec->bs);
     176           6 :         codec->bs = NULL;
     177           6 :         return e;
     178             : }
     179             : 
     180             : GF_EXPORT
     181           0 : GF_Err gf_laser_encoder_get_rap(GF_LASeRCodec *codec, u8 **out_data, u32 *out_data_length)
     182             : {
     183             :         GF_Err e;
     184           0 :         if (!codec->info) codec->info = (LASeRStreamInfo*)gf_list_get(codec->streamInfo, 0);
     185           0 :         codec->coord_bits = codec->info->cfg.coord_bits;
     186           0 :         codec->scale_bits = codec->info->cfg.scale_bits_minus_coord_bits;
     187           0 :         codec->time_resolution = codec->info->cfg.time_resolution;
     188           0 :         codec->color_scale = (1<<codec->info->cfg.colorComponentBits) - 1;
     189           0 :         if (codec->info->cfg.resolution>=0)
     190           0 :                 codec->res_factor = gf_divfix(FIX_ONE, INT2FIX(1<<codec->info->cfg.resolution) );
     191             :         else
     192           0 :                 codec->res_factor = INT2FIX(1 << (-codec->info->cfg.resolution));
     193             : 
     194           0 :         codec->bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     195           0 :         e = lsr_write_laser_unit(codec, NULL, GF_FALSE);
     196           0 :         if (e == GF_OK) gf_bs_get_content(codec->bs, out_data, out_data_length);
     197           0 :         gf_bs_del(codec->bs);
     198           0 :         codec->bs = NULL;
     199           0 :         return e;
     200             : }
     201             : 
     202        1020 : static void lsr_write_vluimsbf5(GF_LASeRCodec *lsr, u32 val, const char *name)
     203             : {
     204             :         u32 nb_words;
     205        1020 :         u32 nb_bits = val ? gf_get_bit_size(val) : 1;
     206        1020 :         nb_words = nb_bits / 4;
     207        1020 :         if (nb_bits%4) nb_words++;
     208             :         assert(nb_words * 4 >= nb_bits);
     209        1020 :         nb_bits = 4*nb_words;
     210        2526 :         while (nb_words) {
     211        1506 :                 nb_words--;
     212        1506 :                 gf_bs_write_int(lsr->bs, nb_words ? 1 : 0, 1);
     213             :         }
     214        1020 :         gf_bs_write_int(lsr->bs, val, nb_bits);
     215        1020 :         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] %s\t\t%d\t\t%d\n", name, nb_bits + (nb_bits/4), val));
     216        1020 : }
     217             : 
     218           2 : static void lsr_write_vluimsbf5_ex(GF_LASeRCodec *lsr, u32 val, u32 extra_words, const char *name)
     219             : {
     220             :         u32 nb_words;
     221           2 :         u32 nb_bits = val ? gf_get_bit_size(val) : 1;
     222           2 :         nb_words = nb_bits / 4;
     223           2 :         if (nb_bits%4) nb_words++;
     224           2 :         nb_words += extra_words;
     225             : 
     226             :         assert(nb_words * 4 >= nb_bits);
     227           2 :         nb_bits = 4*nb_words;
     228           8 :         while (nb_words) {
     229           6 :                 nb_words--;
     230           6 :                 gf_bs_write_int(lsr->bs, nb_words ? 1 : 0, 1);
     231             :         }
     232           2 :         gf_bs_write_int(lsr->bs, val, nb_bits);
     233           2 :         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] %s\t\t%d\t\t%d\n", name, nb_bits + (nb_bits/4), val));
     234           2 : }
     235             : 
     236           2 : static u32 lsr_get_vluimsbf5_size(u32 val, u32 extra_words)
     237             : {
     238             :         u32 nb_words;
     239           2 :         u32 nb_bits = val ? gf_get_bit_size(val) : 1;
     240           2 :         nb_words = nb_bits / 4;
     241           2 :         if (nb_bits%4) nb_words++;
     242           2 :         nb_words += extra_words;
     243           2 :         return 4*nb_words + nb_words;
     244             : }
     245             : 
     246         116 : static void lsr_write_vluimsbf8(GF_LASeRCodec *lsr, u32 val, const char *name)
     247             : {
     248             :         u32 nb_words;
     249         116 :         u32 nb_tot, nb_bits = val ? gf_get_bit_size(val) : 1;
     250         116 :         nb_words = nb_bits / 7;
     251         116 :         if (nb_bits%7) nb_words++;
     252             :         assert(nb_words * 7 >= nb_bits);
     253         116 :         nb_bits = nb_words * 7;
     254         116 :         nb_tot = nb_words+nb_bits;
     255         232 :         while (nb_words) {
     256         116 :                 nb_words--;
     257         116 :                 gf_bs_write_int(lsr->bs, nb_words ? 1 : 0, 1);
     258             :         }
     259         116 :         gf_bs_write_int(lsr->bs, val, nb_bits);
     260         116 :         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] %s\t\t%d\t\t%d\n", name, nb_tot, val));
     261         116 : }
     262             : 
     263           0 : static void lsr_write_extension(GF_LASeRCodec *lsr, char *data, u32 len, const char *name)
     264             : {
     265           0 :         if (!len) len = (u32) strlen(name);
     266           0 :         lsr_write_vluimsbf5(lsr, len, name);
     267           0 :         gf_bs_write_data(lsr->bs, data, len);
     268           0 : }
     269             : 
     270          56 : static void lsr_write_codec_IDREF(GF_LASeRCodec *lsr, XMLRI *href, const char *name)
     271             : {
     272             :         u32 nID = 0;
     273          56 :         if (href && href->target)
     274          54 :                 nID = gf_node_get_id((GF_Node *)href->target);
     275           2 :         else if (name[0]=='#') {
     276           0 :                 GF_Node *n = gf_sg_find_node_by_name(lsr->sg, (char *) name + 1);
     277           0 :                 if (n) nID = gf_node_get_id((GF_Node *)href->target);
     278           2 :         } else if (href)
     279           2 :                 nID = 1+href->lsr_stream_id;
     280             :         else
     281             :                 nID=1;
     282             :         assert(nID);
     283             : 
     284          56 :         lsr_write_vluimsbf5(lsr, nID-1, name);
     285          56 :         GF_LSR_WRITE_INT(lsr, 0, 1, "reserved");
     286          56 : }
     287             : 
     288         182 : static void lsr_write_codec_IDREF_Node(GF_LASeRCodec *lsr, GF_Node *href, const char *name)
     289             : {
     290         182 :         u32 nID = gf_node_get_id(href);
     291             :         assert(nID);
     292         182 :         lsr_write_vluimsbf5(lsr, nID-1, name);
     293         182 :         GF_LSR_WRITE_INT(lsr, 0, 1, "reserved");
     294         182 : }
     295             : 
     296           4 : static u32 lsr_get_IDREF_nb_bits(GF_LASeRCodec *lsr, GF_Node *href)
     297             : {
     298             :         u32 nb_bits, nb_words, nID;
     299             : 
     300           4 :         nID = gf_node_get_id(href);
     301             :         assert(nID);
     302             : 
     303           4 :         nb_bits = nID ? gf_get_bit_size(nID) : 1;
     304           4 :         nb_words = nb_bits / 4;
     305           4 :         if (nb_bits%4) nb_words++;
     306             :         assert(nb_words * 4 >= nb_bits);
     307           4 :         nb_bits = nb_words * 4;
     308           4 :         return nb_words+nb_bits /*IDREF part*/ + 1 /*reserevd bit*/;
     309             : }
     310             : 
     311         154 : static void lsr_write_fixed_16_8(GF_LASeRCodec *lsr, Fixed fix, const char *name)
     312             : {
     313             :         u32 val;
     314         154 :         if (fix<0) {
     315             : #ifdef GPAC_FIXED_POINT
     316             :                 val = (1<<24) + fix / 256;
     317             : #else
     318           2 :                 val = (1<<24) + FIX2INT(fix * 256);
     319             : #endif
     320             :         } else {
     321             : #ifdef GPAC_FIXED_POINT
     322             :                 val = fix/256;
     323             : #else
     324         152 :                 val = FIX2INT(fix*256);
     325             : #endif
     326             :         }
     327         154 :         val &= 0x00FFFFFF;
     328         154 :         GF_LSR_WRITE_INT(lsr, val, 24, name);
     329         154 : }
     330          24 : static void lsr_write_fixed_16_8i(GF_LASeRCodec *lsr, SVG_Number *n, const char *name)
     331             : {
     332          24 :         if (n->type==SVG_NUMBER_INHERIT) {
     333           0 :                 GF_LSR_WRITE_INT(lsr, 1, 1, name);
     334             :         } else {
     335          24 :                 GF_LSR_WRITE_INT(lsr, 0, 1, name);
     336          24 :                 lsr_write_fixed_16_8(lsr, n->value, name);
     337             :         }
     338          24 : }
     339             : 
     340          14 : static s32 lsr_get_font_index(GF_LASeRCodec *lsr, SVG_FontFamily *font)
     341             : {
     342             :         u32 i, count;
     343          14 :         if ((font->type!=SVG_FONTFAMILY_VALUE) || !font->value) return -1;
     344          10 :         count = gf_list_count(lsr->font_table);
     345           2 :         for (i=0; i<count; i++) {
     346          12 :                 char *n = (char *)gf_list_get(lsr->font_table, i);
     347          12 :                 if (!strcmp(n, font->value)) return (s32) i;
     348             :         }
     349             :         return -2;
     350             : }
     351             : 
     352         220 : static s32 lsr_get_col_index(GF_LASeRCodec *lsr, SVG_Color *color)
     353             : {
     354             :         u16 r, g, b;
     355             :         u32 i;
     356         220 :         if (color->type!=SVG_COLOR_RGBCOLOR) return -1;
     357         210 :         r = FIX2INT(color->red*lsr->color_scale);
     358         210 :         g = FIX2INT(color->green*lsr->color_scale);
     359         210 :         b = FIX2INT(color->blue*lsr->color_scale);
     360        1278 :         for (i=0; i<lsr->nb_cols; i++) {
     361        1248 :                 LSRCol *c = &lsr->col_table[i];
     362        1248 :                 if ((c->r == r) && (c->g == g) && (c->b == b)) return (s32) i;
     363             :         }
     364             :         return -2;
     365             : }
     366             : 
     367           6 : static void lsr_write_line_increment_type(GF_LASeRCodec *lsr, SVG_Number *li, const char *name)
     368             : {
     369           6 :         if (li->type==SVG_NUMBER_INHERIT) {
     370           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "choice");
     371           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "inherit");
     372           4 :         } else if (li->type==SVG_NUMBER_AUTO) {
     373           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "choice");
     374           2 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "auto");
     375             :         } else {
     376           2 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "choice");
     377           2 :                 lsr_write_fixed_16_8(lsr, li->value, "line-increment-value");
     378             :         }
     379           6 : }
     380             : 
     381         116 : static void lsr_write_byte_align_string(GF_LASeRCodec *lsr, char *str, const char *name)
     382             : {
     383         116 :         u32 len = str ? (u32) strlen(str) : 0;
     384         116 :         gf_bs_align(lsr->bs);
     385         116 :         lsr_write_vluimsbf8(lsr, len, "len");
     386         116 :         if (len) gf_bs_write_data(lsr->bs, str, len);
     387         116 :         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] %s\t\t%d\t\t%s\n", name, 8*len, str ? str : ""));
     388         116 : }
     389           8 : static void lsr_write_byte_align_string_list(GF_LASeRCodec *lsr, GF_List *l, const char *name, Bool is_iri)
     390             : {
     391             :         char text[4096];
     392           8 :         u32 i, count = gf_list_count(l);
     393           8 :         text[0] = 0;
     394          28 :         for (i=0; i<count; i++) {
     395             :                 char *str;
     396          12 :                 if (is_iri) {
     397           4 :                         XMLRI *iri = (XMLRI *)gf_list_get(l, i);
     398           4 :                         str = iri->string;
     399             :                 } else {
     400           8 :                         str = (char*)gf_list_get(l, i);
     401             :                 }
     402          12 :                 strncat(text, str, 4096-strlen(text)-1);
     403          12 :                 if (i+1<count) strcat(text, ";");
     404             :         }
     405           8 :         lsr_write_byte_align_string(lsr, text, name);
     406           8 : }
     407             : 
     408          76 : static void lsr_write_any_uri(GF_LASeRCodec *lsr, XMLRI *iri, const char *name)
     409             : {
     410             :         Bool is_iri = GF_FALSE;
     411             : 
     412          76 :         if (iri->type==XMLRI_STRING) {
     413             :                 is_iri = GF_TRUE;
     414          26 :                 if (iri->string[0]=='#') {
     415           8 :                         iri->target = (SVG_Element*)gf_sg_find_node_by_name(lsr->sg, iri->string+1);
     416           8 :                         if (iri->target) {
     417             :                                 is_iri = GF_FALSE;
     418           2 :                                 iri->type = XMLRI_ELEMENTID;
     419             :                         }
     420             :                 }
     421             :         }
     422             : 
     423          76 :         GF_LSR_WRITE_INT(lsr, is_iri, 1, "hasUri");
     424          76 :         if (is_iri) {
     425          24 :                 if (!iri->string || strnicmp(iri->string, "data:", 5)) {
     426          22 :                         lsr_write_byte_align_string(lsr, iri->string, "uri");
     427          22 :                         GF_LSR_WRITE_INT(lsr, 0, 1, "hasData");
     428             :                 } else {
     429             :                         u32 len;
     430           2 :                         char *sep = strchr(iri->string, ',');
     431           2 :                         sep[0] = 0;
     432           2 :                         lsr_write_byte_align_string(lsr, iri->string, "uri");
     433           2 :                         sep[0] = ',';
     434           2 :                         len = (u32) strlen(sep+1);
     435           2 :                         GF_LSR_WRITE_INT(lsr, 1, 1, "hasData");
     436           2 :                         lsr_write_vluimsbf5(lsr, len, "len");
     437           2 :                         gf_bs_write_data(lsr->bs, sep+1, len);
     438             :                 }
     439             :         }
     440          76 :         GF_LSR_WRITE_INT(lsr, (iri->type==XMLRI_ELEMENTID) ? 1 : 0, 1, "hasID");
     441          76 :         if (iri->type==XMLRI_ELEMENTID) lsr_write_codec_IDREF(lsr, iri, "idref");
     442             : 
     443          76 :         GF_LSR_WRITE_INT(lsr, (iri->type==XMLRI_STREAMID) ? 1 : 0, 1, "hasStreamID");
     444          76 :         if (iri->type==XMLRI_STREAMID)
     445           2 :                 lsr_write_codec_IDREF(lsr, iri, "href");
     446          76 : }
     447             : 
     448         130 : static void lsr_write_paint(GF_LASeRCodec *lsr, SVG_Paint *paint, const char *name)
     449             : {
     450         130 :         if ((paint->type==SVG_PAINT_COLOR) && (paint->color.type==SVG_COLOR_RGBCOLOR)) {
     451             :                 s32 idx;
     452         106 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "hasIndex");
     453         106 :                 idx = lsr_get_col_index(lsr, &paint->color);
     454         106 :                 if (idx<0) {
     455             :                         idx = 0;
     456           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[LASeR] color not in colorTable\n"));
     457             :                 }
     458         106 :                 GF_LSR_WRITE_INT(lsr, (u32) idx, lsr->colorIndexBits, name);
     459             :         } else {
     460          24 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "hasIndex");
     461             : 
     462          24 :                 switch (paint->type) {
     463           8 :                 case SVG_PAINT_INHERIT:
     464           8 :                         GF_LSR_WRITE_INT(lsr, 0, 2, "enum");
     465           8 :                         GF_LSR_WRITE_INT(lsr, 0, 2, "choice");
     466             :                         break;
     467           8 :                 case SVG_PAINT_NONE:
     468           8 :                         GF_LSR_WRITE_INT(lsr, 0, 2, "enum");
     469           8 :                         GF_LSR_WRITE_INT(lsr, 2, 2, "choice");
     470             :                         break;
     471           2 :                 case SVG_PAINT_COLOR:
     472           2 :                         if (paint->color.type == SVG_COLOR_CURRENTCOLOR) {
     473           2 :                                 GF_LSR_WRITE_INT(lsr, 0, 2, "enum");
     474           2 :                                 GF_LSR_WRITE_INT(lsr, 1, 2, "choice");
     475             :                         } else {
     476           0 :                                 GF_LSR_WRITE_INT(lsr, 2, 2, "enum");
     477           0 :                                 lsr_write_byte_align_string(lsr, (char*)gf_svg_get_system_paint_server_name(paint->color.type), "systemsPaint");
     478             :                         }
     479             :                         break;
     480           6 :                 case SVG_PAINT_URI:
     481           6 :                         GF_LSR_WRITE_INT(lsr, 1, 2, "enum");
     482           6 :                         lsr_write_any_uri(lsr, &paint->iri, "uri");
     483           6 :                         break;
     484             : 
     485           0 :                 default:
     486           0 :                         GF_LSR_WRITE_INT(lsr, 3, 2, "enum");
     487           0 :                         lsr_write_extension(lsr, "ERROR", 5, "colorExType0");
     488           0 :                         break;
     489             :                 }
     490             :         }
     491         130 : }
     492             : 
     493             : #ifdef GPAC_UNUSED_FUNC
     494             : static void lsr_write_private_element_container(GF_LASeRCodec *lsr)
     495             : {
     496             :         /*NO PRIVATE DATA ON ENCODING YET*/
     497             :         assert(0);
     498             : }
     499             : 
     500             : static void lsr_write_private_att_class(GF_LASeRCodec *lsr)
     501             : {
     502             :         /*NO PRIVATE DATA ON ENCODING YET*/
     503             :         assert(0);
     504             : }
     505             : 
     506             : static void lsr_write_extend_class(GF_LASeRCodec *lsr, char *data, u32 len, const char *name)
     507             : {
     508             :         u32 i=0;
     509             :         GF_LSR_WRITE_INT(lsr, 0, lsr->info->cfg.extensionIDBits, "reserved");
     510             :         lsr_write_vluimsbf5(lsr, len, "len");
     511             :         while (i<len) {
     512             :                 gf_bs_write_int(lsr->bs, data[i], 8);
     513             :                 i++;
     514             :         }
     515             : }
     516             : 
     517             : static void lsr_write_private_attr_container(GF_LASeRCodec *lsr, u32 index, const char *name)
     518             : {
     519             :         assert(0);
     520             : }
     521             : 
     522             : static Bool lsr_float_list_equal(GF_List *l1, GF_List *l2)
     523             : {
     524             :         u32 i, count = gf_list_count(l1);
     525             :         if (count != gf_list_count(l2)) return 0;
     526             :         for (i=0; i<count; i++) {
     527             :                 Fixed *v1 = (Fixed *)gf_list_get(l1, i);
     528             :                 Fixed *v2 = (Fixed *)gf_list_get(l2, i);
     529             :                 if (*v1 != *v2) return 0;
     530             :         }
     531             :         return 1;
     532             : }
     533             : #endif /*GPAC_UNUSED_FUNC*/
     534             : 
     535             : 
     536             : 
     537         388 : static void lsr_write_any_attribute(GF_LASeRCodec *lsr, SVG_Element *node, Bool skippable)
     538             : {
     539             : #if 1
     540         388 :         if (skippable) GF_LSR_WRITE_INT(lsr, 0, 1, "has_attrs");
     541             : #else
     542             :         if (skippable) GF_LSR_WRITE_INT(lsr, 1, 1, "has_attrs");
     543             :         /*
     544             :                         do () {
     545             :                                 GF_LSR_WRITE_INT(lsr, 0, lsr->info->cfg.extensionIDBits, "reserved");
     546             :                                 lsr_write_vluimsbf5(lsr, 0, "len");//len in BITS
     547             :                                 GF_LSR_WRITE_INT(lsr, 0, 0, "reserved_val");
     548             :                         } while ()
     549             :         */
     550             : #endif
     551         388 : }
     552             : 
     553         316 : static void lsr_write_private_attributes(GF_LASeRCodec *lsr, SVG_Element *elt)
     554             : {
     555             :         if (1) {
     556         316 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "has_private_attr");
     557             :         } else {
     558             :                 GF_LSR_WRITE_INT(lsr, 1, 1, "has_private_attr");
     559             : #ifdef GPAC_UNUSED_FUNC
     560             :                 lsr_write_private_att_class(lsr);
     561             : #endif /*GPAC_UNUSED_FUNC*/
     562             :         }
     563         316 : }
     564          12 : static void lsr_write_string_attribute(GF_LASeRCodec *lsr, char *class_attr, char *name)
     565             : {
     566          12 :         if (class_attr) {
     567           0 :                 GF_LSR_WRITE_INT(lsr, 1, 1, name);
     568           0 :                 lsr_write_byte_align_string(lsr, class_attr, name);
     569             :         } else {
     570          12 :                 GF_LSR_WRITE_INT(lsr, 0, 1, name);
     571             :         }
     572          12 : }
     573         354 : static void lsr_write_id(GF_LASeRCodec *lsr, GF_Node *n)
     574             : {
     575         354 :         u32 id = gf_node_get_id(n);
     576         354 :         if (id) {
     577          74 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "has_id");
     578          74 :                 lsr_write_vluimsbf5(lsr, id-1, "ID");
     579             : #if TODO_LASER_EXTENSIONS
     580             :                 if (0) {
     581             :                         GF_LSR_WRITE_INT(lsr, 1, 1, "reserved");
     582             :                         lsr_write_vluimsbf5(lsr, reserved_len, "len");
     583             :                         GF_LSR_WRITE_INT(lsr, 0, reserved_len, "reserved");
     584             :                 } else
     585             : #endif
     586          74 :                         GF_LSR_WRITE_INT(lsr, 0, 1, "reserved");
     587             :         } else {
     588         280 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "has_id");
     589             :         }
     590         354 : }
     591             : 
     592         816 : static u32 lsr_translate_coords(GF_LASeRCodec *lsr, Fixed x, u32 nb_bits)
     593             : {
     594             :         s32 res, max;
     595             : 
     596         816 :         if (!nb_bits) return 0;
     597             : 
     598         816 :         res = FIX2INT( gf_divfix(x, lsr->res_factor) );
     599             :         /*don't loose too much*/
     600         816 :         if (!res && x) {
     601           0 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] resolution factor %g too small to allow coding of %g - adjusting to smallest integer!\n", lsr->res_factor, FIX2FLT(x) ));
     602           0 :                 res = (x>0) ? 1 : -1;
     603             :         }
     604         816 :         if (nb_bits>=32)
     605             :                 max = 0xFFFFFFFF;
     606             :         else
     607         816 :                 max = (1<<(nb_bits-1)) - 1;
     608             : 
     609         816 :         if (res>=0) {
     610         702 :                 if (res > max) {
     611           0 :                         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] nb_bits %d not large enough to encode positive number %g!\n", nb_bits, FIX2FLT(x) ));
     612             :                         res = max;
     613             :                 }
     614             :                 assert( ! (res & (1<<(nb_bits-1)) ));
     615         702 :                 return (u32) res;
     616             :         }
     617         114 :         res += 1<<(nb_bits);
     618         114 :         if (res<=max) {
     619           0 :                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] nb_bits %d not large enough to encode negative number %g!\n", nb_bits, FIX2FLT(x) ));
     620           0 :                 res = max+1;
     621             :         }
     622             :         assert( res & (1<<(nb_bits-1)) );
     623         114 :         return res;
     624             : }
     625             : 
     626          20 : static u32 lsr_translate_scale(GF_LASeRCodec *lsr, Fixed v)
     627             : {
     628             :         s32 res;
     629             :         /*always 8 bits for fractional part*/
     630          20 :         if (ABS(v) * 256 < 1) v = 0;
     631          20 :         v = v*256;
     632          20 :         if (v<0) {
     633           4 :                 res = FIX2INT(v) + (1<<lsr->coord_bits);
     634           4 :                 if (res<0) GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[LASeR] nb_bits %d not large enough to encode negative number %d!\n", lsr->coord_bits, res));
     635           4 :                 return res;
     636             :         }
     637          16 :         res = FIX2INT(v);
     638          16 :         if (res & (1<<(lsr->coord_bits-1)) ) {
     639           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[LASeR] nb_bits %d not large enough to encode positive number %d!\n", lsr->coord_bits, res));
     640             :         }
     641          16 :         return res;
     642             : }
     643          14 : static void lsr_write_matrix(GF_LASeRCodec *lsr, SVG_Transform *mx)
     644             : {
     645             :         u32 res;
     646          14 :         if (mx->is_ref) {
     647           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "isNotMatrix");
     648           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "isRef");
     649           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "hasXY");
     650           2 :                 lsr_write_fixed_16_8(lsr, mx->mat.m[2], "valueX");
     651           2 :                 lsr_write_fixed_16_8(lsr, mx->mat.m[5], "valueY");
     652             :         } else {
     653          12 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "isNotMatrix");
     654          12 :                 lsr->coord_bits += lsr->scale_bits;
     655             : 
     656          12 :                 if ((mx->mat.m[0]!=FIX_ONE) || (mx->mat.m[4]!=FIX_ONE)) {
     657           6 :                         GF_LSR_WRITE_INT(lsr, 1, 1, "xx_yy_present");
     658           6 :                         res = lsr_translate_scale(lsr, mx->mat.m[0]);
     659           6 :                         GF_LSR_WRITE_INT(lsr, res, lsr->coord_bits, "xx");
     660           6 :                         res = lsr_translate_scale(lsr, mx->mat.m[4]);
     661           6 :                         GF_LSR_WRITE_INT(lsr, res, lsr->coord_bits, "yy");
     662             :                 } else {
     663           6 :                         GF_LSR_WRITE_INT(lsr, 0, 1, "xx_yy_present");
     664             :                 }
     665          12 :                 if (mx->mat.m[1] || mx->mat.m[3]) {
     666           4 :                         GF_LSR_WRITE_INT(lsr, 1, 1, "xy_yx_present");
     667           4 :                         res = lsr_translate_scale(lsr, mx->mat.m[1]);
     668           4 :                         GF_LSR_WRITE_INT(lsr, res, lsr->coord_bits, "xy");
     669           4 :                         res = lsr_translate_scale(lsr, mx->mat.m[3]);
     670           4 :                         GF_LSR_WRITE_INT(lsr, res, lsr->coord_bits, "yx");
     671             :                 } else {
     672           8 :                         GF_LSR_WRITE_INT(lsr, 0, 1, "xy_yx_present");
     673             :                 }
     674             : 
     675          12 :                 if (mx->mat.m[2] || mx->mat.m[5]) {
     676           8 :                         GF_LSR_WRITE_INT(lsr, 1, 1, "xz_yz_present");
     677           8 :                         res = lsr_translate_coords(lsr, mx->mat.m[2], lsr->coord_bits);
     678           8 :                         GF_LSR_WRITE_INT(lsr, res, lsr->coord_bits, "xz");
     679           8 :                         res = lsr_translate_coords(lsr, mx->mat.m[5], lsr->coord_bits);
     680           8 :                         GF_LSR_WRITE_INT(lsr, res, lsr->coord_bits, "yz");
     681             :                 } else {
     682           4 :                         GF_LSR_WRITE_INT(lsr, 0, 1, "xz_yz_present");
     683             :                 }
     684          12 :                 lsr->coord_bits -= lsr->scale_bits;
     685             :         }
     686          14 : }
     687             : 
     688          34 : static void lsr_write_fixed_clamp(GF_LASeRCodec *lsr, Fixed f, const char *name)
     689             : {
     690             : #ifdef GPAC_FIXED_POINT
     691             :         s32 val = f >> 8;
     692             : #else
     693          34 :         s32 val = (u32) (255 * f);
     694             : #endif
     695          34 :         if (val<0) val = 0;
     696          34 :         else if (val>255) val = 255;
     697          34 :         GF_LSR_WRITE_INT(lsr, (u32) val, 8, name);
     698          34 : }
     699             : 
     700         152 : u32 dom_to_lsr_key(u32 dom_k)
     701             : {
     702         152 :         switch (dom_k) {
     703             :         case GF_KEY_STAR:
     704             :                 return 0;
     705           6 :         case GF_KEY_0:
     706           6 :                 return 1;
     707          12 :         case GF_KEY_1:
     708          12 :                 return 2;
     709           6 :         case GF_KEY_2:
     710           6 :                 return 3;
     711           6 :         case GF_KEY_3:
     712           6 :                 return 4;
     713          12 :         case GF_KEY_4:
     714          12 :                 return 5;
     715           6 :         case GF_KEY_5:
     716           6 :                 return 6;
     717           6 :         case GF_KEY_6:
     718           6 :                 return 7;
     719           6 :         case GF_KEY_7:
     720           6 :                 return 8;
     721           6 :         case GF_KEY_8:
     722           6 :                 return 9;
     723           6 :         case GF_KEY_9:
     724           6 :                 return 10;
     725           6 :         case GF_KEY_DOWN:
     726           6 :                 return 12;
     727           6 :         case GF_KEY_LEFT:
     728           6 :                 return 14;
     729           6 :         case GF_KEY_RIGHT:
     730           6 :                 return 16;
     731          12 :         case GF_KEY_UP:
     732          12 :                 return 20;
     733             :         /*WHAT IS ANY_KEY (11) ??*/
     734          12 :         case GF_KEY_ENTER:
     735             :         case GF_KEY_EXECUTE:
     736          12 :                 return 13;
     737           6 :         case GF_KEY_ESCAPE:
     738           6 :                 return 15;
     739           6 :         case GF_KEY_NUMBER:
     740           6 :                 return 17;
     741           6 :         case GF_KEY_CELL_SOFT1:
     742           6 :                 return 18;
     743           6 :         case GF_KEY_CELL_SOFT2:
     744           6 :                 return 19;
     745           8 :         default:
     746           8 :                 return 100;
     747             :         }
     748             : }
     749         112 : static void lsr_write_event_type(GF_LASeRCodec *lsr, u32 evtType, u32 evtParam)
     750             : {
     751             :         u32 force_string = 0;
     752             :         switch (evtType) {
     753          52 :         case GF_EVENT_KEYDOWN:
     754             :         case GF_EVENT_LONGKEYPRESS:
     755             :         case GF_EVENT_REPEAT_KEY:
     756             :         case GF_EVENT_SHORT_ACCESSKEY:
     757          52 :                 if (dom_to_lsr_key(evtParam)==100) force_string = 2;
     758             :                 break;
     759             :         case GF_EVENT_BEGIN:
     760             :         case GF_EVENT_END:
     761             :                 force_string = 1;
     762             :                 break;
     763             :         case GF_EVENT_REPEAT:
     764             :                 force_string = 1;
     765             :                 break;
     766             :         }
     767             : 
     768             :         if (force_string) {
     769             :                 char szName[1024];
     770           4 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "choice");
     771           4 :                 if (evtParam) {
     772           2 :                         if (force_string==2) {
     773           2 :                                 sprintf(szName, "%s(%s)", gf_dom_event_get_name(evtType), gf_dom_get_key_name(evtParam) );
     774             :                         } else {
     775           0 :                                 sprintf(szName, "%s(%d)", gf_dom_event_get_name(evtType), evtParam);
     776             :                         }
     777             :                 } else {
     778           2 :                         sprintf(szName, "%s", gf_dom_event_get_name(evtType));
     779             :                 }
     780           4 :                 lsr_write_byte_align_string(lsr, szName, "evtString");
     781             :         } else {
     782         108 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "choice");
     783         108 :                 switch (evtType) {
     784           2 :                 case GF_EVENT_ABORT:
     785           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_abort, 6, "event");
     786             :                         break;
     787           2 :                 case GF_EVENT_ACTIVATE:
     788           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_activate, 6, "event");
     789             :                         break;
     790           2 :                 case GF_EVENT_ACTIVATED:
     791           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_activatedEvent, 6, "event");
     792             :                         break;
     793           2 :                 case GF_EVENT_BEGIN:/*SPEC IS BROKEN, CANNOT ENCODE elt.begin !! */
     794             :                 case GF_EVENT_BEGIN_EVENT:
     795           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_beginEvent, 6, "event");
     796             :                         break;
     797           2 :                 case GF_EVENT_CLICK:
     798           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_click, 6, "event");
     799             :                         break;
     800           2 :                 case GF_EVENT_DEACTIVATED:
     801           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_deactivatedEvent, 6, "event");
     802             :                         break;
     803           2 :                 case GF_EVENT_END:/*SPEC IS BROKEN, CANNOT ENCODE elt.end !! */
     804             :                 case GF_EVENT_END_EVENT:
     805           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_endEvent, 6, "event");
     806             :                         break;
     807           2 :                 case GF_EVENT_ERROR:
     808           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_error, 6, "event");
     809             :                         break;
     810           2 :                 case GF_EVENT_EXECUTION_TIME:
     811           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_executionTime, 6, "event");
     812             :                         break;
     813           2 :                 case GF_EVENT_FOCUSIN:
     814           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_focusin, 6, "event");
     815             :                         break;
     816           2 :                 case GF_EVENT_FOCUSOUT:
     817           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_focusout, 6, "event");
     818             :                         break;
     819           2 :                 case GF_EVENT_KEYDOWN:
     820             :                         /*encode as accessKey() if param*/
     821           2 :                         GF_LSR_WRITE_INT(lsr, evtParam ? LSR_EVT_accessKey : LSR_EVT_keydown, 6, "event");
     822             :                         break;
     823           2 :                 case GF_EVENT_KEYUP:
     824           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_keyup, 6, "event");
     825             :                         break;
     826           2 :                 case GF_EVENT_LOAD:
     827           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_load, 6, "event");
     828             :                         break;
     829          44 :                 case GF_EVENT_LONGKEYPRESS:
     830          44 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_longAccessKey, 6, "event");
     831             :                         break;
     832           2 :                 case GF_EVENT_MOUSEDOWN:
     833           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_mousedown, 6, "event");
     834             :                         break;
     835           2 :                 case GF_EVENT_MOUSEMOVE:
     836           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_mousemove, 6, "event");
     837             :                         break;
     838           2 :                 case GF_EVENT_MOUSEOUT:
     839           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_mouseout, 6, "event");
     840             :                         break;
     841           2 :                 case GF_EVENT_MOUSEOVER:
     842           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_mouseover, 6, "event");
     843             :                         break;
     844           2 :                 case GF_EVENT_MOUSEUP:
     845           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_mouseup, 6, "event");
     846             :                         break;
     847           2 :                 case GF_EVENT_PAUSE:
     848           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_pause, 6, "event");
     849             :                         break;
     850           2 :                 case GF_EVENT_PAUSED_EVENT:
     851           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_pausedEvent, 6, "event");
     852             :                         break;
     853           2 :                 case GF_EVENT_PLAY:
     854           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_play, 6, "event");
     855             :                         break;
     856           2 :                 case GF_EVENT_REPEAT_EVENT:
     857           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_repeatEvent, 6, "event");
     858             :                         break;
     859           2 :                 case GF_EVENT_REPEAT_KEY:
     860           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_repeatKey, 6, "event");
     861             :                         break;
     862           2 :                 case GF_EVENT_RESIZE:
     863           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_resize, 6, "event");
     864             :                         break;
     865           2 :                 case GF_EVENT_RESUME_EVENT:
     866           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_resumedEvent, 6, "event");
     867             :                         break;
     868           2 :                 case GF_EVENT_SCROLL:
     869           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_scroll, 6, "event");
     870             :                         break;
     871           0 :                 case GF_EVENT_SHORT_ACCESSKEY:
     872           0 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_shortAccessKey, 6, "event");
     873             :                         break;
     874           2 :                 case GF_EVENT_TEXTINPUT:
     875           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_textinput, 6, "event");
     876             :                         break;
     877           2 :                 case GF_EVENT_UNLOAD:
     878           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_unload, 6, "event");
     879             :                         break;
     880           2 :                 case GF_EVENT_ZOOM:
     881           2 :                         GF_LSR_WRITE_INT(lsr, LSR_EVT_zoom, 6, "event");
     882             :                         break;
     883           4 :                 default:
     884           4 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] Unsupported LASER event %d\n", evtType) );
     885           4 :                         GF_LSR_WRITE_INT(lsr, 0, 6, "event");
     886             :                         break;
     887             :                 }
     888         108 :                 switch (evtType) {
     889           2 :                 case GF_EVENT_KEYDOWN:
     890           2 :                         if (!evtParam) break;
     891             :                 case GF_EVENT_LONGKEYPRESS:
     892             :                 case GF_EVENT_REPEAT_KEY:
     893             :                 case GF_EVENT_SHORT_ACCESSKEY:
     894          48 :                         lsr_write_vluimsbf5(lsr, dom_to_lsr_key(evtParam), "keyCode");
     895          48 :                         break;
     896             :                 }
     897             :         }
     898         112 : }
     899             : 
     900          42 : static void lsr_write_smil_time(GF_LASeRCodec *lsr, SMIL_Time *t)
     901             : {
     902             :         s32 now;
     903          42 :         if (t->type==GF_SMIL_TIME_EVENT) {
     904           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "hasEvent");
     905           4 :                 if (t->element && gf_node_get_id((GF_Node*)t->element) ) {
     906             :                         XMLRI iri;
     907           2 :                         GF_LSR_WRITE_INT(lsr, 1, 1, "hasIdentifier");
     908           2 :                         iri.string = NULL;
     909           2 :                         iri.type = XMLRI_ELEMENTID;
     910           2 :                         iri.target =  t->element;
     911           2 :                         lsr_write_codec_IDREF(lsr, &iri, "idref");
     912             :                 } else {
     913           0 :                         GF_LSR_WRITE_INT(lsr, 0, 1, "hasIdentifier");
     914             :                 }
     915           2 :                 lsr_write_event_type(lsr, t->event.type, t->event.parameter);
     916             :         } else {
     917          40 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "hasEvent");
     918             :         }
     919          42 :         if (!t->clock) {
     920          12 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "hasClock");
     921             :                 return;
     922             :         }
     923          30 :         GF_LSR_WRITE_INT(lsr, 1, 1, "hasClock");
     924             : 
     925          30 :         now = (s32) (t->clock * lsr->time_resolution);
     926          30 :         if (now<0) {
     927           0 :                 now = -now;
     928           0 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "sign");
     929             :         } else {
     930          30 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "sign");
     931             :         }
     932          30 :         lsr_write_vluimsbf5(lsr, now, "value");
     933             : }
     934             : 
     935             : 
     936         198 : static void lsr_write_smil_times(GF_LASeRCodec *lsr, GF_List **l, const char *name, Bool skipable)
     937             : {
     938             :         SMIL_Time *v;
     939             :         u32 r_count, i, count;
     940             :         Bool indef = GF_FALSE;
     941             : 
     942         198 :         count = l ? gf_list_count(*l) : 0;
     943             : 
     944             :         r_count = 0;
     945         238 :         for (i=0; i<count; i++) {
     946          46 :                 v = (SMIL_Time*)gf_list_get(*l, i);
     947          46 :                 if (v->type==GF_SMIL_TIME_INDEFINITE) {
     948             :                         indef = GF_TRUE;
     949             :                         break;
     950             :                 }
     951          40 :                 else if (v->type!=GF_SMIL_TIME_EVENT_RESOLVED) r_count++;
     952             :         }
     953         198 :         if (skipable && !r_count && !indef) {
     954          58 :                 GF_LSR_WRITE_INT(lsr, 0, 1, name);
     955             :                 return;
     956             :         }
     957         140 :         if (skipable) GF_LSR_WRITE_INT(lsr, 1, 1, name);
     958         140 :         GF_LSR_WRITE_INT(lsr, indef, 1, "choice");
     959         140 :         if (indef) return;
     960         134 :         lsr_write_vluimsbf5(lsr, r_count, "count");
     961         174 :         for (i=0; i<count; i++) {
     962          40 :                 v = (SMIL_Time*)gf_list_get(*l, i);
     963          40 :                 lsr_write_smil_time(lsr, v);
     964             :         }
     965             : }
     966             : 
     967         104 : static void lsr_write_duration_ex(GF_LASeRCodec *lsr, SMIL_Duration *v, const char *name, Bool skipable)
     968             : {
     969         104 :         if (skipable) {
     970         100 :                 if (!v || !v->type) {
     971          22 :                         GF_LSR_WRITE_INT(lsr, 0, 1, name);
     972             :                         return;
     973             :                 }
     974          78 :                 GF_LSR_WRITE_INT(lsr, 1, 1, name);
     975             :         }
     976             : 
     977          82 :         if (v->type==SMIL_DURATION_DEFINED) {
     978          80 :                 s32 now = (s32) (v->clock_value * lsr->time_resolution);
     979          80 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "choice");
     980          80 :                 GF_LSR_WRITE_INT(lsr, (now<0) ? 1 : 0, 1, "sign");
     981          80 :                 if (now<0) now = -now;
     982          80 :                 lsr_write_vluimsbf5(lsr, now, "value");
     983             :         } else {
     984           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "choice");
     985           2 :                 GF_LSR_WRITE_INT(lsr, v->type, 2, "time");
     986             :         }
     987             : }
     988             : #define lsr_write_duration(a, b, c) lsr_write_duration_ex(a, b, c, 1)
     989             : 
     990          20 : static void lsr_write_focus(GF_LASeRCodec *lsr, SVG_Focus *foc, const char *name)
     991             : {
     992          20 :         if (foc->type==SVG_FOCUS_IRI) {
     993           2 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "isEnum");
     994           2 :                 lsr_write_codec_IDREF(lsr, &foc->target, "id");
     995             :         } else {
     996          18 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "isEnum");
     997          18 :                 GF_LSR_WRITE_INT(lsr, foc->type, 1, "enum");
     998             :         }
     999          20 : }
    1000             : 
    1001         114 : static Bool lsr_elt_has_same_base(GF_LASeRCodec *lsr, SVGAllAttributes *atts, SVG_Element *base, Bool *same_fill, Bool *same_stroke, Bool no_stroke_check)
    1002             : {
    1003             :         SVGAllAttributes base_atts;
    1004             :         GF_FieldInfo info, base_info;
    1005             : 
    1006         114 :         if (same_stroke) *same_stroke = GF_FALSE;
    1007         114 :         if (same_fill) *same_fill = GF_FALSE;
    1008             : 
    1009         114 :         if (!base) return GF_FALSE;
    1010             : 
    1011          98 :         gf_svg_flatten_attributes(base, &base_atts);
    1012          98 :         if (atts->externalResourcesRequired != base_atts.externalResourcesRequired) return GF_FALSE;
    1013             : 
    1014          98 :         info.fieldType = base_info.fieldType = SVG_Paint_datatype;
    1015          98 :         info.far_ptr = atts->stroke;
    1016          98 :         base_info.far_ptr = base_atts.stroke;
    1017             :         /*check stroke color*/
    1018          98 :         if (!gf_svg_attributes_equal(&info, &base_info)) {
    1019          34 :                 if (!no_stroke_check) return GF_FALSE;
    1020             :         } else {
    1021          64 :                 if (same_stroke) *same_stroke = GF_TRUE;
    1022             :         }
    1023          70 :         if (same_fill) {
    1024          68 :                 info.fieldType = base_info.fieldType = SVG_Paint_datatype;
    1025          68 :                 info.far_ptr = atts->fill;
    1026          68 :                 base_info.far_ptr = base_atts.fill;
    1027             :                 /*check stroke color*/
    1028          68 :                 *same_fill = gf_svg_attributes_equal(&info, &base_info) ? GF_TRUE : GF_FALSE;
    1029             :         }
    1030             : 
    1031          70 :         switch (gf_node_get_tag((GF_Node*) base)) {
    1032             :         /*check path length*/
    1033           6 :         case TAG_SVG_path:
    1034           6 :                 info.fieldType = base_info.fieldType = SVG_Number_datatype;
    1035           6 :                 info.far_ptr = atts->pathLength;
    1036           6 :                 base_info.far_ptr = base_atts.pathLength;
    1037           6 :                 if (!gf_svg_attributes_equal(&info, &base_info)) return GF_FALSE;
    1038             :                 break;
    1039             :         /*check rx and ry for rect*/
    1040          34 :         case TAG_SVG_rect:
    1041          34 :                 info.fieldType = base_info.fieldType = SVG_Length_datatype;
    1042          34 :                 info.far_ptr = atts->rx;
    1043          34 :                 base_info.far_ptr = base_atts.rx;
    1044          34 :                 if (!gf_svg_attributes_equal(&info, &base_info)) return GF_FALSE;
    1045             : 
    1046          34 :                 info.fieldType = base_info.fieldType = SVG_Length_datatype;
    1047          34 :                 info.far_ptr = atts->ry;
    1048          34 :                 base_info.far_ptr = base_atts.ry;
    1049          34 :                 if (!gf_svg_attributes_equal(&info, &base_info)) return GF_FALSE;
    1050             :                 break;
    1051             :         /*check x and y for use*/
    1052           2 :         case TAG_SVG_use:
    1053           2 :                 info.fieldType = base_info.fieldType = SVG_Coordinate_datatype;
    1054           2 :                 info.far_ptr = atts->x;
    1055           2 :                 base_info.far_ptr = base_atts.x;
    1056           2 :                 if (!gf_svg_attributes_equal(&info, &base_info)) return GF_FALSE;
    1057             : 
    1058           2 :                 info.fieldType = base_info.fieldType = SVG_Coordinate_datatype;
    1059           2 :                 info.far_ptr = atts->y;
    1060           2 :                 base_info.far_ptr = base_atts.y;
    1061           2 :                 if (!gf_svg_attributes_equal(&info, &base_info)) return GF_FALSE;
    1062             :                 break;
    1063             :         /*check editable and rotate for text*/
    1064           6 :         case TAG_SVG_text:
    1065           6 :                 info.fieldType = base_info.fieldType = SVG_Boolean_datatype;
    1066           6 :                 info.far_ptr = atts->editable;
    1067           6 :                 base_info.far_ptr = base_atts.editable;
    1068           6 :                 if (!gf_svg_attributes_equal(&info, &base_info)) return GF_FALSE;
    1069             : 
    1070           6 :                 info.fieldType = base_info.fieldType = SVG_Numbers_datatype;
    1071           6 :                 info.far_ptr = atts->text_rotate;
    1072           6 :                 base_info.far_ptr = base_atts.text_rotate;
    1073           6 :                 if (!gf_svg_attributes_equal(&info, &base_info)) return GF_FALSE;
    1074             :                 break;
    1075             :         }
    1076             : 
    1077          70 :         return gf_lsr_same_rare(atts, &base_atts);
    1078             : }
    1079             : 
    1080         318 : static void lsr_write_rare(GF_LASeRCodec *lsr, GF_Node *n)
    1081             : {
    1082             :         u32 i, nb_rare;
    1083             :         s32 field_rare;
    1084             :         SVGAttribute *att;
    1085             : 
    1086             :         nb_rare = 0;
    1087         318 :         att = ((SVG_Element*)n)->attributes;
    1088        1888 :         while (att) {
    1089        1252 :                 field_rare = gf_lsr_rare_type_from_attribute(att->tag);
    1090        1252 :                 if (field_rare>=0) nb_rare++;
    1091        1252 :                 att = att->next;
    1092             :         }
    1093             : 
    1094         318 :         GF_LSR_WRITE_INT(lsr, nb_rare ? 1 : 0, 1, "has_rare");
    1095         318 :         if (!nb_rare) return;
    1096             : 
    1097         174 :         GF_LSR_WRITE_INT(lsr, nb_rare, 6, "nbOfAttributes");
    1098             : 
    1099         174 :         att = ((SVG_Element*)n)->attributes;
    1100        1432 :         while (att) {
    1101        1084 :                 field_rare = gf_lsr_rare_type_from_attribute(att->tag);
    1102        1084 :                 if (field_rare==-1) {
    1103         780 :                         att = att->next;
    1104         780 :                         continue;
    1105             :                 }
    1106             :                 /*RARE extension*/
    1107         304 :                 if (field_rare==49) {
    1108             :                         Bool is_string = GF_FALSE;
    1109             :                         u32 size, cur_bits;
    1110             :                         u32 len = 2+3;
    1111          10 :                         switch (att->tag) {
    1112             :                         case TAG_SVG_ATT_syncMaster:
    1113             :                                 len +=1;
    1114             :                                 break;
    1115           2 :                         case TAG_SVG_ATT_requiredFonts:
    1116             :                         {
    1117           2 :                                 GF_List *l = *(GF_List **)att->data;
    1118             :                                 u32 str_len = 0;
    1119           6 :                                 for (i=0; i<gf_list_count(l); i++) {
    1120           4 :                                         char *st = gf_list_get(l, i);
    1121           4 :                                         str_len += (u32) strlen(st);
    1122           4 :                                         if (i) str_len += 1;
    1123             :                                 }
    1124             : 
    1125           2 :                                 len += 8 * (u32) str_len;
    1126             : 
    1127             :                                 /*get vluimsbf5 field size with one extra word (4 bits, enough to code string alignment)*/
    1128           2 :                                 size = lsr_get_vluimsbf5_size(len, 1);
    1129           2 :                                 cur_bits = gf_bs_get_bit_position(lsr->bs) + lsr->info->cfg.extensionIDBits + size + 5;
    1130             :                                 /*count string alignment*/
    1131           8 :                                 while (cur_bits%8) {
    1132           4 :                                         len++;
    1133           4 :                                         cur_bits++;
    1134             :                                 }
    1135             :                                 is_string = GF_TRUE;
    1136             :                         }
    1137             :                                 break;
    1138           6 :                         default:
    1139             :                                 len +=2;
    1140           6 :                                 break;
    1141             :                         }
    1142          10 :                         GF_LSR_WRITE_INT(lsr, 49, 6, "attributeRARE");
    1143          10 :                         GF_LSR_WRITE_INT(lsr, 2, lsr->info->cfg.extensionIDBits, "extensionID");
    1144          10 :                         if (is_string) {
    1145           2 :                                 lsr_write_vluimsbf5_ex(lsr, len, 1, "len");
    1146             :                         } else {
    1147           8 :                                 lsr_write_vluimsbf5(lsr, len, "len");
    1148             :                         }
    1149          10 :                         GF_LSR_WRITE_INT(lsr, 1, 2, "nbOfAttributes");
    1150             : 
    1151          10 :                         switch (att->tag) {
    1152           2 :                         case TAG_SVG_ATT_syncMaster:
    1153           2 :                                 GF_LSR_WRITE_INT(lsr, 0, 3, "attributeRARE");
    1154           2 :                                 GF_LSR_WRITE_INT(lsr, *(SVG_Boolean *)att->data ? 1 : 0, 1, "syncMaster");
    1155             :                                 break;
    1156           2 :                         case TAG_SVG_ATT_focusHighlight:
    1157           2 :                                 GF_LSR_WRITE_INT(lsr, 1, 3, "attributeRARE");
    1158           2 :                                 GF_LSR_WRITE_INT(lsr, *(SVG_FocusHighlight*)att->data, 2, "focusHighlight");
    1159             :                                 break;
    1160           2 :                         case TAG_SVG_ATT_initialVisibility:
    1161           2 :                                 GF_LSR_WRITE_INT(lsr, 2, 3, "attributeRARE");
    1162           2 :                                 GF_LSR_WRITE_INT(lsr, *(SVG_InitialVisibility*)att->data, 2, "initialVisibility");
    1163             :                                 break;
    1164           2 :                         case TAG_SVG_ATT_fullscreen:
    1165           2 :                                 GF_LSR_WRITE_INT(lsr, 3, 3, "attributeRARE");
    1166           2 :                                 GF_LSR_WRITE_INT(lsr, *(SVG_Boolean *)att->data ? 1 : 0, 1, "fullscreen");
    1167             :                                 break;
    1168           2 :                         case TAG_SVG_ATT_requiredFonts:
    1169           2 :                                 GF_LSR_WRITE_INT(lsr, 4, 3, "attributeRARE");
    1170           2 :                                 lsr_write_byte_align_string_list(lsr, *(GF_List **)att->data, "requiredFonts", GF_FALSE);
    1171           2 :                                 break;
    1172             :                         }
    1173          10 :                         GF_LSR_WRITE_INT(lsr, 0, 1, "hasNextExtension");
    1174          10 :                         att = att->next;
    1175          10 :                         continue;
    1176             :                 }
    1177             : 
    1178         294 :                 GF_LSR_WRITE_INT(lsr, (u32)field_rare, 6, "attributeRARE");
    1179         294 :                 switch (att->tag) {
    1180           0 :                 case TAG_SVG_ATT__class:
    1181           0 :                         lsr_write_byte_align_string(lsr, *(SVG_String *)att->data, "class");
    1182           0 :                         break;
    1183             : 
    1184           2 :                 case TAG_SVG_ATT_audio_level:
    1185           2 :                         lsr_write_fixed_clamp(lsr, ((SVG_Number *) att->data)->value, "audio-level");
    1186           2 :                         break;
    1187           4 :                 case TAG_SVG_ATT_color:
    1188           4 :                         lsr_write_paint(lsr, (SVG_Paint*) att->data, "color");
    1189           4 :                         break;
    1190           4 :                 case TAG_SVG_ATT_color_rendering:
    1191           4 :                         GF_LSR_WRITE_INT(lsr, *(SVG_RenderingHint*)att->data, 2, "color-rendering");
    1192             :                         break;
    1193           8 :                 case TAG_SVG_ATT_display:
    1194           8 :                         GF_LSR_WRITE_INT(lsr, *(SVG_Display*)att->data, 5, "display");
    1195             :                         break;
    1196           2 :                 case TAG_SVG_ATT_display_align:
    1197           2 :                         GF_LSR_WRITE_INT(lsr, *(SVG_DisplayAlign*)att->data, 3, "display-align");
    1198             :                         break;
    1199           4 :                 case TAG_SVG_ATT_fill_opacity:
    1200           4 :                         lsr_write_fixed_clamp(lsr, ((SVG_Number *)att->data)->value, "fill-opacity");
    1201           4 :                         break;
    1202           2 :                 case TAG_SVG_ATT_fill_rule:
    1203           2 :                         GF_LSR_WRITE_INT(lsr, *(SVG_FillRule*)att->data, 2, "fill-rule");
    1204             :                         break;
    1205           2 :                 case TAG_SVG_ATT_image_rendering:
    1206           2 :                         GF_LSR_WRITE_INT(lsr, *(SVG_RenderingHint*)att->data, 2, "image-rendering");
    1207             :                         break;
    1208           6 :                 case TAG_SVG_ATT_line_increment:
    1209           6 :                         lsr_write_line_increment_type(lsr, (SVG_Number*)att->data, "lineIncrement");
    1210           6 :                         break;
    1211           2 :                 case TAG_SVG_ATT_pointer_events:
    1212           2 :                         GF_LSR_WRITE_INT(lsr, *(SVG_PointerEvents*)att->data, 4, "pointer-events");
    1213             :                         break;
    1214           2 :                 case TAG_SVG_ATT_shape_rendering:
    1215           2 :                         GF_LSR_WRITE_INT(lsr, *(SVG_RenderingHint*)att->data, 3, "shape-rendering");
    1216             :                         break;
    1217           4 :                 case TAG_SVG_ATT_solid_color:
    1218           4 :                         lsr_write_paint(lsr, (SVG_Paint*)att->data, "solid-color");
    1219           4 :                         break;
    1220           2 :                 case TAG_SVG_ATT_solid_opacity:
    1221           2 :                         lsr_write_fixed_clamp(lsr, ((SVG_Number *)att->data)->value, "solid-opacity");
    1222           2 :                         break;
    1223          14 :                 case TAG_SVG_ATT_stop_color:
    1224          14 :                         lsr_write_paint(lsr, (SVG_Paint*)att->data, "stop-color");
    1225          14 :                         break;
    1226          16 :                 case TAG_SVG_ATT_stop_opacity:
    1227          16 :                         lsr_write_fixed_clamp(lsr, ((SVG_Number *)att->data)->value, "stop-opacity");
    1228          16 :                         break;
    1229           6 :                 case TAG_SVG_ATT_stroke_dasharray:
    1230             :                 {
    1231             :                         u32 j;
    1232           6 :                         SVG_StrokeDashArray *da = (SVG_StrokeDashArray*)att->data;
    1233           6 :                         if (da->type==SVG_STROKEDASHARRAY_INHERIT) {
    1234           4 :                                 GF_LSR_WRITE_INT(lsr, 1, 1, "dashArray");
    1235             :                         } else {
    1236           2 :                                 GF_LSR_WRITE_INT(lsr, 0, 1, "dashArray");
    1237           2 :                                 lsr_write_vluimsbf5(lsr, da->array.count, "len");
    1238           8 :                                 for (j=0; j<da->array.count; j++) {
    1239           6 :                                         lsr_write_fixed_16_8(lsr, da->array.vals[j], "dash");
    1240             :                                 }
    1241             :                         }
    1242             :                 }
    1243             :                 break;
    1244           2 :                 case TAG_SVG_ATT_stroke_dashoffset:
    1245           2 :                         lsr_write_fixed_16_8i(lsr, (SVG_Number*)att->data, "dashOffset");
    1246           2 :                         break;
    1247             : 
    1248           2 :                 case TAG_SVG_ATT_stroke_linecap:
    1249           2 :                         GF_LSR_WRITE_INT(lsr, *(SVG_StrokeLineCap*)att->data, 2, "stroke-linecap");
    1250             :                         break;
    1251           2 :                 case TAG_SVG_ATT_stroke_linejoin:
    1252           2 :                         GF_LSR_WRITE_INT(lsr, *(SVG_StrokeLineJoin*)att->data, 2, "stroke-linejoin");
    1253             :                         break;
    1254           2 :                 case TAG_SVG_ATT_stroke_miterlimit:
    1255           2 :                         lsr_write_fixed_16_8i(lsr, (SVG_Number*)att->data, "miterLimit");
    1256           2 :                         break;
    1257           4 :                 case TAG_SVG_ATT_stroke_opacity:
    1258           4 :                         lsr_write_fixed_clamp(lsr, ((SVG_Number *)att->data)->value, "stroke-opacity");
    1259           4 :                         break;
    1260          18 :                 case TAG_SVG_ATT_stroke_width:
    1261          18 :                         lsr_write_fixed_16_8i(lsr, (SVG_Number*)att->data, "strokeWidth");
    1262          18 :                         break;
    1263           2 :                 case TAG_SVG_ATT_text_anchor:
    1264           2 :                         GF_LSR_WRITE_INT(lsr, *(SVG_TextAnchor*)att->data, 2, "text-achor");
    1265             :                         break;
    1266           2 :                 case TAG_SVG_ATT_text_rendering:
    1267           2 :                         GF_LSR_WRITE_INT(lsr, *(SVG_RenderingHint*)att->data, 3, "text-rendering");
    1268             :                         break;
    1269           2 :                 case TAG_SVG_ATT_viewport_fill:
    1270           2 :                         lsr_write_paint(lsr, (SVG_Paint*)att->data, "viewport-fill");
    1271           2 :                         break;
    1272           2 :                 case TAG_SVG_ATT_viewport_fill_opacity:
    1273           2 :                         lsr_write_fixed_clamp(lsr, ((SVG_Number *)att->data)->value, "viewport-fill-opacity");
    1274           2 :                         break;
    1275           2 :                 case TAG_SVG_ATT_vector_effect:
    1276           2 :                         GF_LSR_WRITE_INT(lsr, *(SVG_VectorEffect*)att->data, 4, "vector-effect");
    1277             :                         break;
    1278           2 :                 case TAG_SVG_ATT_visibility:
    1279           2 :                         GF_LSR_WRITE_INT(lsr, *(SVG_PointerEvents*)att->data, 2, "visibility");
    1280             :                         break;
    1281           2 :                 case TAG_SVG_ATT_requiredExtensions:
    1282           2 :                         lsr_write_byte_align_string_list(lsr, *(GF_List **)att->data, "requiredExtensions", GF_TRUE);
    1283           2 :                         break;
    1284           2 :                 case TAG_SVG_ATT_requiredFormats:
    1285           2 :                         lsr_write_byte_align_string_list(lsr, *(GF_List **)att->data, "requiredFormats", GF_FALSE);
    1286           2 :                         break;
    1287           2 :                 case TAG_SVG_ATT_requiredFeatures:
    1288             :                 {
    1289           2 :                         GF_List *l = *(GF_List **)att->data;
    1290           2 :                         u32 j, tot_count, count = gf_list_count(l);
    1291           2 :                         u8 *vals = (u8*)gf_malloc(sizeof(u8)*count);
    1292             :                         tot_count = 0;
    1293          70 :                         for (i=0; i<count; i++) {
    1294             :                                 char *ext;
    1295          68 :                                 XMLRI *iri = (XMLRI*)gf_list_get(l, i);
    1296          68 :                                 if (iri->type != XMLRI_STRING) continue;
    1297          68 :                                 ext = strchr(iri->string, '#');
    1298          68 :                                 if (!ext) continue;
    1299          68 :                                 ext++;
    1300          68 :                                 if (!stricmp(ext, "Animation")) {
    1301           2 :                                         vals[tot_count] = 0;
    1302           2 :                                         tot_count++;
    1303             :                                 }
    1304          66 :                                 else if (!stricmp(ext, "Audio")) {
    1305           2 :                                         vals[tot_count] = 1;
    1306           2 :                                         tot_count++;
    1307             :                                 }
    1308          64 :                                 else if (!stricmp(ext, "ComposedVideo")) {
    1309           2 :                                         vals[tot_count] = 2;
    1310           2 :                                         tot_count++;
    1311             :                                 }
    1312          62 :                                 else if (!stricmp(ext, "ConditionalProcessing")) {
    1313           2 :                                         vals[tot_count] = 3;
    1314           2 :                                         tot_count++;
    1315             :                                 }
    1316          60 :                                 else if (!stricmp(ext, "ConditionalProcessingAttribute")) {
    1317           2 :                                         vals[tot_count] = 4;
    1318           2 :                                         tot_count++;
    1319             :                                 }
    1320          58 :                                 else if (!stricmp(ext, "CoreAttribute")) {
    1321           2 :                                         vals[tot_count] = 5;
    1322           2 :                                         tot_count++;
    1323             :                                 }
    1324          56 :                                 else if (!stricmp(ext, "Extensibility")) {
    1325           2 :                                         vals[tot_count] = 6;
    1326           2 :                                         tot_count++;
    1327             :                                 }
    1328          54 :                                 else if (!stricmp(ext, "ExternalResourcesRequired")) {
    1329           2 :                                         vals[tot_count] = 7;
    1330           2 :                                         tot_count++;
    1331             :                                 }
    1332          52 :                                 else if (!stricmp(ext, "Font")) {
    1333           2 :                                         vals[tot_count] = 8;
    1334           2 :                                         tot_count++;
    1335             :                                 }
    1336          50 :                                 else if (!stricmp(ext, "Gradient")) {
    1337           2 :                                         vals[tot_count] = 9;
    1338           2 :                                         tot_count++;
    1339             :                                 }
    1340          48 :                                 else if (!stricmp(ext, "GraphicsAttribute")) {
    1341           2 :                                         vals[tot_count] = 10;
    1342           2 :                                         tot_count++;
    1343             :                                 }
    1344          46 :                                 else if (!stricmp(ext, "Handler")) {
    1345           2 :                                         vals[tot_count] = 11;
    1346           2 :                                         tot_count++;
    1347             :                                 }
    1348          44 :                                 else if (!stricmp(ext, "Hyperlinking")) {
    1349           2 :                                         vals[tot_count] = 12;
    1350           2 :                                         tot_count++;
    1351             :                                 }
    1352          42 :                                 else if (!stricmp(ext, "Image")) {
    1353           2 :                                         vals[tot_count] = 13;
    1354           2 :                                         tot_count++;
    1355             :                                 }
    1356          40 :                                 else if (!stricmp(ext, "OpacityAttribute")) {
    1357           2 :                                         vals[tot_count] = 14;
    1358           2 :                                         tot_count++;
    1359             :                                 }
    1360          38 :                                 else if (!stricmp(ext, "PaintAttribute")) {
    1361           2 :                                         vals[tot_count] = 15;
    1362           2 :                                         tot_count++;
    1363             :                                 }
    1364          36 :                                 else if (!stricmp(ext, "Prefetch")) {
    1365           2 :                                         vals[tot_count] = 16;
    1366           2 :                                         tot_count++;
    1367             :                                 }
    1368          34 :                                 else if (!stricmp(ext, "SVG")) {
    1369           2 :                                         vals[tot_count] = 17;
    1370           2 :                                         tot_count++;
    1371             :                                 }
    1372          32 :                                 else if (!stricmp(ext, "SVG-animation")) {
    1373           2 :                                         vals[tot_count] = 18;
    1374           2 :                                         tot_count++;
    1375             :                                 }
    1376          30 :                                 else if (!stricmp(ext, "SVG-dynamic")) {
    1377           2 :                                         vals[tot_count] = 19;
    1378           2 :                                         tot_count++;
    1379             :                                 }
    1380          28 :                                 else if (!stricmp(ext, "SVG-static")) {
    1381           2 :                                         vals[tot_count] = 20;
    1382           2 :                                         tot_count++;
    1383             :                                 }
    1384          26 :                                 else if (!stricmp(ext, "SVGDOM")) {
    1385           2 :                                         vals[tot_count] = 21;
    1386           2 :                                         tot_count++;
    1387             :                                 }
    1388          24 :                                 else if (!stricmp(ext, "SVGDOM-animation")) {
    1389           2 :                                         vals[tot_count] = 22;
    1390           2 :                                         tot_count++;
    1391             :                                 }
    1392          22 :                                 else if (!stricmp(ext, "SVGDOM-dynamic")) {
    1393           2 :                                         vals[tot_count] = 23;
    1394           2 :                                         tot_count++;
    1395             :                                 }
    1396          20 :                                 else if (!stricmp(ext, "SVGDOM-static")) {
    1397           2 :                                         vals[tot_count] = 24;
    1398           2 :                                         tot_count++;
    1399             :                                 }
    1400          18 :                                 else if (!stricmp(ext, "Script")) {
    1401           2 :                                         vals[tot_count] = 25;
    1402           2 :                                         tot_count++;
    1403             :                                 }
    1404          16 :                                 else if (!stricmp(ext, "Shape")) {
    1405           2 :                                         vals[tot_count] = 26;
    1406           2 :                                         tot_count++;
    1407             :                                 }
    1408          14 :                                 else if (!stricmp(ext, "SolidColor")) {
    1409           2 :                                         vals[tot_count] = 27;
    1410           2 :                                         tot_count++;
    1411             :                                 }
    1412          12 :                                 else if (!stricmp(ext, "Structure")) {
    1413           2 :                                         vals[tot_count] = 28;
    1414           2 :                                         tot_count++;
    1415             :                                 }
    1416          10 :                                 else if (!stricmp(ext, "Text")) {
    1417           2 :                                         vals[tot_count] = 29;
    1418           2 :                                         tot_count++;
    1419             :                                 }
    1420           8 :                                 else if (!stricmp(ext, "TimedAnimation")) {
    1421           2 :                                         vals[tot_count] = 30;
    1422           2 :                                         tot_count++;
    1423             :                                 }
    1424           6 :                                 else if (!stricmp(ext, "TransformedVideo")) {
    1425           2 :                                         vals[tot_count] = 31;
    1426           2 :                                         tot_count++;
    1427             :                                 }
    1428           4 :                                 else if (!stricmp(ext, "Video")) {
    1429           2 :                                         vals[tot_count] = 32;
    1430           2 :                                         tot_count++;
    1431             :                                 }
    1432           2 :                                 else if (!stricmp(ext, "XlinkAttribute")) {
    1433           2 :                                         vals[tot_count] = 33;
    1434           2 :                                         tot_count++;
    1435             :                                 }
    1436             :                         }
    1437           2 :                         lsr_write_vluimsbf5(lsr, tot_count, "len");
    1438          70 :                         for (j=0; j<tot_count; j++) {
    1439          68 :                                 GF_LSR_WRITE_INT(lsr, vals[j], 6, "feature");
    1440             :                         }
    1441           2 :                         gf_free(vals);
    1442             :                 }
    1443           2 :                 break;
    1444             : 
    1445           2 :                 case TAG_SVG_ATT_systemLanguage:
    1446           2 :                         lsr_write_byte_align_string_list(lsr, *(GF_List **)att->data, "systemLanguage", GF_FALSE);
    1447           2 :                         break;
    1448           2 :                 case TAG_XML_ATT_base:
    1449           2 :                         lsr_write_byte_align_string(lsr, ((XMLRI*)att->data)->string, "xml:base");
    1450           2 :                         break;
    1451           2 :                 case TAG_XML_ATT_lang:
    1452           2 :                         lsr_write_byte_align_string(lsr, *(SVG_String *)att->data, "xml:lang");
    1453           2 :                         break;
    1454           2 :                 case TAG_XML_ATT_space:
    1455           2 :                         GF_LSR_WRITE_INT(lsr, *(XML_Space *)att->data, 1, "xml:space");
    1456             :                         break;
    1457           2 :                 case TAG_SVG_ATT_nav_next:
    1458           2 :                         lsr_write_focus(lsr, (SVG_Focus*)att->data, "focusNext");
    1459           2 :                         break;
    1460           2 :                 case TAG_SVG_ATT_nav_up:
    1461           2 :                         lsr_write_focus(lsr, (SVG_Focus*)att->data, "focusNorth");
    1462           2 :                         break;
    1463           2 :                 case TAG_SVG_ATT_nav_up_left:
    1464           2 :                         lsr_write_focus(lsr, (SVG_Focus*)att->data, "focusNorthEast");
    1465           2 :                         break;
    1466           2 :                 case TAG_SVG_ATT_nav_up_right:
    1467           2 :                         lsr_write_focus(lsr, (SVG_Focus*)att->data, "focusNorthWest");
    1468           2 :                         break;
    1469           2 :                 case TAG_SVG_ATT_nav_prev:
    1470           2 :                         lsr_write_focus(lsr, (SVG_Focus*)att->data, "focusPrev");
    1471           2 :                         break;
    1472           2 :                 case TAG_SVG_ATT_nav_down:
    1473           2 :                         lsr_write_focus(lsr, (SVG_Focus*)att->data, "focusSouth");
    1474           2 :                         break;
    1475           2 :                 case TAG_SVG_ATT_nav_down_left:
    1476           2 :                         lsr_write_focus(lsr, (SVG_Focus*)att->data, "focusSouthEast");
    1477           2 :                         break;
    1478           2 :                 case TAG_SVG_ATT_nav_down_right:
    1479           2 :                         lsr_write_focus(lsr, (SVG_Focus*)att->data, "focusSouthWest");
    1480           2 :                         break;
    1481           2 :                 case TAG_SVG_ATT_nav_right:
    1482           2 :                         lsr_write_focus(lsr, (SVG_Focus*)att->data, "focusWest");
    1483           2 :                         break;
    1484           2 :                 case TAG_SVG_ATT_nav_left:
    1485           2 :                         lsr_write_focus(lsr, (SVG_Focus*)att->data, "focusEast");
    1486           2 :                         break;
    1487             : 
    1488           2 :                 case TAG_SVG_ATT_font_variant:
    1489           2 :                         GF_LSR_WRITE_INT(lsr, *(SVG_FontVariant *)att->data, 2, "font-variant");
    1490             :                         break;
    1491           2 :                 case TAG_SVG_ATT_font_family:
    1492             :                 {
    1493           2 :                         s32 idx = lsr_get_font_index(lsr, (SVG_FontFamily*)att->data);
    1494           2 :                         if (idx<0) {
    1495           2 :                                 GF_LSR_WRITE_INT(lsr, 1, 1, "isInherit");
    1496             :                         } else {
    1497           0 :                                 GF_LSR_WRITE_INT(lsr, 0, 1, "isInherit");
    1498           0 :                                 GF_LSR_WRITE_INT(lsr, idx, lsr->fontIndexBits, "fontIndex");
    1499             :                         }
    1500             :                 }
    1501             :                 break;
    1502           2 :                 case TAG_SVG_ATT_font_size:
    1503           2 :                         lsr_write_fixed_16_8i(lsr, (SVG_Number*)att->data, "fontSize");
    1504           2 :                         break;
    1505           2 :                 case TAG_SVG_ATT_font_style:
    1506           2 :                         GF_LSR_WRITE_INT(lsr, *((SVG_FontStyle *)att->data), 3, "fontStyle");
    1507             :                         break;
    1508           2 :                 case TAG_SVG_ATT_font_weight:
    1509           2 :                         GF_LSR_WRITE_INT(lsr, *((SVG_FontWeight *)att->data), 4, "fontWeight");
    1510             :                         break;
    1511             : 
    1512           2 :                 case TAG_XLINK_ATT_title:
    1513           2 :                         lsr_write_byte_align_string(lsr, *(SVG_String *)att->data, "xlink:title");
    1514           2 :                         break;
    1515             :                 /*TODO FIXME*/
    1516           2 :                 case TAG_XLINK_ATT_type:
    1517           2 :                         GF_LSR_WRITE_INT(lsr, 0, 3, "xlink:type");
    1518             :                         break;
    1519           2 :                 case TAG_XLINK_ATT_role:
    1520           2 :                         lsr_write_any_uri(lsr, (XMLRI*)att->data, "xlink:role");
    1521           2 :                         break;
    1522           2 :                 case TAG_XLINK_ATT_arcrole:
    1523           2 :                         lsr_write_any_uri(lsr, (XMLRI*)att->data, "xlink:arcrole");
    1524           2 :                         break;
    1525             :                 /*TODO FIXME*/
    1526           2 :                 case TAG_XLINK_ATT_actuate:
    1527           2 :                         GF_LSR_WRITE_INT(lsr, 0, 2, "xlink:actuate");
    1528             :                         break;
    1529           2 :                 case TAG_XLINK_ATT_show:
    1530           2 :                         GF_LSR_WRITE_INT(lsr, 0, 3, "xlink:show");
    1531             :                         break;
    1532          98 :                 case TAG_SVG_ATT_end:
    1533          98 :                         lsr_write_smil_times(lsr, (GF_List **)att->data, "end", GF_FALSE);
    1534          98 :                         break;
    1535           2 :                 case TAG_SVG_ATT_min:
    1536           2 :                         lsr_write_duration_ex(lsr, (SMIL_Duration*)att->data, "min", GF_FALSE);
    1537           2 :                         break;
    1538           2 :                 case TAG_SVG_ATT_max:
    1539           2 :                         lsr_write_duration_ex(lsr, (SMIL_Duration*)att->data, "max", GF_FALSE);
    1540           2 :                         break;
    1541          12 :                 case TAG_SVG_ATT_transform:
    1542          12 :                         lsr_write_matrix(lsr, (SVG_Transform*)att->data);
    1543          12 :                         break;
    1544           2 :                 case TAG_SVG_ATT_focusable:
    1545           2 :                         GF_LSR_WRITE_INT(lsr, *(SVG_Focusable*)att->data, 2, "focusable");
    1546             :                         break;
    1547           0 :                 default:
    1548           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[LASeR Enc] Rare Field declared but not encoded\n"));
    1549             :                         break;
    1550             :                 }
    1551         294 :                 att = att->next;
    1552             :         }
    1553             : }
    1554             : 
    1555         174 : static void lsr_write_fill(GF_LASeRCodec *lsr, SVG_Element *n, SVGAllAttributes *atts)
    1556             : {
    1557         174 :         if (atts->fill) {
    1558          40 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "fill");
    1559          40 :                 lsr_write_paint(lsr, atts->fill, "fill");
    1560             :         } else {
    1561         134 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "fill");
    1562             :         }
    1563         174 : }
    1564             : 
    1565         168 : static void lsr_write_stroke(GF_LASeRCodec *lsr, SVG_Element *n, SVGAllAttributes *atts)
    1566             : {
    1567         168 :         if (atts->stroke) {
    1568          36 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "has_stroke");
    1569          36 :                 lsr_write_paint(lsr, atts->stroke, "stroke");
    1570             :         } else {
    1571         132 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "has_stroke");
    1572             :         }
    1573         168 : }
    1574          96 : static void lsr_write_href(GF_LASeRCodec *lsr, XMLRI *iri)
    1575             : {
    1576          96 :         Bool has_href = iri ? GF_TRUE : GF_FALSE;
    1577          96 :         if (iri) {
    1578          50 :                 if (iri->type==XMLRI_ELEMENTID) {
    1579          34 :                         if (!iri->target && iri->string) iri->target = (SVG_Element *)gf_sg_find_node_by_name(lsr->sg, iri->string+1);
    1580          34 :                         if (!iri->target || !gf_node_get_id((GF_Node *)iri->target)) has_href = GF_FALSE;
    1581             :                 }
    1582          16 :                 else if (iri->type==XMLRI_STREAMID) {
    1583           2 :                         if (!iri->lsr_stream_id) has_href = GF_FALSE;
    1584             :                 }
    1585          14 :                 else if (!iri->string) has_href = GF_FALSE;
    1586             :         }
    1587             : 
    1588          96 :         GF_LSR_WRITE_INT(lsr, has_href, 1, "has_href");
    1589          96 :         if (has_href) lsr_write_any_uri(lsr, iri, "href");
    1590          96 : }
    1591             : 
    1592          86 : static void lsr_write_accumulate(GF_LASeRCodec *lsr, SMIL_Accumulate *accum_type)
    1593             : {
    1594          86 :         GF_LSR_WRITE_INT(lsr, accum_type ? 1 : 0, 1, "has_accumulate");
    1595          86 :         if (accum_type) GF_LSR_WRITE_INT(lsr, *accum_type, 1, "accumulate");
    1596          86 : }
    1597          86 : static void lsr_write_additive(GF_LASeRCodec *lsr, SMIL_Additive *add_type)
    1598             : {
    1599          86 :         GF_LSR_WRITE_INT(lsr, add_type ? 1 : 0, 1, "has_additive");
    1600          86 :         if (add_type) GF_LSR_WRITE_INT(lsr, *add_type, 1, "additive");
    1601          86 : }
    1602          86 : static void lsr_write_calc_mode(GF_LASeRCodec *lsr, u8 *calc_mode)
    1603             : {
    1604             : 
    1605             :         /*SMIL_CALCMODE_LINEAR is default and 0 in our code*/
    1606          86 :         GF_LSR_WRITE_INT(lsr, (!calc_mode || (*calc_mode==SMIL_CALCMODE_LINEAR)) ? 0 : 1, 1, "has_calcMode");
    1607          86 :         if (calc_mode && (*calc_mode!=SMIL_CALCMODE_LINEAR)) {
    1608          10 :                 GF_LSR_WRITE_INT(lsr, *calc_mode, 2, "calcMode");
    1609             :         }
    1610          86 : }
    1611             : 
    1612          82 : static void lsr_write_animatable(GF_LASeRCodec *lsr, SMIL_AttributeName *anim_type, XMLRI *iri, const char *name)
    1613             : {
    1614             :         s32 a_type = -1;
    1615             : 
    1616          82 :         if (!anim_type || !iri || !iri->target) {
    1617           2 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "hasAttributeName");
    1618             :                 return;
    1619             :         }
    1620             : 
    1621             :         /*locate field - checkme, this may not work since anim is not setup...*/
    1622             :         assert(anim_type->name || anim_type->tag);
    1623          80 :         if (!anim_type->tag) anim_type->tag = gf_xml_get_attribute_tag((GF_Node*)iri->target, anim_type->name, 0);
    1624          80 :         if (!anim_type->type) anim_type->type = gf_xml_get_attribute_type(anim_type->tag);
    1625          80 :         a_type = gf_lsr_anim_type_from_attribute(anim_type->tag);
    1626          80 :         if (a_type<0) {
    1627           4 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] Unsupported attributeName %s for animatable type, skipping\n", anim_type->name));
    1628           4 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "hasAttributeName");
    1629             :         } else {
    1630          76 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "hasAttributeName");
    1631          76 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "choice");
    1632          76 :                 GF_LSR_WRITE_INT(lsr, (u8) a_type, 8, "attributeType");
    1633             :         }
    1634             : }
    1635             : 
    1636          88 : static void lsr_write_anim_fill(GF_LASeRCodec *lsr, u8 *animFreeze)
    1637             : {
    1638          88 :         GF_LSR_WRITE_INT(lsr, animFreeze ? 1 : 0, 1, "has_smil_fill");
    1639          88 :         if (animFreeze) GF_LSR_WRITE_INT(lsr, *animFreeze, 1, "smil_fill");
    1640          88 : }
    1641          96 : static void lsr_write_anim_repeat(GF_LASeRCodec *lsr, SMIL_RepeatCount *repeat)
    1642             : {
    1643          96 :         GF_LSR_WRITE_INT(lsr, repeat ? 1 : 0, 1, "has_repeatCount");
    1644          96 :         if (!repeat) return;
    1645             : 
    1646          14 :         if (repeat->type==SMIL_REPEATCOUNT_DEFINED) {
    1647           6 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "repeatCount");
    1648           6 :                 lsr_write_fixed_16_8(lsr, repeat->count, "repeatCount");
    1649             :         } else {
    1650           8 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "repeatCount");
    1651             :                 /*enumeration indefinite{0}*/
    1652             :         }
    1653             : }
    1654          96 : static void lsr_write_repeat_duration(GF_LASeRCodec *lsr, SMIL_Duration *smil)
    1655             : {
    1656          96 :         GF_LSR_WRITE_INT(lsr, smil ? 1 : 0, 1, "has_repeatDur");
    1657          96 :         if (!smil) return;
    1658             : 
    1659           2 :         if (smil->type==SMIL_DURATION_DEFINED) {
    1660           2 :                 u32 now = (u32) (smil->clock_value * lsr->time_resolution);
    1661           2 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "choice");
    1662           2 :                 lsr_write_vluimsbf5(lsr, now, "value");
    1663             :         } else {
    1664           0 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "choice");
    1665             :                 /*enumeration indefinite{0}*/
    1666             :         }
    1667             : }
    1668          96 : static void lsr_write_anim_restart(GF_LASeRCodec *lsr, u8 *animRestart)
    1669             : {
    1670          96 :         GF_LSR_WRITE_INT(lsr, animRestart ? 1 : 0, 1, "has_restart");
    1671             : 
    1672             :         /*enumeration always{0} never{1} whenNotActive{2}*/
    1673          96 :         if (animRestart) GF_LSR_WRITE_INT(lsr, *animRestart, 2, "restart");
    1674          96 : }
    1675             : 
    1676          94 : static u32 svg_type_to_lsr_anim(u32 svg_type, u32 transform_type, GF_List *vals, void *a_val)
    1677             : {
    1678          94 :         switch (svg_type) {
    1679             :         /*all string types*/
    1680             :         case DOM_String_datatype:
    1681             :                 return 0;
    1682             :         /*all length types*/
    1683          22 :         case SVG_Number_datatype:
    1684             :         case SVG_FontSize_datatype:
    1685             :         case SVG_Length_datatype:
    1686             :         case SVG_Coordinate_datatype:
    1687             :                 return 1;
    1688           4 :         case SVG_PathData_datatype:
    1689             :                 return 2;
    1690             :         /*list of points*/
    1691           0 :         case SMIL_KeyPoints_datatype:
    1692             :         case SVG_Points_datatype:
    1693             :                 return 3;
    1694             :         /*all 0 - 1 types*/
    1695             :         /*
    1696             :                 case SVG_Opacity_datatype:
    1697             :                         return 4;
    1698             :         */
    1699          14 :         case SVG_Paint_datatype:
    1700             :                 return 5;
    1701             :         /*all enums (u8) types*/
    1702          22 :         case SVG_FillRule_datatype:
    1703             :         case SVG_StrokeLineJoin_datatype:
    1704             :         case SVG_StrokeLineCap_datatype:
    1705             :         case SVG_FontStyle_datatype:
    1706             :         case SVG_FontWeight_datatype:
    1707             :         case SVG_FontVariant_datatype:
    1708             :         case SVG_TextAnchor_datatype:
    1709             :         case SVG_TransformType_datatype:
    1710             :         case SVG_Display_datatype:
    1711             :         case SVG_Visibility_datatype:
    1712             :         case SVG_Overflow_datatype:
    1713             :         case SVG_ZoomAndPan_datatype:
    1714             :         case SVG_DisplayAlign_datatype:
    1715             :         case SVG_TextAlign_datatype:
    1716             :         case SVG_PointerEvents_datatype:
    1717             :         case SVG_RenderingHint_datatype:
    1718             :         case SVG_VectorEffect_datatype:
    1719             :         case SVG_PlaybackOrder_datatype:
    1720             :         case SVG_TimelineBegin_datatype:
    1721             :                 return 6;
    1722             : /*all list-of-int types*/ //return 7;
    1723             :         /*all list-of-float types*/
    1724           2 :         case SVG_StrokeDashArray_datatype:
    1725             :         case SVG_ViewBox_datatype:
    1726             :         case SVG_Coordinates_datatype:
    1727             :                 return 8;
    1728             : /*ID (u32) types*/ //return 10;
    1729           2 :         case SVG_FontFamily_datatype:
    1730             :                 return 11;
    1731           4 :         case XMLRI_datatype:
    1732             :                 return 12;
    1733           0 :         case SVG_Motion_datatype:
    1734             :                 return 9;
    1735             : 
    1736             :         /*ARG LOOKS LIKE THE SPEC IS BROKEN HERE*/
    1737           2 :         case SVG_Transform_Translate_datatype:
    1738             :                 return 9;
    1739           0 :         case SVG_Transform_Scale_datatype:
    1740             :                 return 8;
    1741           4 :         case SVG_Transform_Rotate_datatype:
    1742           4 :                 if (vals) {
    1743           0 :                         u32 i=0;
    1744             :                         SVG_Point_Angle *pt;
    1745           0 :                         while ((pt = (SVG_Point_Angle *) gf_list_enum(vals, &i))) {
    1746           0 :                                 if (pt->x || pt->y) return 8;
    1747             :                         }
    1748           4 :                 } else if (a_val) {
    1749             :                         SVG_Point_Angle *pt = (SVG_Point_Angle *) a_val;
    1750           4 :                         if (pt->x || pt->y) return 8;
    1751             :                 }
    1752             :                 return 1;
    1753           2 :         case SVG_Transform_SkewX_datatype:
    1754             :                 return 1;
    1755           4 :         case SVG_Transform_SkewY_datatype:
    1756             :                 return 1;
    1757             :         //case SVG_Transform_datatype: return;
    1758             :         /*FALL THROUH*/
    1759           8 :         default:
    1760             :                 return 255;
    1761             :         }
    1762             : }
    1763          50 : static void lsr_write_coordinate(GF_LASeRCodec *lsr, Fixed val, Bool skipable, const char *name)
    1764             : {
    1765          50 :         if (skipable && !val) {
    1766           0 :                 GF_LSR_WRITE_INT(lsr, 0, 1, name);
    1767             :         } else {
    1768          50 :                 u32 res = lsr_translate_coords(lsr, val, lsr->coord_bits);
    1769          50 :                 if (skipable) GF_LSR_WRITE_INT(lsr, 1, 1, name);
    1770          50 :                 GF_LSR_WRITE_INT(lsr, res, lsr->coord_bits, name);
    1771             :         }
    1772          50 : }
    1773             : 
    1774         494 : static void lsr_write_coordinate_ptr(GF_LASeRCodec *lsr, SVG_Coordinate *val, Bool skipable, const char *name)
    1775             : {
    1776         494 :         if (skipable && !val) {
    1777         244 :                 GF_LSR_WRITE_INT(lsr, 0, 1, name);
    1778             :         } else {
    1779         250 :                 u32 res = lsr_translate_coords(lsr, val ? val->value : 0, lsr->coord_bits);
    1780         250 :                 if (skipable) GF_LSR_WRITE_INT(lsr, 1, 1, name);
    1781         250 :                 GF_LSR_WRITE_INT(lsr, res, lsr->coord_bits, name);
    1782             :         }
    1783         494 : }
    1784             : 
    1785         214 : static void lsr_write_an_anim_value(GF_LASeRCodec *lsr, void *val, u32 lsr_type, u32 svg_type, u32 transform_type, const char *name)
    1786             : {
    1787         214 :         if ((lsr_type==1) || (lsr_type==4)) {
    1788          54 :                 switch (svg_type) {
    1789           6 :                 case SVG_Transform_Rotate_datatype:
    1790             :                 case SVG_Transform_SkewX_datatype:
    1791             :                 case SVG_Transform_SkewY_datatype:
    1792           6 :                         GF_LSR_WRITE_INT(lsr, 0, 1, "escapeFlag");
    1793             :                         break;
    1794          48 :                 default:
    1795             :                 {
    1796             :                         SVG_Number  *n = (SVG_Number *) val;
    1797          48 :                         if (n->type != SVG_NUMBER_VALUE) {
    1798             :                                 u8 value = 0;
    1799           2 :                                 if (n->type==SVG_NUMBER_INHERIT) value=1;
    1800             :                                 /*fixe me spec is not clear here regarding what values should be used ...*/
    1801             :                                 
    1802           2 :                                 GF_LSR_WRITE_INT(lsr, 1, 1, "escapeFlag");
    1803           2 :                                 GF_LSR_WRITE_INT(lsr, value, 2, "escapeEnum");
    1804             :                                 return;
    1805             :                         } else {
    1806          46 :                                 GF_LSR_WRITE_INT(lsr, 0, 1, "escapeFlag");
    1807             :                         }
    1808             :                 }
    1809             :                 break;
    1810             :                 }
    1811         160 :         } else if (svg_type==SVG_StrokeDashArray_datatype) {
    1812             :                 SVG_StrokeDashArray *da = (SVG_StrokeDashArray *)val;
    1813           6 :                 if (da->type==SVG_STROKEDASHARRAY_INHERIT) {
    1814           2 :                         GF_LSR_WRITE_INT(lsr, 1, 1, "escapeFlag");
    1815           2 :                         GF_LSR_WRITE_INT(lsr, 0, 2, "escapeEnum");
    1816             :                 } else {
    1817           4 :                         GF_LSR_WRITE_INT(lsr, 0, 1, "escapeFlag");
    1818             :                 }
    1819             :         } else {
    1820         154 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "escapeFlag");
    1821             :         }
    1822             : 
    1823         212 :         switch(lsr_type) {
    1824          32 :         case 0:
    1825          32 :                 lsr_write_byte_align_string(lsr, *(DOM_String *)val, name);
    1826             :                 break;
    1827          52 :         case 1:
    1828          52 :                 if (svg_type==SVG_Transform_Rotate_datatype) {
    1829           0 :                         Fixed angle = ((SVG_Point_Angle *) val)->angle;
    1830           0 :                         angle = gf_muldiv(angle, INT2FIX(180), GF_PI);
    1831           0 :                         lsr_write_fixed_16_8(lsr, angle, name);
    1832          52 :                 } else if ((svg_type==SVG_Transform_SkewX_datatype) || (svg_type==SVG_Transform_SkewY_datatype))  {
    1833           6 :                         lsr_write_fixed_16_8(lsr, *(Fixed *)val, name);
    1834             :                 } else {
    1835          46 :                         lsr_write_fixed_16_8(lsr, ((SVG_Number *) val)->value, name);
    1836             :                 }
    1837             :                 break;
    1838          14 :         case 12:
    1839          14 :                 lsr_write_any_uri(lsr, (XMLRI*)val, name);
    1840             :                 break;
    1841           4 :         case 2:
    1842           4 :                 lsr_write_path_type(lsr, (SVG_PathData*)val, name);
    1843             :                 break;
    1844           0 :         case 3:
    1845           0 :                 lsr_write_point_sequence(lsr, (GF_List **)val, name);
    1846             :                 break;
    1847           0 :         case 4:
    1848           0 :                 lsr_write_fixed_clamp(lsr, ((SVG_Number *) val)->value, name);
    1849             :                 break;
    1850          26 :         case 5:
    1851          26 :                 lsr_write_paint(lsr, (SVG_Paint*)val, name);
    1852             :                 break;
    1853          62 :         case 6:
    1854          62 :                 lsr_write_vluimsbf5(lsr, (u32) *(u8 *) val, name);
    1855             :                 break;
    1856           0 :         case 10:
    1857           0 :                 lsr_write_vluimsbf5(lsr, *(u32 *) val, name);
    1858             :                 break;
    1859          10 :         case 11:
    1860             :         {
    1861          10 :                 s32 idx = lsr_get_font_index(lsr, (SVG_FontFamily*)val);
    1862          10 :                 if (idx<0) {
    1863           2 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] corrupted font table while encoding anim value\n"));
    1864             :                         idx=0;
    1865             :                 }
    1866          10 :                 lsr_write_vluimsbf5(lsr, idx, name);
    1867             :         }
    1868             :         break;
    1869           0 :         case 7:
    1870             :         {
    1871           0 :                 GF_List *l = *(GF_List **)val;
    1872           0 :                 u32 i, count = gf_list_count(l);
    1873           0 :                 lsr_write_vluimsbf5(lsr, count, "count");
    1874           0 :                 for (i=0; i<count; i++) {
    1875           0 :                         u8 *v = (u8 *)gf_list_get(l, i);
    1876           0 :                         lsr_write_vluimsbf5(lsr, *v, "val");
    1877             :                 }
    1878             :         }
    1879             :         break;
    1880          10 :         case 8: // floats
    1881             :         {
    1882             :                 u32 i, count;
    1883          10 :                 if (svg_type==SVG_StrokeDashArray_datatype) {
    1884             :                         SVG_StrokeDashArray *da = (SVG_StrokeDashArray *)val;
    1885           6 :                         lsr_write_vluimsbf5(lsr, da->array.count, "count");
    1886          12 :                         for (i=0; i<da->array.count; i++) {
    1887          12 :                                 lsr_write_fixed_16_8(lsr, da->array.vals[i], "val");
    1888             :                         }
    1889           4 :                 } else if (svg_type==SVG_ViewBox_datatype) {
    1890             :                         SVG_ViewBox *vb = (SVG_ViewBox *)val;
    1891           0 :                         lsr_write_vluimsbf5(lsr, 4, "count");
    1892           0 :                         lsr_write_fixed_16_8(lsr, vb->x, "val");
    1893           0 :                         lsr_write_fixed_16_8(lsr, vb->y, "val");
    1894           0 :                         lsr_write_fixed_16_8(lsr, vb->width, "val");
    1895           0 :                         lsr_write_fixed_16_8(lsr, vb->height, "val");
    1896           4 :                 } else if (svg_type==SVG_Coordinates_datatype) {
    1897           0 :                         GF_List *l = *(GF_List **)val;
    1898           0 :                         count = gf_list_count(l);
    1899           0 :                         lsr_write_vluimsbf5(lsr, count, "count");
    1900           0 :                         for (i=0; i<count; i++) {
    1901           0 :                                 SVG_Coordinate *v = (SVG_Coordinate *)gf_list_get(l, i);
    1902           0 :                                 lsr_write_fixed_16_8(lsr, v->value, "val");
    1903             :                         }
    1904           4 :                 } else if (svg_type==SVG_Transform_Rotate_datatype) {
    1905             :                         SVG_Point_Angle *p = (SVG_Point_Angle *)val;
    1906           4 :                         Fixed angle = gf_muldiv(p->angle, INT2FIX(180), GF_PI);
    1907           4 :                         count = (p->x || p->y) ? 3 : 1;
    1908           4 :                         lsr_write_vluimsbf5(lsr, count, "count");
    1909           4 :                         lsr_write_fixed_16_8(lsr, angle, "val");
    1910           4 :                         if (count==3) {
    1911           4 :                                 lsr_write_fixed_16_8(lsr, p->x, "val");
    1912           4 :                                 lsr_write_fixed_16_8(lsr, p->y, "val");
    1913             :                         }
    1914           0 :                 } else if (svg_type==SVG_Transform_Scale_datatype) {
    1915             :                         SVG_Point *pt = (SVG_Point *)val;
    1916           0 :                         count = (pt->x == pt->y) ? 1 : 2;
    1917           0 :                         lsr_write_vluimsbf5(lsr, count, "count");
    1918           0 :                         lsr_write_fixed_16_8(lsr, pt->x, "val");
    1919           0 :                         if (count==2) lsr_write_fixed_16_8(lsr, pt->y, "val");
    1920             :                 } else {
    1921           0 :                         GF_List *l = *(GF_List **)val;
    1922           0 :                         count = gf_list_count(l);
    1923           0 :                         lsr_write_vluimsbf5(lsr, count, "count");
    1924           0 :                         for (i=0; i<count; i++) {
    1925           0 :                                 Fixed *v = (Fixed *)gf_list_get(l, i);
    1926           0 :                                 lsr_write_fixed_16_8(lsr, *v, "val");
    1927             :                         }
    1928             :                 }
    1929             :         }
    1930             :         break;
    1931           2 :         case 9: // point
    1932           2 :                 if (svg_type==SVG_Motion_datatype) {
    1933           0 :                         lsr_write_coordinate(lsr, ((GF_Matrix2D*)val)->m[2], GF_FALSE, "valX");
    1934           0 :                         lsr_write_coordinate(lsr, ((GF_Matrix2D*)val)->m[5], GF_FALSE, "valY");
    1935             :                 } else {
    1936           2 :                         lsr_write_coordinate(lsr, ((SVG_Point *)val)->x, GF_FALSE, "valX");
    1937           2 :                         lsr_write_coordinate(lsr, ((SVG_Point *)val)->y, GF_FALSE, "valY");
    1938             :                 }
    1939             :                 break;
    1940           0 :         default:
    1941           0 :                 lsr_write_extension(lsr, NULL, 0, name);
    1942             :                 break;
    1943             :         }
    1944             : }
    1945             : 
    1946         260 : static void lsr_write_anim_value(GF_LASeRCodec *lsr, SMIL_AnimateValue *val, const char *name)
    1947             : {
    1948         260 :         if (!val || !val->type) {
    1949         208 :                 GF_LSR_WRITE_INT(lsr, 0, 1, name);
    1950             :         } else {
    1951          52 :                 u32 type = svg_type_to_lsr_anim(val->type, 0, NULL, val->value);
    1952          52 :                 if (type==255) {
    1953           8 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] unsupported anim type %d (%s) - skipping\n", val->type , gf_svg_attribute_type_to_string(val->type) ));
    1954           8 :                         GF_LSR_WRITE_INT(lsr, 0, 1, name);
    1955             :                 } else {
    1956          44 :                         GF_LSR_WRITE_INT(lsr, 1, 1, name);
    1957          44 :                         GF_LSR_WRITE_INT(lsr, type, 4, "type");
    1958          44 :                         lsr_write_an_anim_value(lsr, val->value, type, val->type, 0, name);
    1959             :                 }
    1960             :         }
    1961         260 : }
    1962             : 
    1963          86 : static void lsr_write_anim_values(GF_LASeRCodec *lsr, SMIL_AnimateValues *anims, const char *name)
    1964             : {
    1965             :         u32 type, i, count = 0;
    1966          86 :         if (anims && anims->type) count = gf_list_count(anims->values);
    1967             : 
    1968          42 :         if (!count) {
    1969          44 :                 GF_LSR_WRITE_INT(lsr, 0, 1, name);
    1970             :                 return;
    1971             :         }
    1972          42 :         type = svg_type_to_lsr_anim(anims->type, 0, anims->values, NULL);
    1973          42 :         if (type==255) {
    1974           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] unsupported anim type %d (%s) - skipping\n", anims->type, gf_svg_attribute_type_to_string(anims->type) ));
    1975           0 :                 GF_LSR_WRITE_INT(lsr, 0, 1, name);
    1976             :         } else {
    1977          42 :                 GF_LSR_WRITE_INT(lsr, 1, 1, name);
    1978          42 :                 GF_LSR_WRITE_INT(lsr, type, 4, "type");
    1979          42 :                 lsr_write_vluimsbf5(lsr, count, "count");
    1980         212 :                 for (i=0; i<count; i++) {
    1981         170 :                         void *att = gf_list_get(anims->values, i);
    1982         170 :                         lsr_write_an_anim_value(lsr, att, type, anims->type, 0, "a_value");
    1983             :                 }
    1984             :         }
    1985             : }
    1986             : 
    1987         172 : static void lsr_write_fraction_12(GF_LASeRCodec *lsr, GF_List **l, const char *name)
    1988             : {
    1989             :         u32 i, count;
    1990         172 :         count = l ? gf_list_count(*l) : 0;
    1991           6 :         if (!count) {
    1992         166 :                 GF_LSR_WRITE_INT(lsr, 0, 1, name);
    1993             :                 return;
    1994             :         }
    1995           6 :         GF_LSR_WRITE_INT(lsr, 1, 1, name);
    1996           6 :         lsr_write_vluimsbf5(lsr, count, "name");
    1997          44 :         for (i=0; i<count; i++) {
    1998          38 :                 Fixed f = * (Fixed *) gf_list_get(*l, i);
    1999          38 :                 if (!f || (f == FIX_ONE)) {
    2000          28 :                         GF_LSR_WRITE_INT(lsr, 1, 1, "hasShort");
    2001          28 :                         GF_LSR_WRITE_INT(lsr, f ? 0 : 1, 1, "isZero");
    2002             :                 } else {
    2003          10 :                         u32 ft = (u32) ( FIX2FLT(f) * 4096/*(1<<12)*/ );
    2004          10 :                         GF_LSR_WRITE_INT(lsr, 0, 1, "hasShort");
    2005          10 :                         GF_LSR_WRITE_INT(lsr, ft, 12, "val");
    2006             :                 }
    2007             :         }
    2008             : }
    2009          18 : static void lsr_write_float_list(GF_LASeRCodec *lsr, GF_List **l, const char *name)
    2010             : {
    2011          18 :         u32 i, count = l ? gf_list_count(*l) : 0;
    2012           2 :         if (!count) {
    2013          16 :                 GF_LSR_WRITE_INT(lsr, 0, 1, name);
    2014             :                 return;
    2015             :         }
    2016           2 :         GF_LSR_WRITE_INT(lsr, 1, 1, name);
    2017           2 :         lsr_write_vluimsbf5(lsr, count, "count");
    2018           8 :         for (i=0; i<count; i++) {
    2019           6 :                 Fixed *v = (Fixed *)gf_list_get(*l, i);
    2020           6 :                 lsr_write_fixed_16_8(lsr, *v, "val");
    2021             :         }
    2022             : }
    2023             : 
    2024         488 : static u32 lsr_get_bit_size(GF_LASeRCodec *lsr, Fixed v)
    2025             : {
    2026             :         u32 val;
    2027         488 :         v = gf_divfix(v, lsr->res_factor);
    2028         488 :         val = (v<0) ? FIX2INT(-v) : FIX2INT(v);
    2029         488 :         return 1 + gf_get_bit_size(val);
    2030             : }
    2031             : 
    2032          42 : static void lsr_write_point_sequence(GF_LASeRCodec *lsr, GF_List **pts, const char *name)
    2033             : {
    2034          42 :         u32 i, count = pts ? gf_list_count(*pts) : 0;
    2035          42 :         lsr_write_vluimsbf5(lsr, count, "nbPoints");
    2036          42 :         if (!count) return;
    2037             :         /*TODO golomb coding*/
    2038          38 :         GF_LSR_WRITE_INT(lsr, 0, 1, "flag");
    2039             :         if (1) {
    2040          38 :                 if (count < 3) {
    2041             :                         u32 nb_bits = 0;
    2042           8 :                         for (i=0; i<count; i++) {
    2043             :                                 u32 k;
    2044           8 :                                 SVG_Point *pt = (SVG_Point *)gf_list_get(*pts, i);
    2045           8 :                                 k = lsr_get_bit_size(lsr, pt->x);
    2046           8 :                                 if (k>nb_bits) nb_bits = k;
    2047           8 :                                 k = lsr_get_bit_size(lsr, pt->y);
    2048           8 :                                 if (k>nb_bits) nb_bits = k;
    2049             :                         }
    2050             : 
    2051           4 :                         GF_LSR_WRITE_INT(lsr, nb_bits, 5, "bits");
    2052           8 :                         for (i=0; i<count; i++) {
    2053           8 :                                 SVG_Point *pt = (SVG_Point *)gf_list_get(*pts, i);
    2054           8 :                                 u32 v = lsr_translate_coords(lsr, pt->x, nb_bits);
    2055           8 :                                 GF_LSR_WRITE_INT(lsr, v, nb_bits, "x");
    2056           8 :                                 v = lsr_translate_coords(lsr, pt->y, nb_bits);
    2057           8 :                                 GF_LSR_WRITE_INT(lsr, v, nb_bits, "y");
    2058             :                         }
    2059             :                 } else {
    2060             :                         Fixed c_x, c_y;
    2061             :                         u32 k, nb_dx, nb_dy;
    2062          34 :                         SVG_Point *pt = (SVG_Point *)gf_list_get(*pts, 0);
    2063             :                         nb_dx = 0;
    2064          34 :                         k = lsr_get_bit_size(lsr, pt->x);
    2065          34 :                         if (k>nb_dx) nb_dx = k;
    2066          34 :                         k = lsr_get_bit_size(lsr, pt->y);
    2067          34 :                         if (k>nb_dx) nb_dx = k;
    2068          34 :                         GF_LSR_WRITE_INT(lsr, nb_dx, 5, "bits");
    2069          34 :                         k = lsr_translate_coords(lsr, pt->x, nb_dx);
    2070          34 :                         GF_LSR_WRITE_INT(lsr, k, nb_dx, "x");
    2071          34 :                         k = lsr_translate_coords(lsr, pt->y, nb_dx);
    2072          34 :                         GF_LSR_WRITE_INT(lsr, k, nb_dx, "y");
    2073          34 :                         c_x = pt->x;
    2074          34 :                         c_y = pt->y;
    2075             :                         nb_dx = nb_dy = 0;
    2076         202 :                         for (i=1; i<count; i++) {
    2077         202 :                                 SVG_Point *a_pt = (SVG_Point *)gf_list_get(*pts, i);
    2078         202 :                                 k = lsr_get_bit_size(lsr, a_pt->x - c_x);
    2079         202 :                                 if (k>nb_dx) nb_dx = k;
    2080         202 :                                 k = lsr_get_bit_size(lsr, a_pt->y - c_y);
    2081         202 :                                 if (k>nb_dy) nb_dy = k;
    2082         202 :                                 c_x = a_pt->x;
    2083         202 :                                 c_y = a_pt->y;
    2084             :                         }
    2085          34 :                         GF_LSR_WRITE_INT(lsr, nb_dx, 5, "bitsx");
    2086          34 :                         GF_LSR_WRITE_INT(lsr, nb_dy, 5, "bitsy");
    2087          34 :                         c_x = pt->x;
    2088          34 :                         c_y = pt->y;
    2089         202 :                         for (i=1; i<count; i++) {
    2090         202 :                                 SVG_Point *a_pt = (SVG_Point *)gf_list_get(*pts, i);
    2091         202 :                                 k = lsr_translate_coords(lsr, a_pt->x - c_x, nb_dx);
    2092         202 :                                 GF_LSR_WRITE_INT(lsr, k, nb_dx, "dx");
    2093         202 :                                 k = lsr_translate_coords(lsr, a_pt->y - c_y, nb_dy);
    2094         202 :                                 GF_LSR_WRITE_INT(lsr, k, nb_dy, "dy");
    2095         202 :                                 c_x = a_pt->x;
    2096         202 :                                 c_y = a_pt->y;
    2097             :                         }
    2098             :                 }
    2099             :         }
    2100             : }
    2101          22 : static void lsr_write_path_type(GF_LASeRCodec *lsr, SVG_PathData *path, const char *name)
    2102             : {
    2103             : #if USE_GF_PATH
    2104             :         u32 i, *contour, nb_types;
    2105             :         GF_List *pts;
    2106             : 
    2107          22 :         if (!path) {
    2108           2 :                 lsr_write_vluimsbf5(lsr, 0, "nbPoints");
    2109           2 :                 lsr_write_vluimsbf5(lsr, 0, "nbOfTypes");
    2110           2 :                 return;
    2111             :         }
    2112          20 :         pts = gf_list_new();
    2113             : 
    2114          20 :         contour = path->contours;
    2115             :         nb_types = 0;
    2116         132 :         for (i=0; i<path->n_points; ) {
    2117          92 :                 switch (path->tags[i]) {
    2118          40 :                 case GF_PATH_CURVE_ON:
    2119          40 :                         gf_list_add(pts, &path->points[i]);
    2120          40 :                         nb_types++;
    2121          40 :                         i++;
    2122          40 :                         break;
    2123          14 :                 case GF_PATH_CLOSE:
    2124          14 :                         nb_types++;
    2125          14 :                         i++;
    2126          14 :                         break;
    2127           2 :                 case GF_PATH_CURVE_CONIC:
    2128           2 :                         gf_list_add(pts, &path->points[i]);
    2129           2 :                         gf_list_add(pts, &path->points[i+1]);
    2130           2 :                         i+=2;
    2131           2 :                         nb_types++;
    2132           2 :                         break;
    2133          36 :                 case GF_PATH_CURVE_CUBIC:
    2134          36 :                         gf_list_add(pts, &path->points[i]);
    2135          36 :                         gf_list_add(pts, &path->points[i+1]);
    2136          36 :                         gf_list_add(pts, &path->points[i+2]);
    2137          36 :                         i+=3;
    2138          36 :                         nb_types++;
    2139          36 :                         break;
    2140             :                 }
    2141             :         }
    2142          20 :         lsr_write_point_sequence(lsr, &pts, "seq");
    2143          20 :         gf_list_del(pts);
    2144             :         /*first moveTo is skiped*/
    2145          20 :         lsr_write_vluimsbf5(lsr, nb_types-1, "nbOfTypes");
    2146         132 :         for (i=0; i<path->n_points; ) {
    2147          92 :                 switch (path->tags[i]) {
    2148          14 :                 case GF_PATH_CLOSE:
    2149             :                         /*close*/
    2150          14 :                         GF_LSR_WRITE_INT(lsr, LSR_PATH_COM_Z, 5, name);
    2151          14 :                         i++;
    2152          14 :                         break;
    2153          40 :                 case GF_PATH_CURVE_ON:
    2154          40 :                         if (!i) {
    2155          20 :                         } else if (*contour == i-1) {
    2156             :                                 /*moveTo*/
    2157           0 :                                 GF_LSR_WRITE_INT(lsr, LSR_PATH_COM_M, 5, name);
    2158             :                         } else {
    2159             :                                 /*lineTo*/
    2160          20 :                                 GF_LSR_WRITE_INT(lsr, LSR_PATH_COM_L, 5, name);
    2161             :                         }
    2162          40 :                         i++;
    2163          40 :                         break;
    2164           2 :                 case GF_PATH_CURVE_CONIC:
    2165             :                         /*Conic*/
    2166           2 :                         GF_LSR_WRITE_INT(lsr, LSR_PATH_COM_Q, 5, name);
    2167           2 :                         i+=2;
    2168           2 :                         break;
    2169          36 :                 case GF_PATH_CURVE_CUBIC:
    2170             :                         /*cubic*/
    2171          36 :                         GF_LSR_WRITE_INT(lsr, LSR_PATH_COM_C, 5, name);
    2172          36 :                         i+=3;
    2173          36 :                         break;
    2174             :                 }
    2175             :         }
    2176             : #else
    2177             :         u32 i, count;
    2178             :         lsr_write_point_sequence(lsr, path->points, "seq");
    2179             :         /*initial move is not coded*/
    2180             :         count = gf_list_count(path->commands);
    2181             :         lsr_write_vluimsbf5(lsr, count, "nbOfTypes");
    2182             :         for (i; i<count; i++) {
    2183             :                 u8 type = *(u8 *) gf_list_get(path->commands, i);
    2184             :                 GF_LSR_WRITE_INT(lsr, type, 5, name);
    2185             :         }
    2186             : #endif
    2187             : }
    2188             : 
    2189           6 : static void lsr_write_rotate_type(GF_LASeRCodec *lsr, SVG_Rotate *rotate, const char *name)
    2190             : {
    2191           6 :         GF_LSR_WRITE_INT(lsr, rotate ? 1 : 0, 1, name);
    2192           6 :         if (!rotate) return;
    2193             : 
    2194           4 :         if ((rotate->type == SVG_NUMBER_AUTO) || (rotate->type == SVG_NUMBER_AUTO_REVERSE)) {
    2195           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "choice");
    2196           2 :                 GF_LSR_WRITE_INT(lsr, (rotate->type == SVG_NUMBER_AUTO) ? 0 : 1, 1, "rotate");
    2197             :         } else {
    2198           2 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "choice");
    2199           2 :                 lsr_write_fixed_16_8(lsr, rotate->value, "rotate");
    2200             :         }
    2201             : }
    2202           8 : static void lsr_write_sync_behavior(GF_LASeRCodec *lsr, SMIL_SyncBehavior *sync, const char *name)
    2203             : {
    2204           8 :         GF_LSR_WRITE_INT(lsr, sync ? 1 : 0, 1, name);
    2205           8 :         if (!sync) return;
    2206             :         assert(*sync!=SMIL_SYNCBEHAVIOR_INHERIT);
    2207           2 :         GF_LSR_WRITE_INT(lsr, *sync-1, 2, name);
    2208             : }
    2209           8 : static void lsr_write_sync_tolerance(GF_LASeRCodec *lsr, SMIL_SyncTolerance *sync, const char *name)
    2210             : {
    2211           8 :         GF_LSR_WRITE_INT(lsr, sync ? 1 : 0, 1, name);
    2212           8 :         if (!sync) return;
    2213             :         assert(sync->type!=SMIL_SYNCTOLERANCE_INHERIT);
    2214             : 
    2215           4 :         if (sync->type==SMIL_SYNCTOLERANCE_DEFAULT) {
    2216           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, name);
    2217             :         } else {
    2218           2 :                 GF_LSR_WRITE_INT(lsr, 0, 1, name);
    2219           2 :                 lsr_write_vluimsbf5(lsr, (u32) (sync->value*lsr->time_resolution), "value");
    2220             :         }
    2221             : }
    2222          24 : static void lsr_write_coord_list(GF_LASeRCodec *lsr, GF_List **coords, const char *name)
    2223             : {
    2224          24 :         u32 i, count = coords ? gf_list_count(*coords) : 0;
    2225          12 :         if (!count) {
    2226          12 :                 GF_LSR_WRITE_INT(lsr, 0, 1, name);
    2227             :         } else {
    2228          12 :                 GF_LSR_WRITE_INT(lsr, 1, 1, name);
    2229          12 :                 lsr_write_vluimsbf5(lsr, count, "nb_coords");
    2230          24 :                 for (i=0; i<count; i++) {
    2231          12 :                         SVG_Coordinate *c = (SVG_Coordinate *)gf_list_get(*coords, i);
    2232          12 :                         u32 res = lsr_translate_coords(lsr, c->value, lsr->coord_bits);
    2233          12 :                         GF_LSR_WRITE_INT(lsr, res, lsr->coord_bits, name);
    2234             :                 }
    2235             :         }
    2236          24 : }
    2237             : 
    2238          32 : static void lsr_write_transform_behavior(GF_LASeRCodec *lsr, SVG_TransformBehavior *type)
    2239             : {
    2240          32 :         GF_LSR_WRITE_INT(lsr, type ? 1 : 0, 1, "hasTransformBehavior");
    2241          32 :         if (!type) return;
    2242           0 :         GF_LSR_WRITE_INT(lsr, *type, 4, "transformBehavior");
    2243             : }
    2244             : 
    2245           8 : static void lsr_write_gradient_units(GF_LASeRCodec *lsr, SVG_GradientUnit *type)
    2246             : {
    2247           8 :         GF_LSR_WRITE_INT(lsr, type ? 1 : 0, 1, "hasGradientUnits");
    2248           8 :         if (!type) return;
    2249           2 :         GF_LSR_WRITE_INT(lsr, *type ? 1 : 0, 1, "gradientUnits");
    2250             : }
    2251             : 
    2252          36 : static void lsr_write_content_type(GF_LASeRCodec *lsr, SVG_String *type, const char *name)
    2253             : {
    2254          36 :         if (type) {
    2255           0 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "hasType");
    2256           0 :                 lsr_write_byte_align_string(lsr, *type, "type");
    2257             :         } else {
    2258          36 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "hasType");
    2259             :         }
    2260          36 : }
    2261           4 : static void lsr_write_script_type(GF_LASeRCodec *lsr, SVG_String *type)
    2262             : {
    2263           4 :         GF_LSR_WRITE_INT(lsr, type ? 1 : 0, 1, "hasType");
    2264           4 :         if (!type) return;
    2265           2 :         if (!strcmp(*type, "application/ecmascript")) {
    2266           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "choice");
    2267           2 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "script");
    2268           0 :         } else if (!strcmp(*type, "application/jar-archive")) {
    2269           0 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "choice");
    2270           0 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "script");
    2271             :         } else {
    2272           0 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "choice");
    2273           0 :                 lsr_write_byte_align_string(lsr, *type, "type");
    2274             :         }
    2275             : }
    2276             : 
    2277          10 : static void lsr_write_value_with_units(GF_LASeRCodec *lsr, SVG_Number *n, const char *name)
    2278             : {
    2279             :         s32 val;
    2280             : 
    2281          10 :         if (!n) {
    2282           4 :                 GF_LSR_WRITE_INT(lsr, 0, 32, name);
    2283           4 :                 GF_LSR_WRITE_INT(lsr, 0, 3, "units");
    2284             :                 return;
    2285             :         }
    2286             : 
    2287             : #ifdef GPAC_FIXED_POINT
    2288             :         val = n->value >> 8;
    2289             : #else
    2290           6 :         val = (s32) (n->value * (1<<8) );
    2291             : #endif
    2292           6 :         GF_LSR_WRITE_INT(lsr, val, 32, name);
    2293           6 :         switch (n->type) {
    2294           0 :         case SVG_NUMBER_IN:
    2295           0 :                 GF_LSR_WRITE_INT(lsr, 1, 3, "units");
    2296             :                 break;
    2297           0 :         case SVG_NUMBER_CM:
    2298           0 :                 GF_LSR_WRITE_INT(lsr, 2, 3, "units");
    2299             :                 break;
    2300           0 :         case SVG_NUMBER_MM:
    2301           0 :                 GF_LSR_WRITE_INT(lsr, 3, 3, "units");
    2302             :                 break;
    2303           0 :         case SVG_NUMBER_PT:
    2304           0 :                 GF_LSR_WRITE_INT(lsr, 4, 3, "units");
    2305             :                 break;
    2306           0 :         case SVG_NUMBER_PC:
    2307           0 :                 GF_LSR_WRITE_INT(lsr, 5, 3, "units");
    2308             :                 break;
    2309           2 :         case SVG_NUMBER_PERCENTAGE:
    2310           2 :                 GF_LSR_WRITE_INT(lsr, 6, 3, "units");
    2311             :                 break;
    2312           4 :         default:
    2313           4 :                 GF_LSR_WRITE_INT(lsr, 0, 3, "units");
    2314             :                 break;
    2315             :         }
    2316             : }
    2317             : 
    2318             : 
    2319          16 : static void lsr_write_clip_time(GF_LASeRCodec *lsr, SVG_Clock *clock, const char *name)
    2320             : {
    2321          16 :         if (!clock || *clock <= 0) {
    2322          14 :                 GF_LSR_WRITE_INT(lsr, 0, 1, name);
    2323             :         } else {
    2324           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, name);
    2325           2 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "isEnum");
    2326           2 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "sign");
    2327           2 :                 lsr_write_vluimsbf5(lsr, (u32) (lsr->time_resolution**clock), "val");
    2328             :         }
    2329          16 : }
    2330             : 
    2331          88 : static void lsr_write_href_anim(GF_LASeRCodec *lsr, XMLRI *href, SVG_Element *parent)
    2332             : {
    2333          88 :         if (!href || (href->target && (href->target==parent))) {
    2334          56 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "has_href");
    2335             :         } else {
    2336          32 :                 lsr_write_href(lsr, href);
    2337             :         }
    2338          88 : }
    2339             : 
    2340          88 : static void lsr_write_attribute_type(GF_LASeRCodec *lsr, SVGAllAttributes *atts)
    2341             : {
    2342          88 :         if (!atts->attributeType) {
    2343          88 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "hasAttributeType");
    2344             :         } else {
    2345           0 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "hasAttributeType");
    2346           0 :                 GF_LSR_WRITE_INT(lsr, (*atts->attributeType), 2, "attributeType");
    2347             :         }
    2348          88 : }
    2349             : 
    2350          36 : static void lsr_write_preserve_aspect_ratio(GF_LASeRCodec *lsr, SVG_PreserveAspectRatio *preserveAspectRatio)
    2351             : {
    2352          36 :         GF_LSR_WRITE_INT(lsr, preserveAspectRatio ? 1 : 0, 1, "hasPreserveAspectRatio");
    2353          36 :         if (!preserveAspectRatio) return;
    2354          26 :         GF_LSR_WRITE_INT(lsr, 0, 1, "choice (meetOrSlice)");
    2355          26 :         GF_LSR_WRITE_INT(lsr, preserveAspectRatio->defer ? 1 : 0, 1, "choice (defer)");
    2356          26 :         switch (preserveAspectRatio->align) {
    2357           2 :         case SVG_PRESERVEASPECTRATIO_XMAXYMAX:
    2358           2 :                 GF_LSR_WRITE_INT(lsr, 1, 4, "alignXandY");
    2359             :                 break;
    2360           2 :         case SVG_PRESERVEASPECTRATIO_XMAXYMID:
    2361           2 :                 GF_LSR_WRITE_INT(lsr, 2, 4, "alignXandY");
    2362             :                 break;
    2363           2 :         case SVG_PRESERVEASPECTRATIO_XMAXYMIN:
    2364           2 :                 GF_LSR_WRITE_INT(lsr, 3, 4, "alignXandY");
    2365             :                 break;
    2366           2 :         case SVG_PRESERVEASPECTRATIO_XMIDYMAX:
    2367           2 :                 GF_LSR_WRITE_INT(lsr, 4, 4, "alignXandY");
    2368             :                 break;
    2369           8 :         case SVG_PRESERVEASPECTRATIO_XMIDYMID:
    2370           8 :                 GF_LSR_WRITE_INT(lsr, 5, 4, "alignXandY");
    2371             :                 break;
    2372           2 :         case SVG_PRESERVEASPECTRATIO_XMIDYMIN:
    2373           2 :                 GF_LSR_WRITE_INT(lsr, 6, 4, "alignXandY");
    2374             :                 break;
    2375           2 :         case SVG_PRESERVEASPECTRATIO_XMINYMAX:
    2376           2 :                 GF_LSR_WRITE_INT(lsr, 7, 4, "alignXandY");
    2377             :                 break;
    2378           2 :         case SVG_PRESERVEASPECTRATIO_XMINYMID:
    2379           2 :                 GF_LSR_WRITE_INT(lsr, 8, 4, "alignXandY");
    2380             :                 break;
    2381           2 :         case SVG_PRESERVEASPECTRATIO_XMINYMIN:
    2382           2 :                 GF_LSR_WRITE_INT(lsr, 9, 4, "alignXandY");
    2383             :                 break;
    2384           2 :         default:
    2385           2 :                 GF_LSR_WRITE_INT(lsr, 0, 4, "alignXandY");
    2386             :                 break;
    2387             :         }
    2388             : }
    2389             : 
    2390             : 
    2391             : #define lsr_write_err() GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired")
    2392             : 
    2393             : 
    2394          10 : static void lsr_write_a(GF_LASeRCodec *lsr, SVG_Element *elt)
    2395             : {
    2396             :         SVGAllAttributes atts;
    2397          10 :         gf_svg_flatten_attributes(elt, &atts);
    2398             : 
    2399          10 :         lsr_write_id(lsr, (GF_Node *) elt);
    2400          10 :         lsr_write_rare(lsr, (GF_Node *) elt);
    2401          10 :         lsr_write_fill(lsr,  elt, &atts);
    2402          10 :         lsr_write_stroke(lsr,  elt, &atts);
    2403          10 :         lsr_write_err();
    2404          10 :         GF_LSR_WRITE_INT(lsr, (atts.target!=NULL) ? 1 : 0, 1, "hasTarget");
    2405          10 :         if (atts.target) lsr_write_byte_align_string(lsr, *(SVG_String*)atts.target, "target");
    2406          10 :         lsr_write_href(lsr, atts.xlink_href);
    2407          10 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2408          10 :         lsr_write_group_content(lsr,  elt, GF_FALSE);
    2409          10 : }
    2410             : 
    2411          70 : static void lsr_write_animate(GF_LASeRCodec *lsr, SVG_Element *elt, SVG_Element *parent)
    2412             : {
    2413             :         SVGAllAttributes atts;
    2414          70 :         gf_svg_flatten_attributes(elt, &atts);
    2415             : 
    2416          70 :         lsr_write_id(lsr, (GF_Node *) elt);
    2417          70 :         lsr_write_rare(lsr, (GF_Node *) elt);
    2418          70 :         lsr_write_animatable(lsr, atts.attributeName, atts.xlink_href, "attributeName");
    2419             : 
    2420          70 :         lsr_write_accumulate(lsr, atts.accumulate);
    2421          70 :         lsr_write_additive(lsr, atts.additive);
    2422          70 :         lsr_write_anim_value(lsr, atts.by, "by");
    2423          70 :         lsr_write_calc_mode(lsr, atts.calcMode);
    2424          70 :         lsr_write_anim_value(lsr, atts.from, "from");
    2425          70 :         lsr_write_fraction_12(lsr, atts.keySplines, "keySplines");
    2426          70 :         lsr_write_fraction_12(lsr, atts.keyTimes, "keyTimes");
    2427          70 :         lsr_write_anim_values(lsr, atts.values, "values");
    2428          70 :         lsr_write_attribute_type(lsr, &atts);
    2429          70 :         lsr_write_smil_times(lsr, atts.begin, "begin", GF_TRUE);
    2430          70 :         lsr_write_duration(lsr, atts.dur, "dur");
    2431          70 :         lsr_write_anim_fill(lsr, atts.smil_fill);
    2432          70 :         lsr_write_anim_repeat(lsr, atts.repeatCount);
    2433          70 :         lsr_write_repeat_duration(lsr, atts.repeatDur);
    2434          70 :         lsr_write_anim_restart(lsr, atts.restart);
    2435          70 :         lsr_write_anim_value(lsr, atts.to, "to");
    2436          70 :         lsr_write_href_anim(lsr, atts.xlink_href, parent);
    2437          70 :         GF_LSR_WRITE_INT(lsr, (atts.lsr_enabled && *atts.lsr_enabled) ? 1 : 0, 1, "enabled");
    2438             : 
    2439          70 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2440          70 :         lsr_write_group_content(lsr, elt, GF_FALSE);
    2441          70 : }
    2442             : 
    2443             : 
    2444           6 : static void lsr_write_animateMotion(GF_LASeRCodec *lsr, SVG_Element*elt, SVG_Element *parent)
    2445             : {
    2446             :         SVGAllAttributes atts;
    2447           6 :         gf_svg_flatten_attributes(elt, &atts);
    2448             : 
    2449           6 :         lsr_write_id(lsr, (GF_Node *) elt);
    2450           6 :         lsr_write_rare(lsr, (GF_Node *) elt);
    2451           6 :         lsr_write_accumulate(lsr, atts.accumulate);
    2452           6 :         lsr_write_additive(lsr, atts.additive);
    2453           6 :         lsr_write_anim_value(lsr, atts.by, "by");
    2454           6 :         lsr_write_calc_mode(lsr, atts.calcMode);
    2455           6 :         lsr_write_anim_value(lsr, atts.from, "from");
    2456           6 :         lsr_write_fraction_12(lsr, atts.keySplines, "keySplines");
    2457           6 :         lsr_write_fraction_12(lsr, atts.keyTimes, "keyTimes");
    2458           6 :         lsr_write_anim_values(lsr, atts.values, "values");
    2459           6 :         lsr_write_attribute_type(lsr, &atts);
    2460           6 :         lsr_write_smil_times(lsr, atts.begin, "begin", GF_TRUE);
    2461           6 :         lsr_write_duration(lsr, atts.dur, "dur");
    2462           6 :         lsr_write_anim_fill(lsr, atts.smil_fill);
    2463           6 :         lsr_write_anim_repeat(lsr, atts.repeatCount);
    2464           6 :         lsr_write_repeat_duration(lsr, atts.repeatDur);
    2465           6 :         lsr_write_anim_restart(lsr, atts.restart);
    2466           6 :         lsr_write_anim_value(lsr, atts.to, "to");
    2467             : 
    2468           6 :         lsr_write_float_list(lsr, atts.keyPoints, "keyPoints");
    2469           6 :         if (atts.path) {
    2470           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "hasPath");
    2471           2 :                 lsr_write_path_type(lsr, atts.path, "path");
    2472             :         } else {
    2473           4 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "hasPath");
    2474             :         }
    2475           6 :         lsr_write_rotate_type(lsr, atts.rotate, "rotate");
    2476             : 
    2477           6 :         lsr_write_href_anim(lsr, atts.xlink_href, parent);
    2478           6 :         GF_LSR_WRITE_INT(lsr, (atts.lsr_enabled && *atts.lsr_enabled) ? 1 : 0, 1, "enabled");
    2479           6 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2480           6 :         lsr_write_group_content(lsr, elt, GF_FALSE);
    2481           6 : }
    2482             : 
    2483          10 : static void lsr_write_animateTransform(GF_LASeRCodec *lsr, SVG_Element *elt, SVG_Element *parent)
    2484             : {
    2485             :         u32 type;
    2486             :         SVGAllAttributes atts;
    2487          10 :         gf_svg_flatten_attributes(elt, &atts);
    2488             : 
    2489          10 :         lsr_write_id(lsr, (GF_Node *) elt);
    2490          10 :         lsr_write_rare(lsr, (GF_Node *) elt);
    2491          10 :         lsr_write_animatable(lsr, atts.attributeName, atts.xlink_href, "attributeName");
    2492             : 
    2493             :         /*no default value for type or we MUST code it in LASeR ...*/
    2494          10 :         type = atts.transform_type ? *atts.transform_type : SVG_TRANSFORM_TRANSLATE;
    2495             :         /*enumeration rotate{0} scale{1} skewX{2} skewY{3} translate{4}*/
    2496          10 :         switch (type) {
    2497           2 :         case SVG_TRANSFORM_ROTATE:
    2498           2 :                 GF_LSR_WRITE_INT(lsr, 0, 3, "rotscatra");
    2499             :                 break;
    2500           0 :         case SVG_TRANSFORM_SCALE:
    2501           0 :                 GF_LSR_WRITE_INT(lsr, 1, 3, "rotscatra");
    2502             :                 break;
    2503           2 :         case SVG_TRANSFORM_SKEWX:
    2504           2 :                 GF_LSR_WRITE_INT(lsr, 2, 3, "rotscatra");
    2505             :                 break;
    2506           2 :         case SVG_TRANSFORM_SKEWY:
    2507           2 :                 GF_LSR_WRITE_INT(lsr, 3, 3, "rotscatra");
    2508             :                 break;
    2509           4 :         case SVG_TRANSFORM_TRANSLATE:
    2510           4 :                 GF_LSR_WRITE_INT(lsr, 4, 3, "rotscatra");
    2511             :                 break;
    2512             :         }
    2513             : 
    2514          10 :         lsr_write_accumulate(lsr, atts.accumulate);
    2515          10 :         lsr_write_additive(lsr, atts.additive);
    2516          10 :         lsr_write_anim_value(lsr, atts.by, "by");
    2517          10 :         lsr_write_calc_mode(lsr, atts.calcMode);
    2518          10 :         lsr_write_anim_value(lsr, atts.from, "from");
    2519          10 :         lsr_write_fraction_12(lsr, atts.keySplines, "keySplines");
    2520          10 :         lsr_write_fraction_12(lsr, atts.keyTimes, "keyTimes");
    2521          10 :         lsr_write_anim_values(lsr, atts.values, "values");
    2522          10 :         lsr_write_attribute_type(lsr, &atts);
    2523          10 :         lsr_write_smil_times(lsr, atts.begin, "begin", GF_TRUE);
    2524          10 :         lsr_write_duration(lsr, atts.dur, "dur");
    2525          10 :         lsr_write_anim_fill(lsr, atts.smil_fill);
    2526          10 :         lsr_write_anim_repeat(lsr, atts.repeatCount);
    2527          10 :         lsr_write_repeat_duration(lsr, atts.repeatDur);
    2528          10 :         lsr_write_anim_restart(lsr, atts.restart);
    2529          10 :         lsr_write_anim_value(lsr, atts.to, "to");
    2530             : 
    2531          10 :         lsr_write_href_anim(lsr, atts.xlink_href, parent);
    2532          10 :         GF_LSR_WRITE_INT(lsr, (atts.lsr_enabled && *atts.lsr_enabled) ? 1 : 0, 1, "enabled");
    2533          10 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2534          10 :         lsr_write_group_content(lsr, elt, GF_FALSE);
    2535          10 : }
    2536             : 
    2537           4 : static void lsr_write_audio(GF_LASeRCodec *lsr, SVG_Element *elt)
    2538             : {
    2539             :         SVGAllAttributes atts;
    2540           4 :         gf_svg_flatten_attributes(elt, &atts);
    2541             : 
    2542           4 :         lsr_write_id(lsr, (GF_Node *) elt);
    2543           4 :         lsr_write_rare(lsr, (GF_Node *) elt);
    2544           4 :         lsr_write_smil_times(lsr, atts.begin, "begin", GF_TRUE);
    2545           4 :         lsr_write_duration(lsr, atts.dur, "dur");
    2546           4 :         GF_LSR_WRITE_INT(lsr, atts.externalResourcesRequired ? *atts.externalResourcesRequired : 0, 1, "externalResourcesRequired");
    2547           4 :         lsr_write_anim_repeat(lsr, atts.repeatCount);
    2548           4 :         lsr_write_repeat_duration(lsr, atts.repeatDur);
    2549           4 :         lsr_write_anim_restart(lsr, atts.restart);
    2550           4 :         lsr_write_sync_behavior(lsr, atts.syncBehavior, "syncBehavior");
    2551           4 :         lsr_write_sync_tolerance(lsr, atts.syncTolerance, "syncTolerance");
    2552           4 :         lsr_write_content_type(lsr, atts.xlink_type, "type");
    2553           4 :         lsr_write_href(lsr, atts.xlink_href);
    2554             : 
    2555           4 :         lsr_write_clip_time(lsr, atts.clipBegin, "clipBegin");
    2556           4 :         lsr_write_clip_time(lsr, atts.clipEnd, "clipEnd");
    2557           4 :         GF_LSR_WRITE_INT(lsr, atts.syncReference ? 1 : 0, 1, "hasSyncReference");
    2558           4 :         if (atts.syncReference) lsr_write_any_uri(lsr, atts.syncReference, "syncReference");
    2559             : 
    2560           4 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2561           4 :         lsr_write_group_content(lsr, elt, GF_FALSE);
    2562           4 : }
    2563           8 : static void lsr_write_circle(GF_LASeRCodec *lsr, SVG_Element *elt)
    2564             : {
    2565             :         SVGAllAttributes atts;
    2566           8 :         gf_svg_flatten_attributes(elt, &atts);
    2567             : 
    2568           8 :         lsr_write_id(lsr, (GF_Node *) elt);
    2569           8 :         lsr_write_rare(lsr, (GF_Node *) elt);
    2570           8 :         lsr_write_fill(lsr, (SVG_Element*)elt, &atts);
    2571           8 :         lsr_write_stroke(lsr, (SVG_Element*)elt, &atts);
    2572           8 :         lsr_write_coordinate_ptr(lsr, atts.cx, GF_TRUE, "cx");
    2573           8 :         lsr_write_coordinate_ptr(lsr, atts.cy, GF_TRUE, "cy");
    2574           8 :         lsr_write_coordinate_ptr(lsr, atts.r, GF_FALSE, "r");
    2575           8 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2576           8 :         lsr_write_group_content(lsr,  elt, GF_FALSE);
    2577           8 : }
    2578           4 : static void lsr_write_conditional(GF_LASeRCodec *lsr, SVG_Element *elt)
    2579             : {
    2580             :         GF_DOMUpdates *up;
    2581             :         SVGAllAttributes atts;
    2582           4 :         gf_svg_flatten_attributes(elt, &atts);
    2583             : 
    2584           4 :         lsr_write_id(lsr, (GF_Node *) elt);
    2585           4 :         lsr_write_rare(lsr, (GF_Node *) elt);
    2586           4 :         lsr_write_smil_times(lsr, atts.begin, "begin", 1);
    2587           4 :         GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired");
    2588           4 :         GF_LSR_WRITE_INT(lsr, (atts.lsr_enabled && *atts.lsr_enabled) ? 1 : 0, 1, "enabled");
    2589           4 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2590           4 :         up = elt->children ? (GF_DOMUpdates*)elt->children->node : NULL;
    2591           2 :         lsr_write_command_list(lsr, up ? up->updates : NULL, elt, GF_FALSE);
    2592           4 :         lsr_write_private_attributes(lsr, elt);
    2593           4 : }
    2594             : 
    2595           2 : static void lsr_write_cursorManager(GF_LASeRCodec *lsr, SVG_Element *elt)
    2596             : {
    2597             :         SVGAllAttributes atts;
    2598           2 :         gf_svg_flatten_attributes(elt, &atts);
    2599             : 
    2600           2 :         lsr_write_id(lsr, (GF_Node *) elt);
    2601           2 :         lsr_write_rare(lsr, (GF_Node *) elt);
    2602           2 :         lsr_write_coordinate_ptr(lsr, atts.x, GF_TRUE, "x");
    2603           2 :         lsr_write_coordinate_ptr(lsr, atts.x, GF_TRUE, "y");
    2604           2 :         lsr_write_href(lsr, atts.xlink_href);
    2605           2 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2606           2 :         lsr_write_group_content(lsr, elt, GF_FALSE);
    2607           2 : }
    2608             : 
    2609           8 : static void lsr_write_data(GF_LASeRCodec *lsr, SVG_Element *elt)
    2610             : {
    2611           8 :         lsr_write_id(lsr, (GF_Node *) elt);
    2612           8 :         lsr_write_rare(lsr, (GF_Node *) elt);
    2613           8 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2614           8 :         lsr_write_group_content(lsr, elt, GF_FALSE);
    2615           8 : }
    2616             : 
    2617           2 : static void lsr_write_defs(GF_LASeRCodec *lsr, SVG_Element *elt)
    2618             : {
    2619             :         SVGAllAttributes atts;
    2620           2 :         gf_svg_flatten_attributes(elt, &atts);
    2621             : 
    2622           2 :         lsr_write_id(lsr, (GF_Node *) elt);
    2623           2 :         lsr_write_rare(lsr, (GF_Node *) elt);
    2624           2 :         lsr_write_fill(lsr, (SVG_Element*)elt, &atts);
    2625           2 :         lsr_write_stroke(lsr, (SVG_Element*)elt, &atts);
    2626           2 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2627           2 :         lsr_write_group_content(lsr, elt, GF_FALSE);
    2628           2 : }
    2629           2 : static void lsr_write_ellipse(GF_LASeRCodec *lsr, SVG_Element *elt)
    2630             : {
    2631             :         SVGAllAttributes atts;
    2632           2 :         gf_svg_flatten_attributes(elt, &atts);
    2633             : 
    2634           2 :         lsr_write_id(lsr, (GF_Node *) elt);
    2635           2 :         lsr_write_rare(lsr, (GF_Node *) elt);
    2636           2 :         lsr_write_fill(lsr, (SVG_Element*)elt, &atts);
    2637           2 :         lsr_write_stroke(lsr, (SVG_Element*)elt, &atts);
    2638           2 :         lsr_write_coordinate_ptr(lsr, atts.cx, GF_TRUE, "cx");
    2639           2 :         lsr_write_coordinate_ptr(lsr, atts.cy, GF_TRUE, "cy");
    2640           2 :         lsr_write_coordinate_ptr(lsr, atts.rx, GF_FALSE, "rx");
    2641           2 :         lsr_write_coordinate_ptr(lsr, atts.ry, GF_FALSE, "ry");
    2642           2 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2643           2 :         lsr_write_group_content(lsr, elt, GF_FALSE);
    2644           2 : }
    2645           2 : static void lsr_write_foreignObject(GF_LASeRCodec *lsr, SVG_Element *elt)
    2646             : {
    2647             :         SVGAllAttributes atts;
    2648           2 :         gf_svg_flatten_attributes(elt, &atts);
    2649             : 
    2650           2 :         lsr_write_id(lsr, (GF_Node *) elt);
    2651           2 :         lsr_write_rare(lsr, (GF_Node *) elt);
    2652           2 :         lsr_write_fill(lsr, (SVG_Element*)elt, &atts);
    2653           2 :         lsr_write_stroke(lsr, (SVG_Element*)elt, &atts);
    2654           2 :         GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired&&*atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired");
    2655           2 :         lsr_write_coordinate_ptr(lsr, atts.height, GF_FALSE, "height");
    2656           2 :         lsr_write_coordinate_ptr(lsr, atts.width, GF_FALSE, "width");
    2657           2 :         lsr_write_coordinate_ptr(lsr, atts.x, GF_TRUE, "x");
    2658           2 :         lsr_write_coordinate_ptr(lsr, atts.y, GF_TRUE, "y");
    2659             : 
    2660           2 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2661             :         /*      TODO
    2662             :                 bit(1) opt_group;
    2663             :                 if(opt_group) {
    2664             :                         vluimsbf5 occ1;
    2665             :                         for(int t=0;t<occ1;t++) {
    2666             :                                 privateElementContainer child0[[t]];
    2667             :                         }
    2668             :                 }
    2669             :         */
    2670           2 :         GF_LSR_WRITE_INT(lsr, 0, 1, "opt_group");
    2671           2 : }
    2672             : 
    2673             : 
    2674          20 : static void lsr_write_g(GF_LASeRCodec *lsr, SVG_Element *elt, Bool ommit_tag)
    2675             : {
    2676             :         Bool is_same = GF_FALSE;
    2677             :         Bool same_fill;
    2678             :         SVGAllAttributes atts;
    2679          20 :         gf_svg_flatten_attributes(elt, &atts);
    2680             : 
    2681             : 
    2682          20 :         if (!ommit_tag
    2683          18 :                 && lsr_elt_has_same_base(lsr, &atts, lsr->prev_g, &same_fill, NULL, GF_FALSE)
    2684           0 :                 && same_fill
    2685             :            ) {
    2686             :                 /*samegType*/
    2687           0 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_sameg, 6, "ch4");
    2688           0 :                 lsr_write_id(lsr, (GF_Node *) elt);
    2689           0 :                 is_same = GF_TRUE;
    2690             :         } else {
    2691             :                 /*gType*/
    2692          20 :                 if (!ommit_tag) GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_g, 6, "ch4");
    2693             : 
    2694          20 :                 lsr_write_id(lsr, (GF_Node *) elt);
    2695          20 :                 lsr_write_rare(lsr, (GF_Node *) elt);
    2696          20 :                 lsr_write_fill(lsr, (SVG_Element*)elt, &atts);
    2697          20 :                 lsr_write_stroke(lsr, (SVG_Element*)elt, &atts);
    2698          20 :                 GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired");
    2699          20 :                 lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2700          20 :                 lsr->prev_g = elt;
    2701             :         }
    2702          20 :         lsr_write_group_content(lsr, elt, is_same);
    2703          20 : }
    2704          28 : static void lsr_write_image(GF_LASeRCodec *lsr, SVG_Element *elt)
    2705             : {
    2706             :         SVGAllAttributes atts;
    2707          28 :         gf_svg_flatten_attributes(elt, &atts);
    2708             : 
    2709          28 :         lsr_write_id(lsr, (GF_Node *) elt);
    2710          28 :         lsr_write_rare(lsr, (GF_Node *) elt);
    2711          28 :         GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired");
    2712          28 :         lsr_write_coordinate_ptr(lsr, atts.height, GF_TRUE, "height");
    2713             : 
    2714          28 :         if (atts.opacity && (atts.opacity->type == SVG_NUMBER_VALUE)) {
    2715           0 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "opacity");
    2716           0 :                 lsr_write_fixed_clamp(lsr, atts.opacity->value, "opacity");
    2717             :         } else {
    2718          28 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "opacity");
    2719             :         }
    2720          28 :         lsr_write_preserve_aspect_ratio(lsr, atts.preserveAspectRatio);
    2721             : 
    2722          28 :         lsr_write_content_type(lsr, atts.xlink_type, "type");
    2723          28 :         lsr_write_coordinate_ptr(lsr, atts.width, GF_TRUE, "width");
    2724          28 :         lsr_write_coordinate_ptr(lsr, atts.x, GF_TRUE, "x");
    2725          28 :         lsr_write_coordinate_ptr(lsr, atts.y, GF_TRUE, "y");
    2726          28 :         lsr_write_href(lsr, atts.xlink_href);
    2727          28 :         lsr_write_transform_behavior(lsr, atts.transformBehavior);
    2728          28 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2729          28 :         lsr_write_group_content(lsr, elt, GF_FALSE);
    2730          28 : }
    2731           4 : static void lsr_write_line(GF_LASeRCodec *lsr, SVG_Element *elt, Bool ommit_tag)
    2732             : {
    2733             :         Bool same_fill;
    2734             :         Bool is_same = GF_FALSE;
    2735             :         SVGAllAttributes atts;
    2736           4 :         gf_svg_flatten_attributes(elt, &atts);
    2737             : 
    2738           4 :         if (!ommit_tag && lsr_elt_has_same_base(lsr, &atts, lsr->prev_line, &same_fill, NULL, GF_FALSE)
    2739           0 :                 && same_fill
    2740             :            ) {
    2741             :                 /*samelineType*/
    2742           0 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_sameline, 6, "ch4");
    2743           0 :                 lsr_write_id(lsr, (GF_Node *) elt);
    2744           0 :                 is_same = GF_TRUE;
    2745             :         } else {
    2746             :                 /*lineType*/
    2747           4 :                 if (!ommit_tag) GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_line, 6, "ch4");
    2748             : 
    2749           4 :                 lsr_write_id(lsr, (GF_Node *) elt);
    2750           4 :                 lsr_write_rare(lsr, (GF_Node *) elt);
    2751           4 :                 lsr_write_fill(lsr,  elt, &atts);
    2752           4 :                 lsr_write_stroke(lsr,  elt, &atts);
    2753             :         }
    2754             : 
    2755           4 :         lsr_write_coordinate_ptr(lsr, atts.x1, GF_TRUE, "x1");
    2756           4 :         lsr_write_coordinate_ptr(lsr, atts.x2, GF_FALSE, "x2");
    2757           4 :         lsr_write_coordinate_ptr(lsr, atts.y1, GF_TRUE, "y1");
    2758           4 :         lsr_write_coordinate_ptr(lsr, atts.y2, GF_FALSE, "y2");
    2759           4 :         if (!is_same) {
    2760           4 :                 lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2761           4 :                 lsr->prev_line = elt;
    2762             :         }
    2763           4 :         lsr_write_group_content(lsr, elt, is_same);
    2764           4 : }
    2765           6 : static void lsr_write_linearGradient(GF_LASeRCodec *lsr, SVG_Element *elt)
    2766             : {
    2767             :         SVGAllAttributes atts;
    2768           6 :         gf_svg_flatten_attributes(elt, &atts);
    2769             : 
    2770           6 :         lsr_write_id(lsr, (GF_Node *) elt);
    2771           6 :         lsr_write_rare(lsr, (GF_Node *) elt);
    2772           6 :         lsr_write_fill(lsr,  elt, &atts);
    2773           6 :         lsr_write_stroke(lsr,  elt, &atts);
    2774           6 :         lsr_write_gradient_units(lsr, atts.gradientUnits);
    2775           6 :         lsr_write_coordinate_ptr(lsr, atts.x1, GF_TRUE, "x1");
    2776           6 :         lsr_write_coordinate_ptr(lsr, atts.x2, GF_TRUE, "x2");
    2777           6 :         lsr_write_coordinate_ptr(lsr, atts.y1, GF_TRUE, "y1");
    2778           6 :         lsr_write_coordinate_ptr(lsr, atts.y2, GF_TRUE, "y2");
    2779           6 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2780           6 :         lsr_write_group_content(lsr, elt, GF_FALSE);
    2781           6 : }
    2782           4 : static void lsr_write_mpath(GF_LASeRCodec *lsr, SVG_Element *elt)
    2783             : {
    2784             :         SVGAllAttributes atts;
    2785           4 :         gf_svg_flatten_attributes(elt, &atts);
    2786             : 
    2787           4 :         lsr_write_id(lsr, (GF_Node *) elt);
    2788           4 :         lsr_write_rare(lsr, (GF_Node *) elt);
    2789           4 :         lsr_write_href(lsr, atts.xlink_href);
    2790           4 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2791           4 :         lsr_write_group_content(lsr, elt, GF_FALSE);
    2792           4 : }
    2793          16 : static void lsr_write_path(GF_LASeRCodec *lsr, SVG_Element *elt, Bool ommit_tag)
    2794             : {
    2795             :         Bool same_fill;
    2796             :         Bool is_same = GF_FALSE;
    2797             :         SVGAllAttributes atts;
    2798          16 :         gf_svg_flatten_attributes(elt, &atts);
    2799             : 
    2800          16 :         if (!ommit_tag && lsr_elt_has_same_base(lsr, &atts, lsr->prev_path, &same_fill, NULL, GF_FALSE) ) {
    2801             :                 is_same = GF_TRUE;
    2802           4 :                 if (!same_fill) {
    2803             :                         /*samepathfillType*/
    2804           2 :                         GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_samepathfill, 6, "ch4");
    2805           2 :                         lsr_write_id(lsr, (GF_Node *) elt);
    2806           2 :                         lsr_write_fill(lsr,  elt, &atts);
    2807             :                 } else {
    2808             :                         /*samepathType*/
    2809           2 :                         GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_samepath, 6, "ch4");
    2810           2 :                         lsr_write_id(lsr, (GF_Node *) elt);
    2811             :                 }
    2812           4 :                 lsr_write_path_type(lsr, atts.d, "d");
    2813             :         } else {
    2814             :                 /*pathType*/
    2815          12 :                 if (!ommit_tag) GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_path, 6, "ch4");
    2816             : 
    2817          12 :                 lsr_write_id(lsr, (GF_Node *) elt);
    2818          12 :                 lsr_write_rare(lsr, (GF_Node *) elt);
    2819          12 :                 lsr_write_fill(lsr,  elt, &atts);
    2820          12 :                 lsr_write_stroke(lsr,  elt, &atts);
    2821          12 :                 lsr_write_path_type(lsr, atts.d, "d");
    2822          12 :                 if (atts.pathLength) {
    2823           0 :                         GF_LSR_WRITE_INT(lsr, 1, 1, "hasPathLength");
    2824           0 :                         lsr_write_fixed_16_8(lsr, atts.pathLength->value, "pathLength");
    2825             :                 } else {
    2826          12 :                         GF_LSR_WRITE_INT(lsr, 0, 1, "hasPathLength");
    2827             :                 }
    2828          12 :                 lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2829          12 :                 lsr->prev_path = elt;
    2830             :         }
    2831          16 :         lsr_write_group_content(lsr, elt, is_same);
    2832          16 : }
    2833          22 : static void lsr_write_polygon(GF_LASeRCodec *lsr, SVG_Element *elt, Bool is_polyline, Bool ommit_tag)
    2834             : {
    2835             :         Bool same_fill, same_stroke;
    2836             :         u32 same_type = 0;
    2837             : 
    2838             :         SVGAllAttributes atts;
    2839          22 :         gf_svg_flatten_attributes(elt, &atts);
    2840             : 
    2841          22 :         if (!ommit_tag && lsr_elt_has_same_base(lsr, &atts, lsr->prev_polygon, &same_fill, &same_stroke, GF_TRUE)
    2842             :            ) {
    2843           6 :                 if (same_fill && same_stroke) same_type = 1;
    2844           4 :                 else if (same_fill) same_type = 3;
    2845           4 :                 else if (same_stroke) same_type = 2;
    2846             :         }
    2847             : 
    2848             :         if (same_type) {
    2849             :                 /*samepolylineType / samepolygonType */
    2850           6 :                 u8 type = is_polyline ? LSR_SCENE_CONTENT_MODEL_samepolyline : LSR_SCENE_CONTENT_MODEL_samepolygon;
    2851             :                 /*samepolylinefillType  / samepolygonfillType */
    2852           6 :                 if (same_type==2) type = is_polyline ? LSR_SCENE_CONTENT_MODEL_samepolylinefill : LSR_SCENE_CONTENT_MODEL_samepolygonfill;
    2853             :                 /*samepolylinestrokeType  / samepolygonstrokeType*/
    2854           2 :                 else if (same_type==3) type = is_polyline ? LSR_SCENE_CONTENT_MODEL_samepolylinestroke : LSR_SCENE_CONTENT_MODEL_samepolygonstroke;
    2855             : 
    2856           6 :                 GF_LSR_WRITE_INT(lsr, type, 6, "ch4");
    2857           6 :                 lsr_write_id(lsr, (GF_Node *) elt);
    2858           6 :                 if (same_type==2) lsr_write_fill(lsr, elt, &atts);
    2859           2 :                 else if (same_type==3) lsr_write_stroke(lsr, elt, &atts);
    2860           6 :                 lsr_write_point_sequence(lsr, atts.points, "points");
    2861             :         } else {
    2862             :                 /*polyline/polygon*/
    2863          16 :                 if (!ommit_tag) GF_LSR_WRITE_INT(lsr, is_polyline ? LSR_SCENE_CONTENT_MODEL_polyline : LSR_SCENE_CONTENT_MODEL_polygon, 6, "ch4");
    2864             : 
    2865          16 :                 lsr_write_id(lsr, (GF_Node *) elt);
    2866          16 :                 lsr_write_rare(lsr, (GF_Node *) elt);
    2867          16 :                 lsr_write_fill(lsr, elt, &atts);
    2868          16 :                 lsr_write_stroke(lsr, elt, &atts);
    2869          16 :                 lsr_write_point_sequence(lsr, atts.points, "points");
    2870          16 :                 lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2871          16 :                 lsr->prev_polygon = elt;
    2872             :         }
    2873          22 :         lsr_write_group_content(lsr, elt, same_type);
    2874          22 : }
    2875           2 : static void lsr_write_radialGradient(GF_LASeRCodec *lsr, SVG_Element *elt)
    2876             : {
    2877             :         SVGAllAttributes atts;
    2878           2 :         gf_svg_flatten_attributes(elt, &atts);
    2879             : 
    2880           2 :         lsr_write_id(lsr, (GF_Node *) elt);
    2881           2 :         lsr_write_rare(lsr, (GF_Node *) elt);
    2882           2 :         lsr_write_fill(lsr,  elt, &atts);
    2883           2 :         lsr_write_stroke(lsr,  elt, &atts);
    2884           2 :         lsr_write_coordinate_ptr(lsr, atts.cx, GF_TRUE, "cx");
    2885           2 :         lsr_write_coordinate_ptr(lsr, atts.cy, GF_TRUE, "cy");
    2886           2 :         lsr_write_gradient_units(lsr, atts.gradientUnits);
    2887           2 :         lsr_write_coordinate_ptr(lsr, atts.r, GF_TRUE, "r");
    2888           2 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2889           2 :         lsr_write_group_content(lsr, elt, GF_FALSE);
    2890           2 : }
    2891          52 : static void lsr_write_rect(GF_LASeRCodec *lsr, SVG_Element *elt, Bool ommit_tag)
    2892             : {
    2893             :         u32 same_type = 0;
    2894             :         Bool same_fill;
    2895             :         SVGAllAttributes atts;
    2896          52 :         gf_svg_flatten_attributes(elt, &atts);
    2897             : 
    2898          52 :         if (!ommit_tag && lsr_elt_has_same_base(lsr, &atts, lsr->prev_rect, &same_fill, NULL, GF_FALSE)
    2899             :            ) {
    2900          24 :                 if (!same_fill) {
    2901             :                         same_type = 2;
    2902             :                         /*samerectfillType*/
    2903           0 :                         GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_samerectfill, 6, "ch4");
    2904             :                 } else {
    2905             :                         same_type = 1;
    2906             :                         /*samerectType*/
    2907          24 :                         GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_samerect, 6, "ch4");
    2908             :                 }
    2909          24 :                 lsr_write_id(lsr, (GF_Node *) elt);
    2910          24 :                 if (same_type==2) lsr_write_fill(lsr,  elt, &atts);
    2911          24 :                 lsr_write_coordinate_ptr(lsr, atts.height, GF_FALSE, "height");
    2912          24 :                 lsr_write_coordinate_ptr(lsr, atts.width, GF_FALSE, "width");
    2913          24 :                 lsr_write_coordinate_ptr(lsr, atts.x, GF_TRUE, "x");
    2914          24 :                 lsr_write_coordinate_ptr(lsr, atts.y, GF_TRUE, "y");
    2915             :         } else {
    2916             :                 /*rectType*/
    2917          28 :                 if (!ommit_tag) GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_rect, 6, "ch4");
    2918          28 :                 lsr_write_id(lsr, (GF_Node *) elt);
    2919          28 :                 lsr_write_rare(lsr, (GF_Node *) elt);
    2920          28 :                 lsr_write_fill(lsr,  elt, &atts);
    2921          28 :                 lsr_write_stroke(lsr,  elt, &atts);
    2922          28 :                 lsr_write_coordinate_ptr(lsr, atts.height, GF_FALSE, "height");
    2923          28 :                 lsr_write_coordinate_ptr(lsr, atts.rx, GF_TRUE, "rx");
    2924          28 :                 lsr_write_coordinate_ptr(lsr, atts.ry, GF_TRUE, "ry");
    2925          28 :                 lsr_write_coordinate_ptr(lsr, atts.width, GF_FALSE, "width");
    2926          28 :                 lsr_write_coordinate_ptr(lsr, atts.x, GF_TRUE, "x");
    2927          28 :                 lsr_write_coordinate_ptr(lsr, atts.y, GF_TRUE, "y");
    2928          28 :                 lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2929          28 :                 lsr->prev_rect = elt;
    2930             :         }
    2931          52 :         lsr_write_group_content(lsr, elt, same_type);
    2932          52 : }
    2933             : 
    2934           4 : static void lsr_write_rectClip(GF_LASeRCodec *lsr, SVG_Element *elt)
    2935             : {
    2936             :         SVGAllAttributes atts;
    2937           4 :         gf_svg_flatten_attributes(elt, &atts);
    2938             : 
    2939           4 :         lsr_write_id(lsr, (GF_Node *) elt);
    2940           4 :         lsr_write_rare(lsr, (GF_Node *) elt);
    2941           4 :         lsr_write_fill(lsr, (SVG_Element*)elt, &atts);
    2942           4 :         lsr_write_stroke(lsr, (SVG_Element*)elt, &atts);
    2943           4 :         GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired");
    2944           4 :         if (atts.size) {
    2945           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "size");
    2946           2 :                 lsr_write_coordinate(lsr, atts.size->width, GF_FALSE, "width");
    2947           2 :                 lsr_write_coordinate(lsr, atts.size->height, GF_FALSE, "height");
    2948             :         } else {
    2949           2 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "size");
    2950             :         }
    2951           4 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2952           4 :         lsr_write_group_content(lsr, elt, GF_FALSE);
    2953           4 : }
    2954           4 : static void lsr_write_script(GF_LASeRCodec *lsr, SVG_Element *elt)
    2955             : {
    2956             :         SVGAllAttributes atts;
    2957           4 :         gf_svg_flatten_attributes(elt, &atts);
    2958             : 
    2959           4 :         lsr_write_id(lsr, (GF_Node *) elt);
    2960           4 :         lsr_write_rare(lsr, (GF_Node *) elt);
    2961           4 :         GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired");
    2962           4 :         lsr_write_script_type(lsr, atts.type);
    2963           4 :         lsr_write_href(lsr, atts.xlink_href);
    2964           4 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2965           4 :         lsr_write_group_content(lsr, elt, GF_FALSE);
    2966           4 : }
    2967           8 : static void lsr_write_selector(GF_LASeRCodec *lsr, SVG_Element *elt)
    2968             : {
    2969             :         SVGAllAttributes atts;
    2970           8 :         gf_svg_flatten_attributes(elt, &atts);
    2971             : 
    2972           8 :         lsr_write_id(lsr, (GF_Node *) elt);
    2973           8 :         lsr_write_rare(lsr, (GF_Node *) elt);
    2974           8 :         lsr_write_fill(lsr, (SVG_Element*)elt, &atts);
    2975           8 :         lsr_write_stroke(lsr, (SVG_Element*)elt, &atts);
    2976           8 :         GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired");
    2977             : 
    2978           8 :         GF_LSR_WRITE_INT(lsr, atts.choice ? 1 : 0, 1, "hasChoice");
    2979           8 :         if (atts.choice) {
    2980           6 :                 if (atts.choice->type==LASeR_CHOICE_N) {
    2981           2 :                         GF_LSR_WRITE_INT(lsr, 0, 1, "choice");
    2982           2 :                         GF_LSR_WRITE_INT(lsr, atts.choice->choice_index, 8, "value");
    2983             :                 } else {
    2984           4 :                         GF_LSR_WRITE_INT(lsr, 1, 1, "choice");
    2985           4 :                         GF_LSR_WRITE_INT(lsr, atts.choice->type, 1, "type");
    2986             :                 }
    2987             :         }
    2988           8 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    2989           8 :         lsr_write_group_content(lsr, elt, GF_FALSE);
    2990           8 : }
    2991             : 
    2992           2 : static void lsr_write_set(GF_LASeRCodec *lsr, SVG_Element *elt, SVG_Element *parent)
    2993             : {
    2994             :         SVGAllAttributes atts;
    2995           2 :         gf_svg_flatten_attributes(elt, &atts);
    2996             : 
    2997           2 :         lsr_write_id(lsr, (GF_Node *) elt);
    2998           2 :         lsr_write_rare(lsr, (GF_Node *) elt);
    2999           2 :         lsr_write_animatable(lsr, atts.attributeName, atts.xlink_href, "attributeName");
    3000           2 :         lsr_write_attribute_type(lsr, &atts);
    3001           2 :         lsr_write_smil_times(lsr, atts.begin, "begin", GF_TRUE);
    3002           2 :         lsr_write_duration(lsr, atts.dur, "dur");
    3003           2 :         lsr_write_anim_fill(lsr, atts.smil_fill);
    3004           2 :         lsr_write_anim_repeat(lsr, atts.repeatCount);
    3005           2 :         lsr_write_repeat_duration(lsr, atts.repeatDur);
    3006           2 :         lsr_write_anim_restart(lsr, atts.restart);
    3007           2 :         lsr_write_anim_value(lsr, atts.to, "to");
    3008           2 :         lsr_write_href_anim(lsr, atts.xlink_href, parent);
    3009           2 :         GF_LSR_WRITE_INT(lsr, (atts.lsr_enabled && *atts.lsr_enabled) ? 1 : 0, 1, "enabled");
    3010           2 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    3011           2 :         lsr_write_group_content(lsr, elt, GF_FALSE);
    3012           2 : }
    3013             : 
    3014           4 : static void lsr_write_simpleLayout(GF_LASeRCodec *lsr, SVG_Element *elt)
    3015             : {
    3016             :         SVGAllAttributes atts;
    3017           4 :         gf_svg_flatten_attributes(elt, &atts);
    3018             : 
    3019           4 :         lsr_write_id(lsr, (GF_Node *) elt);
    3020           4 :         lsr_write_rare(lsr, (GF_Node *) elt);
    3021           4 :         lsr_write_fill(lsr, (SVG_Element*)elt, &atts);
    3022           4 :         lsr_write_stroke(lsr, (SVG_Element*)elt, &atts);
    3023           4 :         if (atts.delta) {
    3024           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "delta");
    3025           2 :                 lsr_write_coordinate(lsr, atts.delta->width, GF_FALSE, "width");
    3026           2 :                 lsr_write_coordinate(lsr, atts.delta->height, GF_FALSE, "height");
    3027             :         } else {
    3028           2 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "delta");
    3029             :         }
    3030           4 :         GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired");
    3031             : 
    3032           4 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    3033           4 :         lsr_write_group_content(lsr, elt, GF_FALSE);
    3034           4 : }
    3035             : 
    3036          14 : static void lsr_write_stop(GF_LASeRCodec *lsr, SVG_Element *elt)
    3037             : {
    3038             :         SVGAllAttributes atts;
    3039          14 :         gf_svg_flatten_attributes(elt, &atts);
    3040             : 
    3041          14 :         lsr_write_id(lsr, (GF_Node *) elt);
    3042          14 :         lsr_write_rare(lsr, (GF_Node *) elt);
    3043          14 :         lsr_write_fill(lsr,  elt, &atts);
    3044          14 :         lsr_write_stroke(lsr,  elt, &atts);
    3045          14 :         lsr_write_fixed_16_8(lsr, atts.offset ? atts.offset->value : 0, "offset");
    3046          14 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    3047          14 :         lsr_write_group_content(lsr, elt, GF_FALSE);
    3048          14 : }
    3049           4 : static void lsr_write_svg(GF_LASeRCodec *lsr, SVG_Element *elt)
    3050             : {
    3051             :         SMIL_Duration snap;
    3052             :         SVGAllAttributes atts;
    3053           4 :         gf_svg_flatten_attributes(elt, &atts);
    3054             : 
    3055           4 :         lsr_write_id(lsr, (GF_Node *) elt);
    3056           4 :         lsr_write_rare(lsr, (GF_Node *) elt);
    3057           4 :         lsr_write_fill(lsr,  elt, &atts);
    3058           4 :         lsr_write_stroke(lsr,  elt, &atts);
    3059           4 :         lsr_write_string_attribute(lsr, atts.baseProfile ? *atts.baseProfile : NULL, "baseProfile");
    3060           4 :         lsr_write_string_attribute(lsr, atts.contentScriptType ? *atts.contentScriptType : NULL, "contentScriptType");
    3061           4 :         GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired");
    3062           4 :         lsr_write_value_with_units(lsr, atts.height, "height");
    3063             : 
    3064           4 :         GF_LSR_WRITE_INT(lsr, atts.playbackOrder ? 1 : 0, 1, "hasPlaybackOrder");
    3065           4 :         if (atts.playbackOrder) GF_LSR_WRITE_INT(lsr, *atts.playbackOrder, 1, "playbackOrder");
    3066           4 :         lsr_write_preserve_aspect_ratio(lsr, atts.preserveAspectRatio);
    3067             : 
    3068           4 :         snap.clock_value = atts.snapshotTime ? *atts.snapshotTime : 0;
    3069           4 :         snap.type = snap.clock_value ? SMIL_DURATION_DEFINED : SMIL_DURATION_INDEFINITE;
    3070           4 :         lsr_write_duration(lsr, atts.snapshotTime ? &snap : NULL, "has_snapshotTime");
    3071             : 
    3072           4 :         GF_LSR_WRITE_INT(lsr, atts.syncBehaviorDefault ? 1 : 0, 1, "hasSyncBehavior");
    3073           4 :         if (atts.syncBehaviorDefault) {
    3074           0 :                 switch (*atts.syncBehaviorDefault) {
    3075           0 :                 case SMIL_SYNCBEHAVIOR_CANSLIP:
    3076           0 :                         GF_LSR_WRITE_INT(lsr, 0, 2, "syncBehavior");
    3077             :                         break;
    3078           0 :                 case SMIL_SYNCBEHAVIOR_INDEPENDENT:
    3079           0 :                         GF_LSR_WRITE_INT(lsr, 1, 2, "syncBehavior");
    3080             :                         break;
    3081           0 :                 case SMIL_SYNCBEHAVIOR_LOCKED:
    3082           0 :                         GF_LSR_WRITE_INT(lsr, 3, 2, "syncBehavior");
    3083             :                         break;
    3084           0 :                 default:
    3085           0 :                         GF_LSR_WRITE_INT(lsr, 2, 2, "syncBehavior");
    3086             :                         break;
    3087             :                 }
    3088           4 :         }
    3089           4 :         GF_LSR_WRITE_INT(lsr, atts.syncToleranceDefault ? 1 : 0, 1, "hasSyncToleranceDefault");
    3090           4 :         if (atts.syncToleranceDefault) {
    3091           0 :                 if (atts.syncToleranceDefault->type==SMIL_SYNCTOLERANCE_VALUE) {
    3092           0 :                         GF_LSR_WRITE_INT(lsr, 0, 1, "choice");
    3093           0 :                         lsr_write_vluimsbf5(lsr, (u32) (atts.syncToleranceDefault->value*lsr->time_resolution), "value");
    3094             :                 } else {
    3095           0 :                         GF_LSR_WRITE_INT(lsr, 1, 1, "choice");
    3096             :                 }
    3097             :         }
    3098           4 :         GF_LSR_WRITE_INT(lsr, atts.timelineBegin ? 1 : 0, 1, "hasTimelineBegin");
    3099           4 :         if (atts.timelineBegin) GF_LSR_WRITE_INT(lsr, *atts.timelineBegin, 1, "timelineBegin");
    3100             : 
    3101           4 :         lsr_write_string_attribute(lsr, atts.version ? *atts.version : NULL, "version");
    3102             : 
    3103           4 :         GF_LSR_WRITE_INT(lsr, atts.viewBox ? 1 : 0, 1, "hasViewBox");
    3104           4 :         if (atts.viewBox) {
    3105           2 :                 lsr_write_fixed_16_8(lsr, atts.viewBox->x, "viewbox.x");
    3106           2 :                 lsr_write_fixed_16_8(lsr, atts.viewBox->y, "viewbox.y");
    3107           2 :                 lsr_write_fixed_16_8(lsr, atts.viewBox->width, "viewbox.width");
    3108           2 :                 lsr_write_fixed_16_8(lsr, atts.viewBox->height, "viewbox.height");
    3109             :         }
    3110           4 :         lsr_write_value_with_units(lsr, atts.width, "width");
    3111             : 
    3112           4 :         GF_LSR_WRITE_INT(lsr, atts.zoomAndPan ? 1 : 0, 1, "hasZoomAndPan");
    3113           4 :         if (atts.zoomAndPan) {
    3114           2 :                 GF_LSR_WRITE_INT(lsr, (*atts.zoomAndPan==SVG_ZOOMANDPAN_MAGNIFY) ? 1 : 0, 1, "zoomAndPan");
    3115             :         }
    3116           4 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    3117           4 :         lsr_write_group_content(lsr, elt, GF_FALSE);
    3118           4 : }
    3119             : 
    3120           2 : static void lsr_write_switch(GF_LASeRCodec *lsr, SVG_Element *elt)
    3121             : {
    3122             :         SVGAllAttributes atts;
    3123           2 :         gf_svg_flatten_attributes(elt, &atts);
    3124             : 
    3125           2 :         lsr_write_id(lsr, (GF_Node *) elt);
    3126           2 :         lsr_write_rare(lsr, (GF_Node *) elt);
    3127           2 :         lsr_write_fill(lsr, (SVG_Element*)elt, &atts);
    3128           2 :         lsr_write_stroke(lsr, (SVG_Element*)elt, &atts);
    3129           2 :         GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired");
    3130           2 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    3131           2 :         lsr_write_group_content(lsr, elt, 0);
    3132           2 : }
    3133             : 
    3134          12 : static void lsr_write_text(GF_LASeRCodec *lsr, SVG_Element *elt, Bool ommit_tag)
    3135             : {
    3136             :         Bool same_fill;
    3137             :         u32 same_type = 0;
    3138             :         SVGAllAttributes atts;
    3139          12 :         gf_svg_flatten_attributes(elt, &atts);
    3140             : 
    3141          12 :         if (!ommit_tag && lsr_elt_has_same_base(lsr, &atts, lsr->prev_text, &same_fill, NULL, 0) ) {
    3142           0 :                 if (!same_fill) {
    3143             :                         /*sametextfillType*/
    3144           0 :                         GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_sametextfill, 6, "ch4");
    3145           0 :                         lsr_write_id(lsr, (GF_Node *) elt);
    3146           0 :                         lsr_write_fill(lsr,  elt, &atts);
    3147             :                 } else {
    3148             :                         /*sametextType*/
    3149           0 :                         GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_sametext, 6, "ch4");
    3150           0 :                         lsr_write_id(lsr, (GF_Node *) elt);
    3151             :                 }
    3152           0 :                 lsr_write_coord_list(lsr, atts.text_x, "x");
    3153           0 :                 lsr_write_coord_list(lsr, atts.text_y, "y");
    3154           0 :                 same_type = 1;
    3155             :         } else {
    3156             :                 /*textType*/
    3157          12 :                 if (!ommit_tag) GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_text, 6, "ch4");
    3158          12 :                 lsr_write_id(lsr, (GF_Node *) elt);
    3159          12 :                 lsr_write_rare(lsr, (GF_Node *) elt);
    3160          12 :                 lsr_write_fill(lsr, (SVG_Element*)elt, &atts);
    3161          12 :                 lsr_write_stroke(lsr, (SVG_Element*)elt, &atts);
    3162             : 
    3163          12 :                 GF_LSR_WRITE_INT(lsr, (atts.editable && *atts.editable) ? 1 : 0, 1, "editable");
    3164          12 :                 lsr_write_float_list(lsr, atts.text_rotate, "rotate");
    3165          12 :                 lsr_write_coord_list(lsr, atts.text_x, "x");
    3166          12 :                 lsr_write_coord_list(lsr, atts.text_y, "y");
    3167          12 :                 lsr_write_any_attribute(lsr, elt, GF_TRUE);
    3168          12 :                 lsr->prev_text = elt;
    3169             :         }
    3170          12 :         lsr_write_group_content(lsr, elt, same_type);
    3171          12 : }
    3172             : 
    3173           2 : static void lsr_write_tspan(GF_LASeRCodec *lsr, SVG_Element *elt)
    3174             : {
    3175             :         SVGAllAttributes atts;
    3176           2 :         gf_svg_flatten_attributes(elt, &atts);
    3177             : 
    3178           2 :         lsr_write_id(lsr, (GF_Node *) elt);
    3179           2 :         lsr_write_rare(lsr, (GF_Node *) elt);
    3180           2 :         lsr_write_fill(lsr, (SVG_Element*)elt, &atts);
    3181           2 :         lsr_write_stroke(lsr, (SVG_Element*)elt, &atts);
    3182           2 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    3183           2 :         lsr_write_group_content(lsr, elt, GF_FALSE);
    3184           2 : }
    3185             : 
    3186           8 : static void lsr_write_use(GF_LASeRCodec *lsr, SVG_Element *elt, Bool ommit_tag)
    3187             : {
    3188             :         SVGAllAttributes atts;
    3189             :         Bool is_same = GF_FALSE;
    3190           8 :         gf_svg_flatten_attributes(elt, &atts);
    3191             : 
    3192           8 :         if (!ommit_tag && lsr_elt_has_same_base(lsr, &atts, lsr->prev_use, NULL, NULL, GF_FALSE)
    3193             :                 /*TODO check overflow*/
    3194             :            ) {
    3195             :                 is_same = GF_TRUE;
    3196             :                 /*sameuseType*/
    3197           2 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_sameuse, 6, "ch4");
    3198           2 :                 lsr_write_id(lsr, (GF_Node *) elt);
    3199           2 :                 lsr_write_href(lsr, atts.xlink_href);
    3200             :         } else {
    3201             :                 /*useType*/
    3202           6 :                 if (!ommit_tag) GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_use, 6, "ch4");
    3203           6 :                 lsr_write_id(lsr, (GF_Node *) elt);
    3204           6 :                 lsr_write_rare(lsr, (GF_Node *) elt);
    3205           6 :                 lsr_write_fill(lsr, (SVG_Element*)elt, &atts);
    3206           6 :                 lsr_write_stroke(lsr, (SVG_Element*)elt, &atts);
    3207           6 :                 GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired");
    3208             : 
    3209           6 :                 GF_LSR_WRITE_INT(lsr, atts.overflow ? 1 : 0, 1, "hasOverflow");
    3210             :                 /*one value only??*/
    3211           6 :                 if (atts.overflow) GF_LSR_WRITE_INT(lsr, 0, 2, "overflow");
    3212             : 
    3213           6 :                 lsr_write_coordinate_ptr(lsr, atts.x, GF_TRUE, "x");
    3214           6 :                 lsr_write_coordinate_ptr(lsr, atts.y, GF_TRUE, "y");
    3215           6 :                 lsr_write_href(lsr, atts.xlink_href);
    3216           6 :                 lsr_write_any_attribute(lsr, elt, GF_TRUE);
    3217           6 :                 lsr->prev_use = elt;
    3218             :         }
    3219           8 :         lsr_write_group_content(lsr, elt, is_same);
    3220           8 : }
    3221             : 
    3222           4 : static void lsr_write_video(GF_LASeRCodec *lsr, SVG_Element *elt)
    3223             : {
    3224             :         u32 fs_value;
    3225             :         SVGAllAttributes atts;
    3226           4 :         gf_svg_flatten_attributes(elt, &atts);
    3227             : 
    3228             :         fs_value = 0;
    3229           4 :         if (atts.fullscreen) {
    3230           2 :                 fs_value = *atts.fullscreen + 1;
    3231           2 :                 atts.fullscreen = NULL;
    3232             :         }
    3233             : 
    3234           4 :         lsr_write_id(lsr, (GF_Node *) elt);
    3235           4 :         lsr_write_rare(lsr, (GF_Node *) elt);
    3236           4 :         lsr_write_smil_times(lsr, atts.begin, "begin", GF_TRUE);
    3237           4 :         lsr_write_duration(lsr, atts.dur, "dur");
    3238           4 :         GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired");
    3239           4 :         lsr_write_coordinate_ptr(lsr, atts.height, GF_TRUE, "height");
    3240             : 
    3241           4 :         GF_LSR_WRITE_INT(lsr, atts.overlay  ? 1 : 0, 1, "hasOverlay");
    3242           4 :         if (atts.overlay) {
    3243           0 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "choice");
    3244           0 :                 GF_LSR_WRITE_INT(lsr, *atts.overlay, 1, "overlay");
    3245             :         }
    3246           4 :         lsr_write_preserve_aspect_ratio(lsr, atts.preserveAspectRatio);
    3247             : 
    3248           4 :         lsr_write_anim_repeat(lsr, atts.repeatCount);
    3249           4 :         lsr_write_repeat_duration(lsr, atts.repeatDur);
    3250           4 :         lsr_write_anim_restart(lsr, atts.restart);
    3251           4 :         lsr_write_sync_behavior(lsr, atts.syncBehavior, "syncBehavior");
    3252           4 :         lsr_write_sync_tolerance(lsr, atts.syncTolerance, "syncTolerance");
    3253           4 :         lsr_write_transform_behavior(lsr, atts.transformBehavior);
    3254           4 :         lsr_write_content_type(lsr, atts.xlink_type, "type");
    3255           4 :         lsr_write_coordinate_ptr(lsr, atts.width, GF_TRUE, "width");
    3256           4 :         lsr_write_coordinate_ptr(lsr, atts.x, GF_TRUE, "x");
    3257           4 :         lsr_write_coordinate_ptr(lsr, atts.y, GF_TRUE, "y");
    3258           4 :         lsr_write_href(lsr, atts.xlink_href);
    3259             : 
    3260           4 :         lsr_write_clip_time(lsr, atts.clipBegin, "clipBegin");
    3261           4 :         lsr_write_clip_time(lsr, atts.clipEnd, "clipEnd");
    3262             : 
    3263           4 :         GF_LSR_WRITE_INT(lsr, fs_value ? 1 : 0, 1, "hasFullscreen");
    3264           4 :         if (fs_value) GF_LSR_WRITE_INT(lsr, fs_value - 1, 1, "fullscreen");
    3265             : 
    3266           4 :         GF_LSR_WRITE_INT(lsr, atts.syncReference ? 1 : 0, 1, "hasSyncReference");
    3267           4 :         if (atts.syncReference) lsr_write_any_uri(lsr, atts.syncReference, "syncReference");
    3268             : 
    3269           4 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    3270           4 :         lsr_write_group_content(lsr, elt, GF_FALSE);
    3271           4 : }
    3272             : 
    3273           4 : static void lsr_write_listener(GF_LASeRCodec *lsr, SVG_Element *elt)
    3274             : {
    3275             :         SVGAllAttributes atts;
    3276           4 :         gf_svg_flatten_attributes(elt, &atts);
    3277             : 
    3278           4 :         lsr_write_id(lsr, (GF_Node *) elt);
    3279           4 :         lsr_write_rare(lsr, (GF_Node *) elt);
    3280             : 
    3281           4 :         GF_LSR_WRITE_INT(lsr, atts.defaultAction ? 1 : 0, 1, "hasDefaultAction");
    3282           4 :         if (atts.defaultAction) GF_LSR_WRITE_INT(lsr, *atts.defaultAction ? 1 : 0, 1, "defaultAction");
    3283           4 :         if (atts.event) {
    3284           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "hasEvent");
    3285           2 :                 lsr_write_event_type(lsr, atts.event->type, atts.event->parameter);
    3286             :         } else {
    3287           2 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "hasEvent");
    3288             :         }
    3289           4 :         if (atts.handler && (atts.handler->string || (atts.handler->target && gf_node_get_id((GF_Node *)atts.handler->target) ) )) {
    3290           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "hasHandler");
    3291           2 :                 lsr_write_any_uri(lsr, atts.handler, "handler");
    3292             :         } else {
    3293           2 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "hasHandler");
    3294             :         }
    3295           4 :         if (atts.observer && atts.observer->target && gf_node_get_id((GF_Node *)atts.observer->target) ) {
    3296           0 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "hasObserver");
    3297           0 :                 lsr_write_codec_IDREF(lsr, atts.observer, "observer");
    3298             :         } else {
    3299           4 :                 if (atts.observer) {
    3300           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] listener.observer %s not found in scene - skipping it\n", atts.observer->string ));
    3301             :                 }
    3302           4 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "hasObserver");
    3303             :         }
    3304             : 
    3305           4 :         GF_LSR_WRITE_INT(lsr, atts.phase ? 1 : 0, 1, "hasPhase");
    3306           4 :         if (atts.phase) GF_LSR_WRITE_INT(lsr, *atts.phase, 1, "phase");
    3307             : 
    3308           4 :         GF_LSR_WRITE_INT(lsr, atts.propagate ? 1 : 0, 1, "hasPropagate");
    3309           4 :         if (atts.propagate) GF_LSR_WRITE_INT(lsr, *atts.propagate, 1, "propagate");
    3310             : 
    3311           4 :         if (atts.listener_target && atts.listener_target->target && gf_node_get_id((GF_Node *)atts.listener_target->target) ) {
    3312           0 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "hasTarget");
    3313           0 :                 lsr_write_codec_IDREF(lsr, atts.listener_target, "target");
    3314             :         } else {
    3315           4 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "hasTarget");
    3316             :         }
    3317           4 :         GF_LSR_WRITE_INT(lsr, (atts.lsr_enabled && *atts.lsr_enabled) ? 1 : 0, 1, "enabled");
    3318             : 
    3319           4 :         lsr_write_any_attribute(lsr, elt, GF_TRUE);
    3320           4 :         lsr_write_group_content(lsr, elt, GF_FALSE);
    3321           4 : }
    3322             : 
    3323         272 : static void lsr_write_scene_content_model(GF_LASeRCodec *lsr, SVG_Element *parent, void *node)
    3324             : {
    3325         272 :         u32 tag = gf_node_get_tag((GF_Node*)node);
    3326             : 
    3327         272 :         switch(tag) {
    3328           8 :         case TAG_SVG_a:
    3329           8 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_a, 6, "ch4");
    3330           8 :                 lsr_write_a(lsr, node);
    3331           8 :                 break;
    3332          66 :         case TAG_SVG_animate:
    3333          66 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_animate, 6, "ch4");
    3334          66 :                 lsr_write_animate(lsr, node, parent);
    3335          66 :                 break;
    3336           0 :         case TAG_SVG_animateColor:
    3337           0 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_animateColor, 6, "ch4");
    3338           0 :                 lsr_write_animate(lsr, node, parent);
    3339           0 :                 break;
    3340           4 :         case TAG_SVG_animateMotion:
    3341           4 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_animateMotion, 6, "ch4");
    3342           4 :                 lsr_write_animateMotion(lsr, node, parent);
    3343           4 :                 break;
    3344           8 :         case TAG_SVG_animateTransform:
    3345           8 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_animateTransform, 6, "ch4");
    3346           8 :                 lsr_write_animateTransform(lsr, node, parent);
    3347           8 :                 break;
    3348           2 :         case TAG_SVG_audio:
    3349           2 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_audio, 6, "ch4");
    3350           2 :                 lsr_write_audio(lsr, node);
    3351           2 :                 break;
    3352           6 :         case TAG_SVG_circle:
    3353           6 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_circle, 6, "ch4");
    3354           6 :                 lsr_write_circle(lsr, node);
    3355           6 :                 break;
    3356           0 :         case TAG_LSR_cursorManager:
    3357           0 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_cursorManager, 6, "ch4");
    3358           0 :                 lsr_write_cursorManager(lsr, node);
    3359           0 :                 break;
    3360           0 :         case TAG_SVG_defs:
    3361           0 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_defs, 6, "ch4");
    3362           0 :                 lsr_write_defs(lsr, node);
    3363           0 :                 break;
    3364           0 :         case TAG_SVG_desc:
    3365           0 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_desc, 6, "ch4");
    3366           0 :                 lsr_write_data(lsr, node);
    3367           0 :                 break;
    3368           0 :         case TAG_SVG_ellipse:
    3369           0 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_ellipse, 6, "ch4");
    3370           0 :                 lsr_write_ellipse(lsr, node);
    3371           0 :                 break;
    3372           0 :         case TAG_SVG_foreignObject:
    3373           0 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_foreignObject, 6, "ch4");
    3374           0 :                 lsr_write_foreignObject(lsr, node);
    3375           0 :                 break;
    3376             : 
    3377          18 :         case TAG_SVG_g:
    3378             :                 /*type is written in encoding fct for sameg handling*/
    3379          18 :                 lsr_write_g(lsr, node, 0);
    3380          18 :                 break;
    3381          26 :         case TAG_SVG_image:
    3382          26 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_image, 6, "ch4");
    3383          26 :                 lsr_write_image(lsr, node);
    3384          26 :                 break;
    3385           2 :         case TAG_SVG_line:
    3386             :                 /*type is written in encoding fct for sameline handling*/
    3387           2 :                 lsr_write_line(lsr, node, 0);
    3388           2 :                 break;
    3389           4 :         case TAG_SVG_linearGradient:
    3390           4 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_linearGradient, 6, "ch4");
    3391           4 :                 lsr_write_linearGradient(lsr, node);
    3392           4 :                 break;
    3393           0 :         case TAG_SVG_metadata:
    3394           0 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_metadata, 6, "ch4");
    3395           0 :                 lsr_write_data(lsr, node);
    3396           0 :                 break;
    3397           2 :         case TAG_SVG_mpath:
    3398           2 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_mpath, 6, "ch4");
    3399           2 :                 lsr_write_mpath(lsr, node);
    3400           2 :                 break;
    3401          14 :         case TAG_SVG_path:
    3402             :                 /*type is written in encoding fct for samepath handling*/
    3403          14 :                 lsr_write_path(lsr, node, 0);
    3404          14 :                 break;
    3405          10 :         case TAG_SVG_polygon:
    3406             :                 /*type is written in encoding fct for samepolygon handling*/
    3407          10 :                 lsr_write_polygon(lsr, node, 0, 0);
    3408          10 :                 break;
    3409           8 :         case TAG_SVG_polyline:
    3410             :                 /*type is written in encoding fct for samepolyline handling*/
    3411           8 :                 lsr_write_polygon(lsr, node, 1, 0);
    3412           8 :                 break;
    3413           0 :         case TAG_SVG_radialGradient:
    3414           0 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_radialGradient, 6, "ch4");
    3415           0 :                 lsr_write_radialGradient(lsr, node);
    3416           0 :                 break;
    3417          48 :         case TAG_SVG_rect:
    3418             :                 /*type is written in encoding fct for samepolyline handling*/
    3419          48 :                 lsr_write_rect(lsr, node, 0);
    3420          48 :                 break;
    3421           2 :         case TAG_SVG_script:
    3422           2 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_script, 6, "ch4");
    3423           2 :                 lsr_write_script(lsr, node);
    3424           2 :                 break;
    3425           0 :         case TAG_SVG_set:
    3426           0 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_set, 6, "ch4");
    3427           0 :                 lsr_write_set(lsr, node, parent);
    3428           0 :                 break;
    3429          12 :         case TAG_SVG_stop:
    3430          12 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_stop, 6, "ch4");
    3431          12 :                 lsr_write_stop(lsr, node);
    3432          12 :                 break;
    3433           0 :         case TAG_SVG_switch:
    3434           0 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_switch, 6, "ch4");
    3435           0 :                 lsr_write_switch(lsr, node);
    3436           0 :                 break;
    3437           8 :         case TAG_SVG_text:
    3438             :                 /*type is written in encoding fct for sametext handling*/
    3439           8 :                 lsr_write_text(lsr, node, 0);
    3440           8 :                 break;
    3441           0 :         case TAG_SVG_title:
    3442           0 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_title, 6, "ch4");
    3443           0 :                 lsr_write_data(lsr, node);
    3444           0 :                 break;
    3445           0 :         case TAG_SVG_tspan:
    3446           0 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_tspan, 6, "ch4");
    3447           0 :                 lsr_write_tspan(lsr, node);
    3448           0 :                 break;
    3449           6 :         case TAG_SVG_use:
    3450             :                 /*type is written in encoding fct for sameuse handling*/
    3451           6 :                 lsr_write_use(lsr, node, 0);
    3452           6 :                 break;
    3453           2 :         case TAG_SVG_video:
    3454           2 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_video, 6, "ch4");
    3455           2 :                 lsr_write_video(lsr, node);
    3456           2 :                 break;
    3457           2 :         case TAG_SVG_listener:
    3458           2 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_listener, 6, "ch4");
    3459           2 :                 lsr_write_listener(lsr, node);
    3460           2 :                 break;
    3461           2 :         case TAG_LSR_conditional:
    3462           2 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_conditional, 6, "ch4");
    3463           2 :                 lsr_write_conditional(lsr, node);
    3464           2 :                 break;
    3465           2 :         case TAG_LSR_rectClip:
    3466           2 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_rectClip, 6, "ch4");
    3467           2 :                 lsr_write_rectClip(lsr, node);
    3468           2 :                 break;
    3469           6 :         case TAG_LSR_selector:
    3470           6 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_selector, 6, "ch4");
    3471           6 :                 lsr_write_selector(lsr, node);
    3472           6 :                 break;
    3473           2 :         case TAG_LSR_simpleLayout:
    3474           2 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_simpleLayout, 6, "ch4");
    3475           2 :                 lsr_write_simpleLayout(lsr, node);
    3476           2 :                 break;
    3477             : #if 0
    3478             :         /*case privateElement*/
    3479             :         case TAG_SVG_extendElement:
    3480             :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_privateContainer, 6, "ch4");
    3481             :                 lsr_write_private_element_container(lsr);
    3482             :                 break;
    3483             : #endif
    3484             : 
    3485           2 :         default:
    3486             : #if 0
    3487             :                 /*case extend*/
    3488             :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_element_any, 6, "ch4");
    3489             :                 lsr_write_extend_class(lsr, NULL, 0, node);
    3490             :                 break;
    3491             : #else
    3492             :                 /*hack for encoding - needs cleaning*/
    3493           2 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] node %s not part of LASeR children nodes - skipping\n", gf_node_get_class_name((GF_Node*)node)));
    3494           2 :                 GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_textContent, 6, "ch4");
    3495           2 :                 lsr_write_byte_align_string(lsr, "", "textContent");
    3496           2 :                 break;
    3497             : #endif
    3498             :         }
    3499         272 : }
    3500             : 
    3501          82 : static void lsr_write_update_content_model(GF_LASeRCodec *lsr, SVG_Element *parent, void *node)
    3502             : {
    3503          82 :         u32 tag = gf_node_get_tag((GF_Node*)node);
    3504             : 
    3505          82 :         if (tag==TAG_LSR_conditional) {
    3506           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "ch4");
    3507           2 :                 GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL2_conditional, 3, "ch61");
    3508           2 :                 lsr_write_conditional(lsr, node);
    3509          80 :         } else if (tag==TAG_LSR_cursorManager) {
    3510           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "ch4");
    3511           2 :                 GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL2_cursorManager, 3, "ch61");
    3512           2 :                 lsr_write_cursorManager(lsr, node);
    3513          78 :         } else if (tag==TAG_LSR_rectClip) {
    3514           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "ch4");
    3515           2 :                 GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL2_rectClip, 3, "ch61");
    3516           2 :                 lsr_write_rectClip(lsr, node);
    3517          76 :         } else if (tag==TAG_LSR_selector) {
    3518           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "ch4");
    3519           2 :                 GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL2_selector, 3, "ch61");
    3520           2 :                 lsr_write_selector(lsr, node);
    3521          74 :         } else if (tag==TAG_LSR_simpleLayout) {
    3522           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "ch4");
    3523           2 :                 GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL2_simpleLayout, 3, "ch61");
    3524           2 :                 lsr_write_simpleLayout(lsr, node);
    3525             :         } else {
    3526          72 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "ch4");
    3527          72 :                 switch(tag) {
    3528           2 :                 case TAG_SVG_a:
    3529           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_a, 6, "ch6");
    3530           2 :                         lsr_write_a(lsr, node);
    3531           2 :                         break;
    3532           2 :                 case TAG_SVG_animate:
    3533           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_animate, 6, "ch6");
    3534           2 :                         lsr_write_animate(lsr, node, parent);
    3535           2 :                         break;
    3536           2 :                 case TAG_SVG_animateColor:
    3537           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_animateColor, 6, "ch6");
    3538           2 :                         lsr_write_animate(lsr, node, parent);
    3539           2 :                         break;
    3540           2 :                 case TAG_SVG_animateMotion:
    3541           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_animateMotion, 6, "ch6");
    3542           2 :                         lsr_write_animateMotion(lsr, node, parent);
    3543           2 :                         break;
    3544           2 :                 case TAG_SVG_animateTransform:
    3545           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_animateTransform, 6, "ch6");
    3546           2 :                         lsr_write_animateTransform(lsr, node, parent);
    3547           2 :                         break;
    3548           2 :                 case TAG_SVG_audio:
    3549           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_audio, 6, "ch6");
    3550           2 :                         lsr_write_audio(lsr, node);
    3551           2 :                         break;
    3552           2 :                 case TAG_SVG_circle:
    3553           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_circle, 6, "ch6");
    3554           2 :                         lsr_write_circle(lsr, node);
    3555           2 :                         break;
    3556           2 :                 case TAG_SVG_defs:
    3557           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_defs, 6, "ch6");
    3558           2 :                         lsr_write_defs(lsr, node);
    3559           2 :                         break;
    3560           4 :                 case TAG_SVG_desc:
    3561           4 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_desc, 6, "ch6");
    3562           4 :                         lsr_write_data(lsr, node);
    3563           4 :                         break;
    3564           2 :                 case TAG_SVG_ellipse:
    3565           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_ellipse, 6, "ch6");
    3566           2 :                         lsr_write_ellipse(lsr, node);
    3567           2 :                         break;
    3568           2 :                 case TAG_SVG_foreignObject:
    3569           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_foreignObject, 6, "ch6");
    3570           2 :                         lsr_write_foreignObject(lsr, node);
    3571           2 :                         break;
    3572           2 :                 case TAG_SVG_g:
    3573           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_g, 6, "ch6");
    3574           2 :                         lsr_write_g(lsr, node, 1);
    3575           2 :                         break;
    3576           2 :                 case TAG_SVG_image:
    3577           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_image, 6, "ch6");
    3578           2 :                         lsr_write_image(lsr, node);
    3579           2 :                         break;
    3580           2 :                 case TAG_SVG_line:
    3581           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_line, 6, "ch6");
    3582           2 :                         lsr_write_line(lsr, node, 1);
    3583           2 :                         break;
    3584           2 :                 case TAG_SVG_linearGradient:
    3585           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_linearGradient, 6, "ch6");
    3586           2 :                         lsr_write_linearGradient(lsr, node);
    3587           2 :                         break;
    3588           2 :                 case TAG_SVG_metadata:
    3589           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_metadata, 6, "ch6");
    3590           2 :                         lsr_write_data(lsr, node);
    3591           2 :                         break;
    3592           2 :                 case TAG_SVG_mpath:
    3593           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_mpath, 6, "ch6");
    3594           2 :                         lsr_write_mpath(lsr, node);
    3595           2 :                         break;
    3596           2 :                 case TAG_SVG_path:
    3597           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_path, 6, "ch6");
    3598           2 :                         lsr_write_path(lsr, node, 1);
    3599           2 :                         break;
    3600           2 :                 case TAG_SVG_polygon:
    3601           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_polygon, 6, "ch6");
    3602           2 :                         lsr_write_polygon(lsr, node, 0, 1);
    3603           2 :                         break;
    3604           2 :                 case TAG_SVG_polyline:
    3605           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_polyline, 6, "ch6");
    3606           2 :                         lsr_write_polygon(lsr, node, 1, 1);
    3607           2 :                         break;
    3608           2 :                 case TAG_SVG_radialGradient:
    3609           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_radialGradient, 6, "ch6");
    3610           2 :                         lsr_write_radialGradient(lsr, node);
    3611           2 :                         break;
    3612           4 :                 case TAG_SVG_rect:
    3613           4 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_rect, 6, "ch6");
    3614           4 :                         lsr_write_rect(lsr, node, 1);
    3615           4 :                         break;
    3616           2 :                 case TAG_SVG_script:
    3617           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_script, 6, "ch6");
    3618           2 :                         lsr_write_script(lsr, node);
    3619           2 :                         break;
    3620           2 :                 case TAG_SVG_set:
    3621           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_set, 6, "ch6");
    3622           2 :                         lsr_write_set(lsr, node, parent);
    3623           2 :                         break;
    3624           2 :                 case TAG_SVG_stop:
    3625           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_stop, 6, "ch6");
    3626           2 :                         lsr_write_stop(lsr, node);
    3627           2 :                         break;
    3628           2 :                 case TAG_SVG_svg:
    3629           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_svg, 6, "ch6");
    3630           2 :                         lsr_write_svg(lsr, node);
    3631           2 :                         break;
    3632           2 :                 case TAG_SVG_switch:
    3633           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_switch, 6, "ch6");
    3634           2 :                         lsr_write_switch(lsr, node);
    3635           2 :                         break;
    3636           4 :                 case TAG_SVG_text:
    3637           4 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_text, 6, "ch6");
    3638           4 :                         lsr_write_text(lsr, node, 1);
    3639           4 :                         break;
    3640           2 :                 case TAG_SVG_title:
    3641           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_title, 6, "ch6");
    3642           2 :                         lsr_write_data(lsr, node);
    3643           2 :                         break;
    3644           2 :                 case TAG_SVG_tspan:
    3645           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_tspan, 6, "ch6");
    3646           2 :                         lsr_write_tspan(lsr, node);
    3647           2 :                         break;
    3648           2 :                 case TAG_SVG_use:
    3649           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_use, 6, "ch6");
    3650           2 :                         lsr_write_use(lsr, node, 1);
    3651           2 :                         break;
    3652           2 :                 case TAG_SVG_video:
    3653           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_video, 6, "ch6");
    3654           2 :                         lsr_write_video(lsr, node);
    3655           2 :                         break;
    3656           2 :                 case TAG_SVG_listener:
    3657           2 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_listener, 6, "ch6");
    3658           2 :                         lsr_write_listener(lsr, node);
    3659           2 :                         break;
    3660           0 :                 default:
    3661           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[LASeR] Cannot encode node %s as command child node\n", gf_node_get_class_name((GF_Node*)node)));
    3662           0 :                         lsr->last_error = GF_NON_COMPLIANT_BITSTREAM;
    3663           0 :                         break;
    3664             :                 }
    3665             :         }
    3666          82 : }
    3667             : 
    3668         348 : static void lsr_write_group_content(GF_LASeRCodec *lsr, SVG_Element *elt, Bool skip_object_content)
    3669             : {
    3670             :         GF_ChildNodeItem *l;
    3671             :         u32 count;
    3672         348 :         if (!skip_object_content) lsr_write_private_attributes(lsr, elt);
    3673             : 
    3674         348 :         count = gf_node_list_get_count(elt->children);
    3675             : 
    3676         348 :         l = elt->children;
    3677         348 :         if (!count) {
    3678         280 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "opt_group");
    3679             :                 return;
    3680             :         }
    3681          68 :         GF_LSR_WRITE_INT(lsr, 1, 1, "opt_group");
    3682          68 :         lsr_write_vluimsbf5(lsr, count, "occ0");
    3683             : 
    3684         432 :         while (l) {
    3685         296 :                 if (gf_node_get_tag(l->node)==TAG_DOMText) {
    3686          24 :                         GF_DOMText *txt = (GF_DOMText *)l->node;
    3687          24 :                         GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_textContent, 6, "ch4");
    3688          24 :                         lsr_write_byte_align_string(lsr, txt->textContent, "textContent");
    3689             :                 } else {
    3690         272 :                         lsr_write_scene_content_model(lsr, elt, l->node);
    3691         272 :                         GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] ############## end %s ###########\n", gf_node_get_class_name((GF_Node*)l->node)));
    3692             :                 }
    3693         296 :                 l = l->next;
    3694             :         }
    3695             : }
    3696             : 
    3697          54 : static void lsr_write_update_value(GF_LASeRCodec *lsr, SVG_Element *elt, u32 fieldType, u32 att_tag, u32 transformType, void *val, Bool is_indexed)
    3698             : {
    3699          54 :         if (is_indexed) {
    3700             :                 assert(gf_list_count(*(GF_List **)val));
    3701          12 :                 switch (fieldType) {
    3702           2 :                 case SVG_Points_datatype:/*points*/
    3703             :                 {
    3704           2 :                         GF_Point2D *pt = (GF_Point2D*)gf_list_get(*(GF_List **)val, 0);
    3705           2 :                         lsr_write_coordinate(lsr, pt->x, GF_FALSE, "x");
    3706           2 :                         lsr_write_coordinate(lsr, pt->y, GF_FALSE, "y");
    3707             :                 }
    3708             :                 break;
    3709           2 :                 case SMIL_Times_datatype:/*smil_times*/
    3710             :                 {
    3711           2 :                         SMIL_Time *st = (SMIL_Time*)gf_list_get(*(GF_List **)val, 0);
    3712           2 :                         lsr_write_smil_time(lsr, st);
    3713             :                 }
    3714             :                 break;
    3715           2 :                 case SMIL_KeyPoints_datatype:/*0to1*/
    3716             :                 {
    3717           2 :                         Fixed *f = (Fixed*)gf_list_get(*(GF_List **)val, 0);
    3718           2 :                         lsr_write_fixed_clamp(lsr, *f, "value");
    3719             :                 }
    3720             :                 break;
    3721           2 :                 case SMIL_KeySplines_datatype:/*float*/
    3722             :                 {
    3723           2 :                         Fixed *f = (Fixed*)gf_list_get(*(GF_List **)val, 0);
    3724           2 :                         lsr_write_fixed_16_8(lsr, *f, "v");
    3725             :                 }
    3726             :                 break;
    3727           4 :                 case SMIL_KeyTimes_datatype:/*keyTime*/
    3728             :                 {
    3729           4 :                         Fixed *v = (Fixed*)gf_list_get(*(GF_List **)val, 0);
    3730           4 :                         Fixed f = *v;
    3731           4 :                         if ((f==0) || (f==FIX_ONE)) {
    3732           2 :                                 GF_LSR_WRITE_INT(lsr, 1, 1, "hasShort");
    3733           2 :                                 GF_LSR_WRITE_INT(lsr, (f==0) ? 0 : 1, 1, "isZero");
    3734             :                         } else {
    3735           2 :                                 GF_LSR_WRITE_INT(lsr, 0, 1, "hasShort");
    3736           2 :                                 f *= 4096;
    3737           2 :                                 GF_LSR_WRITE_INT(lsr, (u32) f, 12, "timevalue");
    3738             :                         }
    3739             :                 }
    3740             :                 break;
    3741             :                 case SVG_StrokeDashArray_datatype:/*float*/
    3742             :                 case SVG_ViewBox_datatype:/*float*/
    3743             :                         break;
    3744             :                 case DOM_StringList_datatype:
    3745             :                         if (att_tag==TAG_SVG_ATT_requiredFeatures) {
    3746             :                                 /*int*/
    3747             :                         }
    3748             :                         break;
    3749             :                 }
    3750             :         } else {
    3751             :                 SVG_Number *n;
    3752          42 :                 switch (fieldType) {
    3753           0 :                 case SVG_Boolean_datatype:
    3754           0 :                         GF_LSR_WRITE_INT(lsr, *(SVG_Boolean*)val ? 1 : 0, 1, "val");
    3755             :                         break;
    3756           4 :                 case SVG_Paint_datatype:
    3757           4 :                         lsr_write_paint(lsr, (SVG_Paint *)val, "val");
    3758             :                         break;
    3759           2 :                 case SVG_Transform_datatype:
    3760           2 :                         lsr_write_matrix(lsr, (SVG_Transform*)val);
    3761             :                         break;
    3762           0 :                 case SVG_Transform_Scale_datatype:
    3763           0 :                         lsr_write_fixed_16_8(lsr, ((SVG_Point *)val)->x, "scale_x");
    3764           0 :                         lsr_write_fixed_16_8(lsr, ((SVG_Point *)val)->y, "scale_y");
    3765             :                         break;
    3766           2 :                 case LASeR_Size_datatype:
    3767             :                 case SVG_Transform_Translate_datatype:
    3768           2 :                         lsr_write_coordinate(lsr, ((SVG_Point *)val)->x, GF_FALSE, "translation_x");
    3769           2 :                         lsr_write_coordinate(lsr, ((SVG_Point *)val)->y, GF_FALSE, "translation_y");
    3770             :                         break;
    3771           0 :                 case SVG_Transform_Rotate_datatype:
    3772           0 :                         GF_LSR_WRITE_INT(lsr, 0, 1, "isDefaultValue");
    3773           0 :                         GF_LSR_WRITE_INT(lsr, 0, 1, "escapeFlag");
    3774           0 :                         lsr_write_fixed_16_8(lsr, ((SVG_Point_Angle*)val)->angle, "rotate");
    3775             :                         break;
    3776          14 :                 case SVG_Number_datatype:
    3777             :                 case SVG_FontSize_datatype:
    3778             :                 case SVG_Length_datatype:
    3779             :                         n = (SVG_Number*)val;
    3780          14 :                         switch (att_tag) {
    3781             :                         /*fractions*/
    3782           4 :                         case TAG_SVG_ATT_audio_level:
    3783             :                         case TAG_SVG_ATT_fill_opacity:
    3784             :                         case TAG_SVG_ATT_offset:
    3785             :                         case TAG_SVG_ATT_opacity:
    3786             :                         case TAG_SVG_ATT_solid_opacity:
    3787             :                         case TAG_SVG_ATT_stop_opacity:
    3788             :                         case TAG_SVG_ATT_stroke_opacity:
    3789             :                         case TAG_SVG_ATT_viewport_fill_opacity:
    3790           4 :                                 if (n->type==SVG_NUMBER_INHERIT) {
    3791           2 :                                         GF_LSR_WRITE_INT(lsr, 1, 1, "isDefaultValue");
    3792             :                                 } else {
    3793           2 :                                         GF_LSR_WRITE_INT(lsr, 0, 1, "isDefaultValue");
    3794           2 :                                         lsr_write_fixed_clamp(lsr, n->value, "val");
    3795             :                                 }
    3796             :                                 break;
    3797           6 :                         case TAG_SVG_ATT_width:
    3798             :                         case TAG_SVG_ATT_height:
    3799           6 :                                 if (elt->sgprivate->tag==TAG_SVG_svg) {
    3800           2 :                                         lsr_write_value_with_units(lsr, n, "val");
    3801             :                                 } else {
    3802           4 :                                         lsr_write_coordinate(lsr, n->value, GF_FALSE, "val");
    3803             :                                 }
    3804             :                                 break;
    3805           4 :                         default:
    3806           4 :                                 if (n->type==SVG_NUMBER_INHERIT) {
    3807           2 :                                         GF_LSR_WRITE_INT(lsr, 1, 1, "isDefaultValue");
    3808             :                                 } else {
    3809           2 :                                         GF_LSR_WRITE_INT(lsr, 0, 1, "isDefaultValue");
    3810           2 :                                         GF_LSR_WRITE_INT(lsr, 0, 1, "escapeFlag");
    3811           2 :                                         lsr_write_fixed_16_8(lsr, n->value, "val");
    3812             :                                 }
    3813             :                         }
    3814             :                         break;
    3815           4 :                 case SVG_Rotate_datatype:
    3816             :                         n = (SVG_Number*)val;
    3817           4 :                         if (n->type==SVG_NUMBER_INHERIT) {
    3818           0 :                                 GF_LSR_WRITE_INT(lsr, 1, 1, "isDefaultValue");
    3819             :                         } else {
    3820           4 :                                 GF_LSR_WRITE_INT(lsr, 0, 1, "isDefaultValue");
    3821           4 :                                 if ((n->type == SVG_NUMBER_AUTO) || (n->type == SVG_NUMBER_AUTO_REVERSE)) {
    3822           2 :                                         GF_LSR_WRITE_INT(lsr, 1, 1, "escapeFlag");
    3823           2 :                                         GF_LSR_WRITE_INT(lsr, (n->type == SVG_NUMBER_AUTO) ? 0 : 1, 2, "rotate");
    3824             :                                 } else {
    3825           2 :                                         GF_LSR_WRITE_INT(lsr, 0, 1, "escapeFlag");
    3826           2 :                                         lsr_write_fixed_16_8(lsr, n->value, "rotate");
    3827             :                                 }
    3828             :                         }
    3829             :                         break;
    3830           2 :                 case SVG_Coordinate_datatype:
    3831             :                         n = (SVG_Number*)val;
    3832           2 :                         lsr_write_coordinate(lsr, n->value, GF_FALSE, "val");
    3833             :                         break;
    3834             :                 //only applies to text x,y and not updatable in laser
    3835             : #if 0
    3836             :                 case SVG_Coordinates_datatype:
    3837             :                         GF_LSR_WRITE_INT(lsr, 0, 1, "isInherit");
    3838             :                         GF_LSR_WRITE_INT(lsr, 0, 1, "escapeFlag");
    3839             :                         lsr_write_float_list(lsr, (GF_List **)val, "val");
    3840             :                         break;
    3841             : #endif
    3842           0 :                 case XMLRI_datatype:
    3843           0 :                         if ((att_tag==TAG_XLINK_ATT_href) || (att_tag==TAG_SVG_ATT_syncReference)) {
    3844           0 :                                 lsr_write_any_uri(lsr, (XMLRI*)val, "val");
    3845           0 :                         } else if (((XMLRI*)val)->target) {
    3846           0 :                                 GF_LSR_WRITE_INT(lsr, 0, 1, "isDefault");
    3847           0 :                                 GF_LSR_WRITE_INT(lsr, 0, 1, "isEscape");
    3848           0 :                                 lsr_write_vluimsbf5(lsr, gf_node_get_id( ((XMLRI*)val)->target) - 1, "ID");
    3849             :                         } else {
    3850           0 :                                 GF_LSR_WRITE_INT(lsr, 1, 1, "isDefault");
    3851             :                         }
    3852             :                         break;
    3853           6 :                 case SVG_Focus_datatype:
    3854           6 :                         if (((SVG_Focus*)val)->type == SVG_FOCUS_SELF) {
    3855           2 :                                 GF_LSR_WRITE_INT(lsr, 0, 1, "isDefault");
    3856           2 :                                 GF_LSR_WRITE_INT(lsr, 1, 1, "isEscape");
    3857           2 :                                 GF_LSR_WRITE_INT(lsr, 1, 2, "escapeEnumVal");
    3858           4 :                         } else if ( (((SVG_Focus*)val)->type == SVG_FOCUS_AUTO) || !((SVG_Focus*)val)->target.target) {
    3859           2 :                                 GF_LSR_WRITE_INT(lsr, 1, 1, "isDefault");
    3860             :                         } else {
    3861           2 :                                 GF_LSR_WRITE_INT(lsr, 0, 1, "isDefault");
    3862           2 :                                 GF_LSR_WRITE_INT(lsr, 0, 1, "isEscape");
    3863           2 :                                 lsr_write_vluimsbf5(lsr, gf_node_get_id( ((SVG_Focus*)val)->target.target) - 1, "ID");
    3864             :                         }
    3865             :                         break;
    3866             : 
    3867           4 :                 case DOM_String_datatype:
    3868             :                 case SVG_ContentType_datatype:
    3869             :                 case SVG_LanguageID_datatype:
    3870           4 :                         lsr_write_byte_align_string(lsr, val ? *(DOM_String *)val : (char *)"", "val");
    3871             :                         break;
    3872           0 :                 case SVG_Motion_datatype:
    3873           0 :                         lsr_write_coordinate(lsr, ((GF_Matrix2D *)val)->m[2], GF_FALSE, "pointValueX");
    3874           0 :                         lsr_write_coordinate(lsr, ((GF_Matrix2D *)val)->m[5], GF_FALSE, "pointValueY");
    3875             :                         break;
    3876           0 :                 case SVG_Points_datatype:
    3877           0 :                         lsr_write_point_sequence(lsr, (GF_List **)val, "val");
    3878             :                         break;
    3879           0 :                 case SVG_PathData_datatype:
    3880           0 :                         lsr_write_path_type(lsr, (SVG_PathData*)val, "val");
    3881             :                         break;
    3882           0 :                 case LASeR_Choice_datatype:
    3883             :                 {
    3884             :                         LASeR_Choice *ch = (LASeR_Choice *)val;
    3885           0 :                         GF_LSR_WRITE_INT(lsr, (ch->type==LASeR_CHOICE_ALL) ? 1 : 0, 1, "isDefaultValue");
    3886           0 :                         if (ch->type!=LASeR_CHOICE_ALL) {
    3887           0 :                                 GF_LSR_WRITE_INT(lsr, (ch->type==LASeR_CHOICE_NONE) ? 1 : 0, 1, "escapeFlag");
    3888           0 :                                 if (ch->type==LASeR_CHOICE_NONE) {
    3889           0 :                                         GF_LSR_WRITE_INT(lsr, LASeR_CHOICE_NONE, 2, "escapeEnum");
    3890             :                                 } else {
    3891           0 :                                         lsr_write_vluimsbf5(lsr, ((LASeR_Choice *)val)->choice_index, "value");
    3892             :                                 }
    3893             :                         }
    3894             :                 }
    3895             :                 break;
    3896             :                 //only applies to svg viewport and not updatable in laser
    3897             : #if 0
    3898             :                 case SVG_ViewBox_datatype:
    3899             :                 {
    3900             :                         SVG_ViewBox *b = (SVG_ViewBox *)val;
    3901             :                         GF_LSR_WRITE_INT(lsr, 0, 1, "isDefaultValue");
    3902             :                         GF_LSR_WRITE_INT(lsr, 0, 1, "escapeFlag");
    3903             :                         lsr_write_vluimsbf5(lsr, 4, "nb1");
    3904             :                         lsr_write_fixed_16_8(lsr, b->x, "x");
    3905             :                         lsr_write_fixed_16_8(lsr, b->y, "y");
    3906             :                         lsr_write_fixed_16_8(lsr, b->width, "width");
    3907             :                         lsr_write_fixed_16_8(lsr, b->width, "height");
    3908             :                 }
    3909             :                 break;
    3910             : #endif
    3911           2 :                 case SVG_FontFamily_datatype:
    3912             :                 {
    3913             :                         SVG_FontFamily *ff = (SVG_FontFamily *)val;
    3914           2 :                         GF_LSR_WRITE_INT(lsr, (ff->type == SVG_FONTFAMILY_INHERIT) ? 1 : 0, 1, "isDefaultValue");
    3915           2 :                         if (ff->type != SVG_FONTFAMILY_INHERIT) {
    3916           2 :                                 s32 idx = lsr_get_font_index(lsr, ff);
    3917           2 :                                 if (idx==-1) {
    3918           0 :                                         GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] corrupted font table while encoding update value\n"));
    3919             :                                         idx=0;
    3920             :                                 }
    3921           2 :                                 GF_LSR_WRITE_INT(lsr, 0, 1, "escapeFlag");
    3922           2 :                                 lsr_write_vluimsbf5(lsr, (u32) idx, "nb1");
    3923             :                         }
    3924             :                 }
    3925             :                 break;
    3926           2 :                 default:
    3927           2 :                         if ((fieldType>=SVG_FillRule_datatype) && (fieldType<=SVG_LAST_U8_PROPERTY)) {
    3928           2 :                                 u8 v = *(u8 *)val;
    3929             :                                 /*TODO fixme, check inherit/default values*/
    3930           2 :                                 if (!v) {
    3931           0 :                                         GF_LSR_WRITE_INT(lsr, 1, 1, "isDefaultValue");
    3932             :                                 } else {
    3933           2 :                                         GF_LSR_WRITE_INT(lsr, 0, 1, "isDefaultValue");
    3934           2 :                                         lsr_write_vluimsbf5(lsr, v, "val");
    3935             :                                 }
    3936             :                         } else {
    3937           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] update value not implemented for type %d - please fix or report\n", fieldType));
    3938             :                         }
    3939             :                 }
    3940             :         }
    3941          54 : }
    3942             : /*FIXME - support for scale/translate/rotation*/
    3943          62 : static GF_Err lsr_write_add_replace_insert(GF_LASeRCodec *lsr, GF_Command *com)
    3944             : {
    3945             :         GF_CommandField *field;
    3946             :         u8 type = 0;
    3947             :         Bool is_text_node = GF_FALSE;
    3948             :         u32 field_type, tr_type = 0;
    3949          62 :         if (com->tag==GF_SG_LSR_REPLACE) type = LSR_UPDATE_REPLACE;
    3950           4 :         else if (com->tag==GF_SG_LSR_ADD) type = LSR_UPDATE_ADD;
    3951           4 :         else if (com->tag==GF_SG_LSR_INSERT) type = LSR_UPDATE_INSERT;
    3952             :         else return GF_BAD_PARAM;
    3953             : 
    3954          62 :         GF_LSR_WRITE_INT(lsr, type, 4, "ch4");
    3955          62 :         field = (GF_CommandField*)gf_list_get(com->command_fields, 0);
    3956             :         field_type = 0;
    3957          62 :         if (field && ( !field->new_node || (field->fieldIndex==TAG_LSR_ATT_children) ) && !field->node_list) {
    3958             :                 s32 attType = 0;
    3959          52 :                 field_type = field->fieldType;
    3960          52 :                 attType = gf_lsr_anim_type_from_attribute(field->fieldIndex);
    3961          52 :                 if (attType== -1) {
    3962           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[LASeR] Attribute %s of element %s is not updatable\n", gf_svg_get_attribute_name(com->node, field->fieldIndex), gf_node_get_class_name(com->node) ));
    3963           0 :                         return lsr->last_error = GF_BAD_PARAM;
    3964             :                 }
    3965          52 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "has_attributeName");
    3966          52 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "choice");
    3967          52 :                 GF_LSR_WRITE_INT(lsr, attType, 8, "attributeName");
    3968             :         }
    3969             :         /*single text */
    3970          10 :         else if (field && field->new_node && field->new_node->sgprivate->tag==TAG_DOMText) {
    3971           4 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "has_attributeName");
    3972           4 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "choice");
    3973           4 :                 GF_LSR_WRITE_INT(lsr, LSR_UPDATE_TYPE_TEXT_CONTENT, 8, "attributeName");
    3974             :                 is_text_node = GF_TRUE;
    3975             :         } else {
    3976           6 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "has_attributeName");
    3977             :         }
    3978             :         /*if not add*/
    3979          62 :         if (type!=LSR_UPDATE_ADD) {
    3980          62 :                 if (!field || field->pos<0) {
    3981          46 :                         GF_LSR_WRITE_INT(lsr, 0, 1, "has_index");
    3982             :                 } else {
    3983          16 :                         GF_LSR_WRITE_INT(lsr, 1, 1, "has_index");
    3984          16 :                         lsr_write_vluimsbf5(lsr, (u32) field->pos, "index");
    3985             :                 }
    3986             :         }
    3987          62 :         if (type!=LSR_UPDATE_INSERT) {
    3988          58 :                 if (com->fromNodeID) {
    3989             :                         u8 opAttType;
    3990           2 :                         opAttType = gf_lsr_anim_type_from_attribute(com->fromFieldIndex);
    3991           2 :                         GF_LSR_WRITE_INT(lsr, 1, 1, "has_operandAttribute");
    3992           2 :                         GF_LSR_WRITE_INT(lsr, opAttType, 8, "operandAttribute");
    3993           2 :                         GF_LSR_WRITE_INT(lsr, 1, 1, "has_operandElementId");
    3994           2 :                         lsr_write_codec_IDREF_Node(lsr, com->node, "operandElementId");
    3995             :                 } else {
    3996          56 :                         GF_LSR_WRITE_INT(lsr, 0, 1, "has_operandAttribute");
    3997          56 :                         GF_LSR_WRITE_INT(lsr, 0, 1, "has_operandElementId");
    3998             :                 }
    3999             :         }
    4000          62 :         lsr_write_codec_IDREF_Node(lsr, com->node, "ref");
    4001          62 :         if (field && !field->new_node && !field->node_list && !com->fromNodeID) {
    4002          50 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "has_value");
    4003          50 :                 lsr_write_update_value(lsr, (SVG_Element *)com->node, field_type, field->fieldIndex, tr_type, field->field_ptr, (field->pos>=0) ? GF_TRUE : GF_FALSE);
    4004          12 :         } else if (field && is_text_node) {
    4005           4 :                 GF_DOMText *t = (GF_DOMText *)field->new_node;
    4006           4 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "has_value");
    4007           4 :                 lsr_write_update_value(lsr, (SVG_Element *)com->node, DOM_String_datatype, field->fieldIndex, 0, &t->textContent, (field->pos>=0) ? GF_TRUE : GF_FALSE);
    4008             :         } else {
    4009           8 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "has_value");
    4010             :         }
    4011          62 :         lsr_write_any_attribute(lsr, NULL, GF_TRUE);
    4012             :         /*if not add*/
    4013          62 :         if (type!=LSR_UPDATE_ADD) {
    4014          62 :                 if (field && field->node_list && !com->fromNodeID) {
    4015             :                         GF_ChildNodeItem *l = field->node_list;
    4016           4 :                         u32 count = gf_node_list_get_count(l);
    4017           4 :                         GF_LSR_WRITE_INT(lsr, 1, 1, "opt_group");
    4018             : 
    4019           4 :                         if (type==LSR_UPDATE_REPLACE) lsr_write_vluimsbf5(lsr, count, "count");
    4020             : 
    4021          82 :                         while (l) {
    4022          80 :                                 lsr_write_update_content_model(lsr, (SVG_Element*) com->node, l->node);
    4023          80 :                                 l = l->next;
    4024          80 :                                 if (type==LSR_UPDATE_INSERT) break;
    4025             :                         }
    4026          58 :                 } else if (field && field->new_node && !is_text_node) {
    4027           2 :                         GF_LSR_WRITE_INT(lsr, 1, 1, "opt_group");
    4028           2 :                         if (type==LSR_UPDATE_REPLACE) lsr_write_vluimsbf5(lsr, 1, "count");
    4029           2 :                         lsr_write_update_content_model(lsr, (SVG_Element*) com->node, field->new_node);
    4030             :                 } else {
    4031          56 :                         GF_LSR_WRITE_INT(lsr, 0, 1, "opt_group");
    4032             :                 }
    4033             :         }
    4034             :         return GF_OK;
    4035             : }
    4036             : 
    4037          10 : static GF_Err lsr_write_command_list(GF_LASeRCodec *lsr, GF_List *com_list, SVG_Element *cond, Bool first_implicit)
    4038             : {
    4039             :         GF_CommandField *field;
    4040             :         u32 i, count;
    4041             :         u32 detail;
    4042             :         GF_BitStream *old_bs;
    4043             : 
    4044          10 :         count = com_list ? gf_list_count(com_list) : 0;
    4045             : 
    4046             :         old_bs = NULL;
    4047          10 :         if (cond) {
    4048             :                 /*use temp bitstream for encoding conditional*/
    4049           4 :                 old_bs = lsr->bs;
    4050           4 :                 lsr->bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
    4051             :         }
    4052             :         assert(count>= (u32) (first_implicit ? 1 : 0) );
    4053             : 
    4054          10 :         lsr_write_vluimsbf5(lsr, count-first_implicit, "occ0");
    4055             : 
    4056          10 :         if (!com_list) goto exit;
    4057             : 
    4058           8 :         count = gf_list_count(com_list);
    4059         190 :         for (i=0; i<count; i++) {
    4060         182 :                 GF_Command *com = (GF_Command *)gf_list_get(com_list, i);
    4061         182 :                 switch (com->tag) {
    4062           2 :                 case GF_SG_LSR_NEW_SCENE:
    4063             :                 case GF_SG_LSR_REFRESH_SCENE:
    4064           2 :                         GF_LSR_WRITE_INT(lsr, (com->tag==GF_SG_LSR_REFRESH_SCENE) ? LSR_UPDATE_REFRESH_SCENE : LSR_UPDATE_NEW_SCENE, 4, "ch4");
    4065           2 :                         if (com->tag==GF_SG_LSR_REFRESH_SCENE) lsr_write_vluimsbf5(lsr, /*refresh scene time*/0, "time");
    4066           2 :                         lsr_write_any_attribute(lsr, NULL, 1);
    4067           2 :                         lsr_write_svg(lsr, (SVG_Element*)com->node);
    4068           2 :                         break;
    4069          62 :                 case GF_SG_LSR_REPLACE:
    4070             :                 case GF_SG_LSR_ADD:
    4071             :                 case GF_SG_LSR_INSERT:
    4072          62 :                         lsr_write_add_replace_insert(lsr, com);
    4073          62 :                         break;
    4074             :                 case GF_SG_LSR_CLEAN:
    4075             :                         break;
    4076           6 :                 case GF_SG_LSR_DELETE:
    4077           6 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_DELETE, 4, "ch4");
    4078           6 :                         field = (GF_CommandField*)gf_list_get(com->command_fields, 0);
    4079           6 :                         if (field && field->fieldType) {
    4080             :                                 u8 attType;
    4081           2 :                                 attType = gf_lsr_anim_type_from_attribute(field->fieldIndex);
    4082           2 :                                 GF_LSR_WRITE_INT(lsr, 1, 1, "has_attributeName");
    4083           2 :                                 GF_LSR_WRITE_INT(lsr, 0, 1, "choice");
    4084           2 :                                 GF_LSR_WRITE_INT(lsr, attType, 8, "attributeName");
    4085             :                         } else {
    4086           4 :                                 GF_LSR_WRITE_INT(lsr, 0, 1, "has_attributeName");
    4087             :                         }
    4088           6 :                         if (!field || (field->pos<0) ) {
    4089           4 :                                 GF_LSR_WRITE_INT(lsr, 0, 1, "has_index");
    4090             :                         } else {
    4091           2 :                                 GF_LSR_WRITE_INT(lsr, 1, 1, "has_index");
    4092           2 :                                 lsr_write_vluimsbf5(lsr, (u32) field->pos, "index");
    4093             :                         }
    4094           6 :                         lsr_write_codec_IDREF_Node(lsr, com->node, "ref");
    4095           6 :                         lsr_write_any_attribute(lsr, NULL, 1);
    4096           6 :                         break;
    4097             :                 case GF_SG_LSR_RESTORE:
    4098             :                         return GF_NOT_SUPPORTED;
    4099             :                 case GF_SG_LSR_SAVE:
    4100             :                         return GF_NOT_SUPPORTED;
    4101         108 :                 case GF_SG_LSR_SEND_EVENT:
    4102         108 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_SEND_EVENT, 4, "ch4");
    4103             : 
    4104         108 :                         detail = com->send_event_integer;
    4105         108 :                         switch (com->send_event_name) {
    4106          52 :                         case GF_EVENT_KEYDOWN:
    4107             :                         case GF_EVENT_LONGKEYPRESS:
    4108             :                         case GF_EVENT_REPEAT_KEY:
    4109             :                         case GF_EVENT_SHORT_ACCESSKEY:
    4110          52 :                                 detail = dom_to_lsr_key(detail);
    4111          52 :                                 if (detail==100) detail = 0;
    4112             :                                 break;
    4113             :                         }
    4114             : 
    4115             :                         /*FIXME in the spec, way too obscur*/
    4116         108 :                         lsr_write_event_type(lsr, com->send_event_name, com->send_event_integer);
    4117             : 
    4118         108 :                         if (detail && com->send_event_integer) {
    4119          52 :                                 GF_LSR_WRITE_INT(lsr, 1, 1, "has_intvalue");
    4120          52 :                                 GF_LSR_WRITE_INT(lsr, (com->send_event_integer<0) ? 1 : 0, 1, "sign");
    4121          52 :                                 lsr_write_vluimsbf5(lsr, ABS(com->send_event_integer), "value");
    4122             :                         } else {
    4123          56 :                                 GF_LSR_WRITE_INT(lsr, 0, 1, "has_intvalue");
    4124             :                         }
    4125         108 :                         if (com->send_event_name<=GF_EVENT_MOUSEWHEEL) {
    4126          12 :                                 GF_LSR_WRITE_INT(lsr, 1, 1, "has_pointvalue");
    4127          12 :                                 lsr_write_coordinate(lsr, INT2FIX(com->send_event_x), 0, "x");
    4128          12 :                                 lsr_write_coordinate(lsr, INT2FIX(com->send_event_y), 0, "y");
    4129             :                         } else {
    4130          96 :                                 GF_LSR_WRITE_INT(lsr, 0, 1, "has_pointvalue");
    4131             :                         }
    4132         108 :                         lsr_write_codec_IDREF_Node(lsr, com->node, "ref");
    4133         108 :                         if (com->send_event_string) {
    4134           2 :                                 GF_LSR_WRITE_INT(lsr, 1, 1, "has_stringvalue");
    4135           2 :                                 lsr_write_byte_align_string(lsr, com->send_event_string, "stringvalue");
    4136         106 :                         } else if (!detail && com->send_event_integer) {
    4137           4 :                                 GF_LSR_WRITE_INT(lsr, 1, 1, "has_stringvalue");
    4138           4 :                                 lsr_write_byte_align_string(lsr, (char *)gf_dom_get_key_name(com->send_event_integer), "stringvalue");
    4139             :                         } else {
    4140         102 :                                 GF_LSR_WRITE_INT(lsr, 0, 1, "has_stringvalue");
    4141             :                         }
    4142         108 :                         GF_LSR_WRITE_INT(lsr, 0, 1, "has_attr_any");
    4143             :                         break;
    4144             : 
    4145           4 :                 case GF_SG_LSR_ACTIVATE:
    4146             :                 case GF_SG_LSR_DEACTIVATE:
    4147             :                 {
    4148           4 :                         u32 update_size = lsr_get_IDREF_nb_bits(lsr, com->node);
    4149             : 
    4150           4 :                         GF_LSR_WRITE_INT(lsr, LSR_UPDATE_EXTEND, 4, "ch4");
    4151           4 :                         GF_LSR_WRITE_INT(lsr, 2, lsr->info->cfg.extensionIDBits, "extensionID");
    4152           4 :                         lsr_write_vluimsbf5(lsr, 10 + 5 /*occ2*/ + 2 /*reserved*/ + 5 /*occ3*/ + 2 /*ch5*/ + update_size, "len");
    4153           4 :                         lsr_write_vluimsbf5(lsr, 87, "reserved");
    4154           4 :                         lsr_write_vluimsbf5(lsr, 1, "occ2");
    4155           4 :                         GF_LSR_WRITE_INT(lsr, 1, 2, "reserved");
    4156           4 :                         lsr_write_vluimsbf5(lsr, 1, "occ3");
    4157           4 :                         GF_LSR_WRITE_INT(lsr, (com->tag==GF_SG_LSR_ACTIVATE) ? 1 : 2, 2, "ch5");
    4158           4 :                         lsr_write_codec_IDREF_Node(lsr, com->node, "ref");
    4159             :                 }
    4160           4 :                 break;
    4161           0 :                 default:
    4162           0 :                         return GF_BAD_PARAM;
    4163             :                 }
    4164             :                 /*same-coding scope is command-based (to check in the spec)*/
    4165         182 :                 lsr->prev_g = NULL;
    4166         182 :                 lsr->prev_line = NULL;
    4167         182 :                 lsr->prev_path = NULL;
    4168         182 :                 lsr->prev_polygon = NULL;
    4169         182 :                 lsr->prev_rect = NULL;
    4170         182 :                 lsr->prev_text = NULL;
    4171         182 :                 lsr->prev_use = NULL;
    4172         182 :                 if (lsr->last_error) break;
    4173             :         }
    4174             : 
    4175          10 : exit:
    4176             :         /*script is aligned*/
    4177          10 :         if (cond)       {
    4178             :                 u8 *data;
    4179             :                 u32 data_size;
    4180           4 :                 gf_bs_get_content(lsr->bs, &data, &data_size);
    4181           4 :                 gf_bs_del(lsr->bs);
    4182           4 :                 lsr->bs = old_bs;
    4183           4 :                 lsr_write_vluimsbf5(lsr, data_size, NULL/*"encoding-length" - don't log to avoid corrupting the log order!!*/);
    4184             :                 /*script is aligned*/
    4185           4 :                 gf_bs_align(lsr->bs);
    4186           4 :                 gf_bs_write_data(lsr->bs, data, data_size);
    4187           4 :                 gf_free(data);
    4188             :         }
    4189          10 :         return lsr->last_error;
    4190             : }
    4191             : 
    4192          30 : static void lsr_add_color(GF_LASeRCodec *lsr, SVG_Color *color)
    4193             : {
    4194          30 :         lsr->col_table = (LSRCol*)gf_realloc(lsr->col_table, sizeof(LSRCol)*(lsr->nb_cols+1));
    4195          30 :         lsr->col_table[lsr->nb_cols].r = FIX2INT(color->red*lsr->color_scale);
    4196          30 :         lsr->col_table[lsr->nb_cols].g = FIX2INT(color->green*lsr->color_scale);
    4197          30 :         lsr->col_table[lsr->nb_cols].b = FIX2INT(color->blue*lsr->color_scale);
    4198          30 :         lsr->nb_cols++;
    4199          30 : }
    4200             : 
    4201         138 : static void lsr_check_col_index(GF_LASeRCodec *lsr, SVG_Color *color, SVG_Paint *paint)
    4202             : {
    4203             :         s32 idx;
    4204         138 :         if (color) {
    4205           8 :                 idx = lsr_get_col_index(lsr, color);
    4206           8 :                 if (idx==-2) lsr_add_color(lsr, color);
    4207             :         }
    4208         130 :         else if (paint && (paint->type==SVG_PAINT_COLOR) ) {
    4209         106 :                 idx = lsr_get_col_index(lsr, &paint->color);
    4210         106 :                 if (idx==-2) lsr_add_color(lsr, &paint->color);
    4211             :         }
    4212         138 : }
    4213             : 
    4214          14 : static void lsr_check_font_index(GF_LASeRCodec *lsr, SVG_FontFamily *font)
    4215             : {
    4216             :         u32 count, i;
    4217          14 :         if (font && (font->type == SVG_FONTFAMILY_VALUE) && font->value) {
    4218             :                 Bool found = 0;
    4219          10 :                 count = gf_list_count(lsr->font_table);
    4220           2 :                 for (i=0; i<count; i++) {
    4221           8 :                         char *ff = (char *)gf_list_get(lsr->font_table, i);
    4222           8 :                         if (!strcmp(ff, font->value)) {
    4223             :                                 found = 1;
    4224             :                                 break;
    4225             :                         }
    4226             :                 }
    4227          10 :                 if (!found) gf_list_add(lsr->font_table, gf_strdup(font->value));
    4228             :         }
    4229          14 : }
    4230             : 
    4231         610 : static void lsr_check_font_and_color(GF_LASeRCodec *lsr, SVG_Element *elt)
    4232             : {
    4233             :         GF_ChildNodeItem *l;
    4234             :         SVGAttribute *att;
    4235             :         u32 i, count, tag;
    4236             :         u32 check_anim_font, check_anim_col;
    4237             : 
    4238         610 :         tag = gf_node_get_tag((GF_Node*)elt);
    4239         610 :         if (tag < GF_NODE_FIRST_DOM_NODE_TAG) goto check_children;
    4240             : 
    4241             :         check_anim_font = check_anim_col = 0;
    4242         470 :         att = elt->attributes;
    4243        2894 :         while (att) {
    4244        1954 :                 switch (att->data_type) {
    4245         108 :                 case SVG_Paint_datatype:
    4246         108 :                         lsr_check_col_index(lsr, NULL, att->data);
    4247         108 :                         break;
    4248           2 :                 case SVG_FontFamily_datatype:
    4249           2 :                         lsr_check_font_index(lsr, att->data);
    4250           2 :                         break;
    4251          82 :                 case SMIL_AttributeName_datatype:
    4252             :                 {
    4253          82 :                         SMIL_AttributeName *an = (SMIL_AttributeName*)att->data;
    4254          82 :                         if (an->name) {
    4255          82 :                                 if (!strcmp(an->name, "fill")) check_anim_col = 1; /*we're sure this is not SMIL fill, it is not animatable*/
    4256          74 :                                 else if (!strcmp(an->name, "stroke")) check_anim_col = 1;
    4257          74 :                                 else if (!strcmp(an->name, "color")) check_anim_col = 1;
    4258          74 :                                 else if (!strcmp(an->name, "solid-color")) check_anim_col = 2;
    4259          70 :                                 else if (!strcmp(an->name, "stop-color")) check_anim_col = 2;
    4260          70 :                                 else if (!strcmp(an->name, "font-family")) check_anim_font = 1;
    4261             :                         }
    4262             :                 }
    4263             :                 break;
    4264             :                 }
    4265        1954 :                 att = att->next;
    4266             :         }
    4267             : 
    4268         470 :         if (check_anim_font || check_anim_col) {
    4269          14 :                 att = elt->attributes;
    4270         116 :                 while (att) {
    4271          88 :                         switch (att->data_type) {
    4272           8 :                         case SMIL_AnimateValue_datatype:
    4273           8 :                                 if (check_anim_font) lsr_check_font_index(lsr, ((SMIL_AnimateValue*)att->data)->value);
    4274           8 :                                 else if (check_anim_col == 1) lsr_check_col_index(lsr, NULL, ((SMIL_AnimateValue*)att->data)->value);
    4275           4 :                                 else if (check_anim_col == 2) lsr_check_col_index(lsr, ((SMIL_AnimateValue*)att->data)->value, NULL);
    4276             :                                 break;
    4277           8 :                         case SMIL_AnimateValues_datatype:
    4278             :                         {
    4279           8 :                                 SMIL_AnimateValues *vals = (SMIL_AnimateValues*)att->data;
    4280           8 :                                 count = gf_list_count(vals->values);
    4281          36 :                                 for (i=0; i<count; i++) {
    4282          28 :                                         if (check_anim_font) lsr_check_font_index(lsr, (SVG_FontFamily*)gf_list_get(vals->values, i));
    4283          18 :                                         else if (check_anim_col == 1) lsr_check_col_index(lsr, NULL, (SVG_Paint*)gf_list_get(vals->values, i) );
    4284           4 :                                         else if (check_anim_col == 2) lsr_check_col_index(lsr, (SVG_Color*)gf_list_get(vals->values, i), NULL);
    4285             :                                 }
    4286             :                         }
    4287             :                         break;
    4288             :                         }
    4289          88 :                         att = att->next;
    4290             :                 }
    4291             :         }
    4292             : 
    4293         610 : check_children:
    4294         610 :         l = elt->children;
    4295        1630 :         while (l) {
    4296         410 :                 if (l->node->sgprivate->tag==TAG_DOMUpdates) {
    4297             :                         GF_DOMUpdates *up = (GF_DOMUpdates *)l->node;
    4298           2 :                         count = gf_list_count(up->updates);
    4299          10 :                         for (i=0; i<count; i++) {
    4300             :                                 u32 j, c2;
    4301           8 :                                 GF_Command *com = gf_list_get(up->updates, i);
    4302           8 :                                 c2 = gf_list_count(com->command_fields);
    4303          14 :                                 for (j=0; j<c2; j++) {
    4304           6 :                                         GF_CommandField *field = (GF_CommandField *)gf_list_get(com->command_fields, j);
    4305           6 :                                         if (field->new_node) {
    4306           0 :                                                 lsr_check_font_and_color(lsr, (SVG_Element*)field->new_node);
    4307             :                                         }
    4308             :                                         /*replace/insert*/
    4309           6 :                                         else if (field->field_ptr) {
    4310           6 :                                                 switch (field->fieldType) {
    4311           4 :                                                 case SVG_Paint_datatype:
    4312           4 :                                                         lsr_check_col_index(lsr, NULL, (SVG_Paint*)field->field_ptr);
    4313           4 :                                                         break;
    4314           0 :                                                 case SVG_Color_datatype:
    4315           0 :                                                         lsr_check_col_index(lsr, (SVG_Color*)field->field_ptr, NULL);
    4316           0 :                                                         break;
    4317           2 :                                                 case SVG_FontFamily_datatype:
    4318           2 :                                                         lsr_check_font_index(lsr, (SVG_FontFamily*)field->field_ptr);
    4319           2 :                                                         break;
    4320             :                                                 }
    4321             :                                         }
    4322             :                                 }
    4323             :                         }
    4324             :                 } else {
    4325         408 :                         lsr_check_font_and_color(lsr, (SVG_Element*)l->node);
    4326             :                 }
    4327         410 :                 l = l->next;
    4328             :         }
    4329         610 : }
    4330             : 
    4331           6 : static GF_Err lsr_write_laser_unit(GF_LASeRCodec *lsr, GF_List *com_list, Bool reset_encoding_context)
    4332             : {
    4333             :         u32 i, count, prev_col_count, prev_font_count;
    4334             : 
    4335             :         /*
    4336             :          *      1 - laser unit header
    4337             :          */
    4338           6 :         if (!com_list) {
    4339           0 :                 if (gf_sg_get_root_node(lsr->sg) == NULL) return GF_BAD_PARAM;
    4340             :                 /*RAP generation, force reset encoding context*/
    4341           0 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "resetEncodingContext");
    4342             :         } else {
    4343           6 :                 GF_LSR_WRITE_INT(lsr, reset_encoding_context ? 1 : 0, 1, "resetEncodingContext");
    4344             :         }
    4345           6 :         GF_LSR_WRITE_INT(lsr, 0, 1, "opt_group");
    4346             : #if 0
    4347             :         lsr_write_extension(lsr, NULL, 0, "ext");
    4348             : #endif
    4349             : 
    4350             :         /*clean all tables*/
    4351           6 :         if (reset_encoding_context) {
    4352           0 :                 lsr->nb_cols = 0;
    4353           0 :                 if (lsr->col_table) gf_free(lsr->col_table);
    4354           0 :                 lsr->col_table = NULL;
    4355           0 :                 while (gf_list_count(lsr->font_table)) {
    4356           0 :                         char *ft = (char *)gf_list_last(lsr->font_table);
    4357           0 :                         gf_free(ft);
    4358           0 :                         gf_list_rem_last(lsr->font_table);
    4359             :                 }
    4360             :         }
    4361             : 
    4362             :         /*
    4363             :          *      2 - codecInitialisations
    4364             :          */
    4365             : 
    4366           6 :         prev_col_count = lsr->nb_cols;
    4367           6 :         prev_font_count = gf_list_count(lsr->font_table);
    4368             :         /*RAP generation, send all fonts and colors*/
    4369           6 :         if (!com_list) {
    4370             :                 prev_col_count = prev_font_count = 0;
    4371           0 :                 lsr_check_font_and_color(lsr, (SVG_Element *)gf_sg_get_root_node(lsr->sg));
    4372             :         } else {
    4373             :                 /*process all colors and fonts*/
    4374           6 :                 count = gf_list_count(com_list);
    4375         180 :                 for (i=0; i<count; i++) {
    4376         174 :                         GF_Command *com = (GF_Command *)gf_list_get(com_list, i);
    4377         174 :                         if (gf_list_count(com->command_fields)) {
    4378          58 :                                 GF_CommandField *field = (GF_CommandField *)gf_list_get(com->command_fields, 0);
    4379          58 :                                 if (field->fieldType==SVG_Paint_datatype) lsr_check_col_index(lsr, NULL, (SVG_Paint*)field->field_ptr);
    4380          58 :                                 else if (field->fieldType==SVG_FontFamily_datatype) lsr_check_font_index(lsr, (SVG_FontFamily*)field->field_ptr);
    4381          58 :                                 else if (field->new_node) lsr_check_font_and_color(lsr, (SVG_Element*)field->new_node);
    4382          52 :                                 else if (field->node_list) {
    4383             :                                         GF_ChildNodeItem *l = field->node_list;
    4384          86 :                                         while (l) {
    4385          82 :                                                 lsr_check_font_and_color(lsr, (SVG_Element*)l->node);
    4386          82 :                                                 l = l->next;
    4387             :                                         }
    4388             :                                 }
    4389         116 :                         } else if (com->node && (com->tag!=GF_SG_LSR_DELETE) ) {
    4390         114 :                                 lsr_check_font_and_color(lsr, (SVG_Element *)com->node);
    4391             :                         }
    4392             :                 }
    4393             :         }
    4394             :         /*
    4395             :          * 2.a - condecInitialization.color
    4396             :          */
    4397           6 :         if (prev_col_count == lsr->nb_cols) {
    4398           4 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "colorInitialisation");
    4399             :         } else {
    4400           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "colorInitialisation");
    4401           2 :                 lsr_write_vluimsbf5(lsr, lsr->nb_cols - prev_col_count, "count");
    4402          32 :                 for (i=prev_col_count; i<lsr->nb_cols; i++) {
    4403          30 :                         GF_LSR_WRITE_INT(lsr, lsr->col_table[i].r, lsr->info->cfg.colorComponentBits, "red");
    4404          30 :                         GF_LSR_WRITE_INT(lsr, lsr->col_table[i].g, lsr->info->cfg.colorComponentBits, "green");
    4405          30 :                         GF_LSR_WRITE_INT(lsr, lsr->col_table[i].b, lsr->info->cfg.colorComponentBits, "blue");
    4406             :                 }
    4407             :         }
    4408           6 :         lsr->colorIndexBits = gf_get_bit_size(lsr->nb_cols);
    4409             :         /*
    4410             :          * 2.b - condecInitialization.fonts
    4411             :          */
    4412           6 :         count = gf_list_count(lsr->font_table);
    4413           6 :         if (prev_font_count == count) {
    4414           4 :                 GF_LSR_WRITE_INT(lsr, 0, 1, "fontInitialisation");
    4415             :         } else {
    4416           2 :                 GF_LSR_WRITE_INT(lsr, 1, 1, "fontInitialisation");
    4417           2 :                 lsr_write_vluimsbf5(lsr, count - prev_font_count, "count");
    4418           6 :                 for (i=prev_font_count; i<count; i++) {
    4419           4 :                         char *ft = (char *)gf_list_get(lsr->font_table, i);
    4420           4 :                         lsr_write_byte_align_string(lsr, ft, "font");
    4421             :                 }
    4422             :         }
    4423           6 :         lsr->fontIndexBits = gf_get_bit_size(count);
    4424             :         /*
    4425             :          * 2.c - condecInitialization.private
    4426             :          */
    4427           6 :         GF_LSR_WRITE_INT(lsr, 0, 1, "privateDataIdentifierInitialisation");
    4428             :         /*
    4429             :          * 2.d - condecInitialization.anyXML
    4430             :          */
    4431           6 :         GF_LSR_WRITE_INT(lsr, 0, 1, "anyXMLInitialisation");
    4432             :         /*
    4433             :          * 2.e - condecInitialization.extended
    4434             :          */
    4435             :         /*FIXME - node string IDs are currently not used*/
    4436           6 :         lsr_write_vluimsbf5(lsr, 0, "countG");
    4437             :         /*FIXME - global streams are currently not used*/
    4438           6 :         GF_LSR_WRITE_INT(lsr, 0, 1, "hasExtension");
    4439             : 
    4440             :         /*RAP generation, encode NewScene with root node*/
    4441           6 :         if (!com_list) {
    4442           0 :                 lsr_write_vluimsbf5(lsr, 0, "occ0");
    4443           0 :                 GF_LSR_WRITE_INT(lsr, 4, 4, "ch4");
    4444           0 :                 lsr_write_any_attribute(lsr, NULL, 1);
    4445           0 :                 lsr_write_svg(lsr, (SVG_Element *)gf_sg_get_root_node(lsr->sg) );
    4446             :         } else {
    4447           6 :                 GF_Err e = lsr_write_command_list(lsr, com_list, NULL, 1);
    4448           6 :                 if (e) return e;
    4449             :         }
    4450           6 :         GF_LSR_WRITE_INT(lsr, 0, 1, "opt_group");
    4451             : #if 0
    4452             :         lsr_write_extension(lsr, NULL, 0, "ext");
    4453             : #endif
    4454             :         return GF_OK;
    4455             : }
    4456             : 
    4457             : #endif /*GPAC_DISABLE_LASER*/

Generated by: LCOV version 1.13