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

📄 svg_base_sa.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *			GPAC - Multimedia Framework C SDK * *			Authors: Cyril Concolato - Jean le Feuvre *				Copyright (c) 2005-200X ENST *					All rights reserved * *  This file is part of GPAC / SVG Rendering 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 "visualsurface2d.h"#ifndef GPAC_DISABLE_SVG#include "svg_stacks.h"#ifdef GPAC_ENABLE_SVG_SAvoid svg_sa_apply_local_transformation(RenderEffect2D *eff, GF_Node *node, GF_Matrix2D *backup_matrix){	SVGTransformableElement *tr = (SVGTransformableElement *)node;	gf_mx2d_copy(*backup_matrix, eff->transform);	if (tr->transform.is_ref) 		gf_mx2d_copy(eff->transform, eff->vb_transform);	if (tr->motionTransform) 		gf_mx2d_pre_multiply(&eff->transform, tr->motionTransform);	gf_mx2d_pre_multiply(&eff->transform, &tr->transform.mat);}void svg_sa_restore_parent_transformation(RenderEffect2D *eff, GF_Matrix2D *backup_matrix){	gf_mx2d_copy(eff->transform, *backup_matrix);  }/* Set the viewport of the renderer based on the element that contains a viewport    TODO: change the SVG_SA_svgElement into an element that has a viewport (more generic)*/static void svg_sa_set_viewport_transformation(RenderEffect2D *eff, SVG_SA_svgElement *svg, Bool is_root) {	GF_Matrix2D mat;	Fixed real_width, real_height;	gf_mx2d_init(mat);	if (is_root) {		u32 scene_width = eff->surface->render->compositor->scene_width;		u32 scene_height = eff->surface->render->compositor->scene_height;		u32 dpi = 90; /* Should retrieve the dpi from the system */		switch (svg->width.type) {		case SVG_NUMBER_VALUE:		case SVG_NUMBER_PX:			real_width = INT2FIX(scene_width);			break;		case SVG_NUMBER_PERCENTAGE:			/*u32 * fixed / u32*/			real_width = scene_width*svg->width.value/100;			break;		case SVG_NUMBER_IN:			real_width = dpi * svg->width.value;			break;		case SVG_NUMBER_CM:			real_width = gf_mulfix(dpi*FLT2FIX(0.39), svg->width.value);			break;		case SVG_NUMBER_MM:			real_width = gf_mulfix(dpi*FLT2FIX(0.039), svg->width.value);			break;		case SVG_NUMBER_PT:			real_width = dpi/12 * svg->width.value;			break;		case SVG_NUMBER_PC:			real_width = dpi/6 * svg->width.value;			break;		default:			real_width = INT2FIX(scene_width);			break;		}		switch (svg->height.type) {		case SVG_NUMBER_VALUE:		case SVG_NUMBER_PX:			real_height = INT2FIX(scene_height);			break;		case SVG_NUMBER_PERCENTAGE:			real_height = scene_height*svg->height.value/100;			break;		case SVG_NUMBER_IN:			real_height = dpi * svg->height.value;			break;		case SVG_NUMBER_CM:			real_height = gf_mulfix(dpi*FLT2FIX(0.39), svg->height.value);			break;		case SVG_NUMBER_MM:			real_height = gf_mulfix(dpi*FLT2FIX(0.039), svg->height.value);			break;		case SVG_NUMBER_PT:			real_height = dpi/12 * svg->height.value;			break;		case SVG_NUMBER_PC:			real_height = dpi/6 * svg->height.value;			break;		default:			real_height = INT2FIX(scene_height);			break;		}	} else {		real_width = real_height = 0;		switch (svg->width.type) {		case SVG_NUMBER_VALUE:		case SVG_NUMBER_PX:			real_width = svg->width.value;			break;		default:			break;		}		switch (svg->height.type) {		case SVG_NUMBER_VALUE:		case SVG_NUMBER_PX:			real_height = svg->height.value;			break;		default:			break;		}	}		if (!real_width || !real_height) return;	if (svg->viewBox.is_set && svg->viewBox.width != 0 && svg->viewBox.height != 0) {		Fixed scale, vp_w, vp_h;		if (svg->preserveAspectRatio.meetOrSlice==SVG_MEETORSLICE_MEET) {			if (gf_divfix(real_width, svg->viewBox.width) > gf_divfix(real_height, svg->viewBox.height)) {				scale = gf_divfix(real_height, svg->viewBox.height);				vp_w = gf_mulfix(svg->viewBox.width, scale);				vp_h = real_height;			} else {				scale = gf_divfix(real_width, svg->viewBox.width);				vp_w = real_width;				vp_h = gf_mulfix(svg->viewBox.height, scale);			}		} else {			if (gf_divfix(real_width, svg->viewBox.width) < gf_divfix(real_height, svg->viewBox.height)) {				scale = gf_divfix(real_height, svg->viewBox.height);				vp_w = gf_mulfix(svg->viewBox.width, scale);				vp_h = real_height;			} else {				scale = gf_divfix(real_width, svg->viewBox.width);				vp_w = real_width;				vp_h = gf_mulfix(svg->viewBox.height, scale);			}		}		if (svg->preserveAspectRatio.align==SVG_PRESERVEASPECTRATIO_NONE) {			mat.m[0] = gf_divfix(real_width, svg->viewBox.width);			mat.m[4] = gf_divfix(real_height, svg->viewBox.height);			mat.m[2] = - gf_muldiv(svg->viewBox.x, real_width, svg->viewBox.width); 			mat.m[5] = - gf_muldiv(svg->viewBox.y, real_height, svg->viewBox.height); 		} else {			Fixed dx, dy;			mat.m[0] = mat.m[4] = scale;			mat.m[2] = - gf_mulfix(svg->viewBox.x, scale); 			mat.m[5] = - gf_mulfix(svg->viewBox.y, scale); 			dx = dy = 0;			switch (svg->preserveAspectRatio.align) {			case SVG_PRESERVEASPECTRATIO_XMINYMIN:				break;			case SVG_PRESERVEASPECTRATIO_XMIDYMIN:				dx = ( real_width - vp_w) / 2; 				break;			case SVG_PRESERVEASPECTRATIO_XMAXYMIN:				dx = real_width - vp_w; 				break;			case SVG_PRESERVEASPECTRATIO_XMINYMID:				dy = ( real_height - vp_h) / 2; 				break;			case SVG_PRESERVEASPECTRATIO_XMIDYMID:				dx = ( real_width  - vp_w) / 2; 				dy = ( real_height - vp_h) / 2; 				break;			case SVG_PRESERVEASPECTRATIO_XMAXYMID:				dx = real_width  - vp_w; 				dy = ( real_height - vp_h) / 2; 				break;			case SVG_PRESERVEASPECTRATIO_XMINYMAX:				dy = real_height - vp_h; 				break;			case SVG_PRESERVEASPECTRATIO_XMIDYMAX:				dx = (real_width - vp_w) / 2; 				dy = real_height - vp_h; 				break;			case SVG_PRESERVEASPECTRATIO_XMAXYMAX:				dx = real_width  - vp_w; 				dy = real_height - vp_h; 				break;			}			mat.m[2] += dx;			mat.m[5] += dy;			/*we need a clipper*/			if (svg->preserveAspectRatio.meetOrSlice==SVG_MEETORSLICE_SLICE) {				GF_Rect rc;				rc.width = real_width;				rc.height = real_height;				if (!is_root) {					rc.x = 0;					rc.y = real_height;					gf_mx2d_apply_rect(&eff->vb_transform, &rc);				} else {					rc.x = dx;					rc.y = dy + real_height;				}				eff->surface->top_clipper = gf_rect_pixelize(&rc);			}		}	}	gf_mx2d_pre_multiply(&eff->vb_transform, &mat);}/* Node specific rendering functions   All the nodes follow the same principles:	* Check if the display property is not set to none, otherwise do not render	* Back-up of the renderer properties and apply the current ones	* Back-up of the coordinate system & apply geometric transformation if any	* Render the children if any or the shape if leaf node	* Restore coordinate system	* Restore styling properties */static void SVG_Render_svg(GF_Node *node, void *rs, Bool is_destroy){	u32 viewport_color;	GF_Matrix2D backup_matrix;	GF_IRect top_clip;	Bool is_root_svg = 0;	SVGPropertiesPointers backup_props;	u32 backup_flags;	u32 styling_size = sizeof(SVGPropertiesPointers);	SVG_SA_svgElement *svg = (SVG_SA_svgElement *)node;	RenderEffect2D *eff = (RenderEffect2D *) rs;	if (is_destroy) {		SVGPropertiesPointers *svgp = (SVGPropertiesPointers *) gf_node_get_private(node);		if (svgp) {			gf_svg_properties_reset_pointers(svgp);			free(svgp);		}		return;	}	/*enable or disable navigation*/	eff->surface->render->navigation_disabled = (svg->zoomAndPan == SVG_ZOOMANDPAN_DISABLE) ? 1 : 0;	if (!eff->svg_props) {		eff->svg_props = (SVGPropertiesPointers *) gf_node_get_private(node);		is_root_svg = 1;	}	svg_sa_render_base(node, eff, &backup_props, &backup_flags);	if (svg_is_display_off(eff->svg_props)) {		memcpy(eff->svg_props, &backup_props, styling_size);		eff->svg_flags = backup_flags;		return;	}	top_clip = eff->surface->top_clipper;	gf_mx2d_copy(backup_matrix, eff->transform);	gf_mx2d_init(eff->vb_transform);	svg_sa_set_viewport_transformation(eff, svg, is_root_svg);	gf_mx2d_pre_multiply(&eff->transform, &eff->vb_transform);	if (!is_root_svg && (svg->x.value || svg->y.value)) 		gf_mx2d_add_translation(&eff->transform, svg->x.value, svg->y.value);	/* TODO: FIX ME: this only works for single SVG element in the doc*/	if (is_root_svg && eff->svg_props->viewport_fill->type != SVG_PAINT_NONE) {		viewport_color = GF_COL_ARGB_FIXED(eff->svg_props->viewport_fill_opacity->value, eff->svg_props->viewport_fill->color.red, eff->svg_props->viewport_fill->color.green, eff->svg_props->viewport_fill->color.blue);		if (eff->surface->render->compositor->back_color != viewport_color) {			eff->invalidate_all = 1;			eff->surface->render->compositor->back_color = viewport_color;		}	}	if (eff->traversing_mode == TRAVERSE_GET_BOUNDS) {		svg_get_nodes_bounds(node, svg->children, eff);	} else {		svg_render_node_list(svg->children, eff);	}	svg_sa_restore_parent_transformation(eff, &backup_matrix);	memcpy(eff->svg_props, &backup_props, styling_size);	eff->svg_flags = backup_flags;	eff->surface->top_clipper = top_clip;}void svg_sa_init_svg(Render2D *sr, GF_Node *node){	SVGPropertiesPointers *svgp;	GF_SAFEALLOC(svgp, SVGPropertiesPointers);	gf_svg_properties_init_pointers(svgp);	gf_node_set_private(node, svgp);	gf_node_set_callback_function(node, SVG_Render_svg);}#undef ENABLE_CULLING#ifdef ENABLE_CULLINGstatic GFINLINE Bool rect_over_cliper(GF_Rect *r, GF_IRect *cliper){	if (cliper->x+cliper->width<=r->x) return 0;	if (cliper->x>=r->x+r->width) return 0;	if (cliper->y-cliper->height>=r->y) return 0;	if (cliper->y<=r->y-r->height) return 0;	return 1;}/*@rc2 fully contained in @rc1*/static GFINLINE Bool rect_inside_cliper(GF_IRect *cliper, GF_Rect *r) {	if ( (cliper->x <= r->x) 		&& (cliper->y >= r->y) 		&& (cliper->x + cliper->width >= r->x + r->width) 		&& (cliper->y - cliper->height <= r->y - r->height) )		return 1;	return 0;}#endifstatic void SVG_Render_g(GF_Node *node, void *rs, Bool is_destroy){	GF_Matrix2D backup_matrix;	SVGPropertiesPointers backup_props;	u32 backup_flags;	u32 styling_size = sizeof(SVGPropertiesPointers);	SVG_SA_gElement *g = (SVG_SA_gElement *)node;	RenderEffect2D *eff = (RenderEffect2D *) rs;#ifdef ENABLE_CULLING		GF_Rect *bounds	= gf_node_get_private(node);#endif	if (is_destroy) {#ifdef ENABLE_CULLING		free(bounds);#endif		return;	}	svg_sa_render_base(node, eff, &backup_props, &backup_flags);	if (svg_is_display_off(eff->svg_props)) {		u32 prev_flags = eff->trav_flags;		eff->trav_flags |= GF_SR_TRAV_SWITCHED_OFF;		svg_render_node_list(g->children, eff);		eff->trav_flags = prev_flags;		memcpy(eff->svg_props, &backup_props, styling_size);		eff->svg_flags = backup_flags;		return;	}	#ifdef ENABLE_CULLING	if (gf_node_dirty_get(node) & GF_SG_CHILD_DIRTY) {		u32 prev_mode = eff->traversing_mode;		eff->traversing_mode = TRAVERSE_GET_BOUNDS;		svg_get_nodes_bounds(node, g->children, eff);		*bounds = eff->bounds;		gf_node_dirty_clear(node, GF_SG_CHILD_DIRTY);		eff->traversing_mode = prev_mode;	}#endif	svg_sa_apply_local_transformation(eff, node, &backup_matrix);	if (eff->traversing_mode == TRAVERSE_GET_BOUNDS) {		svg_get_nodes_bounds(node, g->children, eff);	} else {#ifdef ENABLE_CULLING		if (bounds->width && bounds->height) {			if (eff->inside_cliper) {				svg_render_node_list(g->children, eff);			} else {				GF_Rect rc = *bounds;				gf_mx2d_apply_rect(&eff->transform, &rc);				if (rect_inside_cliper(&eff->surface->top_clipper, &rc)) {					eff->inside_cliper = 1;					svg_render_node_list(g->children, eff);				} else if (rect_over_cliper(&rc, &eff->surface->top_clipper)) {					svg_render_node_list(g->children, eff);				}				eff->inside_cliper = 0;			}		}#else		svg_render_node_list(g->children, eff);#endif	}	svg_sa_restore_parent_transformation(eff, &backup_matrix);	memcpy(eff->svg_props, &backup_props, styling_size);	eff->svg_flags = backup_flags;}void svg_sa_init_g(Render2D *sr, GF_Node *node){#ifdef ENABLE_CULLING	GF_Rect *bounds;	GF_SAFEALLOC(bounds, GF_Rect);	gf_node_set_private(node, bounds);#endif	gf_node_set_callback_function(node, SVG_Render_g);}static Bool eval_conditional(GF_Renderer *sr, SVG_SA_Element *elt){	u32 i, count;	Bool found;	const char *lang_3cc, *lang_2cc;	if (!elt->conditional) return 1;	count = gf_list_count(elt->conditional->requiredFeatures);	for (i=0;i<count;i++) {		XMLRI *iri = (XMLRI *)gf_list_get(elt->conditional->requiredFeatures, i);		if (!iri->string) continue;		/*TODO FIXME: be a bit more precise :)*/		if (!strnicmp(iri->string, "http://www.w3.org/", 18)) {			char *feat = strrchr(iri->string, '#');			if (!feat) continue;			feat++;			if (!strcmp(feat, "SVGDOM")) return 0;			if (!strcmp(feat, "Font")) return 0;			continue;		}		return 0;	}	count = gf_list_count(elt->conditional->requiredExtensions);	if (count) return 0;	lang_3cc = gf_cfg_get_key(sr->user->config, "Systems", "Language3CC");	if (!lang_3cc) lang_3cc = "und";	lang_2cc = gf_cfg_get_key(sr->user->config, "Systems", "Language2CC");	if (!lang_2cc) lang_2cc = "un";	count = gf_list_count(elt->conditional->systemLanguage);

⌨️ 快捷键说明

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