/* * GPAC - Multimedia Framework C SDK * * Authors: Jean le Feuvre * Copyright (c) 2005-200X ENST * All rights reserved * * This file is part of GPAC / LASeR codec sub-project * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */ #include #include #include #include #include #define GF_LSR_READ_INT(_codec, _val, _nbBits, _str) {\ (_val) = gf_bs_read_int(_codec->bs, _nbBits); \ GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] %s\t\t%d\t\t%d\n", _str, _nbBits, _val)); \ }\ static void lsr_read_group_content(GF_LASeRCodec *lsr, GF_Node *elt, Bool skip_object_content); static void lsr_read_group_content_post_init(GF_LASeRCodec *lsr, SVG_Element *elt, Bool skip_init); static GF_Err lsr_read_command_list(GF_LASeRCodec *lsr, GF_List *comList, SVG_Element *cond, Bool first_imp); static GF_Err lsr_decode_laser_unit(GF_LASeRCodec *lsr, GF_List *com_list); static void lsr_read_path_type(GF_LASeRCodec *lsr, GF_Node *n, u32 tag, SVG_PathData *path, const char *name); static void lsr_read_point_sequence(GF_LASeRCodec *lsr, GF_List *pts, const char *name); static Bool lsr_setup_smil_anim(GF_LASeRCodec *lsr, SVG_Element *anim, SVG_Element *anim_parent); GF_EXPORT GF_LASeRCodec *gf_laser_decoder_new(GF_SceneGraph *graph) { GF_LASeRCodec *tmp; GF_SAFEALLOC(tmp, GF_LASeRCodec); if (!tmp) return NULL; tmp->streamInfo = gf_list_new(); tmp->font_table = gf_list_new(); tmp->defered_hrefs = gf_list_new(); tmp->defered_listeners = gf_list_new(); tmp->defered_anims = gf_list_new(); tmp->unresolved_commands = gf_list_new(); tmp->sg = graph; return tmp; } GF_EXPORT void gf_laser_decoder_del(GF_LASeRCodec *codec) { /*destroy all config*/ while (gf_list_count(codec->streamInfo)) { LASeRStreamInfo *p = (LASeRStreamInfo *)gf_list_last(codec->streamInfo); free(p); gf_list_rem_last(codec->streamInfo); } gf_list_del(codec->streamInfo); if (codec->col_table) free(codec->col_table); while (gf_list_count(codec->font_table)) { char *ft = (char *)gf_list_last(codec->font_table); free(ft); gf_list_rem_last(codec->font_table); } gf_list_del(codec->font_table); #if 0 while (gf_list_count(codec->defered_hrefs)) { XMLRI *iri = (XMLRI *)gf_list_last(codec->defered_hrefs); gf_list_rem_last(codec->defered_hrefs); if (iri->string) free(iri->string); iri->string = NULL; } #endif gf_list_del(codec->defered_hrefs); gf_list_del(codec->defered_anims); gf_list_del(codec->defered_listeners); gf_list_del(codec->unresolved_commands); free(codec); } static LASeRStreamInfo *lsr_get_stream(GF_LASeRCodec *codec, u16 ESID) { u32 i=0; LASeRStreamInfo *ptr; while ((ptr = (LASeRStreamInfo *)gf_list_enum(codec->streamInfo, &i))) { if (!ESID || (ptr->ESID==ESID)) return ptr; } return NULL; } GF_EXPORT GF_Err gf_laser_decoder_configure_stream(GF_LASeRCodec *codec, u16 ESID, char *dsi, u32 dsi_len) { LASeRStreamInfo *info; GF_BitStream *bs; if (lsr_get_stream(codec, ESID) != NULL) return GF_BAD_PARAM; GF_SAFEALLOC(info, LASeRStreamInfo); info->ESID = ESID; bs = gf_bs_new(dsi, dsi_len, GF_BITSTREAM_READ); info->cfg.profile = gf_bs_read_int(bs, 8); info->cfg.level = gf_bs_read_int(bs, 8); /*info->cfg.reserved = */ gf_bs_read_int(bs, 3); info->cfg.pointsCodec = gf_bs_read_int(bs, 2); info->cfg.pathComponents = gf_bs_read_int(bs, 4); info->cfg.fullRequestHost = gf_bs_read_int(bs, 1); if (gf_bs_read_int(bs, 1)) { info->cfg.time_resolution = gf_bs_read_int(bs, 16); } else { info->cfg.time_resolution = 1000; } info->cfg.colorComponentBits = gf_bs_read_int(bs, 4); info->cfg.colorComponentBits += 1; info->cfg.resolution = gf_bs_read_int(bs, 4); if (info->cfg.resolution>7) info->cfg.resolution -= 16; info->cfg.coord_bits = gf_bs_read_int(bs, 5); info->cfg.scale_bits_minus_coord_bits = gf_bs_read_int(bs, 4); info->cfg.newSceneIndicator = gf_bs_read_int(bs, 1); /*reserved*/ gf_bs_read_int(bs, 3); info->cfg.extensionIDBits = gf_bs_read_int(bs, 4); /*we ignore the rest*/ gf_list_add(codec->streamInfo, info); gf_bs_del(bs); return GF_OK; } GF_EXPORT GF_Err gf_laser_decoder_remove_stream(GF_LASeRCodec *codec, u16 ESID) { u32 i, count; count = gf_list_count(codec->streamInfo); for (i=0;istreamInfo, i); if (ptr->ESID==ESID) { free(ptr); gf_list_rem(codec->streamInfo, i); return GF_OK; } } return GF_BAD_PARAM; } GF_EXPORT GF_Err gf_laser_decode_au(GF_LASeRCodec *codec, u16 ESID, char *data, u32 data_len) { GF_Err e; if (!codec || !data || !data_len) return GF_BAD_PARAM; codec->info = lsr_get_stream(codec, ESID); if (!codec->info) return GF_BAD_PARAM; codec->coord_bits = codec->info->cfg.coord_bits; codec->scale_bits = codec->info->cfg.scale_bits_minus_coord_bits; codec->time_resolution = codec->info->cfg.time_resolution; codec->color_scale = (1<info->cfg.colorComponentBits) - 1; if (codec->info->cfg.resolution >= 0) codec->res_factor = INT2FIX(1<info->cfg.resolution); else codec->res_factor = gf_divfix(FIX_ONE, INT2FIX(1 << (-codec->info->cfg.resolution)) ); codec->bs = gf_bs_new(data, data_len, GF_BITSTREAM_READ); codec->memory_dec = 0; e = lsr_decode_laser_unit(codec, NULL); gf_bs_del(codec->bs); codec->bs = NULL; return e; } GF_Err gf_laser_decode_command_list(GF_LASeRCodec *codec, u16 ESID, char *data, u32 data_len, GF_List *com_list) { GF_Err e; u32 i; if (!codec || !data || !data_len) return GF_BAD_PARAM; codec->info = lsr_get_stream(codec, ESID); if (!codec->info) return GF_BAD_PARAM; codec->coord_bits = codec->info->cfg.coord_bits; codec->scale_bits = codec->info->cfg.scale_bits_minus_coord_bits; codec->time_resolution = codec->info->cfg.time_resolution; codec->color_scale = (1<info->cfg.colorComponentBits) - 1; if (codec->info->cfg.resolution >= 0) codec->res_factor = INT2FIX(1<info->cfg.resolution); else codec->res_factor = gf_divfix(FIX_ONE, INT2FIX(1 << (-codec->info->cfg.resolution)) ); codec->bs = gf_bs_new(data, data_len, GF_BITSTREAM_READ); codec->memory_dec = 1; e = lsr_decode_laser_unit(codec, com_list); gf_bs_del(codec->bs); codec->bs = NULL; if (e) return e; for (i=0; iunresolved_commands); i++) { GF_Command *com = (GF_Command *)gf_list_get(codec->unresolved_commands, i); assert(!com->node); com->node = gf_sg_find_node(codec->sg, com->RouteID); if (com->node) { gf_node_register(com->node, NULL); com->RouteID = 0; gf_list_rem(codec->unresolved_commands, i); i--; } } return GF_OK; } GF_EXPORT void gf_laser_decoder_set_clock(GF_LASeRCodec *codec, Double (*GetSceneTime)(void *st_cbk), void *st_cbk ) { codec->GetSceneTime = GetSceneTime; codec->cbk = st_cbk; } static u32 lsr_read_vluimsbf5(GF_LASeRCodec *lsr, const char *name) { u32 nb_words = 0; u32 nb_tot, nb_bits, val; while (gf_bs_read_int(lsr->bs, 1)) nb_words++; nb_words++; nb_tot = nb_words; nb_bits = nb_words*4; nb_tot += nb_bits; val = gf_bs_read_int(lsr->bs, nb_bits); if (name) GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] %s\t\t%d\t\t%d\n", name, nb_tot, val)); return val; } static u32 lsr_read_vluimsbf8(GF_LASeRCodec *lsr, const char *name) { u32 nb_words = 0; u32 nb_tot, nb_bits, val; while (gf_bs_read_int(lsr->bs, 1)) nb_words++; nb_words++; nb_tot = nb_words; nb_bits = nb_words*7; nb_tot += nb_bits; val = gf_bs_read_int(lsr->bs, nb_bits); GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] %s\t\t%d\t\t%d\n", name, nb_tot, val)); return val; } static void lsr_read_extension(GF_LASeRCodec *lsr, const char *name) { u32 len = lsr_read_vluimsbf5(lsr, name); #if 0 *out_data = malloc(sizeof(char)*len); gf_bs_read_data(lsr->bs, *out_data, len); *out_len = len; #else while (len) { gf_bs_read_int(lsr->bs, 8); len--; } #endif } static void lsr_read_extend_class(GF_LASeRCodec *lsr, char **out_data, u32 *out_len, const char *name) { u32 len; GF_LSR_READ_INT(lsr, len, lsr->info->cfg.extensionIDBits, "reserved"); len = lsr_read_vluimsbf5(lsr, "len"); // while (len) gf_bs_read_int(lsr->bs, 1); gf_bs_read_long_int(lsr->bs, len); if (out_data) *out_data = NULL; if (out_len) *out_len = 0; } static void lsr_read_private_element_container(GF_LASeRCodec *lsr) { u32 val, len; GF_LSR_READ_INT(lsr, val, 4, "ch4"); switch (val) { /*privateAnyXMLElement*/ case 0: len = lsr_read_vluimsbf5(lsr, "len"); gf_bs_skip_bytes(lsr->bs, len); break; /*privateOpaqueElement*/ case 1: len = lsr_read_vluimsbf5(lsr, "len"); gf_bs_skip_bytes(lsr->bs, len); break; /*element_any*/ case 2: lsr_read_extend_class(lsr, NULL, 0, "reserved"); break; /*attr_custom_extension*/ default: len = lsr_read_vluimsbf5(lsr, "len"); gf_bs_skip_bytes(lsr->bs, len); break; } } static void lsr_read_private_attribute_container(GF_LASeRCodec *lsr) { u32 val; do { u32 skip_len; GF_LSR_READ_INT(lsr, val, 2, "privateDataType"); skip_len = lsr_read_vluimsbf5(lsr, "skipLen"); gf_bs_align(lsr->bs); /*just skip data*/ #if 1 if (skip_len>gf_bs_available(lsr->bs)) { lsr->last_error = GF_NON_COMPLIANT_BITSTREAM; return; } gf_bs_skip_bytes(lsr->bs, skip_len); #else switch (val) { /*private data of type "anyXML"*/ case 0: count = lsr_read_vluimsbf5(lsr, "count"); for (i=0; ibs); byte[skipLen - ((nameSpaceIndexBits+7)%8)] data; break; default: /*TODO - spec is wrong here (typo, "len" instead of "skipLen" )*/ gf_bs_skip_bytes(skipLen); break; } #endif gf_bs_align(lsr->bs); GF_LSR_READ_INT(lsr, val, 1, "hasMorePrivateData"); } while (val); } static void lsr_read_any_attribute(GF_LASeRCodec *lsr, GF_Node *node, Bool skippable) { u32 val = 1; if (skippable) GF_LSR_READ_INT(lsr, val, 1, "has_attrs"); if (val) { do { GF_LSR_READ_INT(lsr, val, lsr->info->cfg.extensionIDBits, "reserved"); val = lsr_read_vluimsbf5(lsr, "len");//len in BITS GF_LSR_READ_INT(lsr, val, val, "reserved_val"); GF_LSR_READ_INT(lsr, val, 1, "hasNextExtension"); } while (val); } } static void lsr_read_object_content(GF_LASeRCodec *lsr, SVG_Element *elt) { u32 val; GF_LSR_READ_INT(lsr, val, 1, "has_private_attr"); if (val) lsr_read_private_attribute_container(lsr); } static void lsr_read_codec_IDREF(GF_LASeRCodec *lsr, XMLRI *href, const char *name) { GF_Node *n; u32 flag; u32 nID = 1+lsr_read_vluimsbf5(lsr, name); GF_LSR_READ_INT(lsr, flag, 1, "reserved"); if (flag) { u32 len = lsr_read_vluimsbf5(lsr, "len"); GF_LSR_READ_INT(lsr, flag, len, "reserved"); } n = gf_sg_find_node(lsr->sg, nID); if (!n) { char NodeID[1024]; sprintf(NodeID, "N%d", nID-1); href->string = strdup(NodeID); if (href->type!=0xFF) gf_list_add(lsr->defered_hrefs, href); href->type = XMLRI_ELEMENTID; return; } href->target = (SVG_Element *)n; href->type = XMLRI_ELEMENTID; gf_svg_register_iri(lsr->sg, href); } static u32 lsr_read_codec_IDREF_command(GF_LASeRCodec *lsr, const char *name) { u32 flag; u32 nID = 1+lsr_read_vluimsbf5(lsr, name); GF_LSR_READ_INT(lsr, flag, 1, "reserved"); if (flag) { u32 len = lsr_read_vluimsbf5(lsr, "len"); GF_LSR_READ_INT(lsr, flag, len, "reserved"); } return nID; } static Fixed lsr_read_fixed_16_8(GF_LASeRCodec *lsr, const char *name) { u32 val; GF_LSR_READ_INT(lsr, val, 24, name); if (val & (1<<23)) { s32 res = val - (1<<24); #ifdef GPAC_FIXED_POINT return res*256; #else return INT2FIX(res) / 256; #endif } else { #ifdef GPAC_FIXED_POINT return val*256; #else return INT2FIX(val) / 256; #endif } } static void lsr_read_fixed_16_8i(GF_LASeRCodec *lsr, SVG_Number *n, const char *name) { s32 val; GF_LSR_READ_INT(lsr, val, 1, name); if (val) { n->type=SVG_NUMBER_INHERIT; } else { n->type=SVG_NUMBER_VALUE; n->value = lsr_read_fixed_16_8(lsr, name); } } static void lsr_get_color(GF_LASeRCodec *lsr, u32 idx, SVG_Color *color) { LSRCol *c; if (idx>=lsr->nb_cols) return; c = &lsr->col_table[idx]; color->red = INT2FIX(c->r) / lsr->color_scale; color->green = INT2FIX(c->g) / lsr->color_scale; color->blue = INT2FIX(c->b) / lsr->color_scale; color->type = SVG_COLOR_RGBCOLOR; } static void lsr_read_line_increment_type(GF_LASeRCodec *lsr, SVG_Number *li, const char *name) { u32 val; GF_LSR_READ_INT(lsr, val, 1, "choice"); if (val==1) { GF_LSR_READ_INT(lsr, val, 1, "type"); if (val==1) li->type=SVG_NUMBER_INHERIT; else li->type=SVG_NUMBER_AUTO; } else { li->value = lsr_read_fixed_16_8(lsr, "line-increment-value"); } } static void lsr_read_byte_align_string(GF_LASeRCodec *lsr, char **str, const char *name) { u32 len; gf_bs_align(lsr->bs); len = lsr_read_vluimsbf8(lsr, "len"); if (str) { if (*str) free(*str); *str = NULL; if (len) { if (len > gf_bs_available(lsr->bs) ) { lsr->last_error = GF_NON_COMPLIANT_BITSTREAM; return; } *str = (char*)malloc(sizeof(char)*(len+1)); gf_bs_read_data(lsr->bs, *str, len); (*str) [len] = 0; } } else { while (len) { gf_bs_read_int(lsr->bs, 8); len--; } } GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] %s\t\t%d\t\t%s\n", name, 8*len, *str)); } static void lsr_read_text_content(GF_LASeRCodec *lsr, GF_Node *elt) { char *str = NULL; lsr_read_byte_align_string(lsr, &str, "textContent"); if (!str) return; gf_dom_add_text_node(elt, str); } static void lsr_read_byte_align_string_list(GF_LASeRCodec *lsr, GF_List *l, const char *name, Bool is_iri) { XMLRI *iri; char *text, *sep, *sep2, *cur; while (gf_list_count(l)) { char *str = (char *)gf_list_last(l); gf_list_rem_last(l); free(str); } text = NULL; lsr_read_byte_align_string(lsr, &text, name); cur = text; while (cur) { sep = strchr(cur, '\''); if (!sep) { if (is_iri) { GF_SAFEALLOC(iri, XMLRI); iri->string = strdup(cur); iri->type = XMLRI_STRING; gf_list_add(l, iri); } else { gf_list_add(l, strdup(cur)); } break; } sep2 = strchr(sep + 1, '\''); if (!sep2) { if (is_iri) { GF_SAFEALLOC(iri, XMLRI); iri->string = strdup(cur); iri->type = XMLRI_STRING; gf_list_add(l, iri); } else { gf_list_add(l, strdup(cur)); } break; } sep2[0] = 0; if (is_iri) { GF_SAFEALLOC(iri, XMLRI); iri->string = strdup(sep+1); iri->type = XMLRI_STRING; gf_list_add(l, iri); } else { gf_list_add(l, strdup(sep+1)); } sep2[0] = '\''; cur = sep2 + 1; } free(text); } static void lsr_read_any_uri(GF_LASeRCodec *lsr, XMLRI *iri, const char *name) { u32 val; GF_LSR_READ_INT(lsr, val, 1, "hasUri"); if (val) { char *s = NULL; iri->type=XMLRI_STRING; if (iri->string) { free(iri->string); iri->string = NULL; } lsr_read_byte_align_string(lsr, &s, "uri"); GF_LSR_READ_INT(lsr, val, 1, "hasData"); if (!val) { iri->string = s; } else { u32 len_rad, len; len = lsr_read_vluimsbf5(lsr, "len"); len_rad = s ? strlen(s) : 0; iri->string = (char*)malloc(sizeof(char)*(len_rad+1+len+1)); iri->string[0] = 0; if (s) { strcpy(iri->string, s); free(s); } strcat(iri->string, ","); gf_bs_read_data(lsr->bs, iri->string + len_rad + 1, len); iri->string[len_rad + 1 + len] = 0; } } GF_LSR_READ_INT(lsr, val, 1, "hasID"); if (val) lsr_read_codec_IDREF(lsr, iri, "idref"); GF_LSR_READ_INT(lsr, val, 1, "hasStreamID"); if (val) { iri->type = XMLRI_STREAMID; iri->lsr_stream_id = lsr_read_vluimsbf5(lsr, name); GF_LSR_READ_INT(lsr, val, 1, "reserved"); if (val) { u32 len = lsr_read_vluimsbf5(lsr, "len"); GF_LSR_READ_INT(lsr, val, len, "reserved"); } } } static void lsr_read_paint(GF_LASeRCodec *lsr, SVG_Paint *paint, const char *name) { u32 val; GF_LSR_READ_INT(lsr, val, 1, "hasIndex"); if (val) { GF_LSR_READ_INT(lsr, val, lsr->colorIndexBits, name); lsr_get_color(lsr, val, &paint->color); paint->type = SVG_PAINT_COLOR; paint->color.type = 0; } else { GF_LSR_READ_INT(lsr, val, 2, "enum"); switch (val) { case 0: GF_LSR_READ_INT(lsr, val, 2, "choice"); switch (val) { case 0: paint->type = SVG_PAINT_INHERIT; break; case 1: paint->type = SVG_PAINT_COLOR; paint->color.type = SVG_COLOR_CURRENTCOLOR; break; default: paint->type = SVG_PAINT_NONE; break; } break; case 1: { XMLRI iri; memset(&iri, 0, sizeof(XMLRI)); iri.type = 0xFF; lsr_read_any_uri(lsr, &iri, name); gf_svg_unregister_iri(lsr->sg, &iri); paint->type = SVG_PAINT_URI; if (iri.string) { paint->type = SVG_PAINT_URI; paint->iri.type = XMLRI_STRING; paint->iri.string = iri.string; } else if (iri.target) { paint->iri.type = XMLRI_ELEMENTID; paint->iri.target = iri.target; } } break; case 2: { char *sysPaint=NULL; lsr_read_byte_align_string(lsr, &sysPaint, "systemsPaint"); if (sysPaint) { paint->type = SVG_PAINT_COLOR; paint->color.type = gf_svg_get_system_paint_server_type(sysPaint); free(sysPaint); } } break; case 3: lsr_read_extension(lsr, name); break; } } } static void lsr_read_string_attribute(GF_LASeRCodec *lsr, GF_Node *elt, u32 tag, char *name) { u32 val; GF_LSR_READ_INT(lsr, val, 1, name); if (val) { GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(elt, tag, 1, 0, &info); lsr_read_byte_align_string(lsr, info.far_ptr, name); } } static void lsr_read_id(GF_LASeRCodec *lsr, GF_Node *n) { GF_FieldInfo info; u32 val, id, i, count; char *name; GF_LSR_READ_INT(lsr, val, 1, "has_id"); if (!val) return; name = NULL; id = 1+lsr_read_vluimsbf5(lsr, "ID"); gf_node_set_id(n, id, name); GF_LSR_READ_INT(lsr, val, 1, "reserved"); /*currently not used*/ if (val) { u32 len = lsr_read_vluimsbf5(lsr, "len"); GF_LSR_READ_INT(lsr, val, len, "reserved"); } /*update all pending HREFs*/ count = gf_list_count(lsr->defered_hrefs); for (i=0; idefered_hrefs, i); char *str_id = href->string; if (str_id[0] == '#') str_id++; /*skip 'N'*/ str_id++; if (id == (1 + (u32) atoi(str_id))) { href->target = (SVG_Element*) n; free(href->string); href->string = NULL; gf_list_rem(lsr->defered_hrefs, i); i--; count--; } } /*update unresolved listeners*/ count = gf_list_count(lsr->defered_listeners); for (i=0; idefered_listeners, i); par = NULL; if (gf_svg_get_attribute_by_tag(listener, TAG_SVG_ATT_observer, 0, 0, &info) == GF_OK) { observer = (XMLRI*)info.far_ptr; if (observer->type == XMLRI_ELEMENTID) { if (!observer->target) continue; else par = observer->target; } } if (gf_svg_get_attribute_by_tag(listener, TAG_SVG_ATT_listener_target, 0, 0, &info) == GF_OK) { if (((XMLRI*)info.far_ptr)->type == XMLRI_ELEMENTID) { if (!((XMLRI*)info.far_ptr)->target) continue; else if (!par) par = ((XMLRI*)info.far_ptr)->target; } } /*FIXME - double check with XML events*/ if (!par && !observer) { if (gf_svg_get_attribute_by_tag(listener, TAG_SVG_ATT_event, 0, 0, &info) == GF_OK) { XMLEV_Event *ev = (XMLEV_Event *)info.far_ptr; /*all non-UI get attched to root*/ if (ev && (ev->type>GF_EVENT_MOUSEWHEEL)) { par = (GF_Node*) lsr->current_root; } } } assert(par); gf_dom_listener_add(par, listener); gf_list_rem(lsr->defered_listeners, i); i--; count--; } /*update all pending animations*/ count = gf_list_count(lsr->defered_anims); for (i=0; idefered_anims, i); if (lsr_setup_smil_anim(lsr, elt, NULL)) { gf_list_rem(lsr->defered_anims, i); i--; count--; gf_node_init((GF_Node*)elt); } } } static Fixed lsr_translate_coords(GF_LASeRCodec *lsr, u32 val, u32 nb_bits) { #ifdef GPAC_FIXED_POINT if (val >> (nb_bits-1) ) { s32 neg = (s32) val - (1<res_factor); return gf_divfix(INT2FIX(neg), lsr->res_factor); } else { if (val > FIX_ONE / 2) return 2 * gf_divfix(INT2FIX(val/2), lsr->res_factor); return gf_divfix(INT2FIX(val), lsr->res_factor); } #else if (val >> (nb_bits-1) ) { s32 neg = (s32) val - (1<res_factor); } else { return gf_divfix(INT2FIX(val), lsr->res_factor); } #endif } static Fixed lsr_translate_scale(GF_LASeRCodec *lsr, u32 val) { if (val >> (lsr->coord_bits-1) ) { s32 v = val - (1<coord_bits); return INT2FIX(v) / 256 ; } else { return INT2FIX(val) / 256; } } static void lsr_read_matrix(GF_LASeRCodec *lsr, SVG_Transform *mx) { u32 flag; gf_mx2d_init(mx->mat); mx->is_ref = 0; GF_LSR_READ_INT(lsr, flag, 1, "isNotMatrix"); if (flag) { GF_LSR_READ_INT(lsr, flag, 1, "isRef"); if (flag) { GF_LSR_READ_INT(lsr, flag, 1, "hasXY"); if (flag) { mx->mat.m[2] = lsr_read_fixed_16_8(lsr, "valueX"); mx->mat.m[5] = lsr_read_fixed_16_8(lsr, "valueY"); } } else { lsr_read_extension(lsr, "ext"); } } else { lsr->coord_bits += lsr->scale_bits; GF_LSR_READ_INT(lsr, flag, 1, "xx_yy_present"); if (flag) { GF_LSR_READ_INT(lsr, flag, lsr->coord_bits, "xx"); mx->mat.m[0] = lsr_translate_scale(lsr, flag); GF_LSR_READ_INT(lsr, flag, lsr->coord_bits, "yy"); mx->mat.m[4] = lsr_translate_scale(lsr, flag); } else { mx->mat.m[0] = mx->mat.m[4] = FIX_ONE; } GF_LSR_READ_INT(lsr, flag, 1, "xy_yx_present"); if (flag) { GF_LSR_READ_INT(lsr, flag, lsr->coord_bits, "xy"); mx->mat.m[1] = lsr_translate_scale(lsr, flag); GF_LSR_READ_INT(lsr, flag, lsr->coord_bits, "yx"); mx->mat.m[3] = lsr_translate_scale(lsr, flag); } lsr->coord_bits -= lsr->scale_bits; GF_LSR_READ_INT(lsr, flag, 1, "xz_yz_present"); if (flag) { GF_LSR_READ_INT(lsr, flag, lsr->coord_bits, "xz"); mx->mat.m[2] = lsr_translate_coords(lsr, flag, lsr->coord_bits); GF_LSR_READ_INT(lsr, flag, lsr->coord_bits, "yz"); mx->mat.m[5] = lsr_translate_coords(lsr, flag, lsr->coord_bits); } } } static Fixed lsr_read_fixed_clamp(GF_LASeRCodec *lsr, const char *name) { s32 val; GF_LSR_READ_INT(lsr, val, 8, name); return INT2FIX(val) / 255; } static void lsr_read_focus(GF_LASeRCodec *lsr, SVG_Focus *foc, const char *name) { u32 flag; if (foc->target.string) { free(foc->target.string); foc->target.string = NULL; } if (foc->target.target) foc->target.target = NULL; gf_svg_unregister_iri(lsr->sg, &foc->target); GF_LSR_READ_INT(lsr, flag, 1, "isEnum"); if (flag) { GF_LSR_READ_INT(lsr, foc->type, 1, "enum"); } else { foc->type = SVG_FOCUS_IRI; lsr_read_codec_IDREF(lsr, &foc->target, "id"); } } static void lsr_restore_base(GF_LASeRCodec *lsr, SVG_Element *elt, SVG_Element *base, Bool reset_fill, Bool reset_stroke) { GF_Err e; GF_FieldInfo f_base, f_clone; SVGAttribute *att; /*clone all propertie from base*/ att = base->attributes; while (att) { Bool is_fill, is_stroke; is_fill = is_stroke = 0; switch (att->tag) { /*for all properties*/ case TAG_SVG_ATT_fill: is_fill = 1; break; case TAG_SVG_ATT_stroke: is_stroke = 1; break; case TAG_SVG_ATT_audio_level: case TAG_SVG_ATT_color: case TAG_SVG_ATT_color_rendering: case TAG_SVG_ATT_display: case TAG_SVG_ATT_display_align: case TAG_SVG_ATT_fill_opacity: case TAG_SVG_ATT_fill_rule: case TAG_SVG_ATT_font_family: case TAG_SVG_ATT_font_size: case TAG_SVG_ATT_font_style: case TAG_SVG_ATT_font_variant: case TAG_SVG_ATT_font_weight: case TAG_SVG_ATT_image_rendering: case TAG_SVG_ATT_line_increment: case TAG_SVG_ATT_opacity: case TAG_SVG_ATT_pointer_events: case TAG_SVG_ATT_shape_rendering: case TAG_SVG_ATT_solid_color: case TAG_SVG_ATT_solid_opacity: case TAG_SVG_ATT_stop_color: case TAG_SVG_ATT_stop_opacity: case TAG_SVG_ATT_stroke_dasharray: case TAG_SVG_ATT_stroke_dashoffset: case TAG_SVG_ATT_stroke_linecap: case TAG_SVG_ATT_stroke_linejoin: case TAG_SVG_ATT_stroke_miterlimit: case TAG_SVG_ATT_stroke_opacity: case TAG_SVG_ATT_stroke_width: case TAG_SVG_ATT_text_align: case TAG_SVG_ATT_text_anchor: case TAG_SVG_ATT_text_rendering: case TAG_SVG_ATT_vector_effect: case TAG_SVG_ATT_viewport_fill: case TAG_SVG_ATT_viewport_fill_opacity: case TAG_SVG_ATT_visibility: /*and xml:_class*/ case TAG_SVG_ATT__class: case TAG_SVG_ATT_externalResourcesRequired: break; /*pathLength for path*/ case TAG_SVG_ATT_pathLength: break; /*rx & ry for rect*/ case TAG_SVG_ATT_rx: case TAG_SVG_ATT_ry: if (base->sgprivate->tag!=TAG_SVG_rect) { att = att->next; continue; } break; /*x & y for use*/ case TAG_SVG_ATT_x: case TAG_SVG_ATT_y: if (base->sgprivate->tag!=TAG_SVG_use) { att = att->next; continue; } break; /*editable & rotate for text*/ case TAG_SVG_ATT_editable: case TAG_SVG_ATT_rotate: if (base->sgprivate->tag!=TAG_SVG_text) { att = att->next; continue; } break; case TAG_SVG_ATT_transform: break; default: att = att->next; continue; } /*clone field*/ e = gf_svg_get_attribute_by_tag((GF_Node*)elt, att->tag, 1, 0, &f_clone); if (e) goto err_exit; f_base.fieldIndex = att->tag; f_base.fieldType = att->data_type; f_base.far_ptr = att->data; e = gf_svg_attributes_copy(&f_clone, &f_base, 0); if (e) goto err_exit; if (is_fill && reset_fill) { SVG_Paint*p = (SVG_Paint*)f_clone.far_ptr; if (p->iri.string) free(p->iri.string); memset(p, 0, sizeof(SVG_Paint)); } if (is_stroke && reset_stroke) { SVG_Paint*p = (SVG_Paint*)f_clone.far_ptr; if (p->iri.string) free(p->iri.string); memset(p, 0, sizeof(SVG_Paint)); } att = att->next; } return; err_exit: lsr->last_error = e; } static u32 lsr_to_dom_key(u32 lsr_k) { switch (lsr_k) { case 0: return GF_KEY_STAR; case 1: return GF_KEY_0; case 2: return GF_KEY_1; case 3: return GF_KEY_2; case 4: return GF_KEY_3; case 5: return GF_KEY_4; case 6: return GF_KEY_5; case 7: return GF_KEY_6; case 8: return GF_KEY_7; case 9: return GF_KEY_8; case 10: return GF_KEY_9; case 12: return GF_KEY_DOWN; case 14: return GF_KEY_LEFT; case 16: return GF_KEY_RIGHT; case 20: return GF_KEY_UP; /*WHAT IS ANY_KEY (11) ??*/ case 13: return GF_KEY_ENTER; case 15: return GF_KEY_ESCAPE; case 17: return GF_KEY_NUMBER; case 18: return GF_KEY_CELL_SOFT1; case 19: return GF_KEY_CELL_SOFT2; default: /*use '*' by default ... */ return 0; } } static void lsr_read_event_type(GF_LASeRCodec *lsr, XMLEV_Event *evtType) { u32 flag; GF_LSR_READ_INT(lsr, flag, 1, "choice"); if (!flag) { char *evtName, *sep; evtName = NULL; lsr_read_byte_align_string(lsr, &evtName, "evtString"); evtType->type = evtType->parameter = 0; if (evtName) { sep = strchr(evtName, '('); if (sep) { char *param; sep[0] = 0; evtType->type = gf_dom_event_type_by_name(evtName); sep[0] = '('; param = sep+1; sep = strchr(evtName, ')'); if (sep) sep[0]=0; if (evtType->type==GF_EVENT_REPEAT) { evtType->parameter = atoi(param); } else { evtType->parameter = gf_dom_get_key_type(param); } } else { evtType->type = gf_dom_event_type_by_name(evtName); } free(evtName); } } else { evtType->parameter = 0; GF_LSR_READ_INT(lsr, flag, 6, "event"); switch (flag) { case LSR_EVT_abort: evtType->type = GF_EVENT_ABORT; break; case LSR_EVT_accessKey: evtType->type = GF_EVENT_KEYDOWN; break; case LSR_EVT_activate: evtType->type = GF_EVENT_ACTIVATE; break; case LSR_EVT_activatedEvent: evtType->type = GF_EVENT_ACTIVATED; break; case LSR_EVT_beginEvent: evtType->type = GF_EVENT_BEGIN_EVENT; break; case LSR_EVT_click: evtType->type = GF_EVENT_CLICK; break; case LSR_EVT_deactivatedEvent: evtType->type = GF_EVENT_DEACTIVATED; break; case LSR_EVT_endEvent: evtType->type = GF_EVENT_END_EVENT; break; case LSR_EVT_error: evtType->type = GF_EVENT_ERROR; break; case LSR_EVT_executionTime: evtType->type = GF_EVENT_EXECUTION_TIME; break; case LSR_EVT_focusin: evtType->type = GF_EVENT_FOCUSIN; break; case LSR_EVT_focusout: evtType->type = GF_EVENT_FOCUSOUT; break; case LSR_EVT_keydown: evtType->type = GF_EVENT_KEYDOWN; break; case LSR_EVT_keyup: evtType->type = GF_EVENT_KEYUP; break; case LSR_EVT_load: evtType->type = GF_EVENT_LOAD; break; case LSR_EVT_longAccessKey: evtType->type = GF_EVENT_LONGKEYPRESS; break; case LSR_EVT_mousedown: evtType->type = GF_EVENT_MOUSEDOWN; break; case LSR_EVT_mousemove: evtType->type = GF_EVENT_MOUSEMOVE; break; case LSR_EVT_mouseout: evtType->type = GF_EVENT_MOUSEOUT; break; case LSR_EVT_mouseover: evtType->type = GF_EVENT_MOUSEOVER; break; case LSR_EVT_mouseup: evtType->type = GF_EVENT_MOUSEUP; break; case LSR_EVT_pause: evtType->type = GF_EVENT_PAUSE; break; case LSR_EVT_pausedEvent: evtType->type = GF_EVENT_PAUSED_EVENT; break; case LSR_EVT_play: evtType->type = GF_EVENT_PLAY; break; case LSR_EVT_repeatEvent: evtType->type = GF_EVENT_REPEAT_EVENT; break; case LSR_EVT_repeatKey: evtType->type = GF_EVENT_REPEAT_KEY; break; case LSR_EVT_resize: evtType->type = GF_EVENT_RESIZE; break; case LSR_EVT_resumedEvent: evtType->type = GF_EVENT_RESUME_EVENT; break; case LSR_EVT_scroll: evtType->type = GF_EVENT_SCROLL; break; case LSR_EVT_shortAccessKey: evtType->type = GF_EVENT_SHORT_ACCESSKEY; break; case LSR_EVT_textinput: evtType->type = GF_EVENT_TEXTINPUT; break; case LSR_EVT_unload: evtType->type = GF_EVENT_UNLOAD; break; case LSR_EVT_zoom: evtType->type = GF_EVENT_ZOOM; break; default: GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[LASeR] Undefined LASeR event %d\n", flag)); break; } switch (flag) { case LSR_EVT_accessKey: case LSR_EVT_longAccessKey: case LSR_EVT_repeatKey: case LSR_EVT_shortAccessKey: evtType->parameter = lsr_read_vluimsbf5(lsr, "keyCode"); evtType->parameter = lsr_to_dom_key(evtType->parameter); break; } } } static SMIL_Time *lsr_read_smil_time(GF_LASeRCodec *lsr, GF_Node *n) { SMIL_Time *t; u32 val; GF_SAFEALLOC(t, SMIL_Time); t->type = GF_SMIL_TIME_CLOCK; GF_LSR_READ_INT(lsr, val, 1, "hasEvent"); if (val) { t->type = GF_SMIL_TIME_EVENT; GF_LSR_READ_INT(lsr, val, 1, "hasIdentifier"); if (val) { XMLRI iri; iri.type = 0xFF; iri.string = NULL; lsr_read_codec_IDREF(lsr, &iri, "idref"); gf_svg_unregister_iri(lsr->sg, &iri); if (iri.string) { t->element_id = iri.string; } else { t->element = (GF_Node *)iri.target; } } lsr_read_event_type(lsr, &t->event); if (t->event.type==GF_EVENT_EXECUTION_TIME) { t->type = GF_SMIL_TIME_CLOCK; t->clock = gf_node_get_scene_time(n); } } GF_LSR_READ_INT(lsr, val, 1, "hasClock"); if (val) { u32 now; GF_LSR_READ_INT(lsr, val, 1, "sign"); now = lsr_read_vluimsbf5(lsr, "value"); t->clock = now; t->clock /= lsr->time_resolution; if (val) t->clock *= -1; } return t; } static void lsr_read_smil_times(GF_LASeRCodec *lsr, GF_Node *n, u32 tag, SMIL_Times *times, const char *name, Bool skipable) { GF_FieldInfo info; SMIL_Time *v; u32 val, i, count; if (skipable) { GF_LSR_READ_INT(lsr, val, 1, name); if (!val) return; } if (!times) { lsr->last_error = gf_svg_get_attribute_by_tag(n, tag, 1, 0, &info); times = (SMIL_Times*)info.far_ptr; } while (gf_list_count(*times)) { v = (SMIL_Time *)gf_list_last(*times); gf_list_rem_last(*times); if (v->element_id) free(v->element_id); free(v); } GF_LSR_READ_INT(lsr, val, 1, "choice"); if (val) { GF_SAFEALLOC(v, SMIL_Time); v->type = GF_SMIL_TIME_INDEFINITE; gf_list_add(*times, v); return; } count = lsr_read_vluimsbf5(lsr, "count"); for (i=0; ilast_error = gf_svg_get_attribute_by_tag(n, tag, 1, 0, &info); if (lsr->last_error) return; smil = (SMIL_Duration *)info.far_ptr; } smil->type = 0; GF_LSR_READ_INT(lsr, val, 1, "choice"); if (val) { GF_LSR_READ_INT(lsr, smil->type, 2, "time"); } else { Bool sign; u32 now; GF_LSR_READ_INT(lsr, sign, 1, "sign"); now = lsr_read_vluimsbf5(lsr, "value"); smil->clock_value = now; smil->clock_value /= lsr->time_resolution; if (sign) smil->clock_value *= -1; smil->type = SMIL_DURATION_DEFINED; } } static void lsr_read_duration(GF_LASeRCodec *lsr, GF_Node *n) { lsr_read_duration_ex(lsr, n, TAG_SVG_ATT_dur, NULL, "dur", 1); } /*TODO Add decent error checking...*/ static void lsr_read_rare_full(GF_LASeRCodec *lsr, GF_Node *n) { GF_FieldInfo info; u32 i, nb_rare, field_rare; s32 field_tag; GF_LSR_READ_INT(lsr, nb_rare, 1, "has_rare"); if (!nb_rare) return; GF_LSR_READ_INT(lsr, nb_rare, 6, "nbOfAttributes"); for (i=0; iinfo->cfg.extensionIDBits, "extensionID"); len = lsr_read_vluimsbf5(lsr, "len"); if (extID==2) { GF_LSR_READ_INT(lsr, len, 2, "nbOfAttributes"); for (j=0; jlast_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_syncMaster, 1, 0, &info); GF_LSR_READ_INT(lsr, *(SVG_Boolean *)info.far_ptr, 1, "syncMaster"); break; case 1: lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_focusHighlight, 1, 0, &info); GF_LSR_READ_INT(lsr, *(SVG_FocusHighlight *)info.far_ptr, 2, "focusHighlight"); break; case 2: lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_initialVisibility, 1, 0, &info); GF_LSR_READ_INT(lsr, *(SVG_InitialVisibility *)info.far_ptr, 2, "initialVisibility"); break; case 3: lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_fullscreen, 1, 0, &info); GF_LSR_READ_INT(lsr, *(SVG_Boolean *)info.far_ptr, 1, "fullscreen"); break; case 4: lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_requiredFonts, 1, 0, &info); lsr_read_byte_align_string(lsr, info.far_ptr, "requiredFonts"); break; } } } else { gf_bs_read_int(lsr->bs, len); } GF_LSR_READ_INT(lsr, extID, 1, "hasNextExtension"); if (!extID) break; } continue; } field_tag = gf_lsr_rare_type_to_attribute(field_rare); if (field_tag==-1) { return; } lsr->last_error = gf_svg_get_attribute_by_tag(n, field_tag, 1, 0, &info); if (!info.far_ptr) lsr->last_error = GF_NOT_SUPPORTED; if (lsr->last_error) return; switch (field_tag) { case TAG_SVG_ATT__class: lsr_read_byte_align_string(lsr, info.far_ptr, "class"); break; /*properties*/ case TAG_SVG_ATT_audio_level: ((SVG_Number*)info.far_ptr)->value = lsr_read_fixed_clamp(lsr, "audio-level"); break; case TAG_SVG_ATT_color: lsr_read_paint(lsr, (SVG_Paint *)info.far_ptr, "color"); break; case TAG_SVG_ATT_color_rendering: GF_LSR_READ_INT(lsr, *(SVG_RenderingHint*)info.far_ptr, 2, "color-rendering"); break; case TAG_SVG_ATT_display: GF_LSR_READ_INT(lsr, *(SVG_Display*)info.far_ptr, 5, "display"); break; case TAG_SVG_ATT_display_align: GF_LSR_READ_INT(lsr, *(SVG_DisplayAlign*)info.far_ptr, 3, "display-align"); break; case TAG_SVG_ATT_fill_opacity: ((SVG_Number*)info.far_ptr)->type = SVG_NUMBER_VALUE; ((SVG_Number*)info.far_ptr)->value = lsr_read_fixed_clamp(lsr, "fill-opacity"); break; case TAG_SVG_ATT_fill_rule: GF_LSR_READ_INT(lsr, *(SVG_FillRule*)info.far_ptr, 2, "fill-rule"); break; case TAG_SVG_ATT_image_rendering: GF_LSR_READ_INT(lsr, *(SVG_RenderingHint*)info.far_ptr, 2, "image-rendering"); break; case TAG_SVG_ATT_line_increment: lsr_read_line_increment_type(lsr, info.far_ptr, "line-increment"); break; case TAG_SVG_ATT_pointer_events: GF_LSR_READ_INT(lsr, *(SVG_PointerEvents*)info.far_ptr, 4, "pointer-events"); break; case TAG_SVG_ATT_shape_rendering: GF_LSR_READ_INT(lsr, *(SVG_RenderingHint*)info.far_ptr, 3, "shape-rendering"); break; case TAG_SVG_ATT_solid_color: lsr_read_paint(lsr, info.far_ptr, "solid-color"); break; case TAG_SVG_ATT_solid_opacity: ((SVG_Number*)info.far_ptr)->type = SVG_NUMBER_VALUE; ((SVG_Number*)info.far_ptr)->value = lsr_read_fixed_clamp(lsr, "solid-opacity"); break; case TAG_SVG_ATT_stop_color: lsr_read_paint(lsr, info.far_ptr, "stop-color"); break; case TAG_SVG_ATT_stop_opacity: ((SVG_Number*)info.far_ptr)->type = SVG_NUMBER_VALUE; ((SVG_Number*)info.far_ptr)->value = lsr_read_fixed_clamp(lsr, "stop-opacity"); break; case TAG_SVG_ATT_stroke_dasharray: { u32 j, flag; SVG_StrokeDashArray *da = (SVG_StrokeDashArray *)info.far_ptr; GF_LSR_READ_INT(lsr, flag, 1, "dashArray"); if (flag) { da->type=SVG_STROKEDASHARRAY_INHERIT; } else { da->type=SVG_STROKEDASHARRAY_ARRAY; da->array.count = lsr_read_vluimsbf5(lsr, "len"); da->array.vals = (Fixed*)malloc(sizeof(Fixed)*da->array.count); for (j=0; jarray.count; j++) { da->array.vals[j] = lsr_read_fixed_16_8(lsr, "dash"); } } } break; case TAG_SVG_ATT_stroke_dashoffset: lsr_read_fixed_16_8i(lsr, info.far_ptr, "dashOffset"); break; case TAG_SVG_ATT_stroke_linecap: GF_LSR_READ_INT(lsr, *(SVG_StrokeLineCap*)info.far_ptr, 2, "stroke-linecap"); break; case TAG_SVG_ATT_stroke_linejoin: GF_LSR_READ_INT(lsr, *(SVG_StrokeLineJoin*)info.far_ptr, 2, "stroke-linejoin"); break; case TAG_SVG_ATT_stroke_miterlimit: lsr_read_fixed_16_8i(lsr, info.far_ptr, "miterLimit"); break; case TAG_SVG_ATT_stroke_opacity: ((SVG_Number*)info.far_ptr)->type = SVG_NUMBER_VALUE; ((SVG_Number*)info.far_ptr)->value = lsr_read_fixed_clamp(lsr, "stroke-opacity"); break; case TAG_SVG_ATT_stroke_width: lsr_read_fixed_16_8i(lsr, info.far_ptr, "strokeWidth"); break; case TAG_SVG_ATT_text_anchor: GF_LSR_READ_INT(lsr, *(SVG_TextAnchor*)info.far_ptr, 2, "text-achor"); break; case TAG_SVG_ATT_text_rendering: GF_LSR_READ_INT(lsr, *(SVG_RenderingHint*)info.far_ptr, 3, "text-rendering"); break; case TAG_SVG_ATT_viewport_fill: lsr_read_paint(lsr, info.far_ptr, "viewport-fill"); break; case TAG_SVG_ATT_viewport_fill_opacity: ((SVG_Number*)info.far_ptr)->type = SVG_NUMBER_VALUE; ((SVG_Number*)info.far_ptr)->value = lsr_read_fixed_clamp(lsr, "viewport-fill-opacity"); break; case TAG_SVG_ATT_vector_effect: GF_LSR_READ_INT(lsr, *(SVG_VectorEffect*)info.far_ptr, 4, "vector-effect"); break; case TAG_SVG_ATT_visibility: GF_LSR_READ_INT(lsr, *(SVG_Visibility*)info.far_ptr, 2, "visibility"); break; case TAG_SVG_ATT_requiredExtensions: lsr_read_byte_align_string_list(lsr, *(GF_List**)info.far_ptr, "requiredExtensions", 1); break; case TAG_SVG_ATT_requiredFormats: lsr_read_byte_align_string_list(lsr, *(GF_List**)info.far_ptr, "requiredFormats", 0); break; case TAG_SVG_ATT_requiredFeatures: { u32 j, fcount = lsr_read_vluimsbf5(lsr, "count"); for (j=0; jstring, "xml:base"); ((XMLRI*)info.far_ptr)->type = XMLRI_STRING; break; case TAG_SVG_ATT_xml_lang: lsr_read_byte_align_string(lsr, info.far_ptr, "xml:lang"); break; case TAG_SVG_ATT_xml_space: GF_LSR_READ_INT(lsr, *(XML_Space*)info.far_ptr, 1, "xml:space"); break; /*focusable*/ case TAG_SVG_ATT_nav_next: lsr_read_focus(lsr, (SVG_Focus*)info.far_ptr, "focusNext"); break; case TAG_SVG_ATT_nav_up: lsr_read_focus(lsr, (SVG_Focus*)info.far_ptr, "focusNorth"); break; case TAG_SVG_ATT_nav_up_left: lsr_read_focus(lsr, (SVG_Focus*)info.far_ptr, "focusNorthEast"); break; case TAG_SVG_ATT_nav_up_right: lsr_read_focus(lsr, (SVG_Focus*)info.far_ptr, "focusNorthWest"); break; case TAG_SVG_ATT_nav_prev: lsr_read_focus(lsr, (SVG_Focus*)info.far_ptr, "focusPrev"); break; case TAG_SVG_ATT_nav_down: lsr_read_focus(lsr, (SVG_Focus*)info.far_ptr, "focusSouth"); break; case TAG_SVG_ATT_nav_down_left: lsr_read_focus(lsr, (SVG_Focus*)info.far_ptr, "focusSouthEast"); break; case TAG_SVG_ATT_nav_down_right: lsr_read_focus(lsr, (SVG_Focus*)info.far_ptr, "focusSouthWest"); break; case TAG_SVG_ATT_nav_left: lsr_read_focus(lsr, (SVG_Focus*)info.far_ptr, "focusEast"); break; case TAG_SVG_ATT_focusable: /*wrong !!*/ GF_LSR_READ_INT(lsr, *(SVG_Focusable*)info.far_ptr, 2, "focusable"); break; case TAG_SVG_ATT_nav_right: lsr_read_focus(lsr, (SVG_Focus*)info.far_ptr, "focusWest"); break; case TAG_SVG_ATT_transform: lsr_read_matrix(lsr, info.far_ptr); break; case TAG_SVG_ATT_text_decoration: /*FIXME ASAP*/ assert(0); break; case TAG_SVG_ATT_font_variant: GF_LSR_READ_INT(lsr, *(SVG_FontVariant*)info.far_ptr, 2, "font-variant"); break; case TAG_SVG_ATT_font_family: { u32 flag; GF_LSR_READ_INT(lsr, flag, 1, "isInherit"); if (flag) { ((SVG_FontFamily*)info.far_ptr)->type = SVG_FONTFAMILY_INHERIT; } else { char *ft; ((SVG_FontFamily*)info.far_ptr)->type = SVG_FONTFAMILY_VALUE; GF_LSR_READ_INT(lsr, flag, lsr->fontIndexBits, "fontIndex"); ft = (char*)gf_list_get(lsr->font_table, flag); if (ft) ((SVG_FontFamily*)info.far_ptr)->value = strdup(ft); } } break; case TAG_SVG_ATT_font_size: lsr_read_fixed_16_8i(lsr, info.far_ptr, "fontSize"); break; case TAG_SVG_ATT_font_style: GF_LSR_READ_INT(lsr, *(SVG_FontStyle*)info.far_ptr, 3, "fontStyle"); break; case TAG_SVG_ATT_font_weight: GF_LSR_READ_INT(lsr, *(SVG_FontWeight*)info.far_ptr, 4, "fontWeight"); break; case TAG_SVG_ATT_xlink_title: lsr_read_byte_align_string(lsr, info.far_ptr, "xlink:title"); break; case TAG_SVG_ATT_xlink_type: /*TODO FIXME*/ GF_LSR_READ_INT(lsr, field_rare, 3, "xlink:type"); break; case TAG_SVG_ATT_xlink_role: lsr_read_any_uri(lsr, info.far_ptr, "xlink:role"); break; case TAG_SVG_ATT_xlink_arcrole: lsr_read_any_uri(lsr, info.far_ptr, "xlink:arcrole"); break; case TAG_SVG_ATT_xlink_actuate: /*TODO FIXME*/ GF_LSR_READ_INT(lsr, field_rare, 2, "xlink:actuate"); break; case TAG_SVG_ATT_xlink_show: /*TODO FIXME*/ GF_LSR_READ_INT(lsr, field_rare, 3, "xlink:show"); break; case TAG_SVG_ATT_end: lsr_read_smil_times(lsr, NULL, 0, info.far_ptr, "end", 0); break; case TAG_SVG_ATT_max: lsr_read_duration_ex(lsr, NULL, 0, info.far_ptr, "min", 0); break; case TAG_SVG_ATT_min: lsr_read_duration_ex(lsr, NULL, 0, info.far_ptr, "min", 0); break; } if (lsr->last_error) break; } } #define lsr_read_rare(_a, _b) lsr_read_rare_full(_a, _b) static void lsr_read_fill(GF_LASeRCodec *lsr, GF_Node *n) { Bool has_fill; GF_LSR_READ_INT(lsr, has_fill, 1, "fill"); if (has_fill) { GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_fill, 1, 0, &info); lsr_read_paint(lsr, info.far_ptr, "fill"); } } static void lsr_read_stroke(GF_LASeRCodec *lsr, GF_Node *n) { Bool has_stroke; GF_LSR_READ_INT(lsr, has_stroke, 1, "has_stroke"); if (has_stroke) { GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_stroke, 1, 0, &info); lsr_read_paint(lsr, info.far_ptr, "stroke"); } } static void lsr_read_href(GF_LASeRCodec *lsr, GF_Node *n) { Bool has_href; GF_LSR_READ_INT(lsr, has_href, 1, "has_href"); if (has_href) { GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_xlink_href, 1, 0, &info); lsr_read_any_uri(lsr, info.far_ptr, "href"); } } static void lsr_read_accumulate(GF_LASeRCodec *lsr, GF_Node *n) { Bool v; GF_LSR_READ_INT(lsr, v, 1, "has_accumulate"); if (v) { GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_accumulate, 1, 0, &info); GF_LSR_READ_INT(lsr, *(SMIL_Accumulate*)info.far_ptr, 1, "accumulate"); } } static void lsr_read_additive(GF_LASeRCodec *lsr, GF_Node *n) { Bool v; GF_LSR_READ_INT(lsr, v, 1, "has_additive"); if (v) { GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_additive, 1, 0, &info); GF_LSR_READ_INT(lsr, *(SMIL_Additive*)info.far_ptr, 1, "additive"); } } static void lsr_read_calc_mode(GF_LASeRCodec *lsr, GF_Node *n) { u32 v; /*SMIL_CALCMODE_LINEAR is default and 0 in our code*/ GF_LSR_READ_INT(lsr, v, 1, "has_calcMode"); if (v) { GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_calcMode, 1, 0, &info); GF_LSR_READ_INT(lsr, *(SMIL_CalcMode*)info.far_ptr, 2, "calcMode"); } } static void lsr_read_attribute_name_ex(GF_LASeRCodec *lsr, GF_Node *n, Bool skippable) { u32 val = 1; if (skippable) { GF_LSR_READ_INT(lsr, val, 1, "hasAttributeName"); if (!val) return; } GF_LSR_READ_INT(lsr, val, 1, "choice"); if (val) { lsr_read_vluimsbf5(lsr, "item[i]"); lsr_read_vluimsbf5(lsr, "item[i]"); return; } else { GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_attributeName, 1, 0, &info); GF_LSR_READ_INT(lsr, val, 8, "attributeType"); /*translate type to attribute tag*/ ((SMIL_AttributeName*)info.far_ptr)->type = gf_lsr_anim_type_to_attribute(val); } } static void lsr_read_attribute_name(GF_LASeRCodec *lsr, GF_Node *n) { lsr_read_attribute_name_ex(lsr, n, 1); } static void lsr_translate_anim_value(SMIL_AnimateValue *val, u32 coded_type) { switch (val->type) { case SVG_StrokeDashArray_datatype: { SVG_StrokeDashArray *da; GF_List *l = (GF_List *)val->value; u32 i; GF_SAFEALLOC(da, SVG_StrokeDashArray); da->array.count = gf_list_count(l); if (!da->array.count) { da->type = SVG_STROKEDASHARRAY_INHERIT; } else { da->type = SVG_STROKEDASHARRAY_ARRAY; da->array.vals = (Fixed *) malloc(sizeof(Fixed)*da->array.count); for (i=0; iarray.count; i++) { Fixed *v = (Fixed *)gf_list_get(l, i); da->array.vals[i] = *v; free(v); } gf_list_del(l); val->value = da; } } break; case SVG_ViewBox_datatype: { SVG_ViewBox *vb; GF_List *l = (GF_List *)val->value; GF_SAFEALLOC(vb, SVG_ViewBox); if (gf_list_count(l)==4) { vb->x = * ((Fixed *)gf_list_get(l, 0)); vb->y = * ((Fixed *)gf_list_get(l, 1)); vb->width = * ((Fixed *)gf_list_get(l, 2)); vb->height = * ((Fixed *)gf_list_get(l, 3)); } while (gf_list_count(l)) { Fixed *v = (Fixed *)gf_list_last(l); free(v); gf_list_rem_last(l); } gf_list_del(l); val->value = vb; } break; case SVG_Coordinates_datatype: { SVG_Coordinates *coords; if (coded_type==1) { GF_List *l = gf_list_new(); /*allocated value is already an SVG number*/ gf_list_add(l, val->value); coords = (SVG_Coordinates*)malloc(sizeof(SVG_Coordinates)); *coords = l; val->value = coords; } else if (coded_type==8) { GF_List *l = (GF_List *)val->value; u32 i, count = gf_list_count(l); for (i=0; itype = SVG_NUMBER_VALUE; c->value = *v; free(v); gf_list_rem(l, i); gf_list_insert(l, c, i); } coords = (SVG_Coordinates*)malloc(sizeof(SVG_Coordinates)); *coords = (GF_List *) val->value; val->value = coords; } } break; case SVG_Motion_datatype: if (coded_type==9) { GF_Matrix2D *mat; SVG_Point *pt = (SVG_Point *)val->value; GF_SAFEALLOC(mat, GF_Matrix2D); gf_mx2d_init(*mat); mat->m[2] = pt->x; mat->m[5] = pt->y; free(pt); val->value = mat; } break; } } static void lsr_translate_anim_values(SMIL_AnimateValues *val, u32 coded_type) { u32 i, count; GF_List *list = val->values; count = gf_list_count(list); for (i=0; itype) { case SVG_StrokeDashArray_datatype: { SVG_StrokeDashArray *da; GF_List *l = (GF_List *)gf_list_get(list, i); u32 j; GF_SAFEALLOC(da, SVG_StrokeDashArray); da->array.count = gf_list_count(l); if (!da->array.count) { da->type = SVG_STROKEDASHARRAY_INHERIT; } else { da->type = SVG_STROKEDASHARRAY_ARRAY; da->array.vals = (Fixed *)malloc(sizeof(Fixed)*da->array.count); for (j=0; jarray.count; j++) { Fixed *v = (Fixed *)gf_list_get(l, j); da->array.vals[j] = *v; free(v); } gf_list_del(l); gf_list_rem(list, i); gf_list_insert(list, da, i); } } break; case SVG_ViewBox_datatype: { SVG_ViewBox *vb; GF_List *l = (GF_List *)gf_list_get(list, i); GF_SAFEALLOC(vb, SVG_ViewBox); if (gf_list_count(l)==4) { vb->x = * ((Fixed *)gf_list_get(l, 0)); vb->y = * ((Fixed *)gf_list_get(l, 1)); vb->width = * ((Fixed *)gf_list_get(l, 2)); vb->height = * ((Fixed *)gf_list_get(l, 3)); } while (gf_list_count(l)) { Fixed *v=(Fixed *)gf_list_last(l); free(v); gf_list_rem_last(l); } gf_list_del(l); gf_list_rem(list, i); gf_list_insert(list, vb, i); } break; case SVG_Coordinates_datatype: { SVG_Coordinates *coords; GF_List *l = (GF_List *)gf_list_get(list, i); u32 j, count2; count2 = gf_list_count(l); for (j=0; jtype = SVG_NUMBER_VALUE; c->value = *v; gf_list_rem(l, j); gf_list_insert(l, c, j); free(v); } coords = (SVG_Coordinates*)malloc(sizeof(SVG_Coordinates)); *coords = l; gf_list_rem(list, i); gf_list_insert(list, coords, i); } break; case SVG_Motion_datatype: if (coded_type==9) { GF_Matrix2D *m = (GF_Matrix2D *)malloc(sizeof(GF_Matrix2D )); GF_Point2D *pt = (GF_Point2D *)gf_list_get(list, i); gf_mx2d_init(*m); m->m[2] = pt->x; m->m[5] = pt->y; gf_list_rem(list, i); gf_list_insert(list, m, i); free(pt); } break; } } } static Bool lsr_init_smil_times(GF_LASeRCodec *lsr, SVG_Element *anim, GF_List *times, SVG_Element *parent) { u32 i, count; count = gf_list_count(times); for (i=0; itype==GF_SMIL_TIME_EVENT) { if (t->element_id) { if (t->element_id[0]=='N') { t->element = gf_sg_find_node(lsr->sg, atoi(t->element_id+1) + 1); } else { t->element = gf_sg_find_node_by_name(lsr->sg, t->element_id); } if (!t->element) return 0; free(t->element_id); t->element_id = NULL; } else if (!t->element) { if (t->event.parameter && (t->event.type==GF_EVENT_KEYDOWN) ) { t->element = lsr->sg->RootNode ? lsr->sg->RootNode : lsr->current_root; } else { t->element = (GF_Node*)parent; } } } } return 1; } static Bool lsr_setup_smil_anim(GF_LASeRCodec *lsr, SVG_Element *anim, SVG_Element *anim_parent) { GF_FieldInfo info; u32 coded_type, not_res; GF_Node *target; Bool is_animateMotion, is_animateTransform; XMLRI *xlink; SMIL_AttributeName *name = NULL; SMIL_AnimateValue *value; /*setup smil events*/ not_res = 0; if (gf_svg_get_attribute_by_tag((GF_Node *)anim, TAG_SVG_ATT_begin, 0, 0, &info)==GF_OK) { if (!lsr_init_smil_times(lsr, anim, *(GF_List**)info.far_ptr, anim_parent)) not_res++; } if (gf_svg_get_attribute_by_tag((GF_Node *)anim, TAG_SVG_ATT_end, 0, 0, &info)==GF_OK) { if (!lsr_init_smil_times(lsr, anim, *(GF_List**)info.far_ptr, anim_parent)) not_res++; } /*get xlink*/ xlink = NULL; if (gf_svg_get_attribute_by_tag((GF_Node *)anim, TAG_SVG_ATT_xlink_href, 0, 0, &info)==GF_OK) { xlink = info.far_ptr; } /*setup target node*/ if (!xlink || !xlink->target) { /*target not received*/ if (xlink && (xlink->type == XMLRI_ELEMENTID)) return 0; if (!xlink) { /*target is parent, initialize xlink (needed by anim module)*/ if (gf_svg_get_attribute_by_tag((GF_Node *)anim, TAG_SVG_ATT_xlink_href, 1, 0, &info)==GF_OK) { xlink = info.far_ptr; } else { return 0; } } xlink->type = XMLRI_ELEMENTID; xlink->target = anim_parent; gf_svg_register_iri(lsr->sg, xlink); target = (GF_Node *)anim_parent; } else { target = (GF_Node *)xlink->target; } if (!target || not_res) return 0; is_animateTransform = is_animateMotion = 0; if (anim->sgprivate->tag==TAG_SVG_animateMotion) is_animateMotion = 1; else if (anim->sgprivate->tag==TAG_SVG_animateTransform) { is_animateTransform = 1; } if (is_animateMotion) goto translate_vals; /*for all except animateMotion, get attributeName*/ if (gf_svg_get_attribute_by_tag((GF_Node *)anim, TAG_SVG_ATT_attributeName, 0, 0, &info)==GF_OK) { name = info.far_ptr; } if (!name) return 0; if (!name->field_ptr) { if (gf_svg_get_attribute_by_tag((GF_Node *)target, name->type, 1, 0, &info)!=GF_OK) return 0; name->field_ptr = info.far_ptr; name->type = info.fieldType; name->tag = info.fieldIndex; } /*browse all anim types and retranslate anim values. This must be done in 2 steps since we may not have received the target node when parsing the animation node*/ translate_vals: /*and setup anim values*/ if (gf_svg_get_attribute_by_tag((GF_Node *)anim, TAG_SVG_ATT_from, 0, 0, &info)==GF_OK) { if (is_animateTransform) { name->type = ((SMIL_AnimateValue*)info.far_ptr)->type; } else { value = info.far_ptr; coded_type = value->type; value->type = is_animateMotion ? SVG_Motion_datatype : name->type; lsr_translate_anim_value(value, coded_type); } } if (gf_svg_get_attribute_by_tag((GF_Node *)anim, TAG_SVG_ATT_by, 0, 0, &info)==GF_OK) { if (is_animateTransform) { name->type = ((SMIL_AnimateValue*)info.far_ptr)->type; } else { value = info.far_ptr; coded_type = value->type; value->type = is_animateMotion ? SVG_Motion_datatype : name->type; lsr_translate_anim_value(value, coded_type); } } if (gf_svg_get_attribute_by_tag((GF_Node *)anim, TAG_SVG_ATT_to, 0, 0, &info)==GF_OK) { if (is_animateTransform) { name->type = ((SMIL_AnimateValue*)info.far_ptr)->type; } else { value = info.far_ptr; coded_type = value->type; value->type = is_animateMotion ? SVG_Motion_datatype : name->type; lsr_translate_anim_value(value, coded_type); } } if (gf_svg_get_attribute_by_tag((GF_Node *)anim, TAG_SVG_ATT_values, 0, 0, &info)==GF_OK) { if (is_animateTransform) { name->type = ((SMIL_AnimateValues*)info.far_ptr)->type; } else { SMIL_AnimateValues *values = info.far_ptr; coded_type = values->type; values->type = is_animateMotion ? SVG_Motion_datatype : name->type; lsr_translate_anim_values(values, coded_type); } } return 1; } static void lsr_read_anim_fill(GF_LASeRCodec *lsr, GF_Node *n) { u32 val; GF_LSR_READ_INT(lsr, val, 1, "has_smil_fill"); if (val) { GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_smil_fill, 1, 0, &info); /*enumeration freeze{0} remove{1}*/ GF_LSR_READ_INT(lsr, val, 1, "smil_fill"); *(SMIL_Fill*)info.far_ptr = val ? SMIL_FILL_REMOVE : SMIL_FILL_FREEZE; } } static void lsr_read_anim_repeatCount(GF_LASeRCodec *lsr, GF_Node *n) { u32 val; GF_LSR_READ_INT(lsr, val, 1, "has_repeatCount"); if (val) { GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_repeatCount, 1, 0, &info); GF_LSR_READ_INT(lsr, val, 1, "repeatCount"); if (val) ((SMIL_RepeatCount*)info.far_ptr)->type = SMIL_REPEATCOUNT_INDEFINITE; else { ((SMIL_RepeatCount*)info.far_ptr)->type = SMIL_REPEATCOUNT_DEFINED; ((SMIL_RepeatCount*)info.far_ptr)->count = lsr_read_fixed_16_8(lsr, "repeatCount"); } } } static void lsr_read_repeat_duration(GF_LASeRCodec *lsr, GF_Node *n) { u32 flag; GF_LSR_READ_INT(lsr, flag, 1, "has_repeatDur"); if (flag) { GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_repeatDur, 1, 0, &info); GF_LSR_READ_INT(lsr, flag, 1, "choice"); if (flag) { ((SMIL_Duration *)info.far_ptr)->type = SMIL_DURATION_INDEFINITE; } else { ((SMIL_Duration *)info.far_ptr)->clock_value = (Double) lsr_read_vluimsbf5(lsr, "value"); ((SMIL_Duration *)info.far_ptr)->clock_value /= lsr->time_resolution; ((SMIL_Duration *)info.far_ptr)->type = SMIL_DURATION_DEFINED; } } } static void lsr_read_anim_restart(GF_LASeRCodec *lsr, GF_Node *n) { u32 val; GF_LSR_READ_INT(lsr, val, 1, "has_restart"); if (val) { GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_restart, 1, 0, &info); /*enumeration always{0} never{1} whenNotActive{2}*/ GF_LSR_READ_INT(lsr, *(SMIL_Restart*)info.far_ptr, 2, "restart"); } } static void *lsr_read_an_anim_value(GF_LASeRCodec *lsr, u32 coded_type, const char *name) { u32 flag; u32 escapeFlag, escape_val = 0; u8 *enum_val; u32 *id_val; char *string; SVG_Number *num; XMLRI *iri; SVG_Point *pt; SVG_Paint *paint; GF_LSR_READ_INT(lsr, escapeFlag, 1, "escapeFlag"); if (escapeFlag) GF_LSR_READ_INT(lsr, escape_val, 2, "escapeEnum"); switch (coded_type) { case 0: string = NULL; lsr_read_byte_align_string(lsr, &string, name); return string; case 1: num = (SVG_Number*)malloc(sizeof(SVG_Number)); if (escapeFlag) { num->type = escape_val; } else { num->type = SVG_NUMBER_VALUE; num->value = lsr_read_fixed_16_8(lsr, name); } return num; case 2: { SVG_PathData *pd = (SVG_PathData *)gf_svg_create_attribute_value(SVG_PathData_datatype); lsr_read_path_type(lsr, NULL, 0, pd, name); return pd; } case 3: { SVG_Points *pts = (SVG_Points *)gf_svg_create_attribute_value(SVG_Points_datatype); lsr_read_point_sequence(lsr, *pts, name); return pts; } case 4: num = (SVG_Number*)malloc(sizeof(SVG_Number)); if (escapeFlag) { num->type = escape_val; } else { num->type = SVG_NUMBER_VALUE; num->value = lsr_read_fixed_clamp(lsr, name); } return num; case 5: GF_SAFEALLOC(paint, SVG_Paint); if (escapeFlag) { paint->type = SVG_PAINT_INHERIT; } else { lsr_read_paint(lsr, paint, name); } return paint; case 6: enum_val = (u8*)malloc(sizeof(u8)); *enum_val = lsr_read_vluimsbf5(lsr, name); return enum_val; /*TODO check this is correct*/ case 7: { GF_List *l = gf_list_new(); u32 i, count; count = lsr_read_vluimsbf5(lsr, "count"); for (i=0; icoord_bits, "valX"); pt->x = lsr_translate_coords(lsr, flag, lsr->coord_bits); GF_LSR_READ_INT(lsr, flag, lsr->coord_bits, "valY"); pt->y = lsr_translate_coords(lsr, flag, lsr->coord_bits); return pt; case 10: id_val = (u32*)malloc(sizeof(u32)); *id_val = lsr_read_vluimsbf5(lsr, name); return id_val; case 11: { SVG_FontFamily *ft; u32 idx; GF_SAFEALLOC(ft, SVG_FontFamily); if (escapeFlag) { ft->type = SVG_FONTFAMILY_INHERIT; } else { idx = lsr_read_vluimsbf5(lsr, name); ft->type = SVG_FONTFAMILY_VALUE; ft->value = (char*)gf_list_get(lsr->font_table, idx); if (ft->value) ft->value = strdup(ft->value); } return ft; } case 12: GF_SAFEALLOC(iri, XMLRI); lsr_read_any_uri(lsr, iri, name); return iri; default: lsr_read_extension(lsr, name); break; } return NULL; } static void lsr_translate_anim_trans_value(SMIL_AnimateValue *val, u32 transform_type) { SVG_Point_Angle *p; Fixed *f; u32 coded_type = val->type; switch(transform_type) { case SVG_TRANSFORM_TRANSLATE: val->type = SVG_Transform_Translate_datatype; break; case SVG_TRANSFORM_SCALE: val->type = SVG_Transform_Scale_datatype; break; case SVG_TRANSFORM_ROTATE: val->type = SVG_Transform_Rotate_datatype; break; case SVG_TRANSFORM_SKEWX: val->type = SVG_Transform_SkewX_datatype; break; case SVG_TRANSFORM_SKEWY: val->type = SVG_Transform_SkewY_datatype; break; case SVG_TRANSFORM_MATRIX: val->type = SVG_Transform_datatype; break; default: GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[LSR Parsing] unknown datatype for animate transform.\n")); return; } if (!val->value) return; switch (transform_type) { case SVG_TRANSFORM_ROTATE: p = (SVG_Point_Angle*)malloc(sizeof(SVG_Point_Angle)); p->x = p->y = 0; if (coded_type==8) { GF_List *l = (GF_List *)val->value; f = (Fixed*)gf_list_get(l, 0); if (f) { p->angle = *f; free(f); } f = (Fixed*)gf_list_get(l, 1); if (f) { p->x = *f; free(f); } f = (Fixed*)gf_list_get(l, 2); if (f) { p->y = *f; free(f); } gf_list_del(l); } else { p->angle = ((SVG_Number *)val->value)->value; free(val->value); } p->angle = gf_muldiv(p->angle, GF_PI, INT2FIX(180) ); val->value = p; break; case SVG_TRANSFORM_SCALE: if (coded_type==8) { SVG_Point *pt; GF_List *l = (GF_List *)val->value; GF_SAFEALLOC(pt , SVG_Point); f = (Fixed*)gf_list_get(l, 0); if (f) { pt->x = *f; free(f); } f = (Fixed*)gf_list_get(l, 1); if (f) { pt->y = *f; free(f); } else pt->y = pt->x; gf_list_del(l); val->value = pt; } break; case SVG_TRANSFORM_SKEWX: case SVG_TRANSFORM_SKEWY: f = (Fixed*)malloc(sizeof(Fixed)); *f = ((SVG_Number *)val->value)->value; free(val->value); val->value = f; break; } } static void lsr_translate_anim_trans_values(SMIL_AnimateValues *val, u32 transform_type) { u32 count, i, coded_type; SVG_Point_Angle *p; SVG_Point *pt; Fixed *f; GF_List *l; coded_type = val->type; switch(transform_type) { case SVG_TRANSFORM_TRANSLATE: val->type = SVG_Transform_Translate_datatype; break; case SVG_TRANSFORM_SCALE: val->type = SVG_Transform_Scale_datatype; break; case SVG_TRANSFORM_ROTATE: val->type = SVG_Transform_Rotate_datatype; break; case SVG_TRANSFORM_SKEWX: val->type = SVG_Transform_SkewX_datatype; break; case SVG_TRANSFORM_SKEWY: val->type = SVG_Transform_SkewY_datatype; break; case SVG_TRANSFORM_MATRIX: val->type = SVG_Transform_datatype; break; default: GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[SVG Parsing] unknown datatype for animate transform.\n")); return; } count = gf_list_count(val->values); if (!count) return; if (transform_type==SVG_TRANSFORM_TRANSLATE) return; for (i=0;ivalues, i); switch (transform_type) { case SVG_TRANSFORM_ROTATE: GF_SAFEALLOC(p, SVG_Point_Angle); if (coded_type==8) { l = (GF_List*)a_val; f = (Fixed*)gf_list_get(l, 0); p->angle = *f; f = (Fixed*)gf_list_get(l, 1); if (f) p->x = *f; f = (Fixed*)gf_list_get(l, 2); if (f) p->y = *f; while (gf_list_count(l)) { f = (Fixed*)gf_list_last(l); gf_list_rem_last(l); free(f); } gf_list_del(l); } else if (coded_type==1) { p->angle = ((SVG_Number *)a_val)->value; free(a_val); } p->angle = gf_muldiv(p->angle, GF_PI, INT2FIX(180) ); gf_list_rem(val->values, i); gf_list_insert(val->values, p, i); break; case SVG_TRANSFORM_SKEWX: case SVG_TRANSFORM_SKEWY: f = (Fixed*)malloc(sizeof(Fixed)); *f = ((SVG_Number *)a_val)->value; free(a_val); gf_list_rem(val->values, i); gf_list_insert(val->values, f, i); break; case SVG_TRANSFORM_SCALE: pt = (SVG_Point*)malloc(sizeof(SVG_Point)); l = (GF_List*)a_val; f = (Fixed*)gf_list_get(l, 0); if (f) pt->x = *f; f = (Fixed*)gf_list_get(l, 1); if (f) pt->y = *f; else pt->y = pt->x; while (gf_list_count(l)) { f = (Fixed*)gf_list_last(l); gf_list_rem_last(l); free(f); } gf_list_del(l); gf_list_rem(val->values, i); gf_list_insert(val->values, pt, i); break; default: GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[LASeR] unknown transform type %d\n", transform_type)); break; } } } static void lsr_read_anim_value_ex(GF_LASeRCodec *lsr, GF_Node *n, u32 tag, const char *name, u32 *tr_type) { u32 val, coded_type; GF_LSR_READ_INT(lsr, val, 1, name); if (val) { GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(n, tag, 1, 0, &info); GF_LSR_READ_INT(lsr, coded_type, 4, "type"); ((SMIL_AnimateValue*)info.far_ptr)->value = lsr_read_an_anim_value(lsr, coded_type, name); ((SMIL_AnimateValue*)info.far_ptr)->type = coded_type; if (tr_type) { lsr_translate_anim_trans_value(info.far_ptr, *tr_type); } } } static void lsr_read_anim_values_ex(GF_LASeRCodec *lsr, GF_Node *n, u32 *tr_type) { u32 flag, i, count = 0; u32 coded_type; GF_FieldInfo info; SMIL_AnimateValues *values; GF_LSR_READ_INT(lsr, flag, 1, "values"); if (!flag) return; lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_values, 1, 0, &info); values = (SMIL_AnimateValues *)info.far_ptr; GF_LSR_READ_INT(lsr, coded_type, 4, "type"); values->type = coded_type; count = lsr_read_vluimsbf5(lsr, "count"); for (i=0; ivalues, att); } if (tr_type) { lsr_translate_anim_trans_values(info.far_ptr, *tr_type); } } #define lsr_read_anim_value(_a, _b, _c, _d) lsr_read_anim_value_ex(_a, _b, _c, _d, NULL) #define lsr_read_anim_values(_a, _b) lsr_read_anim_values_ex(_a, _b, NULL) static Fixed *lsr_read_fraction_12_item(GF_LASeRCodec *lsr) { u32 flag; Fixed *f; GF_SAFEALLOC(f, Fixed); GF_LSR_READ_INT(lsr, flag, 1, "hasShort"); if (flag) { GF_LSR_READ_INT(lsr, flag, 1, "isZero"); if (flag) *f = 0; else *f = FIX_ONE; } else { u32 v; GF_LSR_READ_INT(lsr, v, 12, "val"); *f = INT2FIX(v) / 4096/*(1<<12)*/; } return f; } static void lsr_read_fraction_12(GF_LASeRCodec *lsr, GF_Node *elt, u32 tag, const char *name) { GF_FieldInfo info; u32 i, count; GF_LSR_READ_INT(lsr, count, 1, name); if (!count) return; lsr->last_error = gf_svg_get_attribute_by_tag(elt, tag, 1, 0, &info); count = lsr_read_vluimsbf5(lsr, "name"); for (i=0; ilast_error = gf_svg_get_attribute_by_tag(n, tag, 1, 0, &info); coords = (SVG_Coordinates*)info.far_ptr; } else { while (gf_list_count(*coords)) { Fixed *v = (Fixed *)gf_list_last(*coords); gf_list_rem_last(*coords); free(v); } } count = lsr_read_vluimsbf5(lsr, "count"); for (i=0;ix = lsr_translate_coords(lsr, v, nb_bits); GF_LSR_READ_INT(lsr, v, nb_bits, "y"); pt->y = lsr_translate_coords(lsr, v, nb_bits); } } else { u32 nb_dx, nb_dy, k; Fixed x, y; SVG_Point *pt = (SVG_Point *)malloc(sizeof(SVG_Point)); gf_list_add(pts, pt); GF_LSR_READ_INT(lsr, nb_dx, 5, "bits"); GF_LSR_READ_INT(lsr, k, nb_dx, "x"); x = pt->x = lsr_translate_coords(lsr, k, nb_dx); GF_LSR_READ_INT(lsr, k, nb_dx, "y"); y = pt->y = lsr_translate_coords(lsr, k, nb_dx); GF_LSR_READ_INT(lsr, nb_dx, 5, "bitsx"); GF_LSR_READ_INT(lsr, nb_dy, 5, "bitsy"); for (i=1; ix = x + lsr_translate_coords(lsr, k, nb_dx); x = pt->x; GF_LSR_READ_INT(lsr, k, nb_dy, "dy"); pt->y = y + lsr_translate_coords(lsr, k, nb_dy); y = pt->y; } } } } static void lsr_read_path_type(GF_LASeRCodec *lsr, GF_Node *n, u32 tag, SVG_PathData *path, const char *name) { #if USE_GF_PATH GF_Point2D *pt, *ct1, *ct2, *end; GF_Point2D orig, ct_orig; u32 i, count, cur_pt, type; GF_List *pts = gf_list_new(); lsr_read_point_sequence(lsr, pts, "seq"); if (!path) { GF_FieldInfo info; gf_svg_get_attribute_by_tag(n, tag, 1, 0, &info); path = info.far_ptr; } else { gf_path_reset(path); } /*first MoveTo is skipped in LASeR*/ pt = gf_list_get(pts, 0); if (!pt) { gf_list_del(pts); GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] Empty path found.\n")); return; } ct_orig = orig = *pt; gf_path_add_move_to_vec(path, pt); cur_pt = 1; count = lsr_read_vluimsbf5(lsr, "nbOfTypes"); for (i=0; ilast_error = GF_NON_COMPLIANT_BITSTREAM; exit: while (gf_list_count(pts)) { end = gf_list_get(pts, 0); gf_list_rem(pts, 0); free(end); } gf_list_del(pts); #else u32 i, count, c; u8 *type; lsr_read_point_sequence(lsr, path->points, "seq"); while (gf_list_count(path->commands)) { u8 *v = (u8 *)gf_list_last(path->commands); gf_list_rem_last(path->commands); free(v); } count = lsr_read_vluimsbf5(lsr, "nbOfTypes"); for (i=0; icommands, type); } #endif } static void lsr_read_rotate_type(GF_LASeRCodec *lsr, GF_Node *n) { u32 flag; GF_LSR_READ_INT(lsr, flag, 1, "rotate"); if (flag) { GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_rotate, 1, 0, &info); GF_LSR_READ_INT(lsr, flag, 1, "choice"); if (flag) { GF_LSR_READ_INT(lsr, flag, 1, "rotate"); ((SVG_Number *)info.far_ptr)->type = flag ? SVG_NUMBER_AUTO_REVERSE : SVG_NUMBER_AUTO; } else { ((SVG_Number *)info.far_ptr)->value = lsr_read_fixed_16_8(lsr, "rotate"); ((SVG_Number *)info.far_ptr)->type = SVG_NUMBER_VALUE; } } } static void lsr_read_sync_behavior(GF_LASeRCodec *lsr, GF_Node *n) { u32 flag; GF_LSR_READ_INT(lsr, flag, 1, "syncBehavior"); if (flag) { GF_FieldInfo info; GF_LSR_READ_INT(lsr, flag, 2, "syncBehavior"); lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_syncBehavior, 1, 0, &info); *(SMIL_SyncBehavior*)info.far_ptr = flag + 1; } } static void lsr_read_sync_tolerance(GF_LASeRCodec *lsr, GF_Node *n) { u32 flag; GF_LSR_READ_INT(lsr, flag, 1, "syncTolerance"); if (flag) { GF_FieldInfo info; GF_LSR_READ_INT(lsr, flag, 1, "syncTolerance"); lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_syncTolerance, 1, 0, &info); if (flag) ((SMIL_SyncTolerance *)info.far_ptr)->type = SMIL_SYNCTOLERANCE_DEFAULT; else { u32 v = lsr_read_vluimsbf5(lsr, "value"); ((SMIL_SyncTolerance *)info.far_ptr)->value = INT2FIX(v); ((SMIL_SyncTolerance *)info.far_ptr)->value /= lsr->time_resolution; } } } static void lsr_read_sync_reference(GF_LASeRCodec *lsr, GF_Node *n) { u32 flag; GF_LSR_READ_INT(lsr, flag, 1, "syncReference"); if (flag) { GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_syncReference, 1, 0, &info); lsr_read_any_uri(lsr, info.far_ptr, "syncReference"); } } static void lsr_read_coordinate(GF_LASeRCodec *lsr, SVG_Number *coord, Bool skipable, const char *name) { u32 flag; if (skipable) { GF_LSR_READ_INT(lsr, flag, 1, name); if (!flag) { //coord->type = SVG_NUMBER_UNKNOWN; //coord->value = 0; return; } } coord->type = SVG_NUMBER_VALUE; GF_LSR_READ_INT(lsr, flag, lsr->coord_bits, name); coord->value = lsr_translate_coords(lsr, flag, lsr->coord_bits); } static void lsr_read_coordinate_ptr(GF_LASeRCodec *lsr, GF_Node *n, u32 tag, Bool skipable, const char *name) { u32 flag; GF_FieldInfo info; if (skipable) { GF_LSR_READ_INT(lsr, flag, 1, name); if (!flag) return; } lsr->last_error = gf_svg_get_attribute_by_tag(n, tag, 1, 0, &info); ((SVG_Number*)info.far_ptr)->type = SVG_NUMBER_VALUE; GF_LSR_READ_INT(lsr, flag, lsr->coord_bits, name); ((SVG_Number*)info.far_ptr)->value = lsr_translate_coords(lsr, flag, lsr->coord_bits); } static void lsr_read_coord_list(GF_LASeRCodec *lsr, GF_Node *elt, u32 tag, const char *name) { GF_FieldInfo info; u32 i, count; GF_LSR_READ_INT(lsr, count, 1, name); if (!count) return; count = lsr_read_vluimsbf5(lsr, "nb_coords"); if (!count) return; if (count>1000000) { lsr->last_error = GF_NON_COMPLIANT_BITSTREAM; return; } lsr->last_error = gf_svg_get_attribute_by_tag(elt, tag, 1, 0, &info); for (i=0; icoord_bits, name); f->value = lsr_translate_coords(lsr, res, lsr->coord_bits); gf_list_add(*(SVG_Coordinates*)info.far_ptr, f); } } static void lsr_read_transform_behavior(GF_LASeRCodec *lsr, GF_Node *n) { GF_FieldInfo info; u32 flag; GF_LSR_READ_INT(lsr, flag, 1, "transformBehavior"); if (flag) { lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_transformBehavior, 1, 0, &info); GF_LSR_READ_INT(lsr, *(SVG_TransformBehavior*)info.far_ptr, 4, "transformBehavior"); } } static void lsr_read_content_type(GF_LASeRCodec *lsr, GF_Node *n) { u32 flag; GF_LSR_READ_INT(lsr, flag, 1, "hasType"); if (flag) { GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_type, 1, 0, &info); lsr_read_byte_align_string(lsr, info.far_ptr, "type"); } } static void lsr_read_script_type(GF_LASeRCodec *lsr, GF_Node *n) { u32 flag; GF_LSR_READ_INT(lsr, flag, 1, "hasType"); if (flag) { GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_xlink_type, 1, 0, &info); GF_LSR_READ_INT(lsr, flag, 1, "choice"); if (flag) { GF_LSR_READ_INT(lsr, flag, 1, "script"); switch (flag) { case 0: *(SVG_String*)info.far_ptr = strdup("application/ecmascript"); break; case 1: *(SVG_String*)info.far_ptr = strdup("application/jar-archive"); break; default: break; } } else { lsr_read_byte_align_string(lsr, info.far_ptr, "type"); } } } static void lsr_read_value_with_units(GF_LASeRCodec *lsr, SVG_Number *n, const char *name) { s32 val; GF_LSR_READ_INT(lsr, val, 32, name); #ifdef GPAC_FIXED_POINT n->value = val << 8; #else n->value = INT2FIX(val) / (1<<8); #endif GF_LSR_READ_INT(lsr, val, 3, "units"); switch (val) { case 1: n->type = SVG_NUMBER_IN; break; case 2: n->type = SVG_NUMBER_CM; break; case 3: n->type = SVG_NUMBER_MM; break; case 4: n->type = SVG_NUMBER_PT; break; case 5: n->type = SVG_NUMBER_PC; break; case 6: n->type = SVG_NUMBER_PERCENTAGE; break; default: n->type = SVG_NUMBER_VALUE; break; } } static void lsr_read_clip_time(GF_LASeRCodec *lsr, GF_Node *elt, u32 tag, const char *name) { GF_FieldInfo info; u32 flag; GF_LSR_READ_INT(lsr, flag, 1, name); if (flag) { lsr->last_error = gf_svg_get_attribute_by_tag(elt, tag, 1, 0, &info); GF_LSR_READ_INT(lsr, flag, 1, "isEnum"); if (!flag) { GF_LSR_READ_INT(lsr, flag, 1, "sign"); flag = lsr_read_vluimsbf5(lsr, "val"); *((SVG_Clock *)info.far_ptr) = flag; *((SVG_Clock *)info.far_ptr) /= lsr->time_resolution; } } } static void lsr_read_attribute_type(GF_LASeRCodec *lsr, GF_Node *elt) { GF_FieldInfo info; u32 flag; GF_LSR_READ_INT(lsr, flag, 1, "hasAttributeType"); if (!flag) return; lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_attributeType, 1, 0, &info); GF_LSR_READ_INT(lsr, *(SMIL_AttributeType*)info.far_ptr, 2, "attributeType"); } static void lsr_read_preserve_aspect_ratio(GF_LASeRCodec *lsr, GF_Node *n) { GF_FieldInfo info; u32 flag; SVG_PreserveAspectRatio *par; GF_LSR_READ_INT(lsr, flag, 1, "hasPreserveAspectRatio"); if (!flag) return; lsr->last_error = gf_svg_get_attribute_by_tag(n, TAG_SVG_ATT_preserveAspectRatio, 1, 0, &info); par = (SVG_PreserveAspectRatio *)info.far_ptr; GF_LSR_READ_INT(lsr, flag, 1, "choice (meetOrSlice)"); GF_LSR_READ_INT(lsr, par->defer, 1, "choice (defer)"); GF_LSR_READ_INT(lsr, flag, 4, "alignXandY"); switch (flag) { case 1: par->align = SVG_PRESERVEASPECTRATIO_XMAXYMAX; break; case 2: par->align = SVG_PRESERVEASPECTRATIO_XMAXYMID; break; case 3: par->align = SVG_PRESERVEASPECTRATIO_XMAXYMIN; break; case 4: par->align = SVG_PRESERVEASPECTRATIO_XMIDYMAX; break; case 5: par->align = SVG_PRESERVEASPECTRATIO_XMIDYMID; break; case 6: par->align = SVG_PRESERVEASPECTRATIO_XMIDYMIN; break; case 7: par->align = SVG_PRESERVEASPECTRATIO_XMINYMAX; break; case 8: par->align = SVG_PRESERVEASPECTRATIO_XMINYMID; break; case 9: par->align = SVG_PRESERVEASPECTRATIO_XMINYMIN; break; default: par->align = SVG_PRESERVEASPECTRATIO_NONE; break; } } static void lsr_read_eRR(GF_LASeRCodec *lsr, GF_Node *elt) { u32 err; GF_LSR_READ_INT(lsr, err, 1, "externalResourcesRequired"); if (err) { GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_externalResourcesRequired, 1, 0, &info); *(SVG_Boolean*)info.far_ptr = 1; } } static void lsr_read_lsr_enabled(GF_LASeRCodec *lsr, GF_Node *elt) { u32 err; GF_LSR_READ_INT(lsr, err, 1, "enabled"); if (err) { GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_lsr_enabled, 1, 0, &info); *(SVG_Boolean*)info.far_ptr = 1; } } static GF_Node *lsr_read_a(GF_LASeRCodec *lsr) { Bool flag; GF_Node *elt = (GF_Node*) gf_node_new(lsr->sg, TAG_SVG_a); lsr_read_id(lsr, elt); lsr_read_rare_full(lsr, elt); lsr_read_fill(lsr, elt); lsr_read_stroke(lsr, elt); lsr_read_eRR(lsr, elt); GF_LSR_READ_INT(lsr, flag, 1, "hasTarget"); if (flag) { GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_target, 1, 0, &info); lsr_read_byte_align_string(lsr, info.far_ptr, "target"); } lsr_read_href(lsr, elt); lsr_read_any_attribute(lsr, elt, 1); lsr_read_group_content(lsr, elt, 0); return elt; } static GF_Node *lsr_read_animate(GF_LASeRCodec *lsr, SVG_Element *parent, Bool is_animateColor) { GF_Node *elt = gf_node_new(lsr->sg, is_animateColor ? TAG_SVG_animateColor : TAG_SVG_animate); lsr_read_id(lsr, elt); lsr_read_rare(lsr, elt); lsr_read_attribute_name(lsr, elt); lsr_read_accumulate(lsr, elt); lsr_read_additive(lsr, elt); lsr_read_anim_value(lsr, elt, TAG_SVG_ATT_by, "by"); lsr_read_calc_mode(lsr, elt); lsr_read_anim_value(lsr, elt, TAG_SVG_ATT_from, "from"); lsr_read_fraction_12(lsr, elt, TAG_SVG_ATT_keySplines, "keySplines"); lsr_read_fraction_12(lsr, elt, TAG_SVG_ATT_keyTimes, "keyTimes"); lsr_read_anim_values(lsr, elt); lsr_read_attribute_type(lsr, elt); lsr_read_smil_times(lsr, elt, TAG_SVG_ATT_begin, NULL, "begin", 1); lsr_read_duration(lsr, elt); lsr_read_anim_fill(lsr, elt); lsr_read_anim_repeatCount(lsr, elt); lsr_read_repeat_duration(lsr, elt); lsr_read_anim_restart(lsr, elt); lsr_read_anim_value(lsr, elt, TAG_SVG_ATT_to, "to"); lsr_read_href(lsr, elt); lsr_read_lsr_enabled(lsr, elt); lsr_read_any_attribute(lsr, elt, 1); if (!lsr_setup_smil_anim(lsr, (SVG_Element*)elt, parent)) { gf_list_add(lsr->defered_anims, elt); lsr_read_group_content_post_init(lsr, (SVG_Element*)elt, 1); } else { lsr_read_group_content(lsr, elt, 0); } return elt; } static GF_Node *lsr_read_animateMotion(GF_LASeRCodec *lsr, SVG_Element *parent) { Bool flag; GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_animateMotion); lsr_read_id(lsr, elt); lsr_read_rare(lsr, elt); lsr_read_accumulate(lsr, elt); lsr_read_additive(lsr, elt); lsr_read_anim_value(lsr, elt, TAG_SVG_ATT_by, "by"); lsr_read_calc_mode(lsr, elt); lsr_read_anim_value(lsr, elt, TAG_SVG_ATT_from, "from"); lsr_read_fraction_12(lsr, elt, TAG_SVG_ATT_keySplines, "keySplines"); lsr_read_fraction_12(lsr, elt, TAG_SVG_ATT_keyTimes, "keyTimes"); lsr_read_anim_values(lsr, elt); lsr_read_attribute_type(lsr, elt); lsr_read_smil_times(lsr, elt, TAG_SVG_ATT_begin, NULL, "begin", 1); lsr_read_duration(lsr, elt); lsr_read_anim_fill(lsr, elt); lsr_read_anim_repeatCount(lsr, elt); lsr_read_repeat_duration(lsr, elt); lsr_read_anim_restart(lsr, elt); lsr_read_anim_value(lsr, elt, TAG_SVG_ATT_to, "to"); lsr_read_float_list(lsr, elt, TAG_SVG_ATT_keyPoints, NULL, "keyPoints"); GF_LSR_READ_INT(lsr, flag, 1, "hasPath"); if (flag) lsr_read_path_type(lsr, elt, TAG_SVG_ATT_path, NULL, "path"); lsr_read_rotate_type(lsr, elt); lsr_read_href(lsr, elt); lsr_read_lsr_enabled(lsr, elt); lsr_read_any_attribute(lsr, elt, 1); if (!lsr_setup_smil_anim(lsr, (SVG_Element*)elt, parent)) { gf_list_add(lsr->defered_anims, elt); lsr_read_group_content_post_init(lsr, (SVG_Element*)elt, 1); } else { lsr_read_group_content_post_init(lsr, (SVG_Element*)elt, 0); } return elt; } static GF_Node *lsr_read_animateTransform(GF_LASeRCodec *lsr, SVG_Element *parent) { u32 type; Bool flag; GF_FieldInfo info; GF_Node *elt= gf_node_new(lsr->sg, TAG_SVG_animateTransform); lsr_read_id(lsr, elt); lsr_read_rare(lsr, elt); lsr_read_attribute_name(lsr, elt); /*enumeration rotate{0} scale{1} skewX{2} skewY{3} translate{4}*/ GF_LSR_READ_INT(lsr, flag, 3, "rotscatra"); switch (flag) { case 0: type = SVG_TRANSFORM_ROTATE; break; case 1: type = SVG_TRANSFORM_SCALE; break; case 2: type = SVG_TRANSFORM_SKEWX; break; case 3: type = SVG_TRANSFORM_SKEWY; break; case 4: type = SVG_TRANSFORM_TRANSLATE; break; } if (gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_transform_type, 1, 0, &info)==GF_OK) { *(SVG_TransformType *)info.far_ptr = type; } lsr_read_accumulate(lsr, elt); lsr_read_additive(lsr, elt); lsr_read_anim_value_ex(lsr, elt, TAG_SVG_ATT_by, "by", &type); lsr_read_calc_mode(lsr, elt); lsr_read_anim_value_ex(lsr, elt, TAG_SVG_ATT_from, "from", &type); lsr_read_fraction_12(lsr, elt, TAG_SVG_ATT_keySplines, "keySplines"); lsr_read_fraction_12(lsr, elt, TAG_SVG_ATT_keyTimes, "keyTimes"); lsr_read_anim_values_ex(lsr, elt, &type); lsr_read_attribute_type(lsr, elt); lsr_read_smil_times(lsr, elt, TAG_SVG_ATT_begin, NULL, "begin", 1); lsr_read_duration(lsr, elt); lsr_read_anim_fill(lsr, elt); lsr_read_anim_repeatCount(lsr, elt); lsr_read_repeat_duration(lsr, elt); lsr_read_anim_restart(lsr, elt); lsr_read_anim_value_ex(lsr, elt, TAG_SVG_ATT_to, "to", &type); lsr_read_href(lsr, elt); lsr_read_lsr_enabled(lsr, elt); lsr_read_any_attribute(lsr, elt, 1); if (!lsr_setup_smil_anim(lsr, (SVG_Element*)elt, parent)) { gf_list_add(lsr->defered_anims, elt); lsr_read_group_content_post_init(lsr, (SVG_Element*)elt, 1); } else { lsr_read_group_content(lsr, elt, 0); } return elt; } static GF_Node *lsr_read_audio(GF_LASeRCodec *lsr, SVG_Element *parent) { GF_Node *elt= gf_node_new(lsr->sg, TAG_SVG_audio); lsr_read_id(lsr, elt); lsr_read_rare(lsr, elt); lsr_read_smil_times(lsr, elt, TAG_SVG_ATT_begin, NULL, "begin", 1); lsr_read_duration(lsr, elt); lsr_read_eRR(lsr, elt); lsr_read_anim_repeatCount(lsr, elt); lsr_read_repeat_duration(lsr, elt); lsr_read_anim_restart(lsr, elt); lsr_read_sync_behavior(lsr, elt); lsr_read_sync_tolerance(lsr, elt); lsr_read_content_type(lsr, elt); lsr_read_href(lsr, elt); lsr_read_clip_time(lsr, elt, TAG_SVG_ATT_clipBegin, "clipBegin"); lsr_read_clip_time(lsr, elt, TAG_SVG_ATT_clipEnd, "clipEnd"); lsr_read_sync_reference(lsr, elt); lsr_read_any_attribute(lsr, elt, 1); lsr_read_group_content(lsr, elt, 0); return elt; } static GF_Node *lsr_read_circle(GF_LASeRCodec *lsr) { GF_Node *elt= gf_node_new(lsr->sg, TAG_SVG_circle); lsr_read_id(lsr, elt); lsr_read_rare_full(lsr, elt); lsr_read_fill(lsr, elt); lsr_read_stroke(lsr, elt); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_cx, 1, "cx"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_cy, 1, "cy"); lsr_read_coordinate_ptr(lsr, elt,TAG_SVG_ATT_r, 0, "r"); lsr_read_any_attribute(lsr, elt, 1); lsr_read_group_content(lsr, elt, 0); return elt; } static GF_Node *lsr_read_conditional(GF_LASeRCodec *lsr) { GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_conditional); lsr_read_id(lsr, elt); lsr_read_rare(lsr, elt); lsr_read_smil_times(lsr, elt, TAG_SVG_ATT_begin, NULL, "begin", 1); lsr_read_eRR(lsr, elt); lsr_read_lsr_enabled(lsr, elt); lsr_read_any_attribute(lsr, elt, 1); lsr_read_command_list(lsr, NULL, (SVG_Element*)elt, 0); gf_node_init(elt); return elt; } static GF_Node *lsr_read_cursorManager(GF_LASeRCodec *lsr) { GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_cursorManager); lsr_read_id(lsr, elt); lsr_read_rare(lsr, elt); lsr_read_coordinate_ptr(lsr, elt,TAG_SVG_ATT_x, 1, "x"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_y, 1, "y"); lsr_read_href(lsr, elt); lsr_read_any_attribute(lsr, elt, 1); lsr_read_group_content(lsr, elt, 0); return elt; } static GF_Node *lsr_read_data(GF_LASeRCodec *lsr, u32 node_tag) { GF_Node *elt = gf_node_new(lsr->sg, node_tag); lsr_read_id(lsr, elt); lsr_read_rare(lsr, elt); lsr_read_any_attribute(lsr, elt, 1); lsr_read_group_content(lsr, elt, 0); return elt; } static GF_Node *lsr_read_defs(GF_LASeRCodec *lsr) { GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_defs); lsr_read_id(lsr, elt); lsr_read_rare(lsr, elt); lsr_read_fill(lsr, elt); lsr_read_stroke(lsr, elt); lsr_read_any_attribute(lsr, elt, 1); lsr_read_group_content(lsr, elt, 0); return elt; } static GF_Node *lsr_read_ellipse(GF_LASeRCodec *lsr) { GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_ellipse); lsr_read_id(lsr, elt); lsr_read_rare_full(lsr, elt); lsr_read_fill(lsr, elt); lsr_read_stroke(lsr, elt); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_cx, 1, "cx"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_cy, 1, "cy"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_rx, 0, "rx"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_ry, 0, "ry"); lsr_read_any_attribute(lsr, elt, 1); lsr_read_group_content(lsr, elt, 0); return elt; } static GF_Node *lsr_read_foreignObject(GF_LASeRCodec *lsr) { u32 flag; GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_foreignObject); lsr_read_id(lsr, elt); lsr_read_rare_full(lsr, elt); lsr_read_fill(lsr, elt); lsr_read_stroke(lsr, elt); lsr_read_eRR(lsr, elt); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_height, 0, "height"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_width, 0, "width"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_x, 1, "x"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_y, 1, "y"); lsr_read_any_attribute(lsr, elt, 1); /* TODO bit(1) opt_group; if(opt_group) { vluimsbf5 occ1; for(int t=0;tsg, TAG_SVG_g); if (is_same) { if (lsr->prev_g) { lsr_restore_base(lsr, (SVG_Element*) elt, lsr->prev_g, 0, 0); } else { GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] sameg coded in bitstream but no g defined !\n")); } lsr_read_id(lsr, elt); } else { lsr_read_id(lsr, elt); lsr_read_rare_full(lsr, elt); lsr_read_fill(lsr, elt); lsr_read_stroke(lsr, elt); lsr_read_eRR(lsr, elt); lsr_read_any_attribute(lsr, elt, 1); lsr->prev_g = (SVG_Element*)elt; } lsr_read_group_content(lsr, elt, is_same); return elt; } static void lsr_read_opacity(GF_LASeRCodec *lsr, GF_Node *elt) { u32 flag; GF_FieldInfo info; GF_LSR_READ_INT(lsr, flag, 1, "opacity"); if (flag) { lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_opacity, 1, 0, &info); ((SVG_Number*)info.far_ptr)->type = SVG_NUMBER_VALUE; ((SVG_Number*)info.far_ptr)->value = lsr_read_fixed_clamp(lsr, "opacity"); } } static GF_Node *lsr_read_image(GF_LASeRCodec *lsr) { GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_image); lsr_read_id(lsr, elt); lsr_read_rare_full(lsr, elt); lsr_read_eRR(lsr, elt); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_height, 1, "height"); lsr_read_opacity(lsr, elt); lsr_read_preserve_aspect_ratio(lsr, elt); lsr_read_content_type(lsr, elt); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_width, 1, "width"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_x, 1, "x"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_y, 1, "y"); lsr_read_href(lsr, elt); lsr_read_transform_behavior(lsr, elt); lsr_read_any_attribute(lsr, elt, 1); lsr_read_group_content(lsr, elt, 0); return elt; } static GF_Node *lsr_read_line(GF_LASeRCodec *lsr, Bool is_same) { GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_line); if (is_same) { if (lsr->prev_line) { lsr_restore_base(lsr, (SVG_Element*) elt, (SVG_Element *)lsr->prev_line, 0, 0); } else { GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] sameline coded in bitstream but no line defined !\n")); } lsr_read_id(lsr, elt); } else { lsr_read_id(lsr, elt); lsr_read_rare_full(lsr, elt); lsr_read_fill(lsr, elt); lsr_read_stroke(lsr, elt); } lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_x1, 1, "x1"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_x2, 0, "x2"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_y1, 1, "y1"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_y2, 0, "y2"); if (!is_same) { lsr_read_any_attribute(lsr, elt, 1); lsr->prev_line = (SVG_Element*)elt; } lsr_read_group_content(lsr, elt, is_same); return elt; } static void lsr_read_gradient_units(GF_LASeRCodec *lsr, GF_Node *elt) { u32 flag; GF_FieldInfo info; GF_LSR_READ_INT(lsr, flag, 1, "hasGradientUnits"); if (flag) { lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_gradientUnits, 1, 0, &info); GF_LSR_READ_INT(lsr, *(SVG_GradientUnit*)info.far_ptr, 1, "gradientUnits"); } } static GF_Node *lsr_read_linearGradient(GF_LASeRCodec *lsr) { GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_linearGradient); lsr_read_id(lsr, elt); lsr_read_rare(lsr, elt); lsr_read_fill(lsr, elt); lsr_read_stroke(lsr, elt); lsr_read_gradient_units(lsr, elt); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_x1, 1, "x1"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_x2, 1, "x2"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_y1, 1, "y1"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_y2, 1, "y2"); lsr_read_any_attribute(lsr, elt, 1); lsr_read_group_content(lsr, elt, 0); return elt; } static GF_Node *lsr_read_mpath(GF_LASeRCodec *lsr) { GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_mpath); lsr_read_id(lsr, elt); lsr_read_rare(lsr, elt); lsr_read_href(lsr, elt); lsr_read_any_attribute(lsr, elt, 1); lsr_read_group_content(lsr, elt, 0); return elt; } static GF_Node *lsr_read_path(GF_LASeRCodec *lsr, u32 same_type) { u32 flag; GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_path); if (same_type) { if (lsr->prev_path) { lsr_restore_base(lsr, (SVG_Element*)elt, (SVG_Element *)lsr->prev_path, (same_type==2) ? 1 : 0, 0); } else { GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] samepath coded in bitstream but no path defined !\n")); } lsr_read_id(lsr, elt); if (same_type==2) lsr_read_fill(lsr, elt); lsr_read_path_type(lsr, elt, TAG_SVG_ATT_d, NULL, "d"); } else { lsr_read_id(lsr, elt); lsr_read_rare_full(lsr, elt); lsr_read_fill(lsr, elt); lsr_read_stroke(lsr, elt); lsr_read_path_type(lsr, elt, TAG_SVG_ATT_d, NULL, "d"); GF_LSR_READ_INT(lsr, flag, 1, "hasPathLength"); if (flag) { GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_pathLength, 1, 0, &info); ((SVG_Number*)info.far_ptr)->value = lsr_read_fixed_16_8(lsr, "pathLength"); } lsr_read_any_attribute(lsr, elt, 1); lsr->prev_path = (SVG_Element*)elt; } lsr_read_group_content(lsr, elt, same_type); return elt; } static GF_Node *lsr_read_polygon(GF_LASeRCodec *lsr, Bool is_polyline, u32 same_type) { GF_FieldInfo info; GF_Node *elt = gf_node_new(lsr->sg, is_polyline ? TAG_SVG_polyline : TAG_SVG_polygon); lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_points, 1, 0, &info); if (same_type) { if (lsr->prev_polygon) { lsr_restore_base(lsr, (SVG_Element*)elt, (SVG_Element *)lsr->prev_polygon, (same_type==2) ? 0 : 0, (same_type==3) ? 0 : 0); } else { GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] samepolyXXX coded in bitstream but no polyXXX defined !\n")); } lsr_read_id(lsr, elt); if (same_type==2) lsr_read_fill(lsr, elt); else if (same_type==3) lsr_read_stroke(lsr, elt); lsr_read_point_sequence(lsr, *(GF_List**)info.far_ptr, "points"); } else { lsr_read_id(lsr, elt); lsr_read_rare_full(lsr, elt); lsr_read_fill(lsr, elt); lsr_read_stroke(lsr, elt); lsr_read_point_sequence(lsr, *(GF_List**)info.far_ptr, "points"); lsr_read_any_attribute(lsr, elt, 1); lsr->prev_polygon = (SVG_Element*)elt; } lsr_read_group_content(lsr, elt, same_type); return elt; } static GF_Node *lsr_read_radialGradient(GF_LASeRCodec *lsr) { GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_radialGradient); lsr_read_id(lsr, elt); lsr_read_rare(lsr, elt); lsr_read_fill(lsr, elt); lsr_read_stroke(lsr, elt); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_cx, 1, "cx"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_cy, 1, "cy"); lsr_read_gradient_units(lsr, elt); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_r, 1, "r"); lsr_read_any_attribute(lsr, elt, 1); lsr_read_group_content(lsr, elt, 0); return elt; } static GF_Node *lsr_read_rect(GF_LASeRCodec *lsr, u32 same_type) { GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_rect); if (same_type) { if (lsr->prev_rect) { lsr_restore_base(lsr, (SVG_Element*)elt, (SVG_Element *)lsr->prev_rect, (same_type==2) ? 1 : 0, 0); } else { GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] samerect coded in bitstream but no rect defined !\n")); } lsr_read_id(lsr, elt); if (same_type==2) lsr_read_fill(lsr, elt); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_height, 0, "height"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_width, 0, "width"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_x, 1, "x"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_y, 1, "y"); } else { lsr_read_id(lsr, elt); lsr_read_rare_full(lsr, elt); lsr_read_fill(lsr, elt); lsr_read_stroke(lsr, elt); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_height, 0, "height"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_rx, 1, "rx"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_ry, 1, "ry"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_width, 0, "width"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_x, 1, "x"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_y, 1, "y"); lsr_read_any_attribute(lsr, elt, 1); lsr->prev_rect = (SVG_Element*)elt; } lsr_read_group_content(lsr, elt, same_type); return elt; } static GF_Node *lsr_read_rectClip(GF_LASeRCodec *lsr) { u32 flag; GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_rectClip); lsr_read_id(lsr, elt); lsr_read_rare_full(lsr, elt); lsr_read_fill(lsr, elt); lsr_read_stroke(lsr, elt); lsr_read_eRR(lsr, elt); GF_LSR_READ_INT(lsr, flag, 1, "has_size"); if (flag) { SVG_Number num; GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_size, 1, 0, &info); lsr_read_coordinate(lsr, & num, 0, "width"); ((LASeR_Size*)info.far_ptr)->width = num.value; lsr_read_coordinate(lsr, & num, 0, "height"); ((LASeR_Size*)info.far_ptr)->height = num.value; } lsr_read_any_attribute(lsr, elt, 1); lsr_read_group_content(lsr, elt, 0); return elt; } static GF_Node *lsr_read_script(GF_LASeRCodec *lsr) { GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_script); lsr_read_id(lsr, elt); lsr_read_rare(lsr, elt); lsr_read_eRR(lsr, elt); lsr_read_script_type(lsr, elt); lsr_read_href(lsr, elt); lsr_read_any_attribute(lsr, elt, 1); lsr_read_group_content(lsr, elt, 0); return elt; } static GF_Node *lsr_read_selector(GF_LASeRCodec *lsr) { u32 flag; GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_selector); lsr_read_id(lsr, elt); lsr_read_rare_full(lsr, elt); lsr_read_fill(lsr, elt); lsr_read_stroke(lsr, elt); lsr_read_eRR(lsr, elt); GF_LSR_READ_INT(lsr, flag, 1, "hasChoice"); if (flag) { GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_choice, 1, 0, &info); GF_LSR_READ_INT(lsr, flag, 1, "choice"); if (flag) { GF_LSR_READ_INT(lsr, ((LASeR_Choice*)info.far_ptr)->type, 1, "type"); } else { GF_LSR_READ_INT(lsr, ((LASeR_Choice*)info.far_ptr)->choice_index, 8, "value"); ((LASeR_Choice*)info.far_ptr)->type = LASeR_CHOICE_N; } } lsr_read_any_attribute(lsr, elt, 1); lsr_read_group_content(lsr, elt, 0); return elt; } static GF_Node *lsr_read_set(GF_LASeRCodec *lsr, SVG_Element *parent) { GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_set); lsr_read_id(lsr, elt); lsr_read_rare(lsr, elt); lsr_read_attribute_name(lsr, elt); lsr_read_attribute_type(lsr, elt); lsr_read_smil_times(lsr, elt, TAG_SVG_ATT_begin, NULL, "begin", 1); lsr_read_duration(lsr, elt); lsr_read_anim_fill(lsr, elt); lsr_read_anim_repeatCount(lsr, elt); lsr_read_repeat_duration(lsr, elt); lsr_read_anim_restart(lsr, elt); lsr_read_anim_value(lsr, elt, TAG_SVG_ATT_to, "to"); lsr_read_href(lsr, elt); lsr_read_lsr_enabled(lsr, elt); lsr_read_any_attribute(lsr, elt, 1); if (!lsr_setup_smil_anim(lsr, (SVG_Element*)elt, parent)) { gf_list_add(lsr->defered_anims, elt); lsr_read_group_content_post_init(lsr, (SVG_Element*)elt, 1); } else { lsr_read_group_content(lsr, elt, 0); } return elt; } static GF_Node *lsr_read_simpleLayout(GF_LASeRCodec *lsr) { u32 flag; GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_simpleLayout); lsr_read_id(lsr, elt); lsr_read_rare_full(lsr, elt); lsr_read_fill(lsr, elt); lsr_read_stroke(lsr, elt); GF_LSR_READ_INT(lsr, flag, 1, "has_delta"); if (flag) { SVG_Number num; GF_FieldInfo info; lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_delta, 1, 0, &info); lsr_read_coordinate(lsr, & num, 0, "width"); ((LASeR_Size*)info.far_ptr)->width = num.value; lsr_read_coordinate(lsr, & num, 0, "height"); ((LASeR_Size*)info.far_ptr)->height = num.value; } lsr_read_eRR(lsr, elt); lsr_read_any_attribute(lsr, elt, 1); lsr_read_group_content(lsr, elt, 0); return elt; } static GF_Node *lsr_read_stop(GF_LASeRCodec *lsr) { GF_FieldInfo info; GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_stop); lsr_read_id(lsr, elt); lsr_read_rare(lsr, elt); lsr_read_fill(lsr, elt); lsr_read_stroke(lsr, elt); lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_offset, 1, 0, &info); ((SVG_Number*)info.far_ptr)->value = lsr_read_fixed_16_8(lsr, "offset"); lsr_read_any_attribute(lsr, elt, 1); lsr_read_group_content(lsr, elt, 0); return elt; } static GF_Node *lsr_read_svg(GF_LASeRCodec *lsr) { GF_FieldInfo info; SMIL_Duration snap; u32 flag; GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_svg); lsr_read_id(lsr, elt); lsr_read_rare(lsr, elt); lsr_read_fill(lsr, elt); lsr_read_stroke(lsr, elt); lsr_read_string_attribute(lsr, elt, TAG_SVG_ATT_baseProfile, "baseProfile"); lsr_read_string_attribute(lsr, elt, TAG_SVG_ATT_contentScriptType, "contentScriptType"); lsr_read_eRR(lsr, elt); lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_height, 1, 0, &info); lsr_read_value_with_units(lsr, info.far_ptr, "height"); GF_LSR_READ_INT(lsr, flag, 1, "hasPlaybackOrder"); if (flag) { lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_playbackOrder, 1, 1, &info); GF_LSR_READ_INT(lsr, flag, 1, "playbackOrder"); if (flag) *(SVG_PlaybackOrder*)info.far_ptr = SVG_PLAYBACKORDER_FORWARDONLY; } lsr_read_preserve_aspect_ratio(lsr, elt); GF_LSR_READ_INT(lsr, flag, 1, "has_snapshotTime"); if (flag) { lsr_read_duration_ex(lsr, NULL, 0, &snap, "snapshotTime", 0); lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_snapshotTime, 1, 1, &info); if (snap.type==SMIL_DURATION_DEFINED) *((SVG_Clock *)info.far_ptr) = snap.clock_value; } GF_LSR_READ_INT(lsr, flag, 1, "hasSyncBehavior"); if (flag) { lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_syncBehaviorDefault, 1, 0, &info); GF_LSR_READ_INT(lsr, flag, 2, "syncBehaviorDefault"); switch (flag) { case 0: *((SMIL_SyncBehavior*)info.far_ptr) = SMIL_SYNCBEHAVIOR_CANSLIP; break; case 1: *((SMIL_SyncBehavior*)info.far_ptr) = SMIL_SYNCBEHAVIOR_INDEPENDENT; break; case 3: *((SMIL_SyncBehavior*)info.far_ptr) = SMIL_SYNCBEHAVIOR_LOCKED; break; default: *((SMIL_SyncBehavior*)info.far_ptr) = SMIL_SYNCBEHAVIOR_INHERIT; break; } } GF_LSR_READ_INT(lsr, flag, 1, "hasSyncToleranceDefault"); if (flag) { lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_syncToleranceDefault, 1, 0, &info); ((SMIL_SyncTolerance*)info.far_ptr)->type = SMIL_SYNCTOLERANCE_VALUE; GF_LSR_READ_INT(lsr, flag, 1, "choice"); ((SMIL_SyncTolerance*)info.far_ptr)->value = lsr_read_vluimsbf5(lsr, "value"); ((SMIL_SyncTolerance*)info.far_ptr)->value /= lsr->time_resolution; } GF_LSR_READ_INT(lsr, flag, 1, "hasTimelineBegin"); if (flag) { lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_timelineBegin, 1, 0, &info); GF_LSR_READ_INT(lsr, flag, 1, "timelineBegin"); if (flag) *(SVG_TimelineBegin*)info.far_ptr = SVG_TIMELINEBEGIN_ONLOAD; } lsr_read_string_attribute(lsr, elt, TAG_SVG_ATT_version, "version"); GF_LSR_READ_INT(lsr, flag, 1, "hasViewBox"); if (flag) { lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_viewBox, 1, 0, &info); ((SVG_ViewBox*)info.far_ptr)->x = lsr_read_fixed_16_8(lsr, "viewbox.x"); ((SVG_ViewBox*)info.far_ptr)->y = lsr_read_fixed_16_8(lsr, "viewbox.y"); ((SVG_ViewBox*)info.far_ptr)->width = lsr_read_fixed_16_8(lsr, "viewbox.width"); ((SVG_ViewBox*)info.far_ptr)->height = lsr_read_fixed_16_8(lsr, "viewbox.height"); ((SVG_ViewBox*)info.far_ptr)->is_set = 1; } lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_width, 1, 0, &info); lsr_read_value_with_units(lsr, info.far_ptr, "width"); GF_LSR_READ_INT(lsr, flag, 1, "hasZoomAndPan"); if (flag) { lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_zoomAndPan, 1, 0, &info); GF_LSR_READ_INT(lsr, flag, 1, "zoomAndPan"); *((SVG_ZoomAndPan*)info.far_ptr) = flag ? SVG_ZOOMANDPAN_MAGNIFY : SVG_ZOOMANDPAN_DISABLE; } lsr_read_any_attribute(lsr, elt, 1); /*store current root for listeners with no focus target*/ lsr->current_root = elt; lsr_read_group_content(lsr, elt, 0); return elt; } static GF_Node *lsr_read_switch(GF_LASeRCodec *lsr) { GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_switch); lsr_read_id(lsr, elt); lsr_read_rare_full(lsr, elt); lsr_read_fill(lsr, elt); lsr_read_stroke(lsr, elt); lsr_read_eRR(lsr, elt); lsr_read_any_attribute(lsr, elt, 1); lsr_read_group_content(lsr, elt, 0); return elt; } static GF_Node *lsr_read_text(GF_LASeRCodec *lsr, u32 same_type) { u32 flag; GF_FieldInfo info; GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_text); if (same_type) { if (lsr->prev_text) { lsr_restore_base(lsr, (SVG_Element *)elt, (SVG_Element *)lsr->prev_text, (same_type==2) ? 1 : 0, 0); } else { GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] sametext coded in bitstream but no text defined !\n")); } lsr_read_id(lsr, elt); if (same_type==2) lsr_read_fill(lsr, elt); lsr_read_coord_list(lsr, elt, TAG_SVG_ATT_text_x, "x"); lsr_read_coord_list(lsr, elt, TAG_SVG_ATT_text_y, "y"); } else { lsr_read_id(lsr, elt); lsr_read_rare_full(lsr, elt); lsr_read_fill(lsr, elt); lsr_read_stroke(lsr, elt); GF_LSR_READ_INT(lsr, flag, 1, "editable"); if (flag) { lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_editable, 1, 0, &info); *(SVG_Boolean*)info.far_ptr = flag; } lsr_read_float_list(lsr, elt, TAG_SVG_ATT_text_rotate, NULL, "rotate"); lsr_read_coord_list(lsr, elt, TAG_SVG_ATT_text_x, "x"); lsr_read_coord_list(lsr, elt, TAG_SVG_ATT_text_y, "y"); lsr_read_any_attribute(lsr, elt, 1); lsr->prev_text = (SVG_Element*)elt; } lsr_read_group_content(lsr, elt, same_type); return elt; } static GF_Node *lsr_read_tspan(GF_LASeRCodec *lsr) { GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_tspan); lsr_read_id(lsr, elt); lsr_read_rare(lsr, elt); lsr_read_fill(lsr, elt); lsr_read_stroke(lsr, elt); lsr_read_any_attribute(lsr, elt, 1); lsr_read_group_content(lsr, elt, 0); return elt; } static GF_Node *lsr_read_use(GF_LASeRCodec *lsr, Bool is_same) { GF_FieldInfo info; u32 flag; GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_use); if (is_same) { if (lsr->prev_use) { lsr_restore_base(lsr, (SVG_Element *)elt, lsr->prev_use, 0, 0); } else { GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] sameuse coded in bitstream but no use defined !\n")); } lsr_read_id(lsr, elt); lsr_read_href(lsr, elt); } else { lsr_read_id(lsr, elt); lsr_read_rare_full(lsr, elt); lsr_read_fill(lsr, elt); lsr_read_stroke(lsr, elt); lsr_read_eRR(lsr, elt); GF_LSR_READ_INT(lsr, flag, 1, "hasOverflow"); if (flag) { lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_overflow, 1, 0, &info); GF_LSR_READ_INT(lsr, *(SVG_Overflow*)info.far_ptr, 2, "overflow"); } lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_x, 1, "x"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_y, 1, "y"); lsr_read_href(lsr, elt); lsr_read_any_attribute(lsr, elt, 1); lsr->prev_use = (SVG_Element*)elt; } lsr_read_group_content(lsr, elt, is_same); return elt; } static GF_Node *lsr_read_video(GF_LASeRCodec *lsr, SVG_Element *parent) { GF_FieldInfo info; u32 flag; GF_Node*elt = gf_node_new(lsr->sg, TAG_SVG_video); lsr_read_id(lsr, elt); lsr_read_rare_full(lsr, elt); lsr_read_smil_times(lsr, elt, TAG_SVG_ATT_begin, NULL, "begin", 1); lsr_read_duration(lsr, elt); lsr_read_eRR(lsr, elt); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_height, 1, "height"); GF_LSR_READ_INT(lsr, flag, 1, "hasOverlay"); if (flag) { lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_overlay, 1, 1, &info); GF_LSR_READ_INT(lsr, flag, 1, "choice"); if (flag) { GF_LSR_READ_INT(lsr, *(SVG_Overlay*)info.far_ptr, 1, "choice"); } else { char *str = NULL; lsr_read_byte_align_string(lsr, & str, "overlayExt"); if (str) free(str); } } lsr_read_preserve_aspect_ratio(lsr, elt); lsr_read_anim_repeatCount(lsr, elt); lsr_read_repeat_duration(lsr, elt); lsr_read_anim_restart(lsr, elt); lsr_read_sync_behavior(lsr, elt); lsr_read_sync_tolerance(lsr, elt); lsr_read_transform_behavior(lsr, elt); lsr_read_content_type(lsr, elt); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_width, 1, "width"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_x, 1, "x"); lsr_read_coordinate_ptr(lsr, elt, TAG_SVG_ATT_y, 1, "y"); lsr_read_href(lsr, elt); lsr_read_clip_time(lsr, elt, TAG_SVG_ATT_clipBegin, "clipBegin"); lsr_read_clip_time(lsr, elt, TAG_SVG_ATT_clipEnd, "clipEnd"); lsr_read_sync_reference(lsr, elt); lsr_read_any_attribute(lsr, elt, 1); lsr_read_group_content(lsr, elt, 0); return elt; } static GF_Node *lsr_read_listener(GF_LASeRCodec *lsr, SVG_Element *parent) { u32 flag; GF_FieldInfo info; XMLEV_Event *ev = NULL; XMLRI *observer, *target, *handler; GF_Node *elt = gf_node_new(lsr->sg, TAG_SVG_listener); observer = target = handler = NULL; lsr_read_id(lsr, elt); lsr_read_rare(lsr, elt); GF_LSR_READ_INT(lsr, flag, 1, "hasDefaultAction"); if (flag) { lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_defaultAction, 1, 0, &info); GF_LSR_READ_INT(lsr, *(XMLEV_DefaultAction*)info.far_ptr, 1, "defaultAction"); } GF_LSR_READ_INT(lsr, flag, 1, "hasEvent"); if (flag) { lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_event, 1, 0, &info); lsr_read_event_type(lsr, info.far_ptr); ev = info.far_ptr; } /*create default handler but UNINITIALIZED*/ lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_handler, 1, 0, &info); handler = info.far_ptr; GF_LSR_READ_INT(lsr, flag, 1, "hasHandler"); if (flag) { lsr_read_any_uri(lsr, info.far_ptr, "handler"); } GF_LSR_READ_INT(lsr, flag, 1, "hasObserver"); /*TODO double check spec here*/ if (flag) { lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_observer, 1, 0, &info); lsr_read_codec_IDREF(lsr, info.far_ptr, "observer"); observer = info.far_ptr; } GF_LSR_READ_INT(lsr, flag, 1, "hasPhase"); if (flag) { lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_phase, 1, 0, &info); GF_LSR_READ_INT(lsr, *(XMLEV_Phase*)info.far_ptr, 1, "phase"); } GF_LSR_READ_INT(lsr, flag, 1, "hasPropagate"); if (flag) { lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_propagate, 1, 0, &info); GF_LSR_READ_INT(lsr, *(XMLEV_Propagate*)info.far_ptr, 1, "propagate"); } GF_LSR_READ_INT(lsr, flag, 1, "hasTarget"); if (flag) { lsr->last_error = gf_svg_get_attribute_by_tag(elt, TAG_SVG_ATT_listener_target, 1, 0, &info); lsr_read_codec_IDREF(lsr, info.far_ptr, "target"); target = info.far_ptr; } lsr_read_lsr_enabled(lsr, elt); lsr_read_any_attribute(lsr, elt, 1); lsr_read_group_content(lsr, elt, 0); /*register listener element*/ { Bool post_pone = 0; SVG_Element *par = NULL; if (observer && observer->type == XMLRI_ELEMENTID) { if (observer->target) par = observer->target; } if (!par && target && (target->type == XMLRI_ELEMENTID)) { if (!target->target) post_pone = 1; else par = target->target; } if (!handler->target) { handler->type = XMLRI_ELEMENTID; handler->target = parent; } /*FIXME - double check with XML events*/ if (!par && !observer) { /*all non-UI get attched to root*/ if (ev && (ev->type>GF_EVENT_MOUSEWHEEL)) { par = (SVG_Element*) lsr->current_root; } else if (parent) par = parent; else par = (SVG_Element*) lsr->current_root; } if (!par) post_pone = 1; if (post_pone) { gf_list_add(lsr->defered_listeners, elt); } else { if (!par) par = parent; gf_dom_listener_add((GF_Node *)par, elt); } } return elt; } static GF_Node *lsr_read_scene_content_model(GF_LASeRCodec *lsr, SVG_Element *parent) { GF_Node *n; u32 ntype; GF_LSR_READ_INT(lsr, ntype, 6, "ch4"); n = NULL; switch (ntype) { case LSR_SCENE_CONTENT_MODEL_a: n = lsr_read_a(lsr); break; case LSR_SCENE_CONTENT_MODEL_animate: n = lsr_read_animate(lsr, parent, 0); break; case LSR_SCENE_CONTENT_MODEL_animateColor: n = lsr_read_animate(lsr, parent, 1); break; case LSR_SCENE_CONTENT_MODEL_animateMotion: n = lsr_read_animateMotion(lsr, parent); break; case LSR_SCENE_CONTENT_MODEL_animateTransform: n = lsr_read_animateTransform(lsr, parent); break; case LSR_SCENE_CONTENT_MODEL_audio: n = lsr_read_audio(lsr, parent); break; case LSR_SCENE_CONTENT_MODEL_circle: n = lsr_read_circle(lsr); break; case LSR_SCENE_CONTENT_MODEL_conditional: n = lsr_read_conditional(lsr); break; case LSR_SCENE_CONTENT_MODEL_cursorManager: n = lsr_read_cursorManager(lsr); break; case LSR_SCENE_CONTENT_MODEL_defs: n = lsr_read_defs(lsr); break; case LSR_SCENE_CONTENT_MODEL_desc: n = lsr_read_data(lsr, TAG_SVG_desc); break; case LSR_SCENE_CONTENT_MODEL_ellipse: n = lsr_read_ellipse(lsr); break; case LSR_SCENE_CONTENT_MODEL_foreignObject: n = lsr_read_foreignObject(lsr); break; case LSR_SCENE_CONTENT_MODEL_g: n = lsr_read_g(lsr, 0); break; case LSR_SCENE_CONTENT_MODEL_image: n = lsr_read_image(lsr); break; case LSR_SCENE_CONTENT_MODEL_line: n = lsr_read_line(lsr, 0); break; case LSR_SCENE_CONTENT_MODEL_linearGradient: n = lsr_read_linearGradient(lsr); break; case LSR_SCENE_CONTENT_MODEL_metadata: n = lsr_read_data(lsr, TAG_SVG_metadata); break; case LSR_SCENE_CONTENT_MODEL_mpath: n = lsr_read_mpath(lsr); break; case LSR_SCENE_CONTENT_MODEL_path: n = lsr_read_path(lsr, 0); break; case LSR_SCENE_CONTENT_MODEL_polygon: n = lsr_read_polygon(lsr, 0, 0); break; case LSR_SCENE_CONTENT_MODEL_polyline: n = lsr_read_polygon(lsr, 1, 0); break; case LSR_SCENE_CONTENT_MODEL_radialGradient: n = lsr_read_radialGradient(lsr); break; case LSR_SCENE_CONTENT_MODEL_rect: n = lsr_read_rect(lsr, 0); break; case LSR_SCENE_CONTENT_MODEL_rectClip: n = lsr_read_rectClip(lsr); break; case LSR_SCENE_CONTENT_MODEL_sameg: n = lsr_read_g(lsr, 1); break; case LSR_SCENE_CONTENT_MODEL_sameline: n = lsr_read_line(lsr, 1); break; case LSR_SCENE_CONTENT_MODEL_samepath: n = lsr_read_path(lsr, 1); break; case LSR_SCENE_CONTENT_MODEL_samepathfill: n = lsr_read_path(lsr, 2); break; case LSR_SCENE_CONTENT_MODEL_samepolygon: n = lsr_read_polygon(lsr, 0, 1); break; case LSR_SCENE_CONTENT_MODEL_samepolygonfill: n = lsr_read_polygon(lsr, 0, 2); break; case LSR_SCENE_CONTENT_MODEL_samepolygonstroke: n = lsr_read_polygon(lsr, 0, 3); break; case LSR_SCENE_CONTENT_MODEL_samepolyline: n = lsr_read_polygon(lsr, 1, 1); break; case LSR_SCENE_CONTENT_MODEL_samepolylinefill: n = lsr_read_polygon(lsr, 1, 2); break; case LSR_SCENE_CONTENT_MODEL_samepolylinestroke: n = lsr_read_polygon(lsr, 1, 3); break; case LSR_SCENE_CONTENT_MODEL_samerect: n = lsr_read_rect(lsr, 1); break; case LSR_SCENE_CONTENT_MODEL_samerectfill: n = lsr_read_rect(lsr, 2); break; case LSR_SCENE_CONTENT_MODEL_sametext: n = lsr_read_text(lsr, 1); break; case LSR_SCENE_CONTENT_MODEL_sametextfill: n = lsr_read_text(lsr, 2); break; case LSR_SCENE_CONTENT_MODEL_sameuse: n = lsr_read_use(lsr, 1); break; case LSR_SCENE_CONTENT_MODEL_script: n = lsr_read_script(lsr); break; case LSR_SCENE_CONTENT_MODEL_selector: n = lsr_read_selector(lsr); break; case LSR_SCENE_CONTENT_MODEL_set: n = lsr_read_set(lsr, parent); break; case LSR_SCENE_CONTENT_MODEL_simpleLayout: n = lsr_read_simpleLayout(lsr); break; case LSR_SCENE_CONTENT_MODEL_stop: n = lsr_read_stop(lsr); break; case LSR_SCENE_CONTENT_MODEL_switch: n = lsr_read_switch(lsr); break; case LSR_SCENE_CONTENT_MODEL_text: n = lsr_read_text(lsr, 0); break; case LSR_SCENE_CONTENT_MODEL_title: n = lsr_read_data(lsr, TAG_SVG_title); break; case LSR_SCENE_CONTENT_MODEL_tspan: n = lsr_read_tspan(lsr); break; case LSR_SCENE_CONTENT_MODEL_use: n = lsr_read_use(lsr, 0); break; case LSR_SCENE_CONTENT_MODEL_video: n = lsr_read_video(lsr, parent); break; case LSR_SCENE_CONTENT_MODEL_listener: n = lsr_read_listener(lsr, parent); break; case LSR_SCENE_CONTENT_MODEL_element_any: lsr_read_extend_class(lsr, NULL, 0, "node"); break; case LSR_SCENE_CONTENT_MODEL_privateContainer: lsr_read_private_element_container(lsr); break; case LSR_SCENE_CONTENT_MODEL_textContent: lsr_read_text_content(lsr, (GF_Node*)parent); break; default: break; } if (n) { GF_DOM_Event evt; memset(&evt, 0, sizeof(GF_DOM_Event)); evt.type = GF_EVENT_LOAD; gf_dom_event_fire(n, NULL, &evt); } return n; } static GF_Node *lsr_read_update_content_model(GF_LASeRCodec *lsr, SVG_Element *parent) { u32 flag; GF_Node *n=NULL; GF_LSR_READ_INT(lsr, flag, 1, "ch4"); if (flag) { GF_LSR_READ_INT(lsr, flag, 3, "ch61"); switch (flag) { case LSR_UPDATE_CONTENT_MODEL2_conditional: n = lsr_read_conditional(lsr); break; case LSR_UPDATE_CONTENT_MODEL2_cursorManager: n = lsr_read_cursorManager(lsr); break; case LSR_UPDATE_CONTENT_MODEL2_extend: lsr_read_extend_class(lsr, NULL, 0, "extend"); return NULL; case LSR_UPDATE_CONTENT_MODEL2_private: lsr_read_private_element_container(lsr); return NULL; case LSR_UPDATE_CONTENT_MODEL2_rectClip: n = lsr_read_rectClip(lsr); break; case LSR_UPDATE_CONTENT_MODEL2_simpleLayout: n = lsr_read_simpleLayout(lsr); break; case LSR_UPDATE_CONTENT_MODEL2_selector: n = lsr_read_selector(lsr); break; } } else { GF_LSR_READ_INT(lsr, flag, 6, "ch6"); switch(flag) { case LSR_UPDATE_CONTENT_MODEL_a: n = lsr_read_a(lsr); break; case LSR_UPDATE_CONTENT_MODEL_animate: n = lsr_read_animate(lsr, parent, 0); break; case LSR_UPDATE_CONTENT_MODEL_animateColor: n = lsr_read_animate(lsr, parent, 1); break; case LSR_UPDATE_CONTENT_MODEL_animateMotion: n = lsr_read_animateMotion(lsr, parent); break; case LSR_UPDATE_CONTENT_MODEL_animateTransform: n = lsr_read_animateTransform(lsr, parent); break; case LSR_UPDATE_CONTENT_MODEL_audio: n = lsr_read_audio(lsr, parent); break; case LSR_UPDATE_CONTENT_MODEL_circle: n = lsr_read_circle(lsr); break; case LSR_UPDATE_CONTENT_MODEL_defs: n = lsr_read_defs(lsr); break; case LSR_UPDATE_CONTENT_MODEL_desc: n = lsr_read_data(lsr, TAG_SVG_desc); break; case LSR_UPDATE_CONTENT_MODEL_ellipse: n = lsr_read_ellipse(lsr); break; case LSR_UPDATE_CONTENT_MODEL_foreignObject: n = lsr_read_foreignObject(lsr); break; case LSR_UPDATE_CONTENT_MODEL_g: n = lsr_read_g(lsr, 0); break; case LSR_UPDATE_CONTENT_MODEL_image: n = lsr_read_image(lsr); break; case LSR_UPDATE_CONTENT_MODEL_line: n = lsr_read_line(lsr, 0); break; case LSR_UPDATE_CONTENT_MODEL_linearGradient: n = lsr_read_linearGradient(lsr); break; case LSR_UPDATE_CONTENT_MODEL_metadata: n = lsr_read_data(lsr, TAG_SVG_metadata); break; case LSR_UPDATE_CONTENT_MODEL_mpath: n = lsr_read_mpath(lsr); break; case LSR_UPDATE_CONTENT_MODEL_path: n = lsr_read_path(lsr, 0); break; case LSR_UPDATE_CONTENT_MODEL_polygon: n = lsr_read_polygon(lsr, 0, 0); break; case LSR_UPDATE_CONTENT_MODEL_polyline: n = lsr_read_polygon(lsr, 1, 0); break; case LSR_UPDATE_CONTENT_MODEL_radialGradient: n = lsr_read_radialGradient(lsr); break; case LSR_UPDATE_CONTENT_MODEL_rect: n = lsr_read_rect(lsr, 0); break; case LSR_UPDATE_CONTENT_MODEL_script: n = lsr_read_script(lsr); break; case LSR_UPDATE_CONTENT_MODEL_set: n = lsr_read_set(lsr, parent); break; case LSR_UPDATE_CONTENT_MODEL_stop: n = lsr_read_stop(lsr); break; case LSR_UPDATE_CONTENT_MODEL_svg: n = lsr_read_svg(lsr); break; case LSR_UPDATE_CONTENT_MODEL_switch: n = lsr_read_switch(lsr); break; case LSR_UPDATE_CONTENT_MODEL_text: n = lsr_read_text(lsr, 0); break; case LSR_UPDATE_CONTENT_MODEL_title: n = lsr_read_data(lsr, TAG_SVG_title); break; case LSR_UPDATE_CONTENT_MODEL_tspan: n = lsr_read_tspan(lsr); break; case LSR_UPDATE_CONTENT_MODEL_use: n = lsr_read_use(lsr, 0); break; case LSR_UPDATE_CONTENT_MODEL_video: n = lsr_read_video(lsr, parent); break; case LSR_UPDATE_CONTENT_MODEL_listener: n = lsr_read_listener(lsr, parent); break; } } if (n) { GF_DOM_Event evt; memset(&evt, 0, sizeof(GF_DOM_Event)); evt.type = GF_EVENT_LOAD; gf_dom_event_fire(n, NULL, &evt); } return n; } static void lsr_read_group_content(GF_LASeRCodec *lsr, GF_Node *elt, Bool skip_object_content) { u32 i, count; if (lsr->last_error) return; if (!skip_object_content) lsr_read_object_content(lsr, (SVG_Element*)elt); /*node attributes are all parsed*/ gf_node_init(elt); GF_LSR_READ_INT(lsr, count, 1, "opt_group"); if (count) { GF_ChildNodeItem *last = NULL; count = lsr_read_vluimsbf5(lsr, "occ0"); for (i=0; ilast_error) break; n = lsr_read_scene_content_model(lsr, (SVG_Element*)elt); if (n) { gf_node_register(n, elt); gf_node_list_add_child_last(& ((SVG_Element*)elt)->children, n, &last); GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] ############## end %s ###########\n", gf_node_get_class_name(n))); } else { /*either error or text content*/ } } } } static void lsr_read_group_content_post_init(GF_LASeRCodec *lsr, SVG_Element *elt, Bool skip_init) { u32 i, count; if (lsr->last_error) return; lsr_read_object_content(lsr, elt); GF_LSR_READ_INT(lsr, count, 1, "opt_group"); if (count) { GF_ChildNodeItem *last = NULL; count = lsr_read_vluimsbf5(lsr, "occ0"); for (i=0; ilast_error) return; n = lsr_read_scene_content_model(lsr, elt); if (n) { gf_node_register(n, (GF_Node*)elt); gf_node_list_add_child_last(&elt->children, n, &last); GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] ############## end %s ###########\n", gf_node_get_class_name(n))); } else { /*either error or text content*/ } } } if (!skip_init) gf_node_init((GF_Node*)elt); } static void *lsr_read_update_value_indexed(GF_LASeRCodec *lsr, GF_Node*node, u32 fieldType, void *rep_val, u32 idx, Bool is_insert, Bool is_com) { Fixed *f_val; SVG_Point *pt; SVG_Number num; switch (fieldType) { case SVG_Points_datatype/*ITYPE_point*/: pt = (SVG_Point*)malloc(sizeof(SVG_Point)); lsr_read_coordinate(lsr, &num, 0, "coordX"); pt->x = num.value; lsr_read_coordinate(lsr, &num, 0, "coordY"); pt->y = num.value; return pt; case SMIL_KeySplines_datatype/*ITYPE_float*/: case SVG_StrokeDashArray_datatype: case SVG_ViewBox_datatype: f_val = (Fixed*)malloc(sizeof(u8)); *f_val = lsr_read_fixed_16_8(lsr, "floatValue"); return f_val; case SMIL_KeyTimes_datatype/*ITYPE_keyTime*/: f_val = lsr_read_fraction_12_item(lsr); break; case SMIL_KeyPoints_datatype/*ITYPE_0to1 - keyPoints*/: pt = (SVG_Point*)malloc(sizeof(SVG_Point)); pt->x = lsr_read_fixed_clamp(lsr, "valueX"); f_val = (Fixed*)malloc(sizeof(Fixed)); pt->y = lsr_read_fixed_clamp(lsr, "valueY"); return pt; case SMIL_Times_datatype/*ITYPE_smil_time*/: return lsr_read_smil_time(lsr, node); default: lsr_read_extension(lsr, "privateData"); break; } return NULL; } static void lsr_read_update_value(GF_LASeRCodec *lsr, GF_Node *node, u32 att_tag, u32 fieldType, void *val, u32 node_tag) { u32 is_default, has_escape, escape_val = 0; SVG_Paint *paint; SVG_Number num, *n; is_default = has_escape = 0; switch (fieldType) { case SVG_Boolean_datatype: GF_LSR_READ_INT(lsr, *(SVG_Boolean*)val, 1, "val"); break; case SVG_Paint_datatype: paint = (SVG_Paint *)val; lsr_read_paint(lsr, (SVG_Paint*)val, "val"); break; /* case SVG_AudioLevel_datatype: n = val; GF_LSR_READ_INT(lsr, is_default, 1, "isDefaultValue"); if (is_default) n->type=SVG_NUMBER_INHERIT; else { n->type = SVG_NUMBER_VALUE; n->value = lsr_read_fixed_clamp(lsr, "val"); } break; */ case SVG_Transform_Scale_datatype: ((SVG_Point *)val)->x = lsr_read_fixed_16_8(lsr, "scale_x"); ((SVG_Point *)val)->y = lsr_read_fixed_16_8(lsr, "scale_y"); break; case LASeR_Size_datatype: case SVG_Transform_Translate_datatype: lsr_read_coordinate(lsr, &num, 0, "translation_x"); ((SVG_Point *)val)->x = num.value; lsr_read_coordinate(lsr, &num, 0, "translation_y"); ((SVG_Point *)val)->y = num.value; break; case SVG_Transform_Rotate_datatype: ((SVG_Point_Angle*)val)->angle = lsr_read_fixed_16_8(lsr, "rotate"); break; case SVG_Transform_datatype: lsr_read_matrix(lsr, val); break; case SVG_Number_datatype: case SVG_FontSize_datatype: case SVG_Length_datatype: n = (SVG_Number*)val; switch (att_tag) { /*fractions*/ case TAG_SVG_ATT_audio_level: case TAG_SVG_ATT_fill_opacity: case TAG_SVG_ATT_offset: case TAG_SVG_ATT_opacity: case TAG_SVG_ATT_solid_opacity: case TAG_SVG_ATT_stop_opacity: case TAG_SVG_ATT_stroke_opacity: case TAG_SVG_ATT_viewport_fill_opacity: GF_LSR_READ_INT(lsr, is_default, 1, "isDefaultValue"); if (is_default) n->type=SVG_NUMBER_INHERIT; else { n->type = SVG_NUMBER_VALUE; n->value = lsr_read_fixed_16_8(lsr, "val"); } break; case TAG_SVG_ATT_width: case TAG_SVG_ATT_height: if (node_tag==TAG_SVG_svg) { lsr_read_value_with_units(lsr, n, "val"); } else { lsr_read_coordinate(lsr, n, 0, "val"); } break; default: GF_LSR_READ_INT(lsr, is_default, 1, "isDefaultValue"); if (is_default) n->type=SVG_NUMBER_INHERIT; else { GF_LSR_READ_INT(lsr, has_escape, 1, "escapeFlag"); if (has_escape) { GF_LSR_READ_INT(lsr, escape_val, 2, "escapeEnum"); n->type = SVG_NUMBER_AUTO;//only lineIncrement } else { n->type = SVG_NUMBER_VALUE; n->value = lsr_read_fixed_16_8(lsr, "val"); } } break; } break; case SVG_Coordinate_datatype: n = (SVG_Number*)val; n->type = SVG_NUMBER_VALUE; lsr_read_coordinate(lsr, n, 0, "val"); break; case SVG_Rotate_datatype: n = (SVG_Number*)val; GF_LSR_READ_INT(lsr, is_default, 1, "isDefaultValue"); if (is_default) n->type=SVG_NUMBER_INHERIT; else { GF_LSR_READ_INT(lsr, has_escape, 1, "escapeFlag"); if (has_escape) { GF_LSR_READ_INT(lsr, escape_val, 2, "escapeEnum"); n->type = escape_val ? SVG_NUMBER_AUTO_REVERSE : SVG_NUMBER_AUTO; } else { n->type = SVG_NUMBER_VALUE; n->value = lsr_read_fixed_16_8(lsr, "rotate"); } } break; case SVG_Coordinates_datatype: lsr_read_float_list(lsr, NULL, 0, val, "val"); break; case SVG_ViewBox_datatype: { u32 count; SVG_ViewBox *vb = (SVG_ViewBox *)val; GF_LSR_READ_INT(lsr, count, 1, "isDefault"); if (count) { vb->is_set = 0; } else { vb->is_set = 1; GF_LSR_READ_INT(lsr, count, 1, "escapeFlag"); count = lsr_read_vluimsbf5(lsr, "count"); if (count) { vb->x = lsr_read_fixed_16_8(lsr, "val"); count--; } if (count) { vb->y = lsr_read_fixed_16_8(lsr, "val"); count--; } if (count) { vb->width = lsr_read_fixed_16_8(lsr, "val"); count--; } if (count) { vb->height = lsr_read_fixed_16_8(lsr, "val"); } } } break; case XMLRI_datatype: case SVG_Focus_datatype: if ((att_tag==TAG_SVG_ATT_xlink_href) || (att_tag==TAG_SVG_ATT_syncReference)) { lsr_read_any_uri(lsr, (XMLRI*)val, "val"); } else { Bool is_default, is_escape; u32 escape_val, ID; GF_LSR_READ_INT(lsr, is_default, 1, "isDefault"); if (!is_default) { GF_LSR_READ_INT(lsr, is_escape, 1, "isEscape"); if (is_escape) { GF_LSR_READ_INT(lsr, escape_val, 2, "escapeEnumVal"); } else { ID = lsr_read_vluimsbf5(lsr, "ID"); } } if (att_tag==SVG_Focus_datatype) { if (is_default) ((SVG_Focus*)val)->type = SVG_FOCUS_AUTO; else if (is_escape) ((SVG_Focus*)val)->type = escape_val; else { ((SVG_Focus*)val)->type = SVG_FOCUS_IRI; ((SVG_Focus*)val)->target.type = XMLRI_ELEMENTID; ((SVG_Focus*)val)->target.target = gf_sg_find_node(lsr->sg, ID); } } else { if (is_default) ((XMLRI*)val)->type = XMLRI_STRING; else { ((XMLRI*)val)->type = XMLRI_ELEMENTID; ((XMLRI*)val)->target = gf_sg_find_node(lsr->sg, ID); } } } break; case SVG_String_datatype: case SVG_ContentType_datatype: case SVG_LanguageID_datatype: lsr_read_byte_align_string(lsr, (char**)val, "val"); break; case SVG_Motion_datatype: lsr_read_coordinate(lsr, &num, 0, "pointValueX"); ((GF_Matrix2D*)val)->m[2] = num.value; lsr_read_coordinate(lsr, &num, 0, "pointValueY"); ((GF_Matrix2D*)val)->m[5] = num.value; break; case SVG_Points_datatype: lsr_read_point_sequence(lsr, *(GF_List **)val, "val"); break; case SVG_PathData_datatype: lsr_read_path_type(lsr, NULL, 0, (SVG_PathData*)val, "val"); break; case SVG_FontFamily_datatype: { u32 idx; SVG_FontFamily *ff = (SVG_FontFamily *)val; GF_LSR_READ_INT(lsr, idx, 1, "isDefault"); ff->type = SVG_FONTFAMILY_INHERIT; if (!idx) { char *ft; GF_LSR_READ_INT(lsr, idx, 1, "escapeFlag"); idx = lsr_read_vluimsbf5(lsr, "index"); if (ff->value) free(ff->value); ff->value = NULL; ft = (char*)gf_list_get(lsr->font_table, idx); if (ft) { ff->value = strdup(ft); ff->type = SVG_FONTFAMILY_VALUE; } } } break; break; case LASeR_Choice_datatype: GF_LSR_READ_INT(lsr, is_default, 1, "isDefaultValue"); if (is_default) ((LASeR_Choice *)val)->type = LASeR_CHOICE_ALL; else { GF_LSR_READ_INT(lsr, has_escape, 1, "escapeFlag"); if (has_escape) { GF_LSR_READ_INT(lsr, escape_val, 2, "escapeEnum"); ((LASeR_Choice *)val)->type = escape_val ? LASeR_CHOICE_NONE : LASeR_CHOICE_ALL; } else { ((LASeR_Choice *)val)->type = LASeR_CHOICE_N; ((LASeR_Choice *)val)->choice_index = lsr_read_vluimsbf5(lsr, "value"); } } break; default: if ((fieldType>=SVG_FillRule_datatype) && (fieldType<=SVG_LAST_U8_PROPERTY)) { /*TODO fixme, check inherit values*/ GF_LSR_READ_INT(lsr, is_default, 1, "isDefaultValue"); if (is_default) *(u8 *)val = 0; else *(u8 *)val = lsr_read_vluimsbf5(lsr, "val"); } else { GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] Warning: update value not supported: fieldType %d - attribute tag %d\n", fieldType, att_tag)); } } if (node) { //gf_node_dirty_set(node, 0, 0); gf_node_changed(node, NULL); } } static u32 lsr_get_attribute_name(GF_LASeRCodec *lsr) { u32 val = 1; GF_LSR_READ_INT(lsr, val, 1, "has_attributeName"); if (!val) return -1; GF_LSR_READ_INT(lsr, val, 1, "choice"); if (val) { lsr_read_vluimsbf5(lsr, "item[i]"); lsr_read_vluimsbf5(lsr, "item[i]"); return -1; } else { GF_LSR_READ_INT(lsr, val, 8, "attributeName"); return val; } } static GF_Err lsr_read_add_replace_insert(GF_LASeRCodec *lsr, GF_List *com_list, u32 com_type) { GF_FieldInfo info; GF_Node *n, *operandNode, *new_node; GF_Command *com; GF_CommandField *field; s32 idx, att_type, op_att_type; u32 type, idref, op_idref = 0; operandNode = NULL; att_type = op_att_type = -1; att_type = lsr_get_attribute_name(lsr); idx = -1; if (com_type) { GF_LSR_READ_INT(lsr, type, 1, "has_index"); if (type) idx = lsr_read_vluimsbf5(lsr, "index"); } if (com_type!=3) { GF_LSR_READ_INT(lsr, type, 1, "has_operandAttribute"); if (type) GF_LSR_READ_INT(lsr, op_att_type, 8, "attributeName"); GF_LSR_READ_INT(lsr, type, 1, "has_operandElementId"); if (type) { op_idref = lsr_read_codec_IDREF_command(lsr, "operandElementId"); operandNode = gf_sg_find_node(lsr->sg, op_idref); if (!operandNode) return GF_NON_COMPLIANT_BITSTREAM; } } idref = lsr_read_codec_IDREF_command(lsr, "ref"); n = gf_sg_find_node(lsr->sg, idref); if (!n) { if (!com_list) { return GF_NON_COMPLIANT_BITSTREAM; } } GF_LSR_READ_INT(lsr, type, 1, "has_value"); if (type) { /*node or node-list replacement*/ if (att_type==-2) { lsr_read_byte_align_string(lsr, NULL, "anyXML"); } else if (att_type<0) { GF_Node *new_node; if (!com_type) return GF_NON_COMPLIANT_BITSTREAM; GF_LSR_READ_INT(lsr, type, 1, "isInherit"); if (type) return GF_NON_COMPLIANT_BITSTREAM; if (idx==-1) { GF_LSR_READ_INT(lsr, type, 1, "escapeFlag"); if (type) return GF_NON_COMPLIANT_BITSTREAM; } new_node = lsr_read_update_content_model(lsr, (idx==-1) ? NULL : (SVG_Element *)n); if (com_list) { com = gf_sg_command_new(lsr->sg, (com_type==3) ? GF_SG_LSR_INSERT : GF_SG_LSR_REPLACE); gf_list_add(com_list, com); if (n) { com->node = n; gf_node_register(com->node, NULL); } else { com->RouteID = idref; gf_list_add(lsr->unresolved_commands, com); } field = gf_sg_command_field_new(com); field->pos = idx; field->new_node = new_node; if (new_node) gf_node_register(new_node, NULL); gf_node_register(new_node, NULL); } else if (com_type==3) { gf_node_list_insert_child(& ((SVG_Element *)n)->children, new_node, idx); gf_node_register(new_node, n); } else { /*child replacement*/ if (idx!=-1) { GF_Node *old = gf_node_list_get_child( ((SVG_Element *)n)->children, idx); if (old) gf_node_replace(old, new_node, 0); else { gf_node_list_add_child( & ((SVG_Element *)n)->children, new_node); gf_node_register(new_node, n); } } else { /*node replacement*/ gf_node_replace(n, new_node, 0); } } } /*value replace/add*/ else if (com_list) { u32 field_type; Bool text_content = 0; com = gf_sg_command_new(lsr->sg, (com_type==0) ? GF_SG_LSR_ADD : (com_type==3) ? GF_SG_LSR_INSERT : GF_SG_LSR_REPLACE); field = gf_sg_command_field_new(com); field->pos = idx; field_type = 0; switch (att_type) { /*text*/ case LSR_UPDATE_TYPE_TEXT_CONTENT: text_content = 1; break; /*matrix.translation, scale or rotate*/ case LSR_UPDATE_TYPE_SCALE: field->fieldType = field_type = SVG_Transform_Scale_datatype; field->fieldIndex = gf_lsr_anim_type_to_attribute(att_type); break; case LSR_UPDATE_TYPE_ROTATE: field->fieldType = field_type = SVG_Transform_Rotate_datatype; field->fieldIndex = TAG_SVG_ATT_transform; break; case LSR_UPDATE_TYPE_TRANSLATION: field->fieldType = field_type = SVG_Transform_Translate_datatype; field->fieldIndex = gf_lsr_anim_type_to_attribute(att_type); break; case LSR_UPDATE_TYPE_SVG_HEIGHT: field->fieldIndex = TAG_SVG_ATT_height; field_type = field->fieldType = SVG_Length_datatype; break; case LSR_UPDATE_TYPE_SVG_WIDTH: field->fieldIndex = TAG_SVG_ATT_width; field_type = field->fieldType = SVG_Length_datatype; break; default: field->fieldIndex = gf_lsr_anim_type_to_attribute(att_type); if (field->fieldIndex == (u32)-1) { lsr->last_error = GF_NON_COMPLIANT_BITSTREAM; gf_sg_command_del(com); return lsr->last_error; } field_type = field->fieldType = gf_svg_get_attribute_type(field->fieldIndex); break; } gf_list_add(com_list, com); if (n) { com->node = n; gf_node_register(com->node, NULL); } else { com->RouteID = idref; gf_list_add(lsr->unresolved_commands, com); } if (idx==-1) { if (text_content) { GF_DOMText *text = gf_dom_new_text_node(n->sgprivate->scenegraph); gf_node_register((GF_Node *)text, NULL); lsr_read_byte_align_string(lsr, &text->textContent, "val"); field->new_node = (GF_Node*)text; } else { field->field_ptr = gf_svg_create_attribute_value(field_type); lsr_read_update_value(lsr, NULL, field->fieldIndex, field->fieldType, field->field_ptr, n ? n->sgprivate->tag : 0); } } else { field->field_ptr = lsr_read_update_value_indexed(lsr, (GF_Node*)n, field_type, NULL, idx, com_type==LSR_UPDATE_INSERT, 1); } } else { GF_Point2D matrix_tmp; SVG_Point_Angle matrix_tmp_rot; u32 fieldIndex; u32 field_type = 0; Bool text_content = 0; Bool is_lsr_transform = 0; switch (att_type) { /*text*/ case LSR_UPDATE_TYPE_TEXT_CONTENT: text_content = 1; break; /*matrix.translation, scale or rotate*/ case LSR_UPDATE_TYPE_SCALE: info.far_ptr = (void *)&matrix_tmp; field_type = SVG_Transform_Scale_datatype; is_lsr_transform = 1; break; case LSR_UPDATE_TYPE_ROTATE: info.far_ptr = (void *)&matrix_tmp_rot; field_type = SVG_Transform_Rotate_datatype; is_lsr_transform = 1; break; case LSR_UPDATE_TYPE_TRANSLATION: info.far_ptr = (void *)&matrix_tmp; field_type = SVG_Transform_Translate_datatype; is_lsr_transform = 1; break; default: fieldIndex = gf_lsr_anim_type_to_attribute(att_type); gf_svg_get_attribute_by_tag(n, fieldIndex, 1, 0, &info); field_type = info.fieldType; break; } if (is_lsr_transform) { SVG_Transform *dest; if (idx==-1) { lsr_read_update_value(lsr, NULL, fieldIndex, field_type, info.far_ptr, 0); } else { assert(0); } fieldIndex = gf_svg_get_attribute_by_tag((GF_Node*)n, TAG_SVG_ATT_transform, 1, 1, &info); dest = (SVG_Transform *)info.far_ptr; if (com_type) { GF_Point2D scale, translate; SVG_Point_Angle rotate; if (gf_mx2d_decompose(&dest->mat, &scale, &rotate.angle, &translate)) { gf_mx2d_init(dest->mat); if (att_type==LSR_UPDATE_TYPE_SCALE) scale = matrix_tmp; else if (att_type==LSR_UPDATE_TYPE_TRANSLATION) translate = matrix_tmp; else if (att_type==LSR_UPDATE_TYPE_ROTATE) rotate = matrix_tmp_rot; gf_mx2d_add_scale(&dest->mat, scale.x, scale.y); gf_mx2d_add_rotation(&dest->mat, 0, 0, rotate.angle); gf_mx2d_add_translation(&dest->mat, translate.x, translate.y); } } else if (att_type==LSR_UPDATE_TYPE_SCALE) gf_mx2d_add_scale(&dest->mat, matrix_tmp.x, matrix_tmp.y); else if (att_type==LSR_UPDATE_TYPE_TRANSLATION) gf_mx2d_add_translation(&dest->mat, matrix_tmp.x, matrix_tmp.y); else if (att_type==LSR_UPDATE_TYPE_ROTATE) gf_mx2d_add_rotation(&dest->mat, 0, 0, matrix_tmp_rot.angle); gf_node_changed((GF_Node*)n, &info); } else if (com_type) { if (text_content) { GF_DOMText *t = NULL; if (idx>=0) { if (com_type==LSR_UPDATE_INSERT) { t = gf_dom_new_text_node(n->sgprivate->scenegraph); gf_node_register((GF_Node *)t, n); gf_node_list_insert_child(&((GF_ParentNode *)n)->children, (GF_Node*)t, idx); } else { t = (GF_DOMText *) gf_node_list_get_child(((SVG_Element*)n)->children, idx); if (t->sgprivate->tag!=TAG_DOMText) t = NULL; } } else { /*this is a replace, reset ALL node content*/ gf_sg_parent_reset(n); t = gf_dom_add_text_node(n, NULL); } lsr_read_byte_align_string(lsr, t ? &t->textContent : NULL, "textContent"); gf_node_changed(n, NULL); } else if (idx==-1) { lsr_read_update_value(lsr, (GF_Node*)n, fieldIndex, field_type, info.far_ptr, n->sgprivate->tag); } else { SVG_Point *pt; Fixed *v1, *v2; //SMIL_Time *t; void *prev; void *tmp = lsr_read_update_value_indexed(lsr, (GF_Node*)n, field_type, info.far_ptr, idx, com_type==LSR_UPDATE_INSERT, 0); switch (field_type) { /*generic GF_List containers, no type translation needed*/ case SMIL_KeyTimes_datatype/*ITYPE_keyTime*/: case SMIL_KeySplines_datatype/*ITYPE_float*/: case SVG_Points_datatype/*ITYPE_point*/: case SMIL_Times_datatype/*ITYPE_smil_time*/: if (com_type==LSR_UPDATE_INSERT) { gf_list_insert(*(SVG_Coordinates*)info.far_ptr, tmp, idx); } else { prev = gf_list_get(*(SVG_Coordinates*)info.far_ptr, idx); free(prev); gf_list_rem(*(SVG_Coordinates*)info.far_ptr, idx); gf_list_insert(*(SVG_Coordinates*)info.far_ptr, tmp, idx); } gf_node_changed((GF_Node*)n, NULL); break; /*list of floats - to check when implementing it...*/ case SMIL_KeyPoints_datatype/*ITYPE_0to1 - keyPoints*/: pt = (SVG_Point*)tmp; v1 = (Fixed *) malloc(sizeof(Fixed)); *v1 = pt->x; v2 = (Fixed *) malloc(sizeof(Fixed)); *v2 = pt->y; free(pt); if (com_type==LSR_UPDATE_INSERT) { gf_list_insert(*(SVG_Coordinates*)info.far_ptr, v1, idx); gf_list_insert(*(SVG_Coordinates*)info.far_ptr, v2, idx+1); } else { prev = gf_list_get(*(SVG_Coordinates*)info.far_ptr, idx); free(prev); gf_list_rem(*(SVG_Coordinates*)info.far_ptr, idx); prev = gf_list_get(*(SVG_Coordinates*)info.far_ptr, idx); free(prev); gf_list_rem(*(SVG_Coordinates*)info.far_ptr, idx); gf_list_insert(*(SVG_Coordinates*)info.far_ptr, v1, idx); gf_list_insert(*(SVG_Coordinates*)info.far_ptr, v2, idx); } gf_node_changed((GF_Node*)n, NULL); break; case SVG_ViewBox_datatype: v1 = (Fixed*)tmp; switch (idx) { case 0: ((SVG_ViewBox*)info.far_ptr)->x = *v1; break; case 1: ((SVG_ViewBox*)info.far_ptr)->y = *v1; break; case 2: ((SVG_ViewBox*)info.far_ptr)->width = *v1; break; case 3: ((SVG_ViewBox*)info.far_ptr)->height = *v1; break; } free(tmp); gf_node_changed((GF_Node*)n, NULL); break; case SVG_StrokeDashArray_datatype: v1 = (Fixed*)tmp; if (com_type==LSR_UPDATE_INSERT) { SVG_StrokeDashArray*da = (SVG_StrokeDashArray*)info.far_ptr; /*use MFFloat for insert*/ if (gf_sg_vrml_mf_insert(&da->array, GF_SG_VRML_MFFLOAT, (void*) &v2, idx)==GF_OK) *v2 = *v1; } else { SVG_StrokeDashArray*da = (SVG_StrokeDashArray*)info.far_ptr; if (idx<(s32)da->array.count) da->array.vals[idx] = *v1; } free(tmp); gf_node_changed((GF_Node*)n, NULL); break; default: free(tmp); break; } } } else { GF_FieldInfo tmp; tmp = info; if (idx==-1) { tmp.far_ptr = gf_svg_create_attribute_value(info.fieldType); lsr_read_update_value(lsr, n, fieldIndex, field_type, tmp.far_ptr, n->sgprivate->tag); } else { tmp.far_ptr = lsr_read_update_value_indexed(lsr, n, field_type, NULL, idx, 0, 1); } gf_svg_attributes_add(&info, &tmp, &info, 0); gf_svg_delete_attribute_value(info.fieldType, tmp.far_ptr, gf_node_get_graph(n)); } } } /*copy from node*/ else if (operandNode && (op_att_type>=0)) { u32 opFieldIndex = gf_lsr_anim_type_to_attribute(op_att_type); if (com_list) { com = gf_sg_command_new(lsr->sg, com_type ? GF_SG_LSR_REPLACE : GF_SG_LSR_ADD); gf_list_add(com_list, com); com->node = n; gf_node_register(com->node, NULL); com->fromNodeID = op_idref; com->fromFieldIndex = opFieldIndex; field = gf_sg_command_field_new(com); field->pos = idx; field->fieldIndex = gf_lsr_anim_type_to_attribute(att_type); } else { u32 fieldIndex; GF_FieldInfo op_info; fieldIndex = gf_lsr_anim_type_to_attribute(att_type); gf_node_get_field(n, fieldIndex, &info); gf_node_get_field(operandNode, opFieldIndex, &op_info); if (com_type) { gf_svg_attributes_copy(&info, &op_info, 0); } else { gf_svg_attributes_add(&info, &op_info, &info, 0); } } } lsr_read_any_attribute(lsr, NULL, 1); /*if not add*/ if (!com_type) return GF_OK; /*list replacement*/ GF_LSR_READ_INT(lsr, type, 1, "opt_group"); if (type) { if (!com_type /*|| (idx!=-1) */) return GF_NON_COMPLIANT_BITSTREAM; if (com_list) { u32 count; GF_ChildNodeItem *last = NULL; if (com_type==LSR_UPDATE_INSERT) count = 1; else count = lsr_read_vluimsbf5(lsr, "count"); com = gf_sg_command_new(lsr->sg, (com_type==LSR_UPDATE_REPLACE) ? GF_SG_LSR_REPLACE : GF_SG_LSR_INSERT); gf_list_add(com_list, com); com->node = n; gf_node_register(com->node, NULL); field = gf_sg_command_field_new(com); field->pos = idx; if (!count && (att_type==LSR_UPDATE_TYPE_TEXT_CONTENT)) { field->fieldIndex = -1; } else if (count==1) { field->new_node = lsr_read_update_content_model(lsr, (SVG_Element *) n); gf_node_register(field->new_node, n); if (att_type>=0) field->fieldIndex = gf_lsr_anim_type_to_attribute(att_type); } else { field->field_ptr = &field->node_list; while (count) { GF_Node *new_node = lsr_read_update_content_model(lsr, (SVG_Element *) n); gf_node_register(new_node, n); gf_node_list_add_child_last(& field->node_list, new_node, &last); count--; } } } else { SVG_Element*elt = (SVG_Element*)n; GF_ChildNodeItem *last = NULL; u32 count; if (com_type==LSR_UPDATE_INSERT) count = 1; else count = lsr_read_vluimsbf5(lsr, "count"); if (com_type==LSR_UPDATE_REPLACE) { if (idx>=0) { new_node = gf_node_list_del_child_idx(&elt->children, idx); if (new_node) gf_node_unregister(new_node, n); } else { gf_node_unregister_children(n, elt->children); elt->children = NULL; } } if ((com_type==LSR_UPDATE_INSERT) || (gf_lsr_anim_type_to_attribute(att_type) == TAG_LSR_ATT_children)) { while (count) { new_node = lsr_read_update_content_model(lsr, elt); if (new_node) { if (idx>=0) { gf_node_list_insert_child(&elt->children, new_node, idx); } else { gf_node_list_add_child_last(&elt->children, new_node, &last); } gf_node_register(new_node, n); } count--; } gf_node_changed(n, NULL); } /*node replacement*/ else if ((att_type==-1) && (count==1)) { new_node = lsr_read_update_content_model(lsr, elt); gf_node_replace((GF_Node*)elt, new_node, 0); } } } return GF_OK; } static GF_Err lsr_read_delete(GF_LASeRCodec *lsr, GF_List *com_list) { GF_FieldInfo info; s32 idx, att_type; u32 type, idref; att_type = lsr_get_attribute_name(lsr); idx = -2; GF_LSR_READ_INT(lsr, type, 1, "has_index"); if (type) idx = (s32) lsr_read_vluimsbf5(lsr, "index"); idref = lsr_read_codec_IDREF_command(lsr, "ref"); lsr_read_any_attribute(lsr, NULL, 1); if (com_list) { GF_Command *com; GF_CommandField *field; com = gf_sg_command_new(lsr->sg, GF_SG_LSR_DELETE); gf_list_add(com_list, com); com->node = gf_sg_find_node(lsr->sg, idref); if (!com->node) { com->RouteID = idref; gf_list_add(lsr->unresolved_commands, com); } else { gf_node_register(com->node, NULL); } if ((idx>=0) || (att_type>=0)) { field = gf_sg_command_field_new(com); field->pos = idx; if (att_type>=0) { field->fieldIndex = gf_lsr_anim_type_to_attribute(att_type); gf_node_get_field(com->node, field->fieldIndex, &info); field->fieldType = info.fieldType; } } } else { s32 fieldIndex = -1; SVG_Element *elt = (SVG_Element *) gf_sg_find_node(lsr->sg, idref); if (!elt) return GF_NON_COMPLIANT_BITSTREAM; if (att_type>=0) { fieldIndex = gf_lsr_anim_type_to_attribute(att_type); gf_node_get_field((GF_Node*)elt, fieldIndex, &info); /*TODO implement*/ } /*node deletion*/ else if (idx>=0) { GF_Node *c = (GF_Node *)gf_node_list_get_child(elt->children, idx); if (c) { if (!gf_node_list_del_child( & elt->children, c)) return GF_IO_ERR; gf_node_unregister(c, (GF_Node*)elt); } } else { gf_node_replace((GF_Node*)elt, NULL, 0); } } return GF_OK; } static GF_Err lsr_read_send_event(GF_LASeRCodec *lsr, GF_List *com_list) { u32 flag, idref; XMLEV_Event evt; lsr_read_event_type(lsr, &evt); GF_LSR_READ_INT(lsr, flag, 1, "has_intvalue"); if (flag) { GF_LSR_READ_INT(lsr, flag, 1, "sign"); flag = lsr_read_vluimsbf5(lsr, "value"); } GF_LSR_READ_INT(lsr, flag, 1, "has_pointvalue"); if (flag) { SVG_Number coord; lsr_read_coordinate(lsr, &coord, 0, "x"); lsr_read_coordinate(lsr, &coord, 0, "y"); } idref = lsr_read_codec_IDREF_command(lsr, "idref"); GF_LSR_READ_INT(lsr, flag, 1, "has_pointvalue"); if (flag) { lsr_read_byte_align_string(lsr, NULL, "string");; } lsr_read_any_attribute(lsr, NULL, 1); return GF_OK; } static GF_Err lsr_read_save(GF_LASeRCodec *lsr, GF_List *com_list) { u32 i, count; count = lsr_read_vluimsbf5(lsr, "nbIds"); for (i=0; isgprivate->tag!=TAG_DOMUpdates)) return; assert(!codec->bs); codec->info = lsr_get_stream(codec, 0); if (!codec->info) return; codec->coord_bits = codec->info->cfg.coord_bits; codec->scale_bits = codec->info->cfg.scale_bits_minus_coord_bits; codec->time_resolution = codec->info->cfg.time_resolution; codec->color_scale = (1<info->cfg.colorComponentBits) - 1; if (codec->info->cfg.resolution >= 0) codec->res_factor = INT2FIX(1<info->cfg.resolution); else codec->res_factor = gf_divfix(FIX_ONE, INT2FIX(1 << (-codec->info->cfg.resolution)) ); codec->bs = gf_bs_new(up->data, up->data_size, GF_BITSTREAM_READ); codec->memory_dec = 0; lsr_read_command_list(codec, NULL, NULL, 0); gf_bs_del(codec->bs); codec->bs = NULL; } static GF_Err lsr_read_command_list(GF_LASeRCodec *lsr, GF_List *com_list, SVG_Element *cond, Bool first_imp) { GF_Node *n; GF_Command *com; GF_Err e; u32 i, type, count; if (cond) { u32 s_len; GF_DOMUpdates *up = gf_dom_add_updates_node((GF_Node*)cond); gf_node_set_callback_function((GF_Node*)up, lsr_exec_command_list); gf_node_set_private((GF_Node *) up, lsr); s_len = lsr_read_vluimsbf5(lsr, NULL/*"encoding-length" - don't log to avoid corrupting the log order!!*/); gf_bs_align(lsr->bs); /*not in memory mode, direct decode*/ if (!lsr->memory_dec) { com_list = NULL; up->data_size = s_len; up->data = (char*)malloc(sizeof(char)*s_len); gf_bs_read_data(lsr->bs, up->data, s_len); goto exit; } /*memory mode, decode commands*/ else { com_list = up->updates; } } count = lsr_read_vluimsbf5(lsr, "occ0"); if (first_imp) count++; for (i=0; ilast_error = GF_NON_COMPLIANT_BITSTREAM); gf_node_register(n, NULL); com = gf_sg_command_new(lsr->sg, (type==5) ? GF_SG_LSR_REFRESH_SCENE : GF_SG_LSR_NEW_SCENE); com->node = n; gf_list_add(com_list, com); } else { gf_sg_reset(lsr->sg); n = lsr_read_svg(lsr); if (!n) return (lsr->last_error = GF_NON_COMPLIANT_BITSTREAM); gf_node_register(n, NULL); gf_sg_set_root_node(lsr->sg, n); gf_sg_set_scene_size_info(lsr->sg, 0, 0, 1); } break; case LSR_UPDATE_TEXT_CONTENT: lsr_read_byte_align_string(lsr, NULL, "textContent"); break; case LSR_UPDATE_SEND_EVENT: e = lsr_read_send_event(lsr, com_list); break; case LSR_UPDATE_RESTORE: e = lsr_read_restore(lsr, com_list); break; case LSR_UPDATE_SAVE: e = lsr_read_save(lsr, com_list); break; case LSR_UPDATE_EXTEND: { u32 extID, len; GF_Node *n; GF_LSR_READ_INT(lsr, extID, lsr->info->cfg.extensionIDBits, "extensionID"); len = lsr_read_vluimsbf5(lsr, "len"); if (extID==2) { u32 j, sub_count; lsr_read_vluimsbf5(lsr, "reserved"); sub_count = lsr_read_vluimsbf5(lsr, "occ2"); for (j=0; jsg, idref); if (com_list) { com = gf_sg_command_new(lsr->sg, (sub_type==1) ? GF_SG_LSR_ACTIVATE : GF_SG_LSR_DEACTIVATE); if (n) { com->node = n; gf_node_register(n, NULL); } else { com->RouteID = idref; } gf_list_add(com_list, com); } else if (sub_type==1) { if (!n) return GF_NON_COMPLIANT_BITSTREAM; gf_node_activate(n); } else { if (!n) return GF_NON_COMPLIANT_BITSTREAM; gf_node_deactivate(n); } break; default: lsr_read_private_element_container(lsr); break; } } } } } break; default: return (lsr->last_error = GF_NON_COMPLIANT_BITSTREAM); } /*same-coding scope is command-based (to check in the spec)*/ if (cond) { lsr->prev_g = NULL; lsr->prev_line = NULL; lsr->prev_path = NULL; lsr->prev_polygon = NULL; lsr->prev_rect = NULL; lsr->prev_text = NULL; lsr->prev_use = NULL; } if (lsr->last_error) return lsr->last_error; } exit: /*script is align*/ if (cond) { gf_bs_align(lsr->bs); lsr_read_object_content(lsr, (SVG_Element*)cond); lsr->prev_g = NULL; lsr->prev_line = NULL; lsr->prev_path = NULL; lsr->prev_polygon = NULL; lsr->prev_rect = NULL; lsr->prev_text = NULL; lsr->prev_use = NULL; } return GF_OK; } static GF_Err lsr_decode_laser_unit(GF_LASeRCodec *lsr, GF_List *com_list) { GF_Err e; Bool reset_encoding_context; u32 flag, i, count = 0, privateDataIdentifierIndexBits; lsr->last_error = GF_OK; /* * 1 - laser unit header */ GF_LSR_READ_INT(lsr, reset_encoding_context, 1, "resetEncodingContext"); GF_LSR_READ_INT(lsr, flag, 1, "opt_group"); if (flag) lsr_read_extension(lsr, "ext"); /*clean all tables*/ if (reset_encoding_context) { lsr->nb_cols = 0; if (lsr->col_table) free(lsr->col_table); lsr->col_table = NULL; while (gf_list_count(lsr->font_table)) { char *ft = (char *)gf_list_last(lsr->font_table); free(ft); gf_list_rem_last(lsr->font_table); } lsr->privateData_id_index = lsr->privateTag_index = 0; } /* * 2 - codecInitialisations */ /* * 2.a - condecInitialization.color */ GF_LSR_READ_INT(lsr, flag, 1, "colorInitialisation"); count = 0; if (flag) { count = lsr_read_vluimsbf5(lsr, "count"); lsr->col_table = (LSRCol*)realloc(lsr->col_table, sizeof(LSRCol)*(lsr->nb_cols+count)); for (i=0; iinfo->cfg.colorComponentBits, "red"); GF_LSR_READ_INT(lsr, c.g, lsr->info->cfg.colorComponentBits, "green"); GF_LSR_READ_INT(lsr, c.b, lsr->info->cfg.colorComponentBits, "blue"); lsr->col_table[lsr->nb_cols+i] = c; } lsr->nb_cols += count; } lsr->colorIndexBits = gf_get_bit_size(lsr->nb_cols); /* * 2.b - condecInitialization.fonts */ GF_LSR_READ_INT(lsr, flag, 1, "fontInitialisation"); count = 0; if (flag) { count = lsr_read_vluimsbf5(lsr, "count"); for (i=0; ifont_table, ft); } } lsr->fontIndexBits = gf_get_bit_size(count); /* * 2.c - condecInitialization.private */ GF_LSR_READ_INT(lsr, flag, 1, "privateDataIdentifierInitialisation"); count = 0; if (flag) { count = lsr_read_vluimsbf5(lsr, "nbPrivateDataIdentifiers"); for (i=0; iprivateData_id_index++; lsr_read_byte_align_string(lsr, NULL, "privateDataIdentifier"); } } /* * 2.d - condecInitialization.anyXML */ GF_LSR_READ_INT(lsr, flag, 1, "anyXMLInitialisation"); count = 0; if (flag) { privateDataIdentifierIndexBits = gf_get_bit_size(lsr->privateData_id_index); count = lsr_read_vluimsbf5(lsr, "nbTags"); for (i=0; iprivateTag_index++; if (i) { /* uint(privateDataIdentifierIndexBits) = */ GF_LSR_READ_INT(lsr, flag, privateDataIdentifierIndexBits, "privateDataIdentifierIndex"); lsr_read_byte_align_string(lsr, NULL, "tag"); } GF_LSR_READ_INT(lsr, flag, 1, "hasAttrs"); if (flag) { u32 k, c2 = lsr_read_vluimsbf5(lsr, "nbAttrNames"); for (k=0; kbs); count = lsr_read_vluimsbf5(lsr, "len"); for (i=0; ibs) - pos; assert(len>=pos); GF_LSR_READ_INT(lsr, flag, pos, "remainingData"); } e = lsr_read_command_list(lsr, com_list, NULL, 1); GF_LSR_READ_INT(lsr, flag, 1, "opt_group"); if (flag) lsr_read_extension(lsr, "ext"); return e; }