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

📄 svg_base_sani.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_SANI/*	This is the generic routine for child traversing - note we are not duplicating the effect*/void gf_svg_sani_apply_local_transformation(RenderEffect2D *eff, GF_Node *node, GF_Matrix2D *backup_matrix){	gf_mx2d_copy(*backup_matrix, eff->transform);	if (((SVG_SANI_TransformableElement *)node)->transform.is_ref) 		gf_mx2d_copy(eff->transform, eff->vb_transform);	if (((SVG_SANI_TransformableElement *)node)->motionTransform) 		gf_mx2d_pre_multiply(&eff->transform, ((SVG_SANI_TransformableElement *)node)->motionTransform);	gf_mx2d_pre_multiply(&eff->transform, &((SVG_SANI_TransformableElement *)node)->transform.mat);}void gf_svg_sani_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_SANI_svgElement into an element that has a viewport (more generic)*/static void gf_svg_sani_set_viewport_transformation(RenderEffect2D *eff, SVG_SANI_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 coordinate system & apply geometric transformation if any	* Render the children if any or the shape if leaf node	* Restore coordinate system */static void svg_sani_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 = 1;	SVG_SANI_svgElement *svg = (SVG_SANI_svgElement *)node;	RenderEffect2D *eff = (RenderEffect2D *) rs;	if (is_destroy) return;	/*enable or disable navigation*/	eff->surface->render->navigation_disabled = (svg->zoomAndPan == SVG_ZOOMANDPAN_DISABLE) ? 1 : 0;	svg_sani_render_base(node, eff);	if (svg->display == SVG_DISPLAY_NONE) return;	top_clip = eff->surface->top_clipper;	gf_mx2d_copy(backup_matrix, eff->transform);	gf_mx2d_init(eff->vb_transform);	gf_svg_sani_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 && svg->viewport_fill.type != SVG_PAINT_NONE) {		viewport_color = GF_COL_ARGB_FIXED(svg->viewport_fill_opacity.value, svg->viewport_fill.color.red, svg->viewport_fill.color.green, svg->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);	}	gf_svg_sani_restore_parent_transformation(eff, &backup_matrix);	eff->surface->top_clipper = top_clip;}void svg_sani_init_svg(Render2D *sr, GF_Node *node){	gf_node_set_callback_function(node, svg_sani_render_svg);}static void svg_sani_render_g(GF_Node *node, void *rs, Bool is_destroy){	GF_Matrix2D backup_matrix;	SVG_SANI_gElement *g = (SVG_SANI_gElement *)node;	RenderEffect2D *eff = (RenderEffect2D *) rs;	if (is_destroy) return;	svg_sani_render_base(node, eff);	if (g->display == SVG_DISPLAY_NONE) {		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;		return;	}			gf_svg_sani_apply_local_transformation(eff, node, &backup_matrix);	if (eff->traversing_mode == TRAVERSE_GET_BOUNDS) {		svg_get_nodes_bounds(node, g->children, eff);	} else {		svg_render_node_list(g->children, eff);	}	gf_svg_sani_restore_parent_transformation(eff, &backup_matrix);}void svg_sani_init_g(Render2D *sr, GF_Node *node){	gf_node_set_callback_function(node, svg_sani_render_g);}static Bool svg_sani_eval_conditional(GF_Renderer *sr, SVG_SANI_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);	found = count ? 0 : 1;	for (i=0;i<count;i++) {		char *lang = (char*)gf_list_get(elt->conditional->systemLanguage, i);		/*3 char-code*/		if (strlen(lang)==3) {			if (!stricmp(lang, lang_3cc)) { found = 1; break; }		}		/*2 char-code, only check first 2 chars - TODO FIXME*/		else if (!strnicmp(lang, lang_2cc, 2)) { found = 1; break; }	}	if (!found) return 0;	return 1;}static void svg_sani_render_switch(GF_Node *node, void *rs, Bool is_destroy){	GF_Matrix2D backup_matrix;	SVG_SANI_switchElement *s = (SVG_SANI_switchElement *)node;	RenderEffect2D *eff = (RenderEffect2D *) rs;	if (is_destroy) return;	svg_sani_render_base(node, eff);	if (s->display == SVG_DISPLAY_NONE) {		gf_svg_sani_restore_parent_transformation(eff, &backup_matrix);

⌨️ 快捷键说明

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