Esempio n. 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);
	}
}
Esempio n. 2
0
static void DestroyPathLayout(SFNode *node)
{
	PathLayoutStack *st = (PathLayoutStack *)Node_GetPrivate(node);
	DeleteGroupingNode2D((GroupingNode2D *)st);
	if (st->iter) m4_path_delete_iterator(st->iter);
	free(st);
}
Esempio n. 3
0
static void RenderGroup(GF_Node *node, void *rs, Bool is_destroy)
{
	GroupingNode2D *group = (GroupingNode2D *) gf_node_get_private(node);
	if (is_destroy) {
		DeleteGroupingNode2D(group);
		free(group);
		return;
	}
	group2d_traverse(group, ((M_Group *)node)->children, (RenderEffect2D*)rs);
}
Esempio n. 4
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);
	}
}
Esempio n. 5
0
/*ColorTransform*/
static void RenderColorTransform(GF_Node *node, void *rs, Bool is_destroy)
{
	Bool c_changed;
	M_ColorTransform *tr = (M_ColorTransform *)node;
	ColorTransformStack *ptr = (ColorTransformStack  *)gf_node_get_private(node);
	RenderEffect2D *eff;
	eff = (RenderEffect2D *) rs;

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

	c_changed = 0;
	if (gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) {
		gf_cmx_set(&ptr->cmat, 
			tr->mrr , tr->mrg, tr->mrb, tr->mra, tr->tr, 
			tr->mgr , tr->mgg, tr->mgb, tr->mga, tr->tg, 
			tr->mbr, tr->mbg, tr->mbb, tr->mba, tr->tb, 
			tr->mar, tr->mag, tr->mab, tr->maa, tr->ta); 
		c_changed = 1;
	}
	/*note we don't clear dirty flag, this is done in traversing*/
	if (ptr->cmat.identity) {
		group2d_traverse((GroupingNode2D *) ptr, tr->children, eff);
	} else {
		GF_ColorMatrix gf_cmx_bck;
		Bool prev_inv = eff->invalidate_all;
		/*if modified redraw all nodes*/
		if (c_changed) eff->invalidate_all = 1;
		gf_cmx_copy(&gf_cmx_bck, &eff->color_mat);
		gf_cmx_multiply(&eff->color_mat, &ptr->cmat);
		group2d_traverse((GroupingNode2D *) ptr, tr->children, eff);
		/*restore effects*/
		gf_cmx_copy(&eff->color_mat, &gf_cmx_bck);
		eff->invalidate_all = prev_inv;
	}
}
Esempio n. 6
0
static void RenderAnchor(GF_Node *node, void *rs, Bool is_destroy)
{
	AnchorStack *st = (AnchorStack *) gf_node_get_private(node);
	M_Anchor *an = (M_Anchor *) node;
	RenderEffect2D *eff = (RenderEffect2D *)rs;

	if (is_destroy) {
		R2D_UnregisterSensor(st->compositor, &st->hdl);
		if (st->compositor->interaction_sensors) st->compositor->interaction_sensors--;
		DeleteGroupingNode2D((GroupingNode2D *)st);
		free(st);
		return;
	}

	/*update enabled state*/
	if (gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) {
		st->enabled = 0;
		if (an->url.count && an->url.vals[0].url && strlen(an->url.vals[0].url) )
			st->enabled = 1;
	}
	/*note we don't clear dirty flag, this is done in traversing*/
	group2d_traverse((GroupingNode2D*)st, an->children, eff);
}
Esempio n. 7
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);
}
Esempio n. 8
0
static void RenderOrderedGroup(GF_Node *node, void *rs, Bool is_destroy)
{
	u32 i, count;
	GF_Node *child;
	Bool split_text_backup, invalidate_backup;
	M_OrderedGroup *og;
	u32 count2;
	GF_List *sensor_backup;
	SensorHandler *hsens;
	OrderedGroupStack *ogs = (OrderedGroupStack *) gf_node_get_private(node);
	RenderEffect2D *eff = (RenderEffect2D *)rs;

	if (is_destroy) {
		DeleteGroupingNode2D((GroupingNode2D *)ogs);
		if (ogs->priorities) free(ogs->priorities);
		free(ogs);
		return;
	}
	og = (M_OrderedGroup *) ogs->owner;

	if (!og->order.count) {
		group2d_traverse((GroupingNode2D*)ogs, og->children, eff);
		return;
	}
	count = gf_node_list_get_count(og->children);
	invalidate_backup = eff->invalidate_all;

	/*check whether the OrderedGroup node has changed*/
	if (gf_node_dirty_get(node) & GF_SG_NODE_DIRTY) {

		if (ogs->priorities) free(ogs->priorities);
		ogs->priorities = (struct og_pos*)malloc(sizeof(struct og_pos)*count);
		for (i=0; i<count; i++) {
			ogs->priorities[i].position = i;
			ogs->priorities[i].priority = (i<og->order.count) ? og->order.vals[i] : 0;
		}
		qsort(ogs->priorities, count, sizeof(struct og_pos), compare_priority);
		eff->invalidate_all = 1;
	}

	sensor_backup = NULL;
	if (gf_node_dirty_get(node) & GF_SG_CHILD_DIRTY) {
		/*rebuild sensor list*/
		if (gf_list_count(ogs->sensors)) {
			gf_list_del(ogs->sensors);
			ogs->sensors = gf_list_new();
		}

		for (i=0; i<count; i++) {
			child = (GF_Node*)gf_node_list_get_child(og->children, ogs->priorities[i].position);
			if (!child || !is_sensor_node(child) ) continue;
			hsens = get_sensor_handler(child);
			if (hsens) gf_list_add(ogs->sensors, hsens);
		}
	}

	/*if we have an active sensor at this level discard all sensors in current render context (cf VRML)*/
	count2 = gf_list_count(ogs->sensors);
	if (count2) {
		sensor_backup = eff->sensors;
		eff->sensors = gf_list_new();
		/*add sensor to effects*/	
		for (i=0; i <count2; i++) {
			SensorHandler *hsens = (SensorHandler *)gf_list_get(ogs->sensors, i);
			effect_add_sensor(eff, hsens, &eff->transform);
		}
	}
	gf_node_dirty_clear(node, 0);

	if (eff->parent == (GroupingNode2D *) ogs) {
		for (i=0; i<count; i++) {
			group2d_start_child((GroupingNode2D *) ogs);
			child = (GF_Node*)gf_node_list_get_child(og->children, ogs->priorities[i].position);
			gf_node_render(child, eff);
			group2d_end_child((GroupingNode2D *) ogs);
		}
	} else {
		split_text_backup = eff->text_split_mode;
		if (count>1) eff->text_split_mode = 0;
		for (i=0; i<count; i++) {
			child = (GF_Node*)gf_node_list_get_child(og->children, ogs->priorities[i].position);
			gf_node_render(child, eff);
		}
		eff->text_split_mode = split_text_backup;
	}

	/*restore effect*/
	invalidate_backup = eff->invalidate_all;
	if (count2) {
		/*destroy current effect list and restore previous*/
		effect_reset_sensors(eff);
		gf_list_del(eff->sensors);
		eff->sensors = sensor_backup;
	}
}
Esempio n. 9
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);
}