示例#1
0
/*TransformMatrix2D*/
static void RenderTransformMatrix2D(GF_Node *node, void *rs, Bool is_destroy)
{
	GF_Matrix2D bckup;
	M_TransformMatrix2D *tr = (M_TransformMatrix2D*)node;
	Transform2DStack *ptr = (Transform2DStack *) gf_node_get_private(node);
	RenderEffect2D *eff = (RenderEffect2D *)rs;

	if (is_destroy) {
		DeleteGroupingNode2D((GroupingNode2D *)ptr);
		free(ptr);
		return;
	}

	if (gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) {
		TM2D_GetMatrix(node, &ptr->mat);
		if ((tr->mxx==FIX_ONE) && (tr->mxy==0) && (tr->tx==0)
			&& (tr->myx==0) && (tr->myy==FIX_ONE) && (tr->ty==0) )
			ptr->is_identity = 1;
		else
			ptr->is_identity = 0;
	}

	/*note we don't clear dirty flag, this is done in traversing*/
	if (ptr->is_identity) {
		group2d_traverse((GroupingNode2D *)ptr, tr->children, eff);
	} else {
		gf_mx2d_copy(bckup, eff->transform);
		gf_mx2d_copy(eff->transform, ptr->mat);
		gf_mx2d_add_matrix(&eff->transform, &bckup);
		group2d_traverse((GroupingNode2D *)ptr, tr->children, eff);
		gf_mx2d_copy(eff->transform, bckup);
	}
}
示例#2
0
static void traverse_transform(GF_Node *node, Transform2DStack *stack, GF_TraverseState *tr_state)
{
	if (stack->is_null) return;

	/*note we don't clear dirty flag, this is done in traversing*/
	if (stack->is_identity) {
		group_2d_traverse(node, (GroupingNode2D *)stack, tr_state);
	}
#ifndef GPAC_DISABLE_3D
	else if (tr_state->visual->type_3d) {
		GF_Matrix mx_bckup;
		gf_mx_copy(mx_bckup, tr_state->model_matrix);

		gf_mx_add_matrix_2d(&tr_state->model_matrix, &stack->mat);
		group_2d_traverse(node, (GroupingNode2D *)stack, tr_state);
		gf_mx_copy(tr_state->model_matrix, mx_bckup);
	}
#endif
	else {
		GF_Matrix2D bckup;
		gf_mx2d_copy(bckup, tr_state->transform);
		gf_mx2d_pre_multiply(&tr_state->transform, &stack->mat);

		group_2d_traverse(node, (GroupingNode2D *)stack, tr_state);

		gf_mx2d_copy(tr_state->transform, bckup);
	}

	if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) {
		gf_mx2d_apply_rect(&stack->mat, &tr_state->bounds);
	}
}
示例#3
0
Bool visual_2d_draw_frame(GF_VisualManager *visual, GF_Node *root, GF_TraverseState *tr_state, Bool is_root_visual)
{
	GF_SceneGraph *sg;
	GF_Matrix2D backup;
	u32 i;
	Bool res;
	GF_Err e;
#ifndef GPAC_DISABLE_LOG
	u32 itime, time = gf_sys_clock();
#endif

	gf_mx2d_copy(backup, tr_state->transform);
	visual->bounds_tracker_modif_flag = DRAWABLE_HAS_CHANGED;

	e = visual_2d_init_draw(visual, tr_state);
	if (e) {
		gf_mx2d_copy(tr_state->transform, backup);
		GF_LOG(GF_LOG_ERROR, GF_LOG_COMPOSE, ("[Visual2D] Cannot init draw phase: %s\n", gf_error_to_string(e)));
		return 0;
	}

#ifndef GPAC_DISABLE_LOG
	itime = gf_sys_clock();
	visual->compositor->traverse_setup_time = itime - time;
	time = itime;
#endif

	GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Visual2D] Traversing scene subtree (root node %s)\n", root ? gf_node_get_class_name(root) : "none"));

	if (is_root_visual) {
		gf_node_traverse(root, tr_state);

		i=0;
		while ((sg = (GF_SceneGraph*)gf_list_enum(visual->compositor->extra_scenes, &i))) {
			gf_sc_traverse_subscene(visual->compositor, root, sg, tr_state);
		}
	} else {
		gf_node_traverse(root, tr_state);
	}

#ifndef GPAC_DISABLE_LOG
	itime = gf_sys_clock();
	visual->compositor->traverse_and_direct_draw_time = itime - time;
	time = itime;
#endif

	gf_mx2d_copy(tr_state->transform, backup);
	res = visual_2d_terminate_draw(visual, tr_state);

#ifndef GPAC_DISABLE_LOG
	if (!tr_state->immediate_draw) {
		visual->compositor->indirect_draw_time = gf_sys_clock() - time;
	}
#endif

	return res;
}
示例#4
0
void compositor_svg_apply_local_transformation(GF_TraverseState *tr_state, SVGAllAttributes *atts, GF_Matrix2D *backup_matrix_2d, GF_Matrix *backup_matrix)
{
#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d && backup_matrix) {
		GF_Matrix tmp;
		Bool is_draw = (tr_state->traversing_mode==TRAVERSE_SORT) ? 1 : 0;
		gf_mx_copy(*backup_matrix, tr_state->model_matrix);

		if (is_draw) visual_3d_matrix_push(tr_state->visual);

		if (atts->transform && atts->transform->is_ref) {
			gf_mx_from_mx2d(&tr_state->model_matrix, &tr_state->vb_transform);
			if (is_draw) {
				GF_Matrix tmp;
				gf_mx_init(tmp);
				gf_mx_add_translation(&tmp, -tr_state->camera->width/2, tr_state->camera->height/2, 0);
				gf_mx_add_scale(&tmp, FIX_ONE, -FIX_ONE, FIX_ONE);
				gf_mx_add_matrix(&tmp, &tr_state->model_matrix);
				visual_3d_matrix_load(tr_state->visual, tmp.m);
			}
		}

		if (atts->motionTransform) {
			if (is_draw) {
				gf_mx_from_mx2d(&tmp, atts->motionTransform);
				visual_3d_matrix_add(tr_state->visual, tmp.m);
			} else {
				gf_mx_add_matrix_2d(&tr_state->model_matrix, atts->motionTransform);
			}
		}

		if (atts->transform) {
			if (is_draw) {
				gf_mx_from_mx2d(&tmp, &atts->transform->mat);
				visual_3d_matrix_add(tr_state->visual, tmp.m);
			} else {
				gf_mx_add_matrix_2d(&tr_state->model_matrix, &atts->transform->mat);
			}
		}
		return;
	} 
#endif
	gf_mx2d_copy(*backup_matrix_2d, tr_state->transform);

	if (atts->transform && atts->transform->is_ref) 
		gf_mx2d_copy(tr_state->transform, tr_state->vb_transform);

	if (atts->motionTransform) 
		gf_mx2d_pre_multiply(&tr_state->transform, atts->motionTransform);

	if (atts->transform) 
		gf_mx2d_pre_multiply(&tr_state->transform, &atts->transform->mat);

}
示例#5
0
/*
	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);
}
示例#6
0
static void svg_sani_LG_ComputeMatrix(GF_TextureHandler *txh, GF_Rect *bounds, GF_Matrix2D *mat)
{
	SFVec2f start, end;
	SVG_SANI_linearGradientElement *lg = (SVG_SANI_linearGradientElement *) txh->owner;

	/*create gradient brush if needed*/
	if (!txh->hwtx) return;

	start.x = lg->x1.value;
	if (lg->x1.type==SVG_NUMBER_PERCENTAGE) start.x /= 100;
	start.y = lg->y1.value;
	if (lg->y1.type==SVG_NUMBER_PERCENTAGE) start.y /= 100;
	end.x = lg->x2.value;
	if (lg->x2.type==SVG_NUMBER_PERCENTAGE) end.x /= 100;
	end.y = lg->y2.value;
	if (lg->y2.type==SVG_NUMBER_PERCENTAGE) end.x /= 100;

	txh->compositor->r2d->stencil_set_gradient_mode(txh->hwtx, (GF_GradientMode) lg->spreadMethod);

	gf_mx2d_copy(*mat, lg->gradientTransform.mat);

	if (lg->gradientUnits==SVG_GRADIENTUNITS_OBJECT) {
		/*move to local coord system - cf SVG spec*/
		gf_mx2d_add_scale(mat, bounds->width, bounds->height);
		gf_mx2d_add_translation(mat, bounds->x - 1, bounds->y  - bounds->height - 1);
	}
	txh->compositor->r2d->stencil_set_linear_gradient(txh->hwtx, start.x, start.y, end.x, end.y);
}
示例#7
0
GF_Node *CT2D_PickNode(GF_TextureHandler *txh, DrawableContext *ctx, Fixed x, Fixed y)
{
	GF_Rect orig;
	GF_Matrix2D mat, tx_trans;
	Fixed width, height;
	Composite2DStack *st = (Composite2DStack *) gf_node_get_private(txh->owner);
	assert(st->surf);

	orig = ctx->bi->unclip;
	gf_mx2d_copy(mat, ctx->transform);
	gf_mx2d_inverse(&mat);
	gf_mx2d_apply_rect(&mat, &orig);

	gf_mx2d_init(mat);
	gf_mx2d_add_scale(&mat, orig.width / st->width, orig.height / st->height);
	get_gf_sr_texture_transform(ctx->appear, &st->txh, &tx_trans, (ctx->h_texture==&st->txh) ? 0 : 1, INT2FIX(orig.width), INT2FIX(orig.height));
	gf_mx2d_add_matrix(&mat, &tx_trans);
	gf_mx2d_add_translation(&mat, (orig.x), (orig.y - orig.height));
	gf_mx2d_add_matrix(&mat, &ctx->transform);

	gf_mx2d_inverse(&mat);
	gf_mx2d_apply_coords(&mat, &x, &y);

	width = INT2FIX(st->width);
	height = INT2FIX(st->height);
	while (x>width) x -= width;
	while (x < 0) x += width;
	while (y>height) y -= height;
	while (y < 0) y += height;
	x -= width / 2;
	y -= height / 2;

	return VS2D_PickNode(st->surf, x, y);
}
示例#8
0
static void svg_sani_rG_ComputeMatrix(GF_TextureHandler *txh, GF_Rect *bounds, GF_Matrix2D *mat)
{
	SFVec2f center, focal;
	Fixed radius;
	SVG_SANI_radialGradientElement *rg = (SVG_SANI_radialGradientElement *) txh->owner;

	/*create gradient brush if needed*/
	if (!txh->hwtx) return;

	gf_mx2d_copy(*mat, rg->gradientTransform.mat);

	radius = rg->r.value;
	if (rg->r.type==SVG_NUMBER_PERCENTAGE) radius /= 100;
	center.x = rg->cx.value;
	if (rg->cx.type==SVG_NUMBER_PERCENTAGE) center.x /= 100;
	center.y = rg->cy.value;
	if (rg->cy.type==SVG_NUMBER_PERCENTAGE) center.y /= 100;

	txh->compositor->r2d->stencil_set_gradient_mode(txh->hwtx, (GF_GradientMode) rg->spreadMethod);

	focal.x = rg->fx.value;
	if (rg->fx.type==SVG_NUMBER_PERCENTAGE) focal.x /= 100;
	focal.y = rg->fy.value;
	if (rg->fy.type==SVG_NUMBER_PERCENTAGE) focal.y /= 100;

	if (rg->gradientUnits==SVG_GRADIENTUNITS_OBJECT) {
		/*move to local coord system - cf SVG spec*/
		gf_mx2d_add_scale(mat, bounds->width, bounds->height);
		gf_mx2d_add_translation(mat, bounds->x, bounds->y  - bounds->height);
	} else if ((rg->fx.value==rg->fy.value) && (rg->fx.value==FIX_ONE/2)) {
		focal.x = center.x;
		focal.y = center.y;
	}
	txh->compositor->r2d->stencil_set_radial_gradient(txh->hwtx, center.x, center.y, focal.x, focal.y, radius, radius);
}
示例#9
0
文件: svg_base.c 项目: Bevara/GPAC
void compositor_svg_restore_parent_transformation(GF_TraverseState *tr_state, GF_Matrix2D *backup_matrix_2d, GF_Matrix *backup_matrix)
{
#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d && backup_matrix) {
		gf_mx_copy(tr_state->model_matrix, *backup_matrix);
		return;
	}
