Merge commit 'e5b9b5300696c02f872dc8f124fc96402e4570b4' into new-svg-renderer

This commit is contained in:
Leon Styhre 2022-10-26 20:03:32 +02:00
commit 3e9ddde2f3
9 changed files with 263 additions and 386 deletions

View file

@ -418,7 +418,6 @@ static void blend_solid(plutovg_surface_t* surface, plutovg_operator_t op, const
} }
} }
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define BUFFER_SIZE 1024 #define BUFFER_SIZE 1024
static void blend_linear_gradient(plutovg_surface_t* surface, plutovg_operator_t op, const plutovg_rle_t* rle, const gradient_data_t* gradient) static void blend_linear_gradient(plutovg_surface_t* surface, plutovg_operator_t op, const plutovg_rle_t* rle, const gradient_data_t* gradient)
{ {
@ -445,7 +444,7 @@ static void blend_linear_gradient(plutovg_surface_t* surface, plutovg_operator_t
int x = spans->x; int x = spans->x;
while(length) while(length)
{ {
int l = MIN(length, BUFFER_SIZE); int l = plutovg_min(length, BUFFER_SIZE);
fetch_linear_gradient(buffer, &v, gradient, spans->y, x, l); fetch_linear_gradient(buffer, &v, gradient, spans->y, x, l);
uint32_t* target = (uint32_t*)(surface->data + spans->y * surface->stride) + x; uint32_t* target = (uint32_t*)(surface->data + spans->y * surface->stride) + x;
func(target, l, buffer, spans->coverage); func(target, l, buffer, spans->coverage);
@ -479,7 +478,7 @@ static void blend_radial_gradient(plutovg_surface_t* surface, plutovg_operator_t
int x = spans->x; int x = spans->x;
while(length) while(length)
{ {
int l = MIN(length, BUFFER_SIZE); int l = plutovg_min(length, BUFFER_SIZE);
fetch_radial_gradient(buffer, &v, gradient, spans->y, x, l); fetch_radial_gradient(buffer, &v, gradient, spans->y, x, l);
uint32_t* target = (uint32_t*)(surface->data + spans->y * surface->stride) + x; uint32_t* target = (uint32_t*)(surface->data + spans->y * surface->stride) + x;
func(target, l, buffer, spans->coverage); func(target, l, buffer, spans->coverage);
@ -491,7 +490,6 @@ static void blend_radial_gradient(plutovg_surface_t* surface, plutovg_operator_t
} }
} }
#define CLAMP(v, lo, hi) ((v) < (lo) ? (lo) : (hi) < (v) ? (hi) : (v))
#define FIXED_SCALE (1 << 16) #define FIXED_SCALE (1 << 16)
static void blend_transformed_argb(plutovg_surface_t* surface, plutovg_operator_t op, const plutovg_rle_t* rle, const texture_data_t* texture) static void blend_transformed_argb(plutovg_surface_t* surface, plutovg_operator_t op, const plutovg_rle_t* rle, const texture_data_t* texture)
{ {
@ -520,13 +518,13 @@ static void blend_transformed_argb(plutovg_surface_t* surface, plutovg_operator_
const int coverage = (spans->coverage * texture->const_alpha) >> 8; const int coverage = (spans->coverage * texture->const_alpha) >> 8;
while(length) while(length)
{ {
int l = MIN(length, BUFFER_SIZE); int l = plutovg_min(length, BUFFER_SIZE);
const uint32_t* end = buffer + l; const uint32_t* end = buffer + l;
uint32_t* b = buffer; uint32_t* b = buffer;
while(b < end) while(b < end)
{ {
int px = CLAMP(x >> 16, 0, image_width - 1); int px = plutovg_clamp(x >> 16, 0, image_width - 1);
int py = CLAMP(y >> 16, 0, image_height - 1); int py = plutovg_clamp(y >> 16, 0, image_height - 1);
*b = ((const uint32_t*)(texture->data + py * texture->stride))[px]; *b = ((const uint32_t*)(texture->data + py * texture->stride))[px];
x += fdx; x += fdx;
@ -614,7 +612,7 @@ static void blend_untransformed_tiled_argb(plutovg_surface_t* surface, plutovg_o
const int coverage = (spans->coverage * texture->const_alpha) >> 8; const int coverage = (spans->coverage * texture->const_alpha) >> 8;
while(length) while(length)
{ {
int l = MIN(image_width - sx, length); int l = plutovg_min(image_width - sx, length);
if(BUFFER_SIZE < l) if(BUFFER_SIZE < l)
l = BUFFER_SIZE; l = BUFFER_SIZE;
const uint32_t* src = (const uint32_t*)(texture->data + sy * texture->stride) + sx; const uint32_t* src = (const uint32_t*)(texture->data + sy * texture->stride) + sx;
@ -658,7 +656,7 @@ static void blend_transformed_tiled_argb(plutovg_surface_t* surface, plutovg_ope
int length = spans->len; int length = spans->len;
while(length) while(length)
{ {
int l = MIN(length, BUFFER_SIZE); int l = plutovg_min(length, BUFFER_SIZE);
const uint32_t* end = buffer + l; const uint32_t* end = buffer + l;
uint32_t* b = buffer; uint32_t* b = buffer;
int px16 = x % (image_width << 16); int px16 = x % (image_width << 16);
@ -696,13 +694,13 @@ static void blend_transformed_tiled_argb(plutovg_surface_t* surface, plutovg_ope
void plutovg_blend(plutovg_t* pluto, const plutovg_rle_t* rle) void plutovg_blend(plutovg_t* pluto, const plutovg_rle_t* rle)
{ {
plutovg_paint_t* source = pluto->state->source; plutovg_paint_t* source = &pluto->state->paint;
if(source->type == plutovg_paint_type_color) if(source->type == plutovg_paint_type_color)
plutovg_blend_color(pluto, rle, source->color); plutovg_blend_color(pluto, rle, &source->color);
else if(source->type == plutovg_paint_type_gradient) else if(source->type == plutovg_paint_type_gradient)
plutovg_blend_gradient(pluto, rle, source->gradient); plutovg_blend_gradient(pluto, rle, &source->gradient);
else else
plutovg_blend_texture(pluto, rle, source->texture); plutovg_blend_texture(pluto, rle, &source->texture);
} }
void plutovg_blend_color(plutovg_t* pluto, const plutovg_rle_t* rle, const plutovg_color_t* color) void plutovg_blend_color(plutovg_t* pluto, const plutovg_rle_t* rle, const plutovg_color_t* color)

View file

@ -327,14 +327,13 @@ void plutovg_path_add_rect(plutovg_path_t* path, double x, double y, double w, d
plutovg_path_close(path); plutovg_path_close(path);
} }
#define KAPPA 0.5522847498
void plutovg_path_add_round_rect(plutovg_path_t* path, double x, double y, double w, double h, double rx, double ry) void plutovg_path_add_round_rect(plutovg_path_t* path, double x, double y, double w, double h, double rx, double ry)
{ {
double right = x + w; double right = x + w;
double bottom = y + h; double bottom = y + h;
double cpx = rx * KAPPA; double cpx = rx * plutovg_kappa;
double cpy = ry * KAPPA; double cpy = ry * plutovg_kappa;
plutovg_path_move_to(path, x, y+ry); plutovg_path_move_to(path, x, y+ry);
plutovg_path_cubic_to(path, x, y+ry-cpy, x+rx-cpx, y, x+rx, y); plutovg_path_cubic_to(path, x, y+ry-cpy, x+rx-cpx, y, x+rx, y);
@ -355,8 +354,8 @@ void plutovg_path_add_ellipse(plutovg_path_t* path, double cx, double cy, double
double right = cx + rx; double right = cx + rx;
double bottom = cy + ry; double bottom = cy + ry;
double cpx = rx * KAPPA; double cpx = rx * plutovg_kappa;
double cpy = ry * KAPPA; double cpy = ry * plutovg_kappa;
plutovg_path_move_to(path, cx, top); plutovg_path_move_to(path, cx, top);
plutovg_path_cubic_to(path, cx+cpx, top, right, cy-cpy, right, cy); plutovg_path_cubic_to(path, cx+cpx, top, right, cy-cpy, right, cy);

View file

@ -7,69 +7,30 @@ void plutovg_color_init_rgb(plutovg_color_t* color, double r, double g, double b
void plutovg_color_init_rgba(plutovg_color_t* color, double r, double g, double b, double a) void plutovg_color_init_rgba(plutovg_color_t* color, double r, double g, double b, double a)
{ {
color->r = r; color->r = plutovg_clamp(r, 0.0, 1.0);
color->g = g; color->g = plutovg_clamp(g, 0.0, 1.0);
color->b = b; color->b = plutovg_clamp(b, 0.0, 1.0);
color->a = a; color->a = plutovg_clamp(a, 0.0, 1.0);
} }
plutovg_gradient_t* plutovg_gradient_create_linear(double x1, double y1, double x2, double y2) void plutovg_gradient_init_linear(plutovg_gradient_t* gradient, double x1, double y1, double x2, double y2)
{ {
plutovg_gradient_t* gradient = malloc(sizeof(plutovg_gradient_t));
gradient->ref = 1;
gradient->type = plutovg_gradient_type_linear; gradient->type = plutovg_gradient_type_linear;
gradient->spread = plutovg_spread_method_pad; gradient->spread = plutovg_spread_method_pad;
gradient->opacity = 1.0; gradient->opacity = 1.0;
plutovg_array_init(gradient->stops); plutovg_array_clear(gradient->stops);
plutovg_matrix_init_identity(&gradient->matrix); plutovg_matrix_init_identity(&gradient->matrix);
plutovg_gradient_set_values_linear(gradient, x1, y1, x2, y2); plutovg_gradient_set_values_linear(gradient, x1, y1, x2, y2);
return gradient;
} }
plutovg_gradient_t* plutovg_gradient_create_radial(double cx, double cy, double cr, double fx, double fy, double fr) void plutovg_gradient_init_radial(plutovg_gradient_t* gradient, double cx, double cy, double cr, double fx, double fy, double fr)
{ {
plutovg_gradient_t* gradient = malloc(sizeof(plutovg_gradient_t));
gradient->ref = 1;
gradient->type = plutovg_gradient_type_radial; gradient->type = plutovg_gradient_type_radial;
gradient->spread = plutovg_spread_method_pad; gradient->spread = plutovg_spread_method_pad;
gradient->opacity = 1.0; gradient->opacity = 1.0;
plutovg_array_init(gradient->stops); plutovg_array_clear(gradient->stops);
plutovg_matrix_init_identity(&gradient->matrix); plutovg_matrix_init_identity(&gradient->matrix);
plutovg_gradient_set_values_radial(gradient, cx, cy, cr, fx, fy, fr); plutovg_gradient_set_values_radial(gradient, cx, cy, cr, fx, fy, fr);
return gradient;
}
plutovg_gradient_t* plutovg_gradient_reference(plutovg_gradient_t* gradient)
{
++gradient->ref;
return gradient;
}
void plutovg_gradient_destroy(plutovg_gradient_t* gradient)
{
if(gradient==NULL)
return;
if(--gradient->ref==0)
{
free(gradient->stops.data);
free(gradient);
}
}
int plutovg_gradient_get_reference_count(const plutovg_gradient_t* gradient)
{
return gradient->ref;
}
void plutovg_gradient_set_type(plutovg_gradient_t* gradient, plutovg_gradient_type_t type)
{
gradient->type = type;
}
plutovg_gradient_type_t plutovg_gradient_get_type(const plutovg_gradient_t* gradient)
{
return gradient->type;
} }
void plutovg_gradient_set_spread(plutovg_gradient_t* gradient, plutovg_spread_method_t spread) void plutovg_gradient_set_spread(plutovg_gradient_t* gradient, plutovg_spread_method_t spread)
@ -99,26 +60,29 @@ void plutovg_gradient_add_stop_rgb(plutovg_gradient_t* gradient, double offset,
void plutovg_gradient_add_stop_rgba(plutovg_gradient_t* gradient, double offset, double r, double g, double b, double a) void plutovg_gradient_add_stop_rgba(plutovg_gradient_t* gradient, double offset, double r, double g, double b, double a)
{ {
if(offset < 0.0) offset = 0.0;
if(offset > 1.0) offset = 1.0;
plutovg_array_ensure(gradient->stops, 1); plutovg_array_ensure(gradient->stops, 1);
plutovg_gradient_stop_t* stops = gradient->stops.data; plutovg_gradient_stop_t* stops = gradient->stops.data;
int nstops = gradient->stops.size; int nstops = gradient->stops.size;
int i; int i = 0;
for(i = 0;i < nstops;i++) for(; i < nstops; i++) {
{ if(offset < stops[i].offset) {
if(offset < stops[i].offset)
{
memmove(&stops[i+1], &stops[i], (size_t)(nstops - i) * sizeof(plutovg_gradient_stop_t)); memmove(&stops[i+1], &stops[i], (size_t)(nstops - i) * sizeof(plutovg_gradient_stop_t));
break; break;
} }
} }
stops[i].offset = offset; plutovg_gradient_stop_t* stop = &stops[i];
stops[i].color.r = r; stop->offset = offset;
stops[i].color.g = g; plutovg_color_init_rgba(&stop->color, r, g, b, a);
stops[i].color.b = b; gradient->stops.size += 1;
stops[i].color.a = a; }
gradient->stops.size++; void plutovg_gradient_add_stop_color(plutovg_gradient_t* gradient, double offset, const plutovg_color_t* color)
{
plutovg_gradient_add_stop_rgba(gradient, offset, color->r, color->g, color->b, color->a);
} }
void plutovg_gradient_add_stop(plutovg_gradient_t* gradient, const plutovg_gradient_stop_t* stop) void plutovg_gradient_add_stop(plutovg_gradient_t* gradient, const plutovg_gradient_stop_t* stop)
@ -141,22 +105,27 @@ plutovg_gradient_stop_t* plutovg_gradient_get_stops(const plutovg_gradient_t* gr
return gradient->stops.data; return gradient->stops.data;
} }
plutovg_gradient_type_t plutovg_gradient_get_type(const plutovg_gradient_t* gradient)
{
return gradient->type;
}
void plutovg_gradient_get_values_linear(const plutovg_gradient_t* gradient, double* x1, double* y1, double* x2, double* y2) void plutovg_gradient_get_values_linear(const plutovg_gradient_t* gradient, double* x1, double* y1, double* x2, double* y2)
{ {
*x1 = gradient->values[0]; if(x1) *x1 = gradient->values[0];
*y1 = gradient->values[1]; if(y1) *y1 = gradient->values[1];
*x2 = gradient->values[2]; if(x2) *x2 = gradient->values[2];
*y2 = gradient->values[3]; if(y2) *y2 = gradient->values[3];
} }
void plutovg_gradient_get_values_radial(const plutovg_gradient_t* gradient, double* cx, double* cy, double* cr, double* fx, double* fy, double* fr) void plutovg_gradient_get_values_radial(const plutovg_gradient_t* gradient, double* cx, double* cy, double* cr, double* fx, double* fy, double* fr)
{ {
*cx = gradient->values[0]; if(cx) *cx = gradient->values[0];
*cy = gradient->values[1]; if(cy) *cy = gradient->values[1];
*cr = gradient->values[2]; if(cr) *cr = gradient->values[2];
*fx = gradient->values[3]; if(fx) *fx = gradient->values[3];
*fy = gradient->values[4]; if(fy) *fy = gradient->values[4];
*fr = gradient->values[5]; if(fr) *fr = gradient->values[5];
} }
void plutovg_gradient_set_values_linear(plutovg_gradient_t* gradient, double x1, double y1, double x2, double y2) void plutovg_gradient_set_values_linear(plutovg_gradient_t* gradient, double x1, double y1, double x2, double y2)
@ -179,7 +148,7 @@ void plutovg_gradient_set_values_radial(plutovg_gradient_t* gradient, double cx,
void plutovg_gradient_set_opacity(plutovg_gradient_t* gradient, double opacity) void plutovg_gradient_set_opacity(plutovg_gradient_t* gradient, double opacity)
{ {
gradient->opacity = opacity; gradient->opacity = plutovg_clamp(opacity, 0.0, 1.0);
} }
double plutovg_gradient_get_opacity(const plutovg_gradient_t* gradient) double plutovg_gradient_get_opacity(const plutovg_gradient_t* gradient)
@ -187,38 +156,30 @@ double plutovg_gradient_get_opacity(const plutovg_gradient_t* gradient)
return gradient->opacity; return gradient->opacity;
} }
plutovg_texture_t* plutovg_texture_create(plutovg_surface_t* surface) void plutovg_gradient_copy(plutovg_gradient_t* gradient, const plutovg_gradient_t* source)
{ {
plutovg_texture_t* texture = malloc(sizeof(plutovg_texture_t)); gradient->type = source->type;
texture->ref = 1; gradient->spread = source->spread;
texture->type = plutovg_texture_type_plain; gradient->matrix = source->matrix;
texture->surface = plutovg_surface_reference(surface); gradient->opacity = source->opacity;
plutovg_array_ensure(gradient->stops, source->stops.size);
memcpy(gradient->values, source->values, sizeof(source->values));
memcpy(gradient->stops.data, source->stops.data, source->stops.size * sizeof(plutovg_gradient_stop_t));
}
void plutovg_gradient_destroy(plutovg_gradient_t* gradient)
{
plutovg_array_destroy(gradient->stops);
}
void plutovg_texture_init(plutovg_texture_t* texture, plutovg_surface_t* surface, plutovg_texture_type_t type)
{
surface = plutovg_surface_reference(surface);
plutovg_surface_destroy(texture->surface);
texture->type = type;
texture->surface = surface;
texture->opacity = 1.0; texture->opacity = 1.0;
plutovg_matrix_init_identity(&texture->matrix); plutovg_matrix_init_identity(&texture->matrix);
return texture;
}
plutovg_texture_t* plutovg_texture_reference(plutovg_texture_t* texture)
{
++texture->ref;
return texture;
}
void plutovg_texture_destroy(plutovg_texture_t* texture)
{
if(texture==NULL)
return;
if(--texture->ref==0)
{
plutovg_surface_destroy(texture->surface);
free(texture);
}
}
int plutovg_texture_get_reference_count(const plutovg_texture_t* texture)
{
return texture->ref;
} }
void plutovg_texture_set_type(plutovg_texture_t* texture, plutovg_texture_type_t type) void plutovg_texture_set_type(plutovg_texture_t* texture, plutovg_texture_type_t type)
@ -233,12 +194,12 @@ plutovg_texture_type_t plutovg_texture_get_type(const plutovg_texture_t* texture
void plutovg_texture_set_matrix(plutovg_texture_t* texture, const plutovg_matrix_t* matrix) void plutovg_texture_set_matrix(plutovg_texture_t* texture, const plutovg_matrix_t* matrix)
{ {
memcpy(&texture->matrix, matrix, sizeof(plutovg_matrix_t)); texture->matrix = *matrix;
} }
void plutovg_texture_get_matrix(const plutovg_texture_t* texture, plutovg_matrix_t* matrix) void plutovg_texture_get_matrix(const plutovg_texture_t* texture, plutovg_matrix_t* matrix)
{ {
memcpy(matrix, &texture->matrix, sizeof(plutovg_matrix_t)); *matrix = texture->matrix;
} }
void plutovg_texture_set_surface(plutovg_texture_t* texture, plutovg_surface_t* surface) void plutovg_texture_set_surface(plutovg_texture_t* texture, plutovg_surface_t* surface)
@ -255,7 +216,7 @@ plutovg_surface_t* plutovg_texture_get_surface(const plutovg_texture_t* texture)
void plutovg_texture_set_opacity(plutovg_texture_t* texture, double opacity) void plutovg_texture_set_opacity(plutovg_texture_t* texture, double opacity)
{ {
texture->opacity = opacity; texture->opacity = plutovg_clamp(opacity, 0.0, 1.0);
} }
double plutovg_texture_get_opacity(const plutovg_texture_t* texture) double plutovg_texture_get_opacity(const plutovg_texture_t* texture)
@ -263,112 +224,42 @@ double plutovg_texture_get_opacity(const plutovg_texture_t* texture)
return texture->opacity; return texture->opacity;
} }
plutovg_paint_t* plutovg_paint_create_rgb(double r, double g, double b) void plutovg_texture_copy(plutovg_texture_t* texture, const plutovg_texture_t* source)
{ {
return plutovg_paint_create_rgba(r, g, b, 1.0); plutovg_surface_t* surface = plutovg_surface_reference(source->surface);
plutovg_surface_destroy(texture->surface);
texture->type = source->type;
texture->surface = surface;
texture->opacity = source->opacity;
texture->matrix = source->matrix;
} }
plutovg_paint_t* plutovg_paint_create_rgba(double r, double g, double b, double a) void plutovg_texture_destroy(plutovg_texture_t* texture)
{
plutovg_surface_destroy(texture->surface);
}
void plutovg_paint_init(plutovg_paint_t* paint)
{ {
plutovg_paint_t* paint = malloc(sizeof(plutovg_paint_t));
paint->ref = 1;
paint->type = plutovg_paint_type_color; paint->type = plutovg_paint_type_color;
paint->color = malloc(sizeof(plutovg_color_t)); paint->texture.surface = NULL;
plutovg_color_init_rgba(paint->color, r, g, b, a); plutovg_array_init(paint->gradient.stops);
return paint; plutovg_color_init_rgb(&paint->color, 0, 0, 0);
}
plutovg_paint_t* plutovg_paint_create_linear(double x1, double y1, double x2, double y2)
{
plutovg_gradient_t* gradient = plutovg_gradient_create_linear(x1, y1, x2, y2);
plutovg_paint_t* paint = plutovg_paint_create_gradient(gradient);
plutovg_gradient_destroy(gradient);
return paint;
}
plutovg_paint_t* plutovg_paint_create_radial(double cx, double cy, double cr, double fx, double fy, double fr)
{
plutovg_gradient_t* gradient = plutovg_gradient_create_radial(cx, cy, cr, fx, fy, fr);
plutovg_paint_t* paint = plutovg_paint_create_gradient(gradient);
plutovg_gradient_destroy(gradient);
return paint;
}
plutovg_paint_t* plutovg_paint_create_for_surface(plutovg_surface_t* surface)
{
plutovg_texture_t* texture = plutovg_texture_create(surface);
plutovg_paint_t* paint = plutovg_paint_create_texture(texture);
plutovg_texture_destroy(texture);
return paint;
}
plutovg_paint_t* plutovg_paint_create_color(const plutovg_color_t* color)
{
return plutovg_paint_create_rgba(color->r, color->g, color->b, color->a);
}
plutovg_paint_t* plutovg_paint_create_gradient(plutovg_gradient_t* gradient)
{
plutovg_paint_t* paint = malloc(sizeof(plutovg_paint_t));
paint->ref = 1;
paint->type = plutovg_paint_type_gradient;
paint->gradient = plutovg_gradient_reference(gradient);
return paint;
}
plutovg_paint_t* plutovg_paint_create_texture(plutovg_texture_t* texture)
{
plutovg_paint_t* paint = malloc(sizeof(plutovg_paint_t));
paint->ref = 1;
paint->type = plutovg_paint_type_texture;
paint->texture = plutovg_texture_reference(texture);
return paint;
}
plutovg_paint_t* plutovg_paint_reference(plutovg_paint_t* paint)
{
++paint->ref;
return paint;
} }
void plutovg_paint_destroy(plutovg_paint_t* paint) void plutovg_paint_destroy(plutovg_paint_t* paint)
{ {
if(paint==NULL) plutovg_texture_destroy(&paint->texture);
return; plutovg_gradient_destroy(&paint->gradient);
if(--paint->ref==0)
{
if(paint->type==plutovg_paint_type_color)
free(paint->color);
if(paint->type==plutovg_paint_type_gradient)
plutovg_gradient_destroy(paint->gradient);
if(paint->type==plutovg_paint_type_texture)
plutovg_texture_destroy(paint->texture);
free(paint);
}
} }
int plutovg_paint_get_reference_count(const plutovg_paint_t* paint) void plutovg_paint_copy(plutovg_paint_t* paint, const plutovg_paint_t* source)
{ {
return paint->ref; paint->type = source->type;
} if(source->type == plutovg_paint_type_color)
paint->color = source->color;
plutovg_paint_type_t plutovg_paint_get_type(const plutovg_paint_t* paint) else if(source->type == plutovg_paint_type_color)
{ plutovg_gradient_copy(&paint->gradient, &paint->gradient);
return paint->type; else
} plutovg_texture_copy(&paint->texture, &paint->texture);
plutovg_color_t* plutovg_paint_get_color(const plutovg_paint_t* paint)
{
return paint->type==plutovg_paint_type_color?paint->color:NULL;
}
plutovg_gradient_t* plutovg_paint_get_gradient(const plutovg_paint_t* paint)
{
return paint->type==plutovg_paint_type_gradient?paint->gradient:NULL;
}
plutovg_texture_t* plutovg_paint_get_texture(const plutovg_paint_t* paint)
{
return paint->type==plutovg_paint_type_texture?paint->texture:NULL;
} }

View file

@ -55,15 +55,20 @@ struct plutovg_texture {
double opacity; double opacity;
}; };
struct plutovg_paint { typedef int plutovg_paint_type_t;
int ref;
enum {
plutovg_paint_type_color,
plutovg_paint_type_gradient,
plutovg_paint_type_texture
};
typedef struct {
plutovg_paint_type_t type; plutovg_paint_type_t type;
union { plutovg_color_t color;
plutovg_color_t* color; plutovg_gradient_t gradient;
plutovg_gradient_t* gradient; plutovg_texture_t texture;
plutovg_texture_t* texture; } plutovg_paint_t;
};
};
typedef struct { typedef struct {
int x; int x;
@ -101,7 +106,7 @@ typedef struct {
typedef struct plutovg_state { typedef struct plutovg_state {
plutovg_rle_t* clippath; plutovg_rle_t* clippath;
plutovg_paint_t* source; plutovg_paint_t paint;
plutovg_matrix_t matrix; plutovg_matrix_t matrix;
plutovg_fill_rule_t winding; plutovg_fill_rule_t winding;
plutovg_stroke_data_t stroke; plutovg_stroke_data_t stroke;
@ -118,11 +123,23 @@ struct plutovg {
plutovg_rle_t* rle; plutovg_rle_t* rle;
plutovg_rle_t* clippath; plutovg_rle_t* clippath;
plutovg_rect_t clip; plutovg_rect_t clip;
void* outline_data;
size_t outline_size;
}; };
void plutovg_paint_init(plutovg_paint_t* paint);
void plutovg_paint_destroy(plutovg_paint_t* paint);
void plutovg_paint_copy(plutovg_paint_t* paint, const plutovg_paint_t* source);
void plutovg_gradient_copy(plutovg_gradient_t* gradient, const plutovg_gradient_t* source);
void plutovg_gradient_destroy(plutovg_gradient_t* gradient);
void plutovg_texture_copy(plutovg_texture_t* texture, const plutovg_texture_t* source);
void plutovg_texture_destroy(plutovg_texture_t* texture);
plutovg_rle_t* plutovg_rle_create(void); plutovg_rle_t* plutovg_rle_create(void);
void plutovg_rle_destroy(plutovg_rle_t* rle); void plutovg_rle_destroy(plutovg_rle_t* rle);
void plutovg_rle_rasterize(plutovg_rle_t* rle, const plutovg_path_t* path, const plutovg_matrix_t* matrix, const plutovg_rect_t* clip, const plutovg_stroke_data_t* stroke, plutovg_fill_rule_t winding); void plutovg_rle_rasterize(plutovg_t* pluto, plutovg_rle_t* rle, const plutovg_path_t* path, const plutovg_matrix_t* matrix, const plutovg_rect_t* clip, const plutovg_stroke_data_t* stroke, plutovg_fill_rule_t winding);
plutovg_rle_t* plutovg_rle_intersection(const plutovg_rle_t* a, const plutovg_rle_t* b); plutovg_rle_t* plutovg_rle_intersection(const plutovg_rle_t* a, const plutovg_rle_t* b);
void plutovg_rle_clip_path(plutovg_rle_t* rle, const plutovg_rle_t* clip); void plutovg_rle_clip_path(plutovg_rle_t* rle, const plutovg_rle_t* clip);
plutovg_rle_t* plutovg_rle_clone(const plutovg_rle_t* rle); plutovg_rle_t* plutovg_rle_clone(const plutovg_rle_t* rle);
@ -142,6 +159,17 @@ void plutovg_blend_color(plutovg_t* pluto, const plutovg_rle_t* rle, const pluto
void plutovg_blend_gradient(plutovg_t* pluto, const plutovg_rle_t* rle, const plutovg_gradient_t* gradient); void plutovg_blend_gradient(plutovg_t* pluto, const plutovg_rle_t* rle, const plutovg_gradient_t* gradient);
void plutovg_blend_texture(plutovg_t* pluto, const plutovg_rle_t* rle, const plutovg_texture_t* texture); void plutovg_blend_texture(plutovg_t* pluto, const plutovg_rle_t* rle, const plutovg_texture_t* texture);
#define plutovg_sqrt2 1.41421356237309504880
#define plutovg_pi 3.14159265358979323846
#define plutovg_two_pi 6.28318530717958647693
#define plutovg_half_pi 1.57079632679489661923
#define plutovg_kappa 0.55228474983079339840
#define plutovg_min(a, b) ((a) < (b) ? (a) : (b))
#define plutovg_max(a, b) ((a) > (b) ? (a) : (b))
#define plutovg_clamp(v, lo, hi) ((v) < (lo) ? (lo) : (hi) < (v) ? (hi) : (v))
#define plutovg_div255(x) (((x) + ((x) >> 8) + 0x80) >> 8)
#define plutovg_alpha(c) ((c) >> 24) #define plutovg_alpha(c) ((c) >> 24)
#define plutovg_red(c) (((c) >> 16) & 0xff) #define plutovg_red(c) (((c) >> 16) & 0xff)
#define plutovg_green(c) (((c) >> 8) & 0xff) #define plutovg_green(c) (((c) >> 8) & 0xff)
@ -160,9 +188,12 @@ void plutovg_blend_texture(plutovg_t* pluto, const plutovg_rle_t* rle, const plu
int capacity = array.size + count; \ int capacity = array.size + count; \
int newcapacity = array.capacity == 0 ? 8 : array.capacity; \ int newcapacity = array.capacity == 0 ? 8 : array.capacity; \
while(newcapacity < capacity) { newcapacity *= 2; } \ while(newcapacity < capacity) { newcapacity *= 2; } \
array.data = realloc(array.data, (size_t)newcapacity * sizeof(array.data[0])); \ array.data = realloc(array.data, newcapacity * sizeof(array.data[0])); \
array.capacity = newcapacity; \ array.capacity = newcapacity; \
} \ } \
} while(0) } while(0)
#define plutovg_array_clear(array) (array.size = 0)
#define plutovg_array_destroy(array) free(array.data)
#endif // PLUTOVG_PRIVATE_H #endif // PLUTOVG_PRIVATE_H

View file

@ -6,25 +6,26 @@
#include <math.h> #include <math.h>
#include <limits.h> #include <limits.h>
static PVG_FT_Outline* ft_outline_create(size_t points, size_t contours) static void ft_outline_init(PVG_FT_Outline* outline, plutovg_t* pluto, int points, int contours)
{ {
PVG_FT_Outline* ft = malloc(sizeof(PVG_FT_Outline)); size_t size_a = (points + contours) * sizeof(PVG_FT_Vector);
ft->points = malloc((points + contours) * sizeof(PVG_FT_Vector)); size_t size_b = (points + contours) * sizeof(char);
ft->tags = malloc((points + contours) * sizeof(char)); size_t size_c = contours * sizeof(int);
ft->contours = malloc(contours * sizeof(int)); size_t size_d = contours * sizeof(char);
ft->contours_flag = malloc(contours * sizeof(char)); size_t size_n = size_a + size_b + size_c + size_d;
ft->n_points = ft->n_contours = 0; if(size_n > pluto->outline_size) {
ft->flags = 0x0; pluto->outline_data = realloc(pluto->outline_data, size_n);
return ft; pluto->outline_size = size_n;
} }
static void ft_outline_destroy(PVG_FT_Outline* ft) PVG_FT_Byte* data = pluto->outline_data;
{ outline->points = (PVG_FT_Vector*)(data);
free(ft->points); outline->tags = (char*)(data + size_a);
free(ft->tags); outline->contours = (int*)(data + size_a + size_b);
free(ft->contours); outline->contours_flag = (char*)(data + size_a + size_b + size_c);
free(ft->contours_flag); outline->n_points = 0;
free(ft); outline->n_contours = 0;
outline->flags = 0x0;
} }
#define FT_COORD(x) (PVG_FT_Pos)((x) * 64) #define FT_COORD(x) (PVG_FT_Pos)((x) * 64)
@ -89,9 +90,9 @@ static void ft_outline_end(PVG_FT_Outline* ft)
} }
} }
static PVG_FT_Outline* ft_outline_convert(const plutovg_path_t* path, const plutovg_matrix_t* matrix) static void ft_outline_convert(PVG_FT_Outline* outline, plutovg_t* pluto, const plutovg_path_t* path, const plutovg_matrix_t* matrix)
{ {
PVG_FT_Outline* outline = ft_outline_create(path->points.size, path->contours); ft_outline_init(outline, pluto, path->points.size, path->contours);
plutovg_path_element_t* elements = path->elements.data; plutovg_path_element_t* elements = path->elements.data;
plutovg_point_t* points = path->points.data; plutovg_point_t* points = path->points.data;
plutovg_point_t p[3]; plutovg_point_t p[3];
@ -122,15 +123,13 @@ static PVG_FT_Outline* ft_outline_convert(const plutovg_path_t* path, const plut
} }
ft_outline_end(outline); ft_outline_end(outline);
return outline;
} }
static PVG_FT_Outline* ft_outline_convert_dash(const plutovg_path_t* path, const plutovg_matrix_t* matrix, const plutovg_dash_t* dash) static void ft_outline_convert_dash(PVG_FT_Outline* outline, plutovg_t* pluto, const plutovg_path_t* path, const plutovg_matrix_t* matrix, const plutovg_dash_t* dash)
{ {
plutovg_path_t* dashed = plutovg_dash_path(dash, path); plutovg_path_t* dashed = plutovg_dash_path(dash, path);
PVG_FT_Outline* outline = ft_outline_convert(dashed, matrix); ft_outline_convert(outline, pluto, dashed, matrix);
plutovg_path_destroy(dashed); plutovg_path_destroy(dashed);
return outline;
} }
static void generation_callback(int count, const PVG_FT_Span* spans, void* user) static void generation_callback(int count, const PVG_FT_Span* spans, void* user)
@ -162,8 +161,7 @@ void plutovg_rle_destroy(plutovg_rle_t* rle)
free(rle); free(rle);
} }
#define SQRT2 1.41421356237309504880 void plutovg_rle_rasterize(plutovg_t* pluto, plutovg_rle_t* rle, const plutovg_path_t* path, const plutovg_matrix_t* matrix, const plutovg_rect_t* clip, const plutovg_stroke_data_t* stroke, plutovg_fill_rule_t winding)
void plutovg_rle_rasterize(plutovg_rle_t* rle, const plutovg_path_t* path, const plutovg_matrix_t* matrix, const plutovg_rect_t* clip, const plutovg_stroke_data_t* stroke, plutovg_fill_rule_t winding)
{ {
PVG_FT_Raster_Params params; PVG_FT_Raster_Params params;
params.flags = PVG_FT_RASTER_FLAG_DIRECT | PVG_FT_RASTER_FLAG_AA; params.flags = PVG_FT_RASTER_FLAG_DIRECT | PVG_FT_RASTER_FLAG_AA;
@ -171,25 +169,25 @@ void plutovg_rle_rasterize(plutovg_rle_t* rle, const plutovg_path_t* path, const
params.user = rle; params.user = rle;
if(clip) { if(clip) {
params.flags |= PVG_FT_RASTER_FLAG_CLIP; params.flags |= PVG_FT_RASTER_FLAG_CLIP;
params.clip_box.xMin = (PVG_FT_Pos)clip->x; params.clip_box.xMin = (PVG_FT_Pos)(clip->x);
params.clip_box.yMin = (PVG_FT_Pos)clip->y; params.clip_box.yMin = (PVG_FT_Pos)(clip->y);
params.clip_box.xMax = (PVG_FT_Pos)(clip->x + clip->w); params.clip_box.xMax = (PVG_FT_Pos)(clip->x + clip->w);
params.clip_box.yMax = (PVG_FT_Pos)(clip->y + clip->h); params.clip_box.yMax = (PVG_FT_Pos)(clip->y + clip->h);
} }
if(stroke) { if(stroke) {
PVG_FT_Outline* outline; PVG_FT_Outline outline;
if(stroke->dash == NULL) if(stroke->dash == NULL)
outline = ft_outline_convert(path, matrix); ft_outline_convert(&outline, pluto, path, matrix);
else else
outline = ft_outline_convert_dash(path, matrix, stroke->dash); ft_outline_convert_dash(&outline, pluto, path, matrix, stroke->dash);
PVG_FT_Stroker_LineCap ftCap; PVG_FT_Stroker_LineCap ftCap;
PVG_FT_Stroker_LineJoin ftJoin; PVG_FT_Stroker_LineJoin ftJoin;
PVG_FT_Fixed ftWidth; PVG_FT_Fixed ftWidth;
PVG_FT_Fixed ftMiterLimit; PVG_FT_Fixed ftMiterLimit;
plutovg_point_t p1 = {0, 0}; plutovg_point_t p1 = {0, 0};
plutovg_point_t p2 = {SQRT2, SQRT2}; plutovg_point_t p2 = {plutovg_sqrt2, plutovg_sqrt2};
plutovg_point_t p3; plutovg_point_t p3;
plutovg_matrix_map_point(matrix, &p1, &p1); plutovg_matrix_map_point(matrix, &p1, &p1);
@ -230,35 +228,33 @@ void plutovg_rle_rasterize(plutovg_rle_t* rle, const plutovg_path_t* path, const
PVG_FT_Stroker stroker; PVG_FT_Stroker stroker;
PVG_FT_Stroker_New(&stroker); PVG_FT_Stroker_New(&stroker);
PVG_FT_Stroker_Set(stroker, ftWidth, ftCap, ftJoin, ftMiterLimit); PVG_FT_Stroker_Set(stroker, ftWidth, ftCap, ftJoin, ftMiterLimit);
PVG_FT_Stroker_ParseOutline(stroker, outline); PVG_FT_Stroker_ParseOutline(stroker, &outline);
PVG_FT_UInt points; PVG_FT_UInt points;
PVG_FT_UInt contours; PVG_FT_UInt contours;
PVG_FT_Stroker_GetCounts(stroker, &points, &contours); PVG_FT_Stroker_GetCounts(stroker, &points, &contours);
PVG_FT_Outline* strokeOutline = ft_outline_create(points, contours); ft_outline_init(&outline, pluto, points, contours);
PVG_FT_Stroker_Export(stroker, strokeOutline); PVG_FT_Stroker_Export(stroker, &outline);
PVG_FT_Stroker_Done(stroker); PVG_FT_Stroker_Done(stroker);
strokeOutline->flags = PVG_FT_OUTLINE_NONE; outline.flags = PVG_FT_OUTLINE_NONE;
params.source = strokeOutline; params.source = &outline;
PVG_FT_Raster_Render(&params); PVG_FT_Raster_Render(&params);
ft_outline_destroy(outline);
ft_outline_destroy(strokeOutline);
} else { } else {
PVG_FT_Outline* outline = ft_outline_convert(path, matrix); PVG_FT_Outline outline;
ft_outline_convert(&outline, pluto, path, matrix);
switch(winding) { switch(winding) {
case plutovg_fill_rule_even_odd: case plutovg_fill_rule_even_odd:
outline->flags = PVG_FT_OUTLINE_EVEN_ODD_FILL; outline.flags = PVG_FT_OUTLINE_EVEN_ODD_FILL;
break; break;
default: default:
outline->flags = PVG_FT_OUTLINE_NONE; outline.flags = PVG_FT_OUTLINE_NONE;
break; break;
} }
params.source = outline; params.source = &outline;
PVG_FT_Raster_Render(&params); PVG_FT_Raster_Render(&params);
ft_outline_destroy(outline);
} }
if(rle->spans.size == 0) { if(rle->spans.size == 0) {
@ -286,12 +282,9 @@ void plutovg_rle_rasterize(plutovg_rle_t* rle, const plutovg_path_t* path, const
rle->h = y2 - y1 + 1; rle->h = y2 - y1 + 1;
} }
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define DIV255(x) (((x) + ((x) >> 8) + 0x80) >> 8)
plutovg_rle_t* plutovg_rle_intersection(const plutovg_rle_t* a, const plutovg_rle_t* b) plutovg_rle_t* plutovg_rle_intersection(const plutovg_rle_t* a, const plutovg_rle_t* b)
{ {
int count = MAX(a->spans.size, b->spans.size); int count = plutovg_max(a->spans.size, b->spans.size);
plutovg_rle_t* result = malloc(sizeof(plutovg_rle_t)); plutovg_rle_t* result = malloc(sizeof(plutovg_rle_t));
plutovg_array_init(result->spans); plutovg_array_init(result->spans);
plutovg_array_ensure(result->spans, count); plutovg_array_ensure(result->spans, count);
@ -332,15 +325,15 @@ plutovg_rle_t* plutovg_rle_intersection(const plutovg_rle_t* a, const plutovg_rl
continue; continue;
} }
int x = MAX(ax1, bx1); int x = plutovg_max(ax1, bx1);
int len = MIN(ax2, bx2) - x; int len = plutovg_min(ax2, bx2) - x;
if(len) if(len)
{ {
plutovg_span_t* span = result->spans.data + result->spans.size; plutovg_span_t* span = result->spans.data + result->spans.size;
span->x = (short)x; span->x = (short)x;
span->len = (unsigned short)len; span->len = (unsigned short)len;
span->y = a_spans->y; span->y = a_spans->y;
span->coverage = DIV255(a_spans->coverage * b_spans->coverage); span->coverage = plutovg_div255(a_spans->coverage * b_spans->coverage);
++result->spans.size; ++result->spans.size;
--count; --count;
} }

View file

@ -72,7 +72,7 @@ plutovg_state_t* plutovg_state_create(void)
{ {
plutovg_state_t* state = malloc(sizeof(plutovg_state_t)); plutovg_state_t* state = malloc(sizeof(plutovg_state_t));
state->clippath = NULL; state->clippath = NULL;
state->source = plutovg_paint_create_rgb(0, 0, 0); plutovg_paint_init(&state->paint);
plutovg_matrix_init_identity(&state->matrix); plutovg_matrix_init_identity(&state->matrix);
state->winding = plutovg_fill_rule_non_zero; state->winding = plutovg_fill_rule_non_zero;
state->stroke.width = 1.0; state->stroke.width = 1.0;
@ -88,9 +88,9 @@ plutovg_state_t* plutovg_state_create(void)
plutovg_state_t* plutovg_state_clone(const plutovg_state_t* state) plutovg_state_t* plutovg_state_clone(const plutovg_state_t* state)
{ {
plutovg_state_t* newstate = malloc(sizeof(plutovg_state_t)); plutovg_state_t* newstate = plutovg_state_create();
newstate->clippath = plutovg_rle_clone(state->clippath); newstate->clippath = plutovg_rle_clone(state->clippath);
newstate->source = plutovg_paint_reference(state->source); /** FIXME: **/ plutovg_paint_copy(&newstate->paint, &state->paint);
newstate->matrix = state->matrix; newstate->matrix = state->matrix;
newstate->winding = state->winding; newstate->winding = state->winding;
newstate->stroke.width = state->stroke.width; newstate->stroke.width = state->stroke.width;
@ -107,7 +107,7 @@ plutovg_state_t* plutovg_state_clone(const plutovg_state_t* state)
void plutovg_state_destroy(plutovg_state_t* state) void plutovg_state_destroy(plutovg_state_t* state)
{ {
plutovg_rle_destroy(state->clippath); plutovg_rle_destroy(state->clippath);
plutovg_paint_destroy(state->source); plutovg_paint_destroy(&state->paint);
plutovg_dash_destroy(state->stroke.dash); plutovg_dash_destroy(state->stroke.dash);
free(state); free(state);
} }
@ -125,6 +125,8 @@ plutovg_t* plutovg_create(plutovg_surface_t* surface)
pluto->clip.y = 0.0; pluto->clip.y = 0.0;
pluto->clip.w = surface->width; pluto->clip.w = surface->width;
pluto->clip.h = surface->height; pluto->clip.h = surface->height;
pluto->outline_data = NULL;
pluto->outline_size = 0;
return pluto; return pluto;
} }
@ -152,6 +154,7 @@ void plutovg_destroy(plutovg_t* pluto)
plutovg_path_destroy(pluto->path); plutovg_path_destroy(pluto->path);
plutovg_rle_destroy(pluto->rle); plutovg_rle_destroy(pluto->rle);
plutovg_rle_destroy(pluto->clippath); plutovg_rle_destroy(pluto->clippath);
free(pluto->outline_data);
free(pluto); free(pluto);
} }
} }
@ -175,58 +178,53 @@ void plutovg_restore(plutovg_t* pluto)
plutovg_state_destroy(oldstate); plutovg_state_destroy(oldstate);
} }
void plutovg_set_source_rgb(plutovg_t* pluto, double r, double g, double b) plutovg_color_t* plutovg_set_rgb(plutovg_t* pluto, double r, double g, double b)
{ {
plutovg_set_source_rgba(pluto, r, g, b, 1.0); return plutovg_set_rgba(pluto, r, g, b, 1.0);
} }
void plutovg_set_source_rgba(plutovg_t* pluto, double r, double g, double b, double a) plutovg_color_t* plutovg_set_rgba(plutovg_t* pluto, double r, double g, double b, double a)
{ {
plutovg_paint_t* source = plutovg_paint_create_rgba(r, g, b, a); plutovg_paint_t* paint = &pluto->state->paint;
plutovg_set_source(pluto, source); paint->type = plutovg_paint_type_color;
plutovg_paint_destroy(source); plutovg_color_init_rgba(&paint->color, r, g, b, a);
return &paint->color;
} }
void plutovg_set_source_surface(plutovg_t* pluto, plutovg_surface_t* surface, double x, double y) plutovg_color_t* plutovg_set_color(plutovg_t* pluto, const plutovg_color_t* color)
{ {
plutovg_paint_t* source = plutovg_paint_create_for_surface(surface); return plutovg_set_rgba(pluto, color->r, color->g, color->b, color->a);
plutovg_texture_t* texture = plutovg_paint_get_texture(source);
plutovg_matrix_t matrix;
plutovg_matrix_init_translate(&matrix, x, y);
plutovg_texture_set_matrix(texture, &matrix);
plutovg_set_source(pluto, source);
plutovg_paint_destroy(source);
} }
void plutovg_set_source_color(plutovg_t* pluto, const plutovg_color_t* color) plutovg_gradient_t* plutovg_set_linear_gradient(plutovg_t* pluto, double x1, double y1, double x2, double y2)
{ {
plutovg_set_source_rgba(pluto, color->r, color->g, color->b, color->a); plutovg_paint_t* paint = &pluto->state->paint;
paint->type = plutovg_paint_type_gradient;
plutovg_gradient_init_linear(&paint->gradient, x1, y1, x2, y2);
return &paint->gradient;
} }
void plutovg_set_source_gradient(plutovg_t* pluto, plutovg_gradient_t* gradient) plutovg_gradient_t* plutovg_set_radial_gradient(plutovg_t* pluto, double cx, double cy, double cr, double fx, double fy, double fr)
{ {
plutovg_paint_t* source = plutovg_paint_create_gradient(gradient); plutovg_paint_t* paint = &pluto->state->paint;
plutovg_set_source(pluto, source); paint->type = plutovg_paint_type_gradient;
plutovg_paint_destroy(source); plutovg_gradient_init_radial(&paint->gradient, cx, cy, cr, fx, fy, fr);
return &paint->gradient;
} }
void plutovg_set_source_texture(plutovg_t* pluto, plutovg_texture_t* texture) plutovg_texture_t* plutovg_set_texture_surface(plutovg_t* pluto, plutovg_surface_t* surface, double x, double y)
{ {
plutovg_paint_t* source = plutovg_paint_create_texture(texture); plutovg_texture_t* texture = plutovg_set_texture(pluto, surface, plutovg_texture_type_plain);
plutovg_set_source(pluto, source); plutovg_matrix_init_translate(&texture->matrix, x, y);
plutovg_paint_destroy(source); return texture;
} }
void plutovg_set_source(plutovg_t* pluto, plutovg_paint_t* source) plutovg_texture_t* plutovg_set_texture(plutovg_t* pluto, plutovg_surface_t* surface, plutovg_texture_type_t type)
{ {
source = plutovg_paint_reference(source); plutovg_paint_t* paint = &pluto->state->paint;
plutovg_paint_destroy(pluto->state->source); paint->type = plutovg_paint_type_texture;
pluto->state->source = source; plutovg_texture_init(&paint->texture, surface, plutovg_texture_type_plain);
} return &paint->texture;
plutovg_paint_t* plutovg_get_source(const plutovg_t* pluto)
{
return pluto->state->source;
} }
void plutovg_set_operator(plutovg_t* pluto, plutovg_operator_t op) void plutovg_set_operator(plutovg_t* pluto, plutovg_operator_t op)
@ -448,7 +446,7 @@ void plutovg_paint(plutovg_t* pluto)
plutovg_matrix_t matrix; plutovg_matrix_t matrix;
plutovg_matrix_init_identity(&matrix); plutovg_matrix_init_identity(&matrix);
pluto->clippath = plutovg_rle_create(); pluto->clippath = plutovg_rle_create();
plutovg_rle_rasterize(pluto->clippath, path, &matrix, &pluto->clip, NULL, plutovg_fill_rule_non_zero); plutovg_rle_rasterize(pluto, pluto->clippath, path, &matrix, &pluto->clip, NULL, plutovg_fill_rule_non_zero);
plutovg_path_destroy(path); plutovg_path_destroy(path);
} }
@ -460,7 +458,7 @@ void plutovg_fill_preserve(plutovg_t* pluto)
{ {
plutovg_state_t* state = pluto->state; plutovg_state_t* state = pluto->state;
plutovg_rle_clear(pluto->rle); plutovg_rle_clear(pluto->rle);
plutovg_rle_rasterize(pluto->rle, pluto->path, &state->matrix, &pluto->clip, NULL, state->winding); plutovg_rle_rasterize(pluto, pluto->rle, pluto->path, &state->matrix, &pluto->clip, NULL, state->winding);
plutovg_rle_clip_path(pluto->rle, state->clippath); plutovg_rle_clip_path(pluto->rle, state->clippath);
plutovg_blend(pluto, pluto->rle); plutovg_blend(pluto, pluto->rle);
} }
@ -469,7 +467,7 @@ void plutovg_stroke_preserve(plutovg_t* pluto)
{ {
plutovg_state_t* state = pluto->state; plutovg_state_t* state = pluto->state;
plutovg_rle_clear(pluto->rle); plutovg_rle_clear(pluto->rle);
plutovg_rle_rasterize(pluto->rle, pluto->path, &state->matrix, &pluto->clip, &state->stroke, plutovg_fill_rule_non_zero); plutovg_rle_rasterize(pluto, pluto->rle, pluto->path, &state->matrix, &pluto->clip, &state->stroke, plutovg_fill_rule_non_zero);
plutovg_rle_clip_path(pluto->rle, state->clippath); plutovg_rle_clip_path(pluto->rle, state->clippath);
plutovg_blend(pluto, pluto->rle); plutovg_blend(pluto, pluto->rle);
} }
@ -480,13 +478,13 @@ void plutovg_clip_preserve(plutovg_t* pluto)
if(state->clippath) if(state->clippath)
{ {
plutovg_rle_clear(pluto->rle); plutovg_rle_clear(pluto->rle);
plutovg_rle_rasterize(pluto->rle, pluto->path, &state->matrix, &pluto->clip, NULL, state->winding); plutovg_rle_rasterize(pluto, pluto->rle, pluto->path, &state->matrix, &pluto->clip, NULL, state->winding);
plutovg_rle_clip_path(state->clippath, pluto->rle); plutovg_rle_clip_path(state->clippath, pluto->rle);
} }
else else
{ {
state->clippath = plutovg_rle_create(); state->clippath = plutovg_rle_create();
plutovg_rle_rasterize(state->clippath, pluto->path, &state->matrix, &pluto->clip, NULL, state->winding); plutovg_rle_rasterize(pluto, state->clippath, pluto->path, &state->matrix, &pluto->clip, NULL, state->winding);
} }
} }

View file

@ -120,11 +120,8 @@ typedef struct {
plutovg_color_t color; plutovg_color_t color;
} plutovg_gradient_stop_t; } plutovg_gradient_stop_t;
plutovg_gradient_t* plutovg_gradient_create_linear(double x1, double y1, double x2, double y2); void plutovg_gradient_init_linear(plutovg_gradient_t* gradient, double x1, double y1, double x2, double y2);
plutovg_gradient_t* plutovg_gradient_create_radial(double cx, double cy, double cr, double fx, double fy, double fr); void plutovg_gradient_init_radial(plutovg_gradient_t* gradient, double cx, double cy, double cr, double fx, double fy, double fr);
plutovg_gradient_t* plutovg_gradient_reference(plutovg_gradient_t* gradient);
void plutovg_gradient_destroy(plutovg_gradient_t* gradient);
int plutovg_gradient_get_reference_count(const plutovg_gradient_t* gradient);
void plutovg_gradient_set_type(plutovg_gradient_t* gradient, plutovg_gradient_type_t type); void plutovg_gradient_set_type(plutovg_gradient_t* gradient, plutovg_gradient_type_t type);
plutovg_gradient_type_t plutovg_gradient_get_type(const plutovg_gradient_t* gradient); plutovg_gradient_type_t plutovg_gradient_get_type(const plutovg_gradient_t* gradient);
void plutovg_gradient_set_spread(plutovg_gradient_t* gradient, plutovg_spread_method_t spread); void plutovg_gradient_set_spread(plutovg_gradient_t* gradient, plutovg_spread_method_t spread);
@ -151,10 +148,7 @@ typedef enum {
plutovg_texture_type_tiled plutovg_texture_type_tiled
} plutovg_texture_type_t; } plutovg_texture_type_t;
plutovg_texture_t* plutovg_texture_create(plutovg_surface_t* surface); void plutovg_texture_init(plutovg_texture_t* texture, plutovg_surface_t* surface, plutovg_texture_type_t type);
plutovg_texture_t* plutovg_texture_reference(plutovg_texture_t* texture);
void plutovg_texture_destroy(plutovg_texture_t* texture);
int plutovg_texture_get_reference_count(const plutovg_texture_t* texture);
void plutovg_texture_set_type(plutovg_texture_t* texture, plutovg_texture_type_t type); void plutovg_texture_set_type(plutovg_texture_t* texture, plutovg_texture_type_t type);
plutovg_texture_type_t plutovg_texture_get_type(const plutovg_texture_t* texture); plutovg_texture_type_t plutovg_texture_get_type(const plutovg_texture_t* texture);
void plutovg_texture_set_matrix(plutovg_texture_t* texture, const plutovg_matrix_t* matrix); void plutovg_texture_set_matrix(plutovg_texture_t* texture, const plutovg_matrix_t* matrix);
@ -164,30 +158,6 @@ plutovg_surface_t* plutovg_texture_get_surface(const plutovg_texture_t* texture)
void plutovg_texture_set_opacity(plutovg_texture_t* texture, double opacity); void plutovg_texture_set_opacity(plutovg_texture_t* texture, double opacity);
double plutovg_texture_get_opacity(const plutovg_texture_t* texture); double plutovg_texture_get_opacity(const plutovg_texture_t* texture);
typedef struct plutovg_paint plutovg_paint_t;
typedef enum {
plutovg_paint_type_color,
plutovg_paint_type_gradient,
plutovg_paint_type_texture
} plutovg_paint_type_t;
plutovg_paint_t* plutovg_paint_create_rgb(double r, double g, double b);
plutovg_paint_t* plutovg_paint_create_rgba(double r, double g, double b, double a);
plutovg_paint_t* plutovg_paint_create_linear(double x1, double y1, double x2, double y2);
plutovg_paint_t* plutovg_paint_create_radial(double cx, double cy, double cr, double fx, double fy, double fr);
plutovg_paint_t* plutovg_paint_create_for_surface(plutovg_surface_t* surface);
plutovg_paint_t* plutovg_paint_create_color(const plutovg_color_t* color);
plutovg_paint_t* plutovg_paint_create_gradient(plutovg_gradient_t* gradient);
plutovg_paint_t* plutovg_paint_create_texture(plutovg_texture_t* texture);
plutovg_paint_t* plutovg_paint_reference(plutovg_paint_t* paint);
void plutovg_paint_destroy(plutovg_paint_t* paint);
int plutovg_paint_get_reference_count(const plutovg_paint_t* paint);
plutovg_paint_type_t plutovg_paint_get_type(const plutovg_paint_t* paint);
plutovg_color_t* plutovg_paint_get_color(const plutovg_paint_t* paint);
plutovg_gradient_t* plutovg_paint_get_gradient(const plutovg_paint_t* paint);
plutovg_texture_t* plutovg_paint_get_texture(const plutovg_paint_t* paint);
typedef enum { typedef enum {
plutovg_line_cap_butt, plutovg_line_cap_butt,
plutovg_line_cap_round, plutovg_line_cap_round,
@ -220,14 +190,16 @@ void plutovg_destroy(plutovg_t* pluto);
int plutovg_get_reference_count(const plutovg_t* pluto); int plutovg_get_reference_count(const plutovg_t* pluto);
void plutovg_save(plutovg_t* pluto); void plutovg_save(plutovg_t* pluto);
void plutovg_restore(plutovg_t* pluto); void plutovg_restore(plutovg_t* pluto);
void plutovg_set_source_rgb(plutovg_t* pluto, double r, double g, double b);
void plutovg_set_source_rgba(plutovg_t* pluto, double r, double g, double b, double a); plutovg_color_t* plutovg_set_rgb(plutovg_t* pluto, double r, double g, double b);
void plutovg_set_source_surface(plutovg_t* pluto, plutovg_surface_t* surface, double x, double y); plutovg_color_t* plutovg_set_rgba(plutovg_t* pluto, double r, double g, double b, double a);
void plutovg_set_source_color(plutovg_t* pluto, const plutovg_color_t* color); plutovg_color_t* plutovg_set_color(plutovg_t* pluto, const plutovg_color_t* color);
void plutovg_set_source_gradient(plutovg_t* pluto, plutovg_gradient_t* gradient);
void plutovg_set_source_texture(plutovg_t* pluto, plutovg_texture_t* texture); plutovg_gradient_t* plutovg_set_linear_gradient(plutovg_t* pluto, double x1, double y1, double x2, double y2);
void plutovg_set_source(plutovg_t* pluto, plutovg_paint_t* source); plutovg_gradient_t* plutovg_set_radial_gradient(plutovg_t* pluto, double cx, double cy, double cr, double fx, double fy, double fr);
plutovg_paint_t* plutovg_get_source(const plutovg_t* pluto);
plutovg_texture_t* plutovg_set_texture_surface(plutovg_t* pluto, plutovg_surface_t* surface, double x, double y);
plutovg_texture_t* plutovg_set_texture(plutovg_t* pluto, plutovg_surface_t* surface, plutovg_texture_type_t type);
void plutovg_set_operator(plutovg_t* pluto, plutovg_operator_t op); void plutovg_set_operator(plutovg_t* pluto, plutovg_operator_t op);
void plutovg_set_opacity(plutovg_t* pluto, double opacity); void plutovg_set_opacity(plutovg_t* pluto, double opacity);

View file

@ -10,6 +10,7 @@ static plutovg_operator_t to_plutovg_operator(BlendMode mode);
static plutovg_line_cap_t to_plutovg_line_cap(LineCap cap); static plutovg_line_cap_t to_plutovg_line_cap(LineCap cap);
static plutovg_line_join_t to_plutovg_line_join(LineJoin join); static plutovg_line_join_t to_plutovg_line_join(LineJoin join);
static plutovg_spread_method_t to_plutovg_spread_method(SpreadMethod spread); static plutovg_spread_method_t to_plutovg_spread_method(SpreadMethod spread);
static plutovg_texture_type_t to_plutovg_texture_type(TextureType type);
static void to_plutovg_stops(plutovg_gradient_t* gradient, const GradientStops& stops); static void to_plutovg_stops(plutovg_gradient_t* gradient, const GradientStops& stops);
static void to_plutovg_path(plutovg_t* pluto, const Path& path); static void to_plutovg_path(plutovg_t* pluto, const Path& path);
@ -59,43 +60,32 @@ Canvas::~Canvas()
void Canvas::setColor(const Color& color) void Canvas::setColor(const Color& color)
{ {
plutovg_set_source_rgba(pluto, color.red() / 255.0, color.green() / 255.0, color.blue() / 255.0, color.alpha() / 255.0); plutovg_set_rgba(pluto, color.red() / 255.0, color.green() / 255.0, color.blue() / 255.0, color.alpha() / 255.0);
} }
void Canvas::setLinearGradient(double x1, double y1, double x2, double y2, const GradientStops& stops, SpreadMethod spread, const Transform& transform) void Canvas::setLinearGradient(double x1, double y1, double x2, double y2, const GradientStops& stops, SpreadMethod spread, const Transform& transform)
{ {
auto gradient = plutovg_gradient_create_linear(x1, y1, x2, y2); auto gradient = plutovg_set_linear_gradient(pluto, x1, y1, x2, y2);
auto matrix = to_plutovg_matrix(transform); auto matrix = to_plutovg_matrix(transform);
to_plutovg_stops(gradient, stops); to_plutovg_stops(gradient, stops);
plutovg_gradient_set_spread(gradient, to_plutovg_spread_method(spread)); plutovg_gradient_set_spread(gradient, to_plutovg_spread_method(spread));
plutovg_gradient_set_matrix(gradient, &matrix); plutovg_gradient_set_matrix(gradient, &matrix);
plutovg_set_source_gradient(pluto, gradient);
plutovg_gradient_destroy(gradient);
} }
void Canvas::setRadialGradient(double cx, double cy, double r, double fx, double fy, const GradientStops& stops, SpreadMethod spread, const Transform& transform) void Canvas::setRadialGradient(double cx, double cy, double r, double fx, double fy, const GradientStops& stops, SpreadMethod spread, const Transform& transform)
{ {
auto gradient = plutovg_gradient_create_radial(cx, cy, r, fx, fy, 0); auto gradient = plutovg_set_radial_gradient(pluto, cx, cy, r, fx, fy, 0);
auto matrix = to_plutovg_matrix(transform); auto matrix = to_plutovg_matrix(transform);
to_plutovg_stops(gradient, stops); to_plutovg_stops(gradient, stops);
plutovg_gradient_set_spread(gradient, to_plutovg_spread_method(spread)); plutovg_gradient_set_spread(gradient, to_plutovg_spread_method(spread));
plutovg_gradient_set_matrix(gradient, &matrix); plutovg_gradient_set_matrix(gradient, &matrix);
plutovg_set_source_gradient(pluto, gradient);
plutovg_gradient_destroy(gradient);
} }
void Canvas::setTexture(const Canvas* source, TextureType type, const Transform& transform) void Canvas::setTexture(const Canvas* source, TextureType type, const Transform& transform)
{ {
auto texture = plutovg_texture_create(source->surface); auto texture = plutovg_set_texture(pluto, source->surface, to_plutovg_texture_type(type));
auto matrix = to_plutovg_matrix(transform); auto matrix = to_plutovg_matrix(transform);
if(type == TextureType::Plain)
plutovg_texture_set_type(texture, plutovg_texture_type_plain);
else
plutovg_texture_set_type(texture, plutovg_texture_type_tiled);
plutovg_texture_set_matrix(texture, &matrix); plutovg_texture_set_matrix(texture, &matrix);
plutovg_set_source_texture(pluto, texture);
plutovg_texture_destroy(texture);
} }
void Canvas::fill(const Path& path, const Transform& transform, WindRule winding, BlendMode mode, double opacity) void Canvas::fill(const Path& path, const Transform& transform, WindRule winding, BlendMode mode, double opacity)
@ -128,7 +118,7 @@ void Canvas::stroke(const Path& path, const Transform& transform, double width,
void Canvas::blend(const Canvas* source, BlendMode mode, double opacity) void Canvas::blend(const Canvas* source, BlendMode mode, double opacity)
{ {
plutovg_set_source_surface(pluto, source->surface, source->rect.x, source->rect.y); plutovg_set_texture_surface(pluto, source->surface, source->rect.x, source->rect.y);
plutovg_set_operator(pluto, to_plutovg_operator(mode)); plutovg_set_operator(pluto, to_plutovg_operator(mode));
plutovg_set_opacity(pluto, opacity); plutovg_set_opacity(pluto, opacity);
plutovg_set_matrix(pluto, &translation); plutovg_set_matrix(pluto, &translation);
@ -145,7 +135,7 @@ void Canvas::mask(const Rect& clip, const Transform& transform)
plutovg_add_path(pluto, path); plutovg_add_path(pluto, path);
plutovg_path_destroy(path); plutovg_path_destroy(path);
plutovg_set_source_rgba(pluto, 0, 0, 0, 0); plutovg_set_rgba(pluto, 0, 0, 0, 0);
plutovg_set_fill_rule(pluto, plutovg_fill_rule_even_odd); plutovg_set_fill_rule(pluto, plutovg_fill_rule_even_odd);
plutovg_set_operator(pluto, plutovg_operator_src); plutovg_set_operator(pluto, plutovg_operator_src);
plutovg_set_opacity(pluto, 0.0); plutovg_set_opacity(pluto, 0.0);
@ -232,6 +222,11 @@ static plutovg_spread_method_t to_plutovg_spread_method(SpreadMethod spread)
return spread == SpreadMethod::Pad ? plutovg_spread_method_pad : spread == SpreadMethod::Reflect ? plutovg_spread_method_reflect : plutovg_spread_method_repeat; return spread == SpreadMethod::Pad ? plutovg_spread_method_pad : spread == SpreadMethod::Reflect ? plutovg_spread_method_reflect : plutovg_spread_method_repeat;
} }
static plutovg_texture_type_t to_plutovg_texture_type(TextureType type)
{
return type == TextureType::Plain ? plutovg_texture_type_plain : plutovg_texture_type_tiled;
}
static void to_plutovg_stops(plutovg_gradient_t* gradient, const GradientStops& stops) static void to_plutovg_stops(plutovg_gradient_t* gradient, const GradientStops& stops)
{ {
for(const auto& stop : stops) for(const auto& stop : stops)

View file

@ -297,7 +297,7 @@ std::unique_ptr<Document> Document::loadFromData(const char* data, std::size_t s
return nullptr; return nullptr;
auto root = builder.build(); auto root = builder.build();
if(!root || root->children.empty()) if(root == nullptr)
return nullptr; return nullptr;
std::unique_ptr<Document> document(new Document); std::unique_ptr<Document> document(new Document);