From add4a62e0ebf97bd32078952b30a29b9da151e1c Mon Sep 17 00:00:00 2001 From: Hanspeter Portner Date: Fri, 18 Mar 2022 21:27:12 +0100 Subject: [PATCH] outsource idisp and forge functions --- canvas.lv2/forge.h | 303 ++++++++------------------------------------- canvas.lv2/idisp.h | 123 ++---------------- meson.build | 14 +++ src/forge.c | 301 ++++++++++++++++++++++++++++++++++++++++++++ src/idisp.c | 142 +++++++++++++++++++++ test/canvas.c | 209 +++++++++++++++++++++++++++++-- 6 files changed, 721 insertions(+), 371 deletions(-) create mode 100644 src/forge.c create mode 100644 src/idisp.c diff --git a/canvas.lv2/forge.h b/canvas.lv2/forge.h index b5eb616..783d137 100644 --- a/canvas.lv2/forge.h +++ b/canvas.lv2/forge.h @@ -12,300 +12,101 @@ extern "C" { #endif -static inline LV2_Atom_Forge_Ref -_lv2_canvas_forge_simple(LV2_Atom_Forge *forge, LV2_URID otype) -{ - LV2_Atom_Forge_Ref ref; - LV2_Atom_Forge_Frame frame; +LV2_Atom_Forge_Ref +lv2_canvas_forge_beginPath(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid); - ref = lv2_atom_forge_object(forge, &frame, 0, otype); - if(ref) - lv2_atom_forge_pop(forge, &frame); +LV2_Atom_Forge_Ref +lv2_canvas_forge_closePath(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid); - return ref; -} - -static inline LV2_Atom_Forge_Ref -_lv2_canvas_forge_vec(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, - LV2_URID otype, uint32_t n, const float *vec) -{ - LV2_Atom_Forge_Ref ref; - LV2_Atom_Forge_Frame frame; - - ref = lv2_atom_forge_object(forge, &frame, 0, otype); - if(ref) - ref = lv2_atom_forge_key(forge, urid->Canvas_body); - if(ref) - ref = lv2_atom_forge_vector(forge, sizeof(float), forge->Float, n, vec); - if(ref) - lv2_atom_forge_pop(forge, &frame); - - return ref; -} - -static inline LV2_Atom_Forge_Ref -_lv2_canvas_forge_flt(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, - LV2_URID otype, float flt) -{ - LV2_Atom_Forge_Ref ref; - LV2_Atom_Forge_Frame frame; - - ref = lv2_atom_forge_object(forge, &frame, 0, otype); - if(ref) - ref = lv2_atom_forge_key(forge, urid->Canvas_body); - if(ref) - ref = lv2_atom_forge_float(forge, flt); - if(ref) - lv2_atom_forge_pop(forge, &frame); - - return ref; -} - -static inline LV2_Atom_Forge_Ref -_lv2_canvas_forge_lng(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, - LV2_URID otype, int64_t lng) -{ - LV2_Atom_Forge_Ref ref; - LV2_Atom_Forge_Frame frame; - - ref = lv2_atom_forge_object(forge, &frame, 0, otype); - if(ref) - ref = lv2_atom_forge_key(forge, urid->Canvas_body); - if(ref) - ref = lv2_atom_forge_long(forge, lng); - if(ref) - lv2_atom_forge_pop(forge, &frame); - - return ref; -} - -static inline LV2_Atom_Forge_Ref -_lv2_canvas_forge_prp(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, - LV2_URID otype, LV2_URID prop) -{ - LV2_Atom_Forge_Ref ref; - LV2_Atom_Forge_Frame frame; - - ref = lv2_atom_forge_object(forge, &frame, 0, otype); - if(ref) - ref = lv2_atom_forge_key(forge, urid->Canvas_body); - if(ref) - ref = lv2_atom_forge_urid(forge, prop); - if(ref) - lv2_atom_forge_pop(forge, &frame); - - return ref; -} - -static inline LV2_Atom_Forge_Ref -_lv2_canvas_forge_str(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, - LV2_URID otype, const char *text) -{ - LV2_Atom_Forge_Ref ref; - LV2_Atom_Forge_Frame frame; - - ref = lv2_atom_forge_object(forge, &frame, 0, otype); - if(ref) - ref = lv2_atom_forge_key(forge, urid->Canvas_body); - if(ref) - ref = lv2_atom_forge_string(forge, text, strlen(text)); - if(ref) - lv2_atom_forge_pop(forge, &frame); - - return ref; -} - -static inline LV2_Atom_Forge_Ref -lv2_canvas_forge_beginPath(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid) -{ - return _lv2_canvas_forge_simple(forge, urid->Canvas_BeginPath); -} - -static inline LV2_Atom_Forge_Ref -lv2_canvas_forge_closePath(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid) -{ - return _lv2_canvas_forge_simple(forge, urid->Canvas_ClosePath); -} - -static inline LV2_Atom_Forge_Ref +LV2_Atom_Forge_Ref lv2_canvas_forge_arc(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, - float x, float y, float r, float a1, float a2) -{ - const float vec [5] = {x, y, r, a1, a2}; + float x, float y, float r, float a1, float a2); - return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_Arc, 5, vec); -} - -static inline LV2_Atom_Forge_Ref +LV2_Atom_Forge_Ref lv2_canvas_forge_curveTo(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, - float x1, float y1, float x2, float y2, float x3, float y3) -{ - const float vec [6] = {x1, y1, x2, y2, x3, y3}; - - return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_CurveTo, 6, vec); -} + float x1, float y1, float x2, float y2, float x3, float y3); -static inline LV2_Atom_Forge_Ref +LV2_Atom_Forge_Ref lv2_canvas_forge_lineTo(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, - float x, float y) -{ - const float vec [2] = {x, y}; + float x, float y); - return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_LineTo, 2, vec); -} - -static inline LV2_Atom_Forge_Ref +LV2_Atom_Forge_Ref lv2_canvas_forge_moveTo(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, - float x, float y) -{ - const float vec [2] = {x, y}; - - return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_MoveTo, 2, vec); -} + float x, float y); -static inline LV2_Atom_Forge_Ref +LV2_Atom_Forge_Ref lv2_canvas_forge_rectangle(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, - float x, float y, float w, float h) -{ - const float vec [4] = {x, y, w, h}; + float x, float y, float w, float h); - return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_Rectangle, 4, vec); -} - -static inline LV2_Atom_Forge_Ref +LV2_Atom_Forge_Ref lv2_canvas_forge_polyLine(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, - uint32_t n, const float *vec) -{ - return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_PolyLine, n, vec); -} + uint32_t n, const float *vec); -static inline LV2_Atom_Forge_Ref +LV2_Atom_Forge_Ref lv2_canvas_forge_style(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, - uint32_t style) -{ - return _lv2_canvas_forge_lng(forge, urid, urid->Canvas_Style, style); -} + uint32_t style); -static inline LV2_Atom_Forge_Ref +LV2_Atom_Forge_Ref lv2_canvas_forge_lineWidth(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, - float line_width) -{ - return _lv2_canvas_forge_flt(forge, urid, urid->Canvas_LineWidth, line_width); -} + float line_width); -static inline LV2_Atom_Forge_Ref +LV2_Atom_Forge_Ref lv2_canvas_forge_lineDash(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, - float dash_length, float separator_length) -{ - const float vec [2] = {dash_length, separator_length}; - - return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_LineDash, 2, vec); -} + float dash_length, float separator_length); -static inline LV2_Atom_Forge_Ref +LV2_Atom_Forge_Ref lv2_canvas_forge_lineCap(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, - LV2_URID line_cap) -{ - return _lv2_canvas_forge_prp(forge, urid, urid->Canvas_LineCap, line_cap); -} + LV2_URID line_cap); -static inline LV2_Atom_Forge_Ref +LV2_Atom_Forge_Ref lv2_canvas_forge_lineJoin(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, - LV2_URID line_join) -{ - return _lv2_canvas_forge_prp(forge, urid, urid->Canvas_LineJoin, line_join); -} + LV2_URID line_join); -static inline LV2_Atom_Forge_Ref +LV2_Atom_Forge_Ref lv2_canvas_forge_miterLimit(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, - float miter_limit) -{ - return _lv2_canvas_forge_flt(forge, urid, urid->Canvas_MiterLimit, miter_limit); -} + float miter_limit); -static inline LV2_Atom_Forge_Ref -lv2_canvas_forge_stroke(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid) -{ - return _lv2_canvas_forge_simple(forge, urid->Canvas_Stroke); -} +LV2_Atom_Forge_Ref +lv2_canvas_forge_stroke(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid); -static inline LV2_Atom_Forge_Ref -lv2_canvas_forge_fill(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid) -{ - return _lv2_canvas_forge_simple(forge, urid->Canvas_Fill); -} +LV2_Atom_Forge_Ref +lv2_canvas_forge_fill(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid); -static inline LV2_Atom_Forge_Ref -lv2_canvas_forge_clip(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid) -{ - return _lv2_canvas_forge_simple(forge, urid->Canvas_Clip); -} +LV2_Atom_Forge_Ref +lv2_canvas_forge_clip(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid); -static inline LV2_Atom_Forge_Ref -lv2_canvas_forge_save(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid) -{ - return _lv2_canvas_forge_simple(forge, urid->Canvas_Save); -} +LV2_Atom_Forge_Ref +lv2_canvas_forge_save(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid); -static inline LV2_Atom_Forge_Ref -lv2_canvas_forge_restore(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid) -{ - return _lv2_canvas_forge_simple(forge, urid->Canvas_Restore); -} +LV2_Atom_Forge_Ref +lv2_canvas_forge_restore(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid); -static inline LV2_Atom_Forge_Ref +LV2_Atom_Forge_Ref lv2_canvas_forge_translate(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, - float x, float y) -{ - const float vec [2] = {x, y}; + float x, float y); - return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_Translate, 2, vec); -} - -static inline LV2_Atom_Forge_Ref +LV2_Atom_Forge_Ref lv2_canvas_forge_scale(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, - float w, float h) -{ - const float vec [2] = {w, h}; - - return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_Scale, 2, vec); -} + float w, float h); -static inline LV2_Atom_Forge_Ref +LV2_Atom_Forge_Ref lv2_canvas_forge_rotate(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, - float a) -{ - return _lv2_canvas_forge_flt(forge, urid, urid->Canvas_Rotate, a); -} + float a); -static inline LV2_Atom_Forge_Ref +LV2_Atom_Forge_Ref lv2_canvas_forge_transform(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, - float xx, float xy, float x0, float yy, float yx, float y0) -{ - const float vec [6] = {xx, xy, x0, yy, yx, y0}; + float xx, float xy, float x0, float yy, float yx, float y0); - return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_Transform, 6, vec); -} +LV2_Atom_Forge_Ref +lv2_canvas_forge_reset(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid); -static inline LV2_Atom_Forge_Ref -lv2_canvas_forge_reset(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid) -{ - return _lv2_canvas_forge_simple(forge, urid->Canvas_Reset); -} - -static inline LV2_Atom_Forge_Ref +LV2_Atom_Forge_Ref lv2_canvas_forge_fontSize(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, - float size) -{ - return _lv2_canvas_forge_flt(forge, urid, urid->Canvas_FontSize, size); -} + float size); -static inline LV2_Atom_Forge_Ref +LV2_Atom_Forge_Ref lv2_canvas_forge_fillText(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, - const char *text) -{ - return _lv2_canvas_forge_str(forge, urid, urid->Canvas_FillText, text); -} + const char *text); #ifdef __cplusplus } diff --git a/canvas.lv2/idisp.h b/canvas.lv2/idisp.h index 96d3473..3d82302 100644 --- a/canvas.lv2/idisp.h +++ b/canvas.lv2/idisp.h @@ -25,126 +25,23 @@ struct _LV2_Canvas_Idisp { } cairo; }; -static inline LV2_Inline_Display_Image_Surface * -_lv2_canvas_idisp_surf_init(LV2_Canvas_Idisp *idisp, int w, int h) -{ - LV2_Inline_Display_Image_Surface *surf = &idisp->image_surface; - - surf->width = w; - surf->height = h; - surf->stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, surf->width); - surf->data = realloc(surf->data, surf->stride * surf->height); - if(!surf->data) - { - return NULL; - } - - idisp->cairo.surface = cairo_image_surface_create_for_data( - surf->data, CAIRO_FORMAT_ARGB32, surf->width, surf->height, surf->stride); - - if(idisp->cairo.surface) - { - cairo_surface_set_device_scale(idisp->cairo.surface, surf->width, surf->height); - - idisp->cairo.ctx = cairo_create(idisp->cairo.surface); - if(idisp->cairo.ctx) - { - cairo_select_font_face(idisp->cairo.ctx, "cairo:monospace", - CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); - } - } - - return surf; -} - -static inline void -_lv2_canvas_idisp_surf_deinit(LV2_Canvas_Idisp *idisp) -{ - LV2_Inline_Display_Image_Surface *surf = &idisp->image_surface; - - if(idisp->cairo.ctx) - { - cairo_destroy(idisp->cairo.ctx); - idisp->cairo.ctx = NULL; - } - - if(idisp->cairo.surface) - { - cairo_surface_finish(idisp->cairo.surface); - cairo_surface_destroy(idisp->cairo.surface); - idisp->cairo.surface = NULL; - } - - if(surf->data) - { - free(surf->data); - surf->data = NULL; - } -} - -static inline LV2_Inline_Display_Image_Surface * +LV2_Inline_Display_Image_Surface * lv2_canvas_idisp_surf_configure(LV2_Canvas_Idisp *idisp, - uint32_t w, uint32_t h, float aspect_ratio) -{ - LV2_Inline_Display_Image_Surface *surf = &idisp->image_surface; - int W; - int H; - - if(aspect_ratio < 1.f) - { - W = h * aspect_ratio; - H = h; - } - else if(aspect_ratio > 1.f) - { - W = w; - H = w / aspect_ratio; - } - else // aspect_ratio == 1.f - { - W = w; - H = h; - } - - if( (surf->width != W) || (surf->height != H) || !surf->data) - { - _lv2_canvas_idisp_surf_deinit(idisp); - surf = _lv2_canvas_idisp_surf_init(idisp, W, H); - } - - return surf; -} + uint32_t w, uint32_t h, float aspect_ratio); -static inline void +int lv2_canvas_idisp_init(LV2_Canvas_Idisp *idisp, LV2_Inline_Display *queue_draw, - LV2_URID_Map *map) -{ - lv2_canvas_init(&idisp->canvas, map); - idisp->queue_draw = queue_draw; -} + LV2_URID_Map *map); -static inline void -lv2_canvas_idisp_deinit(LV2_Canvas_Idisp *idisp) -{ - _lv2_canvas_idisp_surf_deinit(idisp); -} +int +lv2_canvas_idisp_deinit(LV2_Canvas_Idisp *idisp); -static inline void -lv2_canvas_idisp_queue_draw(LV2_Canvas_Idisp *idisp) -{ - if(idisp->queue_draw) - { - idisp->queue_draw->queue_draw(idisp->queue_draw->handle); - } -} +int +lv2_canvas_idisp_queue_draw(LV2_Canvas_Idisp *idisp); -static inline bool +int lv2_canvas_idisp_render_body(LV2_Canvas_Idisp *idisp, uint32_t type, - uint32_t size, const LV2_Atom *body) -{ - return lv2_canvas_render_body(&idisp->canvas, idisp->cairo.ctx, - type, size, body); -} + uint32_t size, const LV2_Atom *body); #ifdef __cplusplus } diff --git a/meson.build b/meson.build index 82ab997..b033e51 100644 --- a/meson.build +++ b/meson.build @@ -15,6 +15,7 @@ reuse = find_program('reuse', required : false) add_project_arguments('-D_GNU_SOURCE', language : 'c') lv2_dep = dependency('lv2', version : '>=1.14.0') +cairo_dep = dependency('cairo', version : '>=1.16.0') lib_deps = [] lib_deps += lv2_dep @@ -24,18 +25,31 @@ lib_incs += include_directories('') lib_srcs = [] lib_srcs += join_paths('src', 'canvas.c') +lib_srcs += join_paths('src', 'forge.c') + +lib_cairo_deps = [] +lib_cairo_deps += cairo_dep + +lib_cairo_incs = [] +lib_cairo_src = join_paths('src', 'idisp.c') canvas_lv2 = declare_dependency( include_directories : lib_incs, dependencies : lib_deps, sources : lib_srcs) +canvas_idisp_lv2 = declare_dependency( + include_directories : lib_incs, + dependencies : [lib_deps, lib_cairo_deps], + sources : [lib_srcs, lib_cairo_src]) + test_args = [] test_args += '-fvisibility=hidden' test_args += '-ffast-math' test_deps = [] test_deps += canvas_lv2 +test_deps += canvas_idisp_lv2 test_srcs = [] test_srcs += join_paths('test', 'canvas.c') diff --git a/src/forge.c b/src/forge.c new file mode 100644 index 0000000..ad18b86 --- /dev/null +++ b/src/forge.c @@ -0,0 +1,301 @@ +/* + * SPDX-FileCopyrightText: Hanspeter Portner + * SPDX-License-Identifier: Artistic-2.0 + */ + +#include + +static inline LV2_Atom_Forge_Ref +_lv2_canvas_forge_simple(LV2_Atom_Forge *forge, LV2_URID otype) +{ + LV2_Atom_Forge_Ref ref; + LV2_Atom_Forge_Frame frame; + + ref = lv2_atom_forge_object(forge, &frame, 0, otype); + if(ref) + lv2_atom_forge_pop(forge, &frame); + + return ref; +} + +static inline LV2_Atom_Forge_Ref +_lv2_canvas_forge_vec(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, + LV2_URID otype, uint32_t n, const float *vec) +{ + LV2_Atom_Forge_Ref ref; + LV2_Atom_Forge_Frame frame; + + ref = lv2_atom_forge_object(forge, &frame, 0, otype); + if(ref) + ref = lv2_atom_forge_key(forge, urid->Canvas_body); + if(ref) + ref = lv2_atom_forge_vector(forge, sizeof(float), forge->Float, n, vec); + if(ref) + lv2_atom_forge_pop(forge, &frame); + + return ref; +} + +static inline LV2_Atom_Forge_Ref +_lv2_canvas_forge_flt(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, + LV2_URID otype, float flt) +{ + LV2_Atom_Forge_Ref ref; + LV2_Atom_Forge_Frame frame; + + ref = lv2_atom_forge_object(forge, &frame, 0, otype); + if(ref) + ref = lv2_atom_forge_key(forge, urid->Canvas_body); + if(ref) + ref = lv2_atom_forge_float(forge, flt); + if(ref) + lv2_atom_forge_pop(forge, &frame); + + return ref; +} + +static inline LV2_Atom_Forge_Ref +_lv2_canvas_forge_lng(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, + LV2_URID otype, int64_t lng) +{ + LV2_Atom_Forge_Ref ref; + LV2_Atom_Forge_Frame frame; + + ref = lv2_atom_forge_object(forge, &frame, 0, otype); + if(ref) + ref = lv2_atom_forge_key(forge, urid->Canvas_body); + if(ref) + ref = lv2_atom_forge_long(forge, lng); + if(ref) + lv2_atom_forge_pop(forge, &frame); + + return ref; +} + +static inline LV2_Atom_Forge_Ref +_lv2_canvas_forge_prp(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, + LV2_URID otype, LV2_URID prop) +{ + LV2_Atom_Forge_Ref ref; + LV2_Atom_Forge_Frame frame; + + ref = lv2_atom_forge_object(forge, &frame, 0, otype); + if(ref) + ref = lv2_atom_forge_key(forge, urid->Canvas_body); + if(ref) + ref = lv2_atom_forge_urid(forge, prop); + if(ref) + lv2_atom_forge_pop(forge, &frame); + + return ref; +} + +static inline LV2_Atom_Forge_Ref +_lv2_canvas_forge_str(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, + LV2_URID otype, const char *text) +{ + LV2_Atom_Forge_Ref ref; + LV2_Atom_Forge_Frame frame; + + ref = lv2_atom_forge_object(forge, &frame, 0, otype); + if(ref) + ref = lv2_atom_forge_key(forge, urid->Canvas_body); + if(ref) + ref = lv2_atom_forge_string(forge, text, strlen(text)); + if(ref) + lv2_atom_forge_pop(forge, &frame); + + return ref; +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_beginPath(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid) +{ + return _lv2_canvas_forge_simple(forge, urid->Canvas_BeginPath); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_closePath(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid) +{ + return _lv2_canvas_forge_simple(forge, urid->Canvas_ClosePath); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_arc(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, + float x, float y, float r, float a1, float a2) +{ + const float vec [5] = {x, y, r, a1, a2}; + + return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_Arc, 5, vec); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_curveTo(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, + float x1, float y1, float x2, float y2, float x3, float y3) +{ + const float vec [6] = {x1, y1, x2, y2, x3, y3}; + + return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_CurveTo, 6, vec); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_lineTo(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, + float x, float y) +{ + const float vec [2] = {x, y}; + + return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_LineTo, 2, vec); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_moveTo(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, + float x, float y) +{ + const float vec [2] = {x, y}; + + return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_MoveTo, 2, vec); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_rectangle(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, + float x, float y, float w, float h) +{ + const float vec [4] = {x, y, w, h}; + + return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_Rectangle, 4, vec); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_polyLine(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, + uint32_t n, const float *vec) +{ + return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_PolyLine, n, vec); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_style(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, + uint32_t style) +{ + return _lv2_canvas_forge_lng(forge, urid, urid->Canvas_Style, style); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_lineWidth(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, + float line_width) +{ + return _lv2_canvas_forge_flt(forge, urid, urid->Canvas_LineWidth, line_width); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_lineDash(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, + float dash_length, float separator_length) +{ + const float vec [2] = {dash_length, separator_length}; + + return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_LineDash, 2, vec); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_lineCap(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, + LV2_URID line_cap) +{ + return _lv2_canvas_forge_prp(forge, urid, urid->Canvas_LineCap, line_cap); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_lineJoin(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, + LV2_URID line_join) +{ + return _lv2_canvas_forge_prp(forge, urid, urid->Canvas_LineJoin, line_join); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_miterLimit(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, + float miter_limit) +{ + return _lv2_canvas_forge_flt(forge, urid, urid->Canvas_MiterLimit, miter_limit); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_stroke(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid) +{ + return _lv2_canvas_forge_simple(forge, urid->Canvas_Stroke); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_fill(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid) +{ + return _lv2_canvas_forge_simple(forge, urid->Canvas_Fill); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_clip(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid) +{ + return _lv2_canvas_forge_simple(forge, urid->Canvas_Clip); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_save(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid) +{ + return _lv2_canvas_forge_simple(forge, urid->Canvas_Save); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_restore(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid) +{ + return _lv2_canvas_forge_simple(forge, urid->Canvas_Restore); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_translate(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, + float x, float y) +{ + const float vec [2] = {x, y}; + + return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_Translate, 2, vec); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_scale(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, + float w, float h) +{ + const float vec [2] = {w, h}; + + return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_Scale, 2, vec); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_rotate(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, + float a) +{ + return _lv2_canvas_forge_flt(forge, urid, urid->Canvas_Rotate, a); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_transform(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, + float xx, float xy, float x0, float yy, float yx, float y0) +{ + const float vec [6] = {xx, xy, x0, yy, yx, y0}; + + return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_Transform, 6, vec); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_reset(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid) +{ + return _lv2_canvas_forge_simple(forge, urid->Canvas_Reset); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_fontSize(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, + float size) +{ + return _lv2_canvas_forge_flt(forge, urid, urid->Canvas_FontSize, size); +} + +LV2_Atom_Forge_Ref +lv2_canvas_forge_fillText(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid, + const char *text) +{ + return _lv2_canvas_forge_str(forge, urid, urid->Canvas_FillText, text); +} diff --git a/src/idisp.c b/src/idisp.c new file mode 100644 index 0000000..2c20c0c --- /dev/null +++ b/src/idisp.c @@ -0,0 +1,142 @@ +/* + * SPDX-FileCopyrightText: Hanspeter Portner + * SPDX-License-Identifier: Artistic-2.0 + */ + +#include + +#include + +static inline LV2_Inline_Display_Image_Surface * +_lv2_canvas_idisp_surf_init(LV2_Canvas_Idisp *idisp, int w, int h) +{ + LV2_Inline_Display_Image_Surface *surf = &idisp->image_surface; + + surf->width = w; + surf->height = h; + surf->stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, surf->width); + surf->data = realloc(surf->data, surf->stride * surf->height); + if(!surf->data) + { + return NULL; + } + + idisp->cairo.surface = cairo_image_surface_create_for_data( + surf->data, CAIRO_FORMAT_ARGB32, surf->width, surf->height, surf->stride); + + if(idisp->cairo.surface) + { + cairo_surface_set_device_scale(idisp->cairo.surface, surf->width, surf->height); + + idisp->cairo.ctx = cairo_create(idisp->cairo.surface); + if(idisp->cairo.ctx) + { + cairo_select_font_face(idisp->cairo.ctx, "cairo:monospace", + CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); + } + } + + return surf; +} + +static inline int +_lv2_canvas_idisp_surf_deinit(LV2_Canvas_Idisp *idisp) +{ + LV2_Inline_Display_Image_Surface *surf = &idisp->image_surface; + + if(idisp->cairo.ctx) + { + cairo_destroy(idisp->cairo.ctx); + idisp->cairo.ctx = NULL; + } + + if(idisp->cairo.surface) + { + cairo_surface_finish(idisp->cairo.surface); + cairo_surface_destroy(idisp->cairo.surface); + idisp->cairo.surface = NULL; + } + + if(surf->data) + { + free(surf->data); + surf->data = NULL; + } + + return 0; +} + +LV2_Inline_Display_Image_Surface * +lv2_canvas_idisp_surf_configure(LV2_Canvas_Idisp *idisp, + uint32_t w, uint32_t h, float aspect_ratio) +{ + LV2_Inline_Display_Image_Surface *surf = &idisp->image_surface; + int W; + int H; + + if(aspect_ratio < 1.f) + { + W = h * aspect_ratio; + H = h; + } + else if(aspect_ratio > 1.f) + { + W = w; + H = w / aspect_ratio; + } + else // aspect_ratio == 1.f + { + W = w; + H = h; + } + + if( (surf->width != W) || (surf->height != H) || !surf->data) + { + _lv2_canvas_idisp_surf_deinit(idisp); + surf = _lv2_canvas_idisp_surf_init(idisp, W, H); + } + + return surf; +} + +int +lv2_canvas_idisp_init(LV2_Canvas_Idisp *idisp, LV2_Inline_Display *queue_draw, + LV2_URID_Map *map) +{ + lv2_canvas_init(&idisp->canvas, map); + idisp->queue_draw = queue_draw; + + return 0; +} + +int +lv2_canvas_idisp_deinit(LV2_Canvas_Idisp *idisp) +{ + return _lv2_canvas_idisp_surf_deinit(idisp); +} + +int +lv2_canvas_idisp_queue_draw(LV2_Canvas_Idisp *idisp) +{ + if(!idisp->queue_draw || !idisp->queue_draw->queue_draw) + { + return 0; + } + + idisp->queue_draw->queue_draw(idisp->queue_draw->handle); + + return 0; +} + +int +lv2_canvas_idisp_render_body(LV2_Canvas_Idisp *idisp, uint32_t type, + uint32_t size, const LV2_Atom *body) +{ + if(!lv2_canvas_render_body(&idisp->canvas, idisp->cairo.ctx, + type, size, body)) + { + return 1; + } + + return 0; +} diff --git a/test/canvas.c b/test/canvas.c index 9dfa71c..75bacab 100644 --- a/test/canvas.c +++ b/test/canvas.c @@ -3,28 +3,223 @@ * SPDX-License-Identifier: Artistic-2.0 */ +#include #include #include +#include +#include -void -test_canvas_urid_init() +#define MAX_URIDS 128 + +typedef struct _urid_t urid_t; +typedef struct _handle_t handle_t; + +struct _urid_t { + LV2_URID urid; + char *uri; +}; + +struct _handle_t { + LV2_URID_Map map; + + urid_t urids [MAX_URIDS]; + LV2_URID urid; +}; + +static LV2_URID +_map(LV2_URID_Map_Handle instance, const char *uri) +{ + handle_t *handle = instance; + + urid_t *itm; + for(itm=handle->urids; itm->urid; itm++) + { + if(!strcmp(itm->uri, uri)) + { + return itm->urid; + } + } + + assert(handle->urid + 1 < MAX_URIDS); + + // create new + itm->urid = ++handle->urid; + itm->uri = strdup(uri); + + return itm->urid; +} + +static void +_map_free(handle_t *handle) +{ + for(unsigned i = 0; i < MAX_URIDS; i++) + { + urid_t *itm = &handle->urids[i]; + + if(itm->uri) + { + free(itm->uri); + } + + memset(itm, 0x0, sizeof(urid_t)); + } +} + +static void +test_canvas_urid_init(handle_t *handle) { static LV2_Canvas_URID urid; - static LV2_URID_Map map; + + LV2_URID_Map *map = &handle->map; assert(lv2_canvas_urid_init(NULL, NULL) == 1); assert(lv2_canvas_urid_init(&urid, NULL) == 1); - assert(lv2_canvas_urid_init(NULL, &map) == 1); - assert(lv2_canvas_urid_init(&urid, &map) == 1); + assert(lv2_canvas_urid_init(NULL, map) == 1); - //FIXME do some real tests + assert(lv2_canvas_urid_init(&urid, map) == 0); +} + +void +test_canvas_forge(handle_t *handle) +{ + static LV2_Canvas_URID urid; + + const float vec [3] = { + 1.f, 2.f, 3.f + }; + + LV2_URID_Map *map = &handle->map; + uint8_t buf [1024]; + + assert(lv2_canvas_urid_init(&urid, map) == 0); + LV2_Atom_Forge *forge = &(urid.forge); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_beginPath(forge, &urid) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_closePath(forge, &urid) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_arc(forge, &urid, 1.f, 2.f, 3.f, 4.f, 5.f) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_curveTo(forge, &urid, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_lineTo(forge, &urid, 1.f, 2.f) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_moveTo(forge, &urid, 1.f, 2.f) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_rectangle(forge, &urid, 1.f, 2.f, 3.f, 4.f) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_polyLine(forge, &urid, 3, vec) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_style(forge, &urid, 0xff0000ff) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_lineWidth(forge, &urid, 1.f) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_lineDash(forge, &urid, 1.f, 2.f) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_lineCap(forge, &urid, urid.Canvas_lineCapButt) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_lineJoin(forge, &urid, urid.Canvas_lineJoinMiter) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_miterLimit(forge, &urid, 1.f) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_stroke(forge, &urid) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_fill(forge, &urid) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_clip(forge, &urid) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_save(forge, &urid) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_restore(forge, &urid) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_translate(forge, &urid, 1.f, 2.f) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_scale(forge, &urid, 1.f, 2.f) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_rotate(forge, &urid, 1.f) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_transform(forge, &urid, 1.f, 2.f, 3.f, 4.f, 5.f, 6.f) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_reset(forge, &urid) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_fontSize(forge, &urid, 1.f) != 0); + + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_canvas_forge_fillText(forge, &urid, "foo") != 0); +} + +static void +test_canvas_idisp(handle_t *handle) +{ + static LV2_Canvas_URID urid; + static LV2_Canvas_Idisp idisp; + static LV2_Inline_Display queue_draw; + + LV2_URID_Map *map = &handle->map; + uint8_t buf [1024]; + + assert(lv2_canvas_urid_init(&urid, map) == 0); + LV2_Atom_Forge *forge = &(urid.forge); + + assert(lv2_canvas_idisp_init(&idisp, &queue_draw, map) == 0); + + LV2_Inline_Display_Image_Surface *surf = + lv2_canvas_idisp_surf_configure(&idisp, 64, 64, 1.f); + assert(surf); + + assert(lv2_canvas_idisp_queue_draw(&idisp) == 0); + + LV2_Atom_Forge_Frame frame; + lv2_atom_forge_set_buffer(forge, buf, sizeof(buf)); + assert(lv2_atom_forge_tuple(forge, &frame) != 0); + lv2_atom_forge_pop(forge, &frame); + + const LV2_Atom *atom = (const LV2_Atom *)buf; + assert(lv2_canvas_idisp_render_body(&idisp, atom->type, atom->size, + LV2_ATOM_BODY_CONST(atom)) == 0); + + assert(lv2_canvas_idisp_deinit(&idisp) == 0); } int main(int argc __attribute__((unused)), char **argv __attribute__((unused))) { - test_canvas_urid_init(); + static handle_t handle; + + handle.map.handle = &handle; + handle.map.map = _map; + + test_canvas_urid_init(&handle); + test_canvas_forge(&handle); + test_canvas_idisp(&handle); + + _map_free(&handle); return 0; } -- 2.38.5