#endif
	gf_mx2d_copy(tr_state->transform, *backup_matrix_2d);
}
示例#10
0
static void RenderTransform2D(GF_Node *node, void *rs, Bool is_destroy)
{
	GF_Matrix2D bckup;
	M_Transform2D *tr = (M_Transform2D *)node;
	Transform2DStack *ptr = (Transform2DStack *)gf_node_get_private(node);
	RenderEffect2D *eff;
	
	if (is_destroy) {
		DeleteGroupingNode2D((GroupingNode2D *)ptr);
		free(ptr);
		return;
	}

	eff = (RenderEffect2D *) rs;

	if (gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) {
		gf_mx2d_init(ptr->mat);
		ptr->is_identity = 1;
		if ((tr->scale.x != FIX_ONE) || (tr->scale.y != FIX_ONE)) {
			gf_mx2d_add_scale_at(&ptr->mat, tr->scale.x, tr->scale.y, 0, 0, tr->scaleOrientation);
			ptr->is_identity = 0;
		}
		if (tr->rotationAngle) {
			gf_mx2d_add_rotation(&ptr->mat, tr->center.x, tr->center.y, tr->rotationAngle);
			ptr->is_identity = 0;
		}
		if (tr->translation.x || tr->translation.y) {
			ptr->is_identity = 0;
			gf_mx2d_add_translation(&ptr->mat, tr->translation.x, tr->translation.y);
		}
	}

	/*note we don't clear dirty flag, this is done in traversing*/
	if (ptr->is_identity) {
		group2d_traverse((GroupingNode2D *)ptr, tr->children, eff);
	} else {
		gf_mx2d_copy(bckup, eff->transform);
		gf_mx2d_copy(eff->transform, ptr->mat);
		gf_mx2d_add_matrix(&eff->transform, &bckup);
		group2d_traverse((GroupingNode2D *)ptr, tr->children, eff);
		gf_mx2d_copy(eff->transform, bckup);
	}
}
示例#11
0
文件: path2d.c 项目: erelh/gpac
GF_EXPORT
GF_Err gf_path_add_arc_to(GF_Path *gp, Fixed end_x, Fixed end_y, Fixed fa_x, Fixed fa_y, Fixed fb_x, Fixed fb_y, Bool cw)
{
	GF_Matrix2D mat, inv;
	Fixed angle, start_angle, end_angle, sweep, axis_w, axis_h, tmp, cx, cy, _vx, _vy, start_x, start_y;
	s32 i, num_steps;

	if (!gp->n_points) return GF_BAD_PARAM;

	start_x = gp->points[gp->n_points-1].x;
	start_y = gp->points[gp->n_points-1].y;

	cx = (fb_x + fa_x)/2;
	cy = (fb_y + fa_y)/2;

	angle = gf_atan2(fb_y-fa_y, fb_x-fa_x);
	gf_mx2d_init(mat);
	gf_mx2d_add_rotation(&mat, 0, 0, angle);
	gf_mx2d_add_translation(&mat, cx, cy);

	gf_mx2d_copy(inv, mat);
	gf_mx2d_inverse(&inv);
	gf_mx2d_apply_coords(&inv, &start_x, &start_y);
	gf_mx2d_apply_coords(&inv, &end_x, &end_y);
	gf_mx2d_apply_coords(&inv, &fa_x, &fa_y);
	gf_mx2d_apply_coords(&inv, &fb_x, &fb_y);

	//start angle and end angle
	start_angle = gf_atan2(start_y, start_x);
	end_angle = gf_atan2(end_y, end_x);
	tmp = gf_mulfix((start_x - fa_x), (start_x - fa_x)) + gf_mulfix((start_y - fa_y), (start_y - fa_y));
	axis_w = gf_sqrt(tmp);
	tmp = gf_mulfix((start_x - fb_x) , (start_x - fb_x)) + gf_mulfix((start_y - fb_y), (start_y - fb_y));
	axis_w += gf_sqrt(tmp);
	axis_w /= 2;
	axis_h = gf_sqrt(gf_mulfix(axis_w, axis_w) - gf_mulfix(fa_x,fa_x));
	sweep = end_angle - start_angle;

	if (cw) {
		if (sweep>0) sweep -= 2*GF_PI;
	} else {
		if (sweep<0) sweep += 2*GF_PI;
	}
	num_steps = GF_2D_DEFAULT_RES/2;
	for (i=1; i<=num_steps; i++) {
		angle = start_angle + sweep*i/num_steps;
		_vx = gf_mulfix(axis_w, gf_cos(angle));
		_vy = gf_mulfix(axis_h, gf_sin(angle));
		/*re-invert*/
		gf_mx2d_apply_coords(&mat, &_vx, &_vy);
		gf_path_add_line_to(gp, _vx, _vy);
	}
	return GF_OK;
}
示例#12
0
void visual_2d_pick_node(GF_VisualManager *visual, GF_TraverseState *tr_state, GF_Event *ev, GF_ChildNodeItem *children)
{
	GF_Matrix2D backup;
	visual->bounds_tracker_modif_flag = DRAWABLE_HAS_CHANGED_IN_LAST_TRAVERSE;

	gf_mx2d_copy(backup, tr_state->transform);

	visual_2d_setup_projection(visual, tr_state);

	visual->compositor->hit_node = NULL;
	tr_state->ray.orig.x = INT2FIX(ev->mouse.x);
	tr_state->ray.orig.y = INT2FIX(ev->mouse.y);
	tr_state->ray.orig.z = 0;
	tr_state->ray.dir.x = 0;
	tr_state->ray.dir.y = 0;
	tr_state->ray.dir.z = -FIX_ONE;

	visual->compositor->hit_world_point = tr_state->ray.orig;
	visual->compositor->hit_world_ray = tr_state->ray;
	visual->compositor->hit_square_dist = 0;

	gf_list_reset(visual->compositor->sensors);
	tr_state->traversing_mode = TRAVERSE_PICK;

	/*not the root scene, use children list*/
	if (visual->compositor->visual != visual) {
		while (children) {
			gf_node_traverse(children->node, tr_state);
			children = children->next;
		}
	} else {
		u32 i = 0;
		GF_SceneGraph *sg = visual->compositor->scene;
		GF_Node *root = gf_sg_get_root_node(sg);
		gf_node_traverse(root, tr_state);
		while ((sg = (GF_SceneGraph*)gf_list_enum(visual->compositor->extra_scenes, &i))) {
			gf_sc_traverse_subscene(visual->compositor, root, sg, tr_state);
		}
	}
	gf_mx2d_copy(tr_state->transform, backup);
}
示例#13
0
文件: surface.c 项目: golgol7777/gpac
GF_Err evg_surface_set_matrix(GF_SURFACE _this, GF_Matrix2D *mat)
{
	GF_Matrix2D tmp;
	EVGSurface *surf = (EVGSurface *)_this;
	if (!surf) return GF_BAD_PARAM;
	get_surface_world_matrix(surf, &surf->mat);
	if (!mat) return GF_OK;
	gf_mx2d_init(tmp);
	gf_mx2d_add_matrix(&tmp, mat);
	gf_mx2d_add_matrix(&tmp, &surf->mat);
	gf_mx2d_copy(surf->mat, tmp);
	return GF_OK;
}
示例#14
0
/* 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;
}
示例#15
0
文件: svg_filters.c 项目: Bevara/GPAC
/*
	This is a crude draft implementation of filter. The main drawback is that we don't cache any data.
	We should be able to check for changes in the sub-group or in the filter
*/
void svg_draw_filter(GF_Node *filter, GF_Node *node, GF_TraverseState *tr_state)
{
	GF_IRect rc1, rc2;

#ifndef GPAC_DISABLE_3D
	u32 type_3d;
#endif
	u32 prev_flags;
	GF_IRect txrc;
	Fixed scale_x, scale_y, temp_x, temp_y;
	DrawableContext *ctx, *child_ctx;
	GF_SURFACE offscreen_surface, old_surf;
	GF_Rect bounds, local_bounds, rc;
	GF_Matrix2D backup;
	SVGAllAttributes all_atts;
	GF_FilterStack *st = gf_node_get_private(filter);
	assert(tr_state->traversing_mode==TRAVERSE_SORT);

	/*store the current transform matrix, create a new one for group_cache*/
	gf_mx2d_copy(backup, tr_state->transform);
	gf_mx2d_init(tr_state->transform);

	gf_node_allow_cyclic_traverse(node);
	tr_state->traversing_mode = TRAVERSE_GET_BOUNDS;
	tr_state->bounds.width = tr_state->bounds.height = 0;
	gf_node_traverse(node, tr_state);

	local_bounds = bounds = tr_state->bounds;
	/*compute bounds in final coordinate system - this ensures that the cache has the correct anti aliasing*/
	gf_mx2d_apply_rect(&backup, &bounds);
	txrc = gf_rect_pixelize(&bounds);
	if (txrc.width%2) txrc.width++;
	if (txrc.height%2) txrc.height++;
	bounds = gf_rect_ft(&txrc);

	tr_state->traversing_mode = TRAVERSE_SORT;

	gf_mx2d_copy(tr_state->transform, backup);

	if (!bounds.width || !bounds.height) {
		return;
	}

	/*create a context */
	ctx = drawable_init_context_svg(st->drawable, tr_state);
	if (!ctx) return;

	/*setup texture */
	st->txh.height = txrc.height;
	st->txh.width = txrc.width;

	st->txh.stride = txrc.width * 4;
	st->txh.pixelformat = GF_PIXEL_ARGB;
#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d) st->txh.pixelformat = GF_PIXEL_RGBA;
#endif
	st->txh.transparent = 1;

	if (st->txh.stride * st->txh.height > st->alloc_size) {
		st->alloc_size = st->txh.stride * st->txh.height;
		st->data = (u8*)gf_realloc(st->data, sizeof(u8) * st->alloc_size);
	}
	memset(st->data, 0x0, sizeof(char) * st->txh.stride * st->txh.height);
	st->txh.data = (char *) st->data;
	/*setup geometry (rectangle matching the bounds of the object)
	Warning, we want to center the cached bitmap at the center of the screen (main visual)*/
	gf_path_reset(st->drawable->path);

	gf_path_add_rect_center(st->drawable->path,
	                        bounds.x + bounds.width/2,
	                        bounds.y - bounds.height/2,
	                        bounds.width,
	                        bounds.height);


	old_surf = tr_state->visual->raster_surface;
	offscreen_surface = tr_state->visual->compositor->rasterizer->surface_new(tr_state->visual->compositor->rasterizer, tr_state->visual->center_coords);
	tr_state->visual->raster_surface = offscreen_surface;

	gf_mx2d_copy(backup, tr_state->transform);
	gf_mx2d_init(tr_state->transform);

	/*attach the buffer to visual*/
	tr_state->visual->compositor->rasterizer->surface_attach_to_buffer(offscreen_surface, st->txh.data,
	        st->txh.width,
	        st->txh.height,
	        0,
	        st->txh.stride,
	        st->txh.pixelformat);

	prev_flags = tr_state->immediate_draw;
	tr_state->immediate_draw = 1;
	tr_state->traversing_mode = TRAVERSE_SORT;
	tr_state->in_svg_filter = 1;

	/*recompute the bounds with the final scaling used*/
	scale_x = gf_divfix(bounds.width, local_bounds.width);
	scale_y = gf_divfix(bounds.height, local_bounds.height);
	gf_mx2d_init(tr_state->transform);
	gf_mx2d_add_scale(&tr_state->transform, scale_x, scale_y);

	rc = local_bounds;
	gf_mx2d_apply_rect(&tr_state->transform, &rc);

	/*centered the bitmap on the visual*/
	if (tr_state->visual->center_coords) {
		temp_x = -rc.x - rc.width/2;
		temp_y = rc.height/2 - rc.y;
	} else {
		temp_x = -rc.x;
		temp_y = rc.height - rc.y;
	}
	gf_mx2d_add_translation(&tr_state->transform, temp_x, temp_y);


	rc1 = tr_state->visual->surf_rect;
	rc2 = tr_state->visual->top_clipper;
	tr_state->visual->surf_rect.width = st->txh.width;
	tr_state->visual->surf_rect.height = st->txh.height;
	if (tr_state->visual->center_coords) {
		tr_state->visual->surf_rect.y = st->txh.height/2;
		tr_state->visual->surf_rect.x = -1 * (s32) st->txh.width/2;
	} else {
		tr_state->visual->surf_rect.y = st->txh.height;
		tr_state->visual->surf_rect.x = 0;
	}
	tr_state->visual->top_clipper = tr_state->visual->surf_rect;


#ifndef GPAC_DISABLE_3D
	type_3d = tr_state->visual->type_3d;
	tr_state->visual->type_3d=0;
#endif

	if (prev_flags) gf_node_allow_cyclic_traverse(node);
	gf_node_traverse(node, tr_state);

	child_ctx = ctx->next;
	while (child_ctx && child_ctx->drawable) {
		drawable_reset_bounds(child_ctx->drawable, tr_state->visual);
		child_ctx->drawable = NULL;
		child_ctx = child_ctx->next;
	}
	tr_state->visual->cur_context = ctx;


	/*restore state and destroy whatever needs to be cleaned*/
	tr_state->in_svg_filter = 0;
	tr_state->immediate_draw = prev_flags;
	tr_state->visual->compositor->rasterizer->surface_delete(offscreen_surface);
	tr_state->visual->raster_surface = old_surf;
	tr_state->traversing_mode = TRAVERSE_SORT;
	tr_state->visual->surf_rect = rc1;
	tr_state->visual->top_clipper = rc2;
#ifndef GPAC_DISABLE_3D
	tr_state->visual->type_3d = type_3d ;
#endif

	/*update texture*/
	st->txh.transparent = 1;
	st->txh.flags |= GF_SR_TEXTURE_NO_GL_FLIP;
	gf_sc_texture_set_data(&st->txh);
#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d)
		gf_sc_texture_push_image(&st->txh, 0, 0);
	else
#endif
		gf_sc_texture_push_image(&st->txh, 0, 1);

	ctx->flags |= CTX_NO_ANTIALIAS;
	ctx->aspect.fill_color = 0;
	ctx->aspect.line_color = 0xFF000000;
	ctx->aspect.fill_texture = &st->txh;
	ctx->flags |= CTX_TEXTURE_DIRTY;

	/*get the filter region*/
	bounds = local_bounds;
	gf_svg_flatten_attributes((SVG_Element *)filter, &all_atts);
	if (!all_atts.filterUnits || (*all_atts.filterUnits==SVG_GRADIENTUNITS_OBJECT)) {
		Fixed v;
		v = all_atts.x ? all_atts.x->value : INT2FIX(-10);
		bounds.x += gf_mulfix(v, bounds.width);
		v = all_atts.y ? all_atts.y->value : INT2FIX(-10);
		bounds.y += gf_mulfix(v, bounds.height);
		v = all_atts.width ? all_atts.width->value : INT2FIX(120);
		bounds.width = gf_mulfix(v, bounds.width);
		v = all_atts.height ? all_atts.height->value : INT2FIX(120);
		bounds.height = gf_mulfix(v, bounds.height);
	} else {
		bounds.x = all_atts.x ? all_atts.x->value : 0;
		bounds.y = all_atts.y ? all_atts.y->value : 0;
		bounds.width = all_atts.width ? all_atts.x->value : bounds.width;
		bounds.height = all_atts.x ? all_atts.x->value : 120;
	}
	gf_mx2d_apply_rect(&backup, &bounds);

	svg_filter_apply(filter, &st->txh, &bounds);


#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d) {
		if (!st->drawable->mesh) {
			st->drawable->mesh = new_mesh();
			mesh_from_path(st->drawable->mesh, st->drawable->path);
		}
		visual_3d_draw_from_context(tr_state->ctx, tr_state);
		ctx->drawable = NULL;
		return;
	}
#endif

	/*we computed the texture in final screen coordinate, so use the identity matrix for the context*/
	gf_mx2d_init(tr_state->transform);
	drawable_finalize_sort(ctx, tr_state, NULL);
	gf_mx2d_copy(tr_state->transform, backup);
}
示例#16
0
static void TraverseUntransform(GF_Node *node, void *rs, Bool is_destroy)
{
    UntransformStack *stack = (UntransformStack *)gf_node_get_private(node);
    GF_TraverseState *tr_state = (GF_TraverseState *) rs;

    if (is_destroy) {
        gf_free(stack);
        return;
    }

    if (tr_state->traversing_mode==TRAVERSE_SORT) {
        if (gf_node_dirty_get(node)) {
            Untransform_GetNode(node, &stack->untr); /*lets place it below*/
            gf_node_dirty_clear(node, GF_SG_NODE_DIRTY);
        }
    }

#ifndef GPAC_DISABLE_3D
    if (tr_state->visual->type_3d) {
        GF_Matrix mx_model;
        GF_Camera backup_cam;

        if (!tr_state->camera) return;

        gf_mx_copy(mx_model, tr_state->model_matrix);
        gf_mx_init(tr_state->model_matrix);

        memcpy(&backup_cam, tr_state->camera, sizeof(GF_Camera));


        camera_invalidate(tr_state->camera);
        tr_state->camera->is_3D=0;
        tr_state->camera->flags |= CAM_NO_LOOKAT;
        tr_state->camera->end_zoom = FIX_ONE;
        camera_update(tr_state->camera, NULL, 1);


        if (tr_state->traversing_mode == TRAVERSE_SORT) {
            visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_PROJECTION);
            visual_3d_matrix_load(tr_state->visual, tr_state->camera->projection.m);
            visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_MODELVIEW);
            visual_3d_matrix_load(tr_state->visual, tr_state->camera->modelview.m);

            visual_3d_set_viewport(tr_state->visual, tr_state->camera->vp);

            gf_node_traverse_children((GF_Node *)&stack->untr, tr_state);

            gf_mx_copy(tr_state->model_matrix, mx_model);
            memcpy(tr_state->camera, &backup_cam, sizeof(GF_Camera));

            visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_PROJECTION);
            visual_3d_matrix_load(tr_state->visual, tr_state->camera->projection.m);
            visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_MODELVIEW);
            visual_3d_matrix_load(tr_state->visual, tr_state->camera->modelview.m);

            visual_3d_set_viewport(tr_state->visual, tr_state->camera->vp);
        } else if (tr_state->traversing_mode == TRAVERSE_PICK) {
            Fixed prev_dist = tr_state->visual->compositor->hit_square_dist;
            GF_Ray r = tr_state->ray;
            tr_state->ray.orig.x = INT2FIX(tr_state->pick_x);
            tr_state->ray.orig.y = INT2FIX(tr_state->pick_y);
            tr_state->ray.orig.z = 0;
            tr_state->ray.dir.x = 0;
            tr_state->ray.dir.y = 0;
            tr_state->ray.dir.z = -FIX_ONE;
            tr_state->visual->compositor->hit_square_dist=0;

            gf_node_traverse_children((GF_Node *)&stack->untr, tr_state);

            gf_mx_copy(tr_state->model_matrix, mx_model);
            memcpy(tr_state->camera, &backup_cam, sizeof(GF_Camera));
            tr_state->ray = r;

            /*nothing picked, restore previous pick*/
            if (!tr_state->visual->compositor->hit_square_dist)
                tr_state->visual->compositor->hit_square_dist = prev_dist;

        } else {
            gf_node_traverse_children((GF_Node *)&stack->untr, tr_state);

            gf_mx_copy(tr_state->model_matrix, mx_model);
            memcpy(tr_state->camera, &backup_cam, sizeof(GF_Camera));
        }

    } else
