⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smil_anim.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 4 页
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Authors: Cyril Concolato - Jean Le Feuvre *    Copyright (c)2004-200X ENST - All rights reserved * *  This file is part of GPAC / SVG Scene Graph sub-project * *  GPAC is free software; you can redistribute it and/or modify *  it under the terms of the GNU Lesser General Public License as published by *  the Free Software Foundation; either version 2, or (at your option) *  any later version. * *  GPAC is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU Lesser General Public License for more details.	 * *  You should have received a copy of the GNU Lesser General Public *  License along with this library; see the file COPYING.  If not, write to *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <gpac/internal/scenegraph_dev.h>#include <gpac/nodes_svg_sa.h>#include <gpac/nodes_svg_sani.h>#include <gpac/nodes_svg_da.h>#define DO_OPTIMIZATION_TESTS 1/************************************************************************************** * Each GF_Node holds the (SVG/SMIL) animation elements which target itself in a list * * The following are the generic functions to manipulate this list:					  * *  - add a new animation to the list,                                                * *  - get an animation from the list,                                                 * *  - remove an animation from the list,                                              * *  - count the animations in the list,                                               * *  - delete the list                                                                 * **************************************************************************************/GF_Err gf_node_animation_add(GF_Node *node, void *animation){	if (!node || !animation) return GF_BAD_PARAM;	if (!node->sgprivate->interact) GF_SAFEALLOC(node->sgprivate->interact, struct _node_interactive_ext);	if (!node->sgprivate->interact->animations) node->sgprivate->interact->animations = gf_list_new();	return gf_list_add(node->sgprivate->interact->animations, animation);}GF_Err gf_node_animation_del(GF_Node *node){	if (!node || !node->sgprivate->interact || !node->sgprivate->interact->animations) return GF_BAD_PARAM;	gf_list_del(node->sgprivate->interact->animations);	node->sgprivate->interact->animations = NULL;	return GF_OK;}u32 gf_node_animation_count(GF_Node *node){	if (!node || !node->sgprivate->interact|| !node->sgprivate->interact->animations) return 0;	return gf_list_count(node->sgprivate->interact->animations);}void *gf_node_animation_get(GF_Node *node, u32 i){	if (!node || !node->sgprivate->interact || !node->sgprivate->interact->animations) return 0;	return gf_list_get(node->sgprivate->interact->animations, i);}GF_Err gf_node_animation_rem(GF_Node *node, u32 i){	if (!node || !node->sgprivate->interact || !node->sgprivate->interact->animations) return GF_OK;	return gf_list_rem(node->sgprivate->interact->animations, i);}/************************************************************************************** * End of Generic GF_Node animations list                                             * **************************************************************************************//************************************************************************************** * Helping functions for animation                                                    * **************************************************************************************//* Sets the pointer to the attribute value with the pointer    to the value which passed (if unspecified) */void gf_svg_attributes_resolve_unspecified(GF_FieldInfo *in, GF_FieldInfo *p, GF_FieldInfo *t){	if (in->fieldType == 0) {		if (p->fieldType == SVG_Transform_datatype) {			/* if the input value is not specified, and the presentation value is of type Transform,			   then we should use the default identity transform instead of the presentation value */			*in = *t;		} else {			*in = *p;		}	}}/* Replaces the pointer to the attribute value with the pointer    to the value which is inherited (if inherited) */void gf_svg_attributes_resolve_inherit(GF_FieldInfo *in, GF_FieldInfo *prop){	if (gf_svg_is_inherit(in)) *in = *prop;}/* Replaces the pointer to the attribute value with the pointer    to the value of the color attribute (if the current value is set to currentColor) */void gf_svg_attributes_resolve_currentColor(GF_FieldInfo *in, GF_FieldInfo *current_color){	if ((in->fieldType == SVG_Paint_datatype) && gf_svg_is_current_color(in)) {		*in = *current_color;	} }/************************************************************************************** * The main function doing evaluation of the animation is: gf_smil_anim_evaluate      * * Depending on the timing status of the animation it calls:                          * * - gf_smil_anim_animate                                                             * * - gf_smil_anim_animate_with_fraction												  * * - gf_smil_anim_freeze															  * * - gf_smil_anim_remove															  * *																					  * * The gf_smil_anim_animate consists in												  * * - interpolating using gf_smil_anim_compute_interpolation_value					  * * - accumulating using gf_smil_anim_apply_accumulate				                  * * - applying additive behavior                                                       * *																					  * * Depending on the animation attributes, one of the following functions is called    * * by the function gf_smil_anim_compute_interpolation_value                           * * - gf_smil_anim_set                                                                 * * - gf_smil_anim_animate_using_values                                                * * - gf_smil_anim_animate_from_to                                                     * * - gf_smil_anim_animate_from_by                                                     * * - gf_smil_anim_animate_using_path                                                  * *                                                                                    * * In most animation methods, the important step in the animation is to resolve       * *  the inherit and currentColor values to perform further interpolation, i.e. calls: * *	gf_svg_attributes_resolve_currentColor(&info, &rai->owner->current_color_value);  * *	gf_svg_attributes_resolve_inherit(&info, &rai->owner->parent_presentation_value); * *                                                                                    * **************************************************************************************/static void gf_smil_anim_set(SMIL_Anim_RTI *rai){	GF_FieldInfo to_info;	SMILAnimationAttributesPointers *animp = rai->animp;	if (!animp) return;	if (!animp->to || !animp->to->type) return;	if (rai->set_done && !rai->owner->presentation_value_changed) {		GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, 		   ("[SMIL Animation] Time %f - Animation     %s - set animation done - nothing to do\n", 		   gf_node_get_scene_time((GF_Node*)rai->anim_elt), 		   gf_node_get_name((GF_Node *)rai->anim_elt)));		return;	}	GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, 		   ("[SMIL Animation] Time %f - Animation     %s - applying set animation\n", 		   gf_node_get_scene_time((GF_Node*)rai->anim_elt), 		   gf_node_get_name((GF_Node *)rai->anim_elt)));	to_info.fieldType = animp->to->type;	to_info.far_ptr   = animp->to->value;	/* we do not need to resolve currentColor values or inherit values here,	   because no further interpolation is required for the animation and 	   because inheritance is applied after animations in SVG_Render_base. */	gf_svg_attributes_copy(&rai->interpolated_value, &to_info, 0);	rai->interpolated_value_changed = 1;	rai->set_done = 1;}static void gf_smil_anim_animate_using_values(SMIL_Anim_RTI *rai, Fixed normalized_simple_time){	SMILAnimationAttributesPointers *animp = rai->animp;	GF_List *values = NULL;	GF_FieldInfo value_info, value_info_next;	u32 keyValueIndex;	u32 nbValues;	Fixed interval_duration;	Fixed interpolation_coefficient;	u32 real_calcMode;	u32 tag = gf_node_get_tag(rai->anim_elt);	if (!animp) return;	values = animp->values->values;	memset(&value_info, 0, sizeof(GF_FieldInfo));	value_info.fieldType = animp->values->type;	value_info_next = value_info;	real_calcMode = (gf_svg_attribute_is_interpolatable(animp->values->type)?						(animp->calcMode ? *animp->calcMode : SMIL_CALCMODE_LINEAR):						SMIL_CALCMODE_DISCRETE					);	nbValues = gf_list_count(values);	if (nbValues == 1) {		if (rai->previous_key_index != 0) {			value_info.far_ptr = gf_list_get(values, 0);			/* no further interpolation needed 			   therefore no need to resolve inherit and currentColor */			gf_svg_attributes_copy(&rai->interpolated_value, &value_info, 0);			rai->previous_key_index = 0;			rai->interpolated_value_changed = 1;			GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SMIL Animation] Time %f - Animation     %s - Using values[0] as interpolation value\n", gf_node_get_scene_time((GF_Node*)rai->anim_elt), gf_node_get_name((GF_Node *)rai->anim_elt)));		}		return;	}	/* Computing new key value index and interpolation coefficient */	if (animp->keyTimes && gf_list_count(*animp->keyTimes)) {		u32 keyTimeIndex;		Fixed keyTimeBefore = 0, keyTimeAfter=0; 		u32 keyTimesCount = gf_list_count(*animp->keyTimes);		for (keyTimeIndex = rai->previous_keytime_index; keyTimeIndex<keyTimesCount; keyTimeIndex++) {			Fixed *tm1, *t = (Fixed *)gf_list_get(*animp->keyTimes, keyTimeIndex);			if (normalized_simple_time < *t) {				rai->previous_keytime_index = keyTimeIndex;				tm1 = (Fixed *) gf_list_get(*animp->keyTimes, keyTimeIndex-1);				if (tm1) keyTimeBefore = *tm1; 				else keyTimeBefore = 0;				keyTimeAfter = *t;				break;			}		}		keyTimeIndex--;		keyValueIndex = keyTimeIndex;		interval_duration = keyTimeAfter - keyTimeBefore;		if (interval_duration) interpolation_coefficient = gf_divfix(normalized_simple_time - keyTimeBefore, interval_duration);		else interpolation_coefficient = 1;		GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SMIL Animation] Time %f - Animation     %s - Using Key Times: index %d, interval duration %.2f, coeff: %.2f\n", keyTimeIndex, interval_duration, interpolation_coefficient));	} else {		if (real_calcMode == SMIL_CALCMODE_DISCRETE) {			Fixed tmp = normalized_simple_time*nbValues;			if (normalized_simple_time == FIX_ONE) {				keyValueIndex = nbValues-1;			} else {				keyValueIndex = FIX2INT(gf_floor(tmp));			}			interpolation_coefficient = tmp - INT2FIX(keyValueIndex);		} else {			Fixed tmp = normalized_simple_time*(nbValues-1);			if (normalized_simple_time == FIX_ONE) {				keyValueIndex = nbValues-2;			} else {				keyValueIndex = FIX2INT(gf_floor(tmp));			}			interpolation_coefficient = tmp - INT2FIX(keyValueIndex);		}		//GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SMIL Animation] Time %f - Animation     %s - No KeyTimes: key index %d, coeff: %.2f\n", keyValueIndex, FIX2FLT(interpolation_coefficient)));	}	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	{		SVG_SA_animateMotionElement *am = (SVG_SA_animateMotionElement *)rai->anim_elt;		if (gf_list_count(am->keyPoints)) {			interpolation_coefficient = *(Fixed *)gf_list_get(am->keyPoints, keyValueIndex);			keyValueIndex = 0;			GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SMIL Animation] Time %f - Animation     %s - Using Key Points: key Value Index %d, coeff: %.2f\n", keyValueIndex, interpolation_coefficient));		}	}		break;#endif	case TAG_SVG_animateMotion:		{			SVGTimedAnimBaseElement *am = (SVGTimedAnimBaseElement *)rai->anim_elt;			if (am->animp->keyPoints && gf_list_count(*am->animp->keyPoints)) {				interpolation_coefficient = *(Fixed *)gf_list_get(*am->animp->keyPoints, keyValueIndex);				keyValueIndex = 0;				GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SMIL Animation] Time %f - Animation     %s - Using Key Points: key Value Index %d, coeff: %.2f\n", keyValueIndex, interpolation_coefficient));			}		}		break;	default:		break;	}#if DO_OPTIMIZATION_TESTS	if (rai->previous_key_index == (s32)keyValueIndex &&		rai->previous_coef == interpolation_coefficient) return;#endif	rai->previous_key_index = keyValueIndex;	rai->previous_coef = interpolation_coefficient;	rai->interpolated_value_changed = 1;	switch (real_calcMode) {	case SMIL_CALCMODE_DISCRETE:		GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SMIL Animation] Time %f - Animation     %s - applying discrete animation using values (key value index: %d)\n", gf_node_get_scene_time((GF_Node*)rai->anim_elt), gf_node_get_name((GF_Node *)rai->anim_elt), keyValueIndex));		value_info.far_ptr = gf_list_get(values, keyValueIndex);		/* no further interpolation needed  		   therefore no need to resolve inherit and currentColor */		gf_svg_attributes_copy(&rai->interpolated_value, &value_info, 0);		break;	case SMIL_CALCMODE_PACED:		/* TODO: at the moment assume it is linear */	case SMIL_CALCMODE_SPLINE:		/* TODO: at the moment assume it is linear */	case SMIL_CALCMODE_LINEAR:		if (keyValueIndex == nbValues - 1) {			GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SMIL Animation] Time %f - Animation     %s - applying linear animation using values (setting last key value: %d)\n", gf_node_get_scene_time((GF_Node*)rai->anim_elt), gf_node_get_name((GF_Node *)rai->anim_elt), keyValueIndex));			value_info.far_ptr = gf_list_get(values, nbValues - 1);			/* no further interpolation needed  			   therefore no need to resolve inherit and currentColor */			gf_svg_attributes_copy(&rai->interpolated_value, &value_info, 0);		} else {						GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SMIL Animation] Time %f - Animation     %s - applying linear animation using values (key value indices: %d, %d / coeff: %f)\n", gf_node_get_scene_time((GF_Node*)rai->anim_elt), gf_node_get_name((GF_Node *)rai->anim_elt), keyValueIndex, keyValueIndex+1, interpolation_coefficient));			value_info.far_ptr = gf_list_get(values, keyValueIndex);			if (rai->owner->is_property && gf_svg_attribute_is_interpolatable(animp->values->type)) {				gf_svg_attributes_resolve_currentColor(&value_info, &rai->owner->current_color_value);							gf_svg_attributes_resolve_inherit(&value_info, &rai->owner->parent_presentation_value);			}						value_info_next.far_ptr = gf_list_get(values, keyValueIndex+1);						if (rai->owner->is_property && gf_svg_attribute_is_interpolatable(animp->values->type)) {				gf_svg_attributes_resolve_currentColor(&value_info_next, &rai->owner->current_color_value);				gf_svg_attributes_resolve_inherit(&value_info_next, &rai->owner->parent_presentation_value);			}			gf_svg_attributes_interpolate(&value_info, &value_info_next, &rai->interpolated_value, interpolation_coefficient, 1);		}		break;	}}static void gf_smil_anim_animate_from_to(SMIL_Anim_RTI *rai, Fixed normalized_simple_time){	GF_FieldInfo from_info, to_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;	} else {		from_info.fieldType = 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)) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -