This source file includes following definitions.
- gf_svg_is_animation_tag
- gf_svg_is_timing_tag
- gf_svg_create_node
- gf_svg_node_del
- gf_svg_node_init
- gf_svg_node_changed
- gf_svg_reset_path
- gf_svg_path_build
- gf_smil_delete_times
- gf_svg_delete_points
- gf_svg_delete_coordinates
- gf_svg_reset_iri
- gf_svg_delete_paint
- svg_delete_one_anim_value
- gf_svg_reset_animate_values
- gf_svg_reset_animate_value
- gf_svg_delete_attribute_value
- gf_smil_delete_key_types
#include <gpac/internal/scenegraph_dev.h>
#ifndef GPAC_DISABLE_SVG
#include <gpac/nodes_svg.h>
Bool gf_svg_is_animation_tag(u32 tag)
{
return (tag == TAG_SVG_set ||
tag == TAG_SVG_animate ||
tag == TAG_SVG_animateColor ||
tag == TAG_SVG_animateTransform ||
tag == TAG_SVG_animateMotion ||
tag == TAG_SVG_discard
) ? 1 : 0;
}
Bool gf_svg_is_timing_tag(u32 tag)
{
if (gf_svg_is_animation_tag(tag)) return 1;
else return (tag == TAG_SVG_animation ||
tag == TAG_SVG_audio ||
tag == TAG_LSR_conditional ||
tag == TAG_LSR_updates ||
tag == TAG_SVG_video)? GF_TRUE : GF_FALSE;
}
SVG_Element *gf_svg_create_node(u32 ElementTag)
{
SVG_Element *p;
if (gf_svg_is_timing_tag(ElementTag)) {
SVGTimedAnimBaseElement *tap;
GF_SAFEALLOC(tap, SVGTimedAnimBaseElement);
p = (SVG_Element *)tap;
} else if (ElementTag == TAG_SVG_handler) {
SVG_handlerElement *hdl;
GF_SAFEALLOC(hdl, SVG_handlerElement);
p = (SVG_Element *)hdl;
} else {
GF_SAFEALLOC(p, SVG_Element);
}
gf_node_setup((GF_Node *)p, ElementTag);
gf_sg_parent_setup((GF_Node *) p);
return p;
}
void gf_svg_node_del(GF_Node *node)
{
SVG_Element *p = (SVG_Element *)node;
if (p->sgprivate->interact && p->sgprivate->interact->animations) {
gf_smil_anim_delete_animations((GF_Node *)p);
}
if (p->sgprivate->tag==TAG_SVG_listener) {
gf_dom_event_remove_listener_from_parent((GF_DOMEventTarget *)node->sgprivate->UserPrivate, (GF_Node *)p);
}
if (p->sgprivate->tag==TAG_SVG_handler) {
GF_Node *listener = p->sgprivate->UserPrivate;
if (listener && (listener->sgprivate->tag==TAG_SVG_listener)) {
GF_FieldInfo info;
if (gf_node_get_attribute_by_tag(listener, TAG_XMLEV_ATT_handler, 0, 0, &info) == GF_OK) {
XMLRI *iri = (XMLRI *)info.far_ptr;
if (iri->target) {
assert(iri->target==p);
iri->target = NULL;
}
}
gf_node_unregister(listener, NULL);
}
}
if (node->sgprivate->interact && node->sgprivate->interact->dom_evt) {
u32 i, count;
count = gf_dom_listener_count(node);
for (i=0; i<count; i++) {
GF_Node *listener = (GF_Node *)gf_list_get(node->sgprivate->interact->dom_evt->listeners, i);
listener->sgprivate->UserPrivate = NULL;
}
}
if (gf_svg_is_timing_tag(node->sgprivate->tag)) {
SVGTimedAnimBaseElement *tap = (SVGTimedAnimBaseElement *)node;
if (tap->animp) {
gf_free(tap->animp);
gf_smil_anim_remove_from_target((GF_Node *)tap, (GF_Node *)tap->xlinkp->href->target);
}
if (tap->timingp) {
gf_smil_timing_delete_runtime_info((GF_Node *)tap, tap->timingp->runtime);
gf_free(tap->timingp);
}
if (tap->xlinkp) gf_free(tap->xlinkp);
}
gf_node_delete_attributes(node);
gf_sg_parent_reset(node);
gf_node_free(node);
}
Bool gf_svg_node_init(GF_Node *node)
{
switch (node->sgprivate->tag) {
case TAG_SVG_script:
if (node->sgprivate->scenegraph->script_load)
node->sgprivate->scenegraph->script_load(node);
return 1;
case TAG_SVG_handler:
if (node->sgprivate->scenegraph->script_load)
node->sgprivate->scenegraph->script_load(node);
if (node->sgprivate->scenegraph->script_action)
((SVG_handlerElement*)node)->handle_event = gf_sg_handle_dom_event;
return 1;
case TAG_LSR_conditional:
gf_smil_timing_init_runtime_info(node);
gf_smil_setup_events(node);
return 1;
case TAG_SVG_animateMotion:
case TAG_SVG_set:
case TAG_SVG_animate:
case TAG_SVG_animateColor:
case TAG_SVG_animateTransform:
gf_smil_anim_init_node(node);
gf_smil_setup_events(node);
return (node->sgprivate->UserPrivate || node->sgprivate->UserCallback) ? 1 : 0;
case TAG_SVG_audio:
case TAG_SVG_video:
case TAG_LSR_updates:
gf_smil_timing_init_runtime_info(node);
gf_smil_setup_events(node);
return (node->sgprivate->UserPrivate || node->sgprivate->UserCallback) ? 1 : 0;
case TAG_SVG_animation:
gf_smil_timing_init_runtime_info(node);
gf_smil_setup_events(node);
return 0;
case TAG_SVG_discard:
gf_smil_anim_init_discard(node);
gf_smil_setup_events(node);
return 1;
default:
return 0;
}
return 0;
}
Bool gf_svg_node_changed(GF_Node *node, GF_FieldInfo *field)
{
switch (node->sgprivate->tag) {
case TAG_SVG_animateMotion:
case TAG_SVG_discard:
case TAG_SVG_set:
case TAG_SVG_animate:
case TAG_SVG_animateColor:
case TAG_SVG_animateTransform:
case TAG_LSR_conditional:
gf_smil_timing_modified(node, field);
return 1;
case TAG_SVG_animation:
case TAG_SVG_audio:
case TAG_SVG_video:
case TAG_LSR_updates:
gf_smil_timing_modified(node, field);
return 0;
}
return 0;
}
void gf_svg_reset_path(SVG_PathData d)
{
#if USE_GF_PATH
gf_path_reset(&d);
#else
u32 i, count;
count = gf_list_count(d.commands);
for (i = 0; i < count; i++) {
u8 *command = (u8 *)gf_list_get(d.commands, i);
gf_free(command);
}
gf_list_del(d.commands);
count = gf_list_count(d.points);
for (i = 0; i < count; i++) {
SVG_Point *pt = (SVG_Point *)gf_list_get(d.points, i);
gf_free(pt);
}
gf_list_del(d.points);
#endif
}
GF_EXPORT
void gf_svg_path_build(GF_Path *path, GF_List *commands, GF_List *points)
{
u32 i, j, command_count;
SVG_Point orig, ct_orig, ct_end, end, *tmp;
command_count = gf_list_count(commands);
orig.x = orig.y = ct_orig.x = ct_orig.y = 0;
for (i=0, j=0; i<command_count; i++) {
u8 *command = (u8 *)gf_list_get(commands, i);
switch (*command) {
case SVG_PATHCOMMAND_M:
tmp = (SVG_Point*)gf_list_get(points, j);
orig = *tmp;
gf_path_add_move_to(path, orig.x, orig.y);
j++;
ct_orig = orig;
break;
case SVG_PATHCOMMAND_L:
tmp = (SVG_Point*)gf_list_get(points, j);
end = *tmp;
gf_path_add_line_to(path, end.x, end.y);
j++;
orig = end;
ct_orig = orig;
break;
case SVG_PATHCOMMAND_C:
tmp = (SVG_Point*)gf_list_get(points, j);
ct_orig = *tmp;
tmp = (SVG_Point*)gf_list_get(points, j+1);
ct_end = *tmp;
tmp = (SVG_Point*)gf_list_get(points, j+2);
end = *tmp;
gf_path_add_cubic_to(path, ct_orig.x, ct_orig.y, ct_end.x, ct_end.y, end.x, end.y);
ct_orig = ct_end;
orig = end;
j+=3;
break;
case SVG_PATHCOMMAND_S:
ct_orig.x = 2*orig.x - ct_orig.x;
ct_orig.y = 2*orig.y - ct_orig.y;
tmp = (SVG_Point*)gf_list_get(points, j);
ct_end = *tmp;
tmp = (SVG_Point*)gf_list_get(points, j+1);
end = *tmp;
gf_path_add_cubic_to(path, ct_orig.x, ct_orig.y, ct_end.x, ct_end.y, end.x, end.y);
ct_orig = ct_end;
orig = end;
j+=2;
break;
case SVG_PATHCOMMAND_Q:
tmp = (SVG_Point*)gf_list_get(points, j);
ct_orig = *tmp;
tmp = (SVG_Point*)gf_list_get(points, j+1);
end = *tmp;
gf_path_add_quadratic_to(path, ct_orig.x, ct_orig.y, end.x, end.y);
orig = end;
j+=2;
break;
case SVG_PATHCOMMAND_T:
ct_orig.x = 2*orig.x - ct_orig.x;
ct_orig.y = 2*orig.y - ct_orig.y;
tmp = (SVG_Point*)gf_list_get(points, j);
end = *tmp;
gf_path_add_quadratic_to(path, ct_orig.x, ct_orig.y, end.x, end.y);
orig = end;
j++;
break;
case SVG_PATHCOMMAND_Z:
gf_path_close(path);
break;
}
}
}
void gf_smil_delete_times(GF_List *list)
{
u32 i, count;
count = gf_list_count(list);
for (i = 0; i < count; i++) {
SMIL_Time *v = (SMIL_Time *)gf_list_get(list, i);
if (v->element_id) gf_free(v->element_id);
gf_free(v);
}
gf_list_del(list);
}
void gf_svg_delete_points(GF_List *list)
{
u32 i, count = gf_list_count(list);
for (i = 0; i < count; i++) {
SVG_Point *p = (SVG_Point *)gf_list_get(list, i);
gf_free(p);
}
gf_list_del(list);
}
void gf_svg_delete_coordinates(GF_List *list)
{
u32 i, count = gf_list_count(list);
for (i = 0; i < count; i++) {
SVG_Coordinate *c = (SVG_Coordinate *)gf_list_get(list, i);
gf_free(c);
}
gf_list_del(list);
}
void gf_svg_reset_iri(GF_SceneGraph *sg, XMLRI *iri)
{
if (!iri) return;
if (iri->string) gf_free(iri->string);
gf_node_unregister_iri(sg, iri);
}
void gf_svg_delete_paint(GF_SceneGraph *sg, SVG_Paint *paint)
{
if (!paint) return;
if (sg) gf_svg_reset_iri(sg, &paint->iri);
gf_free(paint);
}
static void svg_delete_one_anim_value(u8 anim_datatype, void *anim_value, GF_SceneGraph *sg)
{
gf_svg_delete_attribute_value(anim_datatype, anim_value, sg);
}
void gf_svg_reset_animate_values(SMIL_AnimateValues anim_values, GF_SceneGraph *sg)
{
u32 i, count;
count = gf_list_count(anim_values.values);
for (i = 0; i < count; i++) {
void *value = gf_list_get(anim_values.values, i);
svg_delete_one_anim_value(anim_values.type, value, sg);
}
gf_list_del(anim_values.values);
anim_values.values = NULL;
}
void gf_svg_reset_animate_value(SMIL_AnimateValue anim_value, GF_SceneGraph *sg)
{
svg_delete_one_anim_value(anim_value.type, anim_value.value, sg);
anim_value.value = NULL;
}
void gf_svg_delete_attribute_value(u32 type, void *value, GF_SceneGraph *sg)
{
GF_List *l;
switch (type) {
case SVG_Paint_datatype:
gf_svg_delete_paint(sg, (SVG_Paint *)value);
break;
case XMLRI_datatype:
case XML_IDREF_datatype:
gf_svg_reset_iri(sg, (XMLRI *)value);
gf_free(value);
break;
case SVG_Focus_datatype:
gf_svg_reset_iri(sg, & ((SVG_Focus*)value)->target);
gf_free(value);
break;
case SVG_PathData_datatype:
#if USE_GF_PATH
gf_path_del((GF_Path *)value);
#else
gf_free(value);
#endif
break;
case SVG_ID_datatype:
case DOM_String_datatype:
case SVG_ContentType_datatype:
case SVG_LanguageID_datatype:
if (*(SVG_String *)value) gf_free(*(SVG_String *)value);
gf_free(value);
break;
case SVG_StrokeDashArray_datatype:
if (((SVG_StrokeDashArray*)value)->array.vals) gf_free(((SVG_StrokeDashArray*)value)->array.vals);
if (((SVG_StrokeDashArray*)value)->array.units) gf_free(((SVG_StrokeDashArray*)value)->array.units);
gf_free(value);
break;
case SMIL_KeyTimes_datatype:
case SMIL_KeyPoints_datatype:
case SMIL_KeySplines_datatype:
case SVG_Numbers_datatype:
case SVG_Coordinates_datatype:
case SVG_Points_datatype:
l = *(GF_List**)value;
while (gf_list_count(l)) {
void *n = gf_list_last(l);
gf_list_rem_last(l);
gf_free(n);
}
gf_list_del(l);
gf_free(value);
break;
case SVG_FontFamily_datatype:
{
SVG_FontFamily *ff = (SVG_FontFamily *)value;
if (ff->value) gf_free(ff->value);
gf_free(value);
}
break;
case SMIL_AttributeName_datatype:
{
SMIL_AttributeName *an = (SMIL_AttributeName *)value;
if (an->name) gf_free(an->name);
gf_free(value);
}
break;
case SMIL_Times_datatype:
gf_smil_delete_times(*(SMIL_Times *)value);
gf_free(value);
break;
case SMIL_AnimateValue_datatype:
svg_delete_one_anim_value(((SMIL_AnimateValue *)value)->type, ((SMIL_AnimateValue *)value)->value, sg);
gf_free(value);
break;
case SMIL_AnimateValues_datatype:
gf_svg_reset_animate_values(*((SMIL_AnimateValues *)value), sg);
gf_free(value);
break;
case DOM_StringList_datatype:
l = *(GF_List**)value;
while (gf_list_count(l)) {
char *n = gf_list_last(l);
gf_list_rem_last(l);
gf_free(n);
}
gf_list_del(l);
gf_free(value);
break;
case XMLRI_List_datatype:
l = *(GF_List**)value;
while (gf_list_count(l)) {
XMLRI *r = gf_list_last(l);
gf_list_rem_last(l);
if (r->string) gf_free(r->string);
gf_free(r);
}
gf_list_del(l);
gf_free(value);
break;
case SMIL_RepeatCount_datatype:
case SMIL_Duration_datatype:
case SVG_Length_datatype:
case SVG_Coordinate_datatype:
case SVG_Visibility_datatype:
case SVG_Display_datatype:
default:
gf_free(value);
}
}
void gf_smil_delete_key_types(GF_List *l)
{
while (gf_list_count(l)) {
Fixed *t = (Fixed *)gf_list_get(l, 0);
gf_list_rem(l, 0);
gf_free(t);
}
gf_list_del(l);
}
#endif