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

📄 drawable.c

📁 一个用于智能手机的多媒体库适合S60 WinCE的跨平台开发库
💻 C
📖 第 1 页 / 共 3 页
字号:
	ctx->aspect.pen_props.join = GF_LINE_JOIN_MITER;	if (m->lineProps == NULL) {check_default:		/*this is a bug in the spec: by default line width is 1.0, but in meterMetrics this means half of the screen :)*/		ctx->aspect.pen_props.width = FIX_ONE;		if (!eff->is_pixel_metrics) ctx->aspect.pen_props.width = gf_divfix(ctx->aspect.pen_props.width, eff->min_hsize);		if (m && m->transparency==FIX_ONE) {			ctx->aspect.pen_props.width = 0;		} else {			switch (gf_node_get_tag(ctx->drawable->node)) {			case TAG_MPEG4_IndexedLineSet2D:				ctx->aspect.fill_color &= 0x00FFFFFF;				break;			case TAG_MPEG4_PointSet2D:				ctx->aspect.fill_color |= FIX2INT(255 * (m ? (FIX_ONE - m->transparency) : FIX_ONE)) << 24;				ctx->aspect.pen_props.width = 0;				break;			default:				if (GF_COL_A(ctx->aspect.fill_color)) ctx->aspect.pen_props.width = 0;				/*spec is unclear about that*/				else if (!m && ctx->h_texture) ctx->aspect.pen_props.width = 0;				break;			}		}		return;	}	LP = NULL;	XLP = NULL;	switch (gf_node_get_tag((GF_Node *) m->lineProps) ) {	case TAG_MPEG4_LineProperties:		LP = (M_LineProperties *) m->lineProps;		break;	case TAG_MPEG4_XLineProperties:		XLP = (M_XLineProperties *) m->lineProps;		break;	default:		ctx->aspect.pen_props.width = 0;		return;	}	if (m->lineProps && gf_node_dirty_get(m->lineProps)) ctx->flags |= CTX_APP_DIRTY;	if (LP) {		ctx->aspect.pen_props.dash = (u8) LP->lineStyle;		ctx->aspect.line_color = GF_COL_ARGB_FIXED(FIX_ONE-m->transparency, LP->lineColor.red, LP->lineColor.green, LP->lineColor.blue);		ctx->aspect.pen_props.width = LP->width;		if (ctx->col_mat) {			ctx->aspect.line_color = gf_cmx_apply(ctx->col_mat, ctx->aspect.line_color);		}		return;	} 	ctx->aspect.pen_props.dash = (u8) XLP->lineStyle;	ctx->aspect.line_color = GF_COL_ARGB_FIXED(FIX_ONE-XLP->transparency, XLP->lineColor.red, XLP->lineColor.green, XLP->lineColor.blue);	ctx->aspect.pen_props.width = XLP->width;	if (ctx->col_mat) {		ctx->aspect.line_color = gf_cmx_apply(ctx->col_mat, ctx->aspect.line_color);	}		ctx->aspect.line_scale = XLP->isScalable ? FIX_ONE : 0;	ctx->aspect.pen_props.align = XLP->isCenterAligned ? GF_PATH_LINE_CENTER : GF_PATH_LINE_INSIDE;	ctx->aspect.pen_props.cap = (u8) XLP->lineCap;	ctx->aspect.pen_props.join = (u8) XLP->lineJoin;	ctx->aspect.pen_props.miterLimit = XLP->miterLimit;	ctx->aspect.pen_props.dash_offset = XLP->dashOffset;	/*dash settings strutc is the same as MFFloat from XLP, typecast without storing*/	if (XLP->dashes.count) {		ctx->aspect.pen_props.dash_set = (GF_DashSettings *) &XLP->dashes;	} else {		ctx->aspect.pen_props.dash_set = NULL;	}	ctx->aspect.line_texture = R2D_GetTextureHandler(XLP->texture);}static Bool check_transparent_skip(DrawableContext *ctx, Bool skipFill){	/*if sensor cannot skip*/	if (ctx->sensor) return 0;	/*if texture, cannot skip*/	if (ctx->h_texture) return 0;	if (! GF_COL_A(ctx->aspect.fill_color) && !GF_COL_A(ctx->aspect.line_color) ) return 1;	if (ctx->aspect.pen_props.width == 0) {		if (skipFill) return 1;		if (!GF_COL_A(ctx->aspect.fill_color) ) return 1;	}	return 0;}GF_TextureHandler *drawable_get_texture(RenderEffect2D *eff){	M_Appearance *appear = (M_Appearance *) eff->appear;	if (!appear || !appear->texture) return NULL;	return R2D_GetTextureHandler(appear->texture);}DrawableContext *drawable_init_context(Drawable *drawable, RenderEffect2D *eff){	DrawableContext *ctx;	u32 i, count;	Bool skipFill;	assert(eff->surface);	/*switched-off geometry nodes are not rendered*/	if (eff->trav_flags & GF_SR_TRAV_SWITCHED_OFF) {		GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render2D] Drawable is switched off - skipping\n"));		return NULL;	}	//Get a empty context from the current surface	ctx = VS2D_GetDrawableContext(eff->surface);	gf_mx2d_copy(ctx->transform, eff->transform);	ctx->drawable = drawable;	/*usually set by colorTransform or changes in OrderedGroup*/	if (eff->invalidate_all) ctx->flags |= CTX_APP_DIRTY;	ctx->h_texture = NULL;	if (eff->appear) {		ctx->appear = eff->appear;		if (gf_node_dirty_get(eff->appear)) 			ctx->flags |= CTX_APP_DIRTY;	}#ifndef FIXME	/*todo cliper*/#else	else {		VS2D_RemoveLastContext(eff->surface);		return NULL;	}#endif	/*FIXME - only needed for texture*/	if (!eff->color_mat.identity) {		GF_SAFEALLOC(ctx->col_mat, GF_ColorMatrix);		gf_cmx_copy(ctx->col_mat, &eff->color_mat);	}	/*IndexedLineSet2D and PointSet2D ignores fill flag and texturing*/	skipFill = 0;	ctx->h_texture = NULL;	switch (gf_node_get_tag(ctx->drawable->node) ) {	case TAG_MPEG4_IndexedLineSet2D: 		skipFill = 1;		break;	default:		ctx->h_texture = drawable_get_texture(eff);		break;	}		/*setup sensors*/	count = gf_list_count(eff->sensors);	for (i=0; i<count; i++) 		drawctx_add_sensor(ctx, (SensorContext*)gf_list_get(eff->sensors, i));	setup_drawable_context(ctx, eff);	/*Update texture info - draw even if texture not created (this may happen if the media is removed)*/	if (ctx->h_texture && ctx->h_texture->needs_refresh) ctx->flags |= CTX_TEXTURE_DIRTY;	/*not clear in the spec: what happens when a transparent node is in form/layout ?? this may 	completely break layout of children. We consider the node should be drawn*/	if (!eff->parent && check_transparent_skip(ctx, skipFill)) {		VS2D_RemoveLastContext(eff->surface);		GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render2D] Drawable is fully transparent - skipping\n"));		return NULL;	}	ctx->flags |= CTX_HAS_APPEARANCE;	//setup clipper if needed	return ctx;}void drawable_finalize_end(struct _drawable_context *ctx, RenderEffect2D *eff){	if (eff->parent) {		group2d_add_to_context_list(eff->parent, ctx);	} else {		/*setup clipper and register bounds & sensors*/		gf_irect_intersect(&ctx->bi->clip, &eff->surface->top_clipper);		if (!ctx->bi->clip.width || !ctx->bi->clip.height) {			ctx->bi->clip.width = 0;			/*remove if this is the last context*/			if (eff->surface->cur_context == ctx) eff->surface->cur_context->drawable = NULL;			return;		}		VS2D_RegisterSensor(eff->surface, ctx);		/*keep track of node drawn, whether direct or indirect rendering*/		if (!(ctx->drawable->flags & DRAWABLE_REGISTERED_WITH_SURFACE) ) {			struct _drawable_store *it;			GF_SAFEALLOC(it, struct _drawable_store);			it->drawable = ctx->drawable;			if (eff->surface->last_prev_entry) {				eff->surface->last_prev_entry->next = it;				eff->surface->last_prev_entry = it;			} else {				eff->surface->prev_nodes = eff->surface->last_prev_entry = it;			}			GF_LOG(GF_LOG_DEBUG, GF_LOG_RENDER, ("[Render 2D] Registering new drawn node %s on surface\n", gf_node_get_class_name(it->drawable->node)));			ctx->drawable->flags |= DRAWABLE_REGISTERED_WITH_SURFACE;		}		if (eff->trav_flags & TF_RENDER_DIRECT) {			assert(!eff->traversing_mode);			eff->traversing_mode = TRAVERSE_DRAW;			eff->ctx = ctx;			gf_node_allow_cyclic_render(ctx->drawable->node);			gf_node_render(ctx->drawable->node, eff);						eff->ctx = NULL;			eff->traversing_mode = 0;		}	}}void drawable_check_bounds(struct _drawable_context *ctx, VisualSurface2D *surf){	if (!ctx->bi) {		ctx->bi = drawable_check_alloc_bounds(ctx, surf);		assert(ctx->bi);		ctx->bi->extra_check = ctx->appear;	}}static void drawable_finalize_render_ex(struct _drawable_context *ctx, RenderEffect2D *eff, GF_Rect *orig_bounds, Bool is_focus){	Fixed pw;	GF_Rect unclip, store_orig_bounds;	drawable_check_bounds(ctx, eff->surface);	if (orig_bounds) {		store_orig_bounds = *orig_bounds;	} else {		gf_path_get_bounds(ctx->drawable->path, &store_orig_bounds);	}	ctx->bi->unclip = store_orig_bounds;	gf_mx2d_apply_rect(&eff->transform, &ctx->bi->unclip);	/*apply pen width*/	if (ctx->aspect.pen_props.width) {		StrikeInfo2D *si = NULL;		/*if pen is not scalable, apply user/viewport transform so that original aspect is kept*/		if (!ctx->aspect.line_scale) {			GF_Point2D pt;			pt.x = ctx->transform.m[0] + ctx->transform.m[1];			pt.y = ctx->transform.m[3] + ctx->transform.m[4];			ctx->aspect.line_scale = gf_divfix(FLT2FIX(1.41421356f) , gf_v2d_len(&pt));		}				/*get strike info & outline for exact bounds compute. If failure use default offset*/		si = drawctx_get_strikeinfo(eff->surface->render, ctx, ctx->drawable->path);		if (si && si->outline) {			gf_path_get_bounds(si->outline, &ctx->bi->unclip);			gf_mx2d_apply_rect(&eff->transform, &ctx->bi->unclip);		} else {			pw = gf_mulfix(ctx->aspect.pen_props.width, ctx->aspect.line_scale);			ctx->bi->unclip.x -= pw/2;			ctx->bi->unclip.y += pw/2;			ctx->bi->unclip.width += pw;			ctx->bi->unclip.height += pw;		}	}	if (ctx->bi->unclip.width && ctx->bi->unclip.height) {		unclip = ctx->bi->unclip;		if (! (ctx->flags & CTX_NO_ANTIALIAS)) {			/*grow of 2 pixels (-1 and +1) to handle AA, but ONLY on cliper otherwise we will modify layout/form */			pw = (eff->is_pixel_metrics) ? FIX_ONE : 2*FIX_ONE/eff->surface->width;			unclip.x -= pw;			unclip.y += pw;			unclip.width += 2*pw;			unclip.height += 2*pw;		}		ctx->bi->clip = gf_rect_pixelize(&unclip);	} else {		ctx->bi->clip.width = 0;	}	drawable_finalize_end(ctx, eff);	if (ctx->drawable && !is_focus) drawable_check_focus_highlight(ctx->drawable->node, eff, &store_orig_bounds);}void drawable_finalize_render(struct _drawable_context *ctx, RenderEffect2D *eff, GF_Rect *orig_bounds){	drawable_finalize_render_ex(ctx, eff, orig_bounds, 0);}void drawable_check_focus_highlight(GF_Node *node, RenderEffect2D *eff, GF_Rect *orig_bounds){	DrawableContext *hl;	GF_Node *prev_node;	u32 prev_mode;	GF_Rect *bounds;	GF_Matrix2D cur;	if (eff->surface->render->focus_node!=node) return;	if (!eff->surface->render->focus_highlight) return;	hl = VS2D_GetDrawableContext(eff->surface);	hl->drawable = eff->surface->render->focus_highlight;	/*check if focus node has changed*/	prev_node = gf_node_get_private(hl->drawable->node);	if (prev_node != node) {		if (!orig_bounds) {			gf_mx2d_copy(cur, eff->transform);			gf_mx2d_init(eff->transform);			prev_mode = eff->traversing_mode;			eff->traversing_mode = TRAVERSE_GET_BOUNDS;			eff->bounds.width = eff->bounds.height = 0;			eff->bounds.x = eff->bounds.y = 0;			svg_get_nodes_bounds(node, ((SVG_Element *)node)->children, eff);			eff->traversing_mode = prev_mode;			gf_mx2d_copy(eff->transform, cur);			bounds = &eff->bounds;		} else {			bounds = orig_bounds;		}		gf_node_set_private(hl->drawable->node, node);		drawable_reset_path(hl->drawable);		gf_path_reset(hl->drawable->path);		gf_path_add_rect(hl->drawable->path, bounds->x, bounds->y, bounds->width, bounds->height);	}	hl->aspect.fill_color = eff->surface->render->highlight_fill;	hl->aspect.line_color = eff->surface->render->highlight_stroke;	hl->aspect.line_scale = 0;	hl->aspect.pen_props.width = 1;	hl->aspect.pen_props.join = GF_LINE_JOIN_BEVEL;	hl->aspect.pen_props.dash = GF_DASH_STYLE_DOT;	gf_mx2d_copy(hl->transform, eff->transform);	drawable_finalize_render_ex(hl, eff, NULL, 1);}void drawable_render_focus(GF_Node *node, void *rs, Bool is_destroy) {	RenderEffect2D *eff = (RenderEffect2D *)rs;	if (is_destroy) return;	if (eff->traversing_mode == TRAVERSE_DRAW)		VS2D_DrawPath(eff->surface, eff->ctx->drawable->path, eff->ctx, NULL, NULL);}void delete_strikeinfo2d(StrikeInfo2D *info){	if (info->outline) gf_path_del(info->outline);	free(info);}StrikeInfo2D *drawctx_get_strikeinfo(Render2D *sr, DrawableContext *ctx, GF_Path *path){	StrikeInfo2D *si, *prev;	GF_Node *lp;	u32 now;	if (ctx->appear && !ctx->aspect.pen_props.width) return NULL;	if (path && !path->n_points) return NULL;	lp = NULL;	if (ctx->appear && (gf_node_get_tag(ctx->appear) < GF_NODE_RANGE_LAST_X3D) ) {		lp = ((M_Appearance *)ctx->appear)->material;		if (lp) lp = ((M_Material2D *) lp)->lineProps;	}	prev = NULL;	si = ctx->drawable->outline;	while (si) {		/*note this includes default LP (NULL)*/		if ((si->lineProps == lp) && (!path || (path==si->original)) ) break;		if (!si->lineProps) {			gf_list_del_item(sr->strike_bank, si);			if (si->outline) gf_path_del(si->outline);			if (prev) prev->next = si->next;			else ctx->drawable->outline = si->next;			free(si);			si = prev ? prev->next : ctx->drawable->outline;			continue;		}		prev = si;		si = si->next;	}	/*not found, add*/	if (!si) {		GF_SAFEALLOC(si, StrikeInfo2D);		si->lineProps = lp;		si->node = ctx->drawable->node;		if (ctx->drawable->outline) {			prev = ctx->drawable->outline;			while (prev->next) prev = prev->next;			prev->next = si;		} else {			ctx->drawable->outline = si;		}		gf_list_add(sr->strike_bank, si);	}	/*node changed or outline not build*/	now = lp ? R2D_LP_GetLastUpdateTime(lp) : si->last_update_time;	if (!si->outline || (now!=si->last_update_time) || (si->line_scale != ctx->aspect.line_scale) || (si->path_length != ctx->aspect.pen_props.path_length) || (ctx->flags & CTX_SVG_OUTLINE_GEOMETRY_DIRTY)) {		u32 i;		Fixed w = ctx->aspect.pen_props.width;		Fixed dash_o = ctx->aspect.pen_props.dash_offset;		si->last_update_time = now;		si->line_scale = ctx->aspect.line_scale;		if (si->outline) gf_path_del(si->outline);		/*apply scale whether scalable or not (if not scalable, scale is still needed for scalable zoom)*/		ctx->aspect.pen_props.width = gf_mulfix(ctx->aspect.pen_props.width, ctx->aspect.line_scale);		if (ctx->aspect.pen_props.dash != GF_DASH_STYLE_CUSTOM_ABS) 			ctx->aspect.pen_props.dash_offset = gf_mulfix(ctx->aspect.pen_props.dash_offset, ctx->aspect.pen_props.width);				if (ctx->aspect.pen_props.dash_set) {			for(i=0; i<ctx->aspect.pen_props.dash_set->num_dash; i++) {				ctx->aspect.pen_props.dash_set->dashes[i] = gf_mulfix(ctx->aspect.pen_props.dash_set->dashes[i], ctx->aspect.line_scale);			}		}		if (path) {			si->outline = gf_path_get_outline(path, ctx->aspect.pen_props);			si->original = path;		} else {			si->outline = gf_path_get_outline(ctx->drawable->path, ctx->aspect.pen_props);		}		/*restore*/		ctx->aspect.pen_props.width = w;		ctx->aspect.pen_props.dash_offset = dash_o;		if (ctx->aspect.pen_props.dash_set) {			for(i=0; i<ctx->aspect.pen_props.dash_set->num_dash; i++) {				ctx->aspect.pen_props.dash_set->dashes[i] = gf_divfix(ctx->aspect.pen_props.dash_set->dashes[i], ctx->aspect.line_scale);			}		}	}	return si;}void drawable_reset_path_outline(Drawable *st){	StrikeInfo2D *si = st->outline;	while (si) {		if (si->outline) gf_path_del(si->outline);		si->outline = NULL;		si->original = NULL;		si = si->next;	}}void drawable_reset_path(Drawable *st){	drawable_reset_path_outline(st);	if (st->path) gf_path_reset(st->path);

⌨️ 快捷键说明

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