static Bool composite2d_draw_bitmap(GF_VisualManager *visual, GF_TraverseState *tr_state, struct _drawable_context *ctx, GF_ColorKey *col_key)
{
	u8 alpha = 0xFF;
	GF_VideoSurface offscreen_dst, video_src;
	GF_Window src_wnd, dst_wnd;
	Bool use_blit, has_scale;
	CompositeTextureStack *st;

	if (visual->compositor->disable_composite_blit) return 0;

	if (!ctx->aspect.fill_texture) return 1;
	if (ctx->transform.m[0]<0) return 0;
	if (ctx->transform.m[4]<0) {
		if (!(ctx->flags & CTX_FLIPED_COORDS)) return 0;
	} else {
		if (ctx->flags & CTX_FLIPED_COORDS) return 0;
	}
	if (ctx->transform.m[1] || ctx->transform.m[3]) return 0;
#ifndef GPAC_DISABLE_VRML
	if ((ctx->flags & CTX_HAS_APPEARANCE) && ctx->appear && ((M_Appearance*)ctx->appear)->textureTransform)
		return 0;
#endif

	alpha = GF_COL_A(ctx->aspect.fill_color);
	/*THIS IS A HACK, will not work when setting filled=0, transparency and XLineProps*/
	if (!alpha) alpha = GF_COL_A(ctx->aspect.line_color);
	if (!alpha) return 1;

	st = (CompositeTextureStack *) gf_node_get_private(visual->offscreen);

	if (!compositor_texture_rectangles(visual, ctx->aspect.fill_texture, &ctx->bi->clip, &ctx->bi->unclip, &src_wnd, &dst_wnd, &use_blit, &has_scale)) return 1;

	memset(&video_src, 0, sizeof(GF_VideoSurface));
	video_src.height = ctx->aspect.fill_texture->height;
	video_src.width = ctx->aspect.fill_texture->width;
	video_src.pitch_x = 0;
	video_src.pitch_y = ctx->aspect.fill_texture->stride;
	video_src.pixel_format = ctx->aspect.fill_texture->pixelformat;
#ifdef GF_SR_USE_DEPTH
	if (ctx->aspect.fill_texture->pixelformat==GF_PIXEL_YUVD) video_src.pixel_format = GF_PIXEL_YV12;
#endif
	video_src.video_buffer = ctx->aspect.fill_texture->data;

	memset(&offscreen_dst, 0, sizeof(GF_VideoSurface));
	offscreen_dst.width = st->txh.width;
	offscreen_dst.height = st->txh.height;
	offscreen_dst.pitch_y = st->txh.stride;
	offscreen_dst.pixel_format = st->txh.pixelformat;
	offscreen_dst.video_buffer = st->txh.data;

	gf_stretch_bits(&offscreen_dst, &video_src, &dst_wnd, &src_wnd, alpha, 0, col_key, ctx->col_mat);
	return 1;
}
Beispiel #2
0
static void PointSet2D_Draw(GF_Node *node, GF_TraverseState *tr_state)
{
	GF_Path *path;
	Fixed alpha, w, h;
	u32 i;
	SFColor col;
	DrawableContext *ctx = tr_state->ctx;
	M_PointSet2D *ps2D = (M_PointSet2D *)node;
	M_Coordinate2D *coord = (M_Coordinate2D*) ps2D->coord;
	M_Color *color = (M_Color *) ps2D->color;

	/*never outline PS2D*/
	ctx->flags |= CTX_PATH_STROKE;
	if (!color || color->color.count<coord->point.count) {
		/*no texturing*/
		visual_2d_draw_path(tr_state->visual, ctx->drawable->path, ctx, NULL, NULL, tr_state);
		return;
	}

	get_point_size(&ctx->transform, &w, &h);

	path = gf_path_new();
	alpha = INT2FIX(GF_COL_A(ctx->aspect.line_color)) / 255;
	for (i = 0; i < coord->point.count; i++) {
		col = color->color.vals[i];
		ctx->aspect.line_color = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
		gf_path_add_rect_center(path, coord->point.vals[i].x, coord->point.vals[i].y, w, h);
		visual_2d_draw_path(tr_state->visual, path, ctx, NULL, NULL, tr_state);
		gf_path_reset(path);
		ctx->flags &= ~CTX_PATH_FILLED;
	}
	gf_path_del(path);
}
Beispiel #3
0
void VS2D_TexturePathText(VisualSurface2D *surf, DrawableContext *txt_ctx, GF_Path *path, GF_Rect *object_bounds, GF_HWTEXTURE hwtx, GF_Rect *gf_sr_texture_bounds)
{
	Fixed sS, sT;
	GF_Matrix2D gf_mx2d_txt;
	GF_Rect rc, orig_rc;
	u8 alpha, r, g, b;
	GF_ColorMatrix cmat;
	GF_Raster2D *r2d = surf->render->compositor->r2d;

	VS2D_SetOptions(surf->render, surf->the_surface, 0, 1);

	/*get original bounds*/
	orig_rc = *object_bounds;
	rc = *gf_sr_texture_bounds;

	/*get scaling ratio so that active texture view is stretched to original bounds (std 2D shape texture mapping in MPEG4)*/
	sS = gf_divfix(orig_rc.width, rc.width);
	sT = gf_divfix(orig_rc.height, rc.height);
	
	gf_mx2d_init(gf_mx2d_txt);
	gf_mx2d_add_scale(&gf_mx2d_txt, sS, sT);

	/*move to bottom-left corner of bounds */
	gf_mx2d_add_translation(&gf_mx2d_txt, (orig_rc.x), (orig_rc.y - orig_rc.height));

	/*move to final coordinate system*/	
	gf_mx2d_add_matrix(&gf_mx2d_txt, &txt_ctx->transform);

	/*set path transform, except for background2D node which is directly build in the final coord system*/
	r2d->stencil_set_matrix(hwtx, &gf_mx2d_txt);

	alpha = GF_COL_A(txt_ctx->aspect.fill_color);
	r = GF_COL_R(txt_ctx->aspect.fill_color);
	g = GF_COL_G(txt_ctx->aspect.fill_color);
	b = GF_COL_B(txt_ctx->aspect.fill_color);

	/*if col do a cxmatrix*/
	if (!r && !g && !b) {
		r2d->stencil_set_texture_alpha(hwtx, alpha);
	} else {
		r2d->stencil_set_texture_alpha(hwtx, 0xFF);
		memset(cmat.m, 0, sizeof(Fixed) * 20);
		cmat.m[4] = INT2FIX(r)/255;
		cmat.m[9] = INT2FIX(g)/255;
		cmat.m[14] = INT2FIX(b)/255;
		cmat.m[18] = INT2FIX(alpha)/255;
		cmat.identity = 0;
		r2d->stencil_set_color_matrix(hwtx, &cmat);
	}

	r2d->surface_set_matrix(surf->the_surface, &txt_ctx->transform);

	/*push path*/
	r2d->surface_set_path(surf->the_surface, path);

	VS2D_DoFill(surf, txt_ctx, hwtx);
	r2d->surface_set_path(surf->the_surface, NULL);
	txt_ctx->flags |= CTX_PATH_FILLED;
}
Beispiel #4
0
/**
 *	function DirectFBVid_DrawRectangle
 *	- using hardware accelerator to fill a rectangle
 **/