#endif
    {
        GF_Matrix2D mx2d_backup;
        gf_mx2d_copy(mx2d_backup, tr_state->transform);
        gf_mx2d_init(tr_state->transform);

        group_2d_traverse((GF_Node *)&stack->untr, (GroupingNode2D *)stack, tr_state);

        gf_mx2d_copy(tr_state->transform, mx2d_backup);


    }
}
示例#17
0
static void RenderLayer2D(GF_Node *node, void *rs, Bool is_destroy)
{
	u32 i;
	GF_List *prevback, *prevviews;
	GF_Rect clip;
	M_Viewport *vp;
	ChildGroup2D *cg;
	GF_Matrix2D gf_mx2d_bck;
	GroupingNode2D *parent_bck;
	DrawableContext *back_ctx;
	Bool bool_bck;
	DrawableContext *ctx;
	M_Background2D *back;
	M_Layer2D *l = (M_Layer2D *)node;
	Layer2DStack *l2D = (Layer2DStack *) gf_node_get_private(node);
	RenderEffect2D *eff;

	if (is_destroy) {
		DeleteGroupingNode2D((GroupingNode2D *)l2D);
		gf_list_del(l2D->backs);
		gf_list_del(l2D->views);
		free(l2D);
		return;
	}

	eff = (RenderEffect2D *) rs;
	gf_mx2d_copy(gf_mx2d_bck, eff->transform);
	parent_bck = eff->parent;
	eff->parent = (GroupingNode2D *) l2D;
	gf_mx2d_init(eff->transform);
	bool_bck = eff->draw_background;
	prevback = eff->back_stack;
	prevviews = eff->view_stack;
	eff->back_stack = l2D->backs;
	eff->view_stack = l2D->views;

	if (l2D->first) {
		/*render on back first to register with stack*/
		if (l->background) {
			eff->draw_background = 0;
			gf_node_render((GF_Node*) l->background, eff);
			group2d_reset_children((GroupingNode2D*) l2D);
			eff->draw_background = 1;
		}
		vp = (M_Viewport*)l->viewport;
		if (vp) {
			gf_list_add(l2D->views, vp);
			if (!vp->isBound) {
				vp->isBound = 1;
				gf_node_event_out_str((GF_Node*)vp, "isBound");
			}
		}
	}

	back = NULL;
	if (gf_list_count(l2D->backs) ) {
		back = (M_Background2D*)gf_list_get(l2D->backs, 0);
		if (!back->isBound) back = NULL;
	}
	vp = NULL;
	if (gf_list_count(l2D->views)) {
		vp = (M_Viewport*)gf_list_get(l2D->views, 0);
		if (!vp->isBound) vp = NULL;
	}
	if (!eff->is_pixel_metrics) gf_mx2d_add_scale(&eff->transform, eff->min_hsize, eff->min_hsize);
	l2D->clip = R2D_ClipperToPixelMetrics(eff, l->size);

	/*apply viewport*/
	if (vp) {
		clip = l2D->clip;
		vp_setup((GF_Node *) vp, eff, &clip);
	}


	back_ctx = NULL;
	if (back) {
		/*setup back size and render*/
		group2d_start_child((GroupingNode2D *)l2D);
		
		eff->draw_background = 1;
		ctx = b2D_GetContext(back, l2D->backs);
		ctx->bi->unclip = l2D->clip;
		ctx->bi->clip = gf_rect_pixelize(&ctx->bi->unclip);
		gf_mx2d_init(ctx->transform);
		gf_node_render((GF_Node *) back, eff);
		eff->draw_background = 0;
	
		/*we need a trick since we're not using a dedicated surface for layer rendering, 
		we emulate the back context: remove previous context and insert fake one*/
		if (!(eff->trav_flags & TF_RENDER_DIRECT) && (gf_list_count(l2D->groups)==1)) {
			ChildGroup2D *cg = (ChildGroup2D *)gf_list_get(l2D->groups, 0);
			back_ctx = VS2D_GetDrawableContext(eff->surface);
			gf_list_rem(cg->contexts, 0);
			gf_list_add(cg->contexts, back_ctx);
			back_ctx->h_texture = ctx->h_texture;
			back_ctx->flags = ctx->flags;
			back_ctx->flags &= ~CTX_IS_TRANSPARENT;
			back_ctx->flags |= CTX_IS_BACKGROUND;
			back_ctx->aspect = ctx->aspect;
			back_ctx->drawable = ctx->drawable;
			drawable_check_bounds(back_ctx, eff->surface);
			back_ctx->bi->clip = ctx->bi->clip;
			back_ctx->bi->unclip = ctx->bi->unclip;
		}
		group2d_end_child((GroupingNode2D *)l2D);
	}

	group2d_traverse((GroupingNode2D *)l2D, l->children, eff);
	/*restore effect*/
	eff->draw_background = bool_bck;
	gf_mx2d_copy(eff->transform, gf_mx2d_bck);
	eff->parent = parent_bck;
	eff->back_stack = prevback;
	eff->view_stack = prevviews;

	/*check bindables*/
	if (l2D->first) {
		Bool redraw = 0;
		l2D->first = 0;
		if (!back && gf_list_count(l2D->backs)) redraw = 1;
		if (!vp && gf_list_count(l2D->views) ) redraw = 1;

		/*we missed background or viewport (was not declared as bound during traversal, and is bound now)*/
		if (redraw) {
			group2d_reset_children((GroupingNode2D*)l2D);
			gf_sr_invalidate(l2D->compositor, NULL);
			return;
		}
	}

	i=0;
	while ((cg = (ChildGroup2D *)gf_list_enum(l2D->groups, &i))) {
		child2d_render_done(cg, eff, &l2D->clip);
	}
	group2d_reset_children((GroupingNode2D*)l2D);

	group2d_force_bounds(eff->parent, &l2D->clip);
}
示例#18
0
static void RenderPathLayout(GF_Node *node, void *rs, Bool is_destroy)
{
	u32 i, count, minor, major, int_bck;
	Fixed length, offset, length_after_point;
	Bool res;
	ChildGroup2D *cg;
	GF_Matrix2D mat;
	GroupingNode2D *parent_bck;
	PathLayoutStack *gr = (PathLayoutStack *) gf_node_get_private(node);
	M_PathLayout *pl = (M_PathLayout *)node;
	RenderEffect2D *eff = (RenderEffect2D *) rs;
	
	if (is_destroy) {
		DeleteGroupingNode2D((GroupingNode2D *)gr);
		if (gr->iter) gf_path_iterator_del(gr->iter);
		free(gr);
		return;
	}
	if (!pl->geometry) return;
	
	/*only low-level primitives allowed*/
	switch (gf_node_get_tag((GF_Node *) pl->geometry)) {
	case TAG_MPEG4_Rectangle: return;
	case TAG_MPEG4_Circle: return;
	case TAG_MPEG4_Ellipse: return;
	}

	/*store effect*/
	gf_mx2d_copy(mat, eff->transform);
	parent_bck = eff->parent;

	gf_mx2d_init(eff->transform);
	eff->parent = NULL;

	/*check geom changes*/
	if ((pl->geometry != gr->last_geom) || gf_node_dirty_get(pl->geometry)) {
		if (gr->iter) gf_path_iterator_del(gr->iter);
		gr->iter = NULL;

		int_bck = eff->trav_flags;
		eff->trav_flags |= GF_SR_TRAV_SWITCHED_OFF;
		gf_node_render(pl->geometry, eff);
		eff->trav_flags = int_bck;

		gr->last_geom = pl->geometry;
	}

	if (!gr->iter) {
		/*get the drawable*/
		Drawable *dr = (Drawable *) gf_node_get_private( (GF_Node *) pl->geometry);
		/*init iteration*/
		if (!dr || !dr->path) return;
		gr->iter = gf_path_iterator_new(dr->path);
		if (!gr->iter) return;
	}
	
	eff->parent = (GroupingNode2D*)gr;
	int_bck = eff->text_split_mode;
	eff->text_split_mode = 2;
	group2d_traverse((GroupingNode2D*)gr, pl->children, eff);
	eff->text_split_mode = int_bck;

	/*restore effect*/
	gf_mx2d_copy(eff->transform, mat);
	eff->parent = parent_bck;

	count = gf_list_count(gr->groups);
	
	length = gf_path_iterator_get_length(gr->iter);
	offset = gf_mulfix(length, pl->pathOffset);

	major = pl->alignment.count ? pl->alignment.vals[0] : 0;
	minor = (pl->alignment.count==2) ? pl->alignment.vals[1] : 0;

	if (pl->wrapMode==1) {
		while (offset<0) offset += length;
	}

	for (i=0; i<count; i++) {
		cg = (ChildGroup2D *)gf_list_get(gr->groups, i);
		if (cg->original.width>length) break;

		/*first set our center and baseline*/
		gf_mx2d_init(mat);

		/*major align*/
		switch (major) {
		case 2:
			if (cg->is_text_group) gf_mx2d_add_translation(&mat, -1*cg->original.x - cg->original.width, 0);
			else gf_mx2d_add_translation(&mat, -1 * cg->original.width/2, 0);
			length_after_point = 0;
			break;
		case 1:
			length_after_point = cg->original.width/2;
			if (cg->is_text_group) gf_mx2d_add_translation(&mat, -1*cg->original.x - cg->original.width / 2, 0);
			break;
		default:
		case 0:
			if (cg->is_text_group) gf_mx2d_add_translation(&mat, cg->original.x, 0);
			else gf_mx2d_add_translation(&mat, cg->original.width/2, 0);
			length_after_point = cg->original.width;
			break;
		}

		/*if wrapping and out of path, restart*/
		if ((pl->wrapMode==1) && (offset+length_after_point>=length)) {
			offset += length_after_point;
			offset -= length;
			i--;
			continue;
		}
		/*if not wrapping and not yet in path skip */
		if (!pl->wrapMode && (offset+length_after_point < 0)) {
			child2d_render_done_complex(cg, (RenderEffect2D *)rs, NULL);
			goto next;
		}

		/*minor justify*/
		switch (minor) {
		/*top alignment*/
		case 3:
			if (cg->is_text_group) 
				gf_mx2d_add_translation(&mat, 0, -1 * cg->ascent);
			else 
				gf_mx2d_add_translation(&mat, 0, -1 * cg->original.height / 2);
			
			break;
		/*baseline*/
		case 1:
			/*move to bottom align if not text*/
			if (!cg->is_text_group) 
				gf_mx2d_add_translation(&mat, 0, cg->original.height / 2);
			break;
		/*middle*/
		case 2:
			/*if text use (asc+desc) /2 as line height since glyph height differ*/
			if (cg->is_text_group) 
				gf_mx2d_add_translation(&mat, 0, cg->descent - (cg->ascent + cg->descent) / 2);
			break;
		/*bottomline alignment*/
		case 0:
		default:
			if (cg->is_text_group)
				gf_mx2d_add_translation(&mat, 0, cg->descent);
			else
				gf_mx2d_add_translation(&mat, 0, cg->original.height / 2);
			
			break;
		}
		res = gf_path_iterator_get_transform(gr->iter, offset, (Bool) (pl->wrapMode==2), &mat, 1, length_after_point);
		if (!res) break;

		child2d_render_done_complex(cg, (RenderEffect2D *)rs, &mat);

next:
		if (i+1<count) {
			ChildGroup2D *cg_next = (ChildGroup2D *)gf_list_get(gr->groups, i+1);

			/*update offset according to major alignment */
			switch (major) {
			case 2:
				if (cg_next->is_text_group) offset += gf_mulfix(pl->spacing, cg_next->original.x);
				offset += gf_mulfix(pl->spacing, cg_next->original.width);
				break;
			case 1:
				if (cg->is_text_group) offset += gf_mulfix(pl->spacing, cg->original.x / 2);
				offset += gf_mulfix(pl->spacing, cg->original.width / 2);
				offset += cg_next->original.width / 2;
				break;
			default:
			case 0:
				if (cg->is_text_group) offset += gf_mulfix(pl->spacing, cg->original.x);
				offset += gf_mulfix(pl->spacing, cg->original.width);
				break;
			}
		}
		/*wrap*/
		if ((pl->wrapMode==1) && (offset>=length)) offset-=length;
	}

	/*undrawn nodes*/
	for (;i<count; i++) {
		cg = (ChildGroup2D *)gf_list_get(gr->groups, i);
		child2d_render_done_complex(cg, (RenderEffect2D *)rs, NULL);
	}
	group2d_reset_children((GroupingNode2D *) gr);
}
示例#19
0
static void svg_traverse_bitmap(GF_Node *node, void *rs, Bool is_destroy)
{
	Fixed cx, cy, angle;
	/*video stack is just an extension of image stack, type-casting is OK*/
	SVG_video_stack *stack = (SVG_video_stack*)gf_node_get_private(node);
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;
	SVGPropertiesPointers backup_props;
	u32 backup_flags;
	GF_Matrix2D backup_matrix;
	GF_Matrix mx_3d;
	DrawableContext *ctx;
	SVGAllAttributes all_atts;


	if (is_destroy) {
		gf_sc_texture_destroy(&stack->txh);
		gf_sg_mfurl_del(stack->txurl);

		drawable_del(stack->graph);
		if (stack->audio) {
			gf_node_unregister(stack->audio, NULL);
		}
		gf_free(stack);
		return;
	} 


	/*TRAVERSE_DRAW is NEVER called in 3D mode*/
	if (tr_state->traversing_mode==TRAVERSE_DRAW_2D) {
		SVG_Draw_bitmap(tr_state);
		return;
	}
	else if (tr_state->traversing_mode==TRAVERSE_PICK) {
		svg_drawable_pick(node, stack->graph, tr_state);
		return;
	}

	/*flatten attributes and apply animations + inheritance*/
	gf_svg_flatten_attributes((SVG_Element *)node, &all_atts);
	if (!compositor_svg_traverse_base(node, &all_atts, (GF_TraverseState *)rs, &backup_props, &backup_flags))
		return;

	if (gf_node_dirty_get(node) & GF_SG_SVG_XLINK_HREF_DIRTY) {
		gf_term_get_mfurl_from_xlink(node, &stack->txurl);
		stack->txh.width = stack->txh.height = 0;
		
		/*remove associated audio if any*/
		if (stack->audio) {
			svg_audio_smil_evaluate_ex(NULL, 0, SMIL_TIMING_EVAL_REMOVE, stack->audio, stack->txh.owner);
			gf_node_unregister(stack->audio, NULL);
			stack->audio = NULL;
		}
		stack->audio_dirty = GF_TRUE;
		
		if (stack->txurl.count) svg_play_texture(stack, &all_atts);
		gf_node_dirty_clear(node, GF_SG_SVG_XLINK_HREF_DIRTY);
	}

	if (gf_node_dirty_get(node)) {
		/*do not clear dirty state until the image is loaded*/
		if (stack->txh.width) {
			gf_node_dirty_clear(node, 0);
			SVG_Build_Bitmap_Graph((SVG_video_stack*)gf_node_get_private(node), tr_state);
		}
		
	} 

	if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) {
		if (!compositor_svg_is_display_off(tr_state->svg_props)) {
			gf_path_get_bounds(stack->graph->path, &tr_state->bounds);
			compositor_svg_apply_local_transformation(tr_state, &all_atts, &backup_matrix, &mx_3d);

			if (svg_video_get_transform_behavior(tr_state, &all_atts, &cx, &cy, &angle)) {
				GF_Matrix2D mx;
				tr_state->bounds.width = INT2FIX(stack->txh.width);
				tr_state->bounds.height = INT2FIX(stack->txh.height);
				tr_state->bounds.x = cx - tr_state->bounds.width/2;
				tr_state->bounds.y = cy + tr_state->bounds.height/2;
				gf_mx2d_init(mx);
				gf_mx2d_add_rotation(&mx, 0, 0, angle);
				gf_mx2d_apply_rect(&mx, &tr_state->bounds);
			} else {
				gf_mx2d_apply_rect(&tr_state->transform, &tr_state->bounds);
			}

			compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx_3d);
		}
	} else if (tr_state->traversing_mode == TRAVERSE_SORT) {
		if (!compositor_svg_is_display_off(tr_state->svg_props) && ( *(tr_state->svg_props->visibility) != SVG_VISIBILITY_HIDDEN) ) {
			GF_Matrix mx_bck;
			Bool restore_mx = GF_FALSE;

			compositor_svg_apply_local_transformation(tr_state, &all_atts, &backup_matrix, &mx_3d);

			ctx = drawable_init_context_svg(stack->graph, tr_state);
			if (!ctx || !ctx->aspect.fill_texture ) return;

			if (svg_video_get_transform_behavior(tr_state, &all_atts, &cx, &cy, &angle)) {
				drawable_reset_path(stack->graph);
				gf_path_add_rect_center(stack->graph->path, cx, cy, INT2FIX(stack->txh.width), INT2FIX(stack->txh.height));

				gf_mx2d_copy(mx_bck, tr_state->transform);
				restore_mx = GF_TRUE;
				
				gf_mx2d_init(tr_state->transform);
				gf_mx2d_add_rotation(&tr_state->transform, cx, cy, angle);
			}

			/*even if set this is not true*/
			ctx->aspect.pen_props.width = 0;
			ctx->flags |= CTX_NO_ANTIALIAS;

			/*if rotation, transparent*/
			ctx->flags &= ~CTX_IS_TRANSPARENT;
			if (ctx->transform.m[1] || ctx->transform.m[3]) {
				ctx->flags |= CTX_IS_TRANSPARENT;
				ctx->flags &= ~CTX_NO_ANTIALIAS;
			}
			else if (ctx->aspect.fill_texture->transparent) 
				ctx->flags |= CTX_IS_TRANSPARENT;
			else if (tr_state->svg_props->opacity && (tr_state->svg_props->opacity->type==SVG_NUMBER_VALUE) && (tr_state->svg_props->opacity->value!=FIX_ONE)) {
				ctx->flags = CTX_IS_TRANSPARENT;
				ctx->aspect.fill_color = GF_COL_ARGB(FIX2INT(0xFF * tr_state->svg_props->opacity->value), 0, 0, 0);
			}

#ifndef GPAC_DISABLE_3D
			if (tr_state->visual->type_3d) {
				if (!stack->graph->mesh) {
					stack->graph->mesh = new_mesh();
					mesh_from_path(stack->graph->mesh, stack->graph->path);
				}
				compositor_3d_draw_bitmap(stack->graph, &ctx->aspect, tr_state, 0, 0, FIX_ONE, FIX_ONE);
				ctx->drawable = NULL;
			} else 
#endif
			{
				drawable_finalize_sort(ctx, tr_state, NULL);
			}

			if (restore_mx) gf_mx2d_copy(tr_state->transform, mx_bck);
			compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx_3d);
		}
	}
	if (stack->audio) svg_traverse_audio_ex(stack->audio, rs, GF_FALSE, tr_state->svg_props);

	memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
	tr_state->svg_flags = backup_flags;
}
示例#20
0
文件: surface.c 项目: golgol7777/gpac
GF_Err evg_surface_fill(GF_SURFACE _this, GF_STENCIL stencil)
{
	GF_Rect rc;
	GF_Matrix2D mat, st_mat;
	Bool restore_filter;
	EVGSurface *surf = (EVGSurface *)_this;
	EVGStencil *sten = (EVGStencil *)stencil;
	if (!surf || !stencil) return GF_BAD_PARAM;
	if (!surf->ftoutline.n_points) return GF_OK;
	surf->sten = sten;

	/*setup ft raster calllbacks*/
	if (!setup_grey_callback(surf)) return GF_OK;

/*	surf->ftparams.gray_spans = gray_spans_stub; */

	get_surface_world_matrix(surf, &mat);

	restore_filter = 0;
	/*get path frame for texture convertion */
	if (sten->type != GF_STENCIL_SOLID) {
		rc = surf->path_bounds;
		gf_mx2d_apply_rect(&mat, &rc);
		rc.x = rc.y = 0;
		/*assign target frame and matrix*/
		sten->frame = rc;
		gf_mx2d_copy(sten->pmat, surf->mat);
		gf_mx2d_inverse(&sten->pmat);

		gf_mx2d_copy(st_mat, sten->smat);
		gf_mx2d_init(sten->smat);
		switch (sten->type) {
		case GF_STENCIL_TEXTURE:
			if (! ((EVG_Texture *)sten)->pixels) return GF_BAD_PARAM;

			if (((EVG_Texture *)sten)->mod & GF_TEXTURE_FLIP) {
				if (!surf->center_coords) gf_mx2d_add_scale(&sten->smat, FIX_ONE, -FIX_ONE);
			} else {
				if (surf->center_coords) gf_mx2d_add_scale(&sten->smat, FIX_ONE, -FIX_ONE);
			}
			evg_set_texture_active(sten);
			gf_mx2d_add_matrix(&sten->smat, &st_mat);
			gf_mx2d_add_matrix(&sten->smat, &mat);
			gf_mx2d_inverse(&sten->smat);
			evg_bmp_init(sten);
			if (((EVG_Texture *)sten)->filter == GF_TEXTURE_FILTER_DEFAULT) {
				restore_filter = 1;
				((EVG_Texture *)sten)->filter = surf->texture_filter;
			}

			break;
		case GF_STENCIL_LINEAR_GRADIENT:
		{
			EVG_LinearGradient *lin = (EVG_LinearGradient *)sten;
			gf_mx2d_add_matrix(&sten->smat, &st_mat);
			gf_mx2d_add_matrix(&sten->smat, &mat);
			gf_mx2d_inverse(&sten->smat);
			/*and finalize matrix in gradient coord system*/
			gf_mx2d_add_matrix(&sten->smat, &lin->vecmat);
			gf_mx2d_add_scale(&sten->smat, INT2FIX(1<<EVGGRADIENTBITS), INT2FIX(1<<EVGGRADIENTBITS));

		}
			break;
		case GF_STENCIL_RADIAL_GRADIENT:
		{
			EVG_RadialGradient *rad = (EVG_RadialGradient*)sten;
			gf_mx2d_copy(sten->smat, st_mat);
			gf_mx2d_add_matrix(&sten->smat, &mat);
			gf_mx2d_inverse(&sten->smat);
			gf_mx2d_add_translation(&sten->smat, -rad->center.x, -rad->center.y);
			gf_mx2d_add_scale(&sten->smat, gf_invfix(rad->radius.x), gf_invfix(rad->radius.y));

			rad->d_f.x = gf_divfix(rad->focus.x - rad->center.x, rad->radius.x);
			rad->d_f.y = gf_divfix(rad->focus.y - rad->center.y, rad->radius.y);
			/*init*/
			evg_radial_init(rad);
		}
			break;
		}
	}

	if (surf->useClipper) {
		surf->ftparams.clip_xMin = surf->clipper.x;
		surf->ftparams.clip_yMin = surf->clipper.y;
		surf->ftparams.clip_xMax = (surf->clipper.x + surf->clipper.width);
		surf->ftparams.clip_yMax = (surf->clipper.y + surf->clipper.height);
	} else {
		surf->ftparams.clip_xMin = 0;
		surf->ftparams.clip_yMin = 0;
		surf->ftparams.clip_xMax = (surf->width);
		surf->ftparams.clip_yMax = (surf->height);
	}

	/*and call the raster*/
	evg_raster_render(surf->raster, &surf->ftparams);

	/*restore stencil matrix*/
	if (sten->type != GF_STENCIL_SOLID) {
		gf_mx2d_copy(sten->smat, st_mat);
		if (restore_filter) ((EVG_Texture *)sten)->filter = GF_TEXTURE_FILTER_DEFAULT;
	}
	surf->sten = 0L;
	return GF_OK;
}
示例#21
0
void svg_drawable_pick(GF_Node *node, Drawable *drawable, GF_TraverseState *tr_state)
{
	DrawAspect2D asp;
	GF_Matrix2D inv_2d;
	Fixed x, y;
	Bool picked = 0;
	GF_Compositor *compositor = tr_state->visual->compositor;
	SVGPropertiesPointers backup_props;
	GF_Matrix2D backup_matrix;
	GF_Matrix mx_3d;
	SVGAllAttributes all_atts;

	if (!drawable->path) return;

	gf_svg_flatten_attributes((SVG_Element *)node, &all_atts);

	memcpy(&backup_props, tr_state->svg_props, sizeof(SVGPropertiesPointers));
	gf_svg_apply_inheritance(&all_atts, tr_state->svg_props);
	if (compositor_svg_is_display_off(tr_state->svg_props)) return;

	compositor_svg_apply_local_transformation(tr_state, &all_atts, &backup_matrix, &mx_3d);

	memset(&asp, 0, sizeof(DrawAspect2D));
	drawable_get_aspect_2d_svg(node, &asp, tr_state);

#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d) {
		svg_drawable_3d_pick(drawable, tr_state, &asp);
		compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx_3d);
		memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
		return;
	} 
