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

📄 loader_svg_sani.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Copyright (c) Jean Le Feuvre 2000-2005  *					All rights reserved * *  This file is part of GPAC / Scene Management 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/scene_manager.h>#include <gpac/constants.h>#include <gpac/utf.h>#include <gpac/xml.h>#include <gpac/events.h>#include <gpac/internal/bifs_dev.h>#include <gpac/internal/scenegraph_dev.h>#include <gpac/nodes_svg_sani.h>#ifndef GPAC_DISABLE_SVG#ifdef GPAC_ENABLE_SVG_SANItypedef struct{	GF_SceneLoader *load;	GF_Err last_error;	GF_SAXParser *sax_parser;	Bool has_root;	u32 command_depth;		/* stack of SVG nodes*/	GF_List *node_stack;	GF_List *defered_hrefs;	GF_List *defered_animations;	GF_List *defered_listeners;	/*LASeR parsing*/	GF_StreamContext *laser_es;	GF_AUContext *laser_au;	GF_Command *command;	/*SAF AU maps to OD AU and is used for each new media declaration*/	GF_AUContext *saf_au;	GF_StreamContext *saf_es;} GF_SVG_SANI_Parser;typedef struct{	/*top of parsed sub-tree*/	SVG_SANI_Element *node;	/*depth of unknown elements being skipped*/	u32 unknown_depth;	/*last child added, used to speed-up parsing*/	GF_ChildNodeItem *last_child;} SVG_SANI_NodeStack;typedef struct {	/* Stage of the resolving:	    0: resolving attributes which depends on the target: from, to, by, values, type		1: resolving begin times		2: resolving end times */	u32 resolve_stage;	/* Animation element being defered */	SVG_SANI_Element *animation_elt;	/* anim parent*/	SVG_SANI_Element *anim_parent;	/* target animated element*/	SVG_SANI_Element *target;	/* id of the target element when unresolved*/	char *target_id;	/* attributes which cannot be parsed until the type of the target attribute is known */	char *attributeName;	char *type; /* only for animateTransform */	char *to;	char *from;	char *by;	char *values;} DeferedSVG_SANI_Animation;static GF_Err svg_sani_report(GF_SVG_SANI_Parser *parser, GF_Err e, char *format, ...){#ifndef GPAC_DISABLE_LOG	if (gf_log_get_level() && (gf_log_get_tools() & GF_LOG_PARSER)) {		char szMsg[2048];		va_list args;		va_start(args, format);		vsprintf(szMsg, format, args);		va_end(args);		GF_LOG((u32) (e ? GF_LOG_ERROR : GF_LOG_WARNING), GF_LOG_PARSER, ("[SVG Parsing] %s (line %d)\n", szMsg, gf_xml_sax_get_line(parser->sax_parser)) );	}#endif	if (e) parser->last_error = e;	return e;}static void svg_sani_progress(void *cbk, u32 done, u32 total){	gf_set_progress("SVG Parsing", done, total);}static void svg_sani_init_root_element(GF_SVG_SANI_Parser *parser, SVG_SANI_svgElement *root_svg){	u32 svg_w, svg_h;	svg_w = svg_h = 0;	if (root_svg->width.type == SVG_NUMBER_VALUE) {		svg_w = FIX2INT(root_svg->width.value);		svg_h = FIX2INT(root_svg->height.value);	}	gf_sg_set_scene_size_info(parser->load->scene_graph, svg_w, svg_h, 1);	if (parser->load->ctx) {		parser->load->ctx->scene_width = svg_w;		parser->load->ctx->scene_height = svg_h;	}	if (parser->load->type == GF_SM_LOAD_XSR) {		assert(parser->command);		assert(parser->command->tag == GF_SG_LSR_NEW_SCENE);		parser->command->node = (GF_Node *)root_svg;	} else {		gf_sg_set_root_node(parser->load->scene_graph, (GF_Node *)root_svg);	}	parser->has_root = 1;}static void svg_sani_delete_defered_anim(DeferedSVG_SANI_Animation *anim, GF_List *defered_animations){	if (defered_animations) gf_list_del_item(defered_animations, anim);	if (anim->target_id) free(anim->target_id);	if (anim->attributeName) free(anim->attributeName);	if (anim->to) free(anim->to);	if (anim->from) free(anim->from);	if (anim->by) free(anim->by);	if (anim->values) free(anim->values);	if (anim->type) free(anim->type);	free(anim);}void svg_sani_reset_defered_animations(GF_List *l){	/*delete all unresolved anims*/	while (1) {		DeferedSVG_SANI_Animation *anim = (DeferedSVG_SANI_Animation *)gf_list_last(l);		if (!anim) break;		svg_sani_delete_defered_anim(anim, l);	}}static void svg_sani_post_process_href(GF_SVG_SANI_Parser *parser, XMLRI *iri){	/*keep data when encoding*/	if ( !(parser->load->flags & GF_SM_LOAD_FOR_PLAYBACK)) return;	/*unresolved, queue it...*/	if ((iri->type==XMLRI_ELEMENTID) && !iri->target && iri->string) {		gf_list_add(parser->defered_hrefs, iri);	}	if (iri->type != XMLRI_STRING) return;	gf_svg_store_embedded_data(iri, parser->load->localPath, parser->load->fileName);}static Bool svg_sani_resolve_smil_times(GF_SVG_SANI_Parser *parser, GF_SceneGraph *sg, SVG_SANI_Element *anim_parent, SVG_SANI_Element *anim, GF_List *smil_times, Bool is_end, const char *node_name){	u32 i, done, count = gf_list_count(smil_times);	done = 0;	for (i=0; i<count; i++) {		SMIL_Time *t = (SMIL_Time *)gf_list_get(smil_times, i);		/*not an event*/		if (t->type != GF_SMIL_TIME_EVENT) {			done++;			continue;		}		if (!t->element_id) {			/*event source is anim parent*/			if (!t->element) t->element = (GF_Node *)anim_parent;			done++;			continue;		}		if (node_name && strcmp(node_name, t->element_id)) continue;		t->element = gf_sg_find_node_by_name(sg, t->element_id);		if (t->element) {			free(t->element_id);			t->element_id = NULL;			done++;		}	}	if (done!=count) return 0;	return 1;}static Bool svg_sani_parse_animation(GF_SVG_SANI_Parser *parser, GF_SceneGraph *sg, DeferedSVG_SANI_Animation *anim, const char *nodeID){	GF_FieldInfo info;	u32 tag;	u8 anim_value_type = 0;	if (anim->resolve_stage==0) {		if (!anim->target) anim->target = (SVG_SANI_Element *) gf_sg_find_node_by_name(sg, anim->target_id + 1);		if (!anim->target) return 0;		/*setup IRI ptr*/		anim->animation_elt->xlink->href.type = XMLRI_ELEMENTID;		anim->animation_elt->xlink->href.target = anim->target;		gf_svg_register_iri(sg, &anim->animation_elt->xlink->href);		tag = gf_node_get_tag((GF_Node *)anim->animation_elt);		if (anim->attributeName) {			SMIL_AttributeName *attname_value;			/* get the type of the target attribute to determine type of the from/to/by ... */			if (gf_node_get_field_by_name((GF_Node *)anim->animation_elt, "attributeName", &info) != GF_OK) return 1;			attname_value = (SMIL_AttributeName *)info.far_ptr;			if (gf_node_get_field_by_name((GF_Node *)anim->target, anim->attributeName, &info) == GF_OK) {				attname_value->type = info.fieldType;				attname_value->field_ptr = info.far_ptr;				attname_value->name = anim->attributeName;			} else {				return 1;			}			anim_value_type = attname_value->type;		} else {			if (tag == TAG_SVG_SANI_animateMotion) {				anim_value_type = SVG_Motion_datatype;			} else if (tag == TAG_SVG_SANI_discard) {				anim->resolve_stage = 1;				return svg_sani_parse_animation(parser, sg, anim, nodeID);			} else {				GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("[SVG Parsing] missing attributeName attribute on %s\n", gf_node_get_name((GF_Node *)anim->animation_elt)));			}		}		if (anim->type && (tag== TAG_SVG_SANI_animateTransform) ) {			/* determine the transform_type in case of animateTransform attribute */			gf_node_get_field_by_name((GF_Node *)anim->animation_elt, "type", &info);			gf_svg_parse_attribute((GF_Node *)anim->animation_elt, &info, anim->type, 0);			switch(*(SVG_TransformType *) info.far_ptr) {			case SVG_TRANSFORM_TRANSLATE:				anim_value_type = SVG_Transform_Translate_datatype;				break;			case SVG_TRANSFORM_SCALE:				anim_value_type = SVG_Transform_Scale_datatype;				break;			case SVG_TRANSFORM_ROTATE:				anim_value_type = SVG_Transform_Rotate_datatype;				break;			case SVG_TRANSFORM_SKEWX:				anim_value_type = SVG_Transform_SkewX_datatype;				break;			case SVG_TRANSFORM_SKEWY:				anim_value_type = SVG_Transform_SkewY_datatype;				break;			case SVG_TRANSFORM_MATRIX:				anim_value_type = SVG_Transform_datatype;				break;			default:				GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[SVG Parsing] unknown datatype for animate transform.\n"));				return 0;			}		}		/* Parsing of to / from / by / values */		if (anim->to) {			gf_node_get_field_by_name((GF_Node *)anim->animation_elt, "to", &info);			gf_svg_parse_attribute((GF_Node *)anim->animation_elt, &info, anim->to, anim_value_type);			if (anim_value_type==XMLRI_datatype) svg_sani_post_process_href(parser, (XMLRI*)anim->animation_elt->anim->to.value);		} 		if (anim->from) {			gf_node_get_field_by_name((GF_Node *)anim->animation_elt, "from", &info);			gf_svg_parse_attribute((GF_Node *)anim->animation_elt, &info, anim->from, anim_value_type);			if (anim_value_type==XMLRI_datatype) svg_sani_post_process_href(parser, (XMLRI*)anim->animation_elt->anim->from.value);		} 		if (anim->by) {			gf_node_get_field_by_name((GF_Node *)anim->animation_elt, "by", &info);			gf_svg_parse_attribute((GF_Node *)anim->animation_elt, &info, anim->by, anim_value_type);			if (anim_value_type==XMLRI_datatype) svg_sani_post_process_href(parser, (XMLRI*)anim->animation_elt->anim->by.value);		} 		if (anim->values) {			gf_node_get_field_by_name((GF_Node *)anim->animation_elt, "values", &info);			gf_svg_parse_attribute((GF_Node *)anim->animation_elt, &info, anim->values, anim_value_type);			if (anim_value_type==XMLRI_datatype) {				u32 i, count = gf_list_count(anim->animation_elt->anim->values.values);				for (i=0; i<count; i++) {					XMLRI *iri = (XMLRI *)gf_list_get(anim->animation_elt->anim->values.values, i);					svg_sani_post_process_href(parser, iri);				}			}		}		anim->resolve_stage = 1;	}	if (anim->resolve_stage == 1) {		if (svg_sani_resolve_smil_times(parser, sg, anim->anim_parent, anim->animation_elt, anim->animation_elt->timing->begin, 0, nodeID)) {			anim->resolve_stage = 2;		} else {			return 0;		}	}	if (!svg_sani_resolve_smil_times(parser, sg, anim->anim_parent, anim->animation_elt, anim->animation_elt->timing->end, 1, nodeID)) return 0;	/*animateMotion needs its children to be parsed !! */	if (!nodeID && gf_node_get_tag((GF_Node *)anim->animation_elt) == TAG_SVG_SANI_animateMotion)		return 1;	/*OK init the anim*/	gf_node_init((GF_Node *)anim->animation_elt);	return 1;}static void svg_sani_resolved_refs(GF_SVG_SANI_Parser *parser, GF_SceneGraph *sg, const char *nodeID){	u32 count, i;	/*check unresolved HREF*/	count = gf_list_count(parser->defered_hrefs);	for (i=0; i<count; i++) {		GF_Node *targ;		XMLRI *iri = (XMLRI *)gf_list_get(parser->defered_hrefs, i);		if (nodeID && strcmp(iri->string + 1, nodeID)) continue;		targ = gf_sg_find_node_by_name(sg, iri->string + 1);		if (targ) {			iri->type = XMLRI_ELEMENTID;			iri->target = (SVG_SANI_Element *) targ;			gf_svg_register_iri(sg, iri);			free(iri->string);			iri->string = NULL;			gf_list_rem(parser->defered_hrefs, i);			i--;			count--;		}	}	/*check unresolved listeners*/	count = gf_list_count(parser->defered_listeners);

⌨️ 快捷键说明

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