/* * 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_WRITE_INT(_codec, _val, _nbBits, _str) {\ gf_bs_write_int(_codec->bs, _val, _nbBits); \ GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] %s\t\t%d\t\t%d\n", _str, _nbBits, _val)); \ }\ static void lsr_write_group_content(GF_LASeRCodec *lsr, SVG_Element *elt, Bool skip_object_content); static GF_Err lsr_write_command_list(GF_LASeRCodec *lsr, GF_List *comList, SVG_Element *script, Bool first_implicit); static GF_Err lsr_write_laser_unit(GF_LASeRCodec *lsr, GF_List *com_list, Bool reset_encoding_context); static void lsr_write_point_sequence(GF_LASeRCodec *lsr, GF_List **pts, const char *name); static void lsr_write_path_type(GF_LASeRCodec *lsr, SVG_PathData *path, const char *name); GF_LASeRCodec *gf_laser_encoder_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->sg = graph; return tmp; } void gf_laser_encoder_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); free(codec); } static LASeRStreamInfo *lsr_get_stream(GF_LASeRCodec *codec, u16 ESID) { LASeRStreamInfo *ptr; u32 i = 0; while ((ptr = (LASeRStreamInfo *)gf_list_enum(codec->streamInfo, &i))) { if(ptr->ESID==ESID) return ptr; } return NULL; } GF_Err gf_laser_encoder_new_stream(GF_LASeRCodec *codec, u16 ESID, GF_LASERConfig *cfg) { LASeRStreamInfo *pInfo; if (lsr_get_stream(codec, ESID) != NULL) return GF_BAD_PARAM; GF_SAFEALLOC(pInfo, LASeRStreamInfo); pInfo->ESID = ESID; memcpy(&pInfo->cfg, cfg, sizeof(GF_LASERConfig)); if (!pInfo->cfg.time_resolution) pInfo->cfg.time_resolution = 1000; if (!pInfo->cfg.colorComponentBits) pInfo->cfg.colorComponentBits = 8; if (!pInfo->cfg.coord_bits) pInfo->cfg.coord_bits = 12; if (pInfo->cfg.resolution<-8) pInfo->cfg.resolution = (s8) -8; else if (pInfo->cfg.resolution>7) pInfo->cfg.resolution=7; gf_list_add(codec->streamInfo, pInfo); return GF_OK; } GF_Err gf_laser_encoder_get_config(GF_LASeRCodec *codec, u16 ESID, char **out_data, u32 *out_data_length) { GF_BitStream *bs; if (!codec || !out_data || !out_data_length) return GF_BAD_PARAM; codec->info = lsr_get_stream(codec, ESID); if (!codec->info) return GF_BAD_PARAM; bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); gf_bs_write_int(bs, codec->info->cfg.profile, 8); gf_bs_write_int(bs, codec->info->cfg.level, 8); gf_bs_write_int(bs, 0 /*codec->info->cfg.reserved*/, 3); gf_bs_write_int(bs, codec->info->cfg.pointsCodec, 2); gf_bs_write_int(bs, codec->info->cfg.pathComponents, 4); gf_bs_write_int(bs, codec->info->cfg.fullRequestHost, 1); if (codec->info->cfg.time_resolution != 1000) { gf_bs_write_int(bs, 1, 1); gf_bs_write_int(bs, codec->info->cfg.time_resolution , 16); } else { gf_bs_write_int(bs, 0, 1); } gf_bs_write_int(bs, codec->info->cfg.colorComponentBits - 1, 4); if (codec->info->cfg.resolution<0) gf_bs_write_int(bs, 16 + codec->info->cfg.resolution, 4); else gf_bs_write_int(bs, codec->info->cfg.resolution, 4); gf_bs_write_int(bs, codec->info->cfg.coord_bits, 5); gf_bs_write_int(bs, codec->info->cfg.scale_bits_minus_coord_bits, 4); gf_bs_write_int(bs, codec->info->cfg.newSceneIndicator ? 1 : 0, 1); gf_bs_write_int(bs, 0, 3); gf_bs_write_int(bs, codec->info->cfg.extensionIDBits, 4); /*no extConfig*/ gf_bs_write_int(bs, 0, 1); /*no extensions*/ gf_bs_write_int(bs, 0, 1); gf_bs_align(bs); gf_bs_get_content(bs, out_data, out_data_length); gf_bs_del(bs); return GF_OK; } GF_Err gf_laser_encode_au(GF_LASeRCodec *codec, u16 ESID, GF_List *command_list, Bool reset_context, char **out_data, u32 *out_data_length) { GF_Err e; if (!codec || !command_list || !out_data || !out_data_length) 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 = gf_divfix(FIX_ONE, INT2FIX(1<info->cfg.resolution) ); else codec->res_factor = INT2FIX(1 << (-codec->info->cfg.resolution)); codec->bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); e = lsr_write_laser_unit(codec, command_list, reset_context); if (!e) { gf_bs_align(codec->bs); gf_bs_get_content(codec->bs, out_data, out_data_length); } gf_bs_del(codec->bs); codec->bs = NULL; return e; } GF_Err gf_laser_encoder_get_rap(GF_LASeRCodec *codec, char **out_data, u32 *out_data_length) { GF_Err e; if (!codec->info) codec->info = (LASeRStreamInfo*)gf_list_get(codec->streamInfo, 0); 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 = gf_divfix(FIX_ONE, INT2FIX(1<info->cfg.resolution) ); else codec->res_factor = INT2FIX(1 << (-codec->info->cfg.resolution)); codec->bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); e = lsr_write_laser_unit(codec, NULL, 0); if (e == GF_OK) gf_bs_get_content(codec->bs, out_data, out_data_length); gf_bs_del(codec->bs); codec->bs = NULL; return e; } static void lsr_write_vluimsbf5(GF_LASeRCodec *lsr, u32 val, const char *name) { u32 nb_words; u32 nb_bits = val ? gf_get_bit_size(val) : 1; nb_words = nb_bits / 4; if (nb_bits%4) nb_words++; assert(nb_words * 4 >= nb_bits); nb_bits = 4*nb_words; while (nb_words) { nb_words--; gf_bs_write_int(lsr->bs, nb_words ? 1 : 0, 1); } gf_bs_write_int(lsr->bs, val, nb_bits); GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] %s\t\t%d\t\t%d\n", name, nb_bits + (nb_bits/4), val)); } static void lsr_write_vluimsbf5_ex(GF_LASeRCodec *lsr, u32 val, u32 extra_words, const char *name) { u32 nb_words; u32 nb_bits = val ? gf_get_bit_size(val) : 1; nb_words = nb_bits / 4; if (nb_bits%4) nb_words++; nb_words += extra_words; assert(nb_words * 4 >= nb_bits); nb_bits = 4*nb_words; while (nb_words) { nb_words--; gf_bs_write_int(lsr->bs, nb_words ? 1 : 0, 1); } gf_bs_write_int(lsr->bs, val, nb_bits); GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] %s\t\t%d\t\t%d\n", name, nb_bits + (nb_bits/4), val)); } static u32 lsr_get_vluimsbf5_size(u32 val, u32 extra_words) { u32 nb_words; u32 nb_bits = val ? gf_get_bit_size(val) : 1; nb_words = nb_bits / 4; if (nb_bits%4) nb_words++; nb_words += extra_words; return 4*nb_words + nb_words; } static void lsr_write_vluimsbf8(GF_LASeRCodec *lsr, u32 val, const char *name) { u32 nb_words; u32 nb_tot, nb_bits = val ? gf_get_bit_size(val) : 1; nb_words = nb_bits / 7; if (nb_bits%7) nb_words++; assert(nb_words * 7 >= nb_bits); nb_bits = nb_words * 7; nb_tot = nb_words+nb_bits; while (nb_words) { nb_words--; gf_bs_write_int(lsr->bs, nb_words ? 1 : 0, 1); } gf_bs_write_int(lsr->bs, val, nb_bits); GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] %s\t\t%d\t\t%d\n", name, nb_tot, val)); } static void lsr_write_extension(GF_LASeRCodec *lsr, char *data, u32 len, const char *name) { if (!len) len = strlen(name); lsr_write_vluimsbf5(lsr, len, name); gf_bs_write_data(lsr->bs, data, len); } static void lsr_write_extend_class(GF_LASeRCodec *lsr, char *data, u32 len, const char *name) { u32 i=0; GF_LSR_WRITE_INT(lsr, 0, lsr->info->cfg.extensionIDBits, "reserved"); lsr_write_vluimsbf5(lsr, len, "len"); while (ibs, data[i], 8); i++; } } static void lsr_write_codec_IDREF(GF_LASeRCodec *lsr, XMLRI *href, const char *name) { u32 nID = 0; if (href && href->target) nID = gf_node_get_id((GF_Node *)href->target); else if (name[0]=='#') { GF_Node *n = gf_sg_find_node_by_name(lsr->sg, (char *) name + 1); if (n) nID = gf_node_get_id((GF_Node *)href->target); } else nID = 1+href->lsr_stream_id; assert(nID); lsr_write_vluimsbf5(lsr, nID-1, name); GF_LSR_WRITE_INT(lsr, 0, 1, "reserved"); } static void lsr_write_codec_IDREF_Node(GF_LASeRCodec *lsr, GF_Node *href, const char *name) { u32 nID = gf_node_get_id(href); assert(nID); lsr_write_vluimsbf5(lsr, nID-1, name); GF_LSR_WRITE_INT(lsr, 0, 1, "reserved"); } static u32 lsr_get_IDREF_nb_bits(GF_LASeRCodec *lsr, GF_Node *href) { u32 nb_bits, nb_words, nID; nID = gf_node_get_id(href); assert(nID); nb_bits = nID ? gf_get_bit_size(nID) : 1; nb_words = nb_bits / 4; if (nb_bits%4) nb_words++; assert(nb_words * 4 >= nb_bits); nb_bits = nb_words * 4; return nb_words+nb_bits /*IDREF part*/ + 1 /*reserevd bit*/; } static void lsr_write_fixed_16_8(GF_LASeRCodec *lsr, Fixed fix, const char *name) { u32 val; if (fix<0) { #ifdef GPAC_FIXED_POINT val = (1<<24) + fix / 256; #else val = (1<<24) + FIX2INT(fix * 256); #endif } else { #ifdef GPAC_FIXED_POINT val = fix/256; #else val = FIX2INT(fix*256); #endif } val &= 0x00FFFFFF; GF_LSR_WRITE_INT(lsr, val, 24, name); } static void lsr_write_fixed_16_8i(GF_LASeRCodec *lsr, SVG_Number *n, const char *name) { if (n->type==SVG_NUMBER_INHERIT) { GF_LSR_WRITE_INT(lsr, 1, 1, name); } else { GF_LSR_WRITE_INT(lsr, 0, 1, name); lsr_write_fixed_16_8(lsr, n->value, name); } } static s32 lsr_get_font_index(GF_LASeRCodec *lsr, SVG_FontFamily *font) { u32 i, count; if ((font->type!=SVG_FONTFAMILY_VALUE) || !font->value) return -1; count = gf_list_count(lsr->font_table); for (i=0; ifont_table, i); if (!strcmp(n, font->value)) return (s32) i; } return -2; } static s32 lsr_get_col_index(GF_LASeRCodec *lsr, SVG_Color *color) { u16 r, g, b; u32 i; if (color->type!=SVG_COLOR_RGBCOLOR) return -1; r = FIX2INT(color->red*lsr->color_scale); g = FIX2INT(color->green*lsr->color_scale); b = FIX2INT(color->blue*lsr->color_scale); for (i=0; inb_cols; i++) { LSRCol *c = &lsr->col_table[i]; if ((c->r == r) && (c->g == g) && (c->b == b)) return (s32) i; } return -2; } static void lsr_write_line_increment_type(GF_LASeRCodec *lsr, SVG_Number *li, const char *name) { if (li->type==SVG_NUMBER_INHERIT) { GF_LSR_WRITE_INT(lsr, 1, 1, "choice"); GF_LSR_WRITE_INT(lsr, 1, 1, "inherit"); } else if (li->type==SVG_NUMBER_AUTO) { GF_LSR_WRITE_INT(lsr, 1, 1, "choice"); GF_LSR_WRITE_INT(lsr, 0, 1, "auto"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "choice"); lsr_write_fixed_16_8(lsr, li->value, "line-increment-value"); } } static void lsr_write_byte_align_string(GF_LASeRCodec *lsr, char *str, const char *name) { u32 len = str ? strlen(str) : 0; gf_bs_align(lsr->bs); lsr_write_vluimsbf8(lsr, len, "len"); if (len) gf_bs_write_data(lsr->bs, str, len); GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] %s\t\t%d\t\t%s\n", name, 8*len, str ? str : "")); } static void lsr_write_byte_align_string_list(GF_LASeRCodec *lsr, GF_List *l, const char *name, Bool is_iri) { char text[4096]; u32 i, count = gf_list_count(l); text[0] = 0; for (i=0; istring; } else { str = (char*)gf_list_get(l, i); } strcat(text, str); if (i+1type==XMLRI_STRING) { is_iri = 1; if (iri->string[0]=='#') { iri->target = (SVG_Element*)gf_sg_find_node_by_name(lsr->sg, iri->string+1); if (iri->target) { is_iri = 0; iri->type = XMLRI_ELEMENTID; } } } GF_LSR_WRITE_INT(lsr, is_iri, 1, "hasUri"); if (is_iri) { if (!iri->string || strnicmp(iri->string, "data:", 5)) { lsr_write_byte_align_string(lsr, iri->string, "uri"); GF_LSR_WRITE_INT(lsr, 0, 1, "hasData"); } else { u32 len; char *sep = strchr(iri->string, ','); sep[0] = 0; lsr_write_byte_align_string(lsr, iri->string, "uri"); sep[0] = ','; len = strlen(sep+1); GF_LSR_WRITE_INT(lsr, 1, 1, "hasData"); lsr_write_vluimsbf5(lsr, len, "len"); gf_bs_write_data(lsr->bs, sep+1, len); } } GF_LSR_WRITE_INT(lsr, (iri->type==XMLRI_ELEMENTID) ? 1 : 0, 1, "hasID"); if (iri->type==XMLRI_ELEMENTID) lsr_write_codec_IDREF(lsr, iri, "idref"); GF_LSR_WRITE_INT(lsr, (iri->type==XMLRI_STREAMID) ? 1 : 0, 1, "hasID"); if (iri->type==XMLRI_STREAMID) lsr_write_codec_IDREF(lsr, iri, "ref"); } static void lsr_write_paint(GF_LASeRCodec *lsr, SVG_Paint *paint, const char *name) { if ((paint->type==SVG_PAINT_COLOR) && (paint->color.type==SVG_COLOR_RGBCOLOR)) { s32 idx; GF_LSR_WRITE_INT(lsr, 1, 1, "hasIndex"); idx = lsr_get_col_index(lsr, &paint->color); if (idx<0) { idx = 0; GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[LASeR] color not in colorTable\n")); } GF_LSR_WRITE_INT(lsr, (u32) idx, lsr->colorIndexBits, name); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "hasIndex"); switch (paint->type) { case SVG_PAINT_INHERIT: GF_LSR_WRITE_INT(lsr, 0, 2, "enum"); GF_LSR_WRITE_INT(lsr, 0, 2, "choice"); break; case SVG_PAINT_NONE: GF_LSR_WRITE_INT(lsr, 0, 2, "enum"); GF_LSR_WRITE_INT(lsr, 2, 2, "choice"); break; case SVG_PAINT_COLOR: if (paint->color.type == SVG_COLOR_CURRENTCOLOR) { GF_LSR_WRITE_INT(lsr, 0, 2, "enum"); GF_LSR_WRITE_INT(lsr, 1, 2, "choice"); } else { GF_LSR_WRITE_INT(lsr, 2, 2, "enum"); lsr_write_byte_align_string(lsr, (char*)gf_svg_get_system_paint_server_name(paint->color.type), "systemsPaint"); } break; case SVG_PAINT_URI: GF_LSR_WRITE_INT(lsr, 1, 2, "enum"); lsr_write_any_uri(lsr, &paint->iri, "uri"); break; default: GF_LSR_WRITE_INT(lsr, 3, 2, "enum"); lsr_write_extension(lsr, "ERROR", 5, "colorExType0"); break; } } } static void lsr_write_private_element_container(GF_LASeRCodec *lsr) { /*NO PRIVATE DATA ON ENCODING YET*/ assert(0); } static void lsr_write_private_att_class(GF_LASeRCodec *lsr) { /*NO PRIVATE DATA ON ENCODING YET*/ assert(0); } static void lsr_write_private_attr_container(GF_LASeRCodec *lsr, u32 index, const char *name) { assert(0); } static void lsr_write_any_attribute(GF_LASeRCodec *lsr, SVG_Element *node, Bool skippable) { if (1) { if (skippable) GF_LSR_WRITE_INT(lsr, 0, 1, "has_attrs"); } else { if (skippable) GF_LSR_WRITE_INT(lsr, 1, 1, "has_attrs"); /* do () { GF_LSR_WRITE_INT(lsr, 0, lsr->info->cfg.extensionIDBits, "reserved"); lsr_write_vluimsbf5(lsr, 0, "len");//len in BITS GF_LSR_WRITE_INT(lsr, 0, 0, "reserved_val"); } while () */ } } static void lsr_write_private_attributes(GF_LASeRCodec *lsr, SVG_Element *elt) { if (1) { GF_LSR_WRITE_INT(lsr, 0, 1, "has_private_attr"); } else { GF_LSR_WRITE_INT(lsr, 1, 1, "has_private_attr"); lsr_write_private_att_class(lsr); } } static void lsr_write_string_attribute(GF_LASeRCodec *lsr, char *class_attr, char *name) { if (class_attr) { GF_LSR_WRITE_INT(lsr, 1, 1, name); lsr_write_byte_align_string(lsr, class_attr, name); } else { GF_LSR_WRITE_INT(lsr, 0, 1, name); } } static void lsr_write_id(GF_LASeRCodec *lsr, GF_Node *n) { u32 id = gf_node_get_id(n); if (id) { GF_LSR_WRITE_INT(lsr, 1, 1, "has_id"); lsr_write_vluimsbf5(lsr, id-1, "ID"); #if TODO_LASER_EXTENSIONS if (0) { GF_LSR_WRITE_INT(lsr, 1, 1, "reserved"); lsr_write_vluimsbf5(lsr, reserved_len, "len"); GF_LSR_WRITE_INT(lsr, 0, reserved_len, "reserved"); } else #endif GF_LSR_WRITE_INT(lsr, 0, 1, "reserved"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "has_id"); } } static u32 lsr_translate_coords(GF_LASeRCodec *lsr, Fixed x, u32 nb_bits) { s32 res, max; res = FIX2INT( gf_divfix(x, lsr->res_factor) ); /*don't loose too much*/ if (!res && x) { GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] resolution factor %g too small to allow coding of %g - adjusting to smallest integer!\n", lsr->res_factor, FIX2FLT(x) )); res = (x>0) ? 1 : -1; } max = (1<<(nb_bits-1)) - 1; if (res>=0) { if (res > max) { GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] nb_bits %d not large enough to encode positive number %g!\n", nb_bits, FIX2FLT(x) )); res = max; } assert( ! (res & (1<<(nb_bits-1)) )); return (u32) res; } res += 1<<(nb_bits); if (res<=max){ GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] nb_bits %d not large enough to encode negative number %g!\n", nb_bits, FIX2FLT(x) )); res = max+1; } assert( res & (1<<(nb_bits-1)) ); return res; } static u32 lsr_translate_scale(GF_LASeRCodec *lsr, Fixed v) { s32 res; /*always 8 bits for fractional part*/ if (ABS(v) * 256 < 1) v = 0; v = v*256; if (v<0) { res = FIX2INT(v) + (1<coord_bits); if (res<0) GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[LASeR] nb_bits %d not large enough to encode negative number %d!\n", lsr->coord_bits, res)); return res; } res = FIX2INT(v); if (res & (1<<(lsr->coord_bits-1)) ) { GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[LASeR] nb_bits %d not large enough to encode positive number %d!\n", lsr->coord_bits, res)); } return res; } static void lsr_write_matrix(GF_LASeRCodec *lsr, SVG_Transform *mx) { u32 res; if (mx->is_ref) { GF_LSR_WRITE_INT(lsr, 1, 1, "isNotMatrix"); GF_LSR_WRITE_INT(lsr, 1, 1, "isRef"); GF_LSR_WRITE_INT(lsr, 1, 1, "hasXY"); lsr_write_fixed_16_8(lsr, mx->mat.m[2], "valueX"); lsr_write_fixed_16_8(lsr, mx->mat.m[5], "valueY"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "isNotMatrix"); lsr->coord_bits += lsr->scale_bits; if ((mx->mat.m[0]!=FIX_ONE) || (mx->mat.m[4]!=FIX_ONE)) { GF_LSR_WRITE_INT(lsr, 1, 1, "xx_yy_present"); res = lsr_translate_scale(lsr, mx->mat.m[0]); GF_LSR_WRITE_INT(lsr, res, lsr->coord_bits, "xx"); res = lsr_translate_scale(lsr, mx->mat.m[4]); GF_LSR_WRITE_INT(lsr, res, lsr->coord_bits, "yy"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "xx_yy_present"); } if (mx->mat.m[1] || mx->mat.m[3]) { GF_LSR_WRITE_INT(lsr, 1, 1, "xy_yx_present"); res = lsr_translate_scale(lsr, mx->mat.m[1]); GF_LSR_WRITE_INT(lsr, res, lsr->coord_bits, "xy"); res = lsr_translate_scale(lsr, mx->mat.m[3]); GF_LSR_WRITE_INT(lsr, res, lsr->coord_bits, "yx"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "xy_yx_present"); } lsr->coord_bits -= lsr->scale_bits; if (mx->mat.m[2] || mx->mat.m[5]) { GF_LSR_WRITE_INT(lsr, 1, 1, "xz_yz_present"); res = lsr_translate_coords(lsr, mx->mat.m[2], lsr->coord_bits); GF_LSR_WRITE_INT(lsr, res, lsr->coord_bits, "xz"); res = lsr_translate_coords(lsr, mx->mat.m[5], lsr->coord_bits); GF_LSR_WRITE_INT(lsr, res, lsr->coord_bits, "yz"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "xz_yz_present"); } } } static void lsr_write_fixed_clamp(GF_LASeRCodec *lsr, Fixed f, const char *name) { #ifdef GPAC_FIXED_POINT s32 val = f >> 8; #else s32 val = (u32) (255 * f); #endif if (val<0) val = 0; else if (val>255) val = 255; GF_LSR_WRITE_INT(lsr, (u32) val, 8, name); } static u32 dom_to_lsr_key(u32 dom_k) { switch (dom_k) { case GF_KEY_STAR: return 0; case GF_KEY_0: return 1; case GF_KEY_1: return 2; case GF_KEY_2: return 3; case GF_KEY_3: return 4; case GF_KEY_4: return 5; case GF_KEY_5: return 6; case GF_KEY_6: return 7; case GF_KEY_7: return 8; case GF_KEY_8: return 9; case GF_KEY_9: return 10; case GF_KEY_DOWN: return 12; case GF_KEY_LEFT: return 14; case GF_KEY_RIGHT: return 16; case GF_KEY_UP: return 20; /*WHAT IS ANY_KEY (11) ??*/ case GF_KEY_ENTER: case GF_KEY_EXECUTE: return 13; case GF_KEY_ESCAPE: return 15; case GF_KEY_NUMBER: return 17; case GF_KEY_CELL_SOFT1: return 18; case GF_KEY_CELL_SOFT2: return 19; default: return 100; } } static void lsr_write_event_type(GF_LASeRCodec *lsr, u32 evtType, u32 evtParam) { Bool force_string = 0; switch (evtType) { case GF_EVENT_KEYDOWN: case GF_EVENT_LONGKEYPRESS: case GF_EVENT_REPEAT_KEY: case GF_EVENT_SHORT_ACCESSKEY: if (dom_to_lsr_key(evtParam)==100) force_string = 2; break; case GF_EVENT_BEGIN: case GF_EVENT_END: force_string = 1; break; case GF_EVENT_REPEAT: force_string = 1; break; } if (force_string) { char szName[1024]; GF_LSR_WRITE_INT(lsr, 0, 1, "choice"); if (evtParam) { if (force_string==2) { sprintf(szName, "%s(%s)", gf_dom_event_get_name(evtType), gf_dom_get_key_name(evtParam) ); } else { sprintf(szName, "%s(%d)", gf_dom_event_get_name(evtType), evtParam); } } else { sprintf(szName, "%s", gf_dom_event_get_name(evtType)); } lsr_write_byte_align_string(lsr, szName, "evtString"); } else { GF_LSR_WRITE_INT(lsr, 1, 1, "choice"); switch (evtType) { case GF_EVENT_ABORT: GF_LSR_WRITE_INT(lsr, LSR_EVT_abort, 6, "event"); break; case GF_EVENT_ACTIVATE: GF_LSR_WRITE_INT(lsr, LSR_EVT_activate, 6, "event"); break; case GF_EVENT_ACTIVATED: GF_LSR_WRITE_INT(lsr, LSR_EVT_activatedEvent, 6, "event"); break; case GF_EVENT_BEGIN:/*SPEC IS BROKEN, CANNOT ENCODE elt.begin !! */ case GF_EVENT_BEGIN_EVENT: GF_LSR_WRITE_INT(lsr, LSR_EVT_beginEvent, 6, "event"); break; case GF_EVENT_CLICK: GF_LSR_WRITE_INT(lsr, LSR_EVT_click, 6, "event"); break; case GF_EVENT_DEACTIVATED: GF_LSR_WRITE_INT(lsr, LSR_EVT_deactivatedEvent, 6, "event"); break; case GF_EVENT_END:/*SPEC IS BROKEN, CANNOT ENCODE elt.end !! */ case GF_EVENT_END_EVENT: GF_LSR_WRITE_INT(lsr, LSR_EVT_endEvent, 6, "event"); break; case GF_EVENT_ERROR: GF_LSR_WRITE_INT(lsr, LSR_EVT_error, 6, "event"); break; case GF_EVENT_EXECUTION_TIME: GF_LSR_WRITE_INT(lsr, LSR_EVT_executionTime, 6, "event"); break; case GF_EVENT_FOCUSIN: GF_LSR_WRITE_INT(lsr, LSR_EVT_focusin, 6, "event"); break; case GF_EVENT_FOCUSOUT: GF_LSR_WRITE_INT(lsr, LSR_EVT_focusout, 6, "event"); break; case GF_EVENT_KEYDOWN: /*encode as accessKey() if param*/ GF_LSR_WRITE_INT(lsr, evtParam ? LSR_EVT_accessKey : LSR_EVT_keydown, 6, "event"); break; case GF_EVENT_KEYUP: GF_LSR_WRITE_INT(lsr, LSR_EVT_keyup, 6, "event"); break; case GF_EVENT_LOAD: GF_LSR_WRITE_INT(lsr, LSR_EVT_load, 6, "event"); break; case GF_EVENT_LONGKEYPRESS: GF_LSR_WRITE_INT(lsr, LSR_EVT_longAccessKey, 6, "event"); break; case GF_EVENT_MOUSEDOWN: GF_LSR_WRITE_INT(lsr, LSR_EVT_mousedown, 6, "event"); break; case GF_EVENT_MOUSEMOVE: GF_LSR_WRITE_INT(lsr, LSR_EVT_mousemove, 6, "event"); break; case GF_EVENT_MOUSEOUT: GF_LSR_WRITE_INT(lsr, LSR_EVT_mouseout, 6, "event"); break; case GF_EVENT_MOUSEOVER: GF_LSR_WRITE_INT(lsr, LSR_EVT_mouseover, 6, "event"); break; case GF_EVENT_MOUSEUP: GF_LSR_WRITE_INT(lsr, LSR_EVT_mouseup, 6, "event"); break; case GF_EVENT_PAUSE: GF_LSR_WRITE_INT(lsr, LSR_EVT_pause, 6, "event"); break; case GF_EVENT_PAUSED_EVENT: GF_LSR_WRITE_INT(lsr, LSR_EVT_pausedEvent, 6, "event"); break; case GF_EVENT_PLAY: GF_LSR_WRITE_INT(lsr, LSR_EVT_play, 6, "event"); break; case GF_EVENT_REPEAT_EVENT: GF_LSR_WRITE_INT(lsr, LSR_EVT_repeatEvent, 6, "event"); break; case GF_EVENT_REPEAT_KEY: GF_LSR_WRITE_INT(lsr, LSR_EVT_repeatKey, 6, "event"); break; case GF_EVENT_RESIZE: GF_LSR_WRITE_INT(lsr, LSR_EVT_resize, 6, "event"); break; case GF_EVENT_RESUME_EVENT: GF_LSR_WRITE_INT(lsr, LSR_EVT_resumedEvent, 6, "event"); break; case GF_EVENT_SCROLL: GF_LSR_WRITE_INT(lsr, LSR_EVT_scroll, 6, "event"); break; case GF_EVENT_SHORT_ACCESSKEY: GF_LSR_WRITE_INT(lsr, LSR_EVT_shortAccessKey, 6, "event"); break; case GF_EVENT_TEXTINPUT: GF_LSR_WRITE_INT(lsr, LSR_EVT_textinput, 6, "event"); break; case GF_EVENT_UNLOAD: GF_LSR_WRITE_INT(lsr, LSR_EVT_unload, 6, "event"); break; case GF_EVENT_ZOOM: GF_LSR_WRITE_INT(lsr, LSR_EVT_zoom, 6, "event"); break; default: GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] Unsupported LASER event %d\n", evtType) ); GF_LSR_WRITE_INT(lsr, 0, 6, "event"); break; return; } switch (evtType) { case GF_EVENT_KEYDOWN: if (!evtParam) break; case GF_EVENT_LONGKEYPRESS: case GF_EVENT_REPEAT_KEY: case GF_EVENT_SHORT_ACCESSKEY: lsr_write_vluimsbf5(lsr, dom_to_lsr_key(evtParam), "keyCode"); break; } } } static void lsr_write_smil_time(GF_LASeRCodec *lsr, SMIL_Time *t) { s32 now; if (t->type==GF_SMIL_TIME_EVENT) { GF_LSR_WRITE_INT(lsr, 1, 1, "hasEvent"); if (t->element && gf_node_get_id((GF_Node*)t->element) ) { XMLRI iri; GF_LSR_WRITE_INT(lsr, 1, 1, "hasIdentifier"); iri.string = NULL; iri.type = XMLRI_ELEMENTID; iri.target = t->element; lsr_write_codec_IDREF(lsr, &iri, "idref"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "hasIdentifier"); } lsr_write_event_type(lsr, t->event.type, t->event.parameter); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "hasEvent"); } if (!t->clock) { GF_LSR_WRITE_INT(lsr, 0, 1, "hasClock"); return; } GF_LSR_WRITE_INT(lsr, 1, 1, "hasClock"); now = (s32) (t->clock * lsr->time_resolution); if (now<0) { now = -now; GF_LSR_WRITE_INT(lsr, 1, 1, "sign"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "sign"); } lsr_write_vluimsbf5(lsr, now, "value"); } static void lsr_write_smil_times(GF_LASeRCodec *lsr, GF_List **l, const char *name, Bool skipable) { SMIL_Time *v; u32 r_count, i, count; Bool indef = 0; count = l ? gf_list_count(*l) : 0; r_count = 0; for (i=0; itype==GF_SMIL_TIME_INDEFINITE) { indef = 1; break; } else if (v->type!=GF_SMIL_TIME_EVENT_RESOLVED) r_count++; } if (skipable && !r_count && !indef) { GF_LSR_WRITE_INT(lsr, 0, 1, name); return; } if (skipable) GF_LSR_WRITE_INT(lsr, 1, 1, name); GF_LSR_WRITE_INT(lsr, indef, 1, "choice"); if (indef) return; lsr_write_vluimsbf5(lsr, r_count, "count"); for (i=0; itype) { GF_LSR_WRITE_INT(lsr, 0, 1, name); return; } GF_LSR_WRITE_INT(lsr, 1, 1, name); } if (v->type==SMIL_DURATION_DEFINED) { s32 now = (s32) (v->clock_value * lsr->time_resolution); GF_LSR_WRITE_INT(lsr, 0, 1, "choice"); GF_LSR_WRITE_INT(lsr, (now<0) ? 1 : 0, 1, "sign"); if (now<0) now = -now; lsr_write_vluimsbf5(lsr, now, "value"); } else { GF_LSR_WRITE_INT(lsr, 1, 1, "choice"); GF_LSR_WRITE_INT(lsr, v->type, 2, "time"); } } #define lsr_write_duration(a, b, c) lsr_write_duration_ex(a, b, c, 1) static void lsr_write_focus(GF_LASeRCodec *lsr, SVG_Focus *foc, const char *name) { if (foc->type==SVG_FOCUS_IRI) { GF_LSR_WRITE_INT(lsr, 0, 1, "isEnum"); lsr_write_codec_IDREF(lsr, &foc->target, "id"); } else { GF_LSR_WRITE_INT(lsr, 1, 1, "isEnum"); GF_LSR_WRITE_INT(lsr, foc->type, 1, "enum"); } } static Bool lsr_elt_has_same_base(GF_LASeRCodec *lsr, SVGAllAttributes *atts, SVG_Element *base, Bool *same_fill, Bool *same_stroke, Bool no_stroke_check) { SVGAllAttributes base_atts; GF_FieldInfo info, base_info; if (same_stroke) *same_stroke = 0; if (same_fill) *same_fill = 0; if (!base) return 0; gf_svg_flatten_attributes(base, &base_atts); if (atts->externalResourcesRequired != base_atts.externalResourcesRequired) return 0; info.fieldType = base_info.fieldType = SVG_Paint_datatype; info.far_ptr = atts->stroke; base_info.far_ptr = base_atts.stroke; /*check stroke color*/ if (!gf_svg_attributes_equal(&info, &base_info)) { if (!no_stroke_check) return 0; } else { if (same_stroke) *same_stroke = 1; } if (same_fill) { info.fieldType = base_info.fieldType = SVG_Paint_datatype; info.far_ptr = atts->fill; base_info.far_ptr = base_atts.fill; /*check stroke color*/ *same_fill = gf_svg_attributes_equal(&info, &base_info) ? 1 : 0; } switch (gf_node_get_tag((GF_Node*) base)) { /*check path length*/ case TAG_SVG_path: info.fieldType = base_info.fieldType = SVG_Number_datatype; info.far_ptr = atts->pathLength; base_info.far_ptr = base_atts.pathLength; if (!gf_svg_attributes_equal(&info, &base_info)) return 0; break; /*check rx and ry for rect*/ case TAG_SVG_rect: info.fieldType = base_info.fieldType = SVG_Length_datatype; info.far_ptr = atts->rx; base_info.far_ptr = base_atts.rx; if (!gf_svg_attributes_equal(&info, &base_info)) return 0; info.fieldType = base_info.fieldType = SVG_Length_datatype; info.far_ptr = atts->ry; base_info.far_ptr = base_atts.ry; if (!gf_svg_attributes_equal(&info, &base_info)) return 0; break; /*check x and y for use*/ case TAG_SVG_use: info.fieldType = base_info.fieldType = SVG_Coordinate_datatype; info.far_ptr = atts->x; base_info.far_ptr = base_atts.x; if (!gf_svg_attributes_equal(&info, &base_info)) return 0; info.fieldType = base_info.fieldType = SVG_Coordinate_datatype; info.far_ptr = atts->y; base_info.far_ptr = base_atts.y; if (!gf_svg_attributes_equal(&info, &base_info)) return 0; break; /*check editable and rotate for text*/ case TAG_SVG_text: info.fieldType = base_info.fieldType = SVG_Boolean_datatype; info.far_ptr = atts->editable; base_info.far_ptr = base_atts.editable; if (!gf_svg_attributes_equal(&info, &base_info)) return 0; info.fieldType = base_info.fieldType = SVG_Numbers_datatype; info.far_ptr = atts->text_rotate; base_info.far_ptr = base_atts.text_rotate; if (!gf_svg_attributes_equal(&info, &base_info)) return 0; break; } return gf_lsr_same_rare(atts, &base_atts); } static Bool lsr_float_list_equal(GF_List *l1, GF_List *l2) { u32 i, count = gf_list_count(l1); if (count != gf_list_count(l2)) return 0; for (i=0;iattributes; while (att) { field_rare = gf_lsr_rare_type_from_attribute(att->tag); if (field_rare>=0) nb_rare++; att = att->next; } GF_LSR_WRITE_INT(lsr, nb_rare ? 1 : 0, 1, "has_rare"); if (!nb_rare) return; GF_LSR_WRITE_INT(lsr, nb_rare, 6, "nbOfAttributes"); att = ((SVG_Element*)n)->attributes; while (att) { field_rare = gf_lsr_rare_type_from_attribute(att->tag); if (field_rare==-1) { att = att->next; continue; } /*RARE extension*/ if (field_rare==49) { Bool is_string = 0; u32 size, cur_bits; u32 len = 2+3; switch (att->tag) { case TAG_SVG_ATT_syncMaster: len +=1; break; case TAG_SVG_ATT_requiredFonts: len += 8*strlen(*(SVG_String*)att->data); /*get vluimsbf5 field size with one extra word (4 bits, enough to code string alignment)*/ size = lsr_get_vluimsbf5_size(len, 1); cur_bits = gf_bs_get_bit_position(lsr->bs) + lsr->info->cfg.extensionIDBits + size + 5; /*count string alignment*/ while (cur_bits%8) { len++; cur_bits++; } is_string = 1; break; default: len +=2; break; } GF_LSR_WRITE_INT(lsr, 49, 6, "attributeRARE"); GF_LSR_WRITE_INT(lsr, 2, lsr->info->cfg.extensionIDBits, "extensionID"); if (is_string) { lsr_write_vluimsbf5_ex(lsr, len, 1, "len"); } else { lsr_write_vluimsbf5(lsr, len, "len"); } GF_LSR_WRITE_INT(lsr, 1, 2, "nbOfAttributes"); switch (att->tag) { case TAG_SVG_ATT_syncMaster: GF_LSR_WRITE_INT(lsr, 0, 3, "attributeRARE"); GF_LSR_WRITE_INT(lsr, *(SVG_Boolean *)att->data ? 1 : 0, 1, "syncMaster"); break; case TAG_SVG_ATT_focusHighlight: GF_LSR_WRITE_INT(lsr, 1, 3, "attributeRARE"); GF_LSR_WRITE_INT(lsr, *(SVG_FocusHighlight*)att->data, 2, "focusHighlight"); break; case TAG_SVG_ATT_initialVisibility: GF_LSR_WRITE_INT(lsr, 2, 3, "attributeRARE"); GF_LSR_WRITE_INT(lsr, *(SVG_InitialVisibility*)att->data, 2, "initialVisibility"); break; case TAG_SVG_ATT_fullscreen: GF_LSR_WRITE_INT(lsr, 3, 3, "attributeRARE"); GF_LSR_WRITE_INT(lsr, *(SVG_Boolean *)att->data ? 1 : 0, 2, "fullscreen"); break; case TAG_SVG_ATT_requiredFonts: GF_LSR_WRITE_INT(lsr, 4, 3, "attributeRARE"); lsr_write_byte_align_string(lsr, *(SVG_String*)att->data, "requiredFonts"); break; } GF_LSR_WRITE_INT(lsr, 0, 1, "hasNextExtension"); att = att->next; continue; } GF_LSR_WRITE_INT(lsr, (u32)field_rare, 6, "attributeRARE"); switch (att->tag) { case TAG_SVG_ATT__class: lsr_write_byte_align_string(lsr, *(SVG_String *)att->data, "class"); break; case TAG_SVG_ATT_audio_level: lsr_write_fixed_clamp(lsr, ((SVG_Number *) att->data)->value, "audio-level"); break; case TAG_SVG_ATT_color: lsr_write_paint(lsr, (SVG_Paint*) att->data, "color"); break; case TAG_SVG_ATT_color_rendering: GF_LSR_WRITE_INT(lsr, *(SVG_RenderingHint*)att->data, 2, "color-rendering"); break; case TAG_SVG_ATT_display: GF_LSR_WRITE_INT(lsr, *(SVG_Display*)att->data, 5, "display"); break; case TAG_SVG_ATT_display_align: GF_LSR_WRITE_INT(lsr, *(SVG_DisplayAlign*)att->data, 3, "display-align"); break; case TAG_SVG_ATT_fill_opacity: lsr_write_fixed_clamp(lsr, ((SVG_Number *)att->data)->value, "fill-opacity"); break; case TAG_SVG_ATT_fill_rule: GF_LSR_WRITE_INT(lsr, *(SVG_FillRule*)att->data, 2, "fill-rule"); break; case TAG_SVG_ATT_image_rendering: GF_LSR_WRITE_INT(lsr, *(SVG_RenderingHint*)att->data, 2, "image-rendering"); break; case TAG_SVG_ATT_line_increment: lsr_write_line_increment_type(lsr, (SVG_Number*)att->data, "lineIncrement"); break; case TAG_SVG_ATT_pointer_events: GF_LSR_WRITE_INT(lsr, *(SVG_PointerEvents*)att->data, 4, "pointer-events"); break; case TAG_SVG_ATT_shape_rendering: GF_LSR_WRITE_INT(lsr, *(SVG_RenderingHint*)att->data, 3, "shape-rendering"); break; case TAG_SVG_ATT_solid_color: lsr_write_paint(lsr, (SVG_Paint*)att->data, "solid-color"); break; case TAG_SVG_ATT_solid_opacity: lsr_write_fixed_clamp(lsr, ((SVG_Number *)att->data)->value, "solid-opacity"); break; case TAG_SVG_ATT_stop_color: lsr_write_paint(lsr, (SVG_Paint*)att->data, "stop-color"); break; case TAG_SVG_ATT_stop_opacity: lsr_write_fixed_clamp(lsr, ((SVG_Number *)att->data)->value, "stop-opacity"); break; case TAG_SVG_ATT_stroke_dasharray: { u32 j; SVG_StrokeDashArray *da = (SVG_StrokeDashArray*)att->data; if (da->type==SVG_STROKEDASHARRAY_INHERIT) { GF_LSR_WRITE_INT(lsr, 1, 1, "dashArray"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "dashArray"); lsr_write_vluimsbf5(lsr, da->array.count, "len"); for (j=0; jarray.count; j++) { lsr_write_fixed_16_8(lsr, da->array.vals[j], "dash"); } } } break; case TAG_SVG_ATT_stroke_dashoffset: lsr_write_fixed_16_8i(lsr, (SVG_Number*)att->data, "dashOffset"); break; case TAG_SVG_ATT_stroke_linecap: GF_LSR_WRITE_INT(lsr, *(SVG_StrokeLineCap*)att->data, 2, "stroke-linecap"); break; case TAG_SVG_ATT_stroke_linejoin: GF_LSR_WRITE_INT(lsr, *(SVG_StrokeLineJoin*)att->data, 2, "stroke-linejoin"); break; case TAG_SVG_ATT_stroke_miterlimit: lsr_write_fixed_16_8i(lsr, (SVG_Number*)att->data, "miterLimit"); break; case TAG_SVG_ATT_stroke_opacity: lsr_write_fixed_clamp(lsr, ((SVG_Number *)att->data)->value, "stroke-opacity"); break; case TAG_SVG_ATT_stroke_width: lsr_write_fixed_16_8i(lsr, (SVG_Number*)att->data, "strokeWidth"); break; case TAG_SVG_ATT_text_anchor: GF_LSR_WRITE_INT(lsr, *(SVG_TextAnchor*)att->data, 2, "text-achor"); break; case TAG_SVG_ATT_text_rendering: GF_LSR_WRITE_INT(lsr, *(SVG_RenderingHint*)att->data, 3, "text-rendering"); break; case TAG_SVG_ATT_viewport_fill: lsr_write_paint(lsr, (SVG_Paint*)att->data, "viewport-fill"); break; case TAG_SVG_ATT_viewport_fill_opacity: lsr_write_fixed_clamp(lsr, ((SVG_Number *)att->data)->value, "viewport-fill-opacity"); break; case TAG_SVG_ATT_vector_effect: GF_LSR_WRITE_INT(lsr, *(SVG_VectorEffect*)att->data, 4, "vector-effect"); break; case TAG_SVG_ATT_visibility: GF_LSR_WRITE_INT(lsr, *(SVG_PointerEvents*)att->data, 2, "visibility"); break; case TAG_SVG_ATT_requiredExtensions: lsr_write_byte_align_string_list(lsr, *(GF_List **)att->data, "requiredExtensions", 1); break; case TAG_SVG_ATT_requiredFormats: lsr_write_byte_align_string_list(lsr, *(GF_List **)att->data, "requiredFormats", 0); break; case TAG_SVG_ATT_requiredFeatures: { GF_List *l = *(GF_List **)att->data; u32 j, tot_count, count = gf_list_count(l); u8 *vals = (u8*)malloc(sizeof(u8)*count); tot_count = 0; for (i=0; itype != XMLRI_STRING) continue; ext = strchr(iri->string, '#'); if (!ext) continue; if (!stricmp(ext, "Animation")) { vals[tot_count] = 0; tot_count++; } else if (!stricmp(ext, "Audio")) { vals[tot_count] = 1; tot_count++; } else if (!stricmp(ext, "ComposedVideo")) { vals[tot_count] = 2; tot_count++; } else if (!stricmp(ext, "ConditionalProcessing")) { vals[tot_count] = 3; tot_count++; } else if (!stricmp(ext, "ConditionalProcessingAttribute")) { vals[tot_count] = 4; tot_count++; } else if (!stricmp(ext, "CoreAttribute")) { vals[tot_count] = 5; tot_count++; } else if (!stricmp(ext, "Extensibility")) { vals[tot_count] = 6; tot_count++; } else if (!stricmp(ext, "ExternalResourcesRequired")) { vals[tot_count] = 7; tot_count++; } else if (!stricmp(ext, "Font")) { vals[tot_count] = 8; tot_count++; } else if (!stricmp(ext, "Gradient")) { vals[tot_count] = 9; tot_count++; } else if (!stricmp(ext, "GraphicsAttribute")) { vals[tot_count] = 10; tot_count++; } else if (!stricmp(ext, "Handler")) { vals[tot_count] = 11; tot_count++; } else if (!stricmp(ext, "Hyperlinking")) { vals[tot_count] = 12; tot_count++; } else if (!stricmp(ext, "Image")) { vals[tot_count] = 13; tot_count++; } else if (!stricmp(ext, "OpacityAttribute")) { vals[tot_count] = 14; tot_count++; } else if (!stricmp(ext, "PaintAttribute")) { vals[tot_count] = 15; tot_count++; } else if (!stricmp(ext, "Prefetch")) { vals[tot_count] = 16; tot_count++; } else if (!stricmp(ext, "SVG")) { vals[tot_count] = 17; tot_count++; } else if (!stricmp(ext, "SVG-animation")) { vals[tot_count] = 18; tot_count++; } else if (!stricmp(ext, "SVG-dynamic")) { vals[tot_count] = 19; tot_count++; } else if (!stricmp(ext, "SVG-static")) { vals[tot_count] = 20; tot_count++; } else if (!stricmp(ext, "SVGDOM")) { vals[tot_count] = 21; tot_count++; } else if (!stricmp(ext, "SVGDOM-animation")) { vals[tot_count] = 22; tot_count++; } else if (!stricmp(ext, "SVGDOM-dynamic")) { vals[tot_count] = 23; tot_count++; } else if (!stricmp(ext, "SVGDOM-static")) { vals[tot_count] = 24; tot_count++; } else if (!stricmp(ext, "Script")) { vals[tot_count] = 25; tot_count++; } else if (!stricmp(ext, "Shape")) { vals[tot_count] = 26; tot_count++; } else if (!stricmp(ext, "SolidColor")) { vals[tot_count] = 27; tot_count++; } else if (!stricmp(ext, "Structure")) { vals[tot_count] = 28; tot_count++; } else if (!stricmp(ext, "Text")) { vals[tot_count] = 29; tot_count++; } else if (!stricmp(ext, "TimedAnimation")) { vals[tot_count] = 30; tot_count++; } else if (!stricmp(ext, "TransformedVideo")) { vals[tot_count] = 31; tot_count++; } else if (!stricmp(ext, "Video")) { vals[tot_count] = 32; tot_count++; } else if (!stricmp(ext, "XlinkAttribute")) { vals[tot_count] = 33; tot_count++; } } lsr_write_vluimsbf5(lsr, tot_count, "len"); for (j=0; jdata, "systemLanguage", 0); break; case TAG_SVG_ATT_xml_base: lsr_write_byte_align_string(lsr, ((XMLRI*)att->data)->string, "xml:base"); break; case TAG_SVG_ATT_xml_lang: lsr_write_byte_align_string(lsr, *(SVG_String *)att->data, "xml:lang"); break; case TAG_SVG_ATT_xml_space: GF_LSR_WRITE_INT(lsr, *(XML_Space *)att->data, 1, "xml:space"); break; case TAG_SVG_ATT_nav_next: lsr_write_focus(lsr, (SVG_Focus*)att->data, "focusNext"); break; case TAG_SVG_ATT_nav_up: lsr_write_focus(lsr, (SVG_Focus*)att->data, "focusNorth"); break; case TAG_SVG_ATT_nav_up_left: lsr_write_focus(lsr, (SVG_Focus*)att->data, "focusNorthEast"); break; case TAG_SVG_ATT_nav_up_right: lsr_write_focus(lsr, (SVG_Focus*)att->data, "focusNorthWest"); break; case TAG_SVG_ATT_nav_prev: lsr_write_focus(lsr, (SVG_Focus*)att->data, "focusPrev"); break; case TAG_SVG_ATT_nav_down: lsr_write_focus(lsr, (SVG_Focus*)att->data, "focusSouth"); break; case TAG_SVG_ATT_nav_down_left: lsr_write_focus(lsr, (SVG_Focus*)att->data, "focusSouthEast"); break; case TAG_SVG_ATT_nav_down_right: lsr_write_focus(lsr, (SVG_Focus*)att->data, "focusSouthWest"); break; case TAG_SVG_ATT_nav_right: lsr_write_focus(lsr, (SVG_Focus*)att->data, "focusWest"); break; case TAG_SVG_ATT_nav_left: lsr_write_focus(lsr, (SVG_Focus*)att->data, "focusEast"); break; case TAG_SVG_ATT_font_variant: GF_LSR_WRITE_INT(lsr, *(SVG_FontVariant *)att->data, 2, "font-variant"); break; case TAG_SVG_ATT_font_family: { s32 idx = lsr_get_font_index(lsr, (SVG_FontFamily*)att->data); if (idx<0) { GF_LSR_WRITE_INT(lsr, 1, 1, "isInherit"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "isInherit"); GF_LSR_WRITE_INT(lsr, idx, lsr->fontIndexBits, "fontIndex"); } } break; case TAG_SVG_ATT_font_size: lsr_write_fixed_16_8i(lsr, (SVG_Number*)att->data, "fontSize"); break; case TAG_SVG_ATT_font_style: GF_LSR_WRITE_INT(lsr, *((SVG_FontStyle *)att->data), 3, "fontStyle"); break; case TAG_SVG_ATT_font_weight: GF_LSR_WRITE_INT(lsr, *((SVG_FontWeight *)att->data), 4, "fontWeight"); break; case TAG_SVG_ATT_xlink_title: lsr_write_byte_align_string(lsr, *(SVG_String *)att->data, "xlink:title"); break; /*TODO FIXME*/ case TAG_SVG_ATT_xlink_type: GF_LSR_WRITE_INT(lsr, 0, 3, "xlink:type"); break; case TAG_SVG_ATT_xlink_role: lsr_write_any_uri(lsr, (XMLRI*)att->data, "xlink:role"); break; case TAG_SVG_ATT_xlink_arcrole: lsr_write_any_uri(lsr, (XMLRI*)att->data, "xlink:arcrole"); break; /*TODO FIXME*/ case TAG_SVG_ATT_xlink_actuate: GF_LSR_WRITE_INT(lsr, 0, 2, "xlink:actuate"); break; case TAG_SVG_ATT_xlink_show: GF_LSR_WRITE_INT(lsr, 0, 3, "xlink:show"); break; case TAG_SVG_ATT_end: lsr_write_smil_times(lsr, (GF_List **)att->data, "end", 0); break; case TAG_SVG_ATT_min: lsr_write_duration_ex(lsr, (SMIL_Duration*)att->data, "min", 0); break; case TAG_SVG_ATT_max: lsr_write_duration_ex(lsr, (SMIL_Duration*)att->data, "max", 0); break; case TAG_SVG_ATT_transform: lsr_write_matrix(lsr, (SVG_Transform*)att->data); break; } att = att->next; } } static void lsr_write_fill(GF_LASeRCodec *lsr, SVG_Element *n, SVGAllAttributes *atts) { if (atts->fill) { GF_LSR_WRITE_INT(lsr, 1, 1, "fill"); lsr_write_paint(lsr, atts->fill, "fill"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "fill"); } } static void lsr_write_stroke(GF_LASeRCodec *lsr, SVG_Element *n, SVGAllAttributes *atts) { if (atts->stroke) { GF_LSR_WRITE_INT(lsr, 1, 1, "has_stroke"); lsr_write_paint(lsr, atts->stroke, "stroke"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "has_stroke"); } } static void lsr_write_href(GF_LASeRCodec *lsr, XMLRI *iri) { Bool has_href = iri ? 1 : 0; if (iri) { if (iri->type==XMLRI_ELEMENTID) { if (!iri->target && iri->string) iri->target = (SVG_Element *)gf_sg_find_node_by_name(lsr->sg, iri->string+1); if (!iri->target || !gf_node_get_id((GF_Node *)iri->target)) has_href = 0; } else if (iri->type==XMLRI_STREAMID) { if (!iri->lsr_stream_id) has_href = 0; } else if (!iri->string) has_href = 0; } GF_LSR_WRITE_INT(lsr, has_href, 1, "has_href"); if (has_href) lsr_write_any_uri(lsr, iri, "href"); } static void lsr_write_accumulate(GF_LASeRCodec *lsr, SMIL_Accumulate *accum_type) { GF_LSR_WRITE_INT(lsr, accum_type ? 1 : 0, 1, "has_accumulate"); if (accum_type) GF_LSR_WRITE_INT(lsr, *accum_type, 1, "accumulate"); } static void lsr_write_additive(GF_LASeRCodec *lsr, SMIL_Additive *add_type) { GF_LSR_WRITE_INT(lsr, add_type ? 1 : 0, 1, "has_additive"); if (add_type) GF_LSR_WRITE_INT(lsr, *add_type, 1, "additive"); } static void lsr_write_calc_mode(GF_LASeRCodec *lsr, u8 *calc_mode) { /*SMIL_CALCMODE_LINEAR is default and 0 in our code*/ GF_LSR_WRITE_INT(lsr, (!calc_mode || (*calc_mode==SMIL_CALCMODE_LINEAR)) ? 0 : 1, 1, "has_calcMode"); if (calc_mode && (*calc_mode!=SMIL_CALCMODE_LINEAR)) { GF_LSR_WRITE_INT(lsr, *calc_mode, 2, "calcMode"); } } static void lsr_write_animatable(GF_LASeRCodec *lsr, SMIL_AttributeName *anim_type, XMLRI *iri, const char *name) { s32 a_type = -1; if (!anim_type || !iri || !iri->target) { GF_LSR_WRITE_INT(lsr, 0, 1, "hasAttributeName"); return; } /*locate field - checkme, this may not work since anim is not setup...*/ assert(anim_type->name || anim_type->tag); if (!anim_type->tag) anim_type->tag = gf_svg_get_attribute_tag(((GF_Node*)iri->target)->sgprivate->tag, anim_type->name); if (!anim_type->type) anim_type->type = gf_svg_get_attribute_type(anim_type->tag); a_type = gf_lsr_anim_type_from_attribute(anim_type->tag); if (a_type<0) { GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] Unsupported attributeName %s\n", anim_type->name)); } GF_LSR_WRITE_INT(lsr, 1, 1, "hasAttributeName"); GF_LSR_WRITE_INT(lsr, 0, 1, "choice"); GF_LSR_WRITE_INT(lsr, (u8) a_type, 8, "attributeType"); } static void lsr_write_anim_fill(GF_LASeRCodec *lsr, u8 *animFreeze) { GF_LSR_WRITE_INT(lsr, animFreeze ? 1 : 0, 1, "has_smil_fill"); if (animFreeze) GF_LSR_WRITE_INT(lsr, *animFreeze, 1, "smil_fill"); } static void lsr_write_anim_repeat(GF_LASeRCodec *lsr, SMIL_RepeatCount *repeat) { GF_LSR_WRITE_INT(lsr, repeat ? 1 : 0, 1, "has_repeatCount"); if (!repeat) return; if (repeat->type==SMIL_REPEATCOUNT_DEFINED) { GF_LSR_WRITE_INT(lsr, 0, 1, "repeatCount"); lsr_write_fixed_16_8(lsr, repeat->count, "repeatCount"); } else { GF_LSR_WRITE_INT(lsr, 1, 1, "repeatCount"); /*enumeration indefinite{0}*/ } } static void lsr_write_repeat_duration(GF_LASeRCodec *lsr, SMIL_Duration *smil) { GF_LSR_WRITE_INT(lsr, smil ? 1 : 0, 1, "has_repeatDur"); if (!smil) return; if (smil->type==SMIL_DURATION_DEFINED) { u32 now = (u32) (smil->clock_value * lsr->time_resolution); GF_LSR_WRITE_INT(lsr, 0, 1, "choice"); lsr_write_vluimsbf5(lsr, now, "value"); } else { GF_LSR_WRITE_INT(lsr, 1, 1, "choice"); /*enumeration indefinite{0}*/ } } static void lsr_write_anim_restart(GF_LASeRCodec *lsr, u8 *animRestart) { GF_LSR_WRITE_INT(lsr, animRestart ? 1 : 0, 1, "has_restart"); /*enumeration always{0} never{1} whenNotActive{2}*/ if (animRestart) GF_LSR_WRITE_INT(lsr, *animRestart, 2, "restart"); } static u32 svg_type_to_lsr_anim(u32 svg_type, u32 transform_type, GF_List *vals, void *a_val) { switch (svg_type) { /*all string types*/ case SVG_String_datatype: return 0; /*all length types*/ case SVG_Number_datatype: case SVG_FontSize_datatype: case SVG_Length_datatype: case SVG_Coordinate_datatype: return 1; case SVG_PathData_datatype: return 2; /*list of points*/ case SMIL_KeyPoints_datatype: case SVG_Points_datatype: return 3; /*all 0 - 1 types*/ /* case SVG_Opacity_datatype: return 4; */ case SVG_Paint_datatype: return 5; /*all enums (u8) types*/ case SVG_FillRule_datatype: case SVG_StrokeLineJoin_datatype: case SVG_StrokeLineCap_datatype: case SVG_FontStyle_datatype: case SVG_FontWeight_datatype: case SVG_FontVariant_datatype: case SVG_TextAnchor_datatype: case SVG_TransformType_datatype: case SVG_Display_datatype: case SVG_Visibility_datatype: case SVG_Overflow_datatype: case SVG_ZoomAndPan_datatype: case SVG_DisplayAlign_datatype: case SVG_TextAlign_datatype: case SVG_PointerEvents_datatype: case SVG_RenderingHint_datatype: case SVG_VectorEffect_datatype: case SVG_PlaybackOrder_datatype: case SVG_TimelineBegin_datatype: return 6; /*all list-of-int types*/ //return 7; /*all list-of-float types*/ case SVG_StrokeDashArray_datatype: case SVG_ViewBox_datatype: case SVG_Coordinates_datatype: return 8; /*ID (u32) types*/ //return 10; case SVG_FontFamily_datatype: return 11; case XMLRI_datatype: return 12; case SVG_Motion_datatype: return 9; /*ARG LOOKS LIKE THE SPEC IS BROKEN HERE*/ case SVG_Transform_Translate_datatype: return 9; case SVG_Transform_Scale_datatype: return 8; case SVG_Transform_Rotate_datatype: if (vals) { u32 i=0; SVG_Point_Angle *pt; while ((pt = (SVG_Point_Angle *) gf_list_enum(vals, &i))) { if (pt->x || pt->y) return 8; } } else if (a_val) { SVG_Point_Angle *pt = (SVG_Point_Angle *) a_val; if (pt->x || pt->y) return 8; } return 1; case SVG_Transform_SkewX_datatype: return 1; case SVG_Transform_SkewY_datatype: return 1; //case SVG_Transform_datatype: return; /*FALL THROUH*/ default: return 255; } } static void lsr_write_coordinate(GF_LASeRCodec *lsr, Fixed val, Bool skipable, const char *name) { if (skipable && !val) { GF_LSR_WRITE_INT(lsr, 0, 1, name); } else { u32 res = lsr_translate_coords(lsr, val, lsr->coord_bits); if (skipable) GF_LSR_WRITE_INT(lsr, 1, 1, name); GF_LSR_WRITE_INT(lsr, res, lsr->coord_bits, name); } } static void lsr_write_coordinate_ptr(GF_LASeRCodec *lsr, SVG_Coordinate *val, Bool skipable, const char *name) { if (skipable && !val) { GF_LSR_WRITE_INT(lsr, 0, 1, name); } else { u32 res = lsr_translate_coords(lsr, val ? val->value : 0, lsr->coord_bits); if (skipable) GF_LSR_WRITE_INT(lsr, 1, 1, name); GF_LSR_WRITE_INT(lsr, res, lsr->coord_bits, name); } } static void lsr_write_an_anim_value(GF_LASeRCodec *lsr, void *val, u32 lsr_type, u32 svg_type, u32 transform_type, const char *name) { if ((lsr_type==1) || (lsr_type==4)) { switch (svg_type) { case SVG_Transform_Rotate_datatype: case SVG_Transform_SkewX_datatype: case SVG_Transform_SkewY_datatype: GF_LSR_WRITE_INT(lsr, 0, 1, "escapeFlag"); break; default: { SVG_Number *n = (SVG_Number *) val; if (n->type != SVG_NUMBER_VALUE) { GF_LSR_WRITE_INT(lsr, 1, 1, "escapeFlag"); GF_LSR_WRITE_INT(lsr, n->type, 2, "escapeEnum"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "escapeFlag"); } } break; } } else if (svg_type==SVG_StrokeDashArray_datatype) { SVG_StrokeDashArray *da = (SVG_StrokeDashArray *)val; if (da->type==SVG_STROKEDASHARRAY_INHERIT) { GF_LSR_WRITE_INT(lsr, 1, 1, "escapeFlag"); GF_LSR_WRITE_INT(lsr, 0, 2, "escapeEnum"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "escapeFlag"); } } else { GF_LSR_WRITE_INT(lsr, 0, 1, "escapeFlag"); } switch(lsr_type) { case 0: lsr_write_byte_align_string(lsr, *(DOM_String *)val, name); break; case 1: if (svg_type==SVG_Transform_Rotate_datatype) { Fixed angle = ((SVG_Point_Angle *) val)->angle; angle = gf_muldiv(angle, INT2FIX(180), GF_PI); lsr_write_fixed_16_8(lsr, angle, name); } else if ((svg_type==SVG_Transform_SkewX_datatype) || (svg_type==SVG_Transform_SkewY_datatype)) { lsr_write_fixed_16_8(lsr, *(Fixed *)val, name); } else { lsr_write_fixed_16_8(lsr, ((SVG_Number *) val)->value, name); } break; case 12: lsr_write_any_uri(lsr, (XMLRI*)val, name); break; case 2: lsr_write_path_type(lsr, (SVG_PathData*)val, name); break; case 3: lsr_write_point_sequence(lsr, (GF_List **)val, name); break; case 4: lsr_write_fixed_clamp(lsr, ((SVG_Number *) val)->value, name); break; case 5: lsr_write_paint(lsr, (SVG_Paint*)val, name); break; case 6: lsr_write_vluimsbf5(lsr, (u32) *(u8 *) val, name); break; case 10: lsr_write_vluimsbf5(lsr, *(u32 *) val, name); break; case 11: { s32 idx = lsr_get_font_index(lsr, (SVG_FontFamily*)val); if (idx<0) { GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] corrupted font table while encoding anim value\n")); idx=0; } lsr_write_vluimsbf5(lsr, idx, name); } break; case 7: { GF_List *l = *(GF_List **)val; u32 i, count = gf_list_count(l); lsr_write_vluimsbf5(lsr, count, "count"); for (i=0; iarray.count, "count"); for (i=0; iarray.count; i++) { lsr_write_fixed_16_8(lsr, da->array.vals[i], "val"); } } else if (svg_type==SVG_ViewBox_datatype) { SVG_ViewBox *vb = (SVG_ViewBox *)val; lsr_write_vluimsbf5(lsr, 4, "count"); lsr_write_fixed_16_8(lsr, vb->x, "val"); lsr_write_fixed_16_8(lsr, vb->y, "val"); lsr_write_fixed_16_8(lsr, vb->width, "val"); lsr_write_fixed_16_8(lsr, vb->height, "val"); } else if (svg_type==SVG_Coordinates_datatype) { GF_List *l = *(GF_List **)val; count = gf_list_count(l); lsr_write_vluimsbf5(lsr, count, "count"); for (i=0; ivalue, "val"); } } else if (svg_type==SVG_Transform_Rotate_datatype) { Fixed angle; SVG_Point_Angle *p = (SVG_Point_Angle *)val; count = (p->x || p->y) ? 3 : 1; lsr_write_vluimsbf5(lsr, count, "count"); angle = gf_muldiv(p->angle, INT2FIX(180), GF_PI); lsr_write_fixed_16_8(lsr, p->angle, "val"); if (count==3) { lsr_write_fixed_16_8(lsr, p->x, "val"); lsr_write_fixed_16_8(lsr, p->y, "val"); } } else if (svg_type==SVG_Transform_Scale_datatype) { SVG_Point *pt = (SVG_Point *)val; count = (pt->x == pt->y) ? 1 : 2; lsr_write_vluimsbf5(lsr, count, "count"); lsr_write_fixed_16_8(lsr, pt->x, "val"); if (count==2) lsr_write_fixed_16_8(lsr, pt->y, "val"); } else { GF_List *l = *(GF_List **)val; count = gf_list_count(l); lsr_write_vluimsbf5(lsr, count, "count"); for (i=0; im[2], 0, "valX"); lsr_write_coordinate(lsr, ((GF_Matrix2D*)val)->m[5], 0, "valY"); } else { lsr_write_coordinate(lsr, ((SVG_Point *)val)->x, 0, "valX"); lsr_write_coordinate(lsr, ((SVG_Point *)val)->y, 0, "valY"); } break; default: lsr_write_extension(lsr, NULL, 0, name); break; } } static void lsr_write_anim_value(GF_LASeRCodec *lsr, SMIL_AnimateValue *val, const char *name) { if (!val || !val->type) { GF_LSR_WRITE_INT(lsr, 0, 1, name); } else { u32 type = svg_type_to_lsr_anim(val->type, 0, NULL, val->value); if (type==255) { GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] unsupported anim type %d - skipping\n", val->type )); GF_LSR_WRITE_INT(lsr, 0, 1, name); } else { GF_LSR_WRITE_INT(lsr, 1, 1, name); GF_LSR_WRITE_INT(lsr, type, 4, "type"); lsr_write_an_anim_value(lsr, val->value, type, val->type, 0, name); } } } static void lsr_write_anim_values(GF_LASeRCodec *lsr, SMIL_AnimateValues *anims, const char *name) { u32 type, i, count = 0; if (anims && anims->type) count = gf_list_count(anims->values); if (!count) { GF_LSR_WRITE_INT(lsr, 0, 1, name); return; } type = svg_type_to_lsr_anim(anims->type, 0, anims->values, NULL); if (type==255) { GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] unsupported anim type %d - skipping\n", anims->type )); GF_LSR_WRITE_INT(lsr, 0, 1, name); } else { GF_LSR_WRITE_INT(lsr, 1, 1, name); GF_LSR_WRITE_INT(lsr, type, 4, "type"); lsr_write_vluimsbf5(lsr, count, "count"); for (i=0; ivalues, i); lsr_write_an_anim_value(lsr, att, type, anims->type, 0, "a_value"); } } } static void lsr_write_fraction_12(GF_LASeRCodec *lsr, GF_List **l, const char *name) { u32 i, count; count = l ? gf_list_count(*l) : 0; if (!count) { GF_LSR_WRITE_INT(lsr, 0, 1, name); return; } GF_LSR_WRITE_INT(lsr, 1, 1, name); lsr_write_vluimsbf5(lsr, count, "name"); for (i=0; ires_factor); val = (v<0) ? FIX2INT(-v) : FIX2INT(v); return 1 + gf_get_bit_size(val); } static void lsr_write_point_sequence(GF_LASeRCodec *lsr, GF_List **pts, const char *name) { u32 i, count = pts ? gf_list_count(*pts) : 0; lsr_write_vluimsbf5(lsr, count, "nbPoints"); if (!count) return; /*TODO golomb coding*/ GF_LSR_WRITE_INT(lsr, 0, 1, "flag"); if (1) { if (count < 3) { u32 nb_bits = 0; for (i=0; ix); if (k>nb_bits) nb_bits = k; k = lsr_get_bit_size(lsr, pt->y); if (k>nb_bits) nb_bits = k; } GF_LSR_WRITE_INT(lsr, nb_bits, 5, "bits"); for (i=0; ix, nb_bits); GF_LSR_WRITE_INT(lsr, v, nb_bits, "x"); v = lsr_translate_coords(lsr, pt->y, nb_bits); GF_LSR_WRITE_INT(lsr, v, nb_bits, "y"); } } else { Fixed c_x, c_y; u32 k, nb_dx, nb_dy; SVG_Point *pt = (SVG_Point *)gf_list_get(*pts, 0); nb_dx = 0; k = lsr_get_bit_size(lsr, pt->x); if (k>nb_dx) nb_dx = k; k = lsr_get_bit_size(lsr, pt->y); if (k>nb_dx) nb_dx = k; GF_LSR_WRITE_INT(lsr, nb_dx, 5, "bits"); k = lsr_translate_coords(lsr, pt->x, nb_dx); GF_LSR_WRITE_INT(lsr, k, nb_dx, "x"); k = lsr_translate_coords(lsr, pt->y, nb_dx); GF_LSR_WRITE_INT(lsr, k, nb_dx, "y"); c_x = pt->x; c_y = pt->y; nb_dx = nb_dy = 0; for (i=1; ix - c_x); if (k>nb_dx) nb_dx = k; k = lsr_get_bit_size(lsr, pt->y - c_y); if (k>nb_dy) nb_dy = k; c_x = pt->x; c_y = pt->y; } GF_LSR_WRITE_INT(lsr, nb_dx, 5, "bitsx"); GF_LSR_WRITE_INT(lsr, nb_dy, 5, "bitsy"); c_x = pt->x; c_y = pt->y; for (i=1; ix - c_x, nb_dx); GF_LSR_WRITE_INT(lsr, k, nb_dx, "dx"); k = lsr_translate_coords(lsr, pt->y - c_y, nb_dy); GF_LSR_WRITE_INT(lsr, k, nb_dy, "dy"); c_x = pt->x; c_y = pt->y; } } } } static void lsr_write_path_type(GF_LASeRCodec *lsr, SVG_PathData *path, const char *name) { #if USE_GF_PATH u32 i, *contour, nb_types; GF_List *pts = gf_list_new(); contour = path->contours; nb_types = 0; for (i=0; in_points; ) { switch (path->tags[i]) { case GF_PATH_CURVE_ON: gf_list_add(pts, &path->points[i]); nb_types++; i++; break; case GF_PATH_CLOSE: nb_types++; i++; break; case GF_PATH_CURVE_CONIC: gf_list_add(pts, &path->points[i]); gf_list_add(pts, &path->points[i+1]); i+=2; nb_types++; break; case GF_PATH_CURVE_CUBIC: gf_list_add(pts, &path->points[i]); gf_list_add(pts, &path->points[i+1]); gf_list_add(pts, &path->points[i+2]); i+=3; nb_types++; break; } } lsr_write_point_sequence(lsr, &pts, "seq"); gf_list_del(pts); /*first moveTo is skiped*/ lsr_write_vluimsbf5(lsr, nb_types-1, "nbOfTypes"); for (i=0; in_points; ) { switch (path->tags[i]) { case GF_PATH_CLOSE: /*close*/ GF_LSR_WRITE_INT(lsr, LSR_PATH_COM_Z, 5, name); i++; break; case GF_PATH_CURVE_ON: if (!i) { } else if (*contour == i-1) { /*moveTo*/ GF_LSR_WRITE_INT(lsr, LSR_PATH_COM_M, 5, name); } else { /*lineTo*/ GF_LSR_WRITE_INT(lsr, LSR_PATH_COM_L, 5, name); } i++; break; case GF_PATH_CURVE_CONIC: /*Conic*/ GF_LSR_WRITE_INT(lsr, LSR_PATH_COM_Q, 5, name); i+=2; break; case GF_PATH_CURVE_CUBIC: /*cubic*/ GF_LSR_WRITE_INT(lsr, LSR_PATH_COM_C, 5, name); i+=3; break; } } #else u32 i, count; lsr_write_point_sequence(lsr, path->points, "seq"); /*initial move is not coded*/ count = gf_list_count(path->commands); lsr_write_vluimsbf5(lsr, count, "nbOfTypes"); for (i; icommands, i); GF_LSR_WRITE_INT(lsr, type, 5, name); } #endif } static void lsr_write_rotate_type(GF_LASeRCodec *lsr, SVG_Rotate *rotate, const char *name) { GF_LSR_WRITE_INT(lsr, rotate ? 1 : 0, 1, name); if (!rotate) return; if ((rotate->type == SVG_NUMBER_AUTO) || (rotate->type == SVG_NUMBER_AUTO_REVERSE)) { GF_LSR_WRITE_INT(lsr, 1, 1, "choice"); GF_LSR_WRITE_INT(lsr, (rotate->type == SVG_NUMBER_AUTO) ? 0 : 1, 1, "rotate"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "choice"); lsr_write_fixed_16_8(lsr, rotate->value, "rotate"); } } static void lsr_write_sync_behavior(GF_LASeRCodec *lsr, SMIL_SyncBehavior *sync, const char *name) { GF_LSR_WRITE_INT(lsr, sync ? 1 : 0, 1, name); if (!sync) return; assert(*sync!=SMIL_SYNCBEHAVIOR_INHERIT); GF_LSR_WRITE_INT(lsr, *sync-1, 2, name); } static void lsr_write_sync_tolerance(GF_LASeRCodec *lsr, SMIL_SyncTolerance *sync, const char *name) { GF_LSR_WRITE_INT(lsr, sync ? 1 : 0, 1, name); if (!sync) return; assert(sync->type!=SMIL_SYNCTOLERANCE_INHERIT); if (sync->type==SMIL_SYNCTOLERANCE_DEFAULT) { GF_LSR_WRITE_INT(lsr, 1, 1, name); } else { GF_LSR_WRITE_INT(lsr, 0, 1, name); lsr_write_vluimsbf5(lsr, (u32) (sync->value*lsr->time_resolution), "value"); } } static void lsr_write_coord_list(GF_LASeRCodec *lsr, GF_List **coords, const char *name) { u32 i, count = coords ? gf_list_count(*coords) : 0; if (!count) { GF_LSR_WRITE_INT(lsr, 0, 1, name); } else { GF_LSR_WRITE_INT(lsr, 1, 1, name); lsr_write_vluimsbf5(lsr, count, "nb_coords"); for (i=0; ivalue, lsr->coord_bits); GF_LSR_WRITE_INT(lsr, res, lsr->coord_bits, name); } } } static void lsr_write_transform_behavior(GF_LASeRCodec *lsr, SVG_TransformBehavior *type) { GF_LSR_WRITE_INT(lsr, type ? 1 : 0, 1, "hasTransformBehavior"); if (!type) return; GF_LSR_WRITE_INT(lsr, *type, 4, "transformBehavior"); } static void lsr_write_gradient_units(GF_LASeRCodec *lsr, SVG_GradientUnit *type) { GF_LSR_WRITE_INT(lsr, type ? 1 : 0, 1, "hasGradientUnits"); if (!type) return; GF_LSR_WRITE_INT(lsr, *type ? 1 : 0, 1, "gradientUnits"); } static void lsr_write_content_type(GF_LASeRCodec *lsr, SVG_String *type, const char *name) { if (type) { GF_LSR_WRITE_INT(lsr, 1, 1, "hasType"); lsr_write_byte_align_string(lsr, *type, "type"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "hasType"); } } static void lsr_write_script_type(GF_LASeRCodec *lsr, SVG_String *type) { GF_LSR_WRITE_INT(lsr, type ? 1 : 0, 1, "hasType"); if (!type) return; if (!strcmp(*type, "application/ecmascript")) { GF_LSR_WRITE_INT(lsr, 1, 1, "choice"); GF_LSR_WRITE_INT(lsr, 0, 1, "script"); } else if (!strcmp(*type, "application/jar-archive")) { GF_LSR_WRITE_INT(lsr, 1, 1, "choice"); GF_LSR_WRITE_INT(lsr, 1, 1, "script"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "choice"); lsr_write_byte_align_string(lsr, *type, "type"); } } static void lsr_write_value_with_units(GF_LASeRCodec *lsr, SVG_Number *n, const char *name) { #ifdef GPAC_FIXED_POINT s32 val = n->value >> 8; #else s32 val = (s32) (n->value * (1<<8) ); #endif GF_LSR_WRITE_INT(lsr, val, 32, name); switch (n->type) { case SVG_NUMBER_IN: GF_LSR_WRITE_INT(lsr, 1, 3, "units"); break; case SVG_NUMBER_CM: GF_LSR_WRITE_INT(lsr, 2, 3, "units"); break; case SVG_NUMBER_MM: GF_LSR_WRITE_INT(lsr, 3, 3, "units"); break; case SVG_NUMBER_PT: GF_LSR_WRITE_INT(lsr, 4, 3, "units"); break; case SVG_NUMBER_PC: GF_LSR_WRITE_INT(lsr, 5, 3, "units"); break; case SVG_NUMBER_PERCENTAGE: GF_LSR_WRITE_INT(lsr, 6, 3, "units"); break; default: GF_LSR_WRITE_INT(lsr, 0, 3, "units"); break; } } static void lsr_write_clip_time(GF_LASeRCodec *lsr, SVG_Clock *clock, const char *name) { if (!clock || *clock <= 0) { GF_LSR_WRITE_INT(lsr, 0, 1, name); } else { GF_LSR_WRITE_INT(lsr, 1, 1, name); GF_LSR_WRITE_INT(lsr, 0, 1, "isEnum"); GF_LSR_WRITE_INT(lsr, 0, 1, "sign"); lsr_write_vluimsbf5(lsr, (u32) (lsr->time_resolution* *clock), "val"); } } static void lsr_write_href_anim(GF_LASeRCodec *lsr, XMLRI *href, SVG_Element *parent) { if (href->target && (href->target==parent)) { GF_LSR_WRITE_INT(lsr, 0, 1, "has_href"); } else { lsr_write_href(lsr, href); } } static void lsr_write_attribute_type(GF_LASeRCodec *lsr, SVGAllAttributes *atts) { if (!atts->attributeType) { GF_LSR_WRITE_INT(lsr, 0, 1, "hasAttributeType"); } else { GF_LSR_WRITE_INT(lsr, 1, 1, "hasAttributeType"); GF_LSR_WRITE_INT(lsr, (*atts->attributeType), 2, "attributeType"); } } static void lsr_write_preserve_aspect_ratio(GF_LASeRCodec *lsr, SVG_PreserveAspectRatio *preserveAspectRatio) { GF_LSR_WRITE_INT(lsr, preserveAspectRatio ? 1 : 0, 1, "hasPreserveAspectRatio"); if (!preserveAspectRatio) return; GF_LSR_WRITE_INT(lsr, 0, 1, "choice (meetOrSlice)"); GF_LSR_WRITE_INT(lsr, preserveAspectRatio->defer ? 1 : 0, 1, "choice (defer)"); switch (preserveAspectRatio->align) { case SVG_PRESERVEASPECTRATIO_XMAXYMAX: GF_LSR_WRITE_INT(lsr, 1, 4, "alignXandY"); break; case SVG_PRESERVEASPECTRATIO_XMAXYMID: GF_LSR_WRITE_INT(lsr, 2, 4, "alignXandY"); break; case SVG_PRESERVEASPECTRATIO_XMAXYMIN: GF_LSR_WRITE_INT(lsr, 3, 4, "alignXandY"); break; case SVG_PRESERVEASPECTRATIO_XMIDYMAX: GF_LSR_WRITE_INT(lsr, 4, 4, "alignXandY"); break; case SVG_PRESERVEASPECTRATIO_XMIDYMID: GF_LSR_WRITE_INT(lsr, 5, 4, "alignXandY"); break; case SVG_PRESERVEASPECTRATIO_XMIDYMIN: GF_LSR_WRITE_INT(lsr, 6, 4, "alignXandY"); break; case SVG_PRESERVEASPECTRATIO_XMINYMAX: GF_LSR_WRITE_INT(lsr, 7, 4, "alignXandY"); break; case SVG_PRESERVEASPECTRATIO_XMINYMID: GF_LSR_WRITE_INT(lsr, 8, 4, "alignXandY"); break; case SVG_PRESERVEASPECTRATIO_XMINYMIN: GF_LSR_WRITE_INT(lsr, 9, 4, "alignXandY"); break; default: GF_LSR_WRITE_INT(lsr, 0, 4, "alignXandY"); break; } } #define lsr_write_err() GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired") static void lsr_write_a(GF_LASeRCodec *lsr, SVG_Element *elt) { SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_fill(lsr, elt, &atts); lsr_write_stroke(lsr, elt, &atts); lsr_write_err(); GF_LSR_WRITE_INT(lsr, (atts.target!=NULL) ? 1 : 0, 1, "hasTarget"); if (atts.target) lsr_write_byte_align_string(lsr, *(SVG_String*)atts.target, "target"); lsr_write_href(lsr, atts.xlink_href); lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_animate(GF_LASeRCodec *lsr, SVG_Element *elt, SVG_Element *parent) { SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_animatable(lsr, atts.attributeName, atts.xlink_href, "attributeName"); lsr_write_accumulate(lsr, atts.accumulate); lsr_write_additive(lsr, atts.additive); lsr_write_anim_value(lsr, atts.by, "by"); lsr_write_calc_mode(lsr, atts.calcMode); lsr_write_anim_value(lsr, atts.from, "from"); lsr_write_fraction_12(lsr, atts.keySplines, "keySplines"); lsr_write_fraction_12(lsr, atts.keyTimes, "keyTimes"); lsr_write_anim_values(lsr, atts.values, "values"); lsr_write_attribute_type(lsr, &atts); lsr_write_smil_times(lsr, atts.begin, "begin", 1); lsr_write_duration(lsr, atts.dur, "dur"); lsr_write_anim_fill(lsr, atts.smil_fill); lsr_write_anim_repeat(lsr, atts.repeatCount); lsr_write_repeat_duration(lsr, atts.repeatDur); lsr_write_anim_restart(lsr, atts.restart); lsr_write_anim_value(lsr, atts.to, "to"); lsr_write_href_anim(lsr, atts.xlink_href, parent); GF_LSR_WRITE_INT(lsr, (atts.lsr_enabled && *atts.lsr_enabled) ? 1 : 0, 1, "enabled"); lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_animateMotion(GF_LASeRCodec *lsr, SVG_Element*elt, SVG_Element *parent) { SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_accumulate(lsr, atts.accumulate); lsr_write_additive(lsr, atts.additive); lsr_write_anim_value(lsr, atts.by, "by"); lsr_write_calc_mode(lsr, atts.calcMode); lsr_write_anim_value(lsr, atts.from, "from"); lsr_write_fraction_12(lsr, atts.keySplines, "keySplines"); lsr_write_fraction_12(lsr, atts.keyTimes, "keyTimes"); lsr_write_anim_values(lsr, atts.values, "values"); lsr_write_attribute_type(lsr, &atts); lsr_write_smil_times(lsr, atts.begin, "begin", 1); lsr_write_duration(lsr, atts.dur, "dur"); lsr_write_anim_fill(lsr, atts.smil_fill); lsr_write_anim_repeat(lsr, atts.repeatCount); lsr_write_repeat_duration(lsr, atts.repeatDur); lsr_write_anim_restart(lsr, atts.restart); lsr_write_anim_value(lsr, atts.to, "to"); lsr_write_float_list(lsr, atts.keyPoints, "keyPoints"); if (atts.path) { GF_LSR_WRITE_INT(lsr, 1, 1, "hasPath"); lsr_write_path_type(lsr, atts.path, "path"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "hasPath"); } lsr_write_rotate_type(lsr, atts.rotate, "rotate"); lsr_write_href_anim(lsr, atts.xlink_href, parent); GF_LSR_WRITE_INT(lsr, (atts.lsr_enabled && *atts.lsr_enabled) ? 1 : 0, 1, "enabled"); lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_animateTransform(GF_LASeRCodec *lsr, SVG_Element *elt, SVG_Element *parent) { u32 type; SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_animatable(lsr, atts.attributeName, atts.xlink_href, "attributeName"); /*no default value for type or we MUST code it in LASeR ...*/ type = atts.transform_type ? *atts.transform_type : SVG_TRANSFORM_TRANSLATE; /*enumeration rotate{0} scale{1} skewX{2} skewY{3} translate{4}*/ switch (type) { case SVG_TRANSFORM_ROTATE: GF_LSR_WRITE_INT(lsr, 0, 3, "rotscatra"); break; case SVG_TRANSFORM_SCALE: GF_LSR_WRITE_INT(lsr, 1, 3, "rotscatra"); break; case SVG_TRANSFORM_SKEWX: GF_LSR_WRITE_INT(lsr, 2, 3, "rotscatra"); break; case SVG_TRANSFORM_SKEWY: GF_LSR_WRITE_INT(lsr, 3, 3, "rotscatra"); break; case SVG_TRANSFORM_TRANSLATE: GF_LSR_WRITE_INT(lsr, 4, 3, "rotscatra"); break; } lsr_write_accumulate(lsr, atts.accumulate); lsr_write_additive(lsr, atts.additive); lsr_write_anim_value(lsr, atts.by, "by"); lsr_write_calc_mode(lsr, atts.calcMode); lsr_write_anim_value(lsr, atts.from, "from"); lsr_write_fraction_12(lsr, atts.keySplines, "keySplines"); lsr_write_fraction_12(lsr, atts.keyTimes, "keyTimes"); lsr_write_anim_values(lsr, atts.values, "values"); lsr_write_attribute_type(lsr, &atts); lsr_write_smil_times(lsr, atts.begin, "begin", 1); lsr_write_duration(lsr, atts.dur, "dur"); lsr_write_anim_fill(lsr, atts.smil_fill); lsr_write_anim_repeat(lsr, atts.repeatCount); lsr_write_repeat_duration(lsr, atts.repeatDur); lsr_write_anim_restart(lsr, atts.restart); lsr_write_anim_value(lsr, atts.to, "to"); lsr_write_href_anim(lsr, atts.xlink_href, parent); GF_LSR_WRITE_INT(lsr, (atts.lsr_enabled && *atts.lsr_enabled) ? 1 : 0, 1, "enabled"); lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_audio(GF_LASeRCodec *lsr, SVG_Element *elt) { SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_smil_times(lsr, atts.begin, "begin", 1); lsr_write_duration(lsr, atts.dur, "dur"); GF_LSR_WRITE_INT(lsr, atts.externalResourcesRequired ? *atts.externalResourcesRequired : 0, 1, "externalResourcesRequired"); lsr_write_anim_repeat(lsr, atts.repeatCount); lsr_write_repeat_duration(lsr, atts.repeatDur); lsr_write_anim_restart(lsr, atts.restart); lsr_write_sync_behavior(lsr, atts.syncBehavior, "syncBehavior"); lsr_write_sync_tolerance(lsr, atts.syncTolerance, "syncBehavior"); lsr_write_content_type(lsr, atts.xlink_type, "type"); lsr_write_href(lsr, atts.xlink_href); lsr_write_clip_time(lsr, atts.clipBegin, "clipBegin"); lsr_write_clip_time(lsr, atts.clipEnd, "clipEnd"); GF_LSR_WRITE_INT(lsr, atts.syncReference ? 1 : 0, 1, "hasSyncReference"); if (atts.syncReference) lsr_write_any_uri(lsr, atts.syncReference, "syncReference"); lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_circle(GF_LASeRCodec *lsr, SVG_Element *elt) { SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_fill(lsr, (SVG_Element*)elt, &atts); lsr_write_stroke(lsr, (SVG_Element*)elt, &atts); lsr_write_coordinate_ptr(lsr, atts.cx, 1, "cx"); lsr_write_coordinate_ptr(lsr, atts.cy, 1, "cy"); lsr_write_coordinate_ptr(lsr, atts.r, 0, "r"); lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_conditional(GF_LASeRCodec *lsr, SVG_Element *elt) { GF_DOMUpdates *up; SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_smil_times(lsr, atts.begin, "begin", 1); GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired"); GF_LSR_WRITE_INT(lsr, (atts.lsr_enabled && *atts.lsr_enabled) ? 1 : 0, 1, "enabled"); lsr_write_any_attribute(lsr, elt, 1); up = elt->children ? (GF_DOMUpdates*)elt->children->node : NULL; lsr_write_command_list(lsr, up ? up->updates : NULL, elt, 0); lsr_write_private_attributes(lsr, elt); } static void lsr_write_cursorManager(GF_LASeRCodec *lsr, SVG_Element *elt) { SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_coordinate_ptr(lsr, atts.x, 1, "x"); lsr_write_coordinate_ptr(lsr, atts.x, 1, "y"); lsr_write_href(lsr, atts.xlink_href); lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_data(GF_LASeRCodec *lsr, SVG_Element *elt) { lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_defs(GF_LASeRCodec *lsr, SVG_Element *elt) { SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_fill(lsr, (SVG_Element*)elt, &atts); lsr_write_stroke(lsr, (SVG_Element*)elt, &atts); lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_ellipse(GF_LASeRCodec *lsr, SVG_Element *elt) { SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_fill(lsr, (SVG_Element*)elt, &atts); lsr_write_stroke(lsr, (SVG_Element*)elt, &atts); lsr_write_coordinate_ptr(lsr, atts.cx, 1, "cx"); lsr_write_coordinate_ptr(lsr, atts.cy, 1, "cy"); lsr_write_coordinate_ptr(lsr, atts.rx, 0, "rx"); lsr_write_coordinate_ptr(lsr, atts.ry, 0, "ry"); lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_foreignObject(GF_LASeRCodec *lsr, SVG_Element *elt) { SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_fill(lsr, (SVG_Element*)elt, &atts); lsr_write_stroke(lsr, (SVG_Element*)elt, &atts); GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired&&*atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired"); lsr_write_coordinate_ptr(lsr, atts.height, 0, "height"); lsr_write_coordinate_ptr(lsr, atts.width, 0, "width"); lsr_write_coordinate_ptr(lsr, atts.x, 1, "x"); lsr_write_coordinate_ptr(lsr, atts.y, 1, "y"); lsr_write_any_attribute(lsr, elt, 1); /* TODO bit(1) opt_group; if(opt_group) { vluimsbf5 occ1; for(int t=0;tprev_g, &same_fill, NULL, 0) && same_fill ) { /*samegType*/ GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_sameg, 6, "ch4"); lsr_write_id(lsr, (GF_Node *) elt); is_same = 1; } else { /*gType*/ if (!ommit_tag) GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_g, 6, "ch4"); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_fill(lsr, (SVG_Element*)elt, &atts); lsr_write_stroke(lsr, (SVG_Element*)elt, &atts); GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired"); lsr_write_any_attribute(lsr, elt, 1); lsr->prev_g = elt; } lsr_write_group_content(lsr, elt, is_same); } static void lsr_write_image(GF_LASeRCodec *lsr, SVG_Element *elt) { SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired"); lsr_write_coordinate_ptr(lsr, atts.height, 1, "height"); if (atts.opacity && (atts.opacity->type == SVG_NUMBER_VALUE)) { GF_LSR_WRITE_INT(lsr, 1, 1, "opacity"); lsr_write_fixed_clamp(lsr, atts.opacity->value, "opacity"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "opacity"); } lsr_write_preserve_aspect_ratio(lsr, atts.preserveAspectRatio); lsr_write_content_type(lsr, atts.xlink_type, "type"); lsr_write_coordinate_ptr(lsr, atts.width, 1, "width"); lsr_write_coordinate_ptr(lsr, atts.x, 1, "x"); lsr_write_coordinate_ptr(lsr, atts.y, 1, "y"); lsr_write_href(lsr, atts.xlink_href); lsr_write_transform_behavior(lsr, atts.transformBehavior); lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_line(GF_LASeRCodec *lsr, SVG_Element *elt, Bool ommit_tag) { Bool same_fill; Bool is_same = 0; SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); if (!ommit_tag && lsr_elt_has_same_base(lsr, &atts, lsr->prev_line, &same_fill, NULL, 0) && same_fill ) { /*samelineType*/ GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_sameline, 6, "ch4"); lsr_write_id(lsr, (GF_Node *) elt); is_same = 1; } else { /*lineType*/ if (!ommit_tag) GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_line, 6, "ch4"); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_fill(lsr, elt, &atts); lsr_write_stroke(lsr, elt, &atts); } lsr_write_coordinate_ptr(lsr, atts.x1, 1, "x1"); lsr_write_coordinate_ptr(lsr, atts.x2, 0, "x2"); lsr_write_coordinate_ptr(lsr, atts.y1, 1, "y1"); lsr_write_coordinate_ptr(lsr, atts.y2, 0, "y2"); if (!is_same) { lsr_write_any_attribute(lsr, elt, 1); lsr->prev_line = elt; } lsr_write_group_content(lsr, elt, is_same); } static void lsr_write_linearGradient(GF_LASeRCodec *lsr, SVG_Element *elt) { SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_fill(lsr, elt, &atts); lsr_write_stroke(lsr, elt, &atts); lsr_write_gradient_units(lsr, atts.gradientUnits); lsr_write_coordinate_ptr(lsr, atts.x1, 1, "x1"); lsr_write_coordinate_ptr(lsr, atts.x2, 1, "x2"); lsr_write_coordinate_ptr(lsr, atts.y1, 1, "y1"); lsr_write_coordinate_ptr(lsr, atts.y2, 1, "y2"); lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_mpath(GF_LASeRCodec *lsr, SVG_Element *elt) { SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_href(lsr, atts.xlink_href); lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_path(GF_LASeRCodec *lsr, SVG_Element *elt, Bool ommit_tag) { Bool same_fill; Bool is_same = 0; SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); if (!ommit_tag && lsr_elt_has_same_base(lsr, &atts, lsr->prev_path, &same_fill, NULL, 0) ) { is_same = 1; if (!same_fill) { /*samepathfillType*/ GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_samepathfill, 6, "ch4"); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_fill(lsr, elt, &atts); } else { /*samepathType*/ GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_samepath, 6, "ch4"); lsr_write_id(lsr, (GF_Node *) elt); } lsr_write_path_type(lsr, atts.d, "d"); } else { /*pathType*/ if (!ommit_tag) GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_path, 6, "ch4"); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_fill(lsr, elt, &atts); lsr_write_stroke(lsr, elt, &atts); lsr_write_path_type(lsr, atts.d, "d"); if (atts.pathLength) { GF_LSR_WRITE_INT(lsr, 1, 1, "hasPathLength"); lsr_write_fixed_16_8(lsr, atts.pathLength->value, "pathLength"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "hasPathLength"); } lsr_write_any_attribute(lsr, elt, 1); lsr->prev_path = elt; } lsr_write_group_content(lsr, elt, is_same); } static void lsr_write_polygon(GF_LASeRCodec *lsr, SVG_Element *elt, Bool is_polyline, Bool ommit_tag) { Bool same_fill, same_stroke; Bool same_type = 0; SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); if (!ommit_tag && lsr_elt_has_same_base(lsr, &atts, lsr->prev_polygon, &same_fill, &same_stroke, 1) ) { if (same_fill && same_stroke) same_type = 1; else if (same_fill) same_type = 3; else if (same_stroke) same_type = 2; } if (same_type) { /*samepolylineType / samepolygonType */ u8 type = is_polyline ? LSR_SCENE_CONTENT_MODEL_samepolyline : LSR_SCENE_CONTENT_MODEL_samepolygon; /*samepolylinefillType / samepolygonfillType */ if (same_type==2) type = is_polyline ? LSR_SCENE_CONTENT_MODEL_samepolylinefill : LSR_SCENE_CONTENT_MODEL_samepolygonfill; /*samepolylinestrokeType / samepolygonstrokeType*/ else if (same_type==3) type = is_polyline ? LSR_SCENE_CONTENT_MODEL_samepolylinestroke : LSR_SCENE_CONTENT_MODEL_samepolygonstroke; GF_LSR_WRITE_INT(lsr, type, 6, "ch4"); lsr_write_id(lsr, (GF_Node *) elt); if (same_type==2) lsr_write_fill(lsr, elt, &atts); else if (same_type==3) lsr_write_stroke(lsr, elt, &atts); lsr_write_point_sequence(lsr, atts.points, "points"); } else { /*polyline/polygon*/ if (!ommit_tag) GF_LSR_WRITE_INT(lsr, is_polyline ? LSR_SCENE_CONTENT_MODEL_polyline : LSR_SCENE_CONTENT_MODEL_polygon, 6, "ch4"); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_fill(lsr, elt, &atts); lsr_write_stroke(lsr, elt, &atts); lsr_write_point_sequence(lsr, atts.points, "points"); lsr_write_any_attribute(lsr, elt, 1); lsr->prev_polygon = elt; } lsr_write_group_content(lsr, elt, same_type); } static void lsr_write_radialGradient(GF_LASeRCodec *lsr, SVG_Element *elt) { SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_fill(lsr, elt, &atts); lsr_write_stroke(lsr, elt, &atts); lsr_write_coordinate_ptr(lsr, atts.cx, 1, "cx"); lsr_write_coordinate_ptr(lsr, atts.cy, 1, "cy"); lsr_write_gradient_units(lsr, atts.gradientUnits); lsr_write_coordinate_ptr(lsr, atts.r, 1, "r"); lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_rect(GF_LASeRCodec *lsr, SVG_Element *elt, Bool ommit_tag) { Bool same_type = 0; Bool same_fill; SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); if (!ommit_tag && lsr_elt_has_same_base(lsr, &atts, lsr->prev_rect, &same_fill, NULL, 0) ) { if (!same_fill) { same_type = 2; /*samerectfillType*/ GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_samerectfill, 6, "ch4"); } else { same_type = 1; /*samerectType*/ GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_samerect, 6, "ch4"); } lsr_write_id(lsr, (GF_Node *) elt); if (same_type==2) lsr_write_fill(lsr, elt, &atts); lsr_write_coordinate_ptr(lsr, atts.height, 0, "height"); lsr_write_coordinate_ptr(lsr, atts.width, 0, "width"); lsr_write_coordinate_ptr(lsr, atts.x, 1, "x"); lsr_write_coordinate_ptr(lsr, atts.y, 1, "y"); } else { /*rectType*/ if (!ommit_tag) GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_rect, 6, "ch4"); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_fill(lsr, elt, &atts); lsr_write_stroke(lsr, elt, &atts); lsr_write_coordinate_ptr(lsr, atts.height, 0, "height"); lsr_write_coordinate_ptr(lsr, atts.rx, 1, "rx"); lsr_write_coordinate_ptr(lsr, atts.ry, 1, "ry"); lsr_write_coordinate_ptr(lsr, atts.width, 0, "width"); lsr_write_coordinate_ptr(lsr, atts.x, 1, "x"); lsr_write_coordinate_ptr(lsr, atts.y, 1, "y"); lsr_write_any_attribute(lsr, elt, 1); lsr->prev_rect = elt; } lsr_write_group_content(lsr, elt, same_type); } static void lsr_write_rectClip(GF_LASeRCodec *lsr, SVG_Element *elt) { SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_fill(lsr, (SVG_Element*)elt, &atts); lsr_write_stroke(lsr, (SVG_Element*)elt, &atts); GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired"); if (atts.size) { GF_LSR_WRITE_INT(lsr, 1, 1, "size"); lsr_write_coordinate(lsr, atts.size->width, 0, "width"); lsr_write_coordinate(lsr, atts.size->height, 0, "height"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "size"); } lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_script(GF_LASeRCodec *lsr, SVG_Element *elt) { SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired"); lsr_write_script_type(lsr, atts.xlink_type); lsr_write_href(lsr, atts.xlink_href); lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_selector(GF_LASeRCodec *lsr, SVG_Element *elt) { SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_fill(lsr, (SVG_Element*)elt, &atts); lsr_write_stroke(lsr, (SVG_Element*)elt, &atts); GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired"); GF_LSR_WRITE_INT(lsr, atts.choice ? 1 : 0, 1, "hasChoice"); if (atts.choice) { if (atts.choice->type==LASeR_CHOICE_N) { GF_LSR_WRITE_INT(lsr, 0, 1, "choice"); GF_LSR_WRITE_INT(lsr, atts.choice->choice_index, 8, "value"); } else { GF_LSR_WRITE_INT(lsr, 1, 1, "choice"); GF_LSR_WRITE_INT(lsr, atts.choice->type, 1, "type"); } } lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_set(GF_LASeRCodec *lsr, SVG_Element *elt, SVG_Element *parent) { SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_animatable(lsr, atts.attributeName, atts.xlink_href, "attributeName"); lsr_write_attribute_type(lsr, &atts); lsr_write_smil_times(lsr, atts.begin, "begin", 1); lsr_write_duration(lsr, atts.dur, "dur"); lsr_write_anim_fill(lsr, atts.smil_fill); lsr_write_anim_repeat(lsr, atts.repeatCount); lsr_write_repeat_duration(lsr, atts.repeatDur); lsr_write_anim_restart(lsr, atts.restart); lsr_write_anim_value(lsr, atts.to, "to"); lsr_write_href_anim(lsr, atts.xlink_href, parent); GF_LSR_WRITE_INT(lsr, (atts.lsr_enabled && *atts.lsr_enabled) ? 1 : 0, 1, "enabled"); lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_simpleLayout(GF_LASeRCodec *lsr, SVG_Element *elt) { SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_fill(lsr, (SVG_Element*)elt, &atts); lsr_write_stroke(lsr, (SVG_Element*)elt, &atts); if (atts.delta) { GF_LSR_WRITE_INT(lsr, 1, 1, "delta"); lsr_write_coordinate(lsr, atts.delta->width, 0, "width"); lsr_write_coordinate(lsr, atts.delta->height, 0, "height"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "delta"); } GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired"); lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_stop(GF_LASeRCodec *lsr, SVG_Element *elt) { SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_fill(lsr, elt, &atts); lsr_write_stroke(lsr, elt, &atts); lsr_write_fixed_16_8(lsr, atts.offset ? atts.offset->value : 0, "offset"); lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_svg(GF_LASeRCodec *lsr, SVG_Element *elt) { SMIL_Duration snap; SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_fill(lsr, elt, &atts); lsr_write_stroke(lsr, elt, &atts); lsr_write_string_attribute(lsr, atts.baseProfile ? *atts.baseProfile : NULL, "baseProfile"); lsr_write_string_attribute(lsr, atts.contentScriptType ? *atts.contentScriptType : NULL, "contentScriptType"); GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired"); lsr_write_value_with_units(lsr, atts.height, "height"); GF_LSR_WRITE_INT(lsr, atts.playbackOrder ? 1 : 0, 1, "hasPlaybackOrder"); if (atts.playbackOrder) GF_LSR_WRITE_INT(lsr, *atts.playbackOrder, 1, "playbackOrder"); lsr_write_preserve_aspect_ratio(lsr, atts.preserveAspectRatio); snap.clock_value = atts.snapshotTime ? *atts.snapshotTime : 0; snap.type = snap.clock_value ? SMIL_DURATION_DEFINED : SMIL_DURATION_INDEFINITE; lsr_write_duration(lsr, atts.snapshotTime ? &snap : NULL, "has_snapshotTime"); GF_LSR_WRITE_INT(lsr, atts.syncBehaviorDefault ? 1 : 0, 1, "hasSyncBehavior"); if (atts.syncBehaviorDefault) { switch (*atts.syncBehaviorDefault) { case SMIL_SYNCBEHAVIOR_CANSLIP: GF_LSR_WRITE_INT(lsr, 0, 2, "syncBehavior"); break; case SMIL_SYNCBEHAVIOR_INDEPENDENT: GF_LSR_WRITE_INT(lsr, 1, 2, "syncBehavior"); break; case SMIL_SYNCBEHAVIOR_LOCKED: GF_LSR_WRITE_INT(lsr, 3, 2, "syncBehavior"); break; default: GF_LSR_WRITE_INT(lsr, 2, 2, "syncBehavior"); break; } } GF_LSR_WRITE_INT(lsr, atts.syncToleranceDefault ? 1 : 0, 1, "hasSyncToleranceDefault"); if (atts.syncToleranceDefault) { if (atts.syncToleranceDefault->type==SMIL_SYNCTOLERANCE_VALUE) { GF_LSR_WRITE_INT(lsr, 0, 1, "choice"); lsr_write_vluimsbf5(lsr, (u32) (atts.syncToleranceDefault->value*lsr->time_resolution), "value"); } else { GF_LSR_WRITE_INT(lsr, 1, 1, "choice"); } } GF_LSR_WRITE_INT(lsr, atts.timelineBegin ? 1 : 0, 1, "hasTimelineBegin"); if (atts.timelineBegin) GF_LSR_WRITE_INT(lsr, *atts.timelineBegin, 1, "timelineBegin"); lsr_write_string_attribute(lsr, atts.version ? *atts.version : NULL, "version"); GF_LSR_WRITE_INT(lsr, atts.viewBox ? 1 : 0, 1, "hasViewBox"); if (atts.viewBox) { lsr_write_fixed_16_8(lsr, atts.viewBox->x, "viewbox.x"); lsr_write_fixed_16_8(lsr, atts.viewBox->y, "viewbox.y"); lsr_write_fixed_16_8(lsr, atts.viewBox->width, "viewbox.width"); lsr_write_fixed_16_8(lsr, atts.viewBox->height, "viewbox.height"); } lsr_write_value_with_units(lsr, atts.width, "width"); GF_LSR_WRITE_INT(lsr, atts.zoomAndPan ? 1 : 0, 1, "hasZoomAndPan"); if (atts.zoomAndPan) { GF_LSR_WRITE_INT(lsr, (*atts.zoomAndPan==SVG_ZOOMANDPAN_MAGNIFY) ? 1 : 0, 1, "zoomAndPan"); } lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_switch(GF_LASeRCodec *lsr, SVG_Element *elt) { SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_fill(lsr, (SVG_Element*)elt, &atts); lsr_write_stroke(lsr, (SVG_Element*)elt, &atts); GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired"); lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_text(GF_LASeRCodec *lsr, SVG_Element *elt, Bool ommit_tag) { Bool same_fill; u32 same_type = 0; SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); if (!ommit_tag && lsr_elt_has_same_base(lsr, &atts, lsr->prev_text, &same_fill, NULL, 0) ) { if (!same_fill) { /*sametextfillType*/ GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_sametextfill, 6, "ch4"); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_fill(lsr, elt, &atts); } else { /*sametextType*/ GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_sametext, 6, "ch4"); lsr_write_id(lsr, (GF_Node *) elt); } lsr_write_coord_list(lsr, atts.text_x, "x"); lsr_write_coord_list(lsr, atts.text_y, "y"); same_type = 1; } else { /*textType*/ if (!ommit_tag) GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_text, 6, "ch4"); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_fill(lsr, (SVG_Element*)elt, &atts); lsr_write_stroke(lsr, (SVG_Element*)elt, &atts); GF_LSR_WRITE_INT(lsr, (atts.editable && *atts.editable) ? 1 : 0, 1, "editable"); lsr_write_float_list(lsr, atts.text_rotate, "rotate"); lsr_write_coord_list(lsr, atts.text_x, "x"); lsr_write_coord_list(lsr, atts.text_y, "y"); lsr_write_any_attribute(lsr, elt, 1); lsr->prev_text = elt; } lsr_write_group_content(lsr, elt, same_type); } static void lsr_write_tspan(GF_LASeRCodec *lsr, SVG_Element *elt) { SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_fill(lsr, (SVG_Element*)elt, &atts); lsr_write_stroke(lsr, (SVG_Element*)elt, &atts); lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_use(GF_LASeRCodec *lsr, SVG_Element *elt, Bool ommit_tag) { SVGAllAttributes atts; Bool is_same = 0; gf_svg_flatten_attributes(elt, &atts); if (!ommit_tag && lsr_elt_has_same_base(lsr, &atts, lsr->prev_use, NULL, NULL, 0) /*TODO check overflow*/ ) { is_same = 1; /*sameuseType*/ GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_sameuse, 6, "ch4"); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_href(lsr, atts.xlink_href); } else { /*useType*/ if (!ommit_tag) GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_use, 6, "ch4"); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_fill(lsr, (SVG_Element*)elt, &atts); lsr_write_stroke(lsr, (SVG_Element*)elt, &atts); GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired"); GF_LSR_WRITE_INT(lsr, atts.overflow ? 1 : 0, 1, "hasOverflow"); /*one value only??*/ if (atts.overflow) GF_LSR_WRITE_INT(lsr, 0, 2, "overflow"); lsr_write_coordinate_ptr(lsr, atts.x, 1, "x"); lsr_write_coordinate_ptr(lsr, atts.y, 1, "y"); lsr_write_href(lsr, atts.xlink_href); lsr_write_any_attribute(lsr, elt, 1); lsr->prev_use = elt; } lsr_write_group_content(lsr, elt, is_same); } static void lsr_write_video(GF_LASeRCodec *lsr, SVG_Element *elt) { SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); lsr_write_smil_times(lsr, atts.begin, "begin", 1); lsr_write_duration(lsr, atts.dur, "dur"); GF_LSR_WRITE_INT(lsr, (atts.externalResourcesRequired && *atts.externalResourcesRequired) ? 1 : 0, 1, "externalResourcesRequired"); lsr_write_coordinate_ptr(lsr, atts.height, 1, "height"); GF_LSR_WRITE_INT(lsr, atts.overlay ? 1 : 0, 1, "hasOverlay"); if (atts.overlay) { GF_LSR_WRITE_INT(lsr, 1, 1, "choice"); GF_LSR_WRITE_INT(lsr, *atts.overlay, 1, "overlay"); } lsr_write_preserve_aspect_ratio(lsr, atts.preserveAspectRatio); lsr_write_anim_repeat(lsr, atts.repeatCount); lsr_write_repeat_duration(lsr, atts.repeatDur); lsr_write_anim_restart(lsr, atts.restart); lsr_write_sync_behavior(lsr, atts.syncBehavior, "syncBehavior"); lsr_write_sync_tolerance(lsr, atts.syncTolerance, "syncBehavior"); lsr_write_transform_behavior(lsr, atts.transformBehavior); lsr_write_content_type(lsr, atts.xlink_type, "type"); lsr_write_coordinate_ptr(lsr, atts.width, 1, "width"); lsr_write_coordinate_ptr(lsr, atts.x, 1, "x"); lsr_write_coordinate_ptr(lsr, atts.y, 1, "y"); lsr_write_href(lsr, atts.xlink_href); lsr_write_clip_time(lsr, atts.clipBegin, "clipBegin"); lsr_write_clip_time(lsr, atts.clipEnd, "clipEnd"); GF_LSR_WRITE_INT(lsr, atts.syncReference ? 1 : 0, 1, "hasSyncReference"); if (atts.syncReference) lsr_write_any_uri(lsr, atts.syncReference, "syncReference"); lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_listener(GF_LASeRCodec *lsr, SVG_Element *elt) { SVGAllAttributes atts; gf_svg_flatten_attributes(elt, &atts); lsr_write_id(lsr, (GF_Node *) elt); lsr_write_rare(lsr, (GF_Node *) elt); GF_LSR_WRITE_INT(lsr, atts.defaultAction ? 1 : 0, 1, "hasDefaultAction"); if (atts.defaultAction) GF_LSR_WRITE_INT(lsr, *atts.defaultAction ? 1 : 0, 1, "defaultAction"); if (atts.event) { GF_LSR_WRITE_INT(lsr, 1, 1, "hasEvent"); lsr_write_event_type(lsr, atts.event->type, atts.event->parameter); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "hasEvent"); } if (atts.handler && (atts.handler->string || (atts.handler->target && gf_node_get_id((GF_Node *)atts.handler->target) ) )) { GF_LSR_WRITE_INT(lsr, 1, 1, "hasHandler"); lsr_write_any_uri(lsr, atts.handler, "handler"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "hasHandler"); } if (atts.observer && atts.observer->target && gf_node_get_id((GF_Node *)atts.observer->target) ) { GF_LSR_WRITE_INT(lsr, 1, 1, "hasObserver"); lsr_write_codec_IDREF(lsr, atts.observer, "observer"); } else { if (atts.observer) { GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] listener.observer %s not found in scene - skipping it\n", atts.observer->string )); } GF_LSR_WRITE_INT(lsr, 0, 1, "hasObserver"); } GF_LSR_WRITE_INT(lsr, atts.phase ? 1 : 0, 1, "hasPhase"); if (atts.phase) GF_LSR_WRITE_INT(lsr, *atts.phase, 1, "phase"); GF_LSR_WRITE_INT(lsr, atts.propagate ? 1 : 0, 1, "hasPropagate"); if (atts.propagate) GF_LSR_WRITE_INT(lsr, *atts.propagate, 1, "propagate"); if (atts.listener_target && atts.listener_target->target && gf_node_get_id((GF_Node *)atts.listener_target->target) ) { GF_LSR_WRITE_INT(lsr, 1, 1, "hasTarget"); lsr_write_codec_IDREF(lsr, atts.listener_target, "target"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "hasTarget"); } GF_LSR_WRITE_INT(lsr, (atts.lsr_enabled && *atts.lsr_enabled) ? 1 : 0, 1, "enabled"); lsr_write_any_attribute(lsr, elt, 1); lsr_write_group_content(lsr, elt, 0); } static void lsr_write_scene_content_model(GF_LASeRCodec *lsr, SVG_Element *parent, void *node) { u32 tag = gf_node_get_tag((GF_Node*)node); switch(tag) { case TAG_SVG_a: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_a, 6, "ch4"); lsr_write_a(lsr, node); break; case TAG_SVG_animate: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_animate, 6, "ch4"); lsr_write_animate(lsr, node, parent); break; case TAG_SVG_animateColor: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_animateColor, 6, "ch4"); lsr_write_animate(lsr, node, parent); break; case TAG_SVG_animateMotion: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_animateMotion, 6, "ch4"); lsr_write_animateMotion(lsr, node, parent); break; case TAG_SVG_animateTransform: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_animateTransform, 6, "ch4"); lsr_write_animateTransform(lsr, node, parent); break; case TAG_SVG_audio: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_audio, 6, "ch4"); lsr_write_audio(lsr, node); break; case TAG_SVG_circle: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_circle, 6, "ch4"); lsr_write_circle(lsr, node); break; case TAG_SVG_cursorManager: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_cursorManager, 6, "ch4"); lsr_write_cursorManager(lsr, node); break; case TAG_SVG_defs: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_defs, 6, "ch4"); lsr_write_defs(lsr, node); break; case TAG_SVG_desc: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_desc, 6, "ch4"); lsr_write_data(lsr, node); break; case TAG_SVG_ellipse: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_ellipse, 6, "ch4"); lsr_write_ellipse(lsr, node); break; case TAG_SVG_foreignObject: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_foreignObject, 6, "ch4"); lsr_write_foreignObject(lsr, node); break; case TAG_SVG_g: /*type is written in encoding fct for sameg handling*/ lsr_write_g(lsr, node, 0); break; case TAG_SVG_image: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_image, 6, "ch4"); lsr_write_image(lsr, node); break; case TAG_SVG_line: /*type is written in encoding fct for sameline handling*/ lsr_write_line(lsr, node, 0); break; case TAG_SVG_linearGradient: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_linearGradient, 6, "ch4"); lsr_write_linearGradient(lsr, node); break; case TAG_SVG_metadata: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_metadata, 6, "ch4"); lsr_write_data(lsr, node); break; case TAG_SVG_mpath: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_mpath, 6, "ch4"); lsr_write_mpath(lsr, node); break; case TAG_SVG_path: /*type is written in encoding fct for samepath handling*/ lsr_write_path(lsr, node, 0); break; case TAG_SVG_polygon: /*type is written in encoding fct for samepolygon handling*/ lsr_write_polygon(lsr, node, 0, 0); break; case TAG_SVG_polyline: /*type is written in encoding fct for samepolyline handling*/ lsr_write_polygon(lsr, node, 1, 0); break; case TAG_SVG_radialGradient: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_radialGradient, 6, "ch4"); lsr_write_radialGradient(lsr, node); break; case TAG_SVG_rect: /*type is written in encoding fct for samepolyline handling*/ lsr_write_rect(lsr, node, 0); break; case TAG_SVG_script: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_script, 6, "ch4"); lsr_write_script(lsr, node); break; case TAG_SVG_set: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_set, 6, "ch4"); lsr_write_set(lsr, node, parent); break; case TAG_SVG_stop: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_stop, 6, "ch4"); lsr_write_stop(lsr, node); break; case TAG_SVG_switch: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_switch, 6, "ch4"); lsr_write_switch(lsr, node); break; case TAG_SVG_text: /*type is written in encoding fct for sametext handling*/ lsr_write_text(lsr, node, 0); break; case TAG_SVG_title: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_title, 6, "ch4"); lsr_write_data(lsr, node); break; case TAG_SVG_tspan: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_tspan, 6, "ch4"); lsr_write_tspan(lsr, node); break; case TAG_SVG_use: /*type is written in encoding fct for sameuse handling*/ lsr_write_use(lsr, node, 0); break; case TAG_SVG_video: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_video, 6, "ch4"); lsr_write_video(lsr, node); break; case TAG_SVG_listener: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_listener, 6, "ch4"); lsr_write_listener(lsr, node); break; case TAG_SVG_conditional: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_conditional, 6, "ch4"); lsr_write_conditional(lsr, node); break; case TAG_SVG_rectClip: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_rectClip, 6, "ch4"); lsr_write_rectClip(lsr, node); break; case TAG_SVG_selector: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_selector, 6, "ch4"); lsr_write_selector(lsr, node); break; case TAG_SVG_simpleLayout: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_simpleLayout, 6, "ch4"); lsr_write_simpleLayout(lsr, node); break; #if 0 /*case privateElement*/ case TAG_SVG_extendElement: GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_privateContainer, 6, "ch4"); lsr_write_private_element_container(lsr); break; #endif default: #if 0 /*case extend*/ GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_element_any, 6, "ch4"); lsr_write_extend_class(lsr, NULL, 0, node); break; #else /*hack for encoding - needs cleaning*/ GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] node %s not part of LASeR children nodes - skipping\n", gf_node_get_class_name((GF_Node*)node))); GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_textContent, 6, "ch4"); lsr_write_byte_align_string(lsr, "", "textContent"); break; #endif } } static void lsr_write_update_content_model(GF_LASeRCodec *lsr, SVG_Element *parent, void *node) { u32 tag = gf_node_get_tag((GF_Node*)node); if (tag==TAG_SVG_conditional) { GF_LSR_WRITE_INT(lsr, 1, 1, "ch4"); GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL2_conditional, 3, "ch61"); lsr_write_conditional(lsr, node); } else if (tag==TAG_SVG_cursorManager) { GF_LSR_WRITE_INT(lsr, 1, 1, "ch4"); GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL2_cursorManager, 3, "ch61"); lsr_write_cursorManager(lsr, node); } else if (tag==TAG_SVG_rectClip) { GF_LSR_WRITE_INT(lsr, 1, 1, "ch4"); GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL2_rectClip, 3, "ch61"); lsr_write_rectClip(lsr, node); } else if (tag==TAG_SVG_selector) { GF_LSR_WRITE_INT(lsr, 1, 1, "ch4"); GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL2_selector, 3, "ch61"); lsr_write_selector(lsr, node); } else if (tag==TAG_SVG_simpleLayout) { GF_LSR_WRITE_INT(lsr, 1, 1, "ch4"); GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL2_simpleLayout, 3, "ch61"); lsr_write_simpleLayout(lsr, node); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "ch4"); switch(tag) { case TAG_SVG_a: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_a, 6, "ch6"); lsr_write_a(lsr, node); break; case TAG_SVG_animate: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_animate, 6, "ch6"); lsr_write_animate(lsr, node, parent); break; case TAG_SVG_animateColor: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_animateColor, 6, "ch6"); lsr_write_animate(lsr, node, parent); break; case TAG_SVG_animateMotion: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_animateMotion, 6, "ch6"); lsr_write_animateMotion(lsr, node, parent); break; case TAG_SVG_animateTransform: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_animateTransform, 6, "ch6"); lsr_write_animateTransform(lsr, node, parent); break; case TAG_SVG_audio: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_audio, 6, "ch6"); lsr_write_audio(lsr, node); break; case TAG_SVG_circle: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_circle, 6, "ch6"); lsr_write_circle(lsr, node); break; case TAG_SVG_defs: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_defs, 6, "ch6"); lsr_write_defs(lsr, node); break; case TAG_SVG_desc: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_desc, 6, "ch6"); lsr_write_data(lsr, node); break; case TAG_SVG_ellipse: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_ellipse, 6, "ch6"); lsr_write_ellipse(lsr, node); break; case TAG_SVG_foreignObject: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_foreignObject, 6, "ch6"); lsr_write_foreignObject(lsr, node); break; case TAG_SVG_g: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_g, 6, "ch6"); lsr_write_g(lsr, node, 1); break; case TAG_SVG_image: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_image, 6, "ch6"); lsr_write_image(lsr, node); break; case TAG_SVG_line: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_line, 6, "ch6"); lsr_write_line(lsr, node, 1); break; case TAG_SVG_linearGradient: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_linearGradient, 6, "ch6"); lsr_write_linearGradient(lsr, node); break; case TAG_SVG_metadata: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_metadata, 6, "ch6"); lsr_write_data(lsr, node); break; case TAG_SVG_mpath: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_mpath, 6, "ch6"); lsr_write_mpath(lsr, node); break; case TAG_SVG_path: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_path, 6, "ch6"); lsr_write_path(lsr, node, 1); break; case TAG_SVG_polygon: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_polygon, 6, "ch6"); lsr_write_polygon(lsr, node, 0, 1); break; case TAG_SVG_polyline: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_polyline, 6, "ch6"); lsr_write_polygon(lsr, node, 1, 1); break; case TAG_SVG_radialGradient: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_radialGradient, 6, "ch6"); lsr_write_radialGradient(lsr, node); break; case TAG_SVG_rect: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_rect, 6, "ch6"); lsr_write_rect(lsr, node, 1); break; case TAG_SVG_script: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_script, 6, "ch6"); lsr_write_script(lsr, node); break; case TAG_SVG_set: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_set, 6, "ch6"); lsr_write_set(lsr, node, parent); break; case TAG_SVG_stop: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_stop, 6, "ch6"); lsr_write_stop(lsr, node); break; case TAG_SVG_svg: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_svg, 6, "ch6"); lsr_write_svg(lsr, node); break; case TAG_SVG_switch: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_switch, 6, "ch6"); lsr_write_switch(lsr, node); break; case TAG_SVG_text: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_text, 6, "ch6"); lsr_write_text(lsr, node, 1); break; case TAG_SVG_title: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_title, 6, "ch6"); lsr_write_data(lsr, node); break; case TAG_SVG_tspan: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_tspan, 6, "ch6"); lsr_write_tspan(lsr, node); break; case TAG_SVG_use: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_use, 6, "ch6"); lsr_write_use(lsr, node, 1); break; case TAG_SVG_video: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_video, 6, "ch6"); lsr_write_video(lsr, node); break; case TAG_SVG_listener: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_CONTENT_MODEL_listener, 6, "ch6"); lsr_write_listener(lsr, node); break; } } } static void lsr_write_group_content(GF_LASeRCodec *lsr, SVG_Element *elt, Bool skip_object_content) { GF_ChildNodeItem *l; u32 count; if (!skip_object_content) lsr_write_private_attributes(lsr, elt); count = gf_node_list_get_count(elt->children); l = elt->children; if (!count) { GF_LSR_WRITE_INT(lsr, 0, 1, "opt_group"); return; } GF_LSR_WRITE_INT(lsr, 1, 1, "opt_group"); lsr_write_vluimsbf5(lsr, count, "occ0"); while (l) { if (gf_node_get_tag(l->node)==TAG_DOMText) { GF_DOMText *txt = (GF_DOMText *)l->node; GF_LSR_WRITE_INT(lsr, LSR_SCENE_CONTENT_MODEL_textContent, 6, "ch4"); lsr_write_byte_align_string(lsr, txt->textContent, "textContent"); } else { lsr_write_scene_content_model(lsr, elt, l->node); GF_LOG(GF_LOG_DEBUG, GF_LOG_CODING, ("[LASeR] ############## end %s ###########\n", gf_node_get_class_name((GF_Node*)l->node))); } l = l->next; } } static void lsr_write_update_value(GF_LASeRCodec *lsr, SVG_Element *elt, u32 fieldType, u32 att_tag, u32 transformType, void *val, Bool is_indexed) { SVG_Number *n; if (is_indexed) { assert(gf_list_count(*(GF_List **)val)); switch (fieldType) { case SVG_Points_datatype:/*points*/ { GF_Point2D *pt = gf_list_get(*(GF_List **)val, 0); lsr_write_coordinate(lsr, pt->x, 0, "x"); lsr_write_coordinate(lsr, pt->y, 0, "y"); } break; case SMIL_Times_datatype:/*smil_times*/ { SMIL_Time *st = gf_list_get(*(GF_List **)val, 0); lsr_write_smil_time(lsr, st); } break; case SMIL_KeyPoints_datatype:/*0to1*/ { Fixed *f = gf_list_get(*(GF_List **)val, 0); lsr_write_fixed_clamp(lsr, *f, "v"); } break; case SMIL_KeySplines_datatype:/*float*/ { Fixed *f = gf_list_get(*(GF_List **)val, 0); lsr_write_fixed_16_8(lsr, *f, "v"); } break; case SMIL_KeyTimes_datatype:/*keyTime*/ { Fixed *v = gf_list_get(*(GF_List **)val, 0); Fixed f = *v; if ((f==0) || (f==FIX_ONE)) { GF_LSR_WRITE_INT(lsr, 1, 1, "hasShort"); GF_LSR_WRITE_INT(lsr, (f==0) ? 0 : 1, 1, "isZero"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "hasShort"); lsr_write_fixed_clamp(lsr, f, "timevalue"); } } break; case SVG_FeatureList_datatype:/*int*/ case SVG_StrokeDashArray_datatype:/*float*/ case SVG_ViewBox_datatype:/*float*/ break; } } else { switch (fieldType) { case SVG_Boolean_datatype: GF_LSR_WRITE_INT(lsr, *(SVG_Boolean*)val ? 1 : 0, 1, "val"); break; case SVG_Paint_datatype: lsr_write_paint(lsr, (SVG_Paint *)val, "val"); break; case SVG_Transform_datatype: lsr_write_matrix(lsr, (SVG_Transform*)val); break; case SVG_Transform_Scale_datatype: lsr_write_fixed_16_8(lsr, ((SVG_Point *)val)->x, "scale_x"); lsr_write_fixed_16_8(lsr, ((SVG_Point *)val)->y, "scale_y"); break; case LASeR_Size_datatype: case SVG_Transform_Translate_datatype: lsr_write_coordinate(lsr, ((SVG_Point *)val)->x, 0, "translation_x"); lsr_write_coordinate(lsr, ((SVG_Point *)val)->y, 0, "translation_y"); break; case SVG_Transform_Rotate_datatype: lsr_write_fixed_16_8(lsr, ((SVG_Point_Angle*)val)->angle, "rotate"); 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: if (n->type==SVG_NUMBER_INHERIT) { GF_LSR_WRITE_INT(lsr, 1, 1, "isDefaultValue"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "isDefaultValue"); lsr_write_fixed_16_8(lsr, n->value, "val"); } break; case TAG_SVG_ATT_width: case TAG_SVG_ATT_height: if (elt->sgprivate->tag==TAG_SVG_svg) { lsr_write_value_with_units(lsr, n, "val"); } else { lsr_write_coordinate(lsr, n->value, 0, "val"); } break; default: if (n->type==SVG_NUMBER_INHERIT) { GF_LSR_WRITE_INT(lsr, 1, 1, "isDefaultValue"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "isDefaultValue"); GF_LSR_WRITE_INT(lsr, 0, 1, "escapeFlag"); lsr_write_fixed_16_8(lsr, n->value, "val"); } } break; case SVG_Rotate_datatype: n = (SVG_Number*)val; if (n->type==SVG_NUMBER_INHERIT) { GF_LSR_WRITE_INT(lsr, 1, 1, "isDefaultValue"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "isDefaultValue"); if ((n->type == SVG_NUMBER_AUTO) || (n->type == SVG_NUMBER_AUTO_REVERSE)) { GF_LSR_WRITE_INT(lsr, 1, 1, "escapeFlag"); GF_LSR_WRITE_INT(lsr, (n->type == SVG_NUMBER_AUTO) ? 0 : 1, 2, "rotate"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "escapeFlag"); lsr_write_fixed_16_8(lsr, n->value, "rotate"); } } break; case SVG_Coordinate_datatype: n = (SVG_Number*)val; lsr_write_coordinate(lsr, n->value, 0, "val"); break; case SVG_Coordinates_datatype: GF_LSR_WRITE_INT(lsr, 0, 1, "isInherit"); GF_LSR_WRITE_INT(lsr, 0, 1, "escapeFlag"); lsr_write_float_list(lsr, (GF_List **)val, "val"); break; case XMLRI_datatype: if ((att_tag==TAG_SVG_ATT_xlink_href) || (att_tag==TAG_SVG_ATT_syncReference)) { lsr_write_any_uri(lsr, (XMLRI*)val, "val"); } else if (((XMLRI*)val)->target) { GF_LSR_WRITE_INT(lsr, 0, 1, "isDefault"); GF_LSR_WRITE_INT(lsr, 0, 1, "isEscape"); lsr_write_vluimsbf5(lsr, gf_node_get_id( ((XMLRI*)val)->target) - 1, "ID"); } else { GF_LSR_WRITE_INT(lsr, 1, 1, "isDefault"); } break; case SVG_Focus_datatype: if ( (((SVG_Focus*)val)->type == SVG_FOCUS_AUTO) || !((SVG_Focus*)val)->target.target) { GF_LSR_WRITE_INT(lsr, 1, 1, "isDefault"); } else if (((SVG_Focus*)val)->type == SVG_FOCUS_SELF) { GF_LSR_WRITE_INT(lsr, 0, 1, "isDefault"); GF_LSR_WRITE_INT(lsr, 1, 1, "isEscape"); GF_LSR_WRITE_INT(lsr, 1, 2, "escapeEnumVal"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "isDefault"); GF_LSR_WRITE_INT(lsr, 0, 1, "isEscape"); lsr_write_vluimsbf5(lsr, gf_node_get_id( ((SVG_Focus*)val)->target.target) - 1, "ID"); } break; case SVG_String_datatype: case SVG_ContentType_datatype: case SVG_LanguageID_datatype: lsr_write_byte_align_string(lsr, val ? *(DOM_String *)val : (char *)"", "val"); break; case SVG_Motion_datatype: lsr_write_coordinate(lsr, ((GF_Matrix2D *)val)->m[2], 0, "pointValueX"); lsr_write_coordinate(lsr, ((GF_Matrix2D *)val)->m[5], 0, "pointValueY"); break; case SVG_Points_datatype: lsr_write_point_sequence(lsr, (GF_List **)val, "val"); break; case SVG_PathData_datatype: lsr_write_path_type(lsr, (SVG_PathData*)val, "val"); break; case LASeR_Choice_datatype: { LASeR_Choice *ch = (LASeR_Choice *)val; GF_LSR_WRITE_INT(lsr, (ch->type==LASeR_CHOICE_ALL) ? 1 : 0, 1, "isDefaultValue"); if (ch->type!=LASeR_CHOICE_ALL) { GF_LSR_WRITE_INT(lsr, (ch->type==LASeR_CHOICE_NONE) ? 1 : 0, 1, "escapeFlag"); if (ch->type==LASeR_CHOICE_NONE) { GF_LSR_WRITE_INT(lsr, LASeR_CHOICE_NONE, 2, "escapeEnum"); } else { lsr_write_vluimsbf5(lsr, ((LASeR_Choice *)val)->choice_index, "value"); } } } break; case SVG_ViewBox_datatype: { SVG_ViewBox *b = (SVG_ViewBox *)val; GF_LSR_WRITE_INT(lsr, 0, 1, "isDefaultValue"); GF_LSR_WRITE_INT(lsr, 0, 1, "escapeFlag"); lsr_write_vluimsbf5(lsr, 4, "nb1"); lsr_write_fixed_16_8(lsr, b->x, "x"); lsr_write_fixed_16_8(lsr, b->y, "y"); lsr_write_fixed_16_8(lsr, b->width, "width"); lsr_write_fixed_16_8(lsr, b->width, "height"); } break; case SVG_FontFamily_datatype: { SVG_FontFamily *ff = (SVG_FontFamily *)val; GF_LSR_WRITE_INT(lsr, (ff->type == SVG_FONTFAMILY_INHERIT) ? 1 : 0, 1, "isDefaultValue"); if (ff->type != SVG_FONTFAMILY_INHERIT) { u32 idx = lsr_get_font_index(lsr, ff); if (idx==-1) { GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] corrupted font table while encoding update value\n")); idx=0; } GF_LSR_WRITE_INT(lsr, 0, 1, "escapeFlag"); lsr_write_vluimsbf5(lsr, idx, "nb1"); } } break; default: if ((fieldType>=SVG_FillRule_datatype) && (fieldType<=SVG_LAST_U8_PROPERTY)) { u8 v = *(u8 *)val; /*TODO fixme, check inherit/default values*/ if (!v) { GF_LSR_WRITE_INT(lsr, 1, 1, "isDefaultValue"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "isDefaultValue"); lsr_write_vluimsbf5(lsr, v, "val"); } } else { GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[LASeR] update value not implemented for type %d - please fix or report\n", fieldType)); } } } } /*FIXME - support for scale/translate/rotation*/ static GF_Err lsr_write_add_replace_insert(GF_LASeRCodec *lsr, GF_Command *com) { GF_CommandField *field; u8 type = 0; Bool is_text_node = 0; u32 field_type, tr_type = 0; if (com->tag==GF_SG_LSR_REPLACE) type = LSR_UPDATE_REPLACE; else if (com->tag==GF_SG_LSR_ADD) type = LSR_UPDATE_ADD; else if (com->tag==GF_SG_LSR_INSERT) type = LSR_UPDATE_INSERT; else return GF_BAD_PARAM; GF_LSR_WRITE_INT(lsr, type, 4, "ch4"); field = (GF_CommandField*)gf_list_get(com->command_fields, 0); field_type = 0; if (field && ( !field->new_node || (field->fieldIndex==TAG_LSR_ATT_children) ) && !field->node_list) { s32 attType = 0; field_type = field->fieldType; attType = gf_lsr_anim_type_from_attribute(field->fieldIndex); if (attType== -1) { GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[LASeR] Attribute %s of element %s is not updatable\n", gf_svg_get_attribute_name(field->fieldIndex), gf_node_get_class_name(com->node) )); return lsr->last_error = GF_BAD_PARAM; } GF_LSR_WRITE_INT(lsr, 1, 1, "has_attributeName"); GF_LSR_WRITE_INT(lsr, 0, 1, "choice"); GF_LSR_WRITE_INT(lsr, attType, 8, "attributeName"); } /*single text */ else if (field->new_node->sgprivate->tag==TAG_DOMText) { GF_LSR_WRITE_INT(lsr, 1, 1, "has_attributeName"); GF_LSR_WRITE_INT(lsr, 0, 1, "choice"); GF_LSR_WRITE_INT(lsr, LSR_UPDATE_TYPE_TEXT_CONTENT, 8, "attributeName"); is_text_node = 1; } else { GF_LSR_WRITE_INT(lsr, 0, 1, "has_attributeName"); } /*if not add*/ if (type!=LSR_UPDATE_ADD) { if (!field || field->pos<0) { GF_LSR_WRITE_INT(lsr, 0, 1, "has_index"); } else { GF_LSR_WRITE_INT(lsr, 1, 1, "has_index"); lsr_write_vluimsbf5(lsr, (u32) field->pos, "index"); } } if (type!=LSR_UPDATE_INSERT) { if (com->fromNodeID) { GF_Node *opNode; u8 opAttType; opNode = gf_sg_find_node(lsr->sg, com->fromNodeID); opAttType = gf_lsr_anim_type_from_attribute(com->fromFieldIndex); GF_LSR_WRITE_INT(lsr, 1, 1, "has_operandAttribute"); GF_LSR_WRITE_INT(lsr, opAttType, 8, "operandAttribute"); GF_LSR_WRITE_INT(lsr, 1, 1, "has_operandElementId"); lsr_write_vluimsbf5(lsr, com->fromNodeID-1, "operandElementId"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "has_operandAttribute"); GF_LSR_WRITE_INT(lsr, 0, 1, "has_operandElementId"); } } lsr_write_codec_IDREF_Node(lsr, com->node, "ref"); if (field && !field->new_node && !field->node_list && !com->fromNodeID) { GF_LSR_WRITE_INT(lsr, 1, 1, "has_value"); lsr_write_update_value(lsr, (SVG_Element *)com->node, field_type, field->fieldIndex, tr_type, field->field_ptr, (field->pos>=0) ? 1 : 0); } else if (is_text_node) { GF_DOMText *t = (GF_DOMText *)field->new_node; GF_LSR_WRITE_INT(lsr, 1, 1, "has_value"); lsr_write_update_value(lsr, (SVG_Element *)com->node, SVG_String_datatype, field->fieldIndex, 0, &t->textContent, (field->pos>=0) ? 1 : 0); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "has_value"); } lsr_write_any_attribute(lsr, NULL, 1); /*if not add*/ if (type!=LSR_UPDATE_ADD) { if (field && field->node_list && !com->fromNodeID) { GF_ChildNodeItem *l = field->node_list; u32 count = gf_node_list_get_count(l); GF_LSR_WRITE_INT(lsr, 1, 1, "opt_group"); if (type==LSR_UPDATE_REPLACE) lsr_write_vluimsbf5(lsr, count, "count"); while (l) { lsr_write_update_content_model(lsr, (SVG_Element*) com->node, l->node); l = l->next; if (type==LSR_UPDATE_INSERT) break; } } else if (field && field->new_node && !is_text_node) { GF_LSR_WRITE_INT(lsr, 1, 1, "opt_group"); if (type==LSR_UPDATE_REPLACE) lsr_write_vluimsbf5(lsr, 1, "count"); lsr_write_update_content_model(lsr, (SVG_Element*) com->node, field->new_node); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "opt_group"); } } return GF_OK; } static GF_Err lsr_write_command_list(GF_LASeRCodec *lsr, GF_List *com_list, SVG_Element *cond, Bool first_implicit) { GF_CommandField *field; u32 i, count; GF_BitStream *old_bs; count = com_list ? gf_list_count(com_list) : 0; old_bs = NULL; if (cond) { /*use temp bitstream for encoding conditional*/ old_bs = lsr->bs; lsr->bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); } assert(count>=first_implicit); lsr_write_vluimsbf5(lsr, count-first_implicit, "occ0"); if (!com_list) goto exit; count = gf_list_count(com_list); for (i=0; itag) { case GF_SG_LSR_NEW_SCENE: case GF_SG_LSR_REFRESH_SCENE: GF_LSR_WRITE_INT(lsr, (com->tag==GF_SG_LSR_REFRESH_SCENE) ? LSR_UPDATE_REFRESH_SCENE : LSR_UPDATE_NEW_SCENE, 4, "ch4"); if (com->tag==GF_SG_LSR_REFRESH_SCENE) lsr_write_vluimsbf5(lsr, /*refresh scene time*/0, "time"); lsr_write_any_attribute(lsr, NULL, 1); lsr_write_svg(lsr, (SVG_Element*)com->node); break; case GF_SG_LSR_REPLACE: case GF_SG_LSR_ADD: case GF_SG_LSR_INSERT: lsr_write_add_replace_insert(lsr, com); break; case GF_SG_LSR_CLEAN: break; case GF_SG_LSR_DELETE: GF_LSR_WRITE_INT(lsr, LSR_UPDATE_DELETE, 4, "ch4"); field = (GF_CommandField*)gf_list_get(com->command_fields, 0); if (field && field->fieldType) { u8 attType; attType = gf_lsr_anim_type_from_attribute(field->fieldIndex); GF_LSR_WRITE_INT(lsr, 1, 1, "has_attributeName"); GF_LSR_WRITE_INT(lsr, 0, 1, "choice"); GF_LSR_WRITE_INT(lsr, attType, 8, "attributeName"); } else { GF_LSR_WRITE_INT(lsr, 0, 1, "has_attributeName"); } if (!field || (field->pos<0) ) { GF_LSR_WRITE_INT(lsr, 0, 1, "has_index"); } else { GF_LSR_WRITE_INT(lsr, 1, 1, "has_index"); lsr_write_vluimsbf5(lsr, (u32) field->pos, "index"); } lsr_write_codec_IDREF_Node(lsr, com->node, "ref"); lsr_write_any_attribute(lsr, NULL, 1); break; case GF_SG_LSR_RESTORE: break; case GF_SG_LSR_SAVE: break; case GF_SG_LSR_SEND_EVENT: break; case GF_SG_LSR_ACTIVATE: case GF_SG_LSR_DEACTIVATE: { u32 update_size = lsr_get_IDREF_nb_bits(lsr, com->node); GF_LSR_WRITE_INT(lsr, LSR_UPDATE_EXTEND, 4, "ch4"); GF_LSR_WRITE_INT(lsr, 2, lsr->info->cfg.extensionIDBits, "extensionID"); lsr_write_vluimsbf5(lsr, 10 + 5 /*occ2*/ + 2 /*reserved*/ + 5 /*occ3*/ + 2 /*ch5*/ + update_size, "len"); lsr_write_vluimsbf5(lsr, 87, "reserved"); lsr_write_vluimsbf5(lsr, 1, "occ2"); GF_LSR_WRITE_INT(lsr, 1, 2, "reserved"); lsr_write_vluimsbf5(lsr, 1, "occ3"); GF_LSR_WRITE_INT(lsr, (com->tag==GF_SG_LSR_ACTIVATE) ? 1 : 2, 2, "ch5"); lsr_write_codec_IDREF_Node(lsr, com->node, "ref"); } break; default: return GF_BAD_PARAM; } /*same-coding scope is command-based (to check in the spec)*/ 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) break; } exit: /*script is aligned*/ if (cond) { char *data; u32 data_size; gf_bs_get_content(lsr->bs, &data, &data_size); gf_bs_del(lsr->bs); lsr->bs = old_bs; lsr_write_vluimsbf5(lsr, data_size, NULL/*"encoding-length" - don't log to avoid corrupting the log order!!*/); /*script is aligned*/ gf_bs_align(lsr->bs); gf_bs_write_data(lsr->bs, data, data_size); free(data); } return lsr->last_error; } static void lsr_add_color(GF_LASeRCodec *lsr, SVG_Color *color) { lsr->col_table = (LSRCol*)realloc(lsr->col_table, sizeof(LSRCol)*(lsr->nb_cols+1)); lsr->col_table[lsr->nb_cols].r = FIX2INT(color->red*lsr->color_scale); lsr->col_table[lsr->nb_cols].g = FIX2INT(color->green*lsr->color_scale); lsr->col_table[lsr->nb_cols].b = FIX2INT(color->blue*lsr->color_scale); lsr->nb_cols++; } static void lsr_check_col_index(GF_LASeRCodec *lsr, SVG_Color *color, SVG_Paint *paint) { s32 idx; if (color) { idx = lsr_get_col_index(lsr, color); if (idx==-2) lsr_add_color(lsr, color); } else if (paint && (paint->type==SVG_PAINT_COLOR) ) { idx = lsr_get_col_index(lsr, &paint->color); if (idx==-2) lsr_add_color(lsr, &paint->color); } } static void lsr_check_font_index(GF_LASeRCodec *lsr, SVG_FontFamily *font) { u32 count, i; if (font && (font->type == SVG_FONTFAMILY_VALUE) && font->value) { Bool found = 0; count = gf_list_count(lsr->font_table); for (i=0; ifont_table, i); if (!strcmp(ff, font->value)) { found = 1; break; } } if (!found) gf_list_add(lsr->font_table, strdup(font->value)); } } static void lsr_check_font_and_color(GF_LASeRCodec *lsr, SVG_Element *elt) { GF_ChildNodeItem *l; SVGAttribute *att; u32 i, count, tag; u32 check_anim_font, check_anim_col; tag = gf_node_get_tag((GF_Node*)elt); if (tag < GF_NODE_FIRST_DOM_NODE_TAG) goto check_children; check_anim_font = check_anim_col = 0; att = elt->attributes; while (att) { switch (att->data_type) { case SVG_Paint_datatype: lsr_check_col_index(lsr, NULL, att->data); break; case SVG_FontFamily_datatype: lsr_check_font_index(lsr, att->data); break; case SMIL_AttributeName_datatype: { SMIL_AttributeName *an = (SMIL_AttributeName*)att->data; if (an->name) { if (!strcmp(an->name, "fill")) check_anim_col = 1; /*we're sure this is not SMIL fill, it is not animatable*/ else if (!strcmp(an->name, "stroke")) check_anim_col = 1; else if (!strcmp(an->name, "color")) check_anim_col = 1; else if (!strcmp(an->name, "solid-olor")) check_anim_col = 2; else if (!strcmp(an->name, "stop-color")) check_anim_col = 2; else if (!strcmp(an->name, "font-family")) check_anim_font = 1; } } break; } att = att->next; } if (check_anim_font || check_anim_col) { att = elt->attributes; while (att) { switch (att->data_type) { case SMIL_AnimateValue_datatype: if (check_anim_font) lsr_check_font_index(lsr, ((SMIL_AnimateValue*)att->data)->value); else if (check_anim_col == 1) lsr_check_col_index(lsr, NULL, ((SMIL_AnimateValue*)att->data)->value); else if (check_anim_col == 2) lsr_check_col_index(lsr, ((SMIL_AnimateValue*)att->data)->value, NULL); break; case SMIL_AnimateValues_datatype: { SMIL_AnimateValues *vals = (SMIL_AnimateValues*)att->data; count = gf_list_count(vals->values); for (i=0; ivalues, i)); else if (check_anim_col == 1) lsr_check_col_index(lsr, NULL, (SVG_Paint*)gf_list_get(vals->values, i) ); else if (check_anim_col == 2) lsr_check_col_index(lsr, (SVG_Color*)gf_list_get(vals->values, i), NULL); } } break; } att = att->next; } } check_children: l = elt->children; while (l) { if (l->node->sgprivate->tag==TAG_DOMUpdates) { GF_DOMUpdates *up = (GF_DOMUpdates *)l->node; count = gf_list_count(up->updates); for (i=0; iupdates, i); c2 = gf_list_count(com->command_fields); for (j=0; jcommand_fields, j); if (field->new_node) { lsr_check_font_and_color(lsr, (SVG_Element*)field->new_node); } /*replace/insert*/ else if (field->field_ptr) { switch (field->fieldType) { case SVG_Paint_datatype: lsr_check_col_index(lsr, NULL, (SVG_Paint*)field->field_ptr); break; case SVG_Color_datatype: lsr_check_col_index(lsr, (SVG_Color*)field->field_ptr, NULL); break; case SVG_FontFamily_datatype: lsr_check_font_index(lsr, (SVG_FontFamily*)field->field_ptr); break; } } } } } else { lsr_check_font_and_color(lsr, (SVG_Element*)l->node); } l = l->next; } } static GF_Err lsr_write_laser_unit(GF_LASeRCodec *lsr, GF_List *com_list, Bool reset_encoding_context) { u32 i, count, prev_col_count, prev_font_count; /* * 1 - laser unit header */ if (!com_list) { if (gf_sg_get_root_node(lsr->sg) == NULL) return GF_BAD_PARAM; /*RAP generation, force reset encoding context*/ GF_LSR_WRITE_INT(lsr, 1, 1, "resetEncodingContext"); } else { GF_LSR_WRITE_INT(lsr, reset_encoding_context ? 1 : 0, 1, "resetEncodingContext"); } GF_LSR_WRITE_INT(lsr, 0, 1, "opt_group"); if (0) lsr_write_extension(lsr, NULL, 0, "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); } } /* * 2 - codecInitialisations */ prev_col_count = lsr->nb_cols; prev_font_count = gf_list_count(lsr->font_table); /*RAP generation, send all fonts and colors*/ if (!com_list) { prev_col_count = prev_font_count = 0; lsr_check_font_and_color(lsr, (SVG_Element *)gf_sg_get_root_node(lsr->sg)); } else { /*process all colors and fonts*/ count = gf_list_count(com_list); for (i=0; icommand_fields)) { GF_CommandField *field = (GF_CommandField *)gf_list_get(com->command_fields, 0); if (field->fieldType==SVG_Paint_datatype) lsr_check_col_index(lsr, NULL, (SVG_Paint*)field->field_ptr); else if (field->fieldType==SVG_FontFamily_datatype) lsr_check_font_index(lsr, (SVG_FontFamily*)field->field_ptr); else if (field->new_node) lsr_check_font_and_color(lsr, (SVG_Element*)field->new_node); else if (field->node_list) { GF_ChildNodeItem *l = field->node_list; while (l) { lsr_check_font_and_color(lsr, (SVG_Element*)l->node); l = l->next; } } } else if (com->node && (com->tag!=GF_SG_LSR_DELETE) ) { lsr_check_font_and_color(lsr, (SVG_Element *)com->node); } } } /* * 2.a - condecInitialization.color */ if (prev_col_count == lsr->nb_cols) { GF_LSR_WRITE_INT(lsr, 0, 1, "colorInitialisation"); } else { GF_LSR_WRITE_INT(lsr, 1, 1, "colorInitialisation"); lsr_write_vluimsbf5(lsr, lsr->nb_cols - prev_col_count, "count"); for (i=prev_col_count; inb_cols; i++) { GF_LSR_WRITE_INT(lsr, lsr->col_table[i].r, lsr->info->cfg.colorComponentBits, "red"); GF_LSR_WRITE_INT(lsr, lsr->col_table[i].g, lsr->info->cfg.colorComponentBits, "green"); GF_LSR_WRITE_INT(lsr, lsr->col_table[i].b, lsr->info->cfg.colorComponentBits, "blue"); } } lsr->colorIndexBits = gf_get_bit_size(lsr->nb_cols); /* * 2.b - condecInitialization.fonts */ count = gf_list_count(lsr->font_table); if (prev_font_count == count) { GF_LSR_WRITE_INT(lsr, 0, 1, "fontInitialisation"); } else { GF_LSR_WRITE_INT(lsr, 1, 1, "fontInitialisation"); lsr_write_vluimsbf5(lsr, count - prev_font_count, "count"); for (i=prev_font_count; ifont_table, i); lsr_write_byte_align_string(lsr, ft, "font"); } } lsr->fontIndexBits = gf_get_bit_size(count); /* * 2.c - condecInitialization.private */ GF_LSR_WRITE_INT(lsr, 0, 1, "privateDataIdentifierInitialisation"); /* * 2.d - condecInitialization.anyXML */ GF_LSR_WRITE_INT(lsr, 0, 1, "anyXMLInitialisation"); /* * 2.e - condecInitialization.extended */ /*FIXME - node string IDs are currently not used*/ lsr_write_vluimsbf5(lsr, 0, "countG"); /*FIXME - global streams are currently not used*/ GF_LSR_WRITE_INT(lsr, 0, 1, "hasExtension"); /*RAP generation, encode NewScene with root node*/ if (!com_list) { lsr_write_vluimsbf5(lsr, 0, "occ0"); GF_LSR_WRITE_INT(lsr, 4, 4, "ch4"); lsr_write_any_attribute(lsr, NULL, 1); lsr_write_svg(lsr, (SVG_Element *)gf_sg_get_root_node(lsr->sg) ); } else { GF_Err e = lsr_write_command_list(lsr, com_list, NULL, 1); if (e) return e; } GF_LSR_WRITE_INT(lsr, 0, 1, "opt_group"); if (0) lsr_write_extension(lsr, NULL, 0, "ext"); return GF_OK; }