#endif
	gf_mx2d_copy(inv_2d, tr_state->transform);
	gf_mx2d_inverse(&inv_2d);
	x = tr_state->ray.orig.x;
	y = tr_state->ray.orig.y;
	gf_mx2d_apply_coords(&inv_2d, &x, &y);

	picked = svg_drawable_is_over(drawable, x, y, &asp, tr_state, NULL);

	if (picked) {
		u32 count, i;
		compositor->hit_local_point.x = x;
		compositor->hit_local_point.y = y;
		compositor->hit_local_point.z = 0;

		gf_mx_from_mx2d(&compositor->hit_world_to_local, &tr_state->transform);
		gf_mx_from_mx2d(&compositor->hit_local_to_world, &inv_2d);

		compositor->hit_node = drawable->node;
		compositor->hit_use_dom_events = 1;
		compositor->hit_normal.x = compositor->hit_normal.y = 0; compositor->hit_normal.z = FIX_ONE;
		compositor->hit_texcoords.x = gf_divfix(x, drawable->path->bbox.width) + FIX_ONE/2;
		compositor->hit_texcoords.y = gf_divfix(y, drawable->path->bbox.height) + FIX_ONE/2;
		svg_clone_use_stack(compositor, tr_state);
		/*not use in SVG patterns*/
		compositor->hit_appear = NULL;

		/*also stack any VRML sensors present at the current level. If the event is not catched
		by a listener in the SVG tree, the event will be forwarded to the VRML tree*/
		gf_list_reset(tr_state->visual->compositor->sensors);
		count = gf_list_count(tr_state->vrml_sensors);
		for (i=0; i<count; i++) {
			gf_list_add(tr_state->visual->compositor->sensors, gf_list_get(tr_state->vrml_sensors, i));
		}

		GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[SVG Picking] node %s is under mouse - hit %g %g 0\n", gf_node_get_log_name(drawable->node), FIX2FLT(x), FIX2FLT(y)));
	}

	compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx_3d);
	memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
}
示例#22
0
void gf_svg_sani_restore_parent_transformation(RenderEffect2D *eff, GF_Matrix2D *backup_matrix)
{
	gf_mx2d_copy(eff->transform, *backup_matrix);  
}
示例#23
0
static void TraverseLayer3D(GF_Node *node, void *rs, Bool is_destroy)
{
	Bool prev_layer, changed = 0;
	GF_List *oldb, *oldv, *oldf, *oldn;
	GF_Rect rc;
	u32 cur_lights;
	GF_List *node_list_backup;
	GF_BBox bbox_backup;
	GF_Matrix model_backup;
	GF_Matrix2D mx2d_backup;
	GF_Camera *prev_cam;
	GF_VisualManager *old_visual;
	M_Layer3D *l = (M_Layer3D *)node;
	Layer3DStack *st = (Layer3DStack *) gf_node_get_private(node);
	GF_TraverseState *tr_state = (GF_TraverseState *) rs;
	
	if (is_destroy) {
		DestroyLayer3D(node);
		return;
	}
	if (st->unsupported) return;

	if (gf_node_dirty_get(node)) {

		/*main visual in pixel metrics, use output width*/
		if (tr_state->pixel_metrics && (tr_state->visual->compositor->visual==tr_state->visual)) {
			st->clip.width = INT2FIX(tr_state->visual->compositor->vp_width);
			st->clip.height = INT2FIX(tr_state->visual->compositor->vp_height);
		} else {
			visual_get_size_info(tr_state, &st->clip.width, &st->clip.height);
		}
		/*setup bounds in local coord system*/
		if (l->size.x>=0) st->clip.width = l->size.x;
		if (l->size.y>=0) st->clip.height = l->size.y;
		st->clip = gf_rect_center(st->clip.width, st->clip.height);

		changed = 1;
	}

	switch (tr_state->traversing_mode) {
	case TRAVERSE_GET_BOUNDS:
		if (!tr_state->for_node) {
			tr_state->bounds = st->clip;
			gf_bbox_from_rect(&tr_state->bbox, &st->clip);
			return;
		}
	case TRAVERSE_PICK:
	case TRAVERSE_SORT:
		/*layers can only be used in a 2D context*/
		if (tr_state->camera && tr_state->camera->is_3D) return;
		break;
	case TRAVERSE_DRAW_2D:
		layer3d_draw_2d(node, tr_state);
		return;
	case TRAVERSE_DRAW_3D:
	default:
		return;
	}

	/*layer3D maintains its own stacks*/
	oldb = tr_state->backgrounds;
	oldv = tr_state->viewpoints;
	oldf = tr_state->fogs;
	oldn = tr_state->navigations;
	tr_state->backgrounds = st->visual->back_stack;
	tr_state->viewpoints = st->visual->view_stack;
	tr_state->navigations = st->visual->navigation_stack;
	tr_state->fogs = st->visual->fog_stack;
	prev_layer = tr_state->is_layer;
	tr_state->is_layer = 1;

	prev_cam = tr_state->camera;
	tr_state->camera = &st->visual->camera;
	old_visual = tr_state->visual;

	bbox_backup = tr_state->bbox;
	gf_mx_copy(model_backup, tr_state->model_matrix);
	gf_mx2d_copy(mx2d_backup, tr_state->transform);


	/*compute viewport in visual coordinate*/
	rc = st->clip;
	if (prev_cam) {
		gf_mx_apply_rect(&tr_state->model_matrix, &rc);

		gf_mx_apply_rect(&prev_cam->modelview, &rc);
		if (tr_state->camera->flags & CAM_HAS_VIEWPORT)
			gf_mx_apply_rect(&prev_cam->viewport, &rc);
#if 0
		if (tr_state->visual->compositor->visual==tr_state->visual) {
			GF_Matrix mx;
			gf_mx_init(mx);
			gf_mx_add_scale(&mx, tr_state->visual->compositor->scale_x, tr_state->visual->compositor->scale_y, FIX_ONE);
			gf_mx_apply_rect(&mx, &rc);
		}
#endif
	} else {
		gf_mx2d_apply_rect(&tr_state->transform, &rc);

/*		if (tr_state->visual->compositor->visual==tr_state->visual) {
			gf_mx2d_init(mx2d_backup);
			gf_mx2d_add_scale(&mx2d_backup, tr_state->visual->compositor->scale_x, tr_state->visual->compositor->scale_y);
			gf_mx2d_apply_rect(&mx2d_backup, &rc);
		}
*/
		/*switch visual*/
		tr_state->visual = st->visual;
	}


	/*check bindables*/
	gf_mx_init(tr_state->model_matrix);
	l3d_CheckBindables(node, tr_state, st->first);
	if (prev_cam) gf_mx_copy(tr_state->model_matrix, model_backup);


	/*drawing a layer means drawing all subelements as a whole (no depth sorting with parents)*/
	if (tr_state->traversing_mode==TRAVERSE_SORT) {

		if (gf_node_dirty_get(node)) changed = 1;
		gf_node_dirty_clear(node, GF_SG_NODE_DIRTY|GF_SG_VRML_BINDABLE_DIRTY);

		/*!! we were in a 2D mode, setup associated texture !!*/
		if (!prev_cam) {
			switch (layer3d_setup_offscreen(node, st, tr_state, rc.width, rc.height)) {
			case 0:
				goto l3d_exit;
			case 2:
				if (!changed && !(st->visual->camera.flags & CAM_IS_DIRTY) && !st->visual->camera.anim_len) {
					GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Layer3D] No changes found , skipping 3D draw\n"));
					goto layer3d_unchanged_2d;
				}
			default:
				break;
			}
#ifdef GPAC_USE_TINYGL
			if (st->tgl_ctx) ostgl_make_current(st->tgl_ctx, 0);
#endif

			/*note that we don't backup the state as a layer3D cannot be declared in a layer3D*/
			tr_state->layer3d = node;

			rc = st->vp;
			/*setup GL*/
			visual_3d_setup(tr_state->visual);

			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_PROJECTION);
			visual_3d_matrix_reset(tr_state->visual);
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_TEXTURE);
			visual_3d_matrix_reset(tr_state->visual);
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_MODELVIEW);
			visual_3d_matrix_reset(tr_state->visual);
		} else {
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_PROJECTION);
			visual_3d_matrix_push(tr_state->visual);
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_TEXTURE);
			visual_3d_matrix_push(tr_state->visual);
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_MODELVIEW);
			visual_3d_matrix_push(tr_state->visual);
		}
		GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Layer3D] Redrawing\n"));

		layer3d_setup_clip(st, tr_state, prev_cam ? 1 : 0, rc);

		cur_lights = tr_state->visual->num_lights;
		/*this will init projection. Note that we're binding the viewpoint in the current pixelMetrics context
		even if the viewpoint was declared in an inline below
		if no previous camera, we're using offscreen rendering, force clear */
		visual_3d_init_draw(tr_state, prev_cam ? 1 : 2);

		visual_3d_check_collisions(tr_state, l->children);
		tr_state->traversing_mode = TRAVERSE_SORT;

		/*shortcut node list*/
		node_list_backup = tr_state->visual->alpha_nodes_to_draw;
		tr_state->visual->alpha_nodes_to_draw = gf_list_new();

		/*reset cull flag*/
		tr_state->cull_flag = 0;
		group_3d_traverse(node, (GroupingNode *)st, tr_state);

		visual_3d_flush_contexts(tr_state->visual, tr_state);

		gf_list_del(tr_state->visual->alpha_nodes_to_draw);
		tr_state->visual->alpha_nodes_to_draw = node_list_backup;

		while (cur_lights < tr_state->visual->num_lights) {
			visual_3d_remove_last_light(tr_state->visual);
		}

		tr_state->traversing_mode = TRAVERSE_SORT;

		if (prev_cam) {
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_PROJECTION);
			visual_3d_matrix_pop(tr_state->visual);
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_TEXTURE);
			visual_3d_matrix_pop(tr_state->visual);
			visual_3d_set_matrix_mode(tr_state->visual, V3D_MATRIX_MODELVIEW);
			visual_3d_matrix_pop(tr_state->visual);
		}


		/*!! we were in a 2D mode, create drawable context!!*/
		if (!prev_cam) {
			DrawableContext *ctx;
			
			/*with TinyGL we draw directly to the offscreen buffer*/
#ifndef GPAC_USE_TINYGL
			gf_sc_copy_to_stencil(&st->txh);
#else
			if (st->txh.pixelformat==GF_PIXEL_RGBDS) 
				gf_get_tinygl_depth(&st->txh); 
#endif

			if (tr_state->visual->compositor->rasterizer->stencil_texture_modified) 
				tr_state->visual->compositor->rasterizer->stencil_texture_modified(gf_sc_texture_get_stencil(&st->txh) ); 
			gf_sc_texture_set_stencil(&st->txh, gf_sc_texture_get_stencil(&st->txh) );
			changed = 1;

layer3d_unchanged_2d:

			/*restore visual*/
			tr_state->visual = old_visual;
			tr_state->layer3d = NULL;
			tr_state->appear = NULL;
		//	tr_state->camera = prev_cam;

			ctx = drawable_init_context_mpeg4(st->drawable, tr_state);
			if (!ctx) return;
			ctx->aspect.fill_texture = &st->txh;
			ctx->flags |= CTX_NO_ANTIALIAS;
			if (changed) ctx->flags |= CTX_APP_DIRTY;
			if (st->txh.transparent) ctx->flags |= CTX_IS_TRANSPARENT;
			drawable_finalize_sort(ctx, tr_state, NULL);
		}
	}
	/*check picking - we must fall in our 2D clipper except when mvt is grabbed on layer*/
	else if (!gf_node_dirty_get(node)  && (tr_state->traversing_mode==TRAVERSE_PICK)) {
		GF_Ray prev_r;
		SFVec3f start, end;
		SFVec4f res;
		Fixed in_x, in_y;
		Bool do_pick = 0;

		if (!prev_cam) rc = st->vp;

		layer3d_setup_clip(st, tr_state, prev_cam ? 1 : 0, rc);

		if (tr_state->visual->compositor->active_layer==node) {
			do_pick = (tr_state->visual->compositor->grabbed_sensor || tr_state->visual->compositor->navigation_state) ? 1 : 0;
		}

		if (!prev_cam) gf_mx_from_mx2d(&tr_state->model_matrix, &tr_state->transform);
		
		if (!do_pick && !gf_list_count(tr_state->visual->compositor->sensors)) 
			do_pick = gf_sc_pick_in_clipper(tr_state, &st->clip);

		if (!do_pick) goto l3d_exit;

		prev_r = tr_state->ray;

		compositor_get_2d_plane_intersection(&tr_state->ray, &start);

		gf_mx_inverse(&tr_state->model_matrix);
		gf_mx_apply_vec(&tr_state->model_matrix, &start);


		if (tr_state->visual->compositor->visual==tr_state->visual) {
			start.x = gf_mulfix(start.x, tr_state->visual->compositor->scale_x);
			start.y = gf_mulfix(start.y, tr_state->visual->compositor->scale_y);
		} else if (!prev_cam) {
			start.x = gf_muldiv(start.x, st->visual->camera.width, st->clip.width);
			start.y = gf_muldiv(start.y, st->visual->camera.height, st->clip.height);
		}

		visual_3d_setup_projection(tr_state, 1);
		in_x = 2 * gf_divfix(start.x, st->visual->camera.width);
		in_y = 2 * gf_divfix(start.y, st->visual->camera.height);
					
		res.x = in_x; res.y = in_y; res.z = -FIX_ONE; res.q = FIX_ONE;
		gf_mx_apply_vec_4x4(&st->visual->camera.unprojection, &res);
		if (!res.q) goto l3d_exit;
		start.x = gf_divfix(res.x, res.q);
		start.y = gf_divfix(res.y, res.q);
		start.z = gf_divfix(res.z, res.q);

		res.x = in_x; res.y = in_y; res.z = FIX_ONE; res.q = FIX_ONE;
		gf_mx_apply_vec_4x4(&st->visual->camera.unprojection, &res);
		if (!res.q) goto l3d_exit;
		end.x = gf_divfix(res.x, res.q);
		end.y = gf_divfix(res.y, res.q);
		end.z = gf_divfix(res.z, res.q);
		tr_state->ray = gf_ray(start, end);

		GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Layer3D] Picking: cast ray\n\tOrigin %.4f %.4f %.4f - End %.4f %.4f %.4f\n\tDir %.4f %.4f %.4f\n", 
			FIX2FLT(tr_state->ray.orig.x), FIX2FLT(tr_state->ray.orig.y), FIX2FLT(tr_state->ray.orig.z),
			FIX2FLT(end.x), FIX2FLT(end.y), FIX2FLT(end.z),
			FIX2FLT(tr_state->ray.dir.x), FIX2FLT(tr_state->ray.dir.y), FIX2FLT(tr_state->ray.dir.z)));

		group_3d_traverse(node, (GroupingNode *)st, tr_state);
		tr_state->ray = prev_r;

		/*store info if navigation allowed - we just override any layer3D picked first since we are picking 2D
		objects*/
		if (tr_state->camera->navigate_mode || (tr_state->camera->navigation_flags & NAV_ANY))
			tr_state->layer3d = node;

		tr_state->traversing_mode = TRAVERSE_PICK;
	}

