LCOV - code coverage report
Current view: top level - scenegraph - svg_types.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 184 258 71.3 %
Date: 2021-04-29 23:48:07 Functions: 12 13 92.3 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Cyril Concolato, Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2004-2019
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / SVG Scene Graph 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/scenegraph_dev.h>
      27             : 
      28             : #ifndef GPAC_DISABLE_SVG
      29             : #include <gpac/nodes_svg.h>
      30             : 
      31             : GF_EXPORT
      32       24622 : Bool gf_svg_is_animation_tag(u32 tag)
      33             : {
      34       49244 :         return (tag == TAG_SVG_set ||
      35       24622 :                 tag == TAG_SVG_animate ||
      36       38008 :                 tag == TAG_SVG_animateColor ||
      37       19004 :                 tag == TAG_SVG_animateTransform ||
      38       37274 :                 tag == TAG_SVG_animateMotion ||
      39       18637 :                 tag == TAG_SVG_discard
      40       43259 :                ) ? 1 : 0;
      41             : }
      42             : 
      43       13845 : Bool gf_svg_is_timing_tag(u32 tag)
      44             : {
      45       13845 :         if (gf_svg_is_animation_tag(tag)) return 1;
      46       13287 :         else return (tag == TAG_SVG_animation ||
      47       13287 :                              tag == TAG_SVG_audio ||
      48       13287 :                              tag == TAG_LSR_conditional ||
      49       26346 :                              tag == TAG_LSR_updates ||
      50       39633 :                              tag == TAG_SVG_video)? GF_TRUE : GF_FALSE;
      51             : }
      52             : 
      53        5179 : SVG_Element *gf_svg_create_node(u32 ElementTag)
      54             : {
      55             :         SVG_Element *p;
      56        5179 :         if (gf_svg_is_timing_tag(ElementTag)) {
      57             :                 SVGTimedAnimBaseElement *tap;
      58         338 :                 GF_SAFEALLOC(tap, SVGTimedAnimBaseElement);
      59             :                 p = (SVG_Element *)tap;
      60        4841 :         } else if (ElementTag == TAG_SVG_handler) {
      61             :                 SVG_handlerElement *hdl;
      62          59 :                 GF_SAFEALLOC(hdl, SVG_handlerElement);
      63             :                 p = (SVG_Element *)hdl;
      64             :         } else {
      65        4782 :                 GF_SAFEALLOC(p, SVG_Element);
      66             :         }
      67        5179 :         if (!p) return NULL;
      68        5179 :         gf_node_setup((GF_Node *)p, ElementTag);
      69        5179 :         gf_sg_parent_setup((GF_Node *) p);
      70        5179 :         return p;
      71             : }
      72             : 
      73        5179 : void gf_svg_node_del(GF_Node *node)
      74             : {
      75             :         SVG_Element *p = (SVG_Element *)node;
      76             : 
      77        5179 :         if (p->sgprivate->interact && p->sgprivate->interact->animations) {
      78          49 :                 gf_smil_anim_delete_animations((GF_Node *)p);
      79             :         }
      80        5179 :         if (p->sgprivate->tag==TAG_SVG_listener) {
      81             :                 /*remove from target's listener list*/
      82          68 :                 gf_dom_event_remove_listener_from_parent((GF_DOMEventTarget *)node->sgprivate->UserPrivate, (GF_Node *)p);
      83             :         }
      84             :         /*if this is a handler with a UserPrivate, this is a handler with an implicit listener
      85             :         (eg handler with ev:event=""). Destroy the associated listener*/
      86        5179 :         if (p->sgprivate->tag==TAG_SVG_handler) {
      87          59 :                 GF_Node *listener = p->sgprivate->UserPrivate;
      88          59 :                 if (listener && (listener->sgprivate->tag==TAG_SVG_listener)) {
      89             :                         GF_FieldInfo info;
      90           0 :                         if (gf_node_get_attribute_by_tag(listener, TAG_XMLEV_ATT_handler, 0, 0, &info) == GF_OK) {
      91           0 :                                 XMLRI *iri = (XMLRI *)info.far_ptr;
      92           0 :                                 if (iri->target) {
      93             :                                         assert(iri->target==p);
      94           0 :                                         iri->target = NULL;
      95             :                                 }
      96             :                         }
      97           0 :                         gf_node_unregister(listener, NULL);
      98             : //                      gf_svg_node_del(listener);
      99             :                 }
     100             :         }
     101             :         /*remove this node from associated listeners*/
     102        5179 :         if (node->sgprivate->interact && node->sgprivate->interact->dom_evt) {
     103             :                 u32 i, count;
     104          28 :                 count = gf_dom_listener_count(node);
     105          52 :                 for (i=0; i<count; i++) {
     106          24 :                         GF_Node *listener = (GF_Node *)gf_list_get(node->sgprivate->interact->dom_evt->listeners, i);
     107          24 :                         listener->sgprivate->UserPrivate = NULL;
     108             :                 }
     109             :         }
     110             : 
     111        5179 :         if (gf_svg_is_timing_tag(node->sgprivate->tag)) {
     112             :                 SVGTimedAnimBaseElement *tap = (SVGTimedAnimBaseElement *)node;
     113         338 :                 if (tap->animp) {
     114          67 :                         gf_free(tap->animp);
     115          67 :                         gf_smil_anim_remove_from_target((GF_Node *)tap, (GF_Node *)tap->xlinkp->href->target);
     116             :                 }
     117         338 :                 if (tap->timingp)            {
     118          80 :                         gf_smil_timing_delete_runtime_info((GF_Node *)tap, tap->timingp->runtime);
     119          80 :                         gf_free(tap->timingp);
     120             :                 }
     121         338 :                 if (tap->xlinkp)     gf_free(tap->xlinkp);
     122             :         }
     123             : 
     124        5179 :         gf_node_delete_attributes(node);
     125        5179 :         gf_sg_parent_reset(node);
     126        5179 :         gf_node_free(node);
     127        5179 : }
     128             : 
     129       32928 : Bool gf_svg_node_init(GF_Node *node)
     130             : {
     131       32928 :         switch (node->sgprivate->tag) {
     132           7 :         case TAG_SVG_script:
     133           7 :                 if (node->sgprivate->scenegraph->script_load)
     134           3 :                         node->sgprivate->scenegraph->script_load(node);
     135             :                 return 1;
     136             : 
     137           0 :         case TAG_SVG_handler:
     138           0 :                 if (node->sgprivate->scenegraph->script_load)
     139           0 :                         node->sgprivate->scenegraph->script_load(node);
     140           0 :                 if (node->sgprivate->scenegraph->script_action)
     141           0 :                         ((SVG_handlerElement*)node)->handle_event = gf_sg_handle_dom_event;
     142             :                 return 1;
     143           1 :         case TAG_LSR_conditional:
     144           1 :                 gf_smil_timing_init_runtime_info(node);
     145           1 :                 gf_smil_setup_events(node);
     146           1 :                 return 1;
     147          68 :         case TAG_SVG_animateMotion:
     148             :         case TAG_SVG_set:
     149             :         case TAG_SVG_animate:
     150             :         case TAG_SVG_animateColor:
     151             :         case TAG_SVG_animateTransform:
     152          68 :                 gf_smil_anim_init_node(node);
     153          68 :                 gf_smil_setup_events(node);
     154             :                 /*we may get called several times depending on xlink:href resoling for events*/
     155          68 :                 return (node->sgprivate->UserPrivate || node->sgprivate->UserCallback) ? 1 : 0;
     156           4 :         case TAG_SVG_audio:
     157             :         case TAG_SVG_video:
     158             :         case TAG_LSR_updates:
     159           4 :                 gf_smil_timing_init_runtime_info(node);
     160           4 :                 gf_smil_setup_events(node);
     161             :                 /*we may get called several times depending on xlink:href resoling for events*/
     162           4 :                 return (node->sgprivate->UserPrivate || node->sgprivate->UserCallback) ? 1 : 0;
     163           7 :         case TAG_SVG_animation:
     164           7 :                 gf_smil_timing_init_runtime_info(node);
     165           7 :                 gf_smil_setup_events(node);
     166           7 :                 return 0;
     167             :         /*discard is implemented as a special animation element */
     168           0 :         case TAG_SVG_discard:
     169           0 :                 gf_smil_anim_init_discard(node);
     170           0 :                 gf_smil_setup_events(node);
     171           0 :                 return 1;
     172             :         default:
     173             :                 return 0;
     174             :         }
     175             :         return 0;
     176             : }
     177             : 
     178       61235 : Bool gf_svg_node_changed(GF_Node *node, GF_FieldInfo *field)
     179             : {
     180       61235 :         switch (node->sgprivate->tag) {
     181           8 :         case TAG_SVG_animateMotion:
     182             :         case TAG_SVG_discard:
     183             :         case TAG_SVG_set:
     184             :         case TAG_SVG_animate:
     185             :         case TAG_SVG_animateColor:
     186             :         case TAG_SVG_animateTransform:
     187             :         case TAG_LSR_conditional:
     188           8 :                 gf_smil_timing_modified(node, field);
     189           8 :                 return 1;
     190           0 :         case TAG_SVG_animation:
     191             :         case TAG_SVG_audio:
     192             :         case TAG_SVG_video:
     193             :         case TAG_LSR_updates:
     194           0 :                 gf_smil_timing_modified(node, field);
     195             :                 /*used by compositors*/
     196           0 :                 return 0;
     197             :         }
     198             :         return 0;
     199             : }
     200             : 
     201             : 
     202             : #if 0 //unused
     203             : void gf_svg_reset_path(SVG_PathData d)
     204             : {
     205             : #if USE_GF_PATH
     206             :         gf_path_reset(&d);
     207             : #else
     208             :         u32 i, count;
     209             :         count = gf_list_count(d.commands);
     210             :         for (i = 0; i < count; i++) {
     211             :                 u8 *command = (u8 *)gf_list_get(d.commands, i);
     212             :                 gf_free(command);
     213             :         }
     214             :         gf_list_del(d.commands);
     215             :         count = gf_list_count(d.points);
     216             :         for (i = 0; i < count; i++) {
     217             :                 SVG_Point *pt = (SVG_Point *)gf_list_get(d.points, i);
     218             :                 gf_free(pt);
     219             :         }
     220             :         gf_list_del(d.points);
     221             : #endif
     222             : }
     223             : #endif
     224             : 
     225             : 
     226             : /* TODO: update for elliptical arcs */
     227             : #if USE_GF_PATH
     228           0 : void gf_svg_path_build(GF_Path *path, GF_List *commands, GF_List *points)
     229             : {
     230             :         u32 i, j, command_count;
     231             :         SVG_Point orig, ct_orig, ct_end, end, *tmp;
     232           0 :         command_count = gf_list_count(commands);
     233             :         orig.x = orig.y = ct_orig.x = ct_orig.y = 0;
     234             : 
     235           0 :         for (i=0, j=0; i<command_count; i++) {
     236           0 :                 u8 *command = (u8 *)gf_list_get(commands, i);
     237           0 :                 switch (*command) {
     238           0 :                 case SVG_PATHCOMMAND_M: /* Move To */
     239           0 :                         tmp = (SVG_Point*)gf_list_get(points, j);
     240           0 :                         orig = *tmp;
     241           0 :                         gf_path_add_move_to(path, orig.x, orig.y);
     242           0 :                         j++;
     243             :                         /*provision for nextCurveTo when no curve is specified:
     244             :                                 "If there is no previous command or if the previous command was not an C, c, S or s,
     245             :                                 assume the first control point is coincident with the current point.
     246             :                         */
     247             :                         ct_orig = orig;
     248           0 :                         break;
     249           0 :                 case SVG_PATHCOMMAND_L: /* Line To */
     250           0 :                         tmp = (SVG_Point*)gf_list_get(points, j);
     251           0 :                         end = *tmp;
     252             : 
     253           0 :                         gf_path_add_line_to(path, end.x, end.y);
     254           0 :                         j++;
     255             :                         orig = end;
     256             :                         /*cf above*/
     257             :                         ct_orig = orig;
     258           0 :                         break;
     259           0 :                 case SVG_PATHCOMMAND_C: /* Curve To */
     260           0 :                         tmp = (SVG_Point*)gf_list_get(points, j);
     261           0 :                         ct_orig = *tmp;
     262           0 :                         tmp = (SVG_Point*)gf_list_get(points, j+1);
     263           0 :                         ct_end = *tmp;
     264           0 :                         tmp = (SVG_Point*)gf_list_get(points, j+2);
     265           0 :                         end = *tmp;
     266           0 :                         gf_path_add_cubic_to(path, ct_orig.x, ct_orig.y, ct_end.x, ct_end.y, end.x, end.y);
     267             :                         ct_orig = ct_end;
     268             :                         orig = end;
     269           0 :                         j+=3;
     270           0 :                         break;
     271           0 :                 case SVG_PATHCOMMAND_S: /* Next Curve To */
     272           0 :                         ct_orig.x = 2*orig.x - ct_orig.x;
     273           0 :                         ct_orig.y = 2*orig.y - ct_orig.y;
     274           0 :                         tmp = (SVG_Point*)gf_list_get(points, j);
     275           0 :                         ct_end = *tmp;
     276           0 :                         tmp = (SVG_Point*)gf_list_get(points, j+1);
     277           0 :                         end = *tmp;
     278           0 :                         gf_path_add_cubic_to(path, ct_orig.x, ct_orig.y, ct_end.x, ct_end.y, end.x, end.y);
     279             :                         ct_orig = ct_end;
     280             :                         orig = end;
     281           0 :                         j+=2;
     282           0 :                         break;
     283           0 :                 case SVG_PATHCOMMAND_Q: /* Quadratic Curve To */
     284           0 :                         tmp = (SVG_Point*)gf_list_get(points, j);
     285           0 :                         ct_orig = *tmp;
     286           0 :                         tmp = (SVG_Point*)gf_list_get(points, j+1);
     287           0 :                         end = *tmp;
     288           0 :                         gf_path_add_quadratic_to(path, ct_orig.x, ct_orig.y, end.x, end.y);
     289             :                         orig = end;
     290           0 :                         j+=2;
     291           0 :                         break;
     292           0 :                 case SVG_PATHCOMMAND_T: /* Next Quadratic Curve To */
     293           0 :                         ct_orig.x = 2*orig.x - ct_orig.x;
     294           0 :                         ct_orig.y = 2*orig.y - ct_orig.y;
     295           0 :                         tmp = (SVG_Point*)gf_list_get(points, j);
     296           0 :                         end = *tmp;
     297           0 :                         gf_path_add_quadratic_to(path, ct_orig.x, ct_orig.y, end.x, end.y);
     298             :                         orig = end;
     299           0 :                         j++;
     300           0 :                         break;
     301           0 :                 case SVG_PATHCOMMAND_Z: /* Close */
     302           0 :                         gf_path_close(path);
     303           0 :                         break;
     304             :                 }
     305             :         }
     306           0 : }
     307             : #endif
     308             : 
     309             : 
     310         526 : void gf_smil_delete_times(GF_List *list)
     311             : {
     312             :         u32 i, count;
     313         526 :         count = gf_list_count(list);
     314         690 :         for (i = 0; i < count; i++) {
     315         164 :                 SMIL_Time *v = (SMIL_Time *)gf_list_get(list, i);
     316         164 :                 if (v->element_id) gf_free(v->element_id);
     317         164 :                 gf_free(v);
     318             :         }
     319         526 :         gf_list_del(list);
     320         526 : }
     321             : 
     322             : #if 0 //unused
     323             : void gf_svg_delete_points(GF_List *list)
     324             : {
     325             :         u32 i, count = gf_list_count(list);
     326             :         for (i = 0; i < count; i++) {
     327             :                 SVG_Point *p = (SVG_Point *)gf_list_get(list, i);
     328             :                 gf_free(p);
     329             :         }
     330             :         gf_list_del(list);
     331             : }
     332             : 
     333             : void gf_svg_delete_coordinates(GF_List *list)
     334             : {
     335             :         u32 i, count = gf_list_count(list);
     336             :         for (i = 0; i < count; i++) {
     337             :                 SVG_Coordinate *c = (SVG_Coordinate *)gf_list_get(list, i);
     338             :                 gf_free(c);
     339             :         }
     340             :         gf_list_del(list);
     341             : }
     342             : #endif
     343             : 
     344        2913 : void gf_svg_reset_iri(GF_SceneGraph *sg, XMLRI *iri)
     345             : {
     346        2913 :         if (!iri) return;
     347        2913 :         if (iri->string) gf_free(iri->string);
     348        2913 :         gf_node_unregister_iri(sg, iri);
     349             : }
     350             : 
     351        2584 : void gf_svg_delete_paint(GF_SceneGraph *sg, SVG_Paint *paint)
     352             : {
     353        2584 :         if (!paint) return;
     354             :         //always free since we may allocate the iri to ""
     355        2584 :         if (sg) gf_svg_reset_iri(sg, &paint->iri);
     356        2584 :         gf_free(paint);
     357             : }
     358             : 
     359         194 : static void svg_delete_one_anim_value(u8 anim_datatype, void *anim_value, GF_SceneGraph *sg)
     360             : {
     361             :         /* TODO: handle specific animation types : Motion, else ? */
     362         623 :         gf_svg_delete_attribute_value(anim_datatype, anim_value, sg);
     363         194 : }
     364             : 
     365         109 : void gf_svg_reset_animate_values(SMIL_AnimateValues anim_values, GF_SceneGraph *sg)
     366             : {
     367             :         u32 i, count;
     368         109 :         u8 type = anim_values.type;
     369         109 :         if (anim_values.laser_strings) type = DOM_String_datatype;
     370             : 
     371         109 :         count = gf_list_count(anim_values.values);
     372         538 :         for (i = 0; i < count; i++) {
     373         429 :                 void *value = gf_list_get(anim_values.values, i);
     374             :                 svg_delete_one_anim_value(type, value, sg);
     375             :         }
     376         109 :         gf_list_del(anim_values.values);
     377             :         anim_values.values = NULL;
     378         109 : }
     379             : 
     380             : #if 0 //unused
     381             : void gf_svg_reset_animate_value(SMIL_AnimateValue anim_value, GF_SceneGraph *sg)
     382             : {
     383             :         svg_delete_one_anim_value(anim_value.type, anim_value.value, sg);
     384             :         anim_value.value = NULL;
     385             : }
     386             : #endif
     387             : 
     388       14123 : void gf_svg_delete_attribute_value(u32 type, void *value, GF_SceneGraph *sg)
     389             : {
     390             :         GF_List *l;
     391       14123 :         switch (type) {
     392        2278 :         case SVG_Paint_datatype:
     393        2278 :                 gf_svg_delete_paint(sg, (SVG_Paint *)value);
     394        2278 :                 break;
     395         573 :         case XMLRI_datatype:
     396             :         case XML_IDREF_datatype:
     397         573 :                 gf_svg_reset_iri(sg, (XMLRI *)value);
     398         573 :                 gf_free(value);
     399         573 :                 break;
     400          62 :         case SVG_Focus_datatype:
     401          62 :                 gf_svg_reset_iri(sg, & ((SVG_Focus*)value)->target);
     402          62 :                 gf_free(value);
     403          62 :                 break;
     404        1089 :         case SVG_PathData_datatype:
     405             : #if USE_GF_PATH
     406        1089 :                 gf_path_del((GF_Path *)value);
     407             : #else
     408             :                 gf_free(value);
     409             : #endif
     410        1089 :                 break;
     411        3677 :         case SVG_ID_datatype:
     412             :         case DOM_String_datatype:
     413             :         case SVG_ContentType_datatype:
     414             :         case SVG_LanguageID_datatype:
     415        3677 :                 if (*(SVG_String *)value) gf_free(*(SVG_String *)value);
     416        3677 :                 gf_free(value);
     417        3677 :                 break;
     418          34 :         case SVG_StrokeDashArray_datatype:
     419          34 :                 if (((SVG_StrokeDashArray*)value)->array.vals) gf_free(((SVG_StrokeDashArray*)value)->array.vals);
     420          34 :                 if (((SVG_StrokeDashArray*)value)->array.units) gf_free(((SVG_StrokeDashArray*)value)->array.units);
     421          34 :                 gf_free(value);
     422          34 :                 break;
     423         757 :         case SMIL_KeyTimes_datatype:
     424             :         case SMIL_KeyPoints_datatype:
     425             :         case SMIL_KeySplines_datatype:
     426             :         case SVG_Numbers_datatype:
     427             :         case SVG_Coordinates_datatype:
     428             :         case SVG_Points_datatype:
     429         757 :                 l = *(GF_List**)value;
     430        2764 :                 while (gf_list_count(l)) {
     431        1250 :                         void *n = gf_list_last(l);
     432        1250 :                         gf_list_rem_last(l);
     433        1250 :                         gf_free(n);
     434             :                 }
     435         757 :                 gf_list_del(l);
     436         757 :                 gf_free(value);
     437         757 :                 break;
     438         136 :         case SVG_FontFamily_datatype:
     439             :         {
     440             :                 SVG_FontFamily *ff = (SVG_FontFamily *)value;
     441         136 :                 if (ff->value) gf_free(ff->value);
     442         136 :                 gf_free(value);
     443             :         }
     444         136 :         break;
     445         232 :         case SMIL_AttributeName_datatype:
     446             :         {
     447             :                 SMIL_AttributeName *an = (SMIL_AttributeName *)value;
     448         232 :                 if (an->name) gf_free(an->name);
     449         232 :                 gf_free(value);
     450             :         }
     451         232 :         break;
     452         526 :         case SMIL_Times_datatype:
     453         526 :                 gf_smil_delete_times(*(SMIL_Times *)value);
     454         526 :                 gf_free(value);
     455         526 :                 break;
     456         194 :         case SMIL_AnimateValue_datatype:
     457         194 :                 svg_delete_one_anim_value(((SMIL_AnimateValue *)value)->type, ((SMIL_AnimateValue *)value)->value, sg);
     458         194 :                 gf_free(value);
     459         194 :                 break;
     460         109 :         case SMIL_AnimateValues_datatype:
     461         109 :                 gf_svg_reset_animate_values(*((SMIL_AnimateValues *)value), sg);
     462         109 :                 gf_free(value);
     463         109 :                 break;
     464          19 :         case DOM_StringList_datatype:
     465          19 :                 l = *(GF_List**)value;
     466          62 :                 while (gf_list_count(l)) {
     467          24 :                         char *n = gf_list_last(l);
     468          24 :                         gf_list_rem_last(l);
     469          24 :                         gf_free(n);
     470             :                 }
     471          19 :                 gf_list_del(l);
     472          19 :                 gf_free(value);
     473          19 :                 break;
     474          54 :         case XMLRI_List_datatype:
     475          54 :                 l = *(GF_List**)value;
     476         227 :                 while (gf_list_count(l)) {
     477         119 :                         XMLRI *r = gf_list_last(l);
     478         119 :                         gf_list_rem_last(l);
     479         119 :                         if (r->string) gf_free(r->string);
     480         119 :                         gf_free(r);
     481             :                 }
     482          54 :                 gf_list_del(l);
     483          54 :                 gf_free(value);
     484          54 :                 break;
     485             : 
     486           2 :         case 0:
     487           2 :                 if (*(SVG_String *)value) gf_free(*(SVG_String *)value);
     488           2 :                 gf_free(value);
     489           2 :                 break;
     490        4381 :         case SMIL_RepeatCount_datatype:
     491             :         case SMIL_Duration_datatype:
     492             :         case SVG_Length_datatype:
     493             :         case SVG_Coordinate_datatype:
     494             :         case SVG_Visibility_datatype:
     495             :         case SVG_Display_datatype:
     496             :         default:
     497        4381 :                 gf_free(value);
     498        4381 :                 break;
     499             :         }
     500       14123 : }
     501             : 
     502             : #if 0 //unused
     503             : void gf_smil_delete_key_types(GF_List *l)
     504             : {
     505             :         while (gf_list_count(l)) {
     506             :                 Fixed *t = (Fixed *)gf_list_get(l, 0);
     507             :                 gf_list_rem(l, 0);
     508             :                 gf_free(t);
     509             :         }
     510             :         gf_list_del(l);
     511             : }
     512             : #endif
     513             : 
     514             : 
     515             : #endif /*GPAC_DISABLE_SVG*/

Generated by: LCOV version 1.13