First Commit
This commit is contained in:
714
3rdparty/plutosvg/plutovg/source/plutovg-canvas.c
vendored
Normal file
714
3rdparty/plutosvg/plutovg/source/plutovg-canvas.c
vendored
Normal file
@@ -0,0 +1,714 @@
|
||||
#include "plutovg-private.h"
|
||||
#include "plutovg-utils.h"
|
||||
|
||||
int plutovg_version(void)
|
||||
{
|
||||
return PLUTOVG_VERSION;
|
||||
}
|
||||
|
||||
const char* plutovg_version_string(void)
|
||||
{
|
||||
return PLUTOVG_VERSION_STRING;
|
||||
}
|
||||
|
||||
#define PLUTOVG_DEFAULT_STROKE_STYLE ((plutovg_stroke_style_t){1.f, PLUTOVG_LINE_CAP_BUTT, PLUTOVG_LINE_JOIN_MITER, 10.f})
|
||||
|
||||
static plutovg_state_t* plutovg_state_create(void)
|
||||
{
|
||||
plutovg_state_t* state = malloc(sizeof(plutovg_state_t));
|
||||
state->paint = NULL;
|
||||
state->font_face = NULL;
|
||||
state->color = PLUTOVG_BLACK_COLOR;
|
||||
state->matrix = PLUTOVG_IDENTITY_MATRIX;
|
||||
state->stroke.style = PLUTOVG_DEFAULT_STROKE_STYLE;
|
||||
state->stroke.dash.offset = 0.f;
|
||||
plutovg_array_init(state->stroke.dash.array);
|
||||
plutovg_span_buffer_init(&state->clip_spans);
|
||||
state->winding = PLUTOVG_FILL_RULE_NON_ZERO;
|
||||
state->op = PLUTOVG_OPERATOR_SRC_OVER;
|
||||
state->font_size = 12.f;
|
||||
state->opacity = 1.f;
|
||||
state->clipping = false;
|
||||
state->next = NULL;
|
||||
return state;
|
||||
}
|
||||
|
||||
static void plutovg_state_reset(plutovg_state_t* state)
|
||||
{
|
||||
plutovg_paint_destroy(state->paint);
|
||||
plutovg_font_face_destroy(state->font_face);
|
||||
state->paint = NULL;
|
||||
state->font_face = NULL;
|
||||
state->color = PLUTOVG_BLACK_COLOR;
|
||||
state->matrix = PLUTOVG_IDENTITY_MATRIX;
|
||||
state->stroke.style = PLUTOVG_DEFAULT_STROKE_STYLE;
|
||||
state->stroke.dash.offset = 0.f;
|
||||
plutovg_array_clear(state->stroke.dash.array);
|
||||
plutovg_span_buffer_reset(&state->clip_spans);
|
||||
state->winding = PLUTOVG_FILL_RULE_NON_ZERO;
|
||||
state->op = PLUTOVG_OPERATOR_SRC_OVER;
|
||||
state->font_size = 12.f;
|
||||
state->opacity = 1.f;
|
||||
state->clipping = false;
|
||||
}
|
||||
|
||||
static void plutovg_state_copy(plutovg_state_t* state, const plutovg_state_t* source)
|
||||
{
|
||||
state->paint = plutovg_paint_reference(source->paint);
|
||||
state->font_face = plutovg_font_face_reference(source->font_face);
|
||||
state->color = source->color;
|
||||
state->matrix = source->matrix;
|
||||
state->stroke.style = source->stroke.style;
|
||||
state->stroke.dash.offset = source->stroke.dash.offset;
|
||||
plutovg_array_clear(state->stroke.dash.array);
|
||||
plutovg_array_append(state->stroke.dash.array, source->stroke.dash.array);
|
||||
plutovg_span_buffer_copy(&state->clip_spans, &source->clip_spans);
|
||||
state->winding = source->winding;
|
||||
state->op = source->op;
|
||||
state->font_size = source->font_size;
|
||||
state->opacity = source->opacity;
|
||||
state->clipping = source->clipping;
|
||||
}
|
||||
|
||||
static void plutovg_state_destroy(plutovg_state_t* state)
|
||||
{
|
||||
plutovg_paint_destroy(state->paint);
|
||||
plutovg_font_face_destroy(state->font_face);
|
||||
plutovg_array_destroy(state->stroke.dash.array);
|
||||
plutovg_span_buffer_destroy(&state->clip_spans);
|
||||
free(state);
|
||||
}
|
||||
|
||||
plutovg_canvas_t* plutovg_canvas_create(plutovg_surface_t* surface)
|
||||
{
|
||||
plutovg_canvas_t* canvas = malloc(sizeof(plutovg_canvas_t));
|
||||
canvas->ref_count = 1;
|
||||
canvas->surface = plutovg_surface_reference(surface);
|
||||
canvas->path = plutovg_path_create();
|
||||
canvas->state = plutovg_state_create();
|
||||
canvas->freed_state = NULL;
|
||||
canvas->clip_rect = PLUTOVG_MAKE_RECT(0, 0, surface->width, surface->height);
|
||||
plutovg_span_buffer_init(&canvas->clip_spans);
|
||||
plutovg_span_buffer_init(&canvas->fill_spans);
|
||||
return canvas;
|
||||
}
|
||||
|
||||
plutovg_canvas_t* plutovg_canvas_reference(plutovg_canvas_t* canvas)
|
||||
{
|
||||
if(canvas == NULL)
|
||||
return NULL;
|
||||
++canvas->ref_count;
|
||||
return canvas;
|
||||
}
|
||||
|
||||
void plutovg_canvas_destroy(plutovg_canvas_t* canvas)
|
||||
{
|
||||
if(canvas == NULL)
|
||||
return;
|
||||
if(--canvas->ref_count == 0) {
|
||||
while(canvas->state) {
|
||||
plutovg_state_t* state = canvas->state;
|
||||
canvas->state = state->next;
|
||||
plutovg_state_destroy(state);
|
||||
}
|
||||
|
||||
while(canvas->freed_state) {
|
||||
plutovg_state_t* state = canvas->freed_state;
|
||||
canvas->freed_state = state->next;
|
||||
plutovg_state_destroy(state);
|
||||
}
|
||||
|
||||
plutovg_span_buffer_destroy(&canvas->fill_spans);
|
||||
plutovg_span_buffer_destroy(&canvas->clip_spans);
|
||||
plutovg_surface_destroy(canvas->surface);
|
||||
plutovg_path_destroy(canvas->path);
|
||||
free(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
int plutovg_canvas_get_reference_count(const plutovg_canvas_t* canvas)
|
||||
{
|
||||
if(canvas == NULL)
|
||||
return 0;
|
||||
return canvas->ref_count;
|
||||
}
|
||||
|
||||
plutovg_surface_t* plutovg_canvas_get_surface(const plutovg_canvas_t* canvas)
|
||||
{
|
||||
return canvas->surface;
|
||||
}
|
||||
|
||||
void plutovg_canvas_save(plutovg_canvas_t* canvas)
|
||||
{
|
||||
plutovg_state_t* new_state = canvas->freed_state;
|
||||
if(new_state == NULL)
|
||||
new_state = plutovg_state_create();
|
||||
else
|
||||
canvas->freed_state = new_state->next;
|
||||
plutovg_state_copy(new_state, canvas->state);
|
||||
new_state->next = canvas->state;
|
||||
canvas->state = new_state;
|
||||
}
|
||||
|
||||
void plutovg_canvas_restore(plutovg_canvas_t* canvas)
|
||||
{
|
||||
if(canvas->state->next == NULL)
|
||||
return;
|
||||
plutovg_state_t* old_state = canvas->state;
|
||||
canvas->state = old_state->next;
|
||||
plutovg_state_reset(old_state);
|
||||
old_state->next = canvas->freed_state;
|
||||
canvas->freed_state = old_state;
|
||||
}
|
||||
|
||||
void plutovg_canvas_set_rgb(plutovg_canvas_t* canvas, float r, float g, float b)
|
||||
{
|
||||
plutovg_canvas_set_rgba(canvas, r, g, b, 1.f);
|
||||
}
|
||||
|
||||
void plutovg_canvas_set_rgba(plutovg_canvas_t* canvas, float r, float g, float b, float a)
|
||||
{
|
||||
plutovg_color_init_rgba(&canvas->state->color, r, g, b, a);
|
||||
plutovg_canvas_set_paint(canvas, NULL);
|
||||
}
|
||||
|
||||
void plutovg_canvas_set_color(plutovg_canvas_t* canvas, const plutovg_color_t* color)
|
||||
{
|
||||
plutovg_canvas_set_rgba(canvas, color->r, color->g, color->b, color->a);
|
||||
}
|
||||
|
||||
void plutovg_canvas_set_linear_gradient(plutovg_canvas_t* canvas, float x1, float y1, float x2, float y2, plutovg_spread_method_t spread, const plutovg_gradient_stop_t* stops, int nstops, const plutovg_matrix_t* matrix)
|
||||
{
|
||||
plutovg_paint_t* paint = plutovg_paint_create_linear_gradient(x1, y1, x2, y2, spread, stops, nstops, matrix);
|
||||
plutovg_canvas_set_paint(canvas, paint);
|
||||
plutovg_paint_destroy(paint);
|
||||
}
|
||||
|
||||
void plutovg_canvas_set_radial_gradient(plutovg_canvas_t* canvas, float cx, float cy, float cr, float fx, float fy, float fr, plutovg_spread_method_t spread, const plutovg_gradient_stop_t* stops, int nstops, const plutovg_matrix_t* matrix)
|
||||
{
|
||||
plutovg_paint_t* paint = plutovg_paint_create_radial_gradient(cx, cy, cr, fx, fy, fr, spread, stops, nstops, matrix);
|
||||
plutovg_canvas_set_paint(canvas, paint);
|
||||
plutovg_paint_destroy(paint);
|
||||
}
|
||||
|
||||
void plutovg_canvas_set_texture(plutovg_canvas_t* canvas, plutovg_surface_t* surface, plutovg_texture_type_t type, float opacity, const plutovg_matrix_t* matrix)
|
||||
{
|
||||
plutovg_paint_t* paint = plutovg_paint_create_texture(surface, type, opacity, matrix);
|
||||
plutovg_canvas_set_paint(canvas, paint);
|
||||
plutovg_paint_destroy(paint);
|
||||
}
|
||||
|
||||
void plutovg_canvas_set_paint(plutovg_canvas_t* canvas, plutovg_paint_t* paint)
|
||||
{
|
||||
paint = plutovg_paint_reference(paint);
|
||||
plutovg_paint_destroy(canvas->state->paint);
|
||||
canvas->state->paint = paint;
|
||||
}
|
||||
|
||||
plutovg_paint_t* plutovg_canvas_get_paint(const plutovg_canvas_t* canvas, plutovg_color_t* color)
|
||||
{
|
||||
if(color)
|
||||
*color = canvas->state->color;
|
||||
return canvas->state->paint;
|
||||
}
|
||||
|
||||
void plutovg_canvas_set_font(plutovg_canvas_t* canvas, plutovg_font_face_t* face, float size)
|
||||
{
|
||||
plutovg_canvas_set_font_face(canvas, face);
|
||||
plutovg_canvas_set_font_size(canvas, size);
|
||||
}
|
||||
|
||||
void plutovg_canvas_set_font_face(plutovg_canvas_t* canvas, plutovg_font_face_t* face)
|
||||
{
|
||||
face = plutovg_font_face_reference(face);
|
||||
plutovg_font_face_destroy(canvas->state->font_face);
|
||||
canvas->state->font_face = face;
|
||||
}
|
||||
|
||||
plutovg_font_face_t* plutovg_canvas_get_font_face(const plutovg_canvas_t* canvas)
|
||||
{
|
||||
return canvas->state->font_face;
|
||||
}
|
||||
|
||||
void plutovg_canvas_set_font_size(plutovg_canvas_t* canvas, float size)
|
||||
{
|
||||
canvas->state->font_size = size;
|
||||
}
|
||||
|
||||
float plutovg_canvas_get_font_size(const plutovg_canvas_t* canvas)
|
||||
{
|
||||
return canvas->state->font_size;
|
||||
}
|
||||
|
||||
void plutovg_canvas_set_fill_rule(plutovg_canvas_t* canvas, plutovg_fill_rule_t winding)
|
||||
{
|
||||
canvas->state->winding = winding;
|
||||
}
|
||||
|
||||
plutovg_fill_rule_t plutovg_canvas_get_fill_rule(const plutovg_canvas_t* canvas)
|
||||
{
|
||||
return canvas->state->winding;
|
||||
}
|
||||
|
||||
void plutovg_canvas_set_operator(plutovg_canvas_t* canvas, plutovg_operator_t op)
|
||||
{
|
||||
canvas->state->op = op;
|
||||
}
|
||||
|
||||
plutovg_operator_t plutovg_canvas_get_operator(const plutovg_canvas_t* canvas)
|
||||
{
|
||||
return canvas->state->op;
|
||||
}
|
||||
|
||||
void plutovg_canvas_set_opacity(plutovg_canvas_t* canvas, float opacity)
|
||||
{
|
||||
canvas->state->opacity = plutovg_clamp(opacity, 0.f, 1.f);
|
||||
}
|
||||
|
||||
float plutovg_canvas_get_opacity(const plutovg_canvas_t* canvas)
|
||||
{
|
||||
return canvas->state->opacity;
|
||||
}
|
||||
|
||||
void plutovg_canvas_set_line_width(plutovg_canvas_t* canvas, float line_width)
|
||||
{
|
||||
canvas->state->stroke.style.width = line_width;
|
||||
}
|
||||
|
||||
float plutovg_canvas_get_line_width(const plutovg_canvas_t* canvas)
|
||||
{
|
||||
return canvas->state->stroke.style.width;
|
||||
}
|
||||
|
||||
void plutovg_canvas_set_line_cap(plutovg_canvas_t* canvas, plutovg_line_cap_t line_cap)
|
||||
{
|
||||
canvas->state->stroke.style.cap = line_cap;
|
||||
}
|
||||
|
||||
plutovg_line_cap_t plutovg_canvas_get_line_cap(const plutovg_canvas_t* canvas)
|
||||
{
|
||||
return canvas->state->stroke.style.cap;
|
||||
}
|
||||
|
||||
void plutovg_canvas_set_line_join(plutovg_canvas_t* canvas, plutovg_line_join_t line_join)
|
||||
{
|
||||
canvas->state->stroke.style.join = line_join;
|
||||
}
|
||||
|
||||
plutovg_line_join_t plutovg_canvas_get_line_join(const plutovg_canvas_t* canvas)
|
||||
{
|
||||
return canvas->state->stroke.style.join;
|
||||
}
|
||||
|
||||
void plutovg_canvas_set_miter_limit(plutovg_canvas_t* canvas, float miter_limit)
|
||||
{
|
||||
canvas->state->stroke.style.miter_limit = miter_limit;
|
||||
}
|
||||
|
||||
float plutovg_canvas_get_miter_limit(const plutovg_canvas_t* canvas)
|
||||
{
|
||||
return canvas->state->stroke.style.miter_limit;
|
||||
}
|
||||
|
||||
void plutovg_canvas_set_dash(plutovg_canvas_t* canvas, float offset, const float* dashes, int ndashes)
|
||||
{
|
||||
plutovg_canvas_set_dash_offset(canvas, offset);
|
||||
plutovg_canvas_set_dash_array(canvas, dashes, ndashes);
|
||||
}
|
||||
|
||||
void plutovg_canvas_set_dash_offset(plutovg_canvas_t* canvas, float offset)
|
||||
{
|
||||
canvas->state->stroke.dash.offset = offset;
|
||||
}
|
||||
|
||||
float plutovg_canvas_get_dash_offset(const plutovg_canvas_t* canvas)
|
||||
{
|
||||
return canvas->state->stroke.dash.offset;
|
||||
}
|
||||
|
||||
void plutovg_canvas_set_dash_array(plutovg_canvas_t* canvas, const float* dashes, int ndashes)
|
||||
{
|
||||
plutovg_array_clear(canvas->state->stroke.dash.array);
|
||||
plutovg_array_append_data(canvas->state->stroke.dash.array, dashes, ndashes);
|
||||
}
|
||||
|
||||
int plutovg_canvas_get_dash_array(const plutovg_canvas_t* canvas, const float** dashes)
|
||||
{
|
||||
if(dashes)
|
||||
*dashes = canvas->state->stroke.dash.array.data;
|
||||
return canvas->state->stroke.dash.array.size;
|
||||
}
|
||||
|
||||
void plutovg_canvas_translate(plutovg_canvas_t* canvas, float tx, float ty)
|
||||
{
|
||||
plutovg_matrix_translate(&canvas->state->matrix, tx, ty);
|
||||
}
|
||||
|
||||
void plutovg_canvas_scale(plutovg_canvas_t* canvas, float sx, float sy)
|
||||
{
|
||||
plutovg_matrix_scale(&canvas->state->matrix, sx, sy);
|
||||
}
|
||||
|
||||
void plutovg_canvas_shear(plutovg_canvas_t* canvas, float shx, float shy)
|
||||
{
|
||||
plutovg_matrix_shear(&canvas->state->matrix, shx, shy);
|
||||
}
|
||||
|
||||
void plutovg_canvas_rotate(plutovg_canvas_t* canvas, float angle)
|
||||
{
|
||||
plutovg_matrix_rotate(&canvas->state->matrix, angle);
|
||||
}
|
||||
|
||||
void plutovg_canvas_transform(plutovg_canvas_t* canvas, const plutovg_matrix_t* matrix)
|
||||
{
|
||||
plutovg_matrix_multiply(&canvas->state->matrix, matrix, &canvas->state->matrix);
|
||||
}
|
||||
|
||||
void plutovg_canvas_reset_matrix(plutovg_canvas_t* canvas)
|
||||
{
|
||||
plutovg_matrix_init_identity(&canvas->state->matrix);
|
||||
}
|
||||
|
||||
void plutovg_canvas_set_matrix(plutovg_canvas_t* canvas, const plutovg_matrix_t* matrix)
|
||||
{
|
||||
canvas->state->matrix = matrix ? *matrix : PLUTOVG_IDENTITY_MATRIX;
|
||||
}
|
||||
|
||||
void plutovg_canvas_get_matrix(const plutovg_canvas_t* canvas, plutovg_matrix_t* matrix)
|
||||
{
|
||||
*matrix = canvas->state->matrix;
|
||||
}
|
||||
|
||||
void plutovg_canvas_map(const plutovg_canvas_t* canvas, float x, float y, float* xx, float* yy)
|
||||
{
|
||||
plutovg_matrix_map(&canvas->state->matrix, x, y, xx, yy);
|
||||
}
|
||||
|
||||
void plutovg_canvas_map_point(const plutovg_canvas_t* canvas, const plutovg_point_t* src, plutovg_point_t* dst)
|
||||
{
|
||||
plutovg_matrix_map_point(&canvas->state->matrix, src, dst);
|
||||
}
|
||||
|
||||
void plutovg_canvas_map_rect(const plutovg_canvas_t* canvas, const plutovg_rect_t* src, plutovg_rect_t* dst)
|
||||
{
|
||||
plutovg_matrix_map_rect(&canvas->state->matrix, src, dst);
|
||||
}
|
||||
|
||||
void plutovg_canvas_move_to(plutovg_canvas_t* canvas, float x, float y)
|
||||
{
|
||||
plutovg_path_move_to(canvas->path, x, y);
|
||||
}
|
||||
|
||||
void plutovg_canvas_line_to(plutovg_canvas_t* canvas, float x, float y)
|
||||
{
|
||||
plutovg_path_line_to(canvas->path, x, y);
|
||||
}
|
||||
|
||||
void plutovg_canvas_quad_to(plutovg_canvas_t* canvas, float x1, float y1, float x2, float y2)
|
||||
{
|
||||
plutovg_path_quad_to(canvas->path, x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
void plutovg_canvas_cubic_to(plutovg_canvas_t* canvas, float x1, float y1, float x2, float y2, float x3, float y3)
|
||||
{
|
||||
plutovg_path_cubic_to(canvas->path, x1, y1, x2, y2, x3, y3);
|
||||
}
|
||||
|
||||
void plutovg_canvas_arc_to(plutovg_canvas_t* canvas, float rx, float ry, float angle, bool large_arc_flag, bool sweep_flag, float x, float y)
|
||||
{
|
||||
plutovg_path_arc_to(canvas->path, rx, ry, angle, large_arc_flag, sweep_flag, x, y);
|
||||
}
|
||||
|
||||
void plutovg_canvas_rect(plutovg_canvas_t* canvas, float x, float y, float w, float h)
|
||||
{
|
||||
plutovg_path_add_rect(canvas->path, x, y, w, h);
|
||||
}
|
||||
|
||||
void plutovg_canvas_round_rect(plutovg_canvas_t* canvas, float x, float y, float w, float h, float rx, float ry)
|
||||
{
|
||||
plutovg_path_add_round_rect(canvas->path, x, y, w, h, rx, ry);
|
||||
}
|
||||
|
||||
void plutovg_canvas_ellipse(plutovg_canvas_t* canvas, float cx, float cy, float rx, float ry)
|
||||
{
|
||||
plutovg_path_add_ellipse(canvas->path, cx, cy, rx, ry);
|
||||
}
|
||||
|
||||
void plutovg_canvas_circle(plutovg_canvas_t* canvas, float cx, float cy, float r)
|
||||
{
|
||||
plutovg_path_add_circle(canvas->path, cx, cy, r);
|
||||
}
|
||||
|
||||
void plutovg_canvas_arc(plutovg_canvas_t* canvas, float cx, float cy, float r, float a0, float a1, bool ccw)
|
||||
{
|
||||
plutovg_path_add_arc(canvas->path, cx, cy, r, a0, a1, ccw);
|
||||
}
|
||||
|
||||
void plutovg_canvas_add_path(plutovg_canvas_t* canvas, const plutovg_path_t* path)
|
||||
{
|
||||
plutovg_path_add_path(canvas->path, path, NULL);
|
||||
}
|
||||
|
||||
void plutovg_canvas_new_path(plutovg_canvas_t* canvas)
|
||||
{
|
||||
plutovg_path_reset(canvas->path);
|
||||
}
|
||||
|
||||
void plutovg_canvas_close_path(plutovg_canvas_t* canvas)
|
||||
{
|
||||
plutovg_path_close(canvas->path);
|
||||
}
|
||||
|
||||
void plutovg_canvas_get_current_point(const plutovg_canvas_t* canvas, float* x, float* y)
|
||||
{
|
||||
plutovg_path_get_current_point(canvas->path, x, y);
|
||||
}
|
||||
|
||||
plutovg_path_t* plutovg_canvas_get_path(const plutovg_canvas_t* canvas)
|
||||
{
|
||||
return canvas->path;
|
||||
}
|
||||
|
||||
void plutovg_canvas_fill_extents(const plutovg_canvas_t* canvas, plutovg_rect_t* extents)
|
||||
{
|
||||
plutovg_path_extents(canvas->path, extents, true);
|
||||
plutovg_canvas_map_rect(canvas, extents, extents);
|
||||
}
|
||||
|
||||
void plutovg_canvas_stroke_extents(const plutovg_canvas_t* canvas, plutovg_rect_t* extents)
|
||||
{
|
||||
plutovg_stroke_data_t* stroke = &canvas->state->stroke;
|
||||
float cap_limit = stroke->style.width / 2.f;
|
||||
if(stroke->style.cap == PLUTOVG_LINE_CAP_SQUARE)
|
||||
cap_limit *= PLUTOVG_SQRT2;
|
||||
float join_limit = stroke->style.width / 2.f;
|
||||
if(stroke->style.join == PLUTOVG_LINE_JOIN_MITER) {
|
||||
join_limit *= stroke->style.miter_limit;
|
||||
}
|
||||
|
||||
float delta = plutovg_max(cap_limit, join_limit);
|
||||
plutovg_path_extents(canvas->path, extents, true);
|
||||
extents->x -= delta;
|
||||
extents->y -= delta;
|
||||
extents->w += delta * 2.f;
|
||||
extents->h += delta * 2.f;
|
||||
plutovg_canvas_map_rect(canvas, extents, extents);
|
||||
}
|
||||
|
||||
void plutovg_canvas_clip_extents(const plutovg_canvas_t* canvas, plutovg_rect_t* extents)
|
||||
{
|
||||
if(canvas->state->clipping) {
|
||||
plutovg_span_buffer_extents(&canvas->state->clip_spans, extents);
|
||||
} else {
|
||||
extents->x = canvas->clip_rect.x;
|
||||
extents->y = canvas->clip_rect.y;
|
||||
extents->w = canvas->clip_rect.w;
|
||||
extents->h = canvas->clip_rect.h;
|
||||
}
|
||||
}
|
||||
|
||||
void plutovg_canvas_fill(plutovg_canvas_t* canvas)
|
||||
{
|
||||
plutovg_canvas_fill_preserve(canvas);
|
||||
plutovg_canvas_new_path(canvas);
|
||||
}
|
||||
|
||||
void plutovg_canvas_stroke(plutovg_canvas_t* canvas)
|
||||
{
|
||||
plutovg_canvas_stroke_preserve(canvas);
|
||||
plutovg_canvas_new_path(canvas);
|
||||
}
|
||||
|
||||
void plutovg_canvas_clip(plutovg_canvas_t* canvas)
|
||||
{
|
||||
plutovg_canvas_clip_preserve(canvas);
|
||||
plutovg_canvas_new_path(canvas);
|
||||
}
|
||||
|
||||
void plutovg_canvas_paint(plutovg_canvas_t* canvas)
|
||||
{
|
||||
if(canvas->state->clipping) {
|
||||
plutovg_blend(canvas, &canvas->state->clip_spans);
|
||||
} else {
|
||||
plutovg_span_buffer_init_rect(&canvas->clip_spans, 0, 0, canvas->surface->width, canvas->surface->height);
|
||||
plutovg_blend(canvas, &canvas->clip_spans);
|
||||
}
|
||||
}
|
||||
|
||||
void plutovg_canvas_fill_preserve(plutovg_canvas_t* canvas)
|
||||
{
|
||||
plutovg_rasterize(&canvas->fill_spans, canvas->path, &canvas->state->matrix, &canvas->clip_rect, NULL, canvas->state->winding);
|
||||
if(canvas->state->clipping) {
|
||||
plutovg_span_buffer_intersect(&canvas->clip_spans, &canvas->fill_spans, &canvas->state->clip_spans);
|
||||
plutovg_blend(canvas, &canvas->clip_spans);
|
||||
} else {
|
||||
plutovg_blend(canvas, &canvas->fill_spans);
|
||||
}
|
||||
}
|
||||
|
||||
void plutovg_canvas_stroke_preserve(plutovg_canvas_t* canvas)
|
||||
{
|
||||
plutovg_rasterize(&canvas->fill_spans, canvas->path, &canvas->state->matrix, &canvas->clip_rect, &canvas->state->stroke, PLUTOVG_FILL_RULE_NON_ZERO);
|
||||
if(canvas->state->clipping) {
|
||||
plutovg_span_buffer_intersect(&canvas->clip_spans, &canvas->fill_spans, &canvas->state->clip_spans);
|
||||
plutovg_blend(canvas, &canvas->clip_spans);
|
||||
} else {
|
||||
plutovg_blend(canvas, &canvas->fill_spans);
|
||||
}
|
||||
}
|
||||
|
||||
void plutovg_canvas_clip_preserve(plutovg_canvas_t* canvas)
|
||||
{
|
||||
if(canvas->state->clipping) {
|
||||
plutovg_rasterize(&canvas->fill_spans, canvas->path, &canvas->state->matrix, &canvas->clip_rect, NULL, canvas->state->winding);
|
||||
plutovg_span_buffer_intersect(&canvas->clip_spans, &canvas->fill_spans, &canvas->state->clip_spans);
|
||||
plutovg_span_buffer_copy(&canvas->state->clip_spans, &canvas->clip_spans);
|
||||
} else {
|
||||
plutovg_rasterize(&canvas->state->clip_spans, canvas->path, &canvas->state->matrix, &canvas->clip_rect, NULL, canvas->state->winding);
|
||||
canvas->state->clipping = true;
|
||||
}
|
||||
}
|
||||
|
||||
void plutovg_canvas_fill_rect(plutovg_canvas_t* canvas, float x, float y, float w, float h)
|
||||
{
|
||||
plutovg_canvas_new_path(canvas);
|
||||
plutovg_canvas_rect(canvas, x, y, w, h);
|
||||
plutovg_canvas_fill(canvas);
|
||||
}
|
||||
|
||||
void plutovg_canvas_fill_path(plutovg_canvas_t* canvas, const plutovg_path_t* path)
|
||||
{
|
||||
plutovg_canvas_new_path(canvas);
|
||||
plutovg_canvas_add_path(canvas, path);
|
||||
plutovg_canvas_fill(canvas);
|
||||
}
|
||||
|
||||
void plutovg_canvas_stroke_rect(plutovg_canvas_t* canvas, float x, float y, float w, float h)
|
||||
{
|
||||
plutovg_canvas_new_path(canvas);
|
||||
plutovg_canvas_rect(canvas, x, y, w, h);
|
||||
plutovg_canvas_stroke(canvas);
|
||||
}
|
||||
|
||||
void plutovg_canvas_stroke_path(plutovg_canvas_t* canvas, const plutovg_path_t* path)
|
||||
{
|
||||
plutovg_canvas_new_path(canvas);
|
||||
plutovg_canvas_add_path(canvas, path);
|
||||
plutovg_canvas_stroke(canvas);
|
||||
}
|
||||
|
||||
void plutovg_canvas_clip_rect(plutovg_canvas_t* canvas, float x, float y, float w, float h)
|
||||
{
|
||||
plutovg_canvas_new_path(canvas);
|
||||
plutovg_canvas_rect(canvas, x, y, w, h);
|
||||
plutovg_canvas_clip(canvas);
|
||||
}
|
||||
|
||||
void plutovg_canvas_clip_path(plutovg_canvas_t* canvas, const plutovg_path_t* path)
|
||||
{
|
||||
plutovg_canvas_new_path(canvas);
|
||||
plutovg_canvas_add_path(canvas, path);
|
||||
plutovg_canvas_clip(canvas);
|
||||
}
|
||||
|
||||
float plutovg_canvas_add_glyph(plutovg_canvas_t* canvas, plutovg_codepoint_t codepoint, float x, float y)
|
||||
{
|
||||
plutovg_state_t* state = canvas->state;
|
||||
if(state->font_face && state->font_size > 0.f)
|
||||
return plutovg_font_face_get_glyph_path(state->font_face, state->font_size, x, y, codepoint, canvas->path);
|
||||
return 0.f;
|
||||
}
|
||||
|
||||
float plutovg_canvas_add_text(plutovg_canvas_t* canvas, const void* text, int length, plutovg_text_encoding_t encoding, float x, float y)
|
||||
{
|
||||
plutovg_state_t* state = canvas->state;
|
||||
if(state->font_face == NULL || state->font_size <= 0.f)
|
||||
return 0.f;
|
||||
plutovg_text_iterator_t it;
|
||||
plutovg_text_iterator_init(&it, text, length, encoding);
|
||||
float advance_width = 0.f;
|
||||
while(plutovg_text_iterator_has_next(&it)) {
|
||||
plutovg_codepoint_t codepoint = plutovg_text_iterator_next(&it);
|
||||
advance_width += plutovg_font_face_get_glyph_path(state->font_face, state->font_size, x + advance_width, y, codepoint, canvas->path);
|
||||
}
|
||||
|
||||
return advance_width;
|
||||
}
|
||||
|
||||
float plutovg_canvas_fill_text(plutovg_canvas_t* canvas, const void* text, int length, plutovg_text_encoding_t encoding, float x, float y)
|
||||
{
|
||||
plutovg_canvas_new_path(canvas);
|
||||
float advance_width = plutovg_canvas_add_text(canvas, text, length, encoding, x, y);
|
||||
plutovg_canvas_fill(canvas);
|
||||
return advance_width;
|
||||
}
|
||||
|
||||
float plutovg_canvas_stroke_text(plutovg_canvas_t* canvas, const void* text, int length, plutovg_text_encoding_t encoding, float x, float y)
|
||||
{
|
||||
plutovg_canvas_new_path(canvas);
|
||||
float advance_width = plutovg_canvas_add_text(canvas, text, length, encoding, x, y);
|
||||
plutovg_canvas_stroke(canvas);
|
||||
return advance_width;
|
||||
}
|
||||
|
||||
float plutovg_canvas_clip_text(plutovg_canvas_t* canvas, const void* text, int length, plutovg_text_encoding_t encoding, float x, float y)
|
||||
{
|
||||
plutovg_canvas_new_path(canvas);
|
||||
float advance_width = plutovg_canvas_add_text(canvas, text, length, encoding, x, y);
|
||||
plutovg_canvas_clip(canvas);
|
||||
return advance_width;
|
||||
}
|
||||
|
||||
void plutovg_canvas_font_metrics(const plutovg_canvas_t* canvas, float* ascent, float* descent, float* line_gap, plutovg_rect_t* extents)
|
||||
{
|
||||
plutovg_state_t* state = canvas->state;
|
||||
if(state->font_face && state->font_size > 0.f) {
|
||||
plutovg_font_face_get_metrics(state->font_face, state->font_size, ascent, descent, line_gap, extents);
|
||||
return;
|
||||
}
|
||||
|
||||
if(ascent) *ascent = 0.f;
|
||||
if(descent) *descent = 0.f;
|
||||
if(line_gap) *line_gap = 0.f;
|
||||
if(extents) {
|
||||
extents->x = 0.f;
|
||||
extents->y = 0.f;
|
||||
extents->w = 0.f;
|
||||
extents->h = 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
void plutovg_canvas_glyph_metrics(plutovg_canvas_t* canvas, plutovg_codepoint_t codepoint, float* advance_width, float* left_side_bearing, plutovg_rect_t* extents)
|
||||
{
|
||||
plutovg_state_t* state = canvas->state;
|
||||
if(state->font_face && state->font_size > 0.f) {
|
||||
plutovg_font_face_get_glyph_metrics(state->font_face, state->font_size, codepoint, advance_width, left_side_bearing, extents);
|
||||
return;
|
||||
}
|
||||
|
||||
if(advance_width) *advance_width = 0.f;
|
||||
if(left_side_bearing) *left_side_bearing = 0.f;
|
||||
if(extents) {
|
||||
extents->x = 0.f;
|
||||
extents->y = 0.f;
|
||||
extents->w = 0.f;
|
||||
extents->h = 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
float plutovg_canvas_text_extents(plutovg_canvas_t* canvas, const void* text, int length, plutovg_text_encoding_t encoding, plutovg_rect_t* extents)
|
||||
{
|
||||
plutovg_state_t* state = canvas->state;
|
||||
if(state->font_face && state->font_size > 0.f) {
|
||||
return plutovg_font_face_text_extents(state->font_face, state->font_size, text, length, encoding, extents);
|
||||
}
|
||||
|
||||
if(extents) {
|
||||
extents->x = 0.f;
|
||||
extents->y = 0.f;
|
||||
extents->w = 0.f;
|
||||
extents->h = 0.f;
|
||||
}
|
||||
|
||||
return 0.f;
|
||||
}
|
||||
Reference in New Issue
Block a user