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