示例#1
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);
}
示例#2
0
文件: path2d.c 项目: erelh/gpac
GF_EXPORT
GF_Path *gf_path_get_flatten(GF_Path *gp)
{
	GF_Path *ngp;
	Fixed fineness;
	u32 i, *countour;
	GF_Point2D *pt;
	if (!gp || !gp->n_points) return NULL;

	if (gp->flags & GF_PATH_FLATTENED) return gf_path_clone(gp);

	/*avoid too high precision */
	fineness = MAX(FIX_ONE - gp->fineness, FIX_ONE / 100);

	ngp = gf_path_new();
	pt = &gp->points[0];
	gf_path_add_move_to_vec(ngp, pt);
	countour = gp->contours;
	for (i=1; i<gp->n_points; ) {
		switch (gp->tags[i]) {
		case GF_PATH_CURVE_ON:
		case GF_PATH_CLOSE:
			pt = &gp->points[i];
			if (*countour == i-1) {
				gf_path_add_move_to_vec(ngp, pt);
				countour++;
			} else {
				gf_path_add_line_to_vec(ngp, pt);
			}
			if (gp->tags[i]==GF_PATH_CLOSE) gf_path_close(ngp);
			i++;
			break;
		case GF_PATH_CURVE_CONIC:
		{
			GF_Point2D *ctl, *end, c1, c2;
			ctl = &gp->points[i];
			end = &gp->points[i+1];
			c1.x = pt->x + 2*(ctl->x - pt->x)/3;
			c1.y = pt->y + 2*(ctl->y - pt->y)/3;
			c2.x = c1.x + (end->x - pt->x) / 3;
			c2.y = c1.y + (end->y - pt->y) / 3;

			gf_subdivide_cubic(ngp, pt->x, pt->y, c1.x, c1.y, c2.x, c2.y, end->x, end->y, fineness);
			pt = end;
			if (gp->tags[i+1]==GF_PATH_CLOSE) gf_path_close(ngp);
			i+=2;
		}
			break;
		case GF_PATH_CURVE_CUBIC:
			gf_subdivide_cubic(ngp, pt->x, pt->y, gp->points[i].x, gp->points[i].y, gp->points[i+1].x, gp->points[i+1].y, gp->points[i+2].x, gp->points[i+2].y, fineness);
			pt = &gp->points[i+2];
			if (gp->tags[i+2]==GF_PATH_CLOSE) gf_path_close(ngp);
			i+=3;
			break;
		}
	}
	if (gp->flags & GF_PATH_FILL_ZERO_NONZERO) ngp->flags |= GF_PATH_FILL_ZERO_NONZERO;
	ngp->flags |= (GF_PATH_BBOX_DIRTY | GF_PATH_FLATTENED);
	return ngp;
}
示例#3
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->is_attached) 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);
}
示例#4
0
GF_FontManager *gf_font_manager_new(GF_User *user)
{
	char *def_font = "SERIF";
	u32 i, count;
	GF_FontManager *font_mgr;
	GF_FontReader *ifce;
	const char *opt;

	ifce = NULL;
	opt = gf_cfg_get_key(user->config, "FontEngine", "FontReader");
	if (opt) {
		ifce = (GF_FontReader *) gf_modules_load_interface_by_name(user->modules, opt, GF_FONT_READER_INTERFACE);
		if (ifce && ifce->init_font_engine(ifce) != GF_OK) {
			gf_modules_close_interface((GF_BaseInterface *)ifce);
			ifce = NULL;
		}
	}

	if (!ifce) {
		count = gf_modules_get_count(user->modules);
		for (i=0; i<count; i++) {
			ifce = (GF_FontReader *) gf_modules_load_interface(user->modules, i, GF_FONT_READER_INTERFACE);
			if (!ifce) continue;

			if (ifce->init_font_engine(ifce) != GF_OK) {
				gf_modules_close_interface((GF_BaseInterface *)ifce);
				ifce = NULL;
				continue;
			}

			gf_cfg_set_key(user->config, "FontEngine", "FontReader", ifce->module_name);
			break;
		}
	}
	GF_SAFEALLOC(font_mgr, GF_FontManager);
	font_mgr->reader = ifce;
	font_mgr->id_buffer_size = 20;
	font_mgr->id_buffer = gf_malloc(sizeof(u32)*font_mgr->id_buffer_size);
	gf_font_manager_set_font(font_mgr, &def_font, 1, 0);
	font_mgr->default_font = font_mgr->font;

	font_mgr->line_path= gf_path_new();
	gf_path_add_move_to(font_mgr->line_path, -FIX_ONE/2, FIX_ONE/2);
	gf_path_add_line_to(font_mgr->line_path, FIX_ONE/2, FIX_ONE/2);
	gf_path_add_line_to(font_mgr->line_path, FIX_ONE/2, -FIX_ONE/2);
	gf_path_add_line_to(font_mgr->line_path, -FIX_ONE/2, -FIX_ONE/2);
	gf_path_close(font_mgr->line_path);

	opt = gf_cfg_get_key(user->config, "FontEngine", "WaitForFontLoad");
	if (!opt) gf_cfg_set_key(user->config, "FontEngine", "WaitForFontLoad", "no");
	if (opt && !strcmp(opt, "yes")) font_mgr->wait_font_load = 1;

	return font_mgr;
}
示例#5
0
static FSItem *new_fs_item(FSStack *st, u32 line_col, u32 fill_col, Fixed width)
{
	FSItem *item;
	GF_SAFEALLOC(item, FSItem);
	gf_list_add(st->items, item);
	item->fill_col = fill_col;
	item->width = width;
	item->line_col = line_col;
	item->path = gf_path_new();
	return item;
}
示例#6
0
static void draw_clipper(VisualSurface2D *surf, struct _drawable_context *ctx)
{
	GF_PenSettings clipset;
	GF_Path *clippath, *cliper;
	GF_Raster2D *r2d = surf->render->compositor->r2d;

	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);
	r2d->surface_set_matrix(surf->the_surface, NULL);
	r2d->surface_set_clipper(surf->the_surface, NULL);
	r2d->surface_set_path(surf->the_surface, cliper);
	r2d->stencil_set_brush_color(surf->the_pen, 0xFF000000);
	r2d->surface_fill(surf->the_surface, surf->the_pen);
	gf_path_del(cliper);
}
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);
}
示例#8
0
void VS2D_FillRect(VisualSurface2D *surf, DrawableContext *ctx, GF_Rect *_rc, u32 color, u32 strike_color)
{
	GF_Path *path;
	GF_Rect *rc;
	GF_Raster2D *r2d = surf->render->compositor->r2d;
#ifdef SKIP_DRAW
	return;
#endif

	if (!surf->the_surface) return;
	if (!color && !strike_color) return;

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

	/*no aa*/
	VS2D_SetOptions(surf->render, surf->the_surface, 0, 1);
	if (_rc) {
		rc = _rc;
		r2d->surface_set_matrix(surf->the_surface, &ctx->transform);
	}
	else {
		rc = &ctx->bi->unclip;
		r2d->surface_set_matrix(surf->the_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*/
		r2d->surface_set_path(surf->the_surface, path);
		r2d->stencil_set_brush_color(surf->the_brush, color);
		VS2D_DoFill(surf, ctx, surf->the_brush);
		r2d->surface_set_path(surf->the_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;
		r2d->stencil_set_brush_color(surf->the_brush, strike_color);
		outline = gf_path_get_outline(path,  pen);	
		outline->flags &= ~GF_PATH_FILL_ZERO_NONZERO;
		r2d->surface_set_path(surf->the_surface, outline);
		VS2D_DoFill(surf, ctx, surf->the_brush);
		r2d->surface_set_path(surf->the_surface, NULL);
		gf_path_del(outline);
	}

	gf_path_del(path);
}
示例#9
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);
}
示例#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);
}
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);
}