static void DirectFBVid_DrawRectangle(GF_VideoOutput *driv, u32 x, u32 y, u32 width, u32 height, GF_Color color)
{
	u8 r = GF_COL_R(color);
	u8 g = GF_COL_G(color);
	u8 b = GF_COL_B(color);
	u8 a = GF_COL_A(color);
	DirectFBVID();

	DirectFBVid_DrawRectangleWrapper(ctx, x, y, width, height, r, g, b, a);
}
static void visual_2d_draw_gradient(GF_VisualManager *visual, GF_Path *path, GF_TextureHandler *txh, struct _drawable_context *ctx, GF_TraverseState *tr_state, GF_Matrix2D *ext_mx, GF_Rect *orig_bounds)
{
	GF_Rect rc;
	GF_STENCIL stencil;
	GF_Matrix2D g_mat;
	GF_Raster2D *raster = visual->compositor->rasterizer;

	if (!txh) txh = ctx->aspect.fill_texture;

	gf_path_get_bounds(path, &rc);
	if (!rc.width || !rc.height || !txh->tx_io) return;

	if (orig_bounds) {
		txh->compute_gradient_matrix(txh, orig_bounds, &g_mat, 0);
	} else {
		txh->compute_gradient_matrix(txh, &rc, &g_mat, 0);
	}
	stencil = gf_sc_texture_get_stencil(txh);
	if (!stencil) return;

#ifndef GPAC_DISABLE_VRML
	if (ctx->flags & CTX_HAS_APPEARANCE) {
		GF_Matrix2D txt_mat;
		visual_2d_get_texture_transform(ctx->appear, txh, &txt_mat, (txh == ctx->aspect.fill_texture) ? 0 : 1, INT2FIX(txh->width), INT2FIX(txh->height));
		gf_mx2d_add_matrix(&g_mat, &txt_mat);
	}
#endif

	/*move to bottom-left corner of bounds */
	if (ext_mx) gf_mx2d_add_matrix(&g_mat, ext_mx);
	if (orig_bounds) gf_mx2d_add_translation(&g_mat, (orig_bounds->x), (orig_bounds->y - orig_bounds->height));

	gf_mx2d_add_matrix(&g_mat, &ctx->transform);

	raster->stencil_set_matrix(stencil, &g_mat);
	raster->stencil_set_color_matrix(stencil, ctx->col_mat);

	/*MPEG-4/VRML context or no fill info*/
	if (ctx->flags & CTX_HAS_APPEARANCE || !ctx->aspect.fill_color)
		raster->stencil_set_alpha(stencil, 0xFF);
	else
		raster->stencil_set_alpha(stencil, GF_COL_A(ctx->aspect.fill_color) );

	raster->surface_set_matrix(visual->raster_surface, &ctx->transform);
	txh->flags |= GF_SR_TEXTURE_USED;

	raster->surface_set_path(visual->raster_surface, path);
	visual_2d_fill_path(visual, ctx, stencil, tr_state, 0);
	raster->surface_set_path(visual->raster_surface, NULL);

	ctx->flags |= CTX_PATH_FILLED;
}
Beispiel #6
0
static void c2d_gl_fill_rect(void *cbk, u32 x, u32 y, u32 width, u32 height, GF_Color color)
{
#if defined(GPAC_USE_OGL_ES)
	GLfloat line[8];

	line[0] = FIX2FLT(x);
	line[1] = FIX2FLT(y);
	line[2] = FIX2FLT(x+width);
	line[3] = FIX2FLT(y);
	line[4] = FIX2FLT(x+width);
	line[5] = FIX2FLT(y+height);
	line[6] = FIX2FLT(x);
	line[7] = FIX2FLT(y+height);

	glEnable(GL_BLEND);
	glColor4ub(GF_COL_R(color), GF_COL_G(color), GF_COL_B(color), GF_COL_A(color));

	glVertexPointer(4, GL_FLOAT, 0, line);
	glEnableClientState(GL_VERTEX_ARRAY);
	glDrawArrays(GL_TRIANGLE_FAN, 0, 2);
	glDisableClientState(GL_VERTEX_ARRAY);

	glDisable(GL_BLEND);
#else
	glEnable(GL_BLEND);
	glColor4ub(GF_COL_R(color), GF_COL_G(color), GF_COL_B(color), GF_COL_A(color));
	glBegin(GL_TRIANGLES);
	glVertex2i(x,y);
	glVertex2i(x+width,y);
	glVertex2i(x+width,y+height);
	glEnd();
	glBegin(GL_TRIANGLES);
	glVertex2i(x,y);
	glVertex2i(x+width,y+height);
	glVertex2i(x,y+height);
	glEnd();
	glDisable(GL_BLEND);
#endif
}
Beispiel #7
0
void text_draw_2d(GF_Node *node, GF_TraverseState *tr_state)
{
	Bool force_texture;
	u32 hl_color;
	TextStack *st = (TextStack *) gf_node_get_private((GF_Node *) node);

	if (!GF_COL_A(tr_state->ctx->aspect.fill_color) && !tr_state->ctx->aspect.pen_props.width) return;

	text_get_draw_opt(node, st, &force_texture, &hl_color, &tr_state->ctx->aspect);

	tr_state->text_parent = node;
	gf_font_spans_draw_2d(st->spans, tr_state, hl_color, force_texture, &st->bounds);
	tr_state->text_parent = NULL;
}
Beispiel #8
0
void visual_2d_texture_path(GF_VisualManager *visual, GF_Path *path, struct _drawable_context *ctx, GF_TraverseState *tr_state)
{
#ifdef SKIP_DRAW
	return;
#endif
	if (!visual->is_attached || (ctx->flags & CTX_PATH_FILLED) || !ctx->aspect.fill_texture || visual->compositor->is_hidden) return;

	/*this is ambiguous in the spec, what if the material is filled and the texture is transparent ?
	let's draw, it's nicer */
#if 0
	if (GF_COL_A(ctx->aspect.fill_color) && ctx->aspect.fill_texture->transparent) {
		visual_2d_draw_path(visual, path, ctx, NULL, NULL);
		ctx->flags &= ~CTX_PATH_FILLED;
	}
#endif

	visual_2d_texture_path_extended(visual, path, NULL, ctx, NULL, NULL, tr_state);
}
Beispiel #9
0
void VS2D_TexturePath(VisualSurface2D *surf, GF_Path *path, struct _drawable_context *ctx)
{
#ifdef SKIP_DRAW
	return;
#endif
	if (!surf->the_surface || (ctx->flags & CTX_PATH_FILLED) || !ctx->h_texture || surf->render->compositor->is_hidden) return;

	/*this is ambiguous in the spec, what if the material is filled and the texture is transparent ?
	let's draw, it's nicer */
#if 0
	if (GF_COL_A(ctx->aspect.fill_color) && ctx->h_texture->transparent) {
		VS2D_DrawPath(surf, path, ctx, NULL, NULL);
		ctx->flags &= ~CTX_PATH_FILLED;
	}
#endif

	VS2D_TexturePathIntern(surf, path, NULL, ctx);
}
Beispiel #10
0
static void svg_sani_DrawablePostRender(Drawable *cs, SVG_SANI_TransformableElement *elt, RenderEffect2D *eff, 
									Bool rectangular, Fixed path_length)
{
	GF_FieldInfo info;
	GF_Matrix2D backup_matrix;
	DrawableContext *ctx;

	if (eff->traversing_mode == TRAVERSE_GET_BOUNDS) {
		gf_node_get_field_by_name(cs->node, "display", &info);
		if (*(SVG_Display *)info.far_ptr == SVG_DISPLAY_NONE) gf_path_get_bounds(cs->path, &eff->bounds);
		return;
	}

	gf_node_get_field_by_name(cs->node, "display", &info);
	if (*(SVG_Display *)info.far_ptr == SVG_DISPLAY_NONE) return;
		
	gf_node_get_field_by_name(cs->node, "visibility", &info);
	if (*(SVG_Visibility *)info.far_ptr == SVG_VISIBILITY_HIDDEN) return;

	gf_svg_sani_apply_local_transformation(eff, (GF_Node *)elt, &backup_matrix);

	gf_node_get_field_by_name(cs->node, "fill-rule", &info);
	if (*(SVG_FillRule *)info.far_ptr == SVG_FILLRULE_NONZERO)
		cs->path->flags |= GF_PATH_FILL_ZERO_NONZERO;
	else 
		cs->path->flags &= ~GF_PATH_FILL_ZERO_NONZERO;

	ctx = svg_sani_drawable_init_context(cs, eff);
	if (ctx) {
		if (rectangular) {
			if (ctx->h_texture && ctx->h_texture->transparent) {}
			else if (GF_COL_A(ctx->aspect.fill_color) != 0xFF) {}
			else if (ctx->transform.m[1] || ctx->transform.m[3]) {}
			else {
				ctx->flags &= ~CTX_IS_TRANSPARENT;
			}
		}
		if (path_length) ctx->aspect.pen_props.path_length = path_length;
		drawable_finalize_render(ctx, eff, NULL);
	}

	gf_svg_sani_restore_parent_transformation(eff, &backup_matrix);
}
Beispiel #11
0
Bool c2d_gl_draw_bitmap(GF_VisualManager *visual, GF_TraverseState *tr_state, DrawableContext *ctx, GF_ColorKey *col_key)
{
	u8 alpha = GF_COL_A(ctx->aspect.fill_color);

	if (ctx->transform.m[1] || ctx->transform.m[3]) return 0;

	visual_3d_set_state(visual, V3D_STATE_LIGHT, 0);
	visual_3d_enable_antialias(visual, 0);
	if (alpha && (alpha != 0xFF)) {
		visual_3d_set_material_2d_argb(visual, ctx->aspect.fill_color);
		gf_sc_texture_set_blend_mode(ctx->aspect.fill_texture, TX_MODULATE);
	} else if (gf_sc_texture_is_transparent(ctx->aspect.fill_texture)) {
		gf_sc_texture_set_blend_mode(ctx->aspect.fill_texture, TX_REPLACE);
	} else {
		visual_3d_set_state(visual, V3D_STATE_BLEND, 0);
	}
	/*ignore texture transform for bitmap*/
	tr_state->mesh_num_textures = gf_sc_texture_enable(ctx->aspect.fill_texture, tr_state->appear ? ((M_Appearance *)tr_state->appear)->textureTransform : NULL);
	if (tr_state->mesh_num_textures) {
		SFVec2f size, orig;
		GF_Mesh *mesh;
		size.x = ctx->bi->unclip.width;
		size.y = ctx->bi->unclip.height;
		orig.x = ctx->bi->unclip.x + INT2FIX(visual->compositor->vp_width)/2;
		orig.y = INT2FIX(visual->compositor->vp_height)/2 - ctx->bi->unclip.y + ctx->bi->unclip.height;

		mesh = new_mesh();
		mesh_new_rectangle(mesh, size, &orig, 1);
		visual_3d_mesh_paint(tr_state, mesh);
		mesh_free(mesh);
		gf_sc_texture_disable(ctx->aspect.fill_texture);
		tr_state->mesh_num_textures = 0;
		return 1;
	}
	return 0;
}
Beispiel #12
0
static void Text_Traverse(GF_Node *n, void *rs, Bool is_destroy)
{
	DrawableContext *ctx;
	M_Text *txt = (M_Text *) n;
	TextStack *st = (TextStack *) gf_node_get_private(n);
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;

	if (is_destroy) {
		text_clean_paths(gf_sc_get_compositor(n), st);
		drawable_del(st->graph);
		gf_list_del(st->spans);
		gf_free(st);
		return;
	}

	if (!txt->string.count) return;

	if (tr_state->text_split_mode) {
		gf_node_dirty_clear(n, 0);
		text_clean_paths(tr_state->visual->compositor, st);
		build_text_split(st, txt, tr_state);
		return;
	}

	text_check_changes(n, st, tr_state);

	switch (tr_state->traversing_mode) {
	case TRAVERSE_DRAW_2D:
		text_draw_2d(n, tr_state);
		return;
#ifndef GPAC_DISABLE_3D
	case TRAVERSE_DRAW_3D:
		text_draw_3d(tr_state, n, st);
		return;
#endif
	case TRAVERSE_PICK:
		tr_state->text_parent = n;
		gf_font_spans_pick(n, st->spans, tr_state, &st->bounds, 0, NULL);
		tr_state->text_parent = NULL;
		return;
	case TRAVERSE_GET_BOUNDS:
		tr_state->bounds = st->bounds;
		return;
	case TRAVERSE_GET_TEXT:
		tr_state->text_parent = n;
		gf_font_spans_get_selection(n, st->spans, tr_state);
		tr_state->text_parent = NULL;
		return;
	case TRAVERSE_SORT:
		break;
	default:
		return;
	}

#ifndef GPAC_DISABLE_3D
	if (tr_state->visual->type_3d) return;
#endif

	ctx = drawable_init_context_mpeg4(st->graph, tr_state);
	if (!ctx) return;
	ctx->sub_path_index = tr_state->text_split_idx;

	ctx->flags |= CTX_IS_TEXT;
	if (!GF_COL_A(ctx->aspect.fill_color)) {
		/*override line join*/
		ctx->aspect.pen_props.join = GF_LINE_JOIN_MITER;
		ctx->aspect.pen_props.cap = GF_LINE_CAP_FLAT;
	}

	/*if text selection mode, we must force redraw of the entire text span because we don't
	if glyphs have been (un)selected*/
	if (!tr_state->immediate_draw && 
		/*text selection on*/
		(tr_state->visual->compositor->text_selection 
		/*text sel release*/
		|| (tr_state->visual->compositor->store_text_state==GF_SC_TSEL_RELEASED)) 
	) {
		GF_TextSpan *span;
		u32 i = 0;
		Bool unselect = (tr_state->visual->compositor->store_text_state==GF_SC_TSEL_RELEASED) ? 1 : 0;
		while ((span = gf_list_enum(st->spans, &i))) {
			if (span->flags & GF_TEXT_SPAN_SELECTED) {
				if (unselect) span->flags &= ~GF_TEXT_SPAN_SELECTED;
				ctx->flags |= CTX_APP_DIRTY;
			}
		}
	}

	if (ctx->sub_path_index) {
		GF_TextSpan *span = (GF_TextSpan *)gf_list_get(st->spans, ctx->sub_path_index-1);
		if (span) drawable_finalize_sort(ctx, tr_state, &span->bounds);
	} else {
		drawable_finalize_sort(ctx, tr_state, &st->bounds);
	}
}
void visual_2d_texture_path_text(GF_VisualManager *visual, DrawableContext *txt_ctx, GF_Path *path, GF_Rect *object_bounds, GF_TextureHandler *txh, GF_TraverseState *tr_state)
{
	GF_STENCIL stencil;
	Fixed sS, sT;
	GF_Matrix2D gf_mx2d_txt;
	GF_Rect orig_rc;
	u8 alpha, r, g, b;
	GF_ColorMatrix cmat;
	GF_Raster2D *raster;

	if (! visual->CheckAttached(visual) ) return;

	raster = visual->compositor->rasterizer;

	stencil = gf_sc_texture_get_stencil(txh);
	if (!stencil) return;

	visual_2d_set_options(visual->compositor, visual->raster_surface, 0, 1);

	/*get original bounds*/
	orig_rc = *object_bounds;

	/*get scaling ratio so that active texture view is stretched to original bounds (std 2D shape texture mapping in MPEG4)*/
	sS = gf_divfix(orig_rc.width, INT2FIX(txh->width));
	sT = gf_divfix(orig_rc.height, INT2FIX(txh->height));

	gf_mx2d_init(gf_mx2d_txt);
	gf_mx2d_add_scale(&gf_mx2d_txt, sS, sT);

	/*move to bottom-left corner of bounds */
	gf_mx2d_add_translation(&gf_mx2d_txt, (orig_rc.x), (orig_rc.y - orig_rc.height));

	/*move to final coordinate system*/
	gf_mx2d_add_matrix(&gf_mx2d_txt, &txt_ctx->transform);

	/*set path transform, except for background2D node which is directly build in the final coord system*/
	raster->stencil_set_matrix(stencil, &gf_mx2d_txt);

	alpha = GF_COL_A(txt_ctx->aspect.fill_color);
	r = GF_COL_R(txt_ctx->aspect.fill_color);
	g = GF_COL_G(txt_ctx->aspect.fill_color);
	b = GF_COL_B(txt_ctx->aspect.fill_color);

	/*if col do a cxmatrix*/
	if (!r && !g && !b) {
		raster->stencil_set_alpha(stencil, alpha);
	} else {
		raster->stencil_set_alpha(stencil, 0xFF);
		memset(cmat.m, 0, sizeof(Fixed) * 20);
		cmat.m[4] = INT2FIX(r)/255;
		cmat.m[9] = INT2FIX(g)/255;
		cmat.m[14] = INT2FIX(b)/255;
		cmat.m[18] = INT2FIX(alpha)/255;
		cmat.identity = 0;
		raster->stencil_set_color_matrix(stencil, &cmat);
	}

	raster->surface_set_matrix(visual->raster_surface, &txt_ctx->transform);
	txh->flags |= GF_SR_TEXTURE_USED;

	/*push path*/
	raster->surface_set_path(visual->raster_surface, path);

	visual_2d_fill_path(visual, txt_ctx, stencil, tr_state, 0);
	raster->surface_set_path(visual->raster_surface, NULL);
	txt_ctx->flags |= CTX_PATH_FILLED;
}
void visual_2d_flush_hybgl_canvas(GF_VisualManager *visual, GF_TextureHandler *txh, struct _drawable_context *ctx, GF_TraverseState *tr_state)
{
	Bool line_texture = GF_FALSE;
	u32 i;
	u32 prev_color;
	Bool transparent, had_flush = 0;
	u32 nb_obj_left_on_canvas = visual->nb_objects_on_canvas_since_last_ogl_flush;
	u8 alpha;

	if (! visual->hybgl_drawn.count) 
		return;

	//we have drawn things on the canvas before this object, flush canvas to GPU

	if (txh && (txh==ctx->aspect.line_texture)) {
		line_texture = GF_TRUE;
		alpha = GF_COL_A(ctx->aspect.line_color);
		prev_color = ctx->aspect.line_color;
		ctx->aspect.line_texture = NULL;
		ctx->aspect.line_color = 0;
	} else {
		alpha = GF_COL_A(ctx->aspect.fill_color);
		if (!alpha) alpha = GF_COL_A(ctx->aspect.line_color);
		prev_color = ctx->aspect.fill_color;
		ctx->aspect.fill_texture = NULL;
		ctx->aspect.fill_color = 0;
		
	}
	transparent = txh ? (txh->transparent || (alpha!=0xFF)) : GF_TRUE;
	//clear wherever we have overlap
	for (i=0; i<visual->hybgl_drawn.count; i++) {
		GF_IRect rc = ctx->bi->clip;
		gf_irect_intersect(&ctx->bi->clip, &visual->hybgl_drawn.list[i].rect);
		if (ctx->bi->clip.width && ctx->bi->clip.height) {
			//if something behind this, flush canvas to gpu
			if (transparent) {
				if (!had_flush) {
					//flush the complete area below this object, regardless of intersections
					compositor_2d_hybgl_flush_video(visual->compositor, tr_state->immediate_draw ? NULL : &rc);
					had_flush = 1;
				}
				//if object was not completely in the flush region we will need to flush the canvas
				if (gf_irect_inside(&rc, &visual->hybgl_drawn.list[i].rect)) {
					assert(nb_obj_left_on_canvas);
					nb_obj_left_on_canvas--;
				}
			}

			//erase all part of the canvas below us
			if (txh) {
				visual_2d_draw_path_extended(visual, ctx->drawable->path, ctx, NULL, NULL, tr_state, NULL, NULL, GF_TRUE);
			} else {
				visual->compositor->rasterizer->surface_clear(visual->raster_surface, &ctx->bi->clip, 0);
			}
		}
		ctx->bi->clip = rc;
	}
	if (line_texture) {
		ctx->aspect.line_color = prev_color;
		ctx->aspect.line_texture = txh;
	} else {
		ctx->aspect.fill_color = prev_color;
		ctx->aspect.fill_texture = txh;
	}

	if (had_flush) {
		visual->nb_objects_on_canvas_since_last_ogl_flush = nb_obj_left_on_canvas;
	}
}
Beispiel #15
0
static Bool setup_grey_callback(EVGSurface *surf)
{
	u32 col, a;
	Bool use_const = 1;

	if (surf->sten->type == GF_STENCIL_SOLID) {
		col = surf->fill_col = ((EVG_Brush *)surf->sten)->color;
		a = GF_COL_A(surf->fill_col);
	} else {
		col = a = 0;
		use_const = 0;
	}
	
	if (surf->raster_cbk) {
		if (use_const) {
			if (!a) return 0;
			if (a!=0xFF) {
				surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_user_fill_const_a;
			} else {
				surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_user_fill_const;
			}
		} else {
			surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_user_fill_var;
		}
		return 1;
	}

	switch (surf->pixelFormat) {
	case GF_PIXEL_ARGB:
		if (use_const) {
			if (!a) return 0;
			if (a!=0xFF) {
				surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_bgra_fill_const_a;
			} else {
				surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_bgra_fill_const;
			}
		} else {
			surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_bgra_fill_var;
		}
		break;

	case GF_PIXEL_RGBA:
		if (use_const) {
			if (!a) return 0;
			if (a!=0xFF) {
				surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_rgba_fill_const_a;
			} else {
				surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_rgba_fill_const;
			}
		} else {
			surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_rgba_fill_var;
		}
		break;

	case GF_PIXEL_RGB_32:
		if (use_const) {
			if (!a) return 0;
			if (a!=0xFF) {
				surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_bgrx_fill_const_a;
			} else {
				surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_bgrx_fill_const;
			}
		} else {
			surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_bgrx_fill_var;
		}
		break;

	case GF_PIXEL_BGR_32:
		if (use_const) {
			if (!a) return 0;
			if (a!=0xFF) {
				surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_rgbx_fill_const_a;
			} else {
				surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_rgbx_fill_const;
			}
		} else {
			surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_rgbx_fill_var;
		}
		break;

	case GF_PIXEL_RGB_24:
		if (use_const) {
			if (!a) return 0;
			if (a!=0xFF) {
				surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_rgb_fill_const_a;
			} else {
				surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_rgb_fill_const;
			}
		} else {
			surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_rgb_fill_var;
		}
		break;
	case GF_PIXEL_BGR_24:
		if (use_const) {
			if (!a) return 0;
			if (a!=0xFF) {
				surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_bgr_fill_const_a;
			} else {
				surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_bgr_fill_const;
			}
		} else {
			surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_bgr_fill_var;
		}
		break;
	case GF_PIXEL_RGB_565:
		if (use_const) {
			surf->fill_565 = GF_COL_TO_565(col);
			if (!a) return 0;
			if (a!=0xFF) {
				surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_565_fill_const_a;
			} else {
				surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_565_fill_const;
			}
		} else {
			surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_565_fill_var;
			assert(surf->sten->fill_run);
		}
		break;
#ifdef GF_RGB_444_SUPORT
		if (use_const) {
			surf->fill_444 = GF_COL_TO_444(col);
			if (!a) return 0;
			if (a!=0xFF) {
				surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_444_fill_const_a;
			} else {
				surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_444_fill_const;
			}
		} else {
			surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_444_fill_var;
		}
		break;
#endif
#ifdef GF_RGB_555_SUPORT
	case GF_PIXEL_RGB_555:
		if (use_const) {
			surf->fill_555 = GF_COL_TO_555(col);
			if (!a) return 0;
			if (a!=0xFF) {
				surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_555_fill_const_a;
			} else {
				surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_555_fill_const;
			}
		} else {
			surf->ftparams.gray_spans = (EVG_Raster_Span_Func) evg_555_fill_var;
		}
		break;
#endif
	}
	return 1;
}
Beispiel #16
0
void compositor_3d_draw_bitmap(Drawable *stack, DrawAspect2D *asp, GF_TraverseState *tr_state, Fixed width, Fixed height, Fixed bmp_scale_x, Fixed bmp_scale_y)
{
	u8 alpha;
	GF_TextureHandler *txh;
	GF_Compositor *compositor = tr_state->visual->compositor;

	if (!asp->fill_texture)
		return;
	txh = asp->fill_texture;
	if (!txh || !txh->tx_io || !txh->width || !txh->height)
		return;

	if (((txh->pixelformat==GF_PIXEL_RGBD) || (txh->pixelformat==GF_PIXEL_YUVD))) {
		if (compositor->depth_gl_type) {
			if (txh->data && gf_sc_texture_convert(txh) )
				visual_3d_point_sprite(tr_state->visual, stack, txh, tr_state);
			return;
		}
	}

	alpha = GF_COL_A(asp->fill_color);
	/*THIS IS A HACK, will not work when setting filled=0, transparency and XLineProps*/
	if (!alpha) alpha = GF_COL_A(asp->line_color);

	visual_3d_set_state(tr_state->visual, V3D_STATE_LIGHT, GF_FALSE);
	visual_3d_enable_antialias(tr_state->visual, GF_FALSE);
	if (alpha && (alpha != 0xFF)) {
		visual_3d_set_material_2d_argb(tr_state->visual, GF_COL_ARGB(alpha, 0xFF, 0xFF, 0xFF));
		gf_sc_texture_set_blend_mode(txh, TX_MODULATE);
	} else if (gf_sc_texture_is_transparent(txh)) {
		gf_sc_texture_set_blend_mode(txh, TX_REPLACE);
	} else {
		visual_3d_set_state(tr_state->visual, V3D_STATE_BLEND, GF_FALSE);
	}
	/*ignore texture transform for bitmap*/
	tr_state->mesh_num_textures = gf_sc_texture_enable(txh, NULL);
	if (tr_state->mesh_num_textures) {
		/*we must check the w & h passed are correct because of bitmap node initialization*/
		if (width && height) {
			if (!stack->mesh) {
				SFVec2f size;
				size.x = width;
				size.y = height;

				stack->mesh = new_mesh();
				mesh_new_rectangle(stack->mesh, size, NULL, GF_FALSE);
			}
		}
		if (stack->mesh) {
#ifdef GF_SR_USE_DEPTH
			if (tr_state->depth_offset) {
				GF_Matrix mx;
				Fixed offset;
				Fixed disp_depth = (compositor->display_depth<0) ? INT2FIX(tr_state->visual->height) : INT2FIX(compositor->display_depth);
				if (disp_depth) {
					GF_Matrix bck_mx;
					if (!tr_state->pixel_metrics) disp_depth = gf_divfix(disp_depth, tr_state->min_hsize);
					gf_mx_init(mx);
					/*add recalibration by the scene*/
					offset = tr_state->depth_offset;
					if (tr_state->visual->depth_vp_range) {
						offset = gf_divfix(offset, tr_state->visual->depth_vp_range/2);
					}
					gf_mx_add_translation(&mx, 0, 0, gf_mulfix(offset, disp_depth/2) );

					gf_mx_copy(bck_mx, tr_state->model_matrix);
					gf_mx_add_matrix(&tr_state->model_matrix, &mx);
					visual_3d_mesh_paint(tr_state, stack->mesh);
					gf_mx_copy(tr_state->model_matrix, bck_mx);
				} else {
					visual_3d_mesh_paint(tr_state, stack->mesh);
				}
			} else
#endif
				visual_3d_mesh_paint(tr_state, stack->mesh);
		}
		gf_sc_texture_disable(txh);
		tr_state->mesh_num_textures = 0;
	}
}
void visual_2d_texture_path_extended(GF_VisualManager *visual, GF_Path *path, GF_TextureHandler *txh, struct _drawable_context *ctx, GF_Rect *orig_bounds, GF_Matrix2D *ext_mx, GF_TraverseState *tr_state)
{
	Fixed sS, sT;
	u32 tx_tile;
	GF_STENCIL tx_raster;
	GF_Matrix2D mx_texture;
	GF_Rect orig_rc;
	GF_Raster2D *raster;

	if (! visual->CheckAttached(visual) ) return;

	raster = visual->compositor->rasterizer;

	if (!txh) txh = ctx->aspect.fill_texture;
	if (!txh) return;
	if (!txh->tx_io) {
		gf_node_dirty_set(txh->owner, 0, 1);

		txh->needs_refresh=1;
		return;
	}


	/*this is gradient draw*/
	if (txh->compute_gradient_matrix) {
		visual_2d_draw_gradient(visual, path, txh, ctx, tr_state, ext_mx, orig_bounds);
		return;
	}


#ifndef GPAC_DISABLE_3D
	if (visual->compositor->hybrid_opengl) {
		visual_2d_texture_path_opengl_auto(visual, path, txh, ctx, orig_bounds, ext_mx, tr_state);
		return;
	}
#endif

	if (txh->flags & GF_SR_TEXTURE_PRIVATE_MEDIA) {
		GF_Window src, dst;
		visual_2d_fill_path(visual, ctx, NULL, tr_state, 0);

		/*if texture not ready, update the size before computing output rectangles */
		if (!txh->width || !txh->height) {
			gf_mo_get_visual_info(txh->stream, &txh->width, &txh->height, &txh->stride, &txh->pixel_ar, &txh->pixelformat, &txh->is_flipped);
			/*in case the node is an MPEG-4 bitmap, force stack rebuild at next frame */
			gf_node_dirty_set(ctx->drawable->node, GF_SG_NODE_DIRTY, 1);
		}

		if (compositor_texture_rectangles(visual, txh, &ctx->bi->clip, &ctx->bi->unclip, &src, &dst, NULL, NULL)) {
			if (txh->stream && gf_mo_set_position(txh->stream, &src, &dst)) {
				gf_mo_get_visual_info(txh->stream, &txh->width, &txh->height, &txh->stride, &txh->pixel_ar, &txh->pixelformat, &txh->is_flipped);
				/*force dirty flag to get called again*/
				gf_node_dirty_set(ctx->drawable->node, GF_SG_NODE_DIRTY, 1);
				gf_sc_next_frame_state(visual->compositor, GF_SC_DRAW_FRAME);
			}
		}



		return;
	}

	if (!gf_sc_texture_push_image(txh, 0, 1)) return;
	tx_raster = gf_sc_texture_get_stencil(txh);

	/*setup quality even for background (since quality concerns images)*/
	visual_2d_set_options(visual->compositor, visual->raster_surface, ctx->flags & CTX_IS_TEXT, ctx->flags & CTX_NO_ANTIALIAS);

	/*get original bounds*/
	if (orig_bounds) {
		orig_rc = *orig_bounds;
	} else {
		gf_path_get_bounds(path, &orig_rc);
	}

	/*get scaling ratio so that active texture view is stretched to original bounds (std 2D shape texture mapping in MPEG4)*/
	sS = orig_rc.width / txh->width;
	sT = orig_rc.height / txh->height;

	gf_mx2d_init(mx_texture);
	gf_mx2d_add_scale(&mx_texture, sS, sT);

#ifndef GPAC_DISABLE_VRML
	/*apply texture transform*/
	if (ctx->flags & CTX_HAS_APPEARANCE) {
		GF_Matrix2D tex_trans;
		visual_2d_get_texture_transform(ctx->appear, txh, &tex_trans, (txh == ctx->aspect.fill_texture) ? 0 : 1, txh->width * sS, txh->height * sT);
		gf_mx2d_add_matrix(&mx_texture, &tex_trans);
	}
#endif

	/*move to bottom-left corner of bounds */
	gf_mx2d_add_translation(&mx_texture, (orig_rc.x), (orig_rc.y - orig_rc.height));

	if (ext_mx) gf_mx2d_add_matrix(&mx_texture, ext_mx);

	/*move to final coordinate system (except background which is built directly in final coord system)*/
	if (!(ctx->flags & CTX_IS_BACKGROUND) ) gf_mx2d_add_matrix(&mx_texture, &ctx->transform);

	/*set path transform*/
	raster->stencil_set_matrix(tx_raster, &mx_texture);


	tx_tile = 0;
	if (txh->flags & GF_SR_TEXTURE_REPEAT_S) tx_tile |= GF_TEXTURE_REPEAT_S;
	if (txh->flags & GF_SR_TEXTURE_REPEAT_T) tx_tile |= GF_TEXTURE_REPEAT_T;
	if (ctx->flags & CTX_FLIPED_COORDS)
		tx_tile |= GF_TEXTURE_FLIP;
	raster->stencil_set_tiling(tx_raster, (GF_TextureTiling) tx_tile);

	if (!(ctx->flags & CTX_IS_BACKGROUND) ) {
		u8 a = GF_COL_A(ctx->aspect.fill_color);
		if (!a) a = GF_COL_A(ctx->aspect.line_color);
		/*texture alpha scale is the original material transparency, NOT the one after color transform*/
		raster->stencil_set_alpha(tx_raster, a );
		raster->stencil_set_color_matrix(tx_raster, ctx->col_mat);

		raster->surface_set_matrix(visual->raster_surface, &ctx->transform);
	} else {
		raster->surface_set_matrix(visual->raster_surface, NULL);
	}
	txh->flags |= GF_SR_TEXTURE_USED;

	/*push path & draw*/
	raster->surface_set_path(visual->raster_surface, path);
	visual_2d_fill_path(visual, ctx, tx_raster, tr_state, 0);
	raster->surface_set_path(visual->raster_surface, NULL);



	ctx->flags |= CTX_PATH_FILLED;
}
Beispiel #18
0
static void svg_drawable_traverse(GF_Node *node, void *rs, Bool is_destroy,
							void (*rebuild_path)(GF_Node *, Drawable *, SVGAllAttributes *),
							Bool is_svg_rect, Bool is_svg_path)
{
	GF_Matrix2D backup_matrix;
	GF_Matrix mx_3d;
	DrawableContext *ctx;
	SVGPropertiesPointers backup_props;
	u32 backup_flags;
	Drawable *drawable = (Drawable *)gf_node_get_private(node);
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;
	SVGAllAttributes all_atts;

	if (is_destroy) {
#if USE_GF_PATH
		/* The path is the same as the one in the SVG node, don't delete it here */
		if (is_svg_path) drawable->path = NULL;
#endif
		drawable_node_del(node);
		return;
	}
	assert(tr_state->traversing_mode!=TRAVERSE_DRAW_2D);

	
	if (tr_state->traversing_mode==TRAVERSE_PICK) {
		svg_drawable_pick(node, drawable, 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;
	
	/* Recreates the path (i.e the shape) only if the node is dirty */
	if (gf_node_dirty_get(node) & GF_SG_SVG_GEOMETRY_DIRTY) {
		/*the rebuild function is responsible for cleaning the path*/
		rebuild_path(node, drawable, &all_atts);
		gf_node_dirty_clear(node, GF_SG_SVG_GEOMETRY_DIRTY);
		drawable_mark_modified(drawable, tr_state);
	}
	if (drawable->path) {
		if (*(tr_state->svg_props->fill_rule)==GF_PATH_FILL_ZERO_NONZERO) {
			if (!(drawable->path->flags & GF_PATH_FILL_ZERO_NONZERO)) {
				drawable->path->flags |= GF_PATH_FILL_ZERO_NONZERO;
				drawable_mark_modified(drawable, tr_state);
			}
		} else {
			if (drawable->path->flags & GF_PATH_FILL_ZERO_NONZERO) {
				drawable->path->flags &= ~GF_PATH_FILL_ZERO_NONZERO;
				drawable_mark_modified(drawable, tr_state);
			}
		}
	}

	if (tr_state->traversing_mode == TRAVERSE_GET_BOUNDS) {
		if (! compositor_svg_is_display_off(tr_state->svg_props)) {
			DrawAspect2D asp;
			gf_path_get_bounds(drawable->path, &tr_state->bounds);
			if (!tr_state->ignore_strike) {
				memset(&asp, 0, sizeof(DrawAspect2D));
				drawable_get_aspect_2d_svg(node, &asp, tr_state);
				if (asp.pen_props.width) {
					StrikeInfo2D *si = drawable_get_strikeinfo(tr_state->visual->compositor, drawable, &asp, NULL, drawable->path, 0, NULL);
					if (si && si->outline) {
						gf_path_get_bounds(si->outline, &tr_state->bounds);
					}
				}
			}
			compositor_svg_apply_local_transformation(tr_state, &all_atts, &backup_matrix, NULL);
			if (!tr_state->abort_bounds_traverse)
				gf_mx2d_apply_rect(&tr_state->transform, &tr_state->bounds);
			gf_sc_get_nodes_bounds(node, NULL, tr_state, NULL);

			compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, NULL);
		}
	} else if (tr_state->traversing_mode == TRAVERSE_SORT) {
		/*reset our flags - this may break reuse of nodes and change-detection in dirty-rect algo */
		gf_node_dirty_clear(node, 0);

		if (!compositor_svg_is_display_off(tr_state->svg_props) &&
			( *(tr_state->svg_props->visibility) != SVG_VISIBILITY_HIDDEN) ) {

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

			ctx = drawable_init_context_svg(drawable, tr_state);
			if (ctx) {
				if (is_svg_rect) {
					if (ctx->aspect.fill_texture && ctx->aspect.fill_texture->transparent) {}
					else if (GF_COL_A(ctx->aspect.fill_color) != 0xFF) {}
					else if (ctx->transform.m[1] || ctx->transform.m[3]) {}
					else {
						ctx->flags &= ~CTX_IS_TRANSPARENT;
						if (!ctx->aspect.pen_props.width) 
							ctx->flags |= CTX_NO_ANTIALIAS;
					}
				}

				if (all_atts.pathLength && all_atts.pathLength->type==SVG_NUMBER_VALUE) 
					ctx->aspect.pen_props.path_length = all_atts.pathLength->value;

#ifndef GPAC_DISABLE_3D
				if (tr_state->visual->type_3d) {
					if (!drawable->mesh) {
						drawable->mesh = new_mesh();
						if (drawable->path) mesh_from_path(drawable->mesh, drawable->path);
					}
					visual_3d_draw_from_context(ctx, tr_state);
					ctx->drawable = NULL;
				} else 
#endif
				{
					drawable_finalize_sort(ctx, tr_state, NULL);
				}
			}
			compositor_svg_restore_parent_transformation(tr_state, &backup_matrix, &mx_3d);
		}
	}

	memcpy(tr_state->svg_props, &backup_props, sizeof(SVGPropertiesPointers));
	tr_state->svg_flags = backup_flags;
}
void visual_2d_draw_path_extended(GF_VisualManager *visual, GF_Path *path, DrawableContext *ctx, GF_STENCIL brush, GF_STENCIL pen, GF_TraverseState *tr_state, GF_Rect *orig_bounds, GF_Matrix2D *ext_mx, Bool is_erase)
{
	Bool dofill, dostrike;
	GF_Raster2D *raster = visual->compositor->rasterizer;
#ifdef SKIP_DRAW
	return;
#endif
	if (! visual->CheckAttached(visual) ) return;

	if ((ctx->flags & CTX_PATH_FILLED) && (ctx->flags & CTX_PATH_STROKE) ) {
		if (visual->compositor->draw_bvol) draw_clipper(visual, ctx);
		return;
	}

	if (! (ctx->flags & CTX_IS_BACKGROUND) )
		visual_2d_set_options(visual->compositor, visual->raster_surface, ctx->flags & CTX_IS_TEXT, ctx->flags & CTX_NO_ANTIALIAS);

	dofill = dostrike = 0;
	if (!(ctx->flags & CTX_PATH_FILLED) && (is_erase || GF_COL_A(ctx->aspect.fill_color)) ) {
		dofill = 1;
		if (!brush) {
			brush = visual->raster_brush;
			raster->stencil_set_brush_color(brush, ctx->aspect.fill_color);
		}
	}


	/*compute width based on transform and top_level transform*/
	if (!(ctx->flags & CTX_PATH_STROKE) && ctx->aspect.pen_props.width) {
		dostrike = 1;
	} else if (!dofill) {
		return;
	}

	/*set path transform, except for background2D node which is directly build in the final coord system*/
	raster->surface_set_matrix(visual->raster_surface, (ctx->flags & CTX_IS_BACKGROUND) ? NULL : &ctx->transform);

	/*fill path*/
	if (dofill) {
#if ADAPTATION_SIZE
		if ((ctx->bi->clip.width<ADAPTATION_SIZE) && (ctx->bi->clip.height<ADAPTATION_SIZE)) {
			raster->surface_clear(visual->raster_surface, &ctx->bi->clip, ctx->aspect.fill_color);
		} else
#endif
		{
			/*push path*/
			raster->surface_set_path(visual->raster_surface, path);
			visual_2d_fill_path(visual, ctx, brush, tr_state, is_erase);
			raster->surface_set_path(visual->raster_surface, NULL);
		}
	}

	if (dostrike) {
#if ADAPTATION_SIZE
		if ((ctx->bi->clip.width<ADAPTATION_SIZE) && (ctx->bi->clip.height<ADAPTATION_SIZE)) {
		} else
#endif
		{
			StrikeInfo2D *si;

			if (!pen) {
				pen = visual->raster_brush;
				raster->stencil_set_brush_color(pen, ctx->aspect.line_color);
			}

			si = drawable_get_strikeinfo(visual->compositor, ctx->drawable, &ctx->aspect, ctx->appear, path, ctx->flags, NULL);
			if (si && si->outline) {
				if (ctx->aspect.line_texture) {
					visual_2d_texture_path_extended(visual, si->outline, ctx->aspect.line_texture, ctx, orig_bounds, ext_mx, tr_state);
				} else {
					raster->surface_set_path(visual->raster_surface, si->outline);
					visual_2d_fill_path(visual, ctx, pen, tr_state, 0);
				}
				/*that's ugly, but we cannot cache path outline for IFS2D/ILS2D*/
				if (path && !(ctx->flags & CTX_IS_TEXT) && (path!=ctx->drawable->path) ) {
					gf_path_del(si->outline);
					si->outline = NULL;
				}
			}
//			drawable_reset_path_outline(ctx->drawable);
		}
	}

	if (visual->compositor->draw_bvol) draw_clipper(visual, ctx);
}
Beispiel #20
0
Bool group_cache_compute_stats(GF_Node *node, GroupingNode2D *group, GF_TraverseState *tr_state, DrawableContext *first_child, Bool skip_first_child)
{
	GF_Rect group_bounds;
	DrawableContext *ctx;
	u32 nb_segments, nb_objects;
	u32 alpha_pixels, opaque_pixels, area_world;
	u32 video_cache_max_size, cache_size, prev_cache_size;
	u32 i;
	GF_RectArray ra;

	/*compute stats*/
	nb_objects = 0;
	nb_segments = 0;
	alpha_pixels = opaque_pixels = 0;
	prev_cache_size = group->cached_size;
	/*reset bounds*/
	group_bounds.width = group_bounds.height = 0;
	video_cache_max_size = tr_state->visual->compositor->video_cache_max_size;

	/*never cache root node - this should be refined*/
	if (gf_node_get_parent(node, 0) == NULL) goto group_reject;
	if (!group->traverse_time) goto group_reject;

	ra_init(&ra);

	ctx = first_child;
	if (!first_child) ctx = tr_state->visual->context;
	if (skip_first_child) ctx = ctx->next;
	/*compute properties for the sub display list*/
	while (ctx && ctx->drawable) {
		//Fixed area;
		u32 alpha_comp;

		/*get area and compute alpha/opaque coverage*/
		alpha_comp = GF_COL_A(ctx->aspect.fill_color);

		/*add to group area*/
		gf_rect_union(&group_bounds, &ctx->bi->unclip);
		nb_objects++;

		/*no alpha*/
		if ((alpha_comp==0xFF)
			/*no transparent texture*/
			&& (!ctx->aspect.fill_texture || !ctx->aspect.fill_texture->transparent)
		) {

			ra_union_rect(&ra, &ctx->bi->clip);
		}
		nb_segments += ctx->drawable->path->n_points;

		ctx = ctx->next;
	}

	if (
		/*TEST 1: discard visually empty groups*/
		(!group_bounds.width || !group_bounds.height)
		||
		/*TEST 2: discard small groups*/
		(nb_objects<MIN_OBJECTS_IN_CACHE)
		||
		/*TEST 3: low complexity group*/
		(nb_segments && (nb_segments<10))
	) {
		ra_del(&ra);
		goto group_reject;
	}

	ra_refresh(&ra);
	opaque_pixels = 0;
	for (i=0; i<ra.count; i++) {
		opaque_pixels += ra.list[i].width * ra.list[i].height;
	}
	ra_del(&ra);

	/*get coverage in world coords*/
	area_world = FIX2INT(group_bounds.width) * FIX2INT(group_bounds.height);

	/*TEST 4: discard low coverage groups in world coords (plenty of space wasted)
		we consider that this % of the area is actually drawn - this is of course wrong,
		we would need to compute each path coverage in local coords then get the ratio
	*/
	if (10*opaque_pixels < 7*area_world) goto group_reject;

	/*the memory size allocated for the cache - cache is drawn in final coordinate system !!*/
	group_bounds.width = tr_state->visual->compositor->cache_scale * group_bounds.width / 100;
	group_bounds.height = tr_state->visual->compositor->cache_scale * group_bounds.height / 100;
	cache_size = FIX2INT(group_bounds.width) * FIX2INT(group_bounds.height) * 4 /* pixelFormat is ARGB*/;

	/*TEST 5: cache is less than 10x10 pixels: discard*/
	if (cache_size < 400) goto group_reject;
	/*TEST 6: cache is larger than our allowed memory: discard*/
	if (cache_size>=video_cache_max_size) {
		tr_state->cache_too_small = 1;
		goto group_reject;
	}

	/*compute the delta value for measuring the group importance for later discard
		(avg_time - Tcache) / (size_cache - drawable_gain)
	*/
	group->priority = INT2FIX(nb_objects*1024*group->traverse_time) / cache_size / group->nb_stats_frame;
	/*OK, group is a good candidate for caching*/
	group->nb_objects = nb_objects;
	group->cached_size = cache_size;


	/*we're moving from non-cached to cached*/
	if (!(group->flags & GROUP_IS_CACHABLE)) {
		group->flags |= GROUP_IS_CACHABLE;
		tr_state->visual->compositor->draw_next_frame = 1;

		/*insert the candidate and then update the list in order*/
		group_cache_insert_entry(node, group, tr_state);
		/*keep track of this cache object for later removal*/
		gf_list_add(tr_state->visual->compositor->cached_groups_queue, group);

		GF_LOG(GF_LOG_DEBUG, GF_LOG_CACHE, ("[CACHE] Turning cache on during stat pass for node %s - %d kb used in all caches\n", gf_node_get_log_name(node), tr_state->visual->compositor->video_cache_current_size ));
	}
	/*update memory occupation*/
	else {
		tr_state->visual->compositor->video_cache_current_size -= prev_cache_size;
		tr_state->visual->compositor->video_cache_current_size += group->cached_size;

		if (group->cache)
			group->cache->force_recompute = 1;
	}
	return 1;


group_reject:
	group->nb_objects = nb_objects;

	if ((group->flags & GROUP_IS_CACHABLE) || group->cache) {
		group->flags &= ~GROUP_IS_CACHABLE;

		if (group->cache) {
			group_cache_del(group->cache);
			group->cache = NULL;
			group->flags &= ~GROUP_IS_CACHED;
		}
		gf_list_del_item(tr_state->visual->compositor->cached_groups, group);
		tr_state->visual->compositor->video_cache_current_size -= cache_size;
	}

#if 0
	GF_LOG(GF_LOG_DEBUG, GF_LOG_CACHE, ("[CACHE] REJECT %s\tObjects: %d\tSlope: %g\tBytes: %d\tTime: %d\n",
										gf_node_get_log_name(node),
										group->nb_objects,
										FIX2FLT(group->priority),
										group->cached_size,
										group->traverse_time
										));

	GF_LOG(GF_LOG_DEBUG, GF_LOG_CACHE, ("[CACHE] Status (B): Max: %d\tUsed: %d\tNb Groups: %d\n",
								tr_state->visual->compositor->video_cache_max_size,
								tr_state->visual->compositor->video_cache_current_size,
								gf_list_count(tr_state->visual->compositor->cached_groups)
								));
#endif
	return 0;
}
static void IFS2D_Draw(GF_Node *node, GF_TraverseState *tr_state)
{
	u32 i, count, ci_count;
	u32 j, ind_col, num_col;
	SFVec2f center, end;
	SFColor col_cen;
	GF_STENCIL grad;
	u32 *colors;
	GF_Path *path;
	SFVec2f start;
	SFVec2f *pts;
	SFColor col;
	Fixed alpha;
	GF_Raster2D *raster;
	DrawableContext *ctx = tr_state->ctx;
	M_IndexedFaceSet2D *ifs2D = (M_IndexedFaceSet2D *)node;
	M_Coordinate2D *coord = (M_Coordinate2D*) ifs2D->coord;
	M_Color *color = (M_Color *) ifs2D->color;
		
	col.red = col.green = col.blue = 0;
	/*simple case, no color specified*/
	if (!ifs2D->color) {
		visual_2d_texture_path(tr_state->visual, ctx->drawable->path, ctx, tr_state);
		visual_2d_draw_path(tr_state->visual, ctx->drawable->path, ctx, NULL, NULL, tr_state);
		return;
	}

	/*if default face use first color*/
	ci_count = ifs2D->coordIndex.count;
	pts = coord->point.vals;

	if (ci_count == 0) {
		col = (ifs2D->colorIndex.count > 0) ? color->color.vals[ifs2D->colorIndex.vals[0]] : color->color.vals[0];

		alpha = INT2FIX(GF_COL_A(ctx->aspect.fill_color)) / 255;
		if (!alpha || !ctx->aspect.pen_props.width) {
			alpha = INT2FIX(GF_COL_A(ctx->aspect.line_color)) / 255;
			ctx->aspect.line_color = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
		} else {
			ctx->aspect.fill_color = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
		}
		visual_2d_texture_path(tr_state->visual, ctx->drawable->path, ctx, tr_state);
		visual_2d_draw_path(tr_state->visual, ctx->drawable->path, ctx, NULL, NULL, tr_state);
		return;
	}

	/*we have color per faces so we need N path :(*/
	if (! ifs2D->colorPerVertex) {
		path = gf_path_new();

		count = 0;
		i = 0;
		while (1) {
			gf_path_reset(path);
			start = pts[ifs2D->coordIndex.vals[i]];
			gf_path_add_move_to(path, start.x, start.y);
			i++;

			while (ifs2D->coordIndex.vals[i] != -1) {	
				start = pts[ifs2D->coordIndex.vals[i]];
				gf_path_add_line_to(path, start.x, start.y);
				i++;
				if (i >= ci_count) break;
			}
			/*close in ALL cases because even if the start/end points are the same the line join needs to be present*/
			gf_path_close(path);

			col = (ifs2D->colorIndex.count > 0) ? color->color.vals[ifs2D->colorIndex.vals[count]] : color->color.vals[count];

			alpha = INT2FIX(GF_COL_A(ctx->aspect.fill_color)) / 255;
			if (!alpha) {
				alpha = INT2FIX(GF_COL_A(ctx->aspect.line_color)) / 255;
				ctx->aspect.line_color = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
			} else {
				ctx->aspect.fill_color = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
			}

			visual_2d_texture_path(tr_state->visual, path, ctx, tr_state);
			visual_2d_draw_path(tr_state->visual, path, ctx, NULL, NULL, tr_state);
			count++;
			i++;
			if (i >= ci_count) break;
			ctx->flags &= ~CTX_PATH_FILLED;
			ctx->flags &= ~CTX_PATH_STROKE;
		}
		gf_path_del(path);
		return;
	}

	/*final case, color per vertex means gradient fill/strike*/
	raster = tr_state->visual->compositor->rasterizer;
	grad = raster->stencil_new(raster, GF_STENCIL_VERTEX_GRADIENT);
	/*not supported, fill default*/
	if (!grad) {
		visual_2d_texture_path(tr_state->visual, ctx->drawable->path, ctx, tr_state);
		visual_2d_draw_path(tr_state->visual, ctx->drawable->path, ctx, NULL, NULL, tr_state);
		return;
	}


	path = gf_path_new();

	ind_col = 0;
	i = 0;
	while (1) {
		gf_path_reset(path);
		start = pts[ifs2D->coordIndex.vals[i]];
		center = start;
		gf_path_add_move_to(path, start.x, start.y);
		num_col = 1;
		i+=1;
		while (ifs2D->coordIndex.vals[i] != -1) {	
			end = pts[ifs2D->coordIndex.vals[i]];
			gf_path_add_line_to(path, end.x, end.y);
			i++;
			center.x += end.x;
			center.y += end.y;
			num_col ++;
			if (i >= ci_count) break;
		}
		gf_path_close(path);
		num_col++;

		alpha = INT2FIX(GF_COL_A(ctx->aspect.fill_color) ) / 255;

		colors = (u32*)gf_malloc(sizeof(u32) * num_col);
		col_cen.blue = col_cen.red = col_cen.green = 0;
		for (j=0; j<num_col-1; j++) {
			if (ifs2D->colorIndex.count > ind_col + j) {
				col = color->color.vals[ifs2D->colorIndex.vals[ind_col + j]];
			} else if (ci_count > ind_col + j) {
				col = color->color.vals[ifs2D->coordIndex.vals[ind_col + j]];
			}
			colors[j] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
			col_cen.blue += col.blue;
			col_cen.green += col.green;
			col_cen.red += col.red;
		}
		colors[num_col-1] = colors[0];

		if (ifs2D->colorIndex.count > ind_col) {
			col = color->color.vals[ifs2D->colorIndex.vals[ind_col]];
		} else if (ci_count > ind_col) {
			col = color->color.vals[ifs2D->coordIndex.vals[ind_col]];
		}
		col_cen.blue += col.blue;
		col_cen.green += col.green;
		col_cen.red += col.red;

		raster->stencil_set_vertex_path(grad, path);
		raster->stencil_set_vertex_colors(grad, colors, num_col);

		gf_free(colors);
		
		col_cen.blue /= num_col;
		col_cen.green /= num_col;
		col_cen.red /= num_col;
		center.x /= num_col;
		center.y /= num_col;
		raster->stencil_set_vertex_center(grad, center.x, center.y, GF_COL_ARGB_FIXED(alpha, col_cen.red, col_cen.green, col_cen.blue) );

		raster->stencil_set_matrix(grad, &ctx->transform);

		/*draw*/
		visual_2d_draw_path(tr_state->visual, ctx->drawable->path, ctx, grad, grad, tr_state);

		raster->stencil_delete(grad);

		//goto next point
		i++;
		ind_col += num_col + 1;	
		if (i >= ci_count) break;
		grad = raster->stencil_new(raster, GF_STENCIL_VERTEX_GRADIENT);
		ctx->flags &= ~CTX_PATH_FILLED;
		ctx->flags &= ~CTX_PATH_STROKE;
	}
	gf_path_del(path);
}
Beispiel #22
0
static void TraverseRectangle(GF_Node *node, void *rs, Bool is_destroy)
{
	DrawableContext *ctx;
	Drawable *stack = (Drawable *)gf_node_get_private(node);
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;

	if (is_destroy) {
		drawable_node_del(node);
		return;
	}

	rectangle_check_changes(node, stack, tr_state);

	switch (tr_state->traversing_mode) {
	case TRAVERSE_DRAW_2D:
		compositor_2d_draw_rectangle(tr_state);
		return;
#ifndef GPAC_DISABLE_3D
	case TRAVERSE_DRAW_3D:
		if (!stack->mesh) {
			stack->mesh = new_mesh();
			mesh_new_rectangle(stack->mesh, ((M_Rectangle *) node)->size, NULL, 0);
		}
		visual_3d_draw_2d(stack, tr_state);
		return;
#endif
	case TRAVERSE_PICK:
		vrml_drawable_pick(stack, tr_state);
		return;
	case TRAVERSE_GET_BOUNDS:
		gf_path_get_bounds(stack->path, &tr_state->bounds);
		return;
	case TRAVERSE_SORT:
#ifndef GPAC_DISABLE_3D
		if (tr_state->visual->type_3d) return;
#endif
		break;
	default:
		return;
	}

	ctx = drawable_init_context_mpeg4(stack, tr_state);
	if (!ctx) return;

	/*if rotated, object is transparent (doesn't fill bounds) and antialias must be used*/
	if (tr_state->transform.m[1] || tr_state->transform.m[3]) {
	}
	else {

		/*if alpha or not filled, transparent*/
		if (ctx->aspect.fill_color && (GF_COL_A(ctx->aspect.fill_color) != 0xFF)) {
		}
		/*if texture transparent, transparent*/
		else if (ctx->aspect.fill_texture && ctx->aspect.fill_texture->transparent) {
		}
		/*TODO check matrix for alpha*/
		else if (!tr_state->color_mat.identity) {
		}
		/*otherwise, not transparent*/
		else {
			ctx->flags &= ~CTX_IS_TRANSPARENT;
		}
		/*if no line width, we skip antialiasing*/
		if (!ctx->aspect.pen_props.width) ctx->flags |= CTX_NO_ANTIALIAS;
	}
	drawable_finalize_sort(ctx, tr_state, NULL);
}
Beispiel #23
0
void VS2D_TexturePathIntern(VisualSurface2D *surf, GF_Path *path, GF_TextureHandler *txh, struct _drawable_context *ctx)
{
	Fixed sS, sT;
	u32 tx_tile;
	GF_Matrix2D gf_mx2d_txt, gf_sr_texture_transform;
	GF_Rect rc, orig_rc;
	GF_Raster2D *r2d = surf->render->compositor->r2d;

	if (!txh) txh = ctx->h_texture;
	if (!txh || !txh->hwtx) return;

	/*this is gradient draw*/
	if (txh->compute_gradient_matrix) {
		VS2D_DrawGradient(surf, path, txh, ctx);
		return;
	}

	/*setup quality even for background (since quality concerns images)*/
	VS2D_SetOptions(surf->render, surf->the_surface, ctx->flags & CTX_IS_TEXT, ctx->flags & CTX_NO_ANTIALIAS);

	/*get original bounds*/
	gf_path_get_bounds(path, &orig_rc);

	/*get active texture window in pixels*/
	rc.width = INT2FIX(txh->width);
	rc.height = INT2FIX(txh->height);

	/*get scaling ratio so that active texture view is stretched to original bounds (std 2D shape texture mapping in MPEG4)*/
	sS = orig_rc.width / txh->width;
	sT = orig_rc.height / txh->height;
	
	gf_mx2d_init(gf_mx2d_txt);
	gf_mx2d_add_scale(&gf_mx2d_txt, sS, sT);
	/*apply texture transform*/
	get_gf_sr_texture_transform(ctx->appear, txh, &gf_sr_texture_transform, (txh == ctx->h_texture) ? 0 : 1, txh->width * sS, txh->height * sT);
	gf_mx2d_add_matrix(&gf_mx2d_txt, &gf_sr_texture_transform);

	/*move to bottom-left corner of bounds */
	gf_mx2d_add_translation(&gf_mx2d_txt, (orig_rc.x), (orig_rc.y - orig_rc.height));

	/*move to final coordinate system (except background which is built directly in final coord system)*/	
	if (!(ctx->flags & CTX_IS_BACKGROUND) ) gf_mx2d_add_matrix(&gf_mx2d_txt, &ctx->transform);

	/*set path transform, except for background2D node which is directly build in the final coord system*/
	r2d->stencil_set_matrix(txh->hwtx, &gf_mx2d_txt);


	tx_tile = 0;
	if (txh->flags & GF_SR_TEXTURE_REPEAT_S) tx_tile |= GF_TEXTURE_REPEAT_S;
	if (txh->flags & GF_SR_TEXTURE_REPEAT_T) tx_tile |= GF_TEXTURE_REPEAT_T;
	r2d->stencil_set_tiling(txh->hwtx, (GF_TextureTiling) tx_tile);

	if (!(ctx->flags & CTX_IS_BACKGROUND) ) {
		u8 a = GF_COL_A(ctx->aspect.fill_color);
		if (!a) a = GF_COL_A(ctx->aspect.line_color);
		/*texture alpha scale is the original material transparency, NOT the one after color transform*/
		r2d->stencil_set_texture_alpha(txh->hwtx, a );
		r2d->stencil_set_color_matrix(txh->hwtx, ctx->col_mat);

		r2d->surface_set_matrix(surf->the_surface, &ctx->transform);
	} else {
		r2d->surface_set_matrix(surf->the_surface, NULL);
	}

	/*push path & draw*/
	r2d->surface_set_path(surf->the_surface, path);
	VS2D_DoFill(surf, ctx, txh->hwtx);
	r2d->surface_set_path(surf->the_surface, NULL);
	ctx->flags |= CTX_PATH_FILLED;
}
Beispiel #24
0
void compositor_3d_draw_bitmap(Drawable *stack, DrawAspect2D *asp, GF_TraverseState *tr_state, Fixed width, Fixed height, Fixed bmp_scale_x, Fixed bmp_scale_y)
{
	u8 alpha;
#if !defined(GPAC_USE_OGL_ES) && !defined(GPAC_USE_TINYGL)
	Fixed x, y;
	Fixed sx, sy;
	char *data;
	u32 format;
#endif
	GF_TextureHandler *txh;
	GF_Compositor *compositor = tr_state->visual->compositor;
	Bool use_texture = !compositor->bitmap_use_pixels;

	if (!asp->fill_texture)
		return;
	txh = asp->fill_texture;
	if (!txh || !txh->tx_io || !txh->width || !txh->height)
		return;

	if (((txh->pixelformat==GF_PIXEL_RGBD) || (txh->pixelformat==GF_PIXEL_YUVD))) {
		if (compositor->depth_gl_type) {
			if (txh->data && gf_sc_texture_convert(txh) )
				visual_3d_point_sprite(tr_state->visual, stack, txh, tr_state);
			return;
		} else {
			use_texture = 1;
		}
	}

	alpha = GF_COL_A(asp->fill_color);
	/*THIS IS A HACK, will not work when setting filled=0, transparency and XLineProps*/
	if (!alpha) alpha = GF_COL_A(asp->line_color);

	/*texture is available in hw, use it - if blending, force using texture*/
	if (!gf_sc_texture_needs_reload(txh) || (alpha != 0xFF) || use_texture
#ifdef GF_SR_USE_DEPTH
		|| tr_state->depth_offset
#endif
		) {
		visual_3d_set_state(tr_state->visual, V3D_STATE_LIGHT, 0);
		visual_3d_enable_antialias(tr_state->visual, 0);
		if (alpha && (alpha != 0xFF)) {
			visual_3d_set_material_2d_argb(tr_state->visual, GF_COL_ARGB(alpha, 0xFF, 0xFF, 0xFF));
			gf_sc_texture_set_blend_mode(txh, TX_MODULATE);
		} else if (gf_sc_texture_is_transparent(txh)) {
			gf_sc_texture_set_blend_mode(txh, TX_REPLACE);
		} else {
			visual_3d_set_state(tr_state->visual, V3D_STATE_BLEND, 0);
		}
		/*ignore texture transform for bitmap*/
 		tr_state->mesh_num_textures = gf_sc_texture_enable(txh, NULL);
		if (tr_state->mesh_num_textures) {
			/*we must check the w & h passed are correct because of bitmap node initialization*/
			if (width && height) {
				if (!stack->mesh) {
					SFVec2f size;
					size.x = width;
					size.y = height;

					stack->mesh = new_mesh();
					mesh_new_rectangle(stack->mesh, size, NULL, 0);
				}
			}
			if (stack->mesh) {
#ifdef GF_SR_USE_DEPTH
				if (tr_state->depth_offset) {
					GF_Matrix mx;
					Fixed offset;
					Fixed disp_depth = (compositor->display_depth<0) ? INT2FIX(tr_state->visual->height) : INT2FIX(compositor->display_depth);
					if (disp_depth) {
						if (!tr_state->pixel_metrics) disp_depth = gf_divfix(disp_depth, tr_state->min_hsize);
						gf_mx_init(mx);
						/*add recalibration by the scene*/
						offset = tr_state->depth_offset;
						if (tr_state->visual->depth_vp_range) {
							offset = gf_divfix(offset, tr_state->visual->depth_vp_range/2);
						}
						gf_mx_add_translation(&mx, 0, 0, gf_mulfix(offset, disp_depth/2) );

						visual_3d_matrix_push(tr_state->visual);
						visual_3d_matrix_add(tr_state->visual, mx.m);
						visual_3d_mesh_paint(tr_state, stack->mesh);
						visual_3d_matrix_pop(tr_state->visual);
					} else {
						visual_3d_mesh_paint(tr_state, stack->mesh);
					}
				} else
#endif
					visual_3d_mesh_paint(tr_state, stack->mesh);
			}
 			gf_sc_texture_disable(txh);
			tr_state->mesh_num_textures = 0;
			return;
		}
	}

	/*otherwise use glDrawPixels*/
#if !defined(GPAC_USE_OGL_ES) && !defined(GPAC_USE_TINYGL)
	data = gf_sc_texture_get_data(txh, &format);
	if (!data) return;

	x = INT2FIX(txh->width) / -2;
	y = INT2FIX(txh->height) / 2;

	{
	Fixed g[16];

	sx = bmp_scale_x; if (sx<0) sx = FIX_ONE;
	sy = bmp_scale_y; if (sy<0) sy = FIX_ONE;
#ifndef GPAC_DISABLE_VRML
	compositor_adjust_scale(txh->owner, &sx, &sy);
#endif

	/*add top level scale if any*/
	sx = gf_mulfix(sx, compositor->scale_x);
	sy = gf_mulfix(sy, compositor->scale_y);

	/*get & apply current transform scale*/
	visual_3d_matrix_get(tr_state->visual, V3D_MATRIX_MODELVIEW, g);

	if (g[0]<0) g[0] *= -FIX_ONE;
	if (g[5]<0) g[5] *= -FIX_ONE;
	sx = gf_mulfix(sx, g[0]);
	sy = gf_mulfix(sy, g[5]);
	x = gf_mulfix(x, sx);
	y = gf_mulfix(y, sy);

	}
	visual_3d_draw_image(tr_state->visual, x, y, txh->width, txh->height, format, data, sx, sy);
#endif
}
Beispiel #25
0
static void ILS2D_Draw(GF_Node *node, GF_TraverseState *tr_state)
{
	GF_Path *path;
	SFVec2f *pts;
	SFColor col;
	Fixed alpha;
	u32 i, count, col_ind, ind, end_at;
	u32 linear[2], *colors;
	SFVec2f start, end;
	u32 j, num_col;
	GF_STENCIL grad;
	GF_Raster2D *raster;
	DrawableContext *ctx = tr_state->ctx;
	M_IndexedLineSet2D *ils2D = (M_IndexedLineSet2D *)node;
	M_Coordinate2D *coord = (M_Coordinate2D*) ils2D->coord;
	M_Color *color = (M_Color *) ils2D->color;

	end.x = end.y = 0;
	if (!coord->point.count) return;

	if (! ils2D->color) {
		/*no texturing*/
		visual_2d_draw_path(tr_state->visual, ctx->drawable->path, ctx, NULL, NULL, tr_state);
		return;
	}

	alpha = INT2FIX(GF_COL_A(ctx->aspect.line_color)) / 255;
	pts = coord->point.vals;

	if (!ils2D->colorPerVertex || (color->color.count<2) ) {
		count = 0;
		end_at = ils2D->coordIndex.count;
		if (!end_at) end_at = coord->point.count;
		ind = ils2D->coordIndex.count ? ils2D->coordIndex.vals[0] : 0;
		i=1;
		path = gf_path_new();
		gf_path_add_move_to(path, pts[ind].x, pts[ind].y);

		for (; i<=end_at; i++) {
			if ((i==end_at) || (ils2D->coordIndex.count && ils2D->coordIndex.vals[i] == -1)) {

				/*draw current*/
				col_ind = (ils2D->colorIndex.count && (ils2D->colorIndex.vals[count]>=0) ) ? (u32) ils2D->colorIndex.vals[count] : count;
				if (col_ind>=color->color.count) col_ind=color->color.count-1;
				col = color->color.vals[col_ind];
				ctx->aspect.line_color = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);

				visual_2d_draw_path(tr_state->visual, path, ctx, NULL, NULL, tr_state);

				i++;
				if (i>=end_at) break;
				gf_path_reset(path);

				ind = (ils2D->coordIndex.count && (ils2D->coordIndex.vals[i]>=0)) ? (u32) ils2D->coordIndex.vals[i] : i;
				gf_path_add_move_to(path, pts[ind].x, pts[ind].y);

				if (ils2D->coordIndex.count) count++;
				continue;
			} else {
				ind = (ils2D->coordIndex.count && (ils2D->coordIndex.vals[i]>=0) ) ? (u32) ils2D->coordIndex.vals[i] : i;
				gf_path_add_line_to(path, pts[ind].x, pts[ind].y);
			}
		}
		gf_path_del(path);
		return;
	}

	raster = NULL;
	end_at = ils2D->coordIndex.count;
	if (!end_at) end_at = coord->point.count;
	count = 0;
	col_ind = 0;
	ind = 0;
	i=0;
	path = gf_path_new();
	while (1) {
		gf_path_reset(path);
		ind = (ils2D->coordIndex.count && (ils2D->coordIndex.vals[i]>=0)) ? (u32) ils2D->coordIndex.vals[i] : i;
		start = pts[ind];
		num_col = 1;
		i++;
		gf_path_add_move_to(path, start.x, start.y);

		if (ils2D->coordIndex.count) {
			while (ils2D->coordIndex.vals[i] != -1) {
				end = pts[ils2D->coordIndex.vals[i]];
				gf_path_add_line_to(path, end.x, end.y);
				i++;
				num_col++;
				if (i >= ils2D->coordIndex.count) break;
			}
		} else {
			while (i<end_at) {
				end = pts[i];
				gf_path_add_line_to(path, end.x, end.y);
				i++;
				num_col++;
			}
		}

		raster = tr_state->visual->compositor->rasterizer;
		/*use linear gradient*/
		if (num_col==2) {
			Fixed pos[2];
			grad = raster->stencil_new(raster, GF_STENCIL_LINEAR_GRADIENT);
			if (ils2D->colorIndex.count) {
				col = color->color.vals[ils2D->colorIndex.vals[col_ind]];
				linear[0] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
				col = color->color.vals[ils2D->colorIndex.vals[col_ind+1]];
				linear[1] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
			} else if (ils2D->coordIndex.count) {
				col = color->color.vals[ils2D->coordIndex.vals[col_ind]];
				linear[0] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
				col = color->color.vals[ils2D->coordIndex.vals[col_ind+1]];
				linear[1] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
			} else {
				col = color->color.vals[col_ind];
				linear[0] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
				col = color->color.vals[col_ind+1];
				linear[1] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
			}
			pos[0] = 0;
			pos[1] = FIX_ONE;
			raster->stencil_set_linear_gradient(grad, start.x, start.y, end.x, end.y);
			raster->stencil_set_gradient_interpolation(grad, pos, linear, 2);
		} else {
			grad = raster->stencil_new(raster, GF_STENCIL_VERTEX_GRADIENT);
			if (grad) {
				raster->stencil_set_vertex_path(grad, path);

				colors = (u32*)gf_malloc(sizeof(u32) * num_col);
				for (j=0; j<num_col; j++) {
					if (ils2D->colorIndex.count>0) {
						col = color->color.vals[ils2D->colorIndex.vals[col_ind+j]];
					} else if (ils2D->coordIndex.count) {
						col = color->color.vals[ils2D->coordIndex.vals[col_ind+j]];
					} else {
						col = color->color.vals[col_ind+j];
					}
					colors[j] = GF_COL_ARGB_FIXED(alpha, col.red, col.green, col.blue);
				}
				raster->stencil_set_vertex_colors(grad, colors, num_col);
				gf_free(colors);
			}
		}
		raster->stencil_set_matrix(grad, &ctx->transform);
		visual_2d_draw_path(tr_state->visual, path, ctx, NULL, grad, tr_state);
		if (grad) raster->stencil_delete(grad);

		i ++;
		col_ind += num_col + 1;
		if (i >= ils2D->coordIndex.count) break;
		ctx->flags &= ~CTX_PATH_STROKE;
	}
	gf_path_del(path);
}
Beispiel #26
0
void VS2D_DrawPath(VisualSurface2D *surf, GF_Path *path, DrawableContext *ctx, GF_STENCIL brush, GF_STENCIL pen)
{
	Bool dofill, dostrike;
	GF_Raster2D *r2d = surf->render->compositor->r2d;
#ifdef SKIP_DRAW
	return;
#endif
	
	assert(surf->the_surface);

	if ((ctx->flags & CTX_PATH_FILLED) && (ctx->flags & CTX_PATH_STROKE) ) {
		if (surf->render->compositor->draw_bvol) draw_clipper(surf, ctx);
		return;
	}

	if (! (ctx->flags & CTX_IS_BACKGROUND) ) VS2D_SetOptions(surf->render, surf->the_surface, ctx->flags & CTX_IS_TEXT, 0);

	dofill = dostrike = 0;
	if (!(ctx->flags & CTX_PATH_FILLED) && GF_COL_A(ctx->aspect.fill_color) ) {
		dofill = 1;
		if (!brush) {
			brush = surf->the_brush;
			r2d->stencil_set_brush_color(brush, ctx->aspect.fill_color);
		}
	}


	/*compute width based on transform and top_level transform*/
	if (!(ctx->flags & CTX_PATH_STROKE) && ctx->aspect.pen_props.width) {
		dostrike = 1;
		if (!pen) {
			pen = surf->the_pen;
			r2d->stencil_set_brush_color(pen, ctx->aspect.line_color);
		}
	} else if (!dofill) {
		return;
	}

	/*set path transform, except for background2D node which is directly build in the final coord system*/
	r2d->surface_set_matrix(surf->the_surface, (ctx->flags & CTX_IS_BACKGROUND) ? NULL : &ctx->transform);

	/*fill path*/
	if (dofill) {
#if ADAPTATION_SIZE
		if ((ctx->bi->clip.width<ADAPTATION_SIZE) && (ctx->bi->clip.height<ADAPTATION_SIZE)) {
			r2d->surface_clear(surf->the_surface, &ctx->bi->clip, ctx->aspect.fill_color);
		} else 
#endif
		{
			/*push path*/
			r2d->surface_set_path(surf->the_surface, path);
			VS2D_DoFill(surf, ctx, brush);
			r2d->surface_set_path(surf->the_surface, NULL);
		}
	}

	if (dostrike) {
#if ADAPTATION_SIZE
		if ((ctx->bi->clip.width<ADAPTATION_SIZE) && (ctx->bi->clip.height<ADAPTATION_SIZE)) {
		} else 
#endif
		{
			StrikeInfo2D *si = drawctx_get_strikeinfo(surf->render, ctx, path);
			if (si && si->outline) {
				if (ctx->aspect.line_texture) {
					VS2D_TexturePathIntern(surf, si->outline, ctx->aspect.line_texture, ctx);
				} else {
					r2d->surface_set_path(surf->the_surface, si->outline);
					VS2D_DoFill(surf, ctx, pen);
				}
				/*that's ugly, but we cannot cache path outline for IFS2D/ILS2D*/
				if (path && !(ctx->flags & CTX_IS_TEXT) && (path!=ctx->drawable->path) ) {
					gf_path_del(si->outline);
					si->outline = NULL;
				}
			}
		}
	}

	if (surf->render->compositor->draw_bvol) draw_clipper(surf, ctx);
}
static void TraverseIFS2D(GF_Node *node, void *rs, Bool is_destroy)
{
	DrawableContext *ctx;
	M_IndexedFaceSet2D *ifs2D = (M_IndexedFaceSet2D *)node;
	Drawable *stack = (Drawable *)gf_node_get_private(node);
	GF_TraverseState *tr_state = (GF_TraverseState *)rs;

	if (is_destroy) {
		drawable_node_del(node);
		return;
	}
	if (!ifs2D->coord) return;

	ifs2d_check_changes(node, stack, tr_state);

	switch (tr_state->traversing_mode) {
	case TRAVERSE_DRAW_2D:
		IFS2D_Draw(node, tr_state);
		return;
#ifndef GPAC_DISABLE_3D
	case TRAVERSE_DRAW_3D:
	{
		DrawAspect2D asp;

		if (!stack->mesh) {
			stack->mesh = new_mesh();
			mesh_new_ifs2d(stack->mesh, node);
		}

		memset(&asp, 0, sizeof(DrawAspect2D));
		drawable_get_aspect_2d_mpeg4(node, &asp, tr_state);
		if (ifs2D->color && !GF_COL_A(asp.fill_color) ) {
			/*use special func to disable outline recompute and handle recompute ourselves*/
			StrikeInfo2D *si = drawable_get_strikeinfo(tr_state->visual->compositor, stack, &asp, tr_state->appear, NULL, 0, tr_state);
			if (!si->mesh_outline) {
				si->mesh_outline = new_mesh();
				mesh_new_ils(si->mesh_outline, ifs2D->coord, &ifs2D->coordIndex, ifs2D->color, &ifs2D->colorIndex, ifs2D->colorPerVertex, 1);
			}
			visual_3d_mesh_strike(tr_state, si->mesh_outline, asp.pen_props.width, asp.line_scale, asp.pen_props.dash);
		} else {
			visual_3d_draw_2d_with_aspect(stack, tr_state, &asp);
		}
		return;
	} 
#endif
	case TRAVERSE_PICK:
		vrml_drawable_pick(stack, tr_state);
		return;
	case TRAVERSE_GET_BOUNDS:
		gf_path_get_bounds(stack->path, &tr_state->bounds);
		return;
	case TRAVERSE_SORT:
#ifndef GPAC_DISABLE_3D
		if (tr_state->visual->type_3d) return;
#endif

		ctx = drawable_init_context_mpeg4(stack, tr_state);
		if (!ctx) return;
		drawable_finalize_sort(ctx, tr_state, NULL);
		return;
	}
}