l3d_exit:
	/*restore camera*/
	tr_state->camera = prev_cam;
	if (prev_cam) visual_3d_set_viewport(tr_state->visual, tr_state->camera->vp);
	tr_state->visual = old_visual;

	/*restore traversing state*/
	tr_state->backgrounds = oldb;
	tr_state->viewpoints = oldv;
	tr_state->fogs = oldf;
	tr_state->navigations = oldn;
	tr_state->bbox = bbox_backup;
	tr_state->is_layer = prev_layer;
	gf_mx_copy(tr_state->model_matrix, model_backup);
	gf_mx2d_copy(tr_state->transform, mx2d_backup);

	/*in case we missed bindables*/
	if (st->first) {
		st->first = 0;
		gf_node_dirty_set(node, 0, 0);
		gf_sc_invalidate(tr_state->visual->compositor, NULL);
	}
}
示例#24
0
static void svg_recompute_viewport_transformation(GF_Node *node, SVGsvgStack *stack, GF_TraverseState *tr_state, SVGAllAttributes *atts) 
{
	GF_Matrix2D mx;
	SVG_ViewBox ext_vb, *vb;
	SVG_PreserveAspectRatio par;
	Fixed scale, vp_w, vp_h;
	Fixed parent_width, parent_height, doc_width, doc_height;

	/*canvas size negociation has already been done when attaching the scene to the compositor*/
	if (atts->width && (atts->width->type==SVG_NUMBER_PERCENTAGE) ) { 
		parent_width = gf_mulfix(tr_state->vp_size.x, atts->width->value/100);
		doc_width = 0;
	} else if (!stack->root_svg) {
		doc_width = parent_width = atts->width ? atts->width->value : 0;
	} else {
		parent_width = tr_state->vp_size.x;
		doc_width = atts->width ? atts->width->value : 0;
	}

	if (atts->height && (atts->height->type==SVG_NUMBER_PERCENTAGE) ) { 
		parent_height = gf_mulfix(tr_state->vp_size.y, atts->height->value/100);
		doc_height = 0;
	} else if (!stack->root_svg) {
		doc_height = parent_height = atts->height ? atts->height->value : 0;
	} else {
		parent_height = tr_state->vp_size.y;
		doc_height = atts->height ? atts->height->value : 0;
	}

	stack->vp = stack->parent_vp = tr_state->vp_size;

	vb = atts->viewBox;

	gf_mx2d_init(mx);

	if (stack->root_svg) {
		const char *frag_uri = gf_scene_get_fragment_uri(node);
		if (frag_uri) {
			/*SVGView*/
			if (!strncmp(frag_uri, "svgView", 7)) {
				if (!strncmp(frag_uri, "svgView(viewBox(", 16)) {
					Float x, y, w, h;
					sscanf(frag_uri, "svgView(viewBox(%f,%f,%f,%f))", &x, &y, &w, &h);
					ext_vb.x = FLT2FIX(x);
					ext_vb.y = FLT2FIX(y);
					ext_vb.width = FLT2FIX(w);
					ext_vb.height = FLT2FIX(h);
					ext_vb.is_set = 1;
					vb = &ext_vb;
				}
				else if (!strncmp(frag_uri, "svgView(transform(", 18)) {
					Bool ret = gf_svg_parse_transformlist(&mx, (char *) frag_uri+18);
                    if (!ret) {
                        GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[SVG Parsing] Error parsing SVG View transform component: %s\n", frag_uri+18));
                    }
				}
			}
			/*fragID*/
			else {
				GF_Node *target = gf_sg_find_node_by_name(gf_node_get_graph(node), (char *) frag_uri);
				if (target) {
					GF_Matrix2D mx;
					GF_TraverseState bounds_state;
					memset(&bounds_state, 0, sizeof(bounds_state));
					bounds_state.traversing_mode = TRAVERSE_GET_BOUNDS;
					bounds_state.visual = tr_state->visual;
					bounds_state.for_node = target;
					bounds_state.svg_props = tr_state->svg_props;
					gf_mx2d_init(bounds_state.transform);
					gf_mx2d_init(bounds_state.mx_at_node);
					gf_mx_init(tr_state->visual->compositor->hit_world_to_local);
					gf_sc_get_nodes_bounds(node, ((GF_ParentNode *)node)->children, &bounds_state, NULL);
					gf_mx2d_from_mx(&mx, &tr_state->visual->compositor->hit_world_to_local);
					gf_mx2d_apply_rect(&mx, &bounds_state.bounds);
					ext_vb.x = bounds_state.bounds.x;
					ext_vb.y = bounds_state.bounds.y-bounds_state.bounds.height;
					ext_vb.width = bounds_state.bounds.width;
					ext_vb.height = bounds_state.bounds.height;
					ext_vb.is_set = 1;
					vb = &ext_vb;
				}
			}
		}
	}
	gf_mx2d_init(stack->viewbox_mx);

	if (!vb) {
		if (!doc_width || !doc_height) {
			gf_mx2d_copy(stack->viewbox_mx, mx);
			return;
		}
		/*width/height were specified in the doc, use them to compute a dummy viewbox*/
		ext_vb.x = 0;
		ext_vb.y = 0;
		ext_vb.width = doc_width;
		ext_vb.height = doc_height;
		ext_vb.is_set = 1;
		vb = &ext_vb;
	}
	if ((vb->width<=0) || (vb->height<=0) ) {
		gf_mx2d_copy(stack->viewbox_mx, mx);
		return;
	}
	stack->vp.x = vb->width;
	stack->vp.y = vb->height;

	/*setup default*/
	par.defer = 0;
	par.meetOrSlice = SVG_MEETORSLICE_MEET;
	par.align = SVG_PRESERVEASPECTRATIO_XMIDYMID;

	/*use parent (animation, image) viewport settings*/
	if (tr_state->parent_anim_atts) {
		if (tr_state->parent_anim_atts->preserveAspectRatio) {
			if (tr_state->parent_anim_atts->preserveAspectRatio->defer) {
				if (atts->preserveAspectRatio) 
					par = *atts->preserveAspectRatio;
			} else {
				par = *tr_state->parent_anim_atts->preserveAspectRatio;
			}
		}
	}
	/*use current viewport settings*/
	else if (atts->preserveAspectRatio) {
		par = *atts->preserveAspectRatio;
	}

	if (par.meetOrSlice==SVG_MEETORSLICE_MEET) {
		if (gf_divfix(parent_width, vb->width) > gf_divfix(parent_height, vb->height)) {
			scale = gf_divfix(parent_height, vb->height);
			vp_w = gf_mulfix(vb->width, scale);
			vp_h = parent_height;
		} else {
			scale = gf_divfix(parent_width, vb->width);
			vp_w = parent_width;
			vp_h = gf_mulfix(vb->height, scale);
		}
	} else {
		if (gf_divfix(parent_width, vb->width) < gf_divfix(parent_height, vb->height)) {
			scale = gf_divfix(parent_height, vb->height);
			vp_w = gf_mulfix(vb->width, scale);
			vp_h = parent_height;
		} else {
			scale = gf_divfix(parent_width, vb->width);
			vp_w = parent_width;
			vp_h = gf_mulfix(vb->height, scale);
		}
	}

	if (par.align==SVG_PRESERVEASPECTRATIO_NONE) {
		stack->viewbox_mx.m[0] = gf_divfix(parent_width, vb->width);
		stack->viewbox_mx.m[4] = gf_divfix(parent_height, vb->height);
		stack->viewbox_mx.m[2] = - gf_muldiv(vb->x, parent_width, vb->width); 
		stack->viewbox_mx.m[5] = - gf_muldiv(vb->y, parent_height, vb->height); 
	} else {
		Fixed dx, dy;
		stack->viewbox_mx.m[0] = stack->viewbox_mx.m[4] = scale;
		stack->viewbox_mx.m[2] = - gf_mulfix(vb->x, scale); 
		stack->viewbox_mx.m[5] = - gf_mulfix(vb->y, scale); 

		dx = dy = 0;
		switch (par.align) {
		case SVG_PRESERVEASPECTRATIO_XMINYMIN:
			break;
		case SVG_PRESERVEASPECTRATIO_XMIDYMIN:
			dx = ( parent_width - vp_w) / 2; 
			break;
		case SVG_PRESERVEASPECTRATIO_XMAXYMIN:
			dx = parent_width - vp_w; 
			break;
		case SVG_PRESERVEASPECTRATIO_XMINYMID:
			dy = ( parent_height - vp_h) / 2; 
			break;
		case SVG_PRESERVEASPECTRATIO_XMIDYMID:
			dx = ( parent_width  - vp_w) / 2; 
			dy = ( parent_height - vp_h) / 2; 
			break;
		case SVG_PRESERVEASPECTRATIO_XMAXYMID:
			dx = parent_width  - vp_w; 
			dy = ( parent_height - vp_h) / 2; 
			break;
		case SVG_PRESERVEASPECTRATIO_XMINYMAX:
			dy = parent_height - vp_h; 
			break;
		case SVG_PRESERVEASPECTRATIO_XMIDYMAX:
			dx = (parent_width - vp_w) / 2; 
			dy = parent_height - vp_h; 
			break;
		case SVG_PRESERVEASPECTRATIO_XMAXYMAX:
			dx = parent_width  - vp_w; 
			dy = parent_height - vp_h; 
			break;
		}
		gf_mx2d_add_translation(&stack->viewbox_mx, dx, dy);
		stack->dx = dx;
		stack->dy = dy;
		stack->vpw = vp_w;
		stack->vph = vp_h;

		/*we need a clipper*/
		if (stack->root_svg && !tr_state->parent_anim_atts && (par.meetOrSlice==SVG_MEETORSLICE_SLICE)) {
			GF_Rect rc;
			rc.width = parent_width;
			rc.height = parent_height;
			if (!stack->root_svg) {
				rc.x = 0;
				rc.y = parent_height;
				gf_mx2d_apply_rect(&stack->viewbox_mx, &rc);
			} else {
				rc.x = dx;
				rc.y = dy + parent_height;
			}
//			tr_state->visual->top_clipper = gf_rect_pixelize(&rc);
		}
	}
	gf_mx2d_add_matrix(&stack->viewbox_mx, &mx);
}
示例#25
0
void gf_sc_get_nodes_bounds(GF_Node *self, GF_ChildNodeItem *children, GF_TraverseState *tr_state, s32 *child_idx)
{
	u32 i;
	SFVec2f size;
	GF_Rect rc;
	GF_Matrix2D cur_mx;

	if (tr_state->abort_bounds_traverse) {
		if (self == tr_state->for_node) {
			gf_mx2d_pre_multiply(&tr_state->mx_at_node, &tr_state->transform);
		}
		tr_state->abort_bounds_traverse=0;
		gf_sc_get_nodes_bounds(self, children, tr_state, child_idx);
		tr_state->abort_bounds_traverse=1;
		return;
	}
	if (!children) return;

	size.x = size.y = -FIX_ONE;
#ifndef GPAC_DISABLE_VRML
	switch (gf_node_get_tag(self)) {
	case TAG_MPEG4_Layer2D: size = ((M_Layer2D *)self)->size; break;
	case TAG_MPEG4_Layer3D: size = ((M_Layer3D *)self)->size; break;
	case TAG_MPEG4_Form: size = ((M_Form *)self)->size; break;
	}
#endif
	if ((size.x>=0) && (size.y>=0)) {
		tr_state->bounds = gf_rect_center(size.x, size.y);
		return;
	}

	gf_mx2d_copy(cur_mx, tr_state->transform);
	rc = gf_rect_center(0,0);

	i = 0;
	while (children) {
		if (child_idx && (i != (u32) *child_idx)) {
			children = children->next;
			continue;
		}
		gf_mx2d_init(tr_state->transform);
		tr_state->bounds = gf_rect_center(0,0);

		/*we hit the target node*/
		if (children->node == tr_state->for_node) 
			tr_state->abort_bounds_traverse = 1;

		gf_node_traverse(children->node, tr_state);

		if (tr_state->abort_bounds_traverse) {
			gf_mx2d_add_matrix(&tr_state->mx_at_node, &cur_mx);
			return;
		}

		gf_mx2d_apply_rect(&tr_state->transform, &tr_state->bounds);
		gf_rect_union(&rc, &tr_state->bounds);
		children = children->next;
		if (child_idx) 
			break;
	}

#ifndef GPAC_DISABLE_SVG
	if (gf_node_get_tag(self)==TAG_SVG_use) {
		GF_FieldInfo info;
		if (gf_node_get_attribute_by_tag(self, TAG_XLINK_ATT_href, 0, 0, &info)==GF_OK) {
			GF_Node *iri = ((XMLRI*)info.far_ptr)->target;
			if (iri) {
				gf_mx2d_init(tr_state->transform);
				tr_state->bounds = gf_rect_center(0,0);

				/*we hit the target node*/
				if (iri == tr_state->for_node) 
					tr_state->abort_bounds_traverse = 1;

				gf_node_traverse(iri, tr_state);

				if (tr_state->abort_bounds_traverse) {
					gf_mx2d_pre_multiply(&tr_state->mx_at_node, &cur_mx);
					return;
				}

				gf_mx2d_apply_rect(&tr_state->transform, &tr_state->bounds);
				gf_rect_union(&rc, &tr_state->bounds);
			}
		}
	}
#endif
	
	gf_mx2d_copy(tr_state->transform, cur_mx);
	if (self != tr_state->for_node) {
		gf_mx2d_apply_rect(&tr_state->transform, &rc);
	}
	tr_state->bounds = rc;
}
示例#26
0
Bool group_cache_traverse(GF_Node *node, GroupCache *cache, GF_TraverseState *tr_state, Bool force_recompute, Bool is_mpeg4, Bool auto_fit_vp)
{
	GF_Matrix2D backup;
	DrawableContext *group_ctx = NULL;
	GF_ChildNodeItem *l;

	if (!cache) return 0;

	/*do we need to recompute the cache*/
	if (cache->force_recompute) {
		force_recompute = 1;
		cache->force_recompute = 0;
	}
	else if (gf_node_dirty_get(node) & GF_SG_CHILD_DIRTY) {
		force_recompute = 1;
	}

	/*we need to redraw the group in an offscreen visual*/
	if (force_recompute) {
		GF_Matrix2D backup;
		GF_IRect rc1, rc2;
		u32 type_3d;
		u32 prev_flags;
		GF_Rect cache_bounds;
		GF_SURFACE offscreen_surface, old_surf;
		GF_Raster2D *r2d = tr_state->visual->compositor->rasterizer;
		DrawableContext *child_ctx;
		Fixed temp_x, temp_y, scale_x, scale_y;

		GF_LOG(GF_LOG_INFO, GF_LOG_COMPOSE, ("[Compositor] Recomputing cache for subtree %s\n", gf_node_get_log_name(node)));
		/*step 1 : store current state and indicate children should not be cached*/
		tr_state->in_group_cache = 1;
		prev_flags = tr_state->immediate_draw;
		/*store the current transform matrix, create a new one for group_cache*/
		gf_mx2d_copy(backup, tr_state->transform);
		gf_mx2d_init(tr_state->transform);

		type_3d = 0;
#ifndef GPAC_DISABLE_3D
		/*force 2D rendering*/
		type_3d = tr_state->visual->type_3d;
		tr_state->visual->type_3d = 0;
#endif

		/*step 2: collect the bounds of all children*/
		tr_state->traversing_mode = TRAVERSE_GET_BOUNDS;
		cache_bounds.width = cache_bounds.height = 0;
		l = ((GF_ParentNode*)node)->children;
		while (l) {
			tr_state->bounds.width = tr_state->bounds.height = 0;
			gf_node_traverse(l->node, tr_state);
			l = l->next;
			gf_rect_union(&cache_bounds, &tr_state->bounds);
		}
		tr_state->traversing_mode = TRAVERSE_SORT;

		if (!cache_bounds.width || !cache_bounds.height) {
			tr_state->in_group_cache = 0;
			tr_state->immediate_draw = prev_flags;
			gf_mx2d_copy(tr_state->transform, backup);
#ifndef GPAC_DISABLE_3D
			tr_state->visual->type_3d = type_3d;
#endif
			return 0;
		}

		/*step 3: insert a DrawableContext for this group in the display list*/
		if (is_mpeg4) {
#ifndef GPAC_DISABLE_VRML
			group_ctx = drawable_init_context_mpeg4(cache->drawable, tr_state);
#endif
		} else {
#ifndef GPAC_DISABLE_SVG
			group_ctx = drawable_init_context_svg(cache->drawable, tr_state);
#endif
		}
		if (!group_ctx) return 0;

		/*step 4: now we have the bounds:
			allocate the offscreen memory
			create temp raster visual & attach to buffer
			override the tr_state->visual->the_surface with the temp raster
			add translation (shape is not always centered)
			setup top clipers
		*/
		old_surf = tr_state->visual->raster_surface;
		offscreen_surface = r2d->surface_new(r2d, tr_state->visual->center_coords);	/*a new temp raster visual*/
		tr_state->visual->raster_surface = offscreen_surface;

		/*use current surface coordinate scaling to compute the cache*/
#ifdef GF_SR_USE_VIDEO_CACHE
		scale_x = tr_state->visual->compositor->cache_scale * backup.m[0] / 100;
		scale_y = tr_state->visual->compositor->cache_scale * backup.m[4] / 100;
#else
		scale_x = backup.m[0];
		scale_y = backup.m[4];
#endif

		if (scale_x<0) scale_x = -scale_x;
		if (scale_y<0) scale_y = -scale_y;

		cache->scale = MAX(scale_x, scale_y);
		tr_state->bounds = cache_bounds;
		gf_mx2d_add_scale(&tr_state->transform, scale_x, scale_y);
		gf_mx2d_apply_rect(&tr_state->transform, &cache_bounds);

		rc1 = gf_rect_pixelize(&cache_bounds);
		if (rc1.width % 2) rc1.width++;
		if (rc1.height%2) rc1.height++;

		/* Initialize the group cache with the scaled pixelized bounds for texture but the original bounds for path*/
		group_cache_setup(cache, &tr_state->bounds, &rc1, tr_state->visual->compositor, type_3d);


		/*attach the buffer to visual*/
		r2d->surface_attach_to_buffer(offscreen_surface, cache->txh.data,
										cache->txh.width,
										cache->txh.height,
										0,
										cache->txh.stride,
										cache->txh.pixelformat);


		/*recompute the bounds with the final scaling used*/
		scale_x = gf_divfix(INT2FIX(rc1.width), tr_state->bounds.width);
		scale_y = gf_divfix(INT2FIX(rc1.height), tr_state->bounds.height);
		gf_mx2d_init(tr_state->transform);
		gf_mx2d_add_scale(&tr_state->transform, scale_x, scale_y);
		cache_bounds = tr_state->bounds;
		gf_mx2d_apply_rect(&tr_state->transform, &cache_bounds);

		/*centered the bitmap on the visual*/
		temp_x = -cache_bounds.x;
		temp_y = -cache_bounds.y;
		if (tr_state->visual->center_coords) {
			temp_x -= cache_bounds.width/2;
			temp_y += cache_bounds.height/2;
		} else {
			temp_y += cache_bounds.height;
		}
		gf_mx2d_add_translation(&tr_state->transform, temp_x, temp_y);

		/*override top clippers*/
		rc1 = tr_state->visual->surf_rect;
		rc2 = tr_state->visual->top_clipper;
		tr_state->visual->surf_rect.width = cache->txh.width;
		tr_state->visual->surf_rect.height = cache->txh.height;
		if (tr_state->visual->center_coords) {
			tr_state->visual->surf_rect.y = cache->txh.height/2;
			tr_state->visual->surf_rect.x = -1 * (s32) cache->txh.width/2;
		} else {
			tr_state->visual->surf_rect.y = cache->txh.height;
			tr_state->visual->surf_rect.x = 0;
		}
		tr_state->visual->top_clipper = tr_state->visual->surf_rect;


		/*step 5: traverse subtree in direct draw mode*/
		tr_state->immediate_draw = 1;
		group_ctx->flags &= ~CTX_NO_ANTIALIAS;

		l = ((GF_ParentNode*)node)->children;
		while (l) {
			gf_node_traverse(l->node, tr_state);
			l = l->next;
		}
		/*step 6: reset all contexts after the current group one*/
		child_ctx = group_ctx->next;
		while (child_ctx && child_ctx->drawable) {
			drawable_reset_bounds(child_ctx->drawable, tr_state->visual);
			child_ctx->drawable = NULL;
			child_ctx = child_ctx->next;
		}

		/*and set ourselves as the last context on the main visual*/
		tr_state->visual->cur_context = group_ctx;

		/*restore state and destroy whatever needs to be cleaned*/
		gf_mx2d_copy(tr_state->transform, backup);
		tr_state->in_group_cache = 0;
		tr_state->immediate_draw = prev_flags;
		r2d->surface_delete(offscreen_surface);
		tr_state->visual->raster_surface = old_surf;
		tr_state->traversing_mode = TRAVERSE_SORT;

#ifndef GPAC_DISABLE_3D
		tr_state->visual->type_3d = type_3d;
#endif
		tr_state->visual->surf_rect = rc1;
		tr_state->visual->top_clipper = rc2;

		/*update texture*/
		cache->txh.transparent = 1;
		cache->txh.flags |= GF_SR_TEXTURE_NO_GL_FLIP;
		gf_sc_texture_set_data(&cache->txh);
		gf_sc_texture_push_image(&cache->txh, 0, type_3d ? 0 : 1);

		cache->orig_vp = tr_state->vp_size;
	}
	/*just setup the context*/
	else {
		if (is_mpeg4) {
#ifndef GPAC_DISABLE_VRML
			group_ctx = drawable_init_context_mpeg4(cache->drawable, tr_state);
#endif
		} else {
#ifndef GPAC_DISABLE_SVG
			group_ctx = drawable_init_context_svg(cache->drawable, tr_state);
#endif
		}
	}
	if (!group_ctx) return 0;
	group_ctx->flags |= CTX_NO_ANTIALIAS;
	if (cache->opacity != FIX_ONE)
		group_ctx->aspect.fill_color = GF_COL_ARGB_FIXED(cache->opacity, FIX_ONE, FIX_ONE, FIX_ONE);
	else
		group_ctx->aspect.fill_color = 0;
	group_ctx->aspect.fill_texture = &cache->txh;

	if (!cache->opacity) {
		group_ctx->drawable = NULL;
		return 0;
	}

	if (gf_node_dirty_get(node)) group_ctx->flags |= CTX_TEXTURE_DIRTY;

#ifdef CACHE_DEBUG_CENTER
	gf_mx2d_copy(backup, tr_state->transform);
	gf_mx2d_init(tr_state->transform);
#else
	gf_mx2d_copy(backup, tr_state->transform);
	if (auto_fit_vp) {
		if ((tr_state->vp_size.x != cache->orig_vp.x) || (tr_state->vp_size.y != cache->orig_vp.y)) {
			GF_Matrix2D m;
			gf_mx2d_init(m);
			gf_mx2d_copy(backup, tr_state->transform);
			gf_mx2d_add_scale(&m, gf_divfix(tr_state->vp_size.x, cache->orig_vp.x), gf_divfix(tr_state->vp_size.y, cache->orig_vp.y) );
			gf_mx2d_pre_multiply(&tr_state->transform, &m);
		} else {
			auto_fit_vp = 0;
		}
	}
#endif

#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d) {
		if (!cache->drawable->mesh) {
			cache->drawable->mesh = new_mesh();
			mesh_from_path(cache->drawable->mesh, cache->drawable->path);
		}
		visual_3d_draw_from_context(group_ctx, tr_state);
		group_ctx->drawable = NULL;
	} else
