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

📄 loader_svg_sa.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *			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_sa.h>#ifndef GPAC_DISABLE_SVG#ifdef GPAC_ENABLE_SVG_SAtypedef struct{	GF_SceneLoader *load;	GF_Err last_error;	GF_SAXParser *sax_parser;	Bool has_root;		/* stack of SVG nodes*/	GF_List *node_stack;	GF_List *defered_hrefs;	GF_List *defered_animations;	GF_List *defered_listeners;} GF_SVG_SA_Parser;typedef struct{	/*top of parsed sub-tree*/	SVG_SA_Element *node;	/*depth of unknown elements being skipped*/	u32 unknown_depth;	/*last child added, used to speed-up parsing*/	GF_ChildNodeItem *last_child;} SVG_SA_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_SA_Element *animation_elt;	/* anim parent*/	SVG_SA_Element *anim_parent;	/* target animated element*/	SVG_SA_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;} DeferedAnimation;static GF_Err svg_sa_report(GF_SVG_SA_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_progress(void *cbk, u32 done, u32 total){	gf_set_progress("SVG Parsing", done, total);}static void svg_sa_init_root_element(GF_SVG_SA_Parser *parser, SVG_SA_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;	}	parser->has_root = 1;}static void svg_sa_delete_defered_anim(DeferedAnimation *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_sa_reset_defered_animations(GF_List *l){	/*delete all unresolved anims*/	while (1) {		DeferedAnimation *anim = (DeferedAnimation *)gf_list_last(l);		if (!anim) break;		svg_sa_delete_defered_anim(anim, l);	}}static void svg_post_process_href(GF_SVG_SA_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_sa_parse_animation(GF_SVG_SA_Parser *parser, GF_SceneGraph *sg, DeferedAnimation *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_SA_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_SA_animateMotion) {				anim_value_type = SVG_Motion_datatype;			} else if (tag == TAG_SVG_SA_discard) {				anim->resolve_stage = 1;				return svg_sa_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_SA_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_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_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_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_post_process_href(parser, iri);				}			}		}		anim->resolve_stage = 1;	}	if (anim->resolve_stage == 1) {		if (gf_svg_resolve_smil_times(sg, anim->anim_parent, anim->animation_elt->timing->begin, 0, nodeID)) {			anim->resolve_stage = 2;		} else {			return 0;		}	}	if (!gf_svg_resolve_smil_times(sg, anim->anim_parent, 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_SA_animateMotion)		return 1;	/*OK init the anim*/	gf_node_init((GF_Node *)anim->animation_elt);	return 1;}static void svg_sa_resolved_refs(GF_SVG_SA_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_SA_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);	for (i=0; i<count; i++) {		GF_Node *par;		SVG_SA_listenerElement *listener = (SVG_SA_listenerElement *)gf_list_get(parser->defered_listeners, i);		par = NULL;		if (listener->observer.type == XMLRI_ELEMENTID) {			if (!listener->observer.target) continue;			else par = (GF_Node*)listener->observer.target;		}		if (listener->target.type == XMLRI_ELEMENTID) {			if (!listener->target.target) continue;			else {				if (!par) par = (GF_Node*)listener->target.target;			}		}		assert(par);		gf_dom_listener_add((GF_Node *)par, (GF_Node *) listener);		gf_list_rem(parser->defered_listeners, i);		i--;		count--;	}	/*check unresolved anims*/	count = gf_list_count(parser->defered_animations);	for (i=0; i<count; i++) {		DeferedAnimation *anim = (DeferedAnimation *)gf_list_get(parser->defered_animations, i);		/*resolve it - we don't check the name since it may be used in SMIL times, which we don't track at anim level*/		if (svg_sa_parse_animation(parser, sg, anim, nodeID)) {			svg_sa_delete_defered_anim(anim, parser->defered_animations);			i--;			count--;		}	}}static SVG_SA_Element *svg_sa_parse_element(GF_SVG_SA_Parser *parser, const char *name, const char *name_space, 									 const GF_XMLAttribute *attributes, u32 nb_attributes, 									 SVG_SA_NodeStack *parent){	u32	tag, i;	SVG_SA_Element *elt;	GF_FieldInfo info;	const char *node_name = NULL;	DeferedAnimation *anim = NULL;	/* Translates the node type (called name) from a String into a unique numeric identifier in GPAC */	tag = gf_svg_sa_node_type_by_class_name(name);	if (tag == TAG_UndefinedNode) {		svg_sa_report(parser, GF_OK, "Unknown element %s - skipping", name);		return NULL;	}	/* Creates a node in the current scene graph */	elt = (SVG_SA_Element*)gf_node_new(parser->load->scene_graph, tag);	if (!elt) {		parser->last_error = GF_SG_UNKNOWN_NODE;		return NULL;	}	gf_node_register((GF_Node *)elt, (parent ? (GF_Node *)parent->node : NULL));	if (parent && elt) gf_node_list_add_child_last( & parent->node->children, (GF_Node*)elt, & parent->last_child);	if (gf_svg_sa_is_animation_tag(tag)) {		GF_SAFEALLOC(anim, DeferedAnimation);		/*default anim target is parent node*/		anim->animation_elt = elt;		anim->target = parent->node;		anim->anim_parent = parent->node;	} else if (tag == TAG_SVG_SA_video || tag == TAG_SVG_SA_audio || tag == TAG_SVG_SA_animation || tag == TAG_SVG_SA_conditional) {		/* warning: we use the DeferedAnimation structure for some timing nodes which are not 		   animations, but we put the parse stage at 1 (timing) see svg_sa_parse_animation. */		GF_SAFEALLOC(anim, DeferedAnimation);		/*default anim target is parent node*/		anim->animation_elt = elt;		anim->anim_parent = parent->node;		anim->resolve_stage = 1;	}	/*parse all att*/	for (i=0; i<nb_attributes; i++) {		GF_XMLAttribute *att = (GF_XMLAttribute *)&attributes[i];		if (!att->value || !strlen(att->value)) continue;		if (!stricmp(att->name, "style")) {			/* Special case: style if present will always be first in the list */			gf_svg_parse_style((GF_Node *)elt, att->value);

⌨️ 快捷键说明

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