📄 smil_anim.c
字号:
gf_svg_attributes_resolve_currentColor(&from_info, &rai->owner->current_color_value); gf_svg_attributes_resolve_inherit(&from_info, &rai->owner->parent_presentation_value); } if (animp->to) { to_info.fieldType = animp->to->type; to_info.far_ptr = animp->to->value; } else { to_info.fieldType = 0; } if (rai->is_first_anim) gf_svg_attributes_resolve_unspecified(&to_info, &rai->owner->specified_value, &rai->default_transform_value); else gf_svg_attributes_resolve_unspecified(&to_info, &rai->owner->presentation_value, &rai->default_transform_value); if (rai->owner->is_property && gf_svg_attribute_is_interpolatable(to_info.fieldType)) { gf_svg_attributes_resolve_currentColor(&to_info, &rai->owner->current_color_value); gf_svg_attributes_resolve_inherit(&to_info, &rai->owner->parent_presentation_value); } switch ((animp->calcMode ? *animp->calcMode : SMIL_CALCMODE_LINEAR)) { case SMIL_CALCMODE_DISCRETE: { /* before half of the duration stay at 'from' and then switch to 'to' */ s32 useFrom = (normalized_simple_time<=FIX_ONE/2);#if DO_OPTIMIZATION_TESTS if (useFrom == rai->previous_key_index) return;#endif GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SMIL Animation] Time %f - Animation %s - applying from-to animation (using %s value)\n", gf_node_get_scene_time((GF_Node*)rai->anim_elt), gf_node_get_name((GF_Node *)rai->anim_elt), (useFrom?"from":"to"))); gf_svg_attributes_copy(&rai->interpolated_value, (useFrom?&from_info:&to_info), 0); rai->previous_key_index = useFrom; } break; case SMIL_CALCMODE_SPLINE: case SMIL_CALCMODE_PACED: case SMIL_CALCMODE_LINEAR: default: GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SMIL Animation] Time %f - Animation %s - applying from-to animation (linear interpolation, using coefficient %f)\n", gf_node_get_scene_time((GF_Node*)rai->anim_elt), gf_node_get_name((GF_Node *)rai->anim_elt), normalized_simple_time)); gf_svg_attributes_interpolate(&from_info, &to_info, &rai->interpolated_value, normalized_simple_time, 1); break; } rai->interpolated_value_changed = 1;}static void gf_smil_anim_animate_from_by(SMIL_Anim_RTI *rai, Fixed normalized_simple_time){ Fixed from_coef; GF_FieldInfo from_info, by_info; SMILAnimationAttributesPointers *animp = rai->animp; if (!animp) return; if (rai->previous_coef == normalized_simple_time) return; rai->previous_coef = normalized_simple_time; if (animp->from) { from_info.fieldType = animp->from->type; from_info.far_ptr = animp->from->value; from_coef = FIX_ONE; } else { from_info.fieldType = 0; /* this is a by animation only, then, it is always additive, we don't need the from value*/ from_coef = 0; } if (rai->is_first_anim) gf_svg_attributes_resolve_unspecified(&from_info, &rai->owner->specified_value, &rai->default_transform_value); else gf_svg_attributes_resolve_unspecified(&from_info, &rai->owner->presentation_value, &rai->default_transform_value); if (rai->owner->is_property && gf_svg_attribute_is_interpolatable(from_info.fieldType)) { gf_svg_attributes_resolve_currentColor(&from_info, &rai->owner->current_color_value); gf_svg_attributes_resolve_inherit(&from_info, &rai->owner->parent_presentation_value); } if (animp->by) { by_info.fieldType = animp->by->type; by_info.far_ptr = animp->by->value; } else { by_info.fieldType = 0; } if (rai->owner->is_property && gf_svg_attribute_is_interpolatable(from_info.fieldType)) { gf_svg_attributes_resolve_currentColor(&by_info, &rai->owner->current_color_value); gf_svg_attributes_resolve_inherit(&by_info, &rai->owner->parent_presentation_value); } switch ((animp->calcMode ? *animp->calcMode : SMIL_CALCMODE_LINEAR)) { case SMIL_CALCMODE_DISCRETE: { /* before half of the duration stay at 'from' and then switch to 'to' */ s32 useFrom = (normalized_simple_time<=FIX_ONE/2);#if DO_OPTIMIZATION_TESTS if (useFrom == rai->previous_key_index) return;#endif if (useFrom) { GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SMIL Animation] Time %f - Animation %s - applying from-by animation (setting from)\n", gf_node_get_scene_time((GF_Node*)rai->anim_elt), gf_node_get_name((GF_Node *)rai->anim_elt))); gf_svg_attributes_muladd(from_coef, &from_info, 0, &by_info, &rai->interpolated_value, 0); } else { GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SMIL Animation] Time %f - Animation %s - applying from-by animation (setting from+by)\n", gf_node_get_scene_time((GF_Node*)rai->anim_elt), gf_node_get_name((GF_Node *)rai->anim_elt))); gf_svg_attributes_muladd(from_coef, &from_info, FIX_ONE, &by_info, &rai->interpolated_value, 0); } rai->previous_key_index = useFrom; } break; case SMIL_CALCMODE_SPLINE: case SMIL_CALCMODE_PACED: case SMIL_CALCMODE_LINEAR: default: GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SMIL Animation] Time %f - Animation %s - applying from-by animation (linear interpolation between from and from+by, coef: %f)\n", gf_node_get_scene_time((GF_Node*)rai->anim_elt), gf_node_get_name((GF_Node *)rai->anim_elt), normalized_simple_time)); gf_svg_attributes_muladd(from_coef, &from_info, normalized_simple_time, &by_info, &rai->interpolated_value, 0); break; } rai->interpolated_value_changed = 1;}static Bool gf_svg_compute_path_anim(SMIL_Anim_RTI *rai, GF_Matrix2D *m, Fixed normalized_simple_time) { Bool res = 0; Fixed offset; offset = gf_mulfix(normalized_simple_time, rai->length); gf_mx2d_init(*m); res = gf_path_iterator_get_transform(rai->path_iterator, offset, 1, m, 1, 0); GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("offset: %f, position: (%f, %f)\n", offset, ((GF_Matrix2D *)rai->interpolated_value.far_ptr)->m[2], ((GF_Matrix2D *)rai->interpolated_value.far_ptr)->m[5])); switch (rai->rotate) { case SVG_NUMBER_AUTO: break; case SVG_NUMBER_AUTO_REVERSE: gf_mx2d_add_rotation(m, m->m[2], m->m[5], GF_PI); break; default: m->m[0] = FIX_ONE; m->m[1] = 0; m->m[3] = 0; m->m[4] = FIX_ONE; } return res;}static void gf_smil_anim_animate_using_path(SMIL_Anim_RTI *rai, Fixed normalized_simple_time){ Bool res = 0; GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SMIL Animation] Time %f - Animation %s - applying path animation (coef: %f), ", gf_node_get_scene_time((GF_Node*)rai->anim_elt), gf_node_get_name((GF_Node *)rai->anim_elt), normalized_simple_time)); res = gf_svg_compute_path_anim(rai, (GF_Matrix2D*)rai->interpolated_value.far_ptr, normalized_simple_time); if (res) rai->interpolated_value_changed = 1;}static void gf_smil_anim_compute_interpolation_value(SMIL_Anim_RTI *rai, Fixed normalized_simple_time){ SMILAnimationAttributesPointers *animp = rai->animp; u32 tag = gf_node_get_tag(rai->anim_elt); if (!animp) return; if (rai->path) { gf_smil_anim_animate_using_path(rai, normalized_simple_time); } #ifdef GPAC_ENABLE_SVG_SA else if (tag == TAG_SVG_SA_set) gf_smil_anim_set(rai);#endif#ifdef GPAC_ENABLE_SVG_SANI else if (tag == TAG_SVG_SANI_set) gf_smil_anim_set(rai);#endif else if (tag == TAG_SVG_set) gf_smil_anim_set(rai); else if (animp->values && gf_list_count(animp->values->values)) { /* Ignore 'from'/'to'/'by'*/ gf_smil_anim_animate_using_values(rai, normalized_simple_time); } else if ((animp->by && animp->by->type) && (!animp->to || animp->to->type == 0)) { /* 'to' is not specified but 'by' is, so this is a 'by' animation or a 'from'-'by' animation */ gf_smil_anim_animate_from_by(rai, normalized_simple_time); } else { /* Ignore 'by' if specified */ gf_smil_anim_animate_from_to(rai, normalized_simple_time); }}SMIL_Anim_RTI *gf_smil_anim_get_anim_runtime_from_timing(SMIL_Timing_RTI *rti){ GF_Node *n = rti->timed_elt; u32 i, j; GF_Node *target = NULL; u32 tag = gf_node_get_tag(n); if ((tag>=GF_NODE_RANGE_FIRST_SVG) && (tag<=GF_NODE_RANGE_LAST_SVG)) { if (!gf_svg_is_animation_tag(tag)) return NULL; target = ((SVGTimedAnimBaseElement *)n)->xlinkp->href->target; }#ifdef GPAC_ENABLE_SVG_SA else if ((tag>=GF_NODE_RANGE_FIRST_SVG_SA) && (tag<=GF_NODE_RANGE_LAST_SVG_SA)) { if (!gf_svg_sa_is_animation_tag(tag)) return NULL; target = ((SVG_SA_Element *)n)->xlinkp->href->target; } #endif#ifdef GPAC_ENABLE_SVG_SANI else if ((tag>=GF_NODE_RANGE_FIRST_SVG_SANI) && (tag<=GF_NODE_RANGE_LAST_SVG_SANI)) { target = ((SVG_SANI_Element *)n)->xlinkp->href->target; }#endif if (!target) return NULL; for (i = 0; i < gf_node_animation_count(target); i++) { SMIL_Anim_RTI *rai_tmp; SMIL_AttributeAnimations *aa = (SMIL_AttributeAnimations *)gf_node_animation_get(target, i); j=0; while ((rai_tmp = (SMIL_Anim_RTI *)gf_list_enum(aa->anims, &j))) { if (rai_tmp->timingp->runtime == rti) { return rai_tmp; } } } return NULL;}static void gf_smil_anim_get_last_specified_value(SMIL_Anim_RTI *rai){ SMILAnimationAttributesPointers *animp = rai->animp; u32 tag = gf_node_get_tag(rai->anim_elt); if (!animp) return; if (rai->path) { /*TODO CHECK WITH CYRIL !! */// if (!rai->last_specified_value.far_ptr) rai->last_specified_value.far_ptr = malloc(sizeof(GF_Matrix2D));// gf_svg_compute_path_anim(rai, rai->last_specified_value.far_ptr, FIX_ONE); return; } else if ((tag == TAG_SVG_set)#ifdef GPAC_ENABLE_SVG_SANI || (tag == TAG_SVG_SA_set)#endif#ifdef GPAC_ENABLE_SVG_SANI || (tag == TAG_SVG_SANI_set)#endif ) { if (animp->to) { rai->last_specified_value.fieldType = animp->to->type; rai->last_specified_value.far_ptr = animp->to->value; } else { /* TODO ??? */ } return; } if (animp->values && gf_list_count(animp->values->values)) { /* Ignore from/to/by*/ rai->last_specified_value.fieldType = animp->values->type; rai->last_specified_value.far_ptr = gf_list_last(animp->values->values); } else if ((animp->by && animp->by->type) && (!animp->to || animp->to->type == 0)) { rai->last_specified_value.fieldType = animp->by->type; rai->last_specified_value.far_ptr = animp->by->value; } else if (animp->to) { rai->last_specified_value.fieldType = animp->to->type; rai->last_specified_value.far_ptr = animp->to->value; } if (gf_svg_is_inherit(&rai->last_specified_value)) { rai->last_specified_value.fieldType = rai->owner->presentation_value.fieldType; rai->last_specified_value.far_ptr = rai->owner->presentation_value.far_ptr; } if (rai->owner->is_property && gf_svg_attribute_is_interpolatable(rai->last_specified_value.fieldType)) { gf_svg_attributes_resolve_currentColor(&rai->last_specified_value, &rai->owner->current_color_value); gf_svg_attributes_resolve_inherit(&rai->last_specified_value, &rai->owner->parent_presentation_value); }}/* if the animation behavior is accumulative and this is not the first iteration, then we modify the interpolation value as follows: interpolation value += last specified value * number of iterations completed */static void gf_smil_anim_apply_accumulate(SMIL_Anim_RTI *rai){ u32 nb_iterations; SMILAnimationAttributesPointers *animp = rai->animp; SMILTimingAttributesPointers *timingp = rai->timingp; if (!animp || !timingp) return; nb_iterations = (timingp->runtime->current_interval ? timingp->runtime->current_interval->nb_iterations : 1); if ((animp->accumulate && *animp->accumulate == SMIL_ACCUMULATE_SUM) && nb_iterations > 0) { GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SMIL Animation] Time %f - Animation %s - applying accumulation (iteration #%d)\n", gf_node_get_scene_time((GF_Node*)rai->anim_elt), gf_node_get_name((GF_Node *)rai->anim_elt), nb_iterations)); gf_svg_attributes_muladd(FIX_ONE, &rai->interpolated_value, INT2FIX(nb_iterations), &rai->last_specified_value, &rai->interpolated_value, 1); rai->interpolated_value_changed = 1; } }static void gf_smil_anim_animate(SMIL_Timing_RTI *rti, Fixed normalized_simple_time){ SMIL_Anim_RTI *rai = gf_smil_anim_get_anim_runtime_from_timing(rti); SMILAnimationAttributesPointers *animp = rai->animp; if (!rai || !animp) return; rai->interpolated_value_changed = 0; gf_smil_anim_compute_interpolation_value(rai, normalized_simple_time); if (rai->interpolated_value_changed) gf_smil_anim_apply_accumulate(rai); /* Apply additive behavior if required PV = (additive == sum ? PV + animp->IV : animp->IV); */ if (animp->additive && *animp->additive == SMIL_ADDITIVE_SUM) { /* if the additive behavior is on, any change to either the base value or the interpolated value requires changing the presentation value */ 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 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 behavior (nothing to be done)\n", gf_node_get_scene_time((GF_Node*)rai->anim_elt), gf_node_get_name((GF_Node *)rai->anim_elt))); } } else { /* if the additive behavior is off, and the interpolation value has not changed the presentation value does not need to be changed */ if (rai->interpolated_value_changed) { GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SMIL Animation] Time %f - Animation %s - applying non-additive 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 non-additive behavior (nothing to be 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; } }}static void gf_smil_anim_animate_with_fraction(SMIL_Timing_RTI *rti, Fixed normalized_simple_time){ gf_smil_anim_animate(rti, rti->fraction); rti->evaluate_status = SMIL_TIMING_EVAL_NONE;}void gf_smil_anim_reset_variables(SMIL_Anim_RTI *rai){ if (!rai) return; /* we reset all the animation parameters to force computation of next interpolation value when the animation restarts */ rai->interpolated_value_changed = 0; rai->previous_key_index = -1; rai->previous_coef = -1; rai->set_done = 0;}/* copy/paste of the animate function except for the optimization which consists in not recomputing the interpolation value */static void gf_smil_anim_freeze(SMIL_Timing_RTI *rti, Fixed normalized_simple_time){ SMIL_Anim_RTI *rai = gf_smil_anim_get_anim_runtime_from_timing(rti); SMILAnimationAttributesPointers *animp = rai->animp; if (!rai || !animp) return; /* We do the accumulation only once and store the result in interpolated value */ if (rti->cycle_number == rti->first_frozen) { /* we reset interpolated_value_changed before computing the last interpolation value, in order to remove unecessary calls to gf_smil_anim_apply_accumulate */ rai->interpolated_value_changed = 0; gf_smil_anim_compute_interpolation_value(rai, normalized_simple_time); if (rai->interpolated_value_changed) gf_smil_anim_apply_accumulate(rai); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -