Ejemplo n.º 1
0
GF_Err visual_2d_init_raster(GF_VisualManager *visual)
{
	GF_Raster2D *raster = visual->compositor->rasterizer;
	if (!visual->raster_surface) {
		visual->raster_surface = raster->surface_new(raster, visual->center_coords);
		if (!visual->raster_surface) return GF_IO_ERR;
	}
	return visual->GetSurfaceAccess(visual);
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
static void visual_2d_fill_path(GF_VisualManager *visual, DrawableContext *ctx, GF_STENCIL stencil, GF_TraverseState *tr_state, Bool is_erase)
{
	Bool has_modif = GF_FALSE;
	GF_IRect clip;
	GF_Raster2D *raster = visual->compositor->rasterizer;

	/*background & direct drawing : use ctx clip*/
	if ((ctx->flags & CTX_IS_BACKGROUND) || tr_state->immediate_draw) {
		if (ctx->bi->clip.width && ctx->bi->clip.height) {
			GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Visual2D] Redrawing node %s[%s] (direct draw)\n", gf_node_get_log_name(ctx->drawable->node), gf_node_get_class_name(ctx->drawable->node) ));

			if (stencil) {
				raster->surface_set_clipper(visual->raster_surface, &ctx->bi->clip);
				raster->surface_fill(visual->raster_surface, stencil);
			} else {
				raster->surface_clear(visual->raster_surface, &ctx->bi->clip, 0);
			}

			has_modif = GF_TRUE;
		}
	}
	/*indirect drawing, draw path in all dirty areas*/
	else {
		u32 i;
		for (i=0; i<visual->to_redraw.count; i++) {
			/*there's an opaque region above, don't draw*/
#ifdef TRACK_OPAQUE_REGIONS
			if (!is_erase && (visual->draw_node_index<visual->to_redraw.list[i].opaque_node_index)) continue;
#endif
			clip = ctx->bi->clip;
			gf_irect_intersect(&clip, &visual->to_redraw.list[i].rect);
			if (clip.width && clip.height) {
				GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Visual2D] Redrawing node %s[%s] (indirect draw @ dirty rect idx %d)\n", gf_node_get_log_name(ctx->drawable->node), gf_node_get_class_name(ctx->drawable->node), i));
				if (stencil) {
					raster->surface_set_clipper(visual->raster_surface, &clip);
					raster->surface_fill(visual->raster_surface, stencil);
				} else {
					raster->surface_clear(visual->raster_surface, &clip, 0);
				}
				has_modif = 1;
			}
		}
	}
#ifndef GPAC_DISABLE_3D
	if (!is_erase)
		visual->nb_objects_on_canvas_since_last_ogl_flush++;
