📄 smil_anim.c
字号:
/* we still need to apply additive/replace behavior even when frozen because we don't know how many other animations have run during this cycle, on this attribute, before the current one, which might have changed the underlying value. */ if (animp->additive && *animp->additive == SMIL_ADDITIVE_SUM) { if (rai->owner->presentation_value_changed || rai->interpolated_value_changed) { GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SMIL Animation] Time %f - Animation %s - applying additive freeze behavior\n", gf_node_get_scene_time((GF_Node*)rai->anim_elt), gf_node_get_name((GF_Node *)rai->anim_elt))); if (rai->is_first_anim) gf_svg_attributes_add(&rai->owner->specified_value, &rai->interpolated_value, &rai->owner->presentation_value, 1); else gf_svg_attributes_add(&rai->owner->presentation_value, &rai->interpolated_value, &rai->owner->presentation_value, 1); rai->owner->presentation_value_changed = 1; } else { GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SMIL Animation] Time %f - Animation %s - applying additive freeze behavior (nothing done)\n", gf_node_get_scene_time((GF_Node*)rai->anim_elt), gf_node_get_name((GF_Node *)rai->anim_elt))); } } else { if (rai->interpolated_value_changed) { GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SMIL Animation] Time %f - Animation %s - applying freeze behavior\n", gf_node_get_scene_time((GF_Node*)rai->anim_elt), gf_node_get_name((GF_Node *)rai->anim_elt))); gf_svg_attributes_copy(&rai->owner->presentation_value, &rai->interpolated_value, 1); rai->owner->presentation_value_changed = 1; } else { GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SMIL Animation] Time %f - Animation %s - applying freeze behavior (nothing done)\n", gf_node_get_scene_time((GF_Node*)rai->anim_elt), gf_node_get_name((GF_Node *)rai->anim_elt))); rai->owner->presentation_value_changed = 0; } } if (rti->cycle_number == rti->first_frozen) gf_smil_anim_reset_variables(rai);}static void gf_smil_anim_remove(SMIL_Timing_RTI *rti, Fixed normalized_simple_time){ SMIL_Anim_RTI *rai = gf_smil_anim_get_anim_runtime_from_timing(rti); if (!rai) return; GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SMIL Animation] Time %f - Animation %s - applying remove behavior\n", gf_node_get_scene_time((GF_Node*)rai->anim_elt), gf_node_get_name((GF_Node *)rai->anim_elt))); gf_svg_attributes_copy(&rai->owner->presentation_value, &rai->owner->specified_value, 0); rai->owner->presentation_value_changed = 1; gf_smil_anim_reset_variables(rai);}static void gf_smil_anim_evaluate(SMIL_Timing_RTI *rti, Fixed normalized_simple_time, u32 state){ switch (state) { case SMIL_TIMING_EVAL_UPDATE: case SMIL_TIMING_EVAL_REPEAT: gf_smil_anim_animate(rti, normalized_simple_time); break; case SMIL_TIMING_EVAL_FREEZE: gf_smil_anim_freeze(rti, normalized_simple_time); break; case SMIL_TIMING_EVAL_REMOVE: gf_smil_anim_remove(rti, normalized_simple_time); break; case SMIL_TIMING_EVAL_FRACTION: gf_smil_anim_animate_with_fraction(rti, normalized_simple_time); break;/* discard should be done before in smil_notify_time case SMIL_TIMING_EVAL_DISCARD: break;*/ }}/************************************************************************************** **************************************************************************************/GF_EXPORTvoid gf_svg_apply_animations(GF_Node *node, SVGPropertiesPointers *render_svg_props){ u32 count_all, i; /* Perform all the animations on this node */ count_all = gf_node_animation_count(node); for (i = 0; i < count_all; i++) { u32 j, count; u32 nb_active_animations; SMIL_AttributeAnimations *aa = (SMIL_AttributeAnimations *)gf_node_animation_get(node, i); count = gf_list_count(aa->anims); if (!count) continue; aa->presentation_value_changed = 0; nb_active_animations = 0; if (aa->is_property) { /* Storing the pointer to the parent presentation value, i.e. the presentation value issued at the parent level in the tree */ aa->parent_presentation_value = aa->presentation_value; if ((node->sgprivate->tag>=GF_NODE_RANGE_FIRST_SVG) && (node->sgprivate->tag<=GF_NODE_RANGE_LAST_SVG)) { aa->parent_presentation_value.far_ptr = gf_svg_get_property_pointer((SVG_Element *)node, aa->orig_dom_ptr, render_svg_props); } #ifdef GPAC_ENABLE_SVG_SA else if ((node->sgprivate->tag>=GF_NODE_RANGE_FIRST_SVG_SA) && (node->sgprivate->tag<=GF_NODE_RANGE_LAST_SVG_SA)) { aa->parent_presentation_value.far_ptr = gf_svg_sa_get_property_pointer(render_svg_props, ((SVG_SA_Element*)node)->properties, aa->orig_dom_ptr); }#endif /* Storing also the pointer to the presentation value of the color property (special handling of the keyword 'currentColor' if used in animation values) */ aa->current_color_value.fieldType = SVG_Paint_datatype; if ((node->sgprivate->tag>=GF_NODE_RANGE_FIRST_SVG) && (node->sgprivate->tag<=GF_NODE_RANGE_LAST_SVG)) { GF_FieldInfo info; gf_svg_get_attribute_by_tag(node, TAG_SVG_ATT_color, 1, 1, &info); aa->current_color_value.far_ptr = info.far_ptr; } #ifdef GPAC_ENABLE_SVG_SA else if ((node->sgprivate->tag>=GF_NODE_RANGE_FIRST_SVG_SA) && (node->sgprivate->tag<=GF_NODE_RANGE_LAST_SVG_SA)) { aa->current_color_value.far_ptr = &((SVG_SA_Element*)node)->properties->color; } #endif } /* Performing all the animations targetting the given attribute */ for (j = 0; j < count; j++) { Double scene_time; SMIL_Anim_RTI *rai = (SMIL_Anim_RTI *)gf_list_get(aa->anims, j); SMIL_Timing_RTI *rti = rai->timingp->runtime; if (j == 0) rai->is_first_anim = 1; //scene_time = gf_node_get_scene_time(node); scene_time = rti->scene_time; if (rti->evaluate_status) { Fixed simple_time = gf_smil_timing_get_normalized_simple_time(rti, scene_time); rti->evaluate(rti, simple_time, rti->evaluate_status); nb_active_animations++; } } if (nb_active_animations) { if (aa->presentation_value_changed) { GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SMIL Animation] Time %f - Element %s - Presentation value changed for attribute %s\n", gf_node_get_scene_time(node), gf_node_get_name(node), gf_svg_get_attribute_name(aa->presentation_value.fieldIndex))); gf_node_dirty_set(node, aa->dirty_flags, 0); } else { /* WARNING - This does not work for use elements because apply_animations may be called several times */ gf_node_dirty_clear(node, aa->dirty_flags); } } }}#ifdef GPAC_ENABLE_SVG_SANIGF_EXPORTvoid gf_svg_sani_apply_animations(GF_Node *node){ u32 count_all, i; /*TODO FIXME - THIS IS WRONG, we're changing orders of animations which may corrupt the visual result*/ /* Perform all the animations on this node */ count_all = gf_node_animation_count(node); for (i = 0; i < count_all; i++) { /* Performing the animations for a given animated attribute */ u32 j, count; SMIL_AttributeAnimations *aa = (SMIL_AttributeAnimations *)gf_node_animation_get(node, i); count = gf_list_count(aa->anims); if (!count) continue; aa->presentation_value_changed = 0; for (j = 0; j < count; j++) { SMIL_Anim_RTI *rai = (SMIL_Anim_RTI *)gf_list_get(aa->anims, j); SMIL_Timing_RTI *rti = ((SVG_SANI_Element *)rai->anim_elt)->timingp->runtime; //Double scene_time = gf_node_get_scene_time(node); Double scene_time = rti->scene_time; if (j == 0) rai->is_first_anim = 1; if (rti->evaluate_status) { Fixed simple_time = gf_smil_timing_get_normalized_simple_time(rti, scene_time); rti->evaluate(rti, simple_time, rti->evaluate_status); } } if (aa->presentation_value_changed) { gf_node_dirty_set(node, aa->dirty_flags, 0); } }}#elseGF_EXPORTvoid gf_svg_sani_apply_animations(GF_Node *node){}#endifvoid gf_smil_anim_init_runtime_info(GF_Node *e){ u32 i; GF_FieldInfo target_attribute; SMIL_AttributeAnimations *aa = NULL; SMIL_Anim_RTI *rai; XLinkAttributesPointers *xlinkp = NULL; SMILAnimationAttributesPointers *animp = NULL; SMILTimingAttributesPointers *timingp = NULL; GF_Node *target = NULL; u32 tag; /* Filling animation structures to be independent of the SVG Element structure */ tag = gf_node_get_tag(e); if ((tag>=GF_NODE_RANGE_FIRST_SVG) && (tag<=GF_NODE_RANGE_LAST_SVG)) { animp = ((SVGTimedAnimBaseElement *)e)->animp; timingp = ((SVGTimedAnimBaseElement *)e)->timingp; xlinkp = ((SVGTimedAnimBaseElement *)e)->xlinkp; } #ifdef GPAC_ENABLE_SVG_SA else if ((tag>=GF_NODE_RANGE_FIRST_SVG_SA) && (tag<=GF_NODE_RANGE_LAST_SVG_SA)) { animp = ((SVG_SA_Element *)e)->animp; timingp = ((SVG_SA_Element *)e)->timingp; xlinkp = ((SVG_SA_Element *)e)->xlinkp; } #endif#ifdef GPAC_ENABLE_SVG_SANI else if ((tag>=GF_NODE_RANGE_FIRST_SVG_SANI) && (tag<=GF_NODE_RANGE_LAST_SVG_SANI)) { animp = ((SVG_SANI_Element *)e)->animp; timingp = ((SVG_SANI_Element *)e)->timingp; xlinkp = ((SVG_SANI_Element *)e)->xlinkp; } #endif else { return; } /* from this point, the animation node 'e' should not be used */ target = xlinkp->href->target; memset(&target_attribute, 0, sizeof(GF_FieldInfo)); if (animp->attributeName && (animp->attributeName->name || animp->attributeName->tag)) { /* Filling the target_attribute structure with info on the animated attribute (type, pointer to data, ...) NOTE: in the mode Dynamic Allocation of Attributes, this means that the animated attribute is created with a default value, if it was not specified on the target element */ if (animp->attributeName->tag) { gf_svg_get_attribute_by_tag(target, animp->attributeName->tag, 1, 1, &target_attribute); } else { gf_node_get_field_by_name(target, animp->attributeName->name, &target_attribute); } } else { /* All animation elements should have a target attribute except for animateMotion cf http://www.w3.org/mid/u403c21ajf1sjqtk58g0g38eaep9f9g2ss@hive.bjoern.hoehrmann.de "For animateMotion, the attributeName is implied and cannot be specified; animateTransform requires specification of the attribute name and any attribute that is a transform-like attribute can be a target, e.g. gradientTransform."*/ switch (tag) {#ifdef GPAC_ENABLE_SVG_SA_BASE#ifdef GPAC_ENABLE_SVG_SA case TAG_SVG_SA_animateMotion:#endif#ifdef GPAC_ENABLE_SVG_SANI case TAG_SVG_SANI_animateMotion:#endif { SVGTransformableElement *tr_e = (SVGTransformableElement *)target; if (!tr_e->motionTransform) { tr_e->motionTransform = (GF_Matrix2D*)malloc(sizeof(GF_Matrix2D)); gf_mx2d_init(*tr_e->motionTransform); } gf_node_get_field_by_name((GF_Node *)tr_e, "motionTransform", &target_attribute); } break;#endif case TAG_SVG_animateMotion: /* Explicit creation of the pseudo 'motionTransform' attribute since it cannot be specified */ gf_svg_get_attribute_by_tag(target, TAG_SVG_ATT_motionTransform, 1, 0, &target_attribute); gf_mx2d_init(*(GF_Matrix2D *)target_attribute.far_ptr); break; default: GF_LOG(GF_LOG_WARNING, GF_LOG_COMPOSE, ("[SMIL Animation] Missing attributeName attribute on element %s\n", gf_node_get_name((GF_Node*)e) )); return; } } if ((!animp->values || !gf_list_count(animp->values->values)) && /* 'values' attribute not specified */ (!animp->to || animp->to->type == 0) && /* 'to' attribute not specified */ (!animp->from || animp->from->type == 0) && /* 'from' attribute not specified */ (animp->by && animp->by->type != 0)) { /* 'by' attribute specified */ /* if this is a 'by' animation without from the animation is defined to be additive see http://www.w3.org/TR/2005/REC-SMIL2-20051213/animation.html#AnimationNS-FromToBy we override the additive attribute */ if (!animp->additive) { /* this case can only happen with dynamic allocation of attributes */ GF_FieldInfo info; gf_svg_get_attribute_by_tag(e, TAG_SVG_ATT_additive, 1, 0, &info); animp->additive = info.far_ptr; } *animp->additive = SMIL_ADDITIVE_SUM; } /*TODO http://www.w3.org/TR/2005/REC-SMIL2-20051213/animation.html#animationNS-ToAnimation To animation defines its own kind of additive semantics, so the additive attribute is ignored. */ /*TODO http://www.w3.org/TR/2005/REC-SMIL2-20051213/animation.html#animationNS-ToAnimation Because to animation is defined in terms of absolute values of the target attribute, cumulative animation is not defined: */ /* TODO http://www.w3.org/TR/2005/REC-SMIL2-20051213/animation.html#animationNS-setElement The set element is non-additive. The additive and accumulate attributes are not allowed, and will be ignored if specified. */ /* Creation and setup of the runtime structure for animation */ GF_SAFEALLOC(rai, SMIL_Anim_RTI) rai->anim_elt = e; rai->animp = animp; rai->timingp = timingp; rai->xlinkp = xlinkp; gf_mx2d_init(rai->identity); rai->default_transform_value.far_ptr = &rai->identity; rai->default_transform_value.fieldType = SVG_Transform_datatype; /* the interpolated value has the same type as the target attribute, but we need to create a new pointer to hold its value */ rai->interpolated_value = target_attribute; rai->interpolated_value.far_ptr = gf_svg_create_attribute_value(target_attribute.fieldType); /* there has not been any interpolation yet, so the previous key index and interpolation coefficient shall not be set*/ rai->previous_key_index = -1; rai->previous_coef = -1; /* For animateMotion, we need to retrieve the value of the rotate attribute, retrieve the path either from the 'path' attribute or from the 'mpath' element, and then initialize the path iterator*/ if ((tag == TAG_SVG_animateMotion)#ifdef GPAC_ENABLE_SVG_SA || (tag == TAG_SVG_SA_animateMotion)#endif#ifdef GPAC_ENABLE_SVG_SANI || (tag == TAG_SVG_SANI_animateMotion)#endif ) { GF_Path *the_path = NULL; GF_ChildNodeItem *child = NULL;#ifdef GPAC_ENABLE_SVG_SA if (tag == TAG_SVG_SA_animateMotion) { SVG_SA_animateMotionElement *am = (SVG_SA_animateMotionElement *)e; rai->rotate = am->rotate.type; the_path = &am->path; child = am->children; } else #endif#ifdef GPAC_ENABLE_SVG_SANI if (tag == TAG_SVG_SANI_animateMotion) { SVG_SANI_animateMotionElement *am = (SVG_SANI_animateMotionElement *)e; rai->rotate = am->rotate.type; the_path = &am->path; child = am->children;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -