From ec669c0e77fda84332df622520204a265f90ff46 Mon Sep 17 00:00:00 2001 From: sammycage Date: Sat, 21 Nov 2020 00:31:31 +0100 Subject: [PATCH] Refactor : plutovg --- 3rdparty/plutovg/plutovg-blend.c | 247 ++++++++++++++++++----- 3rdparty/plutovg/plutovg-geometry.c | 22 +- 3rdparty/plutovg/plutovg-paint.c | 3 +- 3rdparty/plutovg/plutovg-private.h | 43 +--- 3rdparty/plutovg/plutovg-rle.c | 293 ++++++++++++++++----------- 3rdparty/plutovg/plutovg.c | 301 +++++++--------------------- 3rdparty/plutovg/plutovg.h | 30 +-- 7 files changed, 494 insertions(+), 445 deletions(-) diff --git a/3rdparty/plutovg/plutovg-blend.c b/3rdparty/plutovg/plutovg-blend.c index 61b8fe4..5b80861 100644 --- a/3rdparty/plutovg/plutovg-blend.c +++ b/3rdparty/plutovg/plutovg-blend.c @@ -3,6 +3,32 @@ #include #include +#define COLOR_TABLE_SIZE 1024 +typedef struct { + plutovg_spread_method_t spread; + plutovg_matrix_t matrix; + uint32_t colortable[COLOR_TABLE_SIZE]; + union { + struct { + double x1, y1; + double x2, y2; + } linear; + struct { + double cx, cy, cr; + double fx, fy, fr; + } radial; + }; +} gradient_data_t; + +typedef struct { + plutovg_matrix_t matrix; + uint8_t* data; + int width; + int height; + int stride; + int const_alpha; +} texture_data_t; + typedef struct { double dx; double dy; @@ -20,13 +46,46 @@ typedef struct { int extended; } radial_gradient_values_t; +static inline uint32_t premultiply_color(const plutovg_color_t* color, double opacity) +{ + uint32_t alpha = (uint8_t)(color->a * opacity * 255); + uint32_t pr = (uint8_t)(color->r * alpha); + uint32_t pg = (uint8_t)(color->g * alpha); + uint32_t pb = (uint8_t)(color->b * alpha); + + return (alpha << 24) | (pr << 16) | (pg << 8) | (pb); +} + +static inline uint32_t interpolate_pixel(uint32_t x, uint32_t a, uint32_t y, uint32_t b) +{ + uint32_t t = (x & 0xff00ff) * a + (y & 0xff00ff) * b; + t >>= 8; + t &= 0xff00ff; + x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b; + x &= 0xff00ff00; + x |= t; + return x; +} + +static inline uint32_t BYTE_MUL(uint32_t x, uint32_t a) +{ + uint32_t t = (x & 0xff00ff) * a; + t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8; + t &= 0xff00ff; + x = ((x >> 8) & 0xff00ff) * a; + x = (x + ((x >> 8) & 0xff00ff) + 0x800080); + x &= 0xff00ff00; + x |= t; + return x; +} + static inline void memfill32(uint32_t* dest, uint32_t value, int length) { for(int i = 0 ;i < length;i++) *dest++ = value; } -static inline int gradient_clamp(const plutovg_gradient_data_t* gradient, int ipos) +static inline int gradient_clamp(const gradient_data_t* gradient, int ipos) { if(gradient->spread == plutovg_spread_method_repeat) { @@ -53,19 +112,19 @@ static inline int gradient_clamp(const plutovg_gradient_data_t* gradient, int ip #define FIXPT_BITS 8 #define FIXPT_SIZE (1 << FIXPT_BITS) -static inline uint32_t gradient_pixel_fixed(const plutovg_gradient_data_t* gradient, int fixed_pos) +static inline uint32_t gradient_pixel_fixed(const gradient_data_t* gradient, int fixed_pos) { int ipos = (fixed_pos + (FIXPT_SIZE / 2)) >> FIXPT_BITS; return gradient->colortable[gradient_clamp(gradient, ipos)]; } -static inline uint32_t gradient_pixel(const plutovg_gradient_data_t* gradient, double pos) +static inline uint32_t gradient_pixel(const gradient_data_t* gradient, double pos) { int ipos = (int)(pos * (COLOR_TABLE_SIZE - 1) + 0.5); return gradient->colortable[gradient_clamp(gradient, ipos)]; } -static void fetch_linear_gradient(uint32_t* buffer, const linear_gradient_values_t* v, const plutovg_gradient_data_t* gradient, int y, int x, int length) +static void fetch_linear_gradient(uint32_t* buffer, const linear_gradient_values_t* v, const gradient_data_t* gradient, int y, int x, int length) { double t, inc; double rx = 0, ry = 0; @@ -114,7 +173,7 @@ static void fetch_linear_gradient(uint32_t* buffer, const linear_gradient_values } } -static void fetch_radial_gradient(uint32_t* buffer, const radial_gradient_values_t* v, const plutovg_gradient_data_t* gradient, int y, int x, int length) +static void fetch_radial_gradient(uint32_t* buffer, const radial_gradient_values_t* v, const gradient_data_t* gradient, int y, int x, int length) { if(v->a == 0.0) { @@ -185,29 +244,6 @@ static void fetch_radial_gradient(uint32_t* buffer, const radial_gradient_values } } -static inline uint32_t BYTE_MUL(uint32_t x, uint32_t a) -{ - uint32_t t = (x & 0xff00ff) * a; - t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8; - t &= 0xff00ff; - x = ((x >> 8) & 0xff00ff) * a; - x = (x + ((x >> 8) & 0xff00ff) + 0x800080); - x &= 0xff00ff00; - x |= t; - return x; -} - -static inline uint32_t interpolate_pixel(uint32_t x, uint32_t a, uint32_t y, uint32_t b) -{ - uint32_t t = (x & 0xff00ff) * a + (y & 0xff00ff) * b; - t >>= 8; - t &= 0xff00ff; - x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b; - x &= 0xff00ff00; - x |= t; - return x; -} - #define ALPHA(c) ((c) >> 24) static void composition_solid_source(uint32_t* dest, int length, uint32_t color, uint32_t alpha) { @@ -345,7 +381,7 @@ static const composition_function_t function_for_mode[] = { composition_destination_out }; -void plutovg_blend_solid(plutovg_surface_t* surface, plutovg_operator_t op, const plutovg_rle_t* rle, uint32_t solid) +static void blend_solid(plutovg_surface_t* surface, plutovg_operator_t op, const plutovg_rle_t* rle, uint32_t solid) { composition_function_solid_t func = function_for_mode_solid[op]; int count = rle->spans.size; @@ -360,7 +396,7 @@ void plutovg_blend_solid(plutovg_surface_t* surface, plutovg_operator_t op, cons #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define BUFFER_SIZE 1024 -static void blend_linear_gradient(plutovg_surface_t* surface, plutovg_operator_t op, const plutovg_rle_t* rle, const plutovg_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) { composition_function_t func = function_for_mode[op]; unsigned int buffer[BUFFER_SIZE]; @@ -378,7 +414,7 @@ static void blend_linear_gradient(plutovg_surface_t* surface, plutovg_operator_t } int count = rle->spans.size; - const plutovg_span_t* spans= rle->spans.data; + const plutovg_span_t* spans = rle->spans.data; while(count--) { int length = spans->len; @@ -397,7 +433,7 @@ static void blend_linear_gradient(plutovg_surface_t* surface, plutovg_operator_t } } -static void blend_radial_gradient(plutovg_surface_t* surface, plutovg_operator_t op, const plutovg_rle_t* rle, const plutovg_gradient_data_t* gradient) +static void blend_radial_gradient(plutovg_surface_t* surface, plutovg_operator_t op, const plutovg_rle_t* rle, const gradient_data_t* gradient) { composition_function_t func = function_for_mode[op]; unsigned int buffer[BUFFER_SIZE]; @@ -415,7 +451,7 @@ static void blend_radial_gradient(plutovg_surface_t* surface, plutovg_operator_t v.extended = gradient->radial.fr != 0.0 || v.a <= 0.0; int count = rle->spans.size; - const plutovg_span_t* spans= rle->spans.data; + const plutovg_span_t* spans = rle->spans.data; while(count--) { int length = spans->len; @@ -436,7 +472,7 @@ 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) -static void blend_transformed_argb(plutovg_surface_t* surface, plutovg_operator_t op, const plutovg_rle_t* rle, const plutovg_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) { composition_function_t func = function_for_mode[op]; uint32_t buffer[BUFFER_SIZE]; @@ -448,7 +484,7 @@ static void blend_transformed_argb(plutovg_surface_t* surface, plutovg_operator_ int fdy = (int)(texture->matrix.m10 * FIXED_SCALE); int count = rle->spans.size; - const plutovg_span_t* spans= rle->spans.data; + const plutovg_span_t* spans = rle->spans.data; while(count--) { uint32_t* target = (uint32_t*)(surface->data + spans->y * surface->stride) + spans->x; @@ -486,7 +522,7 @@ static void blend_transformed_argb(plutovg_surface_t* surface, plutovg_operator_ } } -static void blend_untransformed_argb(plutovg_surface_t* surface, plutovg_operator_t op, const plutovg_rle_t* rle, const plutovg_texture_data_t* texture) +static void blend_untransformed_argb(plutovg_surface_t* surface, plutovg_operator_t op, const plutovg_rle_t* rle, const texture_data_t* texture) { composition_function_t func = function_for_mode[op]; @@ -497,7 +533,7 @@ static void blend_untransformed_argb(plutovg_surface_t* surface, plutovg_operato int yoff = (int)(texture->matrix.m12); int count = rle->spans.size; - const plutovg_span_t* spans= rle->spans.data; + const plutovg_span_t* spans = rle->spans.data; while(count--) { int x = spans->x; @@ -526,7 +562,7 @@ static void blend_untransformed_argb(plutovg_surface_t* surface, plutovg_operato } } -static void blend_untransformed_tiled_argb(plutovg_surface_t* surface, plutovg_operator_t op, const plutovg_rle_t* rle, const plutovg_texture_data_t* texture) +static void blend_untransformed_tiled_argb(plutovg_surface_t* surface, plutovg_operator_t op, const plutovg_rle_t* rle, const texture_data_t* texture) { composition_function_t func = function_for_mode[op]; @@ -542,7 +578,7 @@ static void blend_untransformed_tiled_argb(plutovg_surface_t* surface, plutovg_o yoff += image_height; int count = rle->spans.size; - const plutovg_span_t* spans= rle->spans.data; + const plutovg_span_t* spans = rle->spans.data; while(count--) { int x = spans->x; @@ -572,7 +608,7 @@ static void blend_untransformed_tiled_argb(plutovg_surface_t* surface, plutovg_o } } -static void blend_transformed_tiled_argb(plutovg_surface_t* surface, plutovg_operator_t op, const plutovg_rle_t* rle, const plutovg_texture_data_t* texture) +static void blend_transformed_tiled_argb(plutovg_surface_t* surface, plutovg_operator_t op, const plutovg_rle_t* rle, const texture_data_t* texture) { composition_function_t func = function_for_mode[op]; uint32_t buffer[BUFFER_SIZE]; @@ -585,7 +621,7 @@ static void blend_transformed_tiled_argb(plutovg_surface_t* surface, plutovg_ope int fdy = (int)(texture->matrix.m10 * FIXED_SCALE); int count = rle->spans.size; - const plutovg_span_t* spans= rle->spans.data; + const plutovg_span_t* spans = rle->spans.data; while(count--) { uint32_t* target = (uint32_t*)(surface->data + spans->y * surface->stride) + spans->x; @@ -637,30 +673,143 @@ static void blend_transformed_tiled_argb(plutovg_surface_t* surface, plutovg_ope } } -void plutovg_blend_gradient(plutovg_surface_t* surface, plutovg_operator_t op, const plutovg_rle_t* rle, const plutovg_gradient_data_t* gradient) +void plutovg_blend(plutovg_t* pluto, const plutovg_rle_t* rle) +{ + plutovg_paint_t* source = pluto->state->source; + if(source->type==plutovg_paint_type_color) + { + const plutovg_color_t* color = plutovg_paint_get_color(source); + plutovg_blend_color(pluto, rle, color); + } + else if(source->type==plutovg_paint_type_gradient) + { + const plutovg_gradient_t* gradient = plutovg_paint_get_gradient(source); + plutovg_blend_gradient(pluto, rle, gradient); + } + else + { + const plutovg_texture_t* texture = plutovg_paint_get_texture(source); + plutovg_blend_texture(pluto, rle, texture); + } +} + +void plutovg_blend_color(plutovg_t* pluto, const plutovg_rle_t* rle, const plutovg_color_t* color) +{ + plutovg_state_t* state = pluto->state; + uint32_t solid = premultiply_color(color, state->opacity); + blend_solid(pluto->surface, state->op, rle, solid); +} + +void plutovg_blend_gradient(plutovg_t* pluto, const plutovg_rle_t* rle, const plutovg_gradient_t* gradient) { + plutovg_state_t* state = pluto->state; + gradient_data_t data; + if(gradient->type==plutovg_gradient_type_linear) + { + data.linear.x1 = gradient->values[0]; + data.linear.y1 = gradient->values[1]; + data.linear.x2 = gradient->values[2]; + data.linear.y2 = gradient->values[3]; + } + else + { + data.radial.cx = gradient->values[0]; + data.radial.cy = gradient->values[1]; + data.radial.cr = gradient->values[2]; + data.radial.fx = gradient->values[3]; + data.radial.fy = gradient->values[4]; + data.radial.fr = gradient->values[5]; + } + + int dist, idist, pos = 0; + int i; + int alpha = 0; + int nstop = gradient->stops.size; + const plutovg_gradient_stop_t *curr, *next, *start; + uint32_t curr_color, next_color; + double delta, t, incr, fpos; + double opacity = state->opacity * gradient->opacity; + + if(opacity != 1.0) alpha = 1; + + start = gradient->stops.data; + curr = start; + if(curr->color.a != 0.0) alpha = 1; + curr_color = premultiply_color(&curr->color, opacity); + incr = 1.0 / COLOR_TABLE_SIZE; + fpos = 1.5 * incr; + + data.colortable[pos++] = curr_color; + + while(fpos <= curr->offset) + { + data.colortable[pos] = data.colortable[pos - 1]; + pos++; + fpos += incr; + } + + for(i = 0;i < nstop - 1;i++) + { + curr = (start + i); + next = (start + i + 1); + delta = 1.0 / (next->offset - curr->offset); + if(next->color.a != 0.0) alpha = 1; + next_color = premultiply_color(&next->color, opacity); + while(fpos < next->offset && pos < COLOR_TABLE_SIZE) + { + t = (fpos - curr->offset) * delta; + dist = (int)(255 * t); + idist = 255 - dist; + data.colortable[pos] = interpolate_pixel(curr_color, (uint32_t)idist, next_color, (uint32_t)dist); + ++pos; + fpos += incr; + } + + curr_color = next_color; + } + + for(;pos < COLOR_TABLE_SIZE;++pos) data.colortable[pos] = curr_color; + data.colortable[COLOR_TABLE_SIZE - 1] = curr_color; + data.spread = gradient->spread; + + data.matrix = gradient->matrix; + plutovg_matrix_multiply(&data.matrix, &data.matrix, &state->matrix); + plutovg_matrix_invert(&data.matrix); + if(gradient->type==plutovg_gradient_type_linear) - blend_linear_gradient(surface, op, rle, gradient); + blend_linear_gradient(pluto->surface, state->op, rle, &data); else - blend_radial_gradient(surface, op, rle, gradient); + blend_radial_gradient(pluto->surface, state->op, rle, &data); } -void plutovg_blend_texture(plutovg_surface_t* surface, plutovg_operator_t op, const plutovg_rle_t* rle, const plutovg_texture_data_t* texture) +void plutovg_blend_texture(plutovg_t* pluto, const plutovg_rle_t* rle, const plutovg_texture_t* texture) { + plutovg_state_t* state = pluto->state; + texture_data_t data; + data.data = texture->surface->data; + data.width = texture->surface->width; + data.height = texture->surface->height; + data.stride = texture->surface->stride; + data.const_alpha = (int)(state->opacity * texture->opacity * 256.0); + + data.matrix = texture->matrix; + plutovg_matrix_multiply(&data.matrix, &data.matrix, &state->matrix); + plutovg_matrix_invert(&data.matrix); + const plutovg_matrix_t* matrix = &texture->matrix; int translating = (matrix->m00==1.0 && matrix->m10==0.0 && matrix->m01==0.0 && matrix->m11==1.0); if(translating) { if(texture->type==plutovg_texture_type_plain) - blend_untransformed_argb(surface, op, rle, texture); + blend_untransformed_argb(pluto->surface, state->op, rle, &data); else - blend_untransformed_tiled_argb(surface, op, rle, texture); + blend_untransformed_tiled_argb(pluto->surface, state->op, rle, &data); } else { if(texture->type==plutovg_texture_type_plain) - blend_transformed_argb(surface, op, rle, texture); + blend_transformed_argb(pluto->surface, state->op, rle, &data); else - blend_transformed_tiled_argb(surface, op, rle, texture); + blend_transformed_tiled_argb(pluto->surface, state->op, rle, &data); } } diff --git a/3rdparty/plutovg/plutovg-geometry.c b/3rdparty/plutovg/plutovg-geometry.c index 8d85f79..bc84fc7 100644 --- a/3rdparty/plutovg/plutovg-geometry.c +++ b/3rdparty/plutovg/plutovg-geometry.c @@ -151,6 +151,7 @@ plutovg_path_t* plutovg_path_create(void) { plutovg_path_t* path = malloc(sizeof(plutovg_path_t)); path->ref = 1; + path->contours = 0; path->start.x = 0.0; path->start.y = 0.0; plutovg_array_init(path->elements); @@ -194,6 +195,7 @@ void plutovg_path_move_to(plutovg_path_t* path, double x, double y) path->elements.size += 1; path->points.size += 1; + path->contours += 1; path->start.x = x; path->start.y = y; @@ -382,6 +384,7 @@ void plutovg_path_add_path(plutovg_path_t* path, const plutovg_path_t* source, c path->elements.size += source->elements.size; path->points.size += source->points.size; + path->contours += source->contours; path->start = source->start; } @@ -433,6 +436,7 @@ void plutovg_path_clear(plutovg_path_t* path) { path->elements.size = 0; path->points.size = 0; + path->contours = 0; path->start.x = 0.0; path->start.y = 0.0; } @@ -454,6 +458,7 @@ plutovg_path_t* plutovg_path_clone(const plutovg_path_t* path) p->elements.size = path->elements.size; p->points.size = path->points.size; + p->contours = path->contours; p->start = path->start; return p; @@ -469,15 +474,15 @@ typedef struct { static inline void split(const bezier_t* b, bezier_t* first, bezier_t* second) { double c = (b->x2 + b->x3) * 0.5; - first->x2 = (b->x1 + b->x2)*.5; - second->x3 = (b->x3 + b->x4)*.5; + first->x2 = (b->x1 + b->x2) * 0.5; + second->x3 = (b->x3 + b->x4) * 0.5; first->x1 = b->x1; second->x4 = b->x4; - first->x3 = (first->x2 + c)*.5; - second->x2 = (second->x3 + c)*.5; + first->x3 = (first->x2 + c) * 0.5; + second->x2 = (second->x3 + c) * 0.5; first->x4 = second->x1 = (first->x3 + second->x2) * 0.5; - c = (b->y2 + b->y3) / 2; + c = (b->y2 + b->y3) * 0.5; first->y2 = (b->y1 + b->y2) * 0.5; second->y3 = (b->y3 + b->y4) * 0.5; first->y1 = b->y1; @@ -487,7 +492,6 @@ static inline void split(const bezier_t* b, bezier_t* first, bezier_t* second) first->y4 = second->y1 = (first->y3 + second->y2) * 0.5; } -#define abs(a) ((a) < 0 ? -(a) : (a)) static void flatten_curve(plutovg_path_t* path, const plutovg_point_t* p0, const plutovg_point_t* p1, const plutovg_point_t* p2, const plutovg_point_t* p3) { bezier_t beziers[32]; @@ -507,15 +511,15 @@ static void flatten_curve(plutovg_path_t* path, const plutovg_point_t* p0, const { double y4y1 = b->y4 - b->y1; double x4x1 = b->x4 - b->x1; - double l = abs(x4x1) + abs(y4y1); + double l = fabs(x4x1) + fabs(y4y1); double d; if(l > 1.) { - d = abs((x4x1)*(b->y1 - b->y2) - (y4y1)*(b->x1 - b->x2)) + abs((x4x1)*(b->y1 - b->y3) - (y4y1)*(b->x1 - b->x3)); + d = fabs((x4x1)*(b->y1 - b->y2) - (y4y1)*(b->x1 - b->x2)) + fabs((x4x1)*(b->y1 - b->y3) - (y4y1)*(b->x1 - b->x3)); } else { - d = abs(b->x1 - b->x2) + abs(b->y1 - b->y2) + abs(b->x1 - b->x3) + abs(b->y1 - b->y3); + d = fabs(b->x1 - b->x2) + fabs(b->y1 - b->y2) + fabs(b->x1 - b->x3) + fabs(b->y1 - b->y3); l = 1.; } diff --git a/3rdparty/plutovg/plutovg-paint.c b/3rdparty/plutovg/plutovg-paint.c index fbc0277..370f1da 100644 --- a/3rdparty/plutovg/plutovg-paint.c +++ b/3rdparty/plutovg/plutovg-paint.c @@ -250,8 +250,9 @@ void plutovg_texture_get_matrix(const plutovg_texture_t* texture, plutovg_matrix void plutovg_texture_set_surface(plutovg_texture_t* texture, plutovg_surface_t* surface) { + surface = plutovg_surface_reference(surface); plutovg_surface_destroy(texture->surface); - texture->surface = plutovg_surface_reference(surface); + texture->surface = surface; } plutovg_surface_t* plutovg_texture_get_surface(const plutovg_texture_t* texture) diff --git a/3rdparty/plutovg/plutovg-private.h b/3rdparty/plutovg/plutovg-private.h index 9cc6685..af0e131 100644 --- a/3rdparty/plutovg/plutovg-private.h +++ b/3rdparty/plutovg/plutovg-private.h @@ -19,6 +19,7 @@ struct plutovg_surface { struct plutovg_path { int ref; + int contours; plutovg_point_t start; struct { plutovg_path_element_t* data; @@ -92,7 +93,7 @@ typedef struct { } plutovg_stroke_data_t; typedef struct plutovg_state { - plutovg_rle_t* clip; + plutovg_rle_t* clippath; plutovg_paint_t* source; plutovg_matrix_t matrix; plutovg_fill_rule_t winding; @@ -111,46 +112,20 @@ struct plutovg { plutovg_surface_t* surface; plutovg_state_t* state; plutovg_path_t* path; + plutovg_rle_t* clippath; plutovg_rect_t clip; }; -plutovg_rle_t* plutovg_rle_render(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_rasterize(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_destroy(plutovg_rle_t* rle); +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_rect(plutovg_rle_t* rle, const plutovg_rect_t* clip); plutovg_rle_t* plutovg_rle_clone(const plutovg_rle_t* rle); -#define COLOR_TABLE_SIZE 1024 -typedef struct { - plutovg_gradient_type_t type; - plutovg_spread_method_t spread; - plutovg_matrix_t matrix; - uint32_t colortable[COLOR_TABLE_SIZE]; - union { - struct { - double x1, y1; - double x2, y2; - } linear; - struct { - double cx, cy, cr; - double fx, fy, fr; - } radial; - }; -} plutovg_gradient_data_t; - -typedef struct { - plutovg_texture_type_t type; - plutovg_matrix_t matrix; - uint8_t* data; - int width; - int height; - int stride; - int const_alpha; -} plutovg_texture_data_t; - -void plutovg_blend_solid(plutovg_surface_t* surface, plutovg_operator_t op, const plutovg_rle_t* rle, uint32_t solid); -void plutovg_blend_gradient(plutovg_surface_t* surface, plutovg_operator_t op, const plutovg_rle_t* rle, const plutovg_gradient_data_t* gradient); -void plutovg_blend_texture(plutovg_surface_t* surface, plutovg_operator_t op, const plutovg_rle_t* rle, const plutovg_texture_data_t* texture); +void plutovg_blend(plutovg_t* pluto, const plutovg_rle_t* rle); +void plutovg_blend_color(plutovg_t* pluto, const plutovg_rle_t* rle, const plutovg_color_t* color); +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); #define plutovg_array_init(array) \ do { \ diff --git a/3rdparty/plutovg/plutovg-rle.c b/3rdparty/plutovg/plutovg-rle.c index 63ddaf2..584c9c0 100644 --- a/3rdparty/plutovg/plutovg-rle.c +++ b/3rdparty/plutovg/plutovg-rle.c @@ -3,64 +3,35 @@ #include "sw_ft_raster.h" #include "sw_ft_stroker.h" #include "sw_ft_types.h" +#include "sw_ft_math.h" #include +#include -typedef struct { - SW_FT_Outline ft; - int max_points; - int max_contours; -} outline_t; - -static outline_t* outline_create(void) +static SW_FT_Outline* sw_ft_outline_create(int points, int contours) { - outline_t* outline = malloc(sizeof(outline_t)); - memset(outline, 0, sizeof(outline_t)); - return outline; + SW_FT_Outline* ft = malloc(sizeof(SW_FT_Outline)); + ft->points = malloc((size_t)(points + contours) * sizeof(SW_FT_Vector)); + ft->tags = malloc((size_t)(points + contours) * sizeof(char)); + ft->contours = malloc((size_t)contours * sizeof(short)); + ft->contours_flag = malloc((size_t)contours * sizeof(char)); + ft->n_points = ft->n_contours = 0; + ft->flags = 0x0; + return ft; } -static void outline_destroy(outline_t* outline) +static void sw_ft_outline_destroy(SW_FT_Outline* ft) { - SW_FT_Outline* ft = &outline->ft; - free(ft->points); free(ft->tags); free(ft->contours); free(ft->contours_flag); - free(outline); -} - -static void outline_ensure(outline_t* outline, int points, int contours) -{ - SW_FT_Outline* ft = &outline->ft; - if(ft->n_points + points > outline->max_points) - { - int capacity = ft->n_points + points; - int newcapacity = outline->max_points == 0 ? 8 : outline->max_points; - while(newcapacity < capacity) { newcapacity *= 2; } - ft->points = realloc(ft->points, (size_t)newcapacity * sizeof(SW_FT_Vector)); - ft->tags = realloc(ft->tags, (size_t)newcapacity * sizeof(char)); - outline->max_points = newcapacity; - } - - if(ft->n_contours + contours > outline->max_contours) - { - int capacity = ft->n_contours + contours; - int newcapacity = outline->max_contours == 0 ? 8 : outline->max_contours; - while(newcapacity < capacity) { newcapacity *= 2; } - ft->contours = realloc(ft->contours, (size_t)newcapacity * sizeof(short)); - ft->contours_flag = realloc(ft->contours_flag, (size_t)newcapacity * sizeof(char)); - outline->max_contours = newcapacity; - } + free(ft); } #define FT_COORD(x) (SW_FT_Pos)((x) * 64) -static void outline_move_to(outline_t* outline, double x, double y) +static void sw_ft_outline_move_to(SW_FT_Outline* ft, double x, double y) { - outline_ensure(outline, 1, 1); - - SW_FT_Outline* ft = &outline->ft; - ft->points[ft->n_points].x = FT_COORD(x); ft->points[ft->n_points].y = FT_COORD(y); ft->tags[ft->n_points] = SW_FT_CURVE_TAG_ON; @@ -74,24 +45,16 @@ static void outline_move_to(outline_t* outline, double x, double y) ft->n_points++; } -static void outline_line_to(outline_t* outline, double x, double y) +static void sw_ft_outline_line_to(SW_FT_Outline* ft, double x, double y) { - outline_ensure(outline, 1, 0); - - SW_FT_Outline* ft = &outline->ft; - ft->points[ft->n_points].x = FT_COORD(x); ft->points[ft->n_points].y = FT_COORD(y); ft->tags[ft->n_points] = SW_FT_CURVE_TAG_ON; ft->n_points++; } -static void outline_cubic_to(outline_t* outline, double x1, double y1, double x2, double y2, double x3, double y3) +static void sw_ft_outline_cubic_to(SW_FT_Outline* ft, double x1, double y1, double x2, double y2, double x3, double y3) { - outline_ensure(outline, 3, 0); - - SW_FT_Outline* ft = &outline->ft; - ft->points[ft->n_points].x = FT_COORD(x1); ft->points[ft->n_points].y = FT_COORD(y1); ft->tags[ft->n_points] = SW_FT_CURVE_TAG_CUBIC; @@ -108,14 +71,9 @@ static void outline_cubic_to(outline_t* outline, double x1, double y1, double x2 ft->n_points++; } -static void outline_close(outline_t* outline) +static void sw_ft_outline_close(SW_FT_Outline* ft) { - outline_ensure(outline, 1, 1); - - SW_FT_Outline* ft = &outline->ft; - ft->contours_flag[ft->n_contours] = 0; - int index = ft->n_contours ? ft->contours[ft->n_contours - 1] + 1 : 0; if(index == ft->n_points) return; @@ -126,40 +84,18 @@ static void outline_close(outline_t* outline) ft->n_points++; } -static void outline_end(outline_t* outline) +static void sw_ft_outline_end(SW_FT_Outline* ft) { - SW_FT_Outline* ft = &outline->ft; if(ft->n_points) { - outline_ensure(outline, 0, 1); - ft->contours[ft->n_contours] = ft->n_points - 1; ft->n_contours++; } } -static void generation_callback(int count, const SW_FT_Span* spans, void* user) +static SW_FT_Outline* sw_ft_outline_convert(const plutovg_path_t* path, const plutovg_matrix_t* matrix) { - plutovg_rle_t* rle = user; - plutovg_array_ensure(rle->spans, count); - plutovg_span_t* data = rle->spans.data + rle->spans.size; - memcpy(data, spans, (size_t)count * sizeof(plutovg_span_t)); - rle->spans.size += count; -} - -static void bbox_callback(int x, int y, int w, int h, void* user) -{ - plutovg_rle_t* rle = user; - rle->x = x; - rle->y = y; - rle->w = w; - rle->h = h; -} - -#define SQRT2 1.41421356237309504880 -plutovg_rle_t* plutovg_rle_render(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) -{ - outline_t* outline = outline_create(); + SW_FT_Outline* outline = sw_ft_outline_create(path->points.size, path->contours); plutovg_path_element_t* elements = path->elements.data; plutovg_point_t* points = path->points.data; plutovg_point_t p[3]; @@ -169,30 +105,53 @@ plutovg_rle_t* plutovg_rle_render(const plutovg_path_t* path, const plutovg_matr { case plutovg_path_element_move_to: plutovg_matrix_map_point(matrix, &points[0], &p[0]); - outline_move_to(outline, p[0].x, p[0].y); + sw_ft_outline_move_to(outline, p[0].x, p[0].y); points += 1; break; case plutovg_path_element_line_to: plutovg_matrix_map_point(matrix, &points[0], &p[0]); - outline_line_to(outline, p[0].x, p[0].y); + sw_ft_outline_line_to(outline, p[0].x, p[0].y); points += 1; break; case plutovg_path_element_cubic_to: plutovg_matrix_map_point(matrix, &points[0], &p[0]); plutovg_matrix_map_point(matrix, &points[1], &p[1]); plutovg_matrix_map_point(matrix, &points[2], &p[2]); - outline_cubic_to(outline, p[0].x, p[0].y, p[1].x, p[1].y, p[2].x, p[2].y); + sw_ft_outline_cubic_to(outline, p[0].x, p[0].y, p[1].x, p[1].y, p[2].x, p[2].y); points += 3; break; case plutovg_path_element_close: - outline_close(outline); + sw_ft_outline_close(outline); points += 1; break; } } - outline_end(outline); + sw_ft_outline_end(outline); + return outline; +} +static void generation_callback(int count, const SW_FT_Span* spans, void* user) +{ + plutovg_rle_t* rle = user; + plutovg_array_ensure(rle->spans, count); + plutovg_span_t* data = rle->spans.data + rle->spans.size; + memcpy(data, spans, (size_t)count * sizeof(plutovg_span_t)); + rle->spans.size += count; +} + +static void bbox_callback(int x, int y, int w, int h, void* user) +{ + plutovg_rle_t* rle = user; + rle->x = x; + rle->y = y; + rle->w = w; + rle->h = h; +} + +#define SQRT2 1.41421356237309504880 +plutovg_rle_t* plutovg_rasterize(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* rle = malloc(sizeof(plutovg_rle_t)); plutovg_array_init(rle->spans); @@ -213,6 +172,7 @@ plutovg_rle_t* plutovg_rle_render(const plutovg_path_t* path, const plutovg_matr if(stroke) { + SW_FT_Outline* outline = sw_ft_outline_convert(path, matrix); SW_FT_Stroker_LineCap ftCap; SW_FT_Stroker_LineJoin ftJoin; SW_FT_Fixed ftWidth; @@ -262,30 +222,31 @@ plutovg_rle_t* plutovg_rle_render(const plutovg_path_t* path, const plutovg_matr SW_FT_Stroker stroker; SW_FT_Stroker_New(&stroker); SW_FT_Stroker_Set(stroker, ftWidth, ftCap, ftJoin, ftMiterLimit); - SW_FT_Stroker_ParseOutline(stroker, &outline->ft); + SW_FT_Stroker_ParseOutline(stroker, outline); SW_FT_UInt points; SW_FT_UInt contours; SW_FT_Stroker_GetCounts(stroker, &points, &contours); - outline_t* strokeOutline = outline_create(); - outline_ensure(strokeOutline, (int)points, (int)contours); - SW_FT_Stroker_Export(stroker, &strokeOutline->ft); + SW_FT_Outline* strokeOutline = sw_ft_outline_create((int)points, (int)contours); + SW_FT_Stroker_Export(stroker, strokeOutline); SW_FT_Stroker_Done(stroker); - strokeOutline->ft.flags = SW_FT_OUTLINE_NONE; - params.source = &strokeOutline->ft; + strokeOutline->flags = SW_FT_OUTLINE_NONE; + params.source = strokeOutline; sw_ft_grays_raster.raster_render(NULL, ¶ms); - outline_destroy(strokeOutline); + sw_ft_outline_destroy(outline); + sw_ft_outline_destroy(strokeOutline); } else { - outline->ft.flags = winding == plutovg_fill_rule_even_odd ? SW_FT_OUTLINE_EVEN_ODD_FILL : SW_FT_OUTLINE_NONE; - params.source = &outline->ft; + SW_FT_Outline* outline = sw_ft_outline_convert(path, matrix); + outline->flags = winding == plutovg_fill_rule_even_odd ? SW_FT_OUTLINE_EVEN_ODD_FILL : SW_FT_OUTLINE_NONE; + params.source = outline; sw_ft_grays_raster.raster_render(NULL, ¶ms); + sw_ft_outline_destroy(outline); } - outline_destroy(outline); return rle; } @@ -298,16 +259,116 @@ void plutovg_rle_destroy(plutovg_rle_t* rle) free(rle); } -void plutovg_rle_clip_path(plutovg_rle_t* rle, const plutovg_rle_t* clip) +#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) { - (void)rle; - (void)clip; + int count = MAX(a->spans.size, b->spans.size); + plutovg_rle_t* result = malloc(sizeof(plutovg_rle_t)); + plutovg_array_init(result->spans); + plutovg_array_ensure(result->spans, count); + + plutovg_span_t* a_spans = a->spans.data; + plutovg_span_t* a_end = a_spans + a->spans.size; + + plutovg_span_t* b_spans = b->spans.data; + plutovg_span_t* b_end = b_spans + b->spans.size; + + while(count && a_spans < a_end && b_spans < b_end) + { + if(b_spans->y > a_spans->y) + { + ++a_spans; + continue; + } + + if(a_spans->y != b_spans->y) + { + ++b_spans; + continue; + } + + int ax1 = a_spans->x; + int ax2 = ax1 + a_spans->len; + int bx1 = b_spans->x; + int bx2 = bx1 + b_spans->len; + + if(bx1 < ax1 && bx2 < ax1) + { + ++b_spans; + continue; + } + else if(ax1 < bx1 && ax2 < bx1) + { + ++a_spans; + continue; + } + + int x = MAX(ax1, bx1); + int len = MIN(ax2, bx2) - x; + if(len) + { + plutovg_span_t* span = result->spans.data + result->spans.size; + span->x = (short)x; + span->len = (unsigned short)len; + span->y = a_spans->y; + span->coverage = DIV255(a_spans->coverage * b_spans->coverage); + ++result->spans.size; + --count; + } + + if(ax2 < bx2) + { + ++a_spans; + } + else + { + ++b_spans; + } + } + + if(result->spans.size==0) + { + result->x = 0; + result->y = 0; + result->w = 0; + result->h = 0; + return result; + } + + plutovg_span_t* spans = result->spans.data; + int x1 = INT_MAX; + int y1 = spans[0].y; + int x2 = 0; + int y2 = spans[result->spans.size - 1].y; + for(int i = 0;i < result->spans.size;i++) + { + if(spans[i].x < x1) x1 = spans[i].x; + if(spans[i].x + spans[i].len > x2) x2 = spans[i].x + spans[i].len; + } + + result->x = x1; + result->y = y1; + result->w = x2 - x1; + result->h = y2 - y1 + 1; + return result; } -void plutovg_rle_clip_rect(plutovg_rle_t* rle, const plutovg_rect_t* clip) +void plutovg_rle_clip_path(plutovg_rle_t* rle, const plutovg_rle_t* clip) { - (void)rle; - (void)clip; + if(rle==NULL || clip==NULL) + return; + + plutovg_rle_t* result = plutovg_rle_intersection(rle, clip); + plutovg_array_ensure(rle->spans, result->spans.size); + memcpy(rle->spans.data, result->spans.data, (size_t)result->spans.size * sizeof(plutovg_span_t)); + rle->spans.size = result->spans.size; + rle->x = result->x; + rle->y = result->y; + rle->w = result->w; + rle->h = result->h; + plutovg_rle_destroy(result); } plutovg_rle_t* plutovg_rle_clone(const plutovg_rle_t* rle) @@ -315,15 +376,15 @@ plutovg_rle_t* plutovg_rle_clone(const plutovg_rle_t* rle) if(rle==NULL) return NULL; - plutovg_rle_t* r = malloc(sizeof(plutovg_rle_t)); - plutovg_array_init(r->spans); - plutovg_array_ensure(r->spans, rle->spans.size); - - memcpy(r->spans.data, rle->spans.data, (size_t)rle->spans.size * sizeof(plutovg_span_t)); - r->spans.size = rle->spans.size; - r->x = rle->x; - r->y = rle->y; - r->w = rle->w; - r->h = rle->h; - return r; + plutovg_rle_t* result = malloc(sizeof(plutovg_rle_t)); + plutovg_array_init(result->spans); + plutovg_array_ensure(result->spans, rle->spans.size); + + memcpy(result->spans.data, rle->spans.data, (size_t)rle->spans.size * sizeof(plutovg_span_t)); + result->spans.size = rle->spans.size; + result->x = rle->x; + result->y = rle->y; + result->w = rle->w; + result->h = rle->h; + return result; } diff --git a/3rdparty/plutovg/plutovg.c b/3rdparty/plutovg/plutovg.c index 62e5cc3..8e7a295 100644 --- a/3rdparty/plutovg/plutovg.c +++ b/3rdparty/plutovg/plutovg.c @@ -73,7 +73,7 @@ int plutovg_surface_get_stride(const plutovg_surface_t* surface) plutovg_state_t* plutovg_state_create(void) { plutovg_state_t* state = malloc(sizeof(plutovg_state_t)); - state->clip = NULL; + state->clippath = NULL; state->source = plutovg_paint_create_rgb(0, 0, 0); plutovg_matrix_init_identity(&state->matrix); state->winding = plutovg_fill_rule_non_zero; @@ -90,7 +90,7 @@ plutovg_state_t* plutovg_state_create(void) plutovg_state_t* plutovg_state_clone(const plutovg_state_t* state) { plutovg_state_t* newstate = malloc(sizeof(plutovg_state_t)); - newstate->clip = plutovg_rle_clone(state->clip); + newstate->clippath = plutovg_rle_clone(state->clippath); newstate->source = plutovg_paint_reference(state->source); /** FIXME: **/ newstate->matrix = state->matrix; newstate->winding = state->winding; @@ -106,7 +106,7 @@ plutovg_state_t* plutovg_state_clone(const plutovg_state_t* state) void plutovg_state_destroy(plutovg_state_t* state) { - plutovg_rle_destroy(state->clip); + plutovg_rle_destroy(state->clippath); plutovg_paint_destroy(state->source); free(state); } @@ -118,6 +118,7 @@ plutovg_t* plutovg_create(plutovg_surface_t* surface) pluto->surface = plutovg_surface_reference(surface); pluto->state = plutovg_state_create(); pluto->path = plutovg_path_create(); + pluto->clippath = NULL; pluto->clip.x = 0.0; pluto->clip.y = 0.0; pluto->clip.w = surface->width; @@ -147,6 +148,7 @@ void plutovg_destroy(plutovg_t* pluto) plutovg_surface_destroy(pluto->surface); plutovg_path_destroy(pluto->path); + plutovg_rle_destroy(pluto->clippath); free(pluto); } } @@ -214,8 +216,24 @@ void plutovg_set_source_texture(plutovg_t* pluto, plutovg_texture_t* texture) void plutovg_set_source(plutovg_t* pluto, plutovg_paint_t* source) { + source = plutovg_paint_reference(source); plutovg_paint_destroy(pluto->state->source); - pluto->state->source = plutovg_paint_reference(source); + pluto->state->source = source; +} + +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) +{ + pluto->state->op = op; +} + +void plutovg_set_opacity(plutovg_t* pluto, double opacity) +{ + pluto->state->opacity = opacity; } void plutovg_set_fill_rule(plutovg_t* pluto, plutovg_fill_rule_t fill_rule) @@ -223,6 +241,21 @@ void plutovg_set_fill_rule(plutovg_t* pluto, plutovg_fill_rule_t fill_rule) pluto->state->winding = fill_rule; } +plutovg_operator_t plutovg_get_operator(const plutovg_t* pluto) +{ + return pluto->state->op; +} + +double plutovg_get_opacity(const plutovg_t* pluto) +{ + return pluto->state->opacity; +} + +plutovg_fill_rule_t plutovg_get_fill_rule(const plutovg_t* pluto) +{ + return pluto->state->winding; +} + void plutovg_set_line_width(plutovg_t* pluto, double width) { pluto->state->stroke.width = width; @@ -243,14 +276,24 @@ void plutovg_set_miter_limit(plutovg_t* pluto, double limit) pluto->state->stroke.miterlimit = limit; } -void plutovg_set_operator(plutovg_t* pluto, plutovg_operator_t op) +double plutovg_get_line_width(const plutovg_t* pluto) { - pluto->state->op = op; + return pluto->state->stroke.width; } -void plutovg_set_opacity(plutovg_t* pluto, double opacity) +plutovg_line_cap_t plutovg_get_line_cap(const plutovg_t* pluto) { - pluto->state->opacity = opacity; + return pluto->state->stroke.cap; +} + +plutovg_line_join_t plutovg_get_line_join(const plutovg_t* pluto) +{ + return pluto->state->stroke.join; +} + +double plutovg_get_miter_limit(const plutovg_t* pluto) +{ + return pluto->state->stroke.miterlimit; } void plutovg_translate(plutovg_t* pluto, double x, double y) @@ -283,6 +326,11 @@ void plutovg_identity_matrix(plutovg_t* pluto) plutovg_matrix_init_identity(&pluto->state->matrix); } +void plutovg_get_matrix(const plutovg_t* pluto, plutovg_matrix_t* matrix) +{ + memcpy(matrix, &pluto->state->matrix, sizeof(plutovg_matrix_t)); +} + void plutovg_move_to(plutovg_t* pluto, double x, double y) { plutovg_path_move_to(pluto->path, x, y); @@ -358,6 +406,11 @@ void plutovg_close_path(plutovg_t* pluto) plutovg_path_close(pluto->path); } +plutovg_path_t* plutovg_get_path(const plutovg_t* pluto) +{ + return pluto->path; +} + void plutovg_fill(plutovg_t* pluto) { plutovg_fill_preserve(pluto); @@ -376,252 +429,52 @@ void plutovg_clip(plutovg_t* pluto) plutovg_new_path(pluto); } -static void plutovg_paint_rle(plutovg_t* pluto, const plutovg_rle_t* rle); - void plutovg_fill_preserve(plutovg_t* pluto) { plutovg_state_t* state = pluto->state; - plutovg_rle_t* rle = plutovg_rle_render(pluto->path, &state->matrix, &pluto->clip, NULL, state->winding); - plutovg_rle_clip_path(rle, state->clip); - plutovg_paint_rle(pluto, rle); + plutovg_rle_t* rle = plutovg_rasterize(pluto->path, &state->matrix, &pluto->clip, NULL, state->winding); + plutovg_rle_clip_path(rle, state->clippath); + plutovg_blend(pluto, rle); plutovg_rle_destroy(rle); } void plutovg_stroke_preserve(plutovg_t* pluto) { plutovg_state_t* state = pluto->state; - plutovg_rle_t* rle = plutovg_rle_render(pluto->path, &state->matrix, &pluto->clip, &state->stroke, state->winding); - plutovg_rle_clip_path(rle, state->clip); - plutovg_paint_rle(pluto, rle); + plutovg_rle_t* rle = plutovg_rasterize(pluto->path, &state->matrix, &pluto->clip, &state->stroke, plutovg_fill_rule_non_zero); + plutovg_rle_clip_path(rle, state->clippath); + plutovg_blend(pluto, rle); plutovg_rle_destroy(rle); } void plutovg_clip_preserve(plutovg_t* pluto) { plutovg_state_t* state = pluto->state; - plutovg_rle_t* rle = plutovg_rle_render(pluto->path, &state->matrix, &pluto->clip, NULL, state->winding); - if(state->clip) + plutovg_rle_t* rle = plutovg_rasterize(pluto->path, &state->matrix, &pluto->clip, NULL, state->winding); + if(state->clippath) { - plutovg_rle_clip_path(state->clip, rle); + plutovg_rle_clip_path(state->clippath, rle); plutovg_rle_destroy(rle); } else { - state->clip = rle; + state->clippath = rle; } } void plutovg_paint(plutovg_t* pluto) { plutovg_state_t* state = pluto->state; - if(state->clip==NULL) + if(state->clippath==NULL && pluto->clippath==NULL) { plutovg_path_t* path = plutovg_path_create(); plutovg_path_add_rect(path, pluto->clip.x, pluto->clip.y, pluto->clip.w, pluto->clip.h); - plutovg_rle_t* rle = plutovg_rle_render(path, &state->matrix, &pluto->clip, NULL, state->winding); - plutovg_paint_rle(pluto, rle); + plutovg_matrix_t matrix; + plutovg_matrix_init_identity(&matrix); + pluto->clippath = plutovg_rasterize(path, &matrix, &pluto->clip, NULL, plutovg_fill_rule_non_zero); plutovg_path_destroy(path); - plutovg_rle_destroy(rle); - } - else - { - plutovg_paint_rle(pluto, state->clip); - } -} - -plutovg_fill_rule_t plutovg_get_fill_rule(const plutovg_t* pluto) -{ - return pluto->state->winding; -} - -double plutovg_get_line_width(const plutovg_t* pluto) -{ - return pluto->state->stroke.width; -} - -plutovg_line_cap_t plutovg_get_line_cap(const plutovg_t* pluto) -{ - return pluto->state->stroke.cap; -} - -plutovg_line_join_t plutovg_get_line_join(const plutovg_t* pluto) -{ - return pluto->state->stroke.join; -} - -double plutovg_get_miter_limit(const plutovg_t* pluto) -{ - return pluto->state->stroke.miterlimit; -} - -plutovg_operator_t plutovg_get_operator(const plutovg_t* pluto) -{ - return pluto->state->op; -} - -double plutovg_get_opacity(const plutovg_t* pluto) -{ - return pluto->state->opacity; -} - -void plutovg_get_matrix(const plutovg_t* pluto, plutovg_matrix_t* matrix) -{ - memcpy(matrix, &pluto->state->matrix, sizeof(plutovg_matrix_t)); -} - -plutovg_path_t* plutovg_get_path(const plutovg_t* pluto) -{ - return pluto->path; -} - -plutovg_paint_t* plutovg_get_source(const plutovg_t* pluto) -{ - return pluto->state->source; -} - -static inline uint32_t premultiply_color(const plutovg_color_t* color, double opacity) -{ - uint32_t alpha = (uint8_t)(color->a * opacity * 255); - uint32_t pr = (uint8_t)(color->r * alpha); - uint32_t pg = (uint8_t)(color->g * alpha); - uint32_t pb = (uint8_t)(color->b * alpha); - - return (alpha << 24) | (pr << 16) | (pg << 8) | (pb); -} - -static void plutovg_paint_rle_color(plutovg_t* pluto, const plutovg_color_t* color, const plutovg_rle_t* rle) -{ - plutovg_state_t* state = pluto->state; - uint32_t solid = premultiply_color(color, state->opacity); - plutovg_blend_solid(pluto->surface, state->op, rle, solid); -} - -static inline uint32_t interpolate_pixel(uint32_t x, uint32_t a, uint32_t y, uint32_t b) -{ - uint32_t t = (x & 0xff00ff) * a + (y & 0xff00ff) * b; - t >>= 8; - t &= 0xff00ff; - x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b; - x &= 0xff00ff00; - x |= t; - return x; -} - -static void plutovg_paint_rle_gradient(plutovg_t* pluto, const plutovg_gradient_t* gradient, const plutovg_rle_t* rle) -{ - plutovg_state_t* state = pluto->state; - plutovg_gradient_data_t data; - if(gradient->type==plutovg_gradient_type_linear) - { - data.type = plutovg_gradient_type_linear; - data.linear.x1 = gradient->values[0]; - data.linear.y1 = gradient->values[1]; - data.linear.x2 = gradient->values[2]; - data.linear.y2 = gradient->values[3]; } - else - { - data.type = plutovg_gradient_type_radial; - data.radial.cx = gradient->values[0]; - data.radial.cy = gradient->values[1]; - data.radial.cr = gradient->values[2]; - data.radial.fx = gradient->values[3]; - data.radial.fy = gradient->values[4]; - data.radial.fr = gradient->values[5]; - } - - int dist, idist, pos = 0; - int i; - int alpha = 0; - int nstop = gradient->stops.size; - const plutovg_gradient_stop_t *curr, *next, *start; - uint32_t curr_color, next_color; - double delta, t, incr, fpos; - double opacity = state->opacity * gradient->opacity; - - if(opacity != 1.0) alpha = 1; - - start = gradient->stops.data; - curr = start; - if(curr->color.a != 0.0) alpha = 1; - curr_color = premultiply_color(&curr->color, opacity); - incr = 1.0 / COLOR_TABLE_SIZE; - fpos = 1.5 * incr; - - data.colortable[pos++] = curr_color; - - while(fpos <= curr->offset) - { - data.colortable[pos] = data.colortable[pos - 1]; - pos++; - fpos += incr; - } - - for(i = 0;i < nstop - 1;i++) - { - curr = (start + i); - next = (start + i + 1); - delta = 1.0 / (next->offset - curr->offset); - if(next->color.a != 0.0) alpha = 1; - next_color = premultiply_color(&next->color, opacity); - while(fpos < next->offset && pos < COLOR_TABLE_SIZE) - { - t = (fpos - curr->offset) * delta; - dist = (int)(255 * t); - idist = 255 - dist; - data.colortable[pos] = interpolate_pixel(curr_color, (uint32_t)idist, next_color, (uint32_t)dist); - ++pos; - fpos += incr; - } - curr_color = next_color; - } - - for(;pos < COLOR_TABLE_SIZE;++pos) data.colortable[pos] = curr_color; - data.colortable[COLOR_TABLE_SIZE - 1] = curr_color; - data.spread = gradient->spread; - - data.matrix = gradient->matrix; - plutovg_matrix_multiply(&data.matrix, &data.matrix, &state->matrix); - plutovg_matrix_invert(&data.matrix); - - plutovg_blend_gradient(pluto->surface, state->op, rle, &data); -} - -static void plutovg_paint_rle_texture(plutovg_t* pluto, const plutovg_texture_t* texture, const plutovg_rle_t* rle) -{ - plutovg_state_t* state = pluto->state; - plutovg_texture_data_t data; - data.type = texture->type; - data.data = texture->surface->data; - data.width = texture->surface->width; - data.height = texture->surface->height; - data.stride = texture->surface->stride; - data.const_alpha = (int)(state->opacity * texture->opacity * 255.0); - - data.matrix = texture->matrix; - plutovg_matrix_multiply(&data.matrix, &data.matrix, &state->matrix); - plutovg_matrix_invert(&data.matrix); - - plutovg_blend_texture(pluto->surface, state->op, rle, &data); -} - -static void plutovg_paint_rle(plutovg_t* pluto, const plutovg_rle_t* rle) -{ - plutovg_paint_t* source = pluto->state->source; - if(source->type==plutovg_paint_type_color) - { - const plutovg_color_t* color = plutovg_paint_get_color(source); - plutovg_paint_rle_color(pluto, color, rle); - } - else if(source->type==plutovg_paint_type_gradient) - { - const plutovg_gradient_t* gradient = plutovg_paint_get_gradient(source); - plutovg_paint_rle_gradient(pluto, gradient, rle); - } - else - { - const plutovg_texture_t* texture = plutovg_paint_get_texture(source); - plutovg_paint_rle_texture(pluto, texture, rle); - } + plutovg_rle_t* rle = state->clippath ? state->clippath : pluto->clippath; + plutovg_blend(pluto, rle); } diff --git a/3rdparty/plutovg/plutovg.h b/3rdparty/plutovg/plutovg.h index 7d5c076..dbb7276 100644 --- a/3rdparty/plutovg/plutovg.h +++ b/3rdparty/plutovg/plutovg.h @@ -223,19 +223,32 @@ void plutovg_set_source_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); void plutovg_set_source(plutovg_t* pluto, plutovg_paint_t* source); +plutovg_paint_t* plutovg_get_source(const plutovg_t* pluto); + +void plutovg_set_operator(plutovg_t* pluto, plutovg_operator_t op); +void plutovg_set_opacity(plutovg_t* pluto, double opacity); void plutovg_set_fill_rule(plutovg_t* pluto, plutovg_fill_rule_t fill_rule); +plutovg_operator_t plutovg_get_operator(const plutovg_t* pluto); +double plutovg_get_opacity(const plutovg_t* pluto); +plutovg_fill_rule_t plutovg_get_fill_rule(const plutovg_t* pluto); + void plutovg_set_line_width(plutovg_t* pluto, double width); void plutovg_set_line_cap(plutovg_t* pluto, plutovg_line_cap_t cap); void plutovg_set_line_join(plutovg_t* pluto, plutovg_line_join_t join); void plutovg_set_miter_limit(plutovg_t* pluto, double limit); -void plutovg_set_operator(plutovg_t* pluto, plutovg_operator_t op); -void plutovg_set_opacity(plutovg_t* pluto, double opacity); +double plutovg_get_line_width(const plutovg_t* pluto); +plutovg_line_cap_t plutovg_get_line_cap(const plutovg_t* pluto); +plutovg_line_join_t plutovg_get_line_join(const plutovg_t* pluto); +double plutovg_get_miter_limit(const plutovg_t* pluto); + void plutovg_translate(plutovg_t* pluto, double x, double y); void plutovg_scale(plutovg_t* pluto, double x, double y); void plutovg_rotate(plutovg_t* pluto, double radians, double x, double y); void plutovg_transform(plutovg_t* pluto, const plutovg_matrix_t* matrix); void plutovg_set_matrix(plutovg_t* pluto, const plutovg_matrix_t* matrix); void plutovg_identity_matrix(plutovg_t* pluto); +void plutovg_get_matrix(const plutovg_t* pluto, plutovg_matrix_t* matrix); + void plutovg_move_to(plutovg_t* pluto, double x, double y); void plutovg_line_to(plutovg_t* pluto, double x, double y); void plutovg_quad_to(plutovg_t* pluto, double x1, double y1, double x2, double y2); @@ -251,23 +264,16 @@ void plutovg_circle(plutovg_t* pluto, double cx, double cy, double r); void plutovg_add_path(plutovg_t* pluto, const plutovg_path_t* path); void plutovg_new_path(plutovg_t* pluto); void plutovg_close_path(plutovg_t* pluto); +plutovg_path_t* plutovg_get_path(const plutovg_t* pluto); + void plutovg_fill(plutovg_t* pluto); void plutovg_stroke(plutovg_t* pluto); void plutovg_clip(plutovg_t* pluto); + void plutovg_fill_preserve(plutovg_t* pluto); void plutovg_stroke_preserve(plutovg_t* pluto); void plutovg_clip_preserve(plutovg_t* pluto); void plutovg_paint(plutovg_t* pluto); -plutovg_fill_rule_t plutovg_get_fill_rule(const plutovg_t* pluto); -double plutovg_get_line_width(const plutovg_t* pluto); -plutovg_line_cap_t plutovg_get_line_cap(const plutovg_t* pluto); -plutovg_line_join_t plutovg_get_line_join(const plutovg_t* pluto); -double plutovg_get_miter_limit(const plutovg_t* pluto); -plutovg_operator_t plutovg_get_operator(const plutovg_t* pluto); -double plutovg_get_opacity(const plutovg_t* pluto); -void plutovg_get_matrix(const plutovg_t* pluto, plutovg_matrix_t* matrix); -plutovg_path_t* plutovg_get_path(const plutovg_t* pluto); -plutovg_paint_t* plutovg_get_source(const plutovg_t* pluto); #ifdef __cplusplus }