#endif
	if (has_modif) {
		visual->has_modif = 1;
#ifndef GPAC_DISABLE_3D
		if (!visual->offscreen && visual->compositor->hybrid_opengl && !is_erase)
			ra_union_rect(&visual->hybgl_drawn, &ctx->bi->clip);
#endif
	}
}
Ejemplo n.º 4
0
static void visual_2d_fill_path(GF_VisualManager *visual, DrawableContext *ctx, GF_STENCIL stencil, GF_TraverseState *tr_state)
{
	GF_IRect clip;
	GF_Raster2D *raster = visual->compositor->rasterizer;

	/*background & direct drawing : use ctx clip*/
	if ((ctx->flags & CTX_IS_BACKGROUND) || tr_state->immediate_draw) {
		if (ctx->bi->clip.width && ctx->bi->clip.height) {
			GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Visual2D] Redrawing node %s[%s] (direct draw)\n", gf_node_get_log_name(ctx->drawable->node), gf_node_get_class_name(ctx->drawable->node) ));

			if (stencil) {
				raster->surface_set_clipper(visual->raster_surface, &ctx->bi->clip);
				raster->surface_fill(visual->raster_surface, stencil);
			} else {
				raster->surface_clear(visual->raster_surface, &ctx->bi->clip, 0);
			}

			visual->has_modif = 1;
		}
	}
	/*indirect drawing, draw path in all dirty areas*/
	else {
		u32 i;
		for (i=0; i<visual->to_redraw.count; i++) {
			/*there's an opaque region above, don't draw*/
#ifdef TRACK_OPAQUE_REGIONS
			if (visual->draw_node_index<visual->to_redraw.opaque_node_index[i]) continue;
#endif
			clip = ctx->bi->clip;
			gf_irect_intersect(&clip, &visual->to_redraw.list[i]);
			if (clip.width && clip.height) {
				GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[Visual2D] Redrawing node %s[%s] (indirect draw @ dirty rect idx %d)\n", gf_node_get_log_name(ctx->drawable->node), gf_node_get_class_name(ctx->drawable->node), i));
				if (stencil) {
					raster->surface_set_clipper(visual->raster_surface, &clip);
					raster->surface_fill(visual->raster_surface, stencil);
				} else {
					raster->surface_clear(visual->raster_surface, &clip, 0);
				}
				visual->has_modif = 1;
			}
		}
	}
}
Ejemplo n.º 5
0
static void draw_clipper(GF_VisualManager *visual, struct _drawable_context *ctx)
{
	GF_PenSettings clipset;
	GF_Path *clippath, *cliper;
	GF_Raster2D *raster = visual->compositor->rasterizer;

	if (ctx->flags & CTX_IS_BACKGROUND) return;

	memset(&clipset, 0, sizeof(GF_PenSettings));
	clipset.width = 2*FIX_ONE;

	clippath = gf_path_new();
	gf_path_add_rect_center(clippath, ctx->bi->unclip.x + ctx->bi->unclip.width/2, ctx->bi->unclip.y - ctx->bi->unclip.height/2, ctx->bi->unclip.width, ctx->bi->unclip.height);
	cliper = gf_path_get_outline(clippath, clipset);
	gf_path_del(clippath);
	raster->surface_set_matrix(visual->raster_surface, NULL);
	raster->surface_set_clipper(visual->raster_surface, NULL);
	raster->surface_set_path(visual->raster_surface, cliper);
	raster->stencil_set_brush_color(visual->raster_brush, 0xFF000000);
	raster->surface_fill(visual->raster_surface, visual->raster_brush);
	gf_path_del(cliper);
}
Ejemplo n.º 6
0
static void visual_2d_set_options(GF_Compositor *compositor, GF_SURFACE rend, Bool forText, Bool no_antialias)
{
	GF_Raster2D *raster = compositor->rasterizer;
	if (no_antialias) {
		raster->surface_set_raster_level(rend, GF_RASTER_HIGH_SPEED);
	} else {
		switch (compositor->antiAlias) {
		case GF_ANTIALIAS_NONE:
			raster->surface_set_raster_level(rend, GF_RASTER_HIGH_SPEED);
			break;
		case GF_ANTIALIAS_TEXT:
			if (forText) {
				raster->surface_set_raster_level(rend, GF_RASTER_HIGH_QUALITY);
			} else {
				raster->surface_set_raster_level(rend, compositor->high_speed ? GF_RASTER_HIGH_QUALITY : GF_RASTER_MID);
			}
			break;
		case GF_ANTIALIAS_FULL:
		default:
			raster->surface_set_raster_level(rend, GF_RASTER_HIGH_QUALITY);
			break;
		}
	}
}
Ejemplo n.º 7
0
static void composite_update(GF_TextureHandler *txh)
{
	s32 w, h;
	GF_STENCIL stencil;
	M_Background2D *back;
	GF_TraverseState *tr_state;
	Bool invalidate_all;
	u32 new_pixel_format;
	GF_Compositor *compositor = (GF_Compositor *)txh->compositor;
	CompositeTextureStack *st = (CompositeTextureStack *) gf_node_get_private(txh->owner);
	GF_Raster2D *raster = st->visual->compositor->rasterizer;

	if (st->unsupported) return;


/*
	if (compositor->recompute_ar) {
		gf_node_dirty_set(txh->owner, 0, 0);
		return;
	}
*/
	if (!compositor->rebuild_offscreen_textures && (!compositor->text_edit_changed || !st->visual->has_text_edit ) && !gf_node_dirty_get(txh->owner)) {
		txh->needs_refresh = 0;
		return;
	}
	gf_node_dirty_clear(st->txh.owner, 0);

	new_pixel_format = 0;
	back = gf_list_get(st->visual->back_stack, 0);
	if (back && back->isBound) new_pixel_format = GF_PIXEL_RGB_24;
	else new_pixel_format = GF_PIXEL_RGBA;


#ifdef GPAC_USE_TINYGL
	/*TinyGL pixel format is fixed at compile time, we cannot override it !*/
	if (st->visual->type_3d) new_pixel_format = GF_PIXEL_RGBA;
#else

#ifndef GPAC_DISABLE_3D
	/*no alpha support in offscreen rendering*/
	if ( (st->visual->type_3d) && !(compositor->video_out->hw_caps & GF_VIDEO_HW_OPENGL_OFFSCREEN_ALPHA))
		new_pixel_format = GF_PIXEL_RGB_24;
#endif

	/*in OpenGL_ES, only RGBA can be safelly used with glReadPixels*/
#ifdef GPAC_USE_OGL_ES
	new_pixel_format = GF_PIXEL_RGBA;
#endif

#endif

	/*FIXME - we assume RGB+Depth+bitshape, we should check with the video out module*/
#if defined(GF_SR_USE_DEPTH) && !defined(GPAC_DISABLE_3D)
	if (st->visual->type_3d && (compositor->video_out->hw_caps & GF_VIDEO_HW_HAS_DEPTH) ) new_pixel_format = GF_PIXEL_RGBDS;
#endif


#ifndef GPAC_DISABLE_3D
	if (st->visual->type_3d>1) {
		w = ((M_CompositeTexture3D*)txh->owner)->pixelWidth;
		h = ((M_CompositeTexture3D*)txh->owner)->pixelHeight;
	} else
#endif
	{
		w = ((M_CompositeTexture2D*)txh->owner)->pixelWidth;
		h = ((M_CompositeTexture2D*)txh->owner)->pixelHeight;
	}

	/*internal GPAC hacks for testing color spaces*/
	if (w<-1) {
		w = -w;
		if (h<0) {
			h = -h;
			if (new_pixel_format==GF_PIXEL_RGBA) {
				new_pixel_format=GF_PIXEL_ARGB;
			} else {
				new_pixel_format=GF_PIXEL_BGR_24;
			}
		} else {
			if (new_pixel_format==GF_PIXEL_RGB_24) {
				new_pixel_format=GF_PIXEL_RGB_32;
			}
		}
	}
	else if (h<-1) {
		h = -h;
		if (new_pixel_format==GF_PIXEL_RGB_24) {
			new_pixel_format=GF_PIXEL_RGB_32;
		}
	}

	if (w<0) w = 0;
	if (h<0) h = 0;


	if (!w || !h) {
		if (txh->tx_io) {
#ifdef GPAC_USE_TINYGL
			if (st->tgl_ctx) ostgl_delete_context(st->tgl_ctx);
#endif
			gf_sc_texture_release(txh);
			if (txh->data) gf_free(txh->data);
			txh->data = NULL;
			txh->width = txh->height = txh->stride = 0;
		}
		return;
	}
	invalidate_all = compositor->rebuild_offscreen_textures;

	/*rebuild stencil*/
	if (!txh->tx_io
		|| (w != (s32) txh->width) || ( h != (s32) txh->height)
		|| (new_pixel_format != txh->pixelformat)
		) {

		Bool needs_stencil = 1;
		if (txh->tx_io) {
#ifdef GPAC_USE_TINYGL
			if (st->tgl_ctx) ostgl_delete_context(st->tgl_ctx);
#endif
			gf_sc_texture_release(txh);
			if (txh->data) 
				gf_free(txh->data);
			txh->data = NULL;
		}

		/*we don't use rect ext because of no support for texture transforms*/
		if (1
#ifndef GPAC_DISABLE_3D
			|| compositor->gl_caps.npot_texture
#endif
			) {
			st->txh.width = w;
			st->txh.height = h;
			st->sx = st->sy = FIX_ONE;
		} else {
			st->txh.width = 2;
			while (st->txh.width<(u32)w) st->txh.width*=2;
			st->txh.height = 2;
			while (st->txh.height<(u32)h) st->txh.height*=2;

			st->sx = INT2FIX(st->txh.width) / w;
			st->sy = INT2FIX(st->txh.height) / h;
		}

		gf_sc_texture_allocate(txh);
		txh->pixelformat = new_pixel_format;
		switch (new_pixel_format) {
		case GF_PIXEL_RGBA:
		case GF_PIXEL_ARGB:
			txh->stride = txh->width * 4;
			txh->transparent = 1;
			break;
		case GF_PIXEL_RGB_565:
			txh->stride = txh->width * 2;
			txh->transparent = 0;
			break;
		case GF_PIXEL_RGBDS:
			txh->stride = txh->width * 4;
			txh->transparent = 1;
			break;
		case GF_PIXEL_RGB_24:
			txh->stride = txh->width * 3;
			txh->transparent = 0;
			break;
		}

		st->visual->width = txh->width;
		st->visual->height = txh->height;

		stencil = raster->stencil_new(raster, GF_STENCIL_TEXTURE);
		/*TODO - add support for compositeTexture3D when root is 2D visual*/
#ifndef GPAC_DISABLE_3D
		if (st->visual->type_3d) {
			GF_Compositor *compositor = st->visual->compositor;
			/*figure out what to do if main visual (eg video out) is not in OpenGL ...*/
			if (!compositor->visual->type_3d) {
				/*create an offscreen window for OpenGL rendering*/
				if ((compositor->offscreen_width < st->txh.width) || (compositor->offscreen_height < st->txh.height)) {
#ifndef GPAC_USE_TINYGL
					GF_Err e;
					GF_Event evt;
					compositor->offscreen_width = MAX(compositor->offscreen_width, st->txh.width);
					compositor->offscreen_height = MAX(compositor->offscreen_height, st->txh.height);

					evt.type = GF_EVENT_VIDEO_SETUP;
					evt.setup.width = compositor->offscreen_width;
					evt.setup.height = compositor->offscreen_height;
					evt.setup.back_buffer = 0;
					evt.setup.opengl_mode = 2;
					e = compositor->video_out->ProcessEvent(compositor->video_out, &evt);
					if (e) {
						gf_sc_texture_release(txh);
						st->unsupported = 1;
						return;
					}
					/*reload openGL ext*/
					gf_sc_load_opengl_extensions(compositor, 1);
#endif
				}
			} else {
				needs_stencil = 0;
			}
		}
#endif

		if (needs_stencil) {
			txh->data = (char*)gf_malloc(sizeof(unsigned char) * txh->stride * txh->height);
			memset(txh->data, 0, sizeof(unsigned char) * txh->stride * txh->height);
			
			/*set stencil texture - we don't check error as an image could not be supported by the rasterizer
			but still supported by the blitter (case of RGBD/RGBDS)*/
			raster->stencil_set_texture(stencil, txh->data, txh->width, txh->height, txh->stride, txh->pixelformat, txh->pixelformat, 0);

#ifdef GPAC_USE_TINYGL
			if (st->visual->type_3d && !compositor->visual->type_3d) {
				st->tgl_ctx = ostgl_create_context(txh->width, txh->height, txh->transparent ? 32 : 24, &txh->data, 1);
				GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[CompositeTexture] Creating TinyGL Offscreen context %p (%d %d - pf %s)\n", st->tgl_ctx, txh->width, txh->width, gf_4cc_to_str(txh->pixelformat)));
			}
#endif

		}
		invalidate_all = 1;
		gf_sc_texture_set_stencil(txh, stencil);
	}
	if (!txh->tx_io) return;

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

#ifdef GPAC_USE_TINYGL
	if (st->tgl_ctx) ostgl_make_current(st->tgl_ctx, 0);
#endif

	GF_SAFEALLOC(tr_state, GF_TraverseState);
	tr_state->vrml_sensors = gf_list_new();
	tr_state->visual = st->visual;
	tr_state->invalidate_all = invalidate_all;

	tr_state->immediate_draw = st->visual->compositor->traverse_state->immediate_draw;

	gf_mx2d_init(tr_state->transform);
	gf_cmx_init(&tr_state->color_mat);

	tr_state->backgrounds = st->visual->back_stack;
	tr_state->viewpoints = st->visual->view_stack;
	tr_state->pixel_metrics = gf_sg_use_pixel_metrics(gf_node_get_graph(st->txh.owner));
	tr_state->min_hsize = INT2FIX( MIN(txh->width, txh->height) ) / 2;
	tr_state->vp_size.x = INT2FIX(txh->width);
	tr_state->vp_size.y = INT2FIX(txh->height);

	composite_do_bindable(st->txh.owner, tr_state, st->first);
	st->first = 0;

	GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[CompositeTexture] Entering draw cycle\n"));

	txh->needs_refresh = visual_draw_frame(st->visual, st->txh.owner, tr_state, 0);
	txh->transparent = (st->visual->last_had_back==2) ? 0 : 1;


	if (!compositor->edited_text && st->visual->has_text_edit) 
		st->visual->has_text_edit = 0;


	/*set active viewport in image coordinates top-left=(0, 0), not in BIFS*/
	if (0 && gf_list_count(st->visual->view_stack)) {
		M_Viewport *vp = (M_Viewport *)gf_list_get(st->visual->view_stack, 0);

		if (vp->isBound) {
			SFVec2f size = vp->size;
			if (size.x >=0 && size.y>=0) {
				/*FIXME - we need tracking of VP changes*/
				txh->needs_refresh = 1;
			}
		}
	}

	if (txh->needs_refresh) {
#ifndef GPAC_DISABLE_3D
		if (st->visual->camera.is_3D) {
			if (st->visual->compositor->visual->type_3d) {
#ifndef GPAC_USE_TINYGL
				gf_sc_copy_to_texture(&st->txh);
#else
				/*in TinyGL we only need to push associated bitmap to the texture*/
				gf_sc_texture_push_image(&st->txh, 0, 0);
#endif
			} else {

#ifndef GPAC_USE_TINYGL
				gf_sc_copy_to_stencil(&st->txh);

#else

				if (txh->pixelformat==GF_PIXEL_RGBDS) gf_get_tinygl_depth(&st->txh);
#endif
			}
		} else
#endif
		{
			if (raster->stencil_texture_modified) raster->stencil_texture_modified(stencil);
			gf_sc_texture_set_stencil(txh, stencil);
		}
		gf_sc_invalidate(st->txh.compositor, NULL);
	}
	gf_list_del(tr_state->vrml_sensors);
	gf_free(tr_state);
	GF_LOG(GF_LOG_DEBUG, GF_LOG_COMPOSE, ("[CompositeTexture] Leaving draw cycle\n"));
}
Ejemplo n.º 8
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);
}
Ejemplo n.º 9
0
void visual_2d_fill_irect(GF_VisualManager *visual, GF_IRect *rc, u32 fill, u32 strike)
{
	GF_Path *path;
	GF_Path *outline;
	GF_PenSettings pen;
	GF_Raster2D *raster = visual->compositor->rasterizer;
#ifdef SKIP_DRAW
	return;
#endif

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

	if (!fill && !strike ) return;

	/*no aa*/
	visual_2d_set_options(visual->compositor, visual->raster_surface, 0, 1);
	raster->surface_set_matrix(visual->raster_surface, NULL);

	raster->surface_set_raster_level(visual->raster_surface, GF_RASTER_HIGH_SPEED);
	raster->surface_set_matrix(visual->raster_surface, NULL);

	path = gf_path_new();
	gf_path_add_move_to(path, INT2FIX(rc->x-1), INT2FIX(rc->y+2-rc->height));
	gf_path_add_line_to(path, INT2FIX(rc->x+rc->width-2), INT2FIX(rc->y+2-rc->height));
	gf_path_add_line_to(path, INT2FIX(rc->x+rc->width), INT2FIX(rc->y));
	gf_path_add_line_to(path, INT2FIX(rc->x), INT2FIX(rc->y));
	gf_path_close(path);

	if (fill) {
		raster->surface_set_path(visual->raster_surface, path);
		raster->stencil_set_brush_color(visual->raster_brush, fill);

		raster->surface_set_clipper(visual->raster_surface, rc);
		raster->surface_fill(visual->raster_surface, visual->raster_brush);

		raster->surface_set_path(visual->raster_surface, NULL);
	}

	if (strike) {
		memset(&pen, 0, sizeof(GF_PenSettings));
		pen.width = 2;
		pen.align = GF_PATH_LINE_INSIDE;
		pen.join = GF_LINE_JOIN_BEVEL;
		outline = gf_path_get_outline(path, pen);
		outline->flags &= ~GF_PATH_FILL_ZERO_NONZERO;

		raster->surface_set_path(visual->raster_surface, outline);
		raster->stencil_set_brush_color(visual->raster_brush, strike);

		raster->surface_set_clipper(visual->raster_surface, rc);
		raster->surface_fill(visual->raster_surface, visual->raster_brush);

		raster->surface_set_path(visual->raster_surface, NULL);
		gf_path_del(outline);
	}
	gf_path_del(path);
#ifndef GPAC_DISABLE_3D
	if (!visual->offscreen && visual->compositor->hybrid_opengl)
		ra_union_rect(&visual->hybgl_drawn, rc);
#endif
}
Ejemplo n.º 10
0
void visual_2d_fill_rect(GF_VisualManager *visual, DrawableContext *ctx, GF_Rect *_rc, u32 color, u32 strike_color, GF_TraverseState *tr_state)
{
	GF_Path *path;
	GF_Rect *rc;
	GF_Raster2D *raster = visual->compositor->rasterizer;
#ifdef SKIP_DRAW
	return;
#endif

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

	if (!color && !strike_color) return;

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

	/*no aa*/
	visual_2d_set_options(visual->compositor, visual->raster_surface, 0, 1);
	if (_rc) {
		rc = _rc;
		raster->surface_set_matrix(visual->raster_surface, &ctx->transform);
	}
	else {
		rc = &ctx->bi->unclip;
		raster->surface_set_matrix(visual->raster_surface, NULL);
	}

	path = gf_path_new();
	gf_path_add_move_to(path, rc->x, rc->y-rc->height);
	gf_path_add_line_to(path, rc->x+rc->width, rc->y-rc->height);
	gf_path_add_line_to(path, rc->x+rc->width, rc->y);
	gf_path_add_line_to(path, rc->x, rc->y);
	gf_path_close(path);


	if (color) {
		/*push path*/
		raster->surface_set_path(visual->raster_surface, path);
		raster->stencil_set_brush_color(visual->raster_brush, color);
		visual_2d_fill_path(visual, ctx, visual->raster_brush, tr_state, 0);
		raster->surface_set_path(visual->raster_surface, NULL);
	}
	if (strike_color) {
		GF_Path *outline;
		GF_PenSettings pen;
		memset(&pen, 0, sizeof(GF_PenSettings));
		pen.width = 1;
		pen.join = GF_LINE_JOIN_BEVEL;
		pen.dash = GF_DASH_STYLE_DOT;
		raster->stencil_set_brush_color(visual->raster_brush, strike_color);
		outline = gf_path_get_outline(path,  pen);
		outline->flags &= ~GF_PATH_FILL_ZERO_NONZERO;
		raster->surface_set_path(visual->raster_surface, outline);
		visual_2d_fill_path(visual, ctx, visual->raster_brush, tr_state, 0);
		raster->surface_set_path(visual->raster_surface, NULL);
		gf_path_del(outline);
	}

	gf_path_del(path);
}
Ejemplo n.º 11
0
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);
}
Ejemplo n.º 12
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;
}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 14
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);
}