vg_init_object(&path->base, vg_current_context(), VG_OBJECT_PATH);
path->caps = capabilities & VG_PATH_CAPABILITY_ALL;
- vg_context_add_object(vg_current_context(), VG_OBJECT_PATH, path);
+ vg_context_add_object(vg_current_context(), &path->base);
path->datatype = dt;
path->scale = scale;
return path;
}
+static void polygon_array_cleanup(struct polygon_array *polyarray)
+{
+ if (polyarray->array) {
+ VGint i;
+
+ for (i = 0; i < polyarray->array->num_elements; i++) {
+ struct polygon *p = ((struct polygon **) polyarray->array->data)[i];
+ polygon_destroy(p);
+ }
+
+ array_destroy(polyarray->array);
+ polyarray->array = NULL;
+ }
+}
+
void path_destroy(struct path *p)
{
- vg_context_remove_object(vg_current_context(), VG_OBJECT_PATH, p);
+ vg_context_remove_object(vg_current_context(), &p->base);
array_destroy(p->segments);
array_destroy(p->control_points);
- array_destroy(p->fill_polys.polygon_array.array);
+
+ polygon_array_cleanup(&p->fill_polys.polygon_array);
if (p->stroked.path)
path_destroy(p->stroked.path);
- free(p);
+ vg_free_object(&p->base);
+
+ FREE(p);
}
VGbitfield path_capabilities(struct path *p)
}
}
-
static void polygon_array_calculate_bounds( struct polygon_array *polyarray )
{
struct array *polys = polyarray->array;
unsigned i;
assert(polys);
- assert(polys->num_elements);
+
+ if (!polys->num_elements) {
+ polyarray->min_x = 0.0f;
+ polyarray->min_y = 0.0f;
+ polyarray->max_x = 0.0f;
+ polyarray->max_y = 0.0f;
+ return;
+ }
+
polygon_bounding_rect((((struct polygon**)polys->data)[0]), bounds);
min_x = bounds[0];
min_y = bounds[1];
void *coords = (VGfloat *)p->control_points->data;
struct array *array;
+ memset(data, 0, sizeof(data));
+
if (p->fill_polys.polygon_array.array)
{
if (memcmp( &p->fill_polys.matrix,
return &p->fill_polys.polygon_array;
}
else {
- array_destroy( p->fill_polys.polygon_array.array );
- p->fill_polys.polygon_array.array = NULL;
+ polygon_array_cleanup(&p->fill_polys.polygon_array);
}
}
- array = array_create(sizeof(struct array*));
+ /* an array of pointers to polygons */
+ array = array_create(sizeof(struct polygon *));
sx = sy = px = py = ox = oy = 0.f;
- current = polygon_create(32);
+ if (p->num_segments)
+ current = polygon_create(32);
for (i = 0; i < p->num_segments; ++i) {
VGubyte segment = ((VGubyte*)(p->segments->data))[i];
}
break;
case VG_SCUBIC_TO: {
- VGfloat x0, y0, x1, y1, x2, y2, x3, y3;
+ VGfloat x1, y1, x2, y2, x3, y3;
data_at(&pd->coords, pd->path, 0, 4, data);
- x0 = pd->ox;
- y0 = pd->oy;
x1 = 2*pd->ox-pd->px;
y1 = 2*pd->oy-pd->py;
x2 = data[0];
default:
abort();
assert(!"Unknown segment!");
+ return 0;
}
}
return stroker.base.path;
}
-void path_render(struct path *p, VGbitfield paintModes)
+void path_render(struct path *p, VGbitfield paintModes,
+ struct matrix *mat)
{
struct vg_context *ctx = vg_current_context();
- struct matrix *mat = &ctx->state.vg.path_user_to_surface_matrix;
+ struct matrix paint_matrix;
vg_validate_state(ctx);
mat->m[3], mat->m[4], mat->m[5],
mat->m[6], mat->m[7], mat->m[8]);
#endif
- if (paintModes & VG_FILL_PATH) {
+ if ((paintModes & VG_FILL_PATH) &&
+ vg_get_paint_matrix(ctx,
+ &ctx->state.vg.fill_paint_to_user_matrix,
+ mat,
+ &paint_matrix)) {
/* First the fill */
+ shader_set_surface_matrix(ctx->shader, mat);
shader_set_paint(ctx->shader, ctx->state.vg.fill_paint);
+ shader_set_paint_matrix(ctx->shader, &paint_matrix);
shader_bind(ctx->shader);
- path_fill(p, mat);
+ path_fill(p);
}
- if (paintModes & VG_STROKE_PATH){
+ if ((paintModes & VG_STROKE_PATH) &&
+ vg_get_paint_matrix(ctx,
+ &ctx->state.vg.stroke_paint_to_user_matrix,
+ mat,
+ &paint_matrix)) {
/* 8.7.5: "line width less than or equal to 0 prevents stroking from
* taking place."*/
if (ctx->state.vg.stroke.line_width.f <= 0)
return;
+ shader_set_surface_matrix(ctx->shader, mat);
shader_set_paint(ctx->shader, ctx->state.vg.stroke_paint);
+ shader_set_paint_matrix(ctx->shader, &paint_matrix);
shader_bind(ctx->shader);
path_stroke(p);
}
}
-void path_fill(struct path *p, struct matrix *mat)
+void path_fill(struct path *p)
{
struct vg_context *ctx = vg_current_context();
+ struct matrix identity;
+
+ matrix_load_identity(&identity);
+
{
- struct polygon_array *polygon_array = path_get_fill_polygons(p, mat);
+ struct polygon_array *polygon_array = path_get_fill_polygons(p, &identity);
struct array *polys = polygon_array->array;
if (!polygon_array || !polys || !polys->num_elements) {
void path_stroke(struct path *p)
{
struct vg_context *ctx = vg_current_context();
- struct matrix *mat = &ctx->state.vg.path_user_to_surface_matrix;
VGFillRule old_fill = ctx->state.vg.fill_rule;
struct matrix identity;
struct path *stroke;
if (stroke && !path_is_empty(stroke)) {
ctx->state.vg.fill_rule = VG_NON_ZERO;
- path_fill(stroke, mat);
+ path_fill(stroke);
ctx->state.vg.fill_rule = old_fill;
}