#endif
		drawable_finalize_sort(group_ctx, tr_state, NULL);

#ifndef CACHE_DEBUG_CENTER
	if (auto_fit_vp)
#endif
	{
		gf_mx2d_copy(tr_state->transform, backup);
	}
	return (force_recompute==1);
}
示例#27
0
static void TraverseLayer2D(GF_Node *node, void *rs, Bool is_destroy)
{
	GF_List *oldb, *oldv;
	GF_Node *viewport;
	GF_Node *back;
	Bool prev_layer;
	GF_Matrix2D backup;
	SFVec2f prev_vp;

#ifndef GPAC_DISABLE_3D
	GF_Matrix mx3d;
	GF_List *oldf, *oldn;
	GF_List *node_list_backup;
	GF_Rect prev_clipper;
	Bool had_clip;
#endif
	
	M_Layer2D *l = (M_Layer2D *)node;
	Layer2DStack *st = (Layer2DStack *) gf_node_get_private(node);
	GF_TraverseState *tr_state = (GF_TraverseState *) rs;
	
	if (is_destroy) {
		gf_list_del(st->backs);
		gf_list_del(st->views);
		group_2d_destroy(node, (GroupingNode2D*)st);
		gf_free(st);
		return;
	}

	/*layers can only be used in a 2D context*/
#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d && tr_state->camera->is_3D) return;
#endif

	/*layer2D maintains its own stacks*/
	oldb = tr_state->backgrounds;
	oldv = tr_state->viewpoints;
	tr_state->backgrounds = st->backs;
	tr_state->viewpoints = st->views;
	prev_layer = tr_state->is_layer;
	tr_state->is_layer = 1;
#ifndef GPAC_DISABLE_3D
	oldf = tr_state->fogs;
	oldn = tr_state->navigations;
	tr_state->fogs = tr_state->navigations = NULL;
#endif

	l2d_CheckBindables(node, tr_state, st->first);

	back = (GF_Node*)gf_list_get(st->backs, 0);

	viewport = (GF_Node*)gf_list_get(st->views, 0);

	if ((tr_state->traversing_mode == TRAVERSE_SORT) || (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS)) {
		/*override group bounds*/
		visual_get_size_info(tr_state, &st->clip.width, &st->clip.height);
		/*setup bounds in local coord system*/
		if (l->size.x>=0) st->clip.width = l->size.x;
		if (l->size.y>=0) st->clip.height = l->size.y;
		st->clip = gf_rect_center(st->clip.width, st->clip.height);
		st->bounds = st->clip;
	}
	
	prev_vp = tr_state->vp_size;
	tr_state->vp_size.x = st->clip.width;
	tr_state->vp_size.y = st->clip.height;

	switch (tr_state->traversing_mode) {
	case TRAVERSE_SORT:
#ifndef GPAC_DISABLE_3D
		if (tr_state->visual->type_3d) {
			tr_state->layer_clipper = compositor_2d_update_clipper(tr_state, st->clip, &had_clip, &prev_clipper, 1);

			visual_3d_matrix_push(tr_state->visual);
			gf_mx_copy(mx3d, tr_state->model_matrix);

			/*setup clipping*/
			visual_3d_set_clipper_2d(tr_state->visual, tr_state->layer_clipper);
			
			/*apply background BEFORE viewport*/
			if (back) {
				tr_state->traversing_mode = TRAVERSE_BINDABLE;
				gf_bbox_from_rect(&tr_state->bbox, &st->clip);
				gf_node_traverse(back, tr_state);
			}

			/*sort all children without transform, and use current transform when flushing contexts*/
			gf_mx_init(tr_state->model_matrix);

			/*apply viewport*/
			if (viewport) {
				tr_state->traversing_mode = TRAVERSE_BINDABLE;
				tr_state->bounds = st->clip;
				gf_node_traverse(viewport, tr_state);
				visual_3d_matrix_add(tr_state->visual, tr_state->model_matrix.m);
			}


			node_list_backup = tr_state->visual->alpha_nodes_to_draw;
			tr_state->visual->alpha_nodes_to_draw = gf_list_new();
			tr_state->traversing_mode = TRAVERSE_SORT;
			/*reset cull flag*/
			tr_state->cull_flag = 0;
			group_2d_traverse(node, (GroupingNode2D *)st, tr_state);

			visual_3d_flush_contexts(tr_state->visual, tr_state);
			tr_state->traversing_mode = TRAVERSE_SORT;

			assert(!gf_list_count(tr_state->visual->alpha_nodes_to_draw));
			gf_list_del(tr_state->visual->alpha_nodes_to_draw);
			tr_state->visual->alpha_nodes_to_draw = node_list_backup;

			
			visual_3d_matrix_pop(tr_state->visual);
			gf_mx_copy(tr_state->model_matrix, mx3d);

			visual_3d_reset_clipper_2d(tr_state->visual);

			tr_state->has_layer_clip = had_clip;
			if (had_clip) {
				tr_state->layer_clipper = prev_clipper;
				visual_3d_set_clipper_2d(tr_state->visual, tr_state->layer_clipper);
			}
		} else 
#endif
		{
			GF_IRect prev_clip;
			GF_Rect rc;

			gf_mx2d_copy(backup, tr_state->transform);

			prev_clip = tr_state->visual->top_clipper;
			rc = st->clip;
			
			/*get clipper in world coordinate*/
			gf_mx2d_apply_rect(&tr_state->transform, &rc);

			if (viewport) {
				tr_state->traversing_mode = TRAVERSE_BINDABLE;
				tr_state->bounds = st->clip;
				gf_node_traverse(viewport, tr_state);
#if VIEWPORT_CLIPS
				/*move viewport box in world coordinate*/
				gf_mx2d_apply_rect(&backup, &tr_state->bounds);
				/*and intersect with layer clipper*/
				rect_intersect(&rc, &tr_state->bounds);
#endif
			}

			tr_state->visual->top_clipper = gf_rect_pixelize(&rc);
			gf_irect_intersect(&tr_state->visual->top_clipper, &prev_clip);
			tr_state->traversing_mode = TRAVERSE_SORT;

			if (tr_state->visual->top_clipper.width && tr_state->visual->top_clipper.height) {
				if (back && Bindable_GetIsBound(back) ) {
					DrawableContext *ctx;

					ctx = b2d_get_context((M_Background2D*) back, st->backs);
					gf_mx2d_init(ctx->transform);
					ctx->bi->clip = tr_state->visual->top_clipper;
					ctx->bi->unclip = rc;

					if (tr_state->immediate_draw) {
						tr_state->ctx = ctx;
						tr_state->traversing_mode = TRAVERSE_DRAW_2D;
						gf_node_traverse(back, tr_state);
						tr_state->traversing_mode = TRAVERSE_SORT;
						tr_state->ctx = NULL;
					} else {
						DrawableContext *back_ctx = visual_2d_get_drawable_context(tr_state->visual);

						gf_node_traverse(back, tr_state);

						back_ctx->flags = ctx->flags;
						back_ctx->flags &= ~CTX_IS_TRANSPARENT;
						back_ctx->flags |= CTX_IS_BACKGROUND;
						back_ctx->aspect = ctx->aspect;
						back_ctx->drawable = ctx->drawable;
						drawable_check_bounds(back_ctx, tr_state->visual);
						back_ctx->bi->clip = ctx->bi->clip;
						back_ctx->bi->unclip = ctx->bi->unclip;
					}
					/*keep track of node drawn*/
					if (!(ctx->drawable->flags & DRAWABLE_REGISTERED_WITH_VISUAL) ) {
						struct _drawable_store *it;
						GF_SAFEALLOC(it, struct _drawable_store);
						it->drawable = ctx->drawable;
						if (tr_state->visual->last_prev_entry) {
							tr_state->visual->last_prev_entry->next = it;
							tr_state->visual->last_prev_entry = it;
						} else {
							tr_state->visual->prev_nodes = tr_state->visual->last_prev_entry = it;
						}
						GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Layer2D] Registering new drawn node %s on visual\n", gf_node_get_class_name(it->drawable->node)));
						ctx->drawable->flags |= DRAWABLE_REGISTERED_WITH_VISUAL;
					}
				}

				group_2d_traverse(node, (GroupingNode2D *)st, tr_state);
			}
			tr_state->visual->top_clipper = prev_clip;
			gf_mx2d_copy(tr_state->transform, backup);
		}
		break;
		
		/*check picking - we must fall in our 2D clipper*/
	case TRAVERSE_PICK:
		if (gf_sc_pick_in_clipper(tr_state, &st->clip)) {
		
#ifndef GPAC_DISABLE_3D
			if (tr_state->visual->type_3d) {
				/*apply viewport*/
				if (viewport) {
					gf_mx_copy(mx3d, tr_state->model_matrix);
					tr_state->traversing_mode = TRAVERSE_BINDABLE;
					tr_state->bounds = st->clip;
					gf_node_traverse(viewport, tr_state);
					tr_state->traversing_mode = TRAVERSE_PICK;
					group_2d_traverse(node, (GroupingNode2D *)st, tr_state);
					gf_mx_copy(tr_state->model_matrix, mx3d);
				} else {
					group_2d_traverse(node, (GroupingNode2D *)st, tr_state);
				}
			} else 
#endif
			{
				if (viewport) {
					gf_mx2d_copy(backup, tr_state->transform);
					tr_state->traversing_mode = TRAVERSE_BINDABLE;
					tr_state->bounds = st->clip;
					gf_node_traverse(viewport, tr_state);
					tr_state->traversing_mode = TRAVERSE_PICK;
					group_2d_traverse(node, (GroupingNode2D *)st, tr_state);
					gf_mx2d_copy(tr_state->transform, backup);
				} else {
					group_2d_traverse(node, (GroupingNode2D *)st, tr_state);
				}
			}	
		}
		break;
	case TRAVERSE_GET_BOUNDS:
		if (tr_state->for_node) {
			group_2d_traverse(node, (GroupingNode2D *)st, tr_state);
		} else {
			tr_state->bounds = st->clip;
#ifndef GPAC_DISABLE_3D
			gf_bbox_from_rect(&tr_state->bbox, &st->clip);
#endif
		}
		break;

	case TRAVERSE_DRAW_2D:
		group_2d_traverse(node, (GroupingNode2D *)st, tr_state);
		break;

#ifndef GPAC_DISABLE_3D
	/*drawing a layer means drawing all sub-elements as a whole (no depth sorting with parents)*/
	case TRAVERSE_DRAW_3D:
		assert(0);
		break;
#endif
	}
	
	/*restore traversing state*/
	tr_state->vp_size = prev_vp;
	tr_state->backgrounds = oldb;
	tr_state->viewpoints = oldv;
	tr_state->is_layer = prev_layer;
