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

📄 svg_parser.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *					GPAC Multimedia Framework * *			Authors: Cyril Concolato - Jean le Feuvre - Jean-Claude Moissinac *				Copyright (c) 2005-200X ENST *					All rights reserved * *  This file is part of GPAC / SVG Loader module * *  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 "svg_parser.h"#include <gpac/options.h>#include <gpac/internal/terminal_dev.h>#ifndef GPAC_DISABLE_SVGBool xmllib_is_init = 0;static void svg_init_root_element(SVGParser *parser, SVG_SA_svgElement *root_svg){	if (root_svg->width.type == SVG_NUMBER_VALUE) {		parser->svg_w = FIX2INT(root_svg->width.value);		parser->svg_h = FIX2INT(root_svg->height.value);	} else {		/* if unit for width & height is in percentage, then the only meaningful value for 		width and height is 100 %. In this case, we don't specify a value. It will be assigned by the renderer */		parser->svg_w = parser->svg_h = 0;	}	gf_sg_set_scene_size_info(parser->graph, parser->svg_w, parser->svg_h, 1);	gf_sg_set_root_node(parser->graph, (GF_Node *)root_svg);}defered_element *list_dichotomic_search(GF_List *ptr, const char *search_id, s32 *index){	s32 tst_value;	s32 first = 0;	s32 last = gf_list_count(ptr)-1;	s32 current = -1;	defered_element *de = NULL;	Bool	found = 0;	/* dichotomic search in the sorted list of defered elements */	while (first<=last)	{		current = (first+last)/2;		de = (defered_element *)gf_list_get(ptr, current);		tst_value = strcmp(search_id, &(de->target_id[1]));		if (tst_value==0) {			found = 1;			break;		}		else if (tst_value>0)			first = current +1;		else			last = current -1;	}	if (index)		*index=current; /* index where the item could be inserted if necessary */	return (found?de:NULL);}void svg_entity_decl(void *user_data,				const xmlChar *name,				int type,				const xmlChar *publicId,				const xmlChar *systemId,				xmlChar *content){	SVGParser	*parser = (SVGParser *)user_data;	xmlEntityPtr ent = (xmlEntityPtr)malloc(sizeof(xmlEntity));	if (ent)	{		ent->name = strdup(name);		ent->type = type;		ent->ExternalID = strdup(publicId);		ent->SystemID = strdup(systemId);		ent->content = strdup(content);		gf_list_add(parser->entities, ent);		}}void svg_cdata_block(void *user_data, 					 const xmlChar * value, 					 int len){	SVGParser	*parser = (SVGParser *)user_data;	parser->sax_state = STARTSVG;}void svg_start_document(void *user_data){	SVGParser	*parser = (SVGParser *)user_data;	parser->sax_state = STARTSVG;	parser->unknown_depth = 0;	parser->entities  = gf_list_new();	if (!parser->entities)	{		parser->sax_state = ERROR;		// TODO implement a safe cleaning if errorif (!elt) {		return;	}}void svg_end_document(void *user_data){	SVGParser	*parser = (SVGParser *)user_data;	parser->sax_state = FINISHSVG;}xmlEntityPtr svg_get_entity(void * user_data, const xmlChar *name){	SVGParser	*parser = (SVGParser *)user_data;	u32 i, count;	count = gf_list_count(parser->entities);	for (i=0; i<count; i++) {		xmlEntityPtr ent = gf_list_get(parser->entities, i);		if (!strcmp(ent->name, name))		{			return ent;// and replace entity by ent->content		}	}	return xmlGetPredefinedEntity(name);}Bool is_svg_script_element(SVG_SA_Element *elt){	u32 tag = elt->sgprivate->tag;	return (tag==TAG_SVG_script);}Bool is_svg_text_element(SVG_SA_Element *elt){	u32 tag = elt->sgprivate->tag;	return ((tag==TAG_SVG_text)||(tag==TAG_SVG_textArea)||(tag==TAG_SVG_tspan));}Bool is_svg_anchor_tag(u32 tag){	return (tag == TAG_SVG_a);}Bool is_svg_animation_tag(u32 tag){	return (tag == TAG_SVG_set ||			tag == TAG_SVG_animate ||			tag == TAG_SVG_animateColor ||			tag == TAG_SVG_animateTransform ||			tag == TAG_SVG_animateMotion || 			tag == TAG_SVG_discard)?1:0;}void svg_characters(void *user_data, const xmlChar *ch, s32 len){	SVGParser	*parser = (SVGParser *)user_data;	SVG_SA_Element *elt = (SVG_SA_Element *)gf_list_get(parser->svg_node_stack,gf_list_count(parser->svg_node_stack)-1);	s32		baselen = 0;	if (is_svg_text_element(elt))	{		SVG_SA_textElement *text = (SVG_SA_textElement *)elt;		char *tmp = (char *)ch;		/* suppress begining spaces */		if ((!text->core->space)||(text->core->space != XML_SPACE_PRESERVE)) {			while ((*tmp == ' ' || *tmp=='\n')&& (len>0)) { tmp++; len--; }		}		if (text->textContent)		{			baselen = strlen(text->textContent);			text->textContent = (char *)realloc(text->textContent,baselen+len+1);		}		else			text->textContent = (char *)malloc(len+1);		strncpy(&text->textContent[baselen], tmp, len); // TODO verify how to manage text coding type		text->textContent[baselen+len]=0;		/* suppress ending spaces */		if ((!text->core->space)||(text->core->space != XML_SPACE_PRESERVE)) {			tmp = &(text->textContent[baselen+len - 1]);			while (*tmp == ' ' || *tmp=='\n') tmp--;			tmp++;			*tmp = 0;		}		gf_node_changed((GF_Node *)elt, NULL);	}#if 0	if (is_svg_script_element(elt))	{		SVG_SA_scriptElement *script = (SVG_SA_scriptElement *)elt;	}#endif}// TODO verifiy good practices to replace entitiesxmlChar *svg_expand_entities(SVGParser	*parser, xmlChar *originalStyle){	xmlChar *style = strdup(originalStyle);	xmlChar *newStyle;	u32 len = strlen(style);	Bool	expanded=0;	xmlEntityPtr ent;	u32		newlen;	u32		i, j;	do 	{		char *str = style;		len = strlen(style);		expanded=0;		for (i = 0; i < len+1; i++) {			if (str[i] == '&') 			{				for (j=0; j<len+1; j++)				{					if (str[j] == ';' || str[j] == 0) 					{						char *value_string;						u32 entity_len = 0;						entity_len = j - i -1;						if (entity_len)						{							value_string = (char *) malloc(sizeof(char) * (entity_len+1));							memcpy(value_string, str+i+1, entity_len);							value_string[entity_len] = 0;							ent = svg_get_entity(parser, value_string);							if (ent)							{								newlen = strlen(ent->content);								newStyle = (char *) malloc(sizeof(char) * (len+newlen-entity_len));								memcpy(newStyle, style, i);								memcpy(newStyle+i, ent->content, newlen);								memcpy(newStyle+i+newlen, style+i+entity_len+1, len-i-entity_len-1);								newStyle[len+newlen-entity_len-2] = 0;								free(style);								style = newStyle;								expanded = 1;							}						}					}				}			}		}	}	while (expanded==1);	return style;}void svg_start_element(void *user_data, const xmlChar *name, const xmlChar **attrs){	SVGParser	*parser = (SVGParser *)user_data;	SVG_SA_Element *elt;	switch(parser->sax_state) {	case STARTSVG:		if (!stricmp((char *)name, "svg")) {			elt = svg_parse_sax_element(parser, name, attrs, NULL);			if (!elt) {				parser->last_error = GF_SG_UNKNOWN_NODE;				parser->sax_state = ERROR;				return;			} else {				svg_init_root_element(parser, (SVG_SA_svgElement *)elt);			}			parser->svg_node_stack = gf_list_new();			if (!parser->svg_node_stack) {				parser->sax_state = ERROR;				return;			}			gf_list_add(parser->svg_node_stack, elt);			parser->sax_state = SVGCONTENT;			parser->loader_status = 2;		} else {			parser->prev_sax_state = STARTSVG;			parser->unknown_depth++;			parser->sax_state = UNKNOWN;		}		break;	case SVGCONTENT:		elt = svg_parse_sax_element(parser, name, attrs, 							  (SVG_SA_Element *)gf_list_get(parser->svg_node_stack,gf_list_count(parser->svg_node_stack)-1));		if (elt) 			gf_list_add(parser->svg_node_stack, elt);		else {			parser->prev_sax_state = SVGCONTENT;			parser->unknown_depth++;			parser->sax_state = UNKNOWN;		}		break;	case UNKNOWN:		parser->unknown_depth++;		break;	}}void svg_end_element(void *user_data, const xmlChar *name){	SVGParser	*parser = (SVGParser *)user_data;	switch(parser->sax_state) {	case STARTSVG:		break;	case SVGCONTENT:		gf_list_rem_last(parser->svg_node_stack);		break;	case UNKNOWN:		parser->unknown_depth--;		if (parser->unknown_depth==0) parser->sax_state = parser->prev_sax_state;		break;	}	/*JLF: there's a pb with endDocument, I force it here*/	if (!stricmp(name, "svg")) parser->sax_state = FINISHSVG;}/* end of SAX related functions *//* Generic Scene Graph handling functions for ID */void svg_parse_element_id(SVGParser *parser, SVG_SA_Element *elt, char *nodename){	u32 id = 0;	SVG_SA_Element *unided_elt;	unided_elt = (SVG_SA_Element *)gf_sg_find_node_by_name(parser->graph, nodename);	if (unided_elt) {		id = gf_node_get_id((GF_Node *)unided_elt);		if (svg_has_been_IDed(parser, nodename)) unided_elt = NULL;	} else {		id = svg_get_node_id(parser, nodename);	}	gf_node_set_id((GF_Node *)elt, id, nodename);	if (unided_elt) gf_node_replace((GF_Node *)unided_elt, (GF_Node *)elt, 0);	gf_list_add(parser->ided_nodes, elt);}				Bool svg_has_been_IDed(SVGParser *parser, xmlChar *node_name){	u32 i, count;	count = gf_list_count(parser->ided_nodes);	for (i=0; i<count; i++) {		GF_Node *n = gf_list_get(parser->ided_nodes, i);		const char *nname = gf_node_get_name(n);		if (!strcmp(nname, node_name)) return 1;	}	return 0;}u32 svg_get_next_node_id(SVGParser *parser){	u32 ID;	ID = gf_sg_get_next_available_node_id(parser->graph);	if (ID>parser->max_node_id) parser->max_node_id = ID;	return ID;}u32 svg_get_node_id(SVGParser *parser, xmlChar *nodename){	GF_Node *n;	u32 ID;	if (sscanf(nodename, "N%d", &ID) == 1) {		ID ++;		n = gf_sg_find_node(parser->graph, ID);		if (n && 0) {			u32 nID = svg_get_next_node_id(parser);			const char *nname = gf_node_get_name(n);			gf_node_set_id(n, nID, nname);		}		if (parser->max_node_id<ID) parser->max_node_id=ID;	} else {		ID = svg_get_next_node_id(parser);	}	return ID;}/* end of Generic Scene Graph handling functions for ID *//* DOM Related functions *//* Parses all the attributes of an element except id */		  void svg_parse_dom_attributes(SVGParser *parser, 									xmlNodePtr node,									SVG_SA_Element *elt,									u8 anim_value_type,									u8 anim_transform_type){	xmlAttrPtr attributes;	char *style;	u32 tag;	tag = gf_node_get_tag((GF_Node*)elt);	/* Parsing the style attribute */	if ((style = xmlGetProp(node, "style"))) gf_svg_parse_style((GF_Node *)elt, style);	/* Parsing all the other attributes, with a special case for the id attribute */	attributes = node->properties;	while (attributes) {		if (attributes->type == XML_ATTRIBUTE_NODE) {			if (!stricmp(attributes->name, "id")) {				/* should have been done in svg_parse_element_id */			} else if (!stricmp(attributes->name, "attributeName")) {				/* we don't parse the animation element attributes here */			} else if (!stricmp(attributes->name, "type")) {				if (tag == TAG_SVG_animateTransform) {				/* we don't parse the animation element attributes here */				} else {					GF_FieldInfo info;					if (!gf_node_get_field_by_name((GF_Node *)elt, "type", &info)) {						gf_svg_parse_attribute((GF_Node *)elt, &info, attributes->children->content, 0, 0);					}

⌨️ 快捷键说明

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