Beispiel #1
0
static void svg_sani_render_path(GF_Node *node, void *rs, Bool is_destroy)
{
	SVG_SANI_pathElement *path = (SVG_SANI_pathElement *)node;
	Drawable *cs = (Drawable *)gf_node_get_private(node);
	RenderEffect2D *eff = (RenderEffect2D *)rs;

	if (is_destroy) {
		svg_sani_destroy_path(node);
		return;
	}
	if (eff->traversing_mode==TRAVERSE_DRAW) {
		drawable_draw(eff);
		return;
	}
	else if (eff->traversing_mode==TRAVERSE_PICK) {
		drawable_pick(eff);
		return;
	}

	svg_sani_render_base(node, eff);

	if (gf_node_dirty_get(node) & GF_SG_SVG_GEOMETRY_DIRTY) {
#if USE_GF_PATH
		cs->path = &path->d;
#else
		drawable_reset_path(cs);
		gf_svg_path_build(cs->path, path->d.commands, path->d.points);
#endif
		if (path->fill_rule==GF_PATH_FILL_ZERO_NONZERO) cs->path->flags |= GF_PATH_FILL_ZERO_NONZERO;

		gf_node_dirty_clear(node, GF_SG_SVG_GEOMETRY_DIRTY);
		cs->flags |= DRAWABLE_HAS_CHANGED;
	}
	svg_sani_DrawablePostRender(cs, (SVG_SANI_TransformableElement *)path, eff, 0, (path->pathLength.type==SVG_NUMBER_VALUE) ? path->pathLength.value : 0);
}
Beispiel #2
0
void compositor_extrude_text(GF_Node *node, GF_TraverseState *tr_state, GF_Mesh *mesh, MFVec3f *thespine, Fixed creaseAngle, Bool begin_cap, Bool end_cap, MFRotation *spine_ori, MFVec2f *spine_scale, Bool txAlongSpine)
{
	u32 i, count;
	Fixed min_cx, min_cy, width_cx, width_cy;
	TextStack *st = (TextStack *) gf_node_get_private(node);

	/*rebuild text node*/
	if (gf_node_dirty_get(node)) {
		ParentNode2D *parent = tr_state->parent;
		tr_state->parent = NULL;
		text_clean_paths(tr_state->visual->compositor, st);
		drawable_reset_path(st->graph);
		gf_node_dirty_clear(node, 0);
		build_text(st, (M_Text *)node, tr_state);
		tr_state->parent = parent;
	}

	min_cx = st->bounds.x;
	min_cy = st->bounds.y - st->bounds.height;
	width_cx = st->bounds.width;
	width_cy = st->bounds.height;

	mesh_reset(mesh);
	count = gf_list_count(st->spans);
	for (i=0; i<count; i++) {
		GF_TextSpan *span = (GF_TextSpan *)gf_list_get(st->spans, i);
		GF_Path *span_path = gf_font_span_create_path(span);
		mesh_extrude_path_ext(mesh, span_path, thespine, creaseAngle, min_cx, min_cy, width_cx, width_cy, begin_cap, end_cap, spine_ori, spine_scale, txAlongSpine);
		gf_path_del(span_path);
	}
	mesh_update_bounds(mesh);
	gf_mesh_build_aabbtree(mesh);
}
Beispiel #3
0
static void svg_sani_render_line(GF_Node *node, void *rs, Bool is_destroy)
{
	SVG_SANI_lineElement *line = (SVG_SANI_lineElement *)node;
	Drawable *cs = (Drawable *)gf_node_get_private(node);
	RenderEffect2D *eff = (RenderEffect2D *)rs;

	if (is_destroy) {
		DestroyDrawableNode(node);
		return;
	}
	if (eff->traversing_mode==TRAVERSE_DRAW) {
		drawable_draw(eff);
		return;
	}
	else if (eff->traversing_mode==TRAVERSE_PICK) {
		drawable_pick(eff);
		return;
	}

	svg_sani_render_base(node, (RenderEffect2D *)rs);

	if (gf_node_dirty_get(node) & GF_SG_SVG_GEOMETRY_DIRTY) {
		drawable_reset_path(cs);
		gf_path_add_move_to(cs->path, line->x1.value, line->y1.value);
		gf_path_add_line_to(cs->path, line->x2.value, line->y2.value);
		gf_node_dirty_clear(node, GF_SG_SVG_GEOMETRY_DIRTY);
		cs->flags |= DRAWABLE_HAS_CHANGED;
	}
	svg_sani_DrawablePostRender(cs, (SVG_SANI_TransformableElement *)line, (RenderEffect2D *)rs, 0, 0);
}
Beispiel #4
0
static void RenderCurve2D(SFNode *node, void *rs)
{
	DrawableContext *ctx;
	M_Curve2D *c2D = (M_Curve2D *)node;
	Drawable *cs = Node_GetPrivate(node);
	RenderEffect2D *eff = rs;

	if (!c2D->point) return;


	if (Node_GetDirty(node)) {
		drawable_reset_path(cs);
		cs->path->resolution = eff->surface->render->compositor->base_curve_resolution;
		cs->path->fineness = c2D->fineness;
		if (eff->surface->render->compositor->high_speed)  cs->path->fineness /= 2;
		build_curve2D(cs, c2D);
		Node_ClearDirty(node);
		cs->node_changed = 1;
	}

	ctx = drawable_init_context(cs, eff);
	if (!ctx) return;
	drawctx_store_original_bounds(ctx);
	drawable_finalize_render(ctx, eff);
}
Beispiel #5
0
static void RenderRectangle(SFNode *node, void *reff)
{
	DrawableContext *ctx;
	Drawable *rs = Node_GetPrivate(node);
	RenderEffect2D *eff = reff;

	if (Node_GetDirty(node)) {
		drawable_reset_path(rs);
		m4_path_add_rectangle(rs->path, 0, 0, ((M_Rectangle *) node)->size.x, ((M_Rectangle *) node)->size.y);
		Node_ClearDirty(node);
		rs->node_changed = 1;
	}
	ctx = drawable_init_context(rs, eff);
	if (!ctx) return;
	
	ctx->transparent = 0;
	/*if not filled, transparent*/
	if (!ctx->aspect.filled) {
		ctx->transparent = 1;
	} 
	/*if alpha, transparent*/
	else if (M4C_A(ctx->aspect.fill_color) != 0xFF) {
		ctx->transparent = 1;
	} 
	/*if rotated, transparent (doesn't fill bounds)*/
	else if (ctx->transform.m[1] || ctx->transform.m[3]) {
		ctx->transparent = 1;
	}
	else if (!eff->color_mat.identity) 
		ctx->transparent = 1;	

	drawctx_store_original_bounds(ctx);
	drawable_finalize_render(ctx, eff);
}
Beispiel #6
0
static void svg_ellipse_rebuild(GF_Node *node, Drawable *stack, SVGAllAttributes *atts)
{
	drawable_reset_path(stack);
	gf_path_add_ellipse(stack->path, (atts->cx ? atts->cx->value : 0), 
								  (atts->cy ? atts->cy->value : 0), 
								  (atts->rx ? 2*atts->rx->value : 0), 
								  (atts->ry ? 2*atts->ry->value : 0));
}
Beispiel #7
0
static void ellipse_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state)
{
	if (gf_node_dirty_get(node)) {
		drawable_reset_path(stack);
		gf_path_add_ellipse(stack->path, 0, 0, ((M_Ellipse *) node)->radius.x*2, ((M_Ellipse *) node)->radius.y*2);
		gf_node_dirty_clear(node, 0);
		drawable_mark_modified(stack, tr_state);
	}
}
Beispiel #8
0
static void svg_path_rebuild(GF_Node *node, Drawable *stack, SVGAllAttributes *atts)
{
#if USE_GF_PATH
	drawable_reset_path_outline(stack);
	stack->path = atts->d;
#else
	drawable_reset_path(stack);
	gf_svg_path_build(stack->path, atts->d->commands, atts->d->points);
#endif
}
Beispiel #9
0
static void circle_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state)
{
	if (gf_node_dirty_get(node)) {
		Fixed a = ((M_Circle *) node)->radius * 2;
		drawable_reset_path(stack);
		gf_path_add_ellipse(stack->path, 0, 0, a, a);
		gf_node_dirty_clear(node, 0);
		drawable_mark_modified(stack, tr_state);
	}
}
Beispiel #10
0
static void rectangle_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state)
{
	/*if modified update node - we don't update for other traversing mode in order not to mess up the dirty
	rect tracking (otherwise we would miss geometry changes with same bounds)*/
	if (gf_node_dirty_get(node)) {
		drawable_reset_path(stack);
		gf_path_add_rect_center(stack->path, 0, 0, ((M_Rectangle *) node)->size.x, ((M_Rectangle *) node)->size.y);
		gf_node_dirty_clear(node, 0);
		drawable_mark_modified(stack, tr_state);
	}
}
Beispiel #11
0
static void svg_rect_rebuild(GF_Node *node, Drawable *stack, SVGAllAttributes *atts)
{
	Fixed rx = (atts->rx ? atts->rx->value : 0);
	Fixed ry = (atts->ry ? atts->ry->value : 0);
	Fixed x = (atts->x ? atts->x->value : 0);
	Fixed y = (atts->y ? atts->y->value : 0);
	Fixed width = (atts->width ? atts->width->value : 0);
	Fixed height = (atts->height ? atts->height->value : 0);

	drawable_reset_path(stack);
	if (!width || !height) return;

	/*we follow SVG 1.1 and not 1.2 !!*/
	if (rx || ry) {
		Fixed cx, cy;
		if (rx >= width/2) rx = width/2;
		if (ry >= height/2) ry = height/2;
		if (rx == 0) rx = ry;
		if (ry == 0) ry = rx;
		gf_path_add_move_to(stack->path, x+rx, y);

		if (width-rx!=rx)
			gf_path_add_line_to(stack->path, x+width-rx, y);

		cx = x+width-rx; cy = y+ry;
		svg_rect_add_arc(stack->path, x+width, y+ry, cx, cy, rx, ry);
		
		if (height-ry!=ry)
			gf_path_add_line_to(stack->path, x+width, y+height-ry);

		cx = x+width-rx; cy = y+height-ry;
		svg_rect_add_arc(stack->path, x+width-rx, y+height, cx, cy, rx, ry);
		
		if (width-rx!=rx)
			gf_path_add_line_to(stack->path, x+rx, y+height);

		cx = x+rx; cy = y+height-ry;
		svg_rect_add_arc(stack->path, x, y+height-ry, cx, cy, rx, ry);
		
		if (height-ry!=ry)
			gf_path_add_line_to(stack->path, x, y+ry);

		cx = x+rx; cy = y+ry;
		svg_rect_add_arc(stack->path, x+rx, y, cx, cy, rx, ry);

		gf_path_close(stack->path);
	} else {
		gf_path_add_move_to(stack->path, x, y);
		gf_path_add_line_to(stack->path, x+width, y);		
		gf_path_add_line_to(stack->path, x+width, y+height);		
		gf_path_add_line_to(stack->path, x, y+height);		
		gf_path_close(stack->path);		
	}
}
Beispiel #12
0
void text_clean_paths(GF_Compositor *compositor, TextStack *stack)
{
	GF_TextSpan *span;
	/*delete all path objects*/
	while (gf_list_count(stack->spans)) {
		span = (GF_TextSpan*) gf_list_get(stack->spans, 0);
		gf_list_rem(stack->spans, 0);
		gf_font_manager_delete_span(compositor->font_manager, span);
	}
	stack->bounds.width = stack->bounds.height = 0;
	drawable_reset_path(stack->graph);
}
Beispiel #13
0
static void disk2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state)
{
	if (gf_node_dirty_get(node)) {
		Fixed a = ((X_Disk2D *) node)->outerRadius * 2;
		drawable_reset_path(stack);
		gf_path_add_ellipse(stack->path, 0, 0, a, a);
		a = ((X_Disk2D *) node)->innerRadius * 2;
		if (a) gf_path_add_ellipse(stack->path, 0, 0, a, a);
		gf_node_dirty_clear(node, 0);
		drawable_mark_modified(stack, tr_state);
	}
}
Beispiel #14
0
static void arc2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state)
{
	if (gf_node_dirty_get(node)) {
		drawable_reset_path(stack);
		if (gf_node_get_tag(node)==TAG_X3D_Arc2D) {
			X_Arc2D *a = (X_Arc2D *) node;
			gf_path_add_arc(stack->path, a->radius, a->startAngle, a->endAngle, 0);
		} else {
			X_ArcClose2D *a = (X_ArcClose2D *) node;
			gf_path_add_arc(stack->path, a->radius, a->startAngle, a->endAngle, !stricmp(a->closureType.buffer, "PIE") ? 2 : 1);
		}
		gf_node_dirty_clear(node, 0);
		drawable_mark_modified(stack, tr_state);
	}
}
Beispiel #15
0
static void polyline2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state)
{
	if (gf_node_dirty_get(node)) {
		u32 i;
		X_Polyline2D *a = (X_Polyline2D *) node;
		drawable_reset_path(stack);
		for (i=0; i<a->lineSegments.count; i++) {
			if (i) {
				gf_path_add_line_to(stack->path, a->lineSegments.vals[i].x, a->lineSegments.vals[i].y);
			} else {
				gf_path_add_move_to(stack->path, a->lineSegments.vals[i].x, a->lineSegments.vals[i].y);
			}
		}
		gf_node_dirty_clear(node, 0);
		drawable_mark_modified(stack, tr_state);
	}
}
Beispiel #16
0
static void RenderEllipse(SFNode *node, void *rs)
{
	DrawableContext *ctx;
	Drawable *cs = Node_GetPrivate(node);
	RenderEffect2D *eff = rs;

	if (Node_GetDirty(node)) {
		drawable_reset_path(cs);
		m4_path_add_ellipse(cs->path, ((M_Ellipse *) node)->radius.x, ((M_Ellipse *) node)->radius.y);
		Node_ClearDirty(node);
		cs->node_changed = 1;
	}
	ctx = drawable_init_context(cs, eff);
	if (!ctx) return;
	
	drawctx_store_original_bounds(ctx);
	drawable_finalize_render(ctx, eff);
}
Beispiel #17
0
static void triangleset2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state)
{
	if (gf_node_dirty_get(node)) {
		u32 i, count;
		X_TriangleSet2D *p = (X_TriangleSet2D *)node;
		drawable_reset_path(stack);
		count = p->vertices.count;
		while (count%3) count--;
		for (i=0; i<count; i+=3) {
			gf_path_add_move_to(stack->path, p->vertices.vals[i].x, p->vertices.vals[i].y);
			gf_path_add_line_to(stack->path, p->vertices.vals[i+1].x, p->vertices.vals[i+1].y);
			gf_path_add_line_to(stack->path, p->vertices.vals[i+2].x, p->vertices.vals[i+2].y);
			gf_path_close(stack->path);
		}
		gf_node_dirty_clear(node, 0);
		drawable_mark_modified(stack, tr_state);
	}
}
static void ifs2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state)
{
	u32 i;
	SFVec2f *pts;
	u32 ci_count, c_count;
	Bool started;
	M_IndexedFaceSet2D *ifs2D;
	M_Coordinate2D *coord;

	if (! gf_node_dirty_get(node)) return;

	ifs2D = (M_IndexedFaceSet2D *)node;
	coord = (M_Coordinate2D *)ifs2D->coord;
	drawable_reset_path(stack);
	gf_node_dirty_clear(node, 0);
	drawable_mark_modified(stack, tr_state);


	c_count = coord->point.count;
	ci_count = ifs2D->coordIndex.count;
	pts = coord->point.vals;

	if (ci_count > 0) {
		started = 0;
		for (i=0; i < ci_count; i++) {
			if (ifs2D->coordIndex.vals[i] == -1) {
				gf_path_close(stack->path);
				started = 0;
			} else if (!started) {
				started = 1;
				gf_path_add_move_to_vec(stack->path, &pts[ifs2D->coordIndex.vals[i]]);
			} else {
				gf_path_add_line_to_vec(stack->path, &pts[ifs2D->coordIndex.vals[i]]);
			}
		}
		if (started) gf_path_close(stack->path);
	} else if (c_count) {
		gf_path_add_move_to_vec(stack->path, &pts[0]);
		for (i=1; i < c_count; i++) {
			gf_path_add_line_to_vec(stack->path, &pts[i]);
		}
		gf_path_close(stack->path);
	}
}
Beispiel #19
0
static void svg_polyline_rebuild(GF_Node *node, Drawable *stack, SVGAllAttributes *atts)
{
	u32 i, nbPoints;
	drawable_reset_path(stack);
	if (atts->points) 
		nbPoints = gf_list_count(*atts->points);
	else 
		nbPoints = 0;

	if (nbPoints) {
		SVG_Point *p = (SVG_Point *)gf_list_get(*atts->points, 0);
		gf_path_add_move_to(stack->path, p->x, p->y);
		for (i = 1; i < nbPoints; i++) {
			p = (SVG_Point *)gf_list_get(*atts->points, i);
			gf_path_add_line_to(stack->path, p->x, p->y);
		}
	} else {
		gf_path_add_move_to(stack->path, 0, 0);
	}
}
Beispiel #20
0
static void svg_sani_render_polygon(GF_Node *node, void *rs, Bool is_destroy)
{
	SVG_SANI_polygonElement *polygon = (SVG_SANI_polygonElement *)node;
	Drawable *cs = (Drawable *)gf_node_get_private(node);
	RenderEffect2D *eff = (RenderEffect2D *)rs;

	if (is_destroy) {
		DestroyDrawableNode(node);
		return;
	}
	if (eff->traversing_mode==TRAVERSE_DRAW) {
		drawable_draw(eff);
		return;
	}
	else if (eff->traversing_mode==TRAVERSE_PICK) {
		drawable_pick(eff);
		return;
	}

	svg_sani_render_base(node, (RenderEffect2D *)rs);

	if (gf_node_dirty_get(node) & GF_SG_SVG_GEOMETRY_DIRTY) {
		u32 i;
		u32 nbPoints = gf_list_count(polygon->points);
		drawable_reset_path(cs);
		if (nbPoints) {
			SVG_Point *p = (SVG_Point *)gf_list_get(polygon->points, 0);
			gf_path_add_move_to(cs->path, p->x, p->y);
			for (i = 1; i < nbPoints; i++) {
				p = (SVG_Point *)gf_list_get(polygon->points, i);
				gf_path_add_line_to(cs->path, p->x, p->y);
			}
			gf_path_close(cs->path);
		} else {
			gf_path_add_move_to(cs->path, 0, 0);
		}
		gf_node_dirty_clear(node, GF_SG_SVG_GEOMETRY_DIRTY);
		cs->flags |= DRAWABLE_HAS_CHANGED;
	}
	svg_sani_DrawablePostRender(cs, (SVG_SANI_TransformableElement *)polygon, (RenderEffect2D *)rs, 0, 0);
}
Beispiel #21
0
static void pointset2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state)
{
	u32 i;
	Fixed w, h;
	M_Coordinate2D *coord;

	if (!gf_node_dirty_get(node)) return;
	coord = (M_Coordinate2D *) ((M_PointSet2D *)node)->coord;

	drawable_reset_path(stack);

	get_point_size(&tr_state->transform, &w, &h);
	/*for PS2D don't add to avoid too  much antialiasing, just try to fill the given pixel*/
	for (i=0; i < coord->point.count; i++)
		gf_path_add_rect(stack->path, coord->point.vals[i].x, coord->point.vals[i].y, w, h);

	stack->path->flags |= GF_PATH_FILL_ZERO_NONZERO;

	gf_node_dirty_clear(node, 0);
	drawable_mark_modified(stack, tr_state);
}
Beispiel #22
0
static void ils2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state)
{
	u32 i;
	Bool started;
	SFVec2f *pts;
	M_IndexedLineSet2D *ils2D;
	M_Coordinate2D *coord;

	if (! gf_node_dirty_get(node)) return;

	drawable_reset_path(stack);
	gf_node_dirty_clear(node, 0);
	drawable_mark_modified(stack, tr_state);

	ils2D = (M_IndexedLineSet2D *)node;
	coord = (M_Coordinate2D *)ils2D->coord;

	pts = coord->point.vals;
	if (ils2D->coordIndex.count > 0) {
		started = 0;
		for (i=0; i < ils2D->coordIndex.count; i++) {
			/*NO close on ILS2D*/
			if (ils2D->coordIndex.vals[i] == -1) {
				started = 0;
			} else if (!started) {
				started = 1;
				gf_path_add_move_to(stack->path, pts[ils2D->coordIndex.vals[i]].x, pts[ils2D->coordIndex.vals[i]].y);
			} else {
				gf_path_add_line_to(stack->path, pts[ils2D->coordIndex.vals[i]].x, pts[ils2D->coordIndex.vals[i]].y);
			}
		}
	} else if (coord->point.count) {
		gf_path_add_move_to(stack->path, pts[0].x, pts[0].y);
		for (i=1; i < coord->point.count; i++) {
			gf_path_add_line_to(stack->path, pts[i].x, pts[i].y);
		}
	}
	stack->path->flags |= GF_PATH_FILL_ZERO_NONZERO;
}
Beispiel #23
0
static void Bitmap_BuildGraph(BitmapStack *st, DrawableContext *ctx, RenderEffect2D *eff)
{
	M_Bitmap *bmp = (M_Bitmap *)st->graph->owner;
	M4Matrix2D mat;
	Float w , h;

	w = ctx->h_texture->active_window.width;
	h = ctx->h_texture->active_window.height;

	/*get size with scale*/
	drawable_reset_path(st->graph);
	/*reverse meterMetrics conversion*/
	mx2d_init(mat);
	if (!eff->is_pixel_metrics) mx2d_add_scale(&mat, eff->min_hsize, eff->min_hsize);
	mx2d_inverse(&mat);
	/*the spec says STRICTLY positive or -1, but some content use 0...*/
	mx2d_add_scale(&mat, (bmp->scale.x>=0) ? bmp->scale.x : 1, (bmp->scale.y>=0) ? bmp->scale.y : 1);
	mx2d_apply_coords(&mat, &w, &h);
	m4_path_add_rectangle(st->graph->path, 0, 0, w, h);

	m4_rect_center(&ctx->original, w, h);
}
Beispiel #24
0
static void RenderILS2D(SFNode *node, void *rs)
{
	DrawableContext *ctx;
	M_IndexedLineSet2D *ils2D = (M_IndexedLineSet2D *)node;
	Drawable *cs = Node_GetPrivate(node);
	RenderEffect2D *eff = rs;

	if (!ils2D->coord) return;

	if (Node_GetDirty(node)) {
		drawable_reset_path(cs);
		build_graph(cs, ils2D);
		Node_ClearDirty(node);
		cs->node_changed = 1;
	}

	ctx = drawable_init_context(cs, eff);
	if (!ctx) return;
	/*ILS2D are NEVER filled*/
	ctx->aspect.filled = 0;
	drawctx_store_original_bounds(ctx);
	drawable_finalize_render(ctx, eff);
}
Beispiel #25
0
static void RenderPointSet2D(SFNode *node, void *rs)
{
	DrawableContext *ctx;
	M_PointSet2D *ps2D = (M_PointSet2D *)node;
	Drawable *cs = Node_GetPrivate(node);
	RenderEffect2D *eff = rs;

	if (!ps2D->coord) return;

	if (Node_GetDirty(node)) {
		drawable_reset_path(cs);
		build_graph(cs, &eff->transform, ps2D);
		Node_ClearDirty(node);
		cs->node_changed = 1;
	}

	ctx = drawable_init_context(cs, eff);
	if (!ctx) return;
	ctx->aspect.filled = 1;
	ctx->aspect.has_line = 0;
	drawctx_store_original_bounds(ctx);
	drawable_finalize_render(ctx, eff);
}
Beispiel #26
0
void curve2d_check_changes(GF_Node *node, Drawable *stack, GF_TraverseState *tr_state, MFInt32 *idx)
{
	M_Curve2D *c2D;
	SFVec2f orig, ct_orig, ct_end, end;
	u32 cur_index, i, remain, type_count, pt_count;
	SFVec2f *pts;
	M_Coordinate2D *coord;

	c2D = (M_Curve2D *)node;
	coord = (M_Coordinate2D *)c2D->point;
	drawable_reset_path(stack);
	if (!coord) return;

	stack->path->fineness = c2D->fineness;
	if (tr_state->visual->compositor->high_speed)  stack->path->fineness /= 2;


	pts = coord->point.vals;
	if (!pts)
		return;

	cur_index = c2D->type.count ? 1 : 0;
	/*if the first type is a moveTo skip initial moveTo*/
	i=0;
	if (cur_index) {
		while (c2D->type.vals[i]==0) i++;
	}
	ct_orig = orig = pts[ GET_IDX(i) ];

	gf_path_add_move_to(stack->path, orig.x, orig.y);

	pt_count = coord->point.count;
	type_count = c2D->type.count;
	for (; i<type_count; i++) {

		switch (c2D->type.vals[i]) {
		/*moveTo, 1 point*/
		case 0:
			CHECK_VALID_C2D(0);
			orig = pts[ GET_IDX(cur_index) ];
			if (i) gf_path_add_move_to(stack->path, orig.x, orig.y);
			cur_index += 1;
			break;
		/*lineTo, 1 point*/
		case 1:
			CHECK_VALID_C2D(0);
			end = pts[ GET_IDX(cur_index) ];
			gf_path_add_line_to(stack->path, end.x, end.y);
			orig = end;
			cur_index += 1;
			break;
		/*curveTo, 3 points*/
		case 2:
			CHECK_VALID_C2D(2);
			ct_orig = pts[ GET_IDX(cur_index) ];
			ct_end = pts[ GET_IDX(cur_index+1) ];
			end = pts[ GET_IDX(cur_index+2) ];
			gf_path_add_cubic_to(stack->path, ct_orig.x, ct_orig.y, ct_end.x, ct_end.y, end.x, end.y);
			cur_index += 3;
			ct_orig = ct_end;
			orig = end;
			break;
		/*nextCurveTo, 2 points (cf spec)*/
		case 3:
			CHECK_VALID_C2D(1);
			ct_orig.x = 2*orig.x - ct_orig.x;
			ct_orig.y = 2*orig.y - ct_orig.y;
			ct_end = pts[ GET_IDX(cur_index) ];
			end = pts[ GET_IDX(cur_index+1) ];
			gf_path_add_cubic_to(stack->path, ct_orig.x, ct_orig.y, ct_end.x, ct_end.y, end.x, end.y);
			cur_index += 2;
			ct_orig = ct_end;
			orig = end;
			break;

		/*all XCurve2D specific*/

		/*CW and CCW ArcTo*/
		case 4:
		case 5:
			CHECK_VALID_C2D(2);
			ct_orig = pts[ GET_IDX(cur_index) ];
			ct_end = pts[ GET_IDX(cur_index+1) ];
			end = pts[ GET_IDX(cur_index+2) ];
			gf_path_add_arc_to(stack->path, end.x, end.y, ct_orig.x, ct_orig.y, ct_end.x, ct_end.y, (c2D->type.vals[i]==5) ? 1 : 0);
			cur_index += 3;
			ct_orig = ct_end;
			orig = end;
			break;
		/*ClosePath*/
		case 6:
			gf_path_close(stack->path);
			break;
		/*quadratic CurveTo, 2 points*/
		case 7:
			CHECK_VALID_C2D(1);
			ct_end = pts[ GET_IDX(cur_index) ];
			end = pts[ GET_IDX(cur_index+1) ];
			gf_path_add_quadratic_to(stack->path, ct_end.x, ct_end.y, end.x, end.y);
			cur_index += 2;
			ct_orig = ct_end;
			orig = end;
			break;
		}
	}

	/*what's left is an N-bezier spline*/
	if (!idx && (pt_count > cur_index) ) {
		/*first moveto*/
		if (!cur_index) cur_index++;

		remain = pt_count - cur_index;

		if (remain>1)
			gf_path_add_bezier(stack->path, &pts[cur_index], remain);
	}

	gf_node_dirty_clear(node, 0);
	drawable_mark_modified(stack, tr_state);
}
Beispiel #27
0
static void svg_traverse_text(GF_Node *node, void *rs, Bool is_destroy)
{
	SVGPropertiesPointers backup_props;
	u32 backup_flags;
	GF_Matrix2D backup_matrix;
	GF_Matrix mx3d;
	GF_ChildNodeItem *child;
	DrawableContext *ctx;
	SVG_TextStack *st = (SVG_TextStack *)gf_node_get_private(node);
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;
	SVG_Element *text = (SVG_Element *)node;
	SVGAllAttributes atts;
	u32 i,imax;
	Fixed * lw;

	if (is_destroy) {
		drawable_del(st->drawable);
		svg_reset_text_stack(st);
		gf_list_del(st->spans);
		gf_free(st);
		return;
	}

	if (tr_state->traversing_mode==TRAVERSE_DRAW_2D) {
		svg_text_draw_2d(st, tr_state);
		return;
	}
	else if (tr_state->traversing_mode==TRAVERSE_GET_TEXT) {
		tr_state->text_parent = node;
		gf_font_spans_get_selection(node, st->spans, tr_state);
		/*and browse children*/
		child = ((GF_ParentNode *) text)->children;
		while (child) {
			switch  (gf_node_get_tag(child->node)) {
			case TAG_SVG_tspan:
				gf_node_traverse(child->node, tr_state);
				break;
			}
			child = child->next;
		}
		tr_state->text_parent = NULL;
		return;
	}

	gf_svg_flatten_attributes(text, &atts);
	if (!compositor_svg_traverse_base(node, &atts, tr_state, &backup_props, &backup_flags))
		return;

	tr_state->in_svg_text++;
	tr_state->text_parent = node;

	if (tr_state->traversing_mode==TRAVERSE_PICK) {
		compositor_svg_apply_local_transformation(tr_state, &atts, &backup_matrix, &mx3d);
		if (*tr_state->svg_props->pointer_events!=SVG_POINTEREVENTS_NONE)
			gf_font_spans_pick(node, st->spans, tr_state, &st->bounds, 1, st->drawable);

		/*and browse children*/
		child = ((GF_ParentNode *) text)->children;
		while (child) {
			switch  (gf_node_get_tag(child->node)) {
			case TAG_SVG_tspan:
				gf_node_traverse(child->node, tr_state);
				break;
			}
			child = child->next;
		}
		memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
		compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx3d);
		tr_state->svg_flags = backup_flags;
		tr_state->text_parent = NULL;
		tr_state->in_svg_text--;
		return;
	}
	else if (tr_state->traversing_mode==TRAVERSE_GET_TEXT) {
		gf_font_spans_get_selection(node, st->spans, tr_state);
		memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
		tr_state->svg_flags = backup_flags;
		tr_state->text_parent = NULL;
		tr_state->in_svg_text--;
		return;
	}

	compositor_svg_apply_local_transformation(tr_state, &atts, &backup_matrix, &mx3d);

	if ( (st->prev_size != tr_state->svg_props->font_size->value) ||
	        (st->prev_flags != *tr_state->svg_props->font_style) ||
	        (st->prev_anchor != *tr_state->svg_props->text_anchor) ||
	        (gf_node_dirty_get(node) & (GF_SG_SVG_GEOMETRY_DIRTY | GF_SG_CHILD_DIRTY) )
	        || tr_state->visual->compositor->reset_fonts
	   ) {
		u32 mode;
		child = ((GF_ParentNode *) text)->children;

		svg_reset_text_stack(st);
		tr_state->text_end_x = 0;
		tr_state->text_end_y = 0;
		/*init the xml:space algo*/
		tr_state->last_char_type = 0;

		/*initialize x and y counters - stored at the traverse level for handling tspan & co*/
		if (atts.text_x) tr_state->count_x = gf_list_count(*atts.text_x);
		else tr_state->count_x=0;
		if (atts.text_y) tr_state->count_y = gf_list_count(*atts.text_y);
		else tr_state->count_y=0;
		if (atts.text_rotate) tr_state->count_rotate = gf_list_count(*atts.text_rotate);
		else tr_state->count_rotate=0;

		/*horizontal justifiers container*/
		tr_state->x_anchors = gf_list_new();

		/*compute length of all text blocks*/
		while (child) {
			svg_compute_text_width(child->node, &atts, tr_state);
			child=child->next;
		}

		/*apply justification of all blocks*/
		imax=gf_list_count(tr_state->x_anchors);
		for (i=0; i<imax; i++) {
			lw=gf_list_get(tr_state->x_anchors, i);
			svg_apply_text_anchor(tr_state, lw);
		}

		/*re-initialize x and y counters for final compute*/
		if (atts.text_x) tr_state->count_x = gf_list_count(*atts.text_x);
		else tr_state->count_x=0;
		if (atts.text_y) tr_state->count_y = gf_list_count(*atts.text_y);
		else tr_state->count_y=0;
		if (atts.text_rotate) tr_state->count_rotate = gf_list_count(*atts.text_rotate);
		else tr_state->count_rotate=0;
		tr_state->idx_rotate = 0;
		tr_state->chunk_index = 0;

		/*initialize current text position*/
		if (!tr_state->text_end_x) {
			SVG_Coordinate *xc = (atts.text_x ? (SVG_Coordinate *) gf_list_get(*atts.text_x, 0) : NULL);
			tr_state->text_end_x = (xc ? xc->value : 0);
		}
		if (!tr_state->text_end_y) {
			SVG_Coordinate *yc = (atts.text_y ? (SVG_Coordinate *) gf_list_get(*atts.text_y, 0) : NULL);
			tr_state->text_end_y = (yc ? yc->value : 0);
		}

		/*pass x and y to children*/
		tr_state->text_x = atts.text_x;
		tr_state->text_y = atts.text_y;
		tr_state->text_rotate = atts.text_rotate;

		drawable_reset_path(st->drawable);

		/*switch to bounds mode, and recompute children*/
		mode = tr_state->traversing_mode;
		tr_state->traversing_mode = TRAVERSE_GET_BOUNDS;
		tr_state->last_char_type = 0;

		child = ((GF_ParentNode *) text)->children;
		while (child) {
			svg_traverse_text_block(child->node, &atts, tr_state, st->spans);
			child = child->next;
		}
		tr_state->traversing_mode = mode;
		gf_node_dirty_clear(node, 0);
		drawable_mark_modified(st->drawable, tr_state);
		st->prev_size = tr_state->svg_props->font_size->value;
		st->prev_flags = *tr_state->svg_props->font_style;
		st->prev_anchor = *tr_state->svg_props->text_anchor;

		while (gf_list_count(tr_state->x_anchors)) {
			Fixed *f = gf_list_last(tr_state->x_anchors);
			gf_list_rem_last(tr_state->x_anchors);
			gf_free(f);
		}
		gf_list_del(tr_state->x_anchors);
		tr_state->x_anchors = NULL;

		svg_update_bounds(st);
	}

	if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) {
		if (!compositor_svg_is_display_off(tr_state->svg_props))
			tr_state->bounds = st->bounds;

	} else if ((tr_state->traversing_mode == TRAVERSE_SORT)
	           && !compositor_svg_is_display_off(tr_state->svg_props)
	           && (*(tr_state->svg_props->visibility) != SVG_VISIBILITY_HIDDEN)
	          ) {
		ctx = drawable_init_context_svg(st->drawable, tr_state);
		if (ctx) svg_finalize_sort(ctx, st, tr_state);

		/*and browse children*/
		child = ((GF_ParentNode *) text)->children;
		while (child) {
			switch  (gf_node_get_tag(child->node)) {
			case TAG_SVG_tspan:
				gf_node_traverse(child->node, tr_state);
				break;
			case TAG_SVG_switch:
				gf_node_traverse(child->node, tr_state);
				break;
			}
			child = child->next;
		}
	}
	tr_state->in_svg_text--;
	tr_state->text_parent = NULL;

	compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx3d);
	memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
	tr_state->svg_flags = backup_flags;
}
Beispiel #28
0
static void svg_circle_rebuild(GF_Node *node, Drawable *stack, SVGAllAttributes *atts)
{
	Fixed r = 2*(atts->r ? atts->r->value : 0);
	drawable_reset_path(stack);
	gf_path_add_ellipse(stack->path, (atts->cx ? atts->cx->value : 0), (atts->cy ? atts->cy->value : 0), r, r);
}
Beispiel #29
0
static void svg_line_rebuild(GF_Node *node, Drawable *stack, SVGAllAttributes *atts)
{
	drawable_reset_path(stack);
	gf_path_add_move_to(stack->path, (atts->x1 ? atts->x1->value : 0), (atts->y1 ? atts->y1->value : 0));
	gf_path_add_line_to(stack->path, (atts->x2 ? atts->x2->value : 0), (atts->y2 ? atts->y2->value : 0));
}
Beispiel #30
0
static void DrawBitmap(DrawableContext *ctx)
{
	u8 alpha;
	Render2D *sr;
	Bool use_hw, has_scale;
	M_Bitmap *bmp = (M_Bitmap *) ctx->node->owner;
	BitmapStack *st = (BitmapStack *) Node_GetPrivate(ctx->node->owner);


	sr = ctx->surface->render;
	/*bitmaps are NEVER rotated (forbidden in spec). In case a rotation was done we still display (reset the skew components)*/
	ctx->transform.m[1] = ctx->transform.m[3] = 0;

	has_scale = 0;
	if (bmp->scale.x>0 && bmp->scale.x!=1) has_scale = 1;
	if (bmp->scale.y>0 && bmp->scale.y!=1) has_scale = 1;

	use_hw = 1;
	alpha = M4C_A(ctx->aspect.fill_color);

	/*check if driver can handle alpha blit*/
	if (alpha!=255) {
		use_hw = sr->compositor->video_out->bHasAlpha;
		if (has_scale) use_hw = sr->compositor->video_out->bHasAlphaStretch;
	}
	/*for MatteTexture*/
	if (!ctx->cmat.identity || ctx->h_texture->has_cmat) use_hw = 0;

	/*to do - materialKey*/

	/*this is not a native texture, use graphics*/
	if (!ctx->h_texture->data) {
		use_hw = 0;
	} else {
		if (!ctx->surface->SupportsFormat || !ctx->surface->DrawBitmap ) use_hw = 0;
		/*format not supported directly, try with brush*/
		else if (!ctx->surface->SupportsFormat(ctx->surface, ctx->h_texture->pixelformat) ) use_hw = 0;
	}

	/*no HW, fall back to the graphics driver*/
	if (!use_hw) {
		drawable_reset_path(st->graph);
		m4_path_add_rectangle(st->graph->path, 0, 0, ctx->original.width, ctx->original.height);
		ctx->no_antialias = 1;
		VS2D_TexturePath(ctx->surface, st->graph->path, ctx);
		return;
	}

	/*direct rendering, render without clippers */
	if (ctx->surface->render->top_effect->trav_flags & TF_RENDER_DIRECT) {
		ctx->surface->DrawBitmap(ctx->surface, ctx->h_texture, &ctx->clip, &ctx->unclip);
	}
	/*render bitmap for all dirty rects*/
	else {
		u32 i;
		M4IRect clip;
		for (i=0; i<ctx->surface->to_redraw.count; i++) {
			/*there's an opaque region above, don't draw*/
			if (ctx->surface->draw_node_index<ctx->surface->to_redraw.opaque_node_index[i]) continue;
			clip = ctx->clip;
			m4_irect_intersect(&clip, &ctx->surface->to_redraw.list[i]);
			if (clip.width && clip.height) {
				ctx->surface->DrawBitmap(ctx->surface, ctx->h_texture, &clip, &ctx->unclip);
			}
		}
	}

}