#ifndef GPAC_DISABLE_3D
	tr_state->fogs = oldf;
	tr_state->navigations = oldn;
#endif

	/*in case we missed bindables*/
	if (st->first) {
		st->first = 0;
		gf_sc_invalidate(tr_state->visual->compositor, NULL);
	}
}
示例#28
0
static void svg_traverse_svg(GF_Node *node, void *rs, Bool is_destroy)
{
	Bool rootmost_svg, send_resize;
	u32 viewport_color;
	SVGsvgStack *stack;
	GF_Matrix2D backup_matrix, vb_bck;
#ifndef GPAC_DISABLE_3D
	GF_Matrix bck_mx;
#endif
	Bool is_dirty;
	GF_IRect top_clip;
	SFVec2f prev_vp;
	SVGPropertiesPointers backup_props, *prev_props;
	u32 backup_flags;
	Bool invalidate_flag;
	u32 styling_size = sizeof(SVGPropertiesPointers);
	GF_TraverseState *tr_state = (GF_TraverseState *) rs;
	SVGAllAttributes all_atts;
	stack = gf_node_get_private(node);

	if (is_destroy) {
		if (stack->svg_props) {
			gf_svg_properties_reset_pointers(stack->svg_props);
			gf_free(stack->svg_props);
		}
		gf_sc_check_focus_upon_destroy(node);
		if (stack->vp_fill) drawable_del(stack->vp_fill);
		gf_free(stack);
		return;
	}

	prev_props = tr_state->svg_props;
	/*SVG props not set: we are either the root-most <svg> of the compositor
	or an <svg> inside an <animation>*/
	if (!tr_state->svg_props) {
		tr_state->svg_props = stack->svg_props;
		if (!tr_state->svg_props) return;
	}
	
	gf_svg_flatten_attributes((SVG_Element *)node, &all_atts);
	if (!compositor_svg_traverse_base(node, &all_atts, tr_state, &backup_props, &backup_flags)) {
		tr_state->svg_props = prev_props;
		return;
	}

	/*enable or disable navigation*/
	tr_state->visual->compositor->navigation_disabled = (all_atts.zoomAndPan && *all_atts.zoomAndPan == SVG_ZOOMANDPAN_DISABLE) ? 1 : 0;

	if (compositor_svg_is_display_off(tr_state->svg_props)) {
		memcpy(tr_state->svg_props, &backup_props, styling_size);
		tr_state->svg_flags = backup_flags;
		return;
	}

	top_clip = tr_state->visual->top_clipper;
	gf_mx2d_copy(backup_matrix, tr_state->transform);
	gf_mx2d_copy(vb_bck, tr_state->vb_transform);

#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d) gf_mx_copy(bck_mx, tr_state->model_matrix);
#endif
	
	invalidate_flag = tr_state->invalidate_all;

	is_dirty = gf_node_dirty_get(node);
	if (is_dirty  & GF_SG_CHILD_DIRTY) drawable_reset_group_highlight(tr_state, node);
	gf_node_dirty_clear(node, 0);

	send_resize = 0;
	if ((stack->parent_vp.x != tr_state->vp_size.x) || (stack->parent_vp.y != tr_state->vp_size.y)) {
		is_dirty = 1;
		send_resize = 1;
	}

	if (is_dirty || tr_state->visual->compositor->recompute_ar) {
		svg_recompute_viewport_transformation(node, stack, tr_state, &all_atts);
	}

	gf_mx2d_copy(tr_state->vb_transform, stack->viewbox_mx);

	rootmost_svg = (stack->root_svg && !tr_state->parent_anim_atts) ? 1 : 0;	
	if (tr_state->traversing_mode == TRAVERSE_SORT) {
		SVG_Paint *vp_fill = NULL;
		Fixed vp_opacity;

		if (tr_state->parent_anim_atts) {
			vp_fill = tr_state->parent_anim_atts->viewport_fill;
			vp_opacity = tr_state->parent_anim_atts->viewport_fill_opacity ? tr_state->parent_anim_atts->viewport_fill_opacity->value : FIX_ONE;
		} else {
			vp_fill = tr_state->svg_props->viewport_fill;
			vp_opacity = tr_state->svg_props->viewport_fill_opacity ? tr_state->svg_props->viewport_fill_opacity->value : FIX_ONE;
		} 

		if (vp_fill && (vp_fill->type != SVG_PAINT_NONE) && vp_opacity) {
			Bool col_dirty = 0;
			viewport_color = GF_COL_ARGB_FIXED(vp_opacity, vp_fill->color.red, vp_fill->color.green, vp_fill->color.blue);

			if (stack->prev_color != viewport_color) {
				stack->prev_color = viewport_color;
				col_dirty = 1;
			}

			if (!rootmost_svg) {
				DrawableContext *ctx;
				Fixed width = tr_state->parent_anim_atts->width->value;
				Fixed height = tr_state->parent_anim_atts->height->value;

				if (!stack->vp_fill) {
					stack->vp_fill = drawable_new();
					stack->vp_fill->node = node;
				}
				if ((width != stack->vp_fill->path->bbox.width) || (height != stack->vp_fill->path->bbox.height)) {
					drawable_reset_path(stack->vp_fill);
					gf_path_add_rect(stack->vp_fill->path, 0, 0, width, -height);
				}

				ctx = drawable_init_context_svg(stack->vp_fill, tr_state);
				if (ctx) {
					ctx->flags &= ~CTX_IS_TRANSPARENT;
					ctx->aspect.pen_props.width = 0;
					ctx->aspect.fill_color = viewport_color;
					ctx->aspect.fill_texture = NULL;
					if (col_dirty) ctx->flags |= CTX_APP_DIRTY;
					drawable_finalize_sort(ctx, tr_state, NULL);
				}

			} else if (col_dirty) {
				tr_state->visual->compositor->back_color = viewport_color;
				/*invalidate the entire visual*/
				tr_state->invalidate_all = 1;
			}
		}
	}


	if (!stack->root_svg && (all_atts.x || all_atts.y)) 
		gf_mx2d_add_translation(&tr_state->vb_transform, all_atts.x->value, all_atts.y->value);

#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d) {
		if (tr_state->traversing_mode==TRAVERSE_SORT) {
			GF_Matrix tmp;
			visual_3d_matrix_push(tr_state->visual);

			gf_mx_from_mx2d(&tmp, &tr_state->vb_transform);
			visual_3d_matrix_add(tr_state->visual, tmp.m);
		} else {
			gf_mx_add_matrix_2d(&tr_state->model_matrix, &tr_state->vb_transform);
		}
	} else 
#endif
	{
		gf_mx2d_pre_multiply(&tr_state->transform, &tr_state->vb_transform);
	}

	/*store VP and move it to current VP (eg, the one used to compute the vb_transform)*/
	prev_vp = tr_state->vp_size;
	tr_state->vp_size = stack->vp;

	/*the event may trigger scripts which may delete nodes / modify the scene. We therefore send the resize event 
	before traversing the scene*/
	if (send_resize) {
		GF_DOM_Event evt;
		memset(&evt, 0, sizeof(GF_DOM_Event));
		evt.bubbles = 1;
		evt.type = GF_EVENT_RESIZE;
		gf_dom_event_fire(node, &evt);
	}
	if ((stack->vp.x != prev_vp.x) || (stack->vp.y != prev_vp.y)) {
		GF_Scene *scene = node->sgprivate->scenegraph->userpriv;
		
		if (scene) { 
			GF_DOM_Event evt;
			memset(&evt, 0, sizeof(GF_DOM_Event));
			evt.bubbles = 0;
			evt.screen_rect.width = stack->vpw;
			evt.screen_rect.height = stack->vph;
			evt.screen_rect.x = stack->dx;
			evt.screen_rect.y = stack->dy;
			evt.prev_translate.x = stack->vp.x;
			evt.prev_translate.y = stack->vp.y;
			evt.type = GF_EVENT_VP_RESIZE;
			gf_scene_notify_event(scene, 0, NULL, &evt, GF_OK);
		}
	}

	if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) {
		gf_sc_get_nodes_bounds(node, ((SVG_Element *)node)->children, tr_state, NULL);
	} else {
		compositor_svg_traverse_children(((SVG_Element *)node)->children, tr_state);
	}
	tr_state->vp_size = prev_vp;

#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d) {
		if (tr_state->traversing_mode==TRAVERSE_SORT) visual_3d_matrix_pop(tr_state->visual);
		gf_mx_copy(tr_state->model_matrix, bck_mx);
	}
#endif
	gf_mx2d_copy(tr_state->transform, backup_matrix);  
	gf_mx2d_copy(tr_state->vb_transform, vb_bck);
	memcpy(tr_state->svg_props, &backup_props, styling_size);
	tr_state->svg_flags = backup_flags;
	tr_state->visual->top_clipper = top_clip;
	if (!stack->root_svg) {
		tr_state->invalidate_all = invalidate_flag;
	}
	tr_state->svg_props = prev_props;
}