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

📄 drawable.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 / 2D rendering 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 "drawable.h"#include "visualsurface2d.h"#include "stacks2d.h"#ifndef GPAC_DISABLE_SVG#include "svg_stacks.h"#endif/*default rendering routine*/void drawable_draw(RenderEffect2D *eff) {	VS2D_TexturePath(eff->surface, eff->ctx->drawable->path, eff->ctx);	VS2D_DrawPath(eff->surface, eff->ctx->drawable->path, eff->ctx, NULL, NULL);}/*default point_over routine*/void drawable_pick(RenderEffect2D *eff){	GF_Matrix2D inv;	StrikeInfo2D *si;	Fixed x, y;	if (!eff->ctx || !eff->ctx->drawable->path) return;	assert(eff->surface);	gf_mx2d_copy(inv, eff->ctx->transform);	gf_mx2d_inverse(&inv);	x = eff->x;	y = eff->y;	gf_mx2d_apply_coords(&inv, &x, &y);	if (eff->ctx->h_texture 		|| (eff->pick_type<PICK_FULL) 		|| GF_COL_A(eff->ctx->aspect.fill_color)		|| (eff->ctx->flags & CTX_SVG_PICK_PATH)		) {		if (gf_path_point_over(eff->ctx->drawable->path, x, y)) {			eff->is_over = 1;			return;		}	}	if (eff->ctx->aspect.pen_props.width 		|| eff->ctx->aspect.line_texture 		|| (eff->pick_type!=PICK_PATH)		|| (eff->ctx->flags & CTX_SVG_PICK_OUTLINE)		) {		si = drawctx_get_strikeinfo(eff->surface->render, eff->ctx, NULL);		if (si && si->outline && gf_path_point_over(si->outline, x, y)) {			eff->is_over = 1;		}	}}Drawable *drawable_new(){	Drawable *tmp;	GF_SAFEALLOC(tmp, Drawable)	tmp->path = gf_path_new();	/*allocate a default surface container*/	GF_SAFEALLOC(tmp->dri, DRInfo);	/*allocate a default bounds container*/	GF_SAFEALLOC(tmp->dri->current_bounds, BoundInfo);	return tmp;}void drawable_reset_bounds(Drawable *dr, VisualSurface2D *surf){	DRInfo *dri;	BoundInfo *bi, *_cur;	dri = dr->dri;	while (dri) {		if (dri->surface != surf) {			dri = dri->next;			continue;		}		/*destroy previous bounds only, since current ones are always used during traversing*/		bi = dri->previous_bounds;		while (bi) {			_cur = bi;			bi = bi->next;			free(_cur);		}		dri->previous_bounds = NULL;		return;	}}void drawable_del_ex(Drawable *dr, Render2D *r2d){	StrikeInfo2D *si;	Bool is_reg = 0;	DRInfo *dri, *cur;	BoundInfo *bi, *_cur;	/*remove node from all surfaces it's on*/	dri = dr->dri;	while (dri) {		is_reg = R2D_IsSurfaceRegistered(r2d, dri->surface);			bi = dri->current_bounds;		while (bi) {			_cur = bi;			if (is_reg) ra_add(&dri->surface->to_redraw, &bi->clip);			bi = bi->next;			free(_cur);		}		bi = dri->previous_bounds;		while (bi) {			_cur = bi;			if (is_reg) ra_add(&dri->surface->to_redraw, &bi->clip);			bi = bi->next;			free(_cur);		}		if (is_reg) VS2D_DrawableDeleted(dri->surface, dr);		cur = dri;		dri = dri->next;		free(cur);	}	r2d->compositor->draw_next_frame = 1;	/*remove path object*/	if (dr->path) gf_path_del(dr->path);	si = dr->outline;	while (si) {		StrikeInfo2D *next = si->next;		/*remove from main strike list*/		if (r2d) gf_list_del_item(r2d->strike_bank, si);		delete_strikeinfo2d(si);		si = next;	}	free(dr);}void drawable_del(Drawable *dr){	GF_Renderer *sr = gf_sr_get_renderer(dr->node);	drawable_del_ex(dr, sr ? sr->visual_renderer->user_priv : NULL);}void DestroyDrawableNode(GF_Node *node){	drawable_del( (Drawable *)gf_node_get_private(node) );}Drawable *drawable_stack_new(Render2D *sr, GF_Node *node){	Drawable *stack = drawable_new();	stack->node = node;	gf_node_set_private(node, stack);	return stack;}static BoundInfo *drawable_check_alloc_bounds(struct _drawable_context *ctx, VisualSurface2D *surf){	DRInfo *dri, *prev;	BoundInfo *bi, *_prev;	/*get bounds info for this surface*/	prev = NULL;	dri = ctx->drawable->dri;	while (dri) {		if (dri->surface == surf) break;		if (!dri->surface) {			dri->surface = surf;			break;		}		prev = dri;		dri = dri->next;	}	if (!dri) {		GF_SAFEALLOC(dri, DRInfo);		dri->surface = surf;		if (prev) prev->next = dri;		else ctx->drawable->dri = dri;	}		/*get available bound info slot*/	_prev = NULL;	bi = dri->current_bounds;	while (bi) {		if (!bi->clip.width) break;		_prev = bi;		bi = bi->next;	}	if (!bi) {		GF_SAFEALLOC(bi, BoundInfo);		if (_prev) {			assert(!_prev->next);			_prev->next = bi;		}		else {			assert(!dri->current_bounds);			dri->current_bounds = bi;		}		GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 2D] Allocating new bound info for drawable %s\n", gf_node_get_class_name(ctx->drawable->node)));	}	/*reset next bound info*/	if (bi->next) bi->next->clip.width = 0;	return bi;}/*move current bounds to previous bounds*/Bool drawable_flush_bounds(Drawable *drawable, struct _visual_surface_2D *on_surface, u32 render_mode){	Bool was_drawn;	DRInfo *dri;	BoundInfo *tmp;	/*reset node modified flag*/	drawable->flags &= ~DRAWABLE_HAS_CHANGED;	dri = drawable->dri;	while (dri) {		if (dri->surface == on_surface) break;		dri = dri->next;	}	if (!dri) return 0;	was_drawn = (dri->current_bounds && dri->current_bounds->clip.width) ? 1 : 0;	if (render_mode) {		/*permanent direct rendering, destroy previous bounds*/		if (render_mode==1) {			if (dri->previous_bounds) {				GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 2D] Destroying previous bounds info for drawable %s\n", gf_node_get_class_name(drawable->node)));				while (dri->previous_bounds) {					BoundInfo *bi = dri->previous_bounds;					dri->previous_bounds = bi->next;					free(bi);				}			}		}	}	/*indirect rendering, flush bounds*/	else {		tmp = dri->previous_bounds;		dri->previous_bounds = dri->current_bounds;		dri->current_bounds = tmp;	}	/*reset first allocated bound*/	if (dri->current_bounds) dri->current_bounds->clip.width = 0;	drawable->flags &= ~DRAWABLE_DRAWN_ON_SURFACE;	return was_drawn;}	/*	return 1 if same bound is found in previous list (and remove it from the list)	return 0 otherwise*/Bool drawable_has_same_bounds(struct _drawable_context *ctx, struct _visual_surface_2D *surf){	DRInfo *dri;	BoundInfo *bi;		dri = ctx->drawable->dri;	while (dri) {		if (dri->surface == surf) break;		dri = dri->next;	}	if (!dri) return 0;	bi = dri->previous_bounds;	while (bi) {		if (			/*if 0, end of bounds used in the previous pass*/			bi->clip.width			/*we need the same Appearance || parent <use>*/			&& (bi->extra_check == ctx->appear) 			/*we need exact same cliper*/			&& (bi->clip.x==ctx->bi->clip.x) && (bi->clip.y==ctx->bi->clip.y)			&& (bi->clip.width==ctx->bi->clip.width) && (bi->clip.height==ctx->bi->clip.height)			/*only check x and y (if w or h have changed, object has changed -> bounds info has been reset*/			&& (bi->unclip.x==ctx->bi->unclip.x) && (bi->unclip.y==ctx->bi->unclip.y)			) {			/*remove*/			bi->clip.width = 0;			return 1;		}		bi = bi->next;	}	return 0;}/*	return any previous bounds related to the same surface in @rc if any	if nothing found return 0*/Bool drawable_get_previous_bound(Drawable *drawable, GF_IRect *rc, struct _visual_surface_2D *surf){	DRInfo *dri;	BoundInfo *bi;	dri = drawable->dri;	while (dri) {		if (dri->surface == surf) break;		dri = dri->next;	}	if (!dri) return 0;	bi = dri->previous_bounds;	while (bi) {		if (bi->clip.width) {			*rc = bi->clip;			bi->clip.width = 0;			return 1;		}		bi = bi->next;	}	return 0;}DrawableContext *NewDrawableContext(){	DrawableContext *tmp;	GF_SAFEALLOC(tmp, DrawableContext);	return tmp;}void DeleteDrawableContext(DrawableContext *ctx){	drawctx_reset(ctx);	free(ctx);}void drawctx_reset(DrawableContext *ctx){	DrawableContext *next = ctx->next;	drawctx_reset_sensors(ctx);	if (ctx->col_mat) free(ctx->col_mat);	memset(ctx, 0, sizeof(DrawableContext));	ctx->next = next;	/*by default all nodes are transparent*/	ctx->flags |= CTX_IS_TRANSPARENT;	/*BIFS has default value for 2D appearance ...*/	ctx->aspect.fill_color = 0xFFCCCCCC;	ctx->aspect.line_color = 0xFFCCCCCC;	ctx->aspect.pen_props.width = FIX_ONE;	ctx->aspect.pen_props.cap = GF_LINE_CAP_FLAT;	ctx->aspect.pen_props.join = GF_LINE_JOIN_BEVEL;	ctx->aspect.pen_props.miterLimit = 4*FIX_ONE;}void drawctx_reset_sensors(DrawableContext *ctx){	SensorContext *sc = ctx->sensor;	while (sc) {		SensorContext *cur = sc;		sc = sc->next;		free(cur);	}	ctx->sensor = NULL;}static void drawctx_add_sensor(DrawableContext *ctx, SensorContext *handler){	SensorContext *sc = (SensorContext *)malloc(sizeof(SensorContext));	sc->h_node = handler->h_node;	sc->next = NULL;	gf_mx2d_copy(sc->matrix, handler->matrix);	if (!ctx->sensor) {		ctx->sensor = sc;	} else {		SensorContext *cur = ctx->sensor;		while (cur->next) cur = cur->next;		cur->next = sc;	}}void drawctx_update_info(DrawableContext *ctx, struct _visual_surface_2D *surf){	DRInfo *dri;	Bool moved, need_redraw, drawn;	need_redraw = (ctx->flags & CTX_REDRAW_MASK) ? 1 : 0;	drawn = 0;	dri = ctx->drawable->dri;	while (dri) {		if (dri->surface==surf) {			if (dri->current_bounds && dri->current_bounds->clip.width) drawn = 1;			break;		}		dri = dri->next;	}	if (drawn) {		ctx->drawable->flags |= DRAWABLE_DRAWN_ON_SURFACE; 		/*node has been modified, do not check bounds, just assumed it moved*/		if (ctx->drawable->flags & DRAWABLE_HAS_CHANGED) {			moved = 1;		} else {			/*check if same bounds are used*/			moved = !drawable_has_same_bounds(ctx, surf);		}		if (need_redraw || moved) ctx->flags |= CTX_REDRAW_MASK;	}	/*in all cases reset dirty flag of appearance and its sub-nodes*/	//if (ctx->flags & CTX_HAS_APPEARANCE) gf_node_dirty_reset(ctx->appear);}static void setup_drawable_context(DrawableContext *ctx, RenderEffect2D *eff){	M_Material2D *m = NULL;	M_LineProperties *LP;	M_XLineProperties *XLP;	if (ctx->appear == NULL) goto check_default;	m = (M_Material2D *) ((M_Appearance *)ctx->appear)->material;	if ( m == NULL) {		ctx->aspect.fill_color &= 0x00FFFFFF;		goto check_default;	}	if (gf_node_get_tag((GF_Node *) m) != TAG_MPEG4_Material2D) return;	ctx->aspect.fill_color = GF_COL_ARGB_FIXED(FIX_ONE-m->transparency, m->emissiveColor.red, m->emissiveColor.green, m->emissiveColor.blue);	if (ctx->col_mat) 		ctx->aspect.fill_color = gf_cmx_apply(ctx->col_mat, ctx->aspect.fill_color);	ctx->aspect.line_color = ctx->aspect.fill_color;	if (!m->filled) ctx->aspect.fill_color &= 0x00FFFFFF;	ctx->aspect.pen_props.cap = GF_LINE_CAP_FLAT;

⌨️ 快捷键说明

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