aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Hanspeter Portner <dev@open-music-kontrollers.ch>2016-11-06 20:23:39 +0100
committerGravatar Hanspeter Portner <dev@open-music-kontrollers.ch>2016-11-06 20:23:39 +0100
commit3000bdcdbd3ad7c5aeb367fac467c73fee63ca80 (patch)
tree10f96e9822647a9156d0be6ed1c0cfbcb93b8cdf
parent0983862a4e2bfeedae06c82a22733effea55ae5b (diff)
downloadcanvas.lv2-3000bdcdbd3ad7c5aeb367fac467c73fee63ca80.zip
canvas.lv2-3000bdcdbd3ad7c5aeb367fac467c73fee63ca80.tar.gz
canvas.lv2-3000bdcdbd3ad7c5aeb367fac467c73fee63ca80.tar.bz2
canvas.lv2-3000bdcdbd3ad7c5aeb367fac467c73fee63ca80.tar.xz
finalize API.
-rw-r--r--CMakeLists.txt12
-rw-r--r--VERSION2
-rw-r--r--canvas.h1014
-rw-r--r--canvas.lv2/canvas.h156
-rw-r--r--canvas.lv2/forge.h318
-rw-r--r--canvas.lv2/render.h529
-rw-r--r--test/canvas.c (renamed from canvas.c)113
-rw-r--r--test/canvas.ttl (renamed from canvas.ttl)8
-rw-r--r--test/canvas_ui.c (renamed from canvas_ui.c)111
-rw-r--r--test/canvas_ui.ttl (renamed from canvas_ui.ttl)6
-rw-r--r--test/manifest.ttl.in (renamed from manifest.ttl.in)0
11 files changed, 1158 insertions, 1111 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 89a78f3..b785aba 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -50,7 +50,7 @@ find_package(PkgConfig) # ${PKG_CONFIG_FOUND}
set(LIBS m)
set(LIBS_UI m)
-set(TAR_UI canvas_ui.c)
+set(TAR_UI test/canvas_ui.c)
pkg_search_module(LV2 REQUIRED lv2>=1.10)
include_directories(${LV2_INCLUDE_DIRS})
@@ -118,9 +118,10 @@ else() # GNU/Linux
set(TAR_UI ${TAR_UI} pugl/pugl/pugl_x11.c)
endif()
-add_library(canvas MODULE canvas.c)
+add_library(canvas MODULE test/canvas.c)
target_link_libraries(canvas ${LIBS})
set_target_properties(canvas PROPERTIES PREFIX "")
+set_target_properties(canvas PROPERTIES INTERPROCEDURAL_OPTIMIZATION true) # -flto
if(NOT WIN32)
set_target_properties(canvas PROPERTIES LINK_FLAGS "-Wl,-e,lv2_descriptor")
endif()
@@ -129,12 +130,13 @@ install(TARGETS canvas DESTINATION ${PLUGIN_DEST})
add_library(canvas_ui MODULE ${TAR_UI})
target_link_libraries(canvas_ui ${LIBS_UI})
set_target_properties(canvas_ui PROPERTIES PREFIX "")
+set_target_properties(canvas_ui PROPERTIES INTERPROCEDURAL_OPTIMIZATION true) # -flto
if(NOT WIN32)
set_target_properties(canvas_ui PROPERTIES LINK_FLAGS "-Wl,-e,lv2ui_descriptor")
endif()
install(TARGETS canvas_ui DESTINATION ${PLUGIN_DEST})
-configure_file(${PROJECT_SOURCE_DIR}/manifest.ttl.in ${PROJECT_BINARY_DIR}/manifest.ttl)
+configure_file(${PROJECT_SOURCE_DIR}/test/manifest.ttl.in ${PROJECT_BINARY_DIR}/manifest.ttl)
install(FILES ${PROJECT_BINARY_DIR}/manifest.ttl DESTINATION ${PLUGIN_DEST})
-install(FILES ${PROJECT_SOURCE_DIR}/canvas.ttl DESTINATION ${PLUGIN_DEST})
-install(FILES ${PROJECT_SOURCE_DIR}/canvas_ui.ttl DESTINATION ${PLUGIN_DEST})
+install(FILES ${PROJECT_SOURCE_DIR}/test/canvas.ttl DESTINATION ${PLUGIN_DEST})
+install(FILES ${PROJECT_SOURCE_DIR}/test/canvas_ui.ttl DESTINATION ${PLUGIN_DEST})
diff --git a/VERSION b/VERSION
index 2bfbb8b..75ed58c 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.1.303
+0.1.305
diff --git a/canvas.h b/canvas.h
deleted file mode 100644
index 4c196ab..0000000
--- a/canvas.h
+++ /dev/null
@@ -1,1014 +0,0 @@
-/*
- * Copyright (c) 2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
- *
- * This is free software: you can redistribute it and/or modify
- * it under the terms of the Artistic License 2.0 as published by
- * The Perl Foundation.
- *
- * This source is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * Artistic License 2.0 for more details.
- *
- * You should have received a copy of the Artistic License 2.0
- * along the source as a COPYING file. If not, obtain it from
- * http://www.perlfoundation.org/artistic_license_2_0.
- */
-
-#ifndef _CANVAS_LV2_H
-#define _CANVAS_LV2_H
-
-#include "lv2/lv2plug.in/ns/ext/atom/atom.h"
-#include "lv2/lv2plug.in/ns/ext/atom/forge.h"
-#include "lv2/lv2plug.in/ns/ext/log/log.h"
-#include "lv2/lv2plug.in/ns/ext/log/logger.h"
-#include "lv2/lv2plug.in/ns/ext/patch/patch.h"
-#include "lv2/lv2plug.in/ns/extensions/ui/ui.h"
-#include "lv2/lv2plug.in/ns/lv2core/lv2.h"
-
-#include <cairo.h>
-
-#define CANVAS_URI "http://open-music-kontrollers.ch/lv2/canvas"
-#define CANVAS_PREFIX CANVAS_URI"#"
-
-#define CANVAS__graph CANVAS_PREFIX"graph"
-#define CANVAS__body CANVAS_PREFIX"body"
-
-#define CANVAS__BeginPath CANVAS_PREFIX"BeginPath"
-#define CANVAS__ClosePath CANVAS_PREFIX"ClosePath"
-#define CANVAS__Arc CANVAS_PREFIX"Arc"
-#define CANVAS__CurveTo CANVAS_PREFIX"CurveTo"
-#define CANVAS__LineTo CANVAS_PREFIX"LineTo"
-#define CANVAS__MoveTo CANVAS_PREFIX"MoveTo"
-#define CANVAS__Rectangle CANVAS_PREFIX"Rectangle"
-#define CANVAS__Style CANVAS_PREFIX"Style"
-#define CANVAS__LineWidth CANVAS_PREFIX"LineWidth"
-#define CANVAS__LineDash CANVAS_PREFIX"LineDash"
-#define CANVAS__LineCap CANVAS_PREFIX"LineCap"
-#define CANVAS__LineJoin CANVAS_PREFIX"LineJoin"
-#define CANVAS__MiterLimit CANVAS_PREFIX"MiterLimig"
-#define CANVAS__Stroke CANVAS_PREFIX"Stroke"
-#define CANVAS__Fill CANVAS_PREFIX"Fill"
-#define CANVAS__Clip CANVAS_PREFIX"Clip"
-#define CANVAS__Save CANVAS_PREFIX"Save"
-#define CANVAS__Restore CANVAS_PREFIX"Restore"
-#define CANVAS__Translate CANVAS_PREFIX"Translate"
-#define CANVAS__Scale CANVAS_PREFIX"Scale"
-#define CANVAS__Rotate CANVAS_PREFIX"Rotate"
-#define CANVAS__Reset CANVAS_PREFIX"Reset"
-#define CANVAS__FontSize CANVAS_PREFIX"FontSize"
-#define CANVAS__FillText CANVAS_PREFIX"FillText"
-
-#define CANVAS__lineCapButt CANVAS_PREFIX"lineCapButt"
-#define CANVAS__lineCapRound CANVAS_PREFIX"lineCapRound"
-#define CANVAS__lineCapSquare CANVAS_PREFIX"lineCapSquare"
-
-#define CANVAS__lineJoinMiter CANVAS_PREFIX"lineJoinMiter"
-#define CANVAS__lineJoinRound CANVAS_PREFIX"lineJoinRound"
-#define CANVAS__lineJoinBevel CANVAS_PREFIX"lineJoinBevel"
-
-#define CANVAS_NUM_METHODS 24
-
-typedef struct _LV2_Canvas_URID LV2_Canvas_URID;
-typedef struct _LV2_Canvas_Meth LV2_Canvas_Meth;
-typedef struct _LV2_Canvas LV2_Canvas;
-typedef void (*LV2_Canvas_Func)(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body);
-
-struct _LV2_Canvas_URID {
- LV2_URID Canvas_graph;
- LV2_URID Canvas_body;
-
- LV2_URID Canvas_BeginPath;
- LV2_URID Canvas_ClosePath;
- LV2_URID Canvas_Arc;
- LV2_URID Canvas_CurveTo;
- LV2_URID Canvas_LineTo;
- LV2_URID Canvas_MoveTo;
- LV2_URID Canvas_Rectangle;
- LV2_URID Canvas_Style;
- LV2_URID Canvas_LineWidth;
- LV2_URID Canvas_LineDash;
- LV2_URID Canvas_LineCap;
- LV2_URID Canvas_LineJoin;
- LV2_URID Canvas_MiterLimit;
- LV2_URID Canvas_Stroke;
- LV2_URID Canvas_Fill;
- LV2_URID Canvas_Clip;
- LV2_URID Canvas_Save;
- LV2_URID Canvas_Restore;
- LV2_URID Canvas_Translate;
- LV2_URID Canvas_Scale;
- LV2_URID Canvas_Rotate;
- LV2_URID Canvas_Reset;
- LV2_URID Canvas_FontSize;
- LV2_URID Canvas_FillText;
-
- LV2_URID Canvas_lineCapButt;
- LV2_URID Canvas_lineCapRound;
- LV2_URID Canvas_lineCapSquare;
-
- LV2_URID Canvas_lineJoinMiter;
- LV2_URID Canvas_lineJoinRound;
- LV2_URID Canvas_lineJoinBevel;
-};
-
-struct _LV2_Canvas_Meth {
- LV2_URID command;
- LV2_Canvas_Func func;
-};
-
-struct _LV2_Canvas {
- LV2_Canvas_URID urid;
- LV2_Canvas_Meth methods [CANVAS_NUM_METHODS];
-};
-
-static inline const float *
-_lv2_canvas_get_float_vec(LV2_Atom_Forge *forge, const LV2_Atom *body, uint32_t N)
-{
- const LV2_Atom_Vector *vec = (const LV2_Atom_Vector *)body;
- const float *flt = LV2_ATOM_CONTENTS_CONST(LV2_Atom_Vector, vec);
- const uint32_t n = (vec->atom.type == forge->Vector)
- && (vec->body.child_type == forge->Float)
- ? (vec->atom.size - sizeof(LV2_Atom_Vector_Body)) / vec->body.child_size
- : 0;
-
- return n == N ? flt : NULL;
-}
-
-static inline const void *
-_lv2_canvas_get_type(const LV2_Atom *body, LV2_URID type)
-{
- const float *flt = &((const LV2_Atom_Float *)body)->body;
-
- return body->type == type ? LV2_ATOM_BODY_CONST(body) : NULL;
-}
-
-static inline void
-lv2_canvas_render_beginPath(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- cairo_new_sub_path(ctx);
-}
-
-static inline void
-lv2_canvas_render_closePath(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- cairo_close_path(ctx);
-}
-
-static inline void
-lv2_canvas_render_arc(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- const float *v = _lv2_canvas_get_float_vec(forge, body, 5);
-
- if(v)
- cairo_arc(ctx, v[0], v[1], v[2], v[3], v[4]);
-}
-
-static inline void
-lv2_canvas_render_curveTo(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- const float *v = _lv2_canvas_get_float_vec(forge, body, 6);
-
- if(v)
- cairo_curve_to(ctx, v[0], v[1], v[2], v[3], v[4], v[5]);
-}
-
-static inline void
-lv2_canvas_render_lineTo(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- const float *v = _lv2_canvas_get_float_vec(forge, body, 2);
-
- if(v)
- cairo_line_to(ctx, v[0], v[1]);
-}
-
-static inline void
-lv2_canvas_render_moveTo(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- const float *v = _lv2_canvas_get_float_vec(forge, body, 2);
-
- if(v)
- cairo_move_to(ctx, v[0], v[1]);
-}
-
-static inline void
-lv2_canvas_render_rectangle(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- const float *v = _lv2_canvas_get_float_vec(forge, body, 4);
-
- if(v)
- cairo_rectangle(ctx, v[0], v[1], v[2], v[3]);
-}
-
-static inline void
-lv2_canvas_render_style(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- const int64_t *v = _lv2_canvas_get_type(body, forge->Long);
-
- if(v)
- cairo_set_source_rgba(ctx,
- (float)((*v >> 16) & 0xff) / 0xff,
- (float)((*v >> 8) & 0xff) / 0xff,
- (float)((*v >> 0) & 0xff) / 0xff,
- (float)((*v >> 24) & 0xff) / 0xff);
-}
-
-static inline void
-lv2_canvas_render_lineWidth(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- const float *v = _lv2_canvas_get_type(body, forge->Float);
-
- if(v)
- cairo_set_line_width(ctx, *v);
-}
-
-static inline void
-lv2_canvas_render_lineDash(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- const float *v = _lv2_canvas_get_float_vec(forge, body, 2);
-
- if(v)
- cairo_set_dash(ctx, (const double [2]){v[0], v[1]}, 2, 0);
-}
-
-static inline void
-lv2_canvas_render_lineCap(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- const LV2_URID *v = _lv2_canvas_get_type(body, forge->URID);
-
- if(v)
- {
- cairo_line_cap_t cap = CAIRO_LINE_CAP_BUTT;
- if(*v == urid->Canvas_lineCapButt)
- cap = CAIRO_LINE_CAP_BUTT;
- else if(*v == urid->Canvas_lineCapRound)
- cap = CAIRO_LINE_CAP_ROUND;
- else if(*v == urid->Canvas_lineCapRound)
- cap = CAIRO_LINE_CAP_SQUARE;
- cairo_set_line_cap(ctx, cap);
- }
-}
-
-static inline void
-lv2_canvas_render_lineJoin(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- const LV2_URID *v = _lv2_canvas_get_type(body, forge->URID);
-
- if(v)
- {
- cairo_line_join_t join = CAIRO_LINE_JOIN_MITER;
- if(*v == urid->Canvas_lineJoinMiter)
- join = CAIRO_LINE_JOIN_MITER;
- else if(*v == urid->Canvas_lineJoinRound)
- join = CAIRO_LINE_JOIN_ROUND;
- else if(*v == urid->Canvas_lineJoinBevel)
- join = CAIRO_LINE_JOIN_BEVEL;
- cairo_set_line_join(ctx, join);
- }
-}
-
-static inline void
-lv2_canvas_render_miterLimit(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- const float *v = _lv2_canvas_get_type(body, forge->Float);
-
- if(v)
- cairo_set_miter_limit(ctx, *v);
-}
-
-static inline void
-lv2_canvas_render_stroke(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- cairo_stroke(ctx);
-}
-
-static inline void
-lv2_canvas_render_fill(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- cairo_fill(ctx);
-}
-
-static inline void
-lv2_canvas_render_clip(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- cairo_clip(ctx);
-}
-
-static inline void
-lv2_canvas_render_save(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- cairo_save(ctx);
-}
-
-static inline void
-lv2_canvas_render_restore(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- cairo_restore(ctx);
-}
-
-static inline void
-lv2_canvas_render_translate(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- const float *v = _lv2_canvas_get_float_vec(forge, body, 2);
-
- if(v)
- cairo_translate(ctx, v[0], v[1]);
-}
-
-static inline void
-lv2_canvas_render_scale(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- const float *v = _lv2_canvas_get_float_vec(forge, body, 2);
-
- if(v)
- cairo_scale(ctx, v[0], v[1]);
-}
-
-static inline void
-lv2_canvas_render_rotate(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- const float *v = _lv2_canvas_get_type(body, forge->Float);
-
- if(v)
- cairo_rotate(ctx, *v);
-}
-
-static inline void
-lv2_canvas_render_reset(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- cairo_identity_matrix(ctx);
-}
-
-static inline void
-lv2_canvas_render_fontSize(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- const float *v = _lv2_canvas_get_type(body, forge->Float);
-
- if(v)
- cairo_set_font_size(ctx, *v);
-}
-
-static inline void
-lv2_canvas_render_fillText(cairo_t *ctx, LV2_Atom_Forge *forge,
- LV2_Canvas_URID *urid, const LV2_Atom *body)
-{
- const char *v = _lv2_canvas_get_type(body, forge->String);
-
- if(v)
- {
- cairo_text_extents_t extents;
- cairo_text_extents (ctx, v, &extents);
- const float dx = (extents.width/2 + extents.x_bearing);
- const float dy = (extents.height/2 + extents.y_bearing);
- cairo_rel_move_to(ctx, -dx, -dy);
- cairo_show_text(ctx, v);
- }
-}
-
-static inline void
-lv2_canvas_urid_init(LV2_Canvas_URID *urid, LV2_URID_Map *map)
-{
- urid->Canvas_graph = map->map(map->handle, CANVAS__graph);
- urid->Canvas_body = map->map(map->handle, CANVAS__body);
-
- urid->Canvas_BeginPath = map->map(map->handle, CANVAS__BeginPath);
- urid->Canvas_ClosePath = map->map(map->handle, CANVAS__ClosePath);
- urid->Canvas_Arc = map->map(map->handle, CANVAS__Arc);
- urid->Canvas_CurveTo = map->map(map->handle, CANVAS__CurveTo);
- urid->Canvas_LineTo = map->map(map->handle, CANVAS__LineTo);
- urid->Canvas_MoveTo = map->map(map->handle, CANVAS__MoveTo);
- urid->Canvas_Rectangle = map->map(map->handle, CANVAS__Rectangle);
- urid->Canvas_Style = map->map(map->handle, CANVAS__Style);
- urid->Canvas_LineWidth = map->map(map->handle, CANVAS__LineWidth);
- urid->Canvas_LineDash = map->map(map->handle, CANVAS__LineDash);
- urid->Canvas_LineCap = map->map(map->handle, CANVAS__LineCap);
- urid->Canvas_LineJoin = map->map(map->handle, CANVAS__LineJoin);
- urid->Canvas_MiterLimit = map->map(map->handle, CANVAS__MiterLimit);
- urid->Canvas_Stroke = map->map(map->handle, CANVAS__Stroke);
- urid->Canvas_Fill = map->map(map->handle, CANVAS__Fill);
- urid->Canvas_Clip = map->map(map->handle, CANVAS__Clip);
- urid->Canvas_Save = map->map(map->handle, CANVAS__Save);
- urid->Canvas_Restore = map->map(map->handle, CANVAS__Restore);
- urid->Canvas_Translate = map->map(map->handle, CANVAS__Translate);
- urid->Canvas_Scale = map->map(map->handle, CANVAS__Scale);
- urid->Canvas_Rotate = map->map(map->handle, CANVAS__Rotate);
- urid->Canvas_Reset = map->map(map->handle, CANVAS__Reset);
- urid->Canvas_FontSize = map->map(map->handle, CANVAS__FontSize);
- urid->Canvas_FillText = map->map(map->handle, CANVAS__FillText);
-
- urid->Canvas_lineCapButt = map->map(map->handle, CANVAS__lineCapButt);
- urid->Canvas_lineCapRound = map->map(map->handle, CANVAS__lineCapRound);
- urid->Canvas_lineCapSquare = map->map(map->handle, CANVAS__lineCapSquare);
-
- urid->Canvas_lineJoinMiter = map->map(map->handle, CANVAS__lineJoinMiter);
- urid->Canvas_lineJoinRound = map->map(map->handle, CANVAS__lineJoinRound);
- urid->Canvas_lineJoinBevel = map->map(map->handle, CANVAS__lineJoinBevel);
-}
-
-static inline void
-_lv2_canvas_qsort(LV2_Canvas_Meth *a, unsigned n)
-{
- if(n < 2)
- return;
-
- const LV2_Canvas_Meth *p = &a[n/2];
-
- unsigned i, j;
- for(i=0, j=n-1; ; i++, j--)
- {
- while(a[i].command < p->command)
- i++;
-
- while(p->command < a[j].command)
- j--;
-
- if(i >= j)
- break;
-
- const LV2_Canvas_Meth t = a[i];
- a[i] = a[j];
- a[j] = t;
- }
-
- _lv2_canvas_qsort(a, i);
- _lv2_canvas_qsort(&a[i], n - i);
-}
-
-static inline LV2_Canvas_Meth *
-_lv2_canvas_bsearch(LV2_URID p, LV2_Canvas_Meth *a, unsigned n)
-{
- LV2_Canvas_Meth *base = a;
-
- for(unsigned N = n, half; N > 1; N -= half)
- {
- half = N/2;
- LV2_Canvas_Meth *dst = &base[half];
- base = (dst->command > p) ? base : dst;
- }
-
- return (base->command == p) ? base : NULL;
-}
-
-static inline void
-lv2_canvas_init(LV2_Canvas *canvas, LV2_URID_Map *map)
-{
- lv2_canvas_urid_init(&canvas->urid, map);
-
- unsigned ptr = 0;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_BeginPath;
- canvas->methods[ptr++].func = lv2_canvas_render_beginPath;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_ClosePath;
- canvas->methods[ptr++].func = lv2_canvas_render_closePath;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_Arc;
- canvas->methods[ptr++].func = lv2_canvas_render_arc;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_CurveTo;
- canvas->methods[ptr++].func = lv2_canvas_render_curveTo;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_LineTo;
- canvas->methods[ptr++].func = lv2_canvas_render_lineTo;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_MoveTo;
- canvas->methods[ptr++].func = lv2_canvas_render_moveTo;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_Rectangle;
- canvas->methods[ptr++].func = lv2_canvas_render_rectangle;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_Style;
- canvas->methods[ptr++].func = lv2_canvas_render_style;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_LineWidth;
- canvas->methods[ptr++].func = lv2_canvas_render_lineWidth;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_LineDash;
- canvas->methods[ptr++].func = lv2_canvas_render_lineDash;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_LineCap;
- canvas->methods[ptr++].func = lv2_canvas_render_lineCap;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_LineJoin;
- canvas->methods[ptr++].func = lv2_canvas_render_lineJoin;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_MiterLimit;
- canvas->methods[ptr++].func = lv2_canvas_render_miterLimit;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_Stroke;
- canvas->methods[ptr++].func = lv2_canvas_render_stroke;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_Fill;
- canvas->methods[ptr++].func = lv2_canvas_render_fill;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_Clip;
- canvas->methods[ptr++].func = lv2_canvas_render_clip;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_Save;
- canvas->methods[ptr++].func = lv2_canvas_render_save;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_Restore;
- canvas->methods[ptr++].func = lv2_canvas_render_restore;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_Translate;
- canvas->methods[ptr++].func = lv2_canvas_render_translate;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_Scale;
- canvas->methods[ptr++].func = lv2_canvas_render_scale;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_Rotate;
- canvas->methods[ptr++].func = lv2_canvas_render_rotate;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_Reset;
- canvas->methods[ptr++].func = lv2_canvas_render_reset;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_FontSize;
- canvas->methods[ptr++].func = lv2_canvas_render_fontSize;
-
- canvas->methods[ptr].command = canvas->urid.Canvas_FillText;
- canvas->methods[ptr++].func = lv2_canvas_render_fillText;
-
- assert(ptr == CANVAS_NUM_METHODS);
-
- _lv2_canvas_qsort(canvas->methods, CANVAS_NUM_METHODS);
-}
-
-static inline bool
-lv2_canvas_render(LV2_Canvas *canvas, cairo_t *ctx, LV2_Atom_Forge *forge,
- const LV2_Atom_Tuple *tup)
-{
- if(!tup)
- return false;
-
- // save state
- cairo_save(ctx);
-
- // clear surface
- cairo_set_operator(ctx, CAIRO_OPERATOR_CLEAR);
- cairo_paint(ctx);
-
- // default attributes
- cairo_set_operator(ctx, CAIRO_OPERATOR_SOURCE);
- cairo_set_font_size(ctx, 0.1);
- cairo_set_line_width(ctx, 0.01);
- cairo_set_source_rgba(ctx, 1.0, 1.0, 1.0, 1.0);
-
- LV2_ATOM_TUPLE_FOREACH(tup, itm)
- {
- if(!lv2_atom_forge_is_object_type(forge, itm->type))
- continue;
-
- const LV2_Atom_Object *obj = (const LV2_Atom_Object *)itm;
- const LV2_Atom *body = NULL;
-
- lv2_atom_object_get(obj, canvas->urid.Canvas_body, &body, 0);
- LV2_Canvas_Meth *meth = _lv2_canvas_bsearch(obj->body.otype,
- canvas->methods, CANVAS_NUM_METHODS);
-
- if(meth)
- meth->func(ctx, forge, &canvas->urid, body);
- }
-
- // save state
- cairo_restore(ctx);
-
- // flush
- cairo_surface_t *surface = cairo_get_target(ctx);
- cairo_surface_flush(surface);
-
- return true;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_beginPath(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_BeginPath);
- if(ref)
- lv2_atom_forge_pop(forge, &frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_closePath(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_ClosePath);
- if(ref)
- lv2_atom_forge_pop(forge, &frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_arc(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
- float x, float y, float r, float a1, float a2)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- const float vec [5] = {x, y, r, a1, a2};
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_Arc);
- if(ref)
- ref = lv2_atom_forge_key(forge, urid->Canvas_body);
- if(ref)
- ref = lv2_atom_forge_vector(forge, sizeof(float), forge->Float, 5, vec);
- if(ref)
- lv2_atom_forge_pop(forge, &frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_curveTo(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
- float x1, float y1, float x2, float y2, float x3, float y3)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- const float vec [6] = {x1, y1, x2, y2, x3, y3};
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_CurveTo);
- if(ref)
- ref = lv2_atom_forge_key(forge, urid->Canvas_body);
- if(ref)
- ref = lv2_atom_forge_vector(forge, sizeof(float), forge->Float, 6, vec);
- if(ref)
- lv2_atom_forge_pop(forge, &frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_lineTo(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
- float x, float y)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- const float vec [2] = {x, y};
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_LineTo);
- if(ref)
- ref = lv2_atom_forge_key(forge, urid->Canvas_body);
- if(ref)
- ref = lv2_atom_forge_vector(forge, sizeof(float), forge->Float, 2, vec);
- if(ref)
- lv2_atom_forge_pop(forge, &frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_moveTo(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
- float x, float y)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- const float vec [2] = {x, y};
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_MoveTo);
- if(ref)
- ref = lv2_atom_forge_key(forge, urid->Canvas_body);
- if(ref)
- ref = lv2_atom_forge_vector(forge, sizeof(float), forge->Float, 2, vec);
- if(ref)
- lv2_atom_forge_pop(forge, &frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_rectangle(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
- float x, float y, float w, float h)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- const float vec [4] = {x, y, w, h};
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_Rectangle);
- if(ref)
- ref = lv2_atom_forge_key(forge, urid->Canvas_body);
- if(ref)
- ref = lv2_atom_forge_vector(forge, sizeof(float), forge->Float, 4, vec);
- if(ref)
- lv2_atom_forge_pop(forge, &frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_style(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
- uint32_t style)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_Style);
- if(ref)
- ref = lv2_atom_forge_key(forge, urid->Canvas_body);
- if(ref)
- ref = lv2_atom_forge_long(forge, style);
- if(ref)
- lv2_atom_forge_pop(forge, &frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_lineWidth(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
- float line_width)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_LineWidth);
- if(ref)
- ref = lv2_atom_forge_key(forge, urid->Canvas_body);
- if(ref)
- ref = lv2_atom_forge_long(forge, line_width);
- if(ref)
- lv2_atom_forge_pop(forge, &frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_lineDash(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
- float dash_length, float separator_length)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- const float vec [2] = {dash_length, separator_length};
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_LineDash);
- if(ref)
- ref = lv2_atom_forge_key(forge, urid->Canvas_body);
- if(ref)
- ref = lv2_atom_forge_vector(forge, sizeof(float), forge->Float, 2, vec);
- if(ref)
- lv2_atom_forge_pop(forge, &frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_lineCap(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
- LV2_URID line_cap)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_LineCap);
- if(ref)
- ref = lv2_atom_forge_key(forge, urid->Canvas_body);
- if(ref)
- ref = lv2_atom_forge_urid(forge, line_cap);
- if(ref)
- lv2_atom_forge_pop(forge, &frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_lineJoin(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
- LV2_URID line_join)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_LineJoin);
- if(ref)
- ref = lv2_atom_forge_key(forge, urid->Canvas_body);
- if(ref)
- ref = lv2_atom_forge_urid(forge, line_join);
- if(ref)
- lv2_atom_forge_pop(forge, &frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_miterLimit(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
- float miter_limit)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_MiterLimit);
- if(ref)
- ref = lv2_atom_forge_key(forge, urid->Canvas_body);
- if(ref)
- ref = lv2_atom_forge_float(forge, miter_limit);
- if(ref)
- lv2_atom_forge_pop(forge, &frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_stroke(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_Stroke);
- if(ref)
- lv2_atom_forge_pop(forge, &frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_fill(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_Fill);
- if(ref)
- lv2_atom_forge_pop(forge, &frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_clip(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_Clip);
- if(ref)
- lv2_atom_forge_pop(forge, &frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_save(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_Save);
- if(ref)
- lv2_atom_forge_pop(forge, &frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_restore(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_Restore);
- if(ref)
- lv2_atom_forge_pop(forge, &frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_translate(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
- float x, float y)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- const float vec [2] = {x, y};
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_Translate);
- if(ref)
- ref = lv2_atom_forge_key(forge, urid->Canvas_body);
- if(ref)
- ref = lv2_atom_forge_vector(forge, sizeof(float), forge->Float, 2, vec);
- if(ref)
- lv2_atom_forge_pop(forge, &frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_scale(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
- float w, float h)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- const float vec [2] = {w, h};
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_Scale);
- if(ref)
- ref = lv2_atom_forge_key(forge, urid->Canvas_body);
- if(ref)
- ref = lv2_atom_forge_vector(forge, sizeof(float), forge->Float, 2, vec);
- if(ref)
- lv2_atom_forge_pop(forge, &frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_rotate(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
- float a)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_Scale);
- if(ref)
- ref = lv2_atom_forge_key(forge, urid->Canvas_body);
- if(ref)
- ref = lv2_atom_forge_float(forge, a);
- if(ref)
- lv2_atom_forge_pop(forge, &frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_reset(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_Reset);
- if(ref)
- lv2_atom_forge_pop(forge, &frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_fontSize(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
- float size)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_FontSize);
- if(ref)
- ref = lv2_atom_forge_key(forge, urid->Canvas_body);
- if(ref)
- ref = lv2_atom_forge_float(forge, size);
- if(ref)
- lv2_atom_forge_pop(forge, &frame);
-
- return ref;
-}
-
-static inline LV2_Atom_Forge_Ref
-lv2_canvas_fillText(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
- const char *text)
-{
- LV2_Atom_Forge_Ref ref;
- LV2_Atom_Forge_Frame frame;
-
- ref = lv2_atom_forge_object(forge, &frame, 0, urid->Canvas_FillText);
- 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;
-}
-
-#endif // _CANVAS_LV2_H
diff --git a/canvas.lv2/canvas.h b/canvas.lv2/canvas.h
new file mode 100644
index 0000000..40c1b6a
--- /dev/null
+++ b/canvas.lv2/canvas.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
+ *
+ * This is free software: you can redistribute it and/or modify
+ * it under the terms of the Artistic License 2.0 as published by
+ * The Perl Foundation.
+ *
+ * This source is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Artistic License 2.0 for more details.
+ *
+ * You should have received a copy of the Artistic License 2.0
+ * along the source as a COPYING file. If not, obtain it from
+ * http://www.perlfoundation.org/artistic_license_2_0.
+ */
+
+#ifndef _LV2_CANVAS_H
+#define _LV2_CANVAS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <lv2/lv2plug.in/ns/lv2core/lv2.h>
+#include <lv2/lv2plug.in/ns/ext/atom/atom.h>
+#include <lv2/lv2plug.in/ns/ext/atom/forge.h>
+
+#define CANVAS_URI "http://open-music-kontrollers.ch/lv2/canvas"
+#define CANVAS_PREFIX CANVAS_URI"#"
+
+#define CANVAS__graph CANVAS_PREFIX"graph"
+#define CANVAS__body CANVAS_PREFIX"body"
+
+#define CANVAS__BeginPath CANVAS_PREFIX"BeginPath"
+#define CANVAS__ClosePath CANVAS_PREFIX"ClosePath"
+#define CANVAS__Arc CANVAS_PREFIX"Arc"
+#define CANVAS__CurveTo CANVAS_PREFIX"CurveTo"
+#define CANVAS__LineTo CANVAS_PREFIX"LineTo"
+#define CANVAS__MoveTo CANVAS_PREFIX"MoveTo"
+#define CANVAS__Rectangle CANVAS_PREFIX"Rectangle"
+#define CANVAS__Style CANVAS_PREFIX"Style"
+#define CANVAS__LineWidth CANVAS_PREFIX"LineWidth"
+#define CANVAS__LineDash CANVAS_PREFIX"LineDash"
+#define CANVAS__LineCap CANVAS_PREFIX"LineCap"
+#define CANVAS__LineJoin CANVAS_PREFIX"LineJoin"
+#define CANVAS__MiterLimit CANVAS_PREFIX"MiterLimig"
+#define CANVAS__Stroke CANVAS_PREFIX"Stroke"
+#define CANVAS__Fill CANVAS_PREFIX"Fill"
+#define CANVAS__Clip CANVAS_PREFIX"Clip"
+#define CANVAS__Save CANVAS_PREFIX"Save"
+#define CANVAS__Restore CANVAS_PREFIX"Restore"
+#define CANVAS__Translate CANVAS_PREFIX"Translate"
+#define CANVAS__Scale CANVAS_PREFIX"Scale"
+#define CANVAS__Rotate CANVAS_PREFIX"Rotate"
+#define CANVAS__Reset CANVAS_PREFIX"Reset"
+#define CANVAS__FontSize CANVAS_PREFIX"FontSize"
+#define CANVAS__FillText CANVAS_PREFIX"FillText"
+
+#define CANVAS__lineCapButt CANVAS_PREFIX"lineCapButt"
+#define CANVAS__lineCapRound CANVAS_PREFIX"lineCapRound"
+#define CANVAS__lineCapSquare CANVAS_PREFIX"lineCapSquare"
+
+#define CANVAS__lineJoinMiter CANVAS_PREFIX"lineJoinMiter"
+#define CANVAS__lineJoinRound CANVAS_PREFIX"lineJoinRound"
+#define CANVAS__lineJoinBevel CANVAS_PREFIX"lineJoinBevel"
+
+typedef struct _LV2_Canvas_URID LV2_Canvas_URID;
+
+struct _LV2_Canvas_URID {
+ LV2_URID Canvas_graph;
+ LV2_URID Canvas_body;
+
+ LV2_URID Canvas_BeginPath;
+ LV2_URID Canvas_ClosePath;
+ LV2_URID Canvas_Arc;
+ LV2_URID Canvas_CurveTo;
+ LV2_URID Canvas_LineTo;
+ LV2_URID Canvas_MoveTo;
+ LV2_URID Canvas_Rectangle;
+ LV2_URID Canvas_Style;
+ LV2_URID Canvas_LineWidth;
+ LV2_URID Canvas_LineDash;
+ LV2_URID Canvas_LineCap;
+ LV2_URID Canvas_LineJoin;
+ LV2_URID Canvas_MiterLimit;
+ LV2_URID Canvas_Stroke;
+ LV2_URID Canvas_Fill;
+ LV2_URID Canvas_Clip;
+ LV2_URID Canvas_Save;
+ LV2_URID Canvas_Restore;
+ LV2_URID Canvas_Translate;
+ LV2_URID Canvas_Scale;
+ LV2_URID Canvas_Rotate;
+ LV2_URID Canvas_Reset;
+ LV2_URID Canvas_FontSize;
+ LV2_URID Canvas_FillText;
+
+ LV2_URID Canvas_lineCapButt;
+ LV2_URID Canvas_lineCapRound;
+ LV2_URID Canvas_lineCapSquare;
+
+ LV2_URID Canvas_lineJoinMiter;
+ LV2_URID Canvas_lineJoinRound;
+ LV2_URID Canvas_lineJoinBevel;
+
+ LV2_Atom_Forge forge;
+};
+
+static inline void
+lv2_canvas_urid_init(LV2_Canvas_URID *urid, LV2_URID_Map *map)
+{
+ urid->Canvas_graph = map->map(map->handle, CANVAS__graph);
+ urid->Canvas_body = map->map(map->handle, CANVAS__body);
+
+ urid->Canvas_BeginPath = map->map(map->handle, CANVAS__BeginPath);
+ urid->Canvas_ClosePath = map->map(map->handle, CANVAS__ClosePath);
+ urid->Canvas_Arc = map->map(map->handle, CANVAS__Arc);
+ urid->Canvas_CurveTo = map->map(map->handle, CANVAS__CurveTo);
+ urid->Canvas_LineTo = map->map(map->handle, CANVAS__LineTo);
+ urid->Canvas_MoveTo = map->map(map->handle, CANVAS__MoveTo);
+ urid->Canvas_Rectangle = map->map(map->handle, CANVAS__Rectangle);
+ urid->Canvas_Style = map->map(map->handle, CANVAS__Style);
+ urid->Canvas_LineWidth = map->map(map->handle, CANVAS__LineWidth);
+ urid->Canvas_LineDash = map->map(map->handle, CANVAS__LineDash);
+ urid->Canvas_LineCap = map->map(map->handle, CANVAS__LineCap);
+ urid->Canvas_LineJoin = map->map(map->handle, CANVAS__LineJoin);
+ urid->Canvas_MiterLimit = map->map(map->handle, CANVAS__MiterLimit);
+ urid->Canvas_Stroke = map->map(map->handle, CANVAS__Stroke);
+ urid->Canvas_Fill = map->map(map->handle, CANVAS__Fill);
+ urid->Canvas_Clip = map->map(map->handle, CANVAS__Clip);
+ urid->Canvas_Save = map->map(map->handle, CANVAS__Save);
+ urid->Canvas_Restore = map->map(map->handle, CANVAS__Restore);
+ urid->Canvas_Translate = map->map(map->handle, CANVAS__Translate);
+ urid->Canvas_Scale = map->map(map->handle, CANVAS__Scale);
+ urid->Canvas_Rotate = map->map(map->handle, CANVAS__Rotate);
+ urid->Canvas_Reset = map->map(map->handle, CANVAS__Reset);
+ urid->Canvas_FontSize = map->map(map->handle, CANVAS__FontSize);
+ urid->Canvas_FillText = map->map(map->handle, CANVAS__FillText);
+
+ urid->Canvas_lineCapButt = map->map(map->handle, CANVAS__lineCapButt);
+ urid->Canvas_lineCapRound = map->map(map->handle, CANVAS__lineCapRound);
+ urid->Canvas_lineCapSquare = map->map(map->handle, CANVAS__lineCapSquare);
+
+ urid->Canvas_lineJoinMiter = map->map(map->handle, CANVAS__lineJoinMiter);
+ urid->Canvas_lineJoinRound = map->map(map->handle, CANVAS__lineJoinRound);
+ urid->Canvas_lineJoinBevel = map->map(map->handle, CANVAS__lineJoinBevel);
+
+ lv2_atom_forge_init(&urid->forge, map);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _LV2_CANVAS_H
diff --git a/canvas.lv2/forge.h b/canvas.lv2/forge.h
new file mode 100644
index 0000000..8264f89
--- /dev/null
+++ b/canvas.lv2/forge.h
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
+ *
+ * This is free software: you can redistribute it and/or modify
+ * it under the terms of the Artistic License 2.0 as published by
+ * The Perl Foundation.
+ *
+ * This source is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Artistic License 2.0 for more details.
+ *
+ * You should have received a copy of the Artistic License 2.0
+ * along the source as a COPYING file. If not, obtain it from
+ * http://www.perlfoundation.org/artistic_license_2_0.
+ */
+
+#ifndef _LV2_CANVAS_FORGE_H
+#define _LV2_CANVAS_FORGE_H
+
+#include <canvas.lv2/canvas.h>
+
+#ifdef __cplusplus
+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;
+
+ 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;
+}
+
+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_canvas_forge_arc(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
+ float x, float y, float r, float a1, float a2)
+{
+ const uint32_t n = 5;
+ const float vec [n] = {x, y, r, a1, a2};
+
+ return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_Arc, n, vec);
+}
+
+static inline 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 uint32_t n = 6;
+ const float vec [n] = {x1, y1, x2, y2, x3, y3};
+
+ return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_CurveTo, n, vec);
+}
+
+static inline LV2_Atom_Forge_Ref
+lv2_canvas_forge_lineTo(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
+ float x, float y)
+{
+ const uint32_t n = 2;
+ const float vec [n] = {x, y};
+
+ return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_LineTo, n, vec);
+}
+
+static inline LV2_Atom_Forge_Ref
+lv2_canvas_forge_moveTo(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
+ float x, float y)
+{
+ const uint32_t n = 2;
+ const float vec [n] = {x, y};
+
+ return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_MoveTo, n, vec);
+}
+
+static inline 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 uint32_t n = 4;
+ const float vec [n] = {x, y, w, h};
+
+ return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_Rectangle, n, vec);
+}
+
+static inline 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);
+}
+
+static inline 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);
+}
+
+static inline LV2_Atom_Forge_Ref
+lv2_canvas_forge_lineDash(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
+ float dash_length, float separator_length)
+{
+ const uint32_t n = 2;
+ const float vec [n] = {dash_length, separator_length};
+
+ return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_LineDash, n, vec);
+}
+
+static inline 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);
+}
+
+static inline 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);
+}
+
+static inline 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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+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);
+}
+
+static inline LV2_Atom_Forge_Ref
+lv2_canvas_forge_translate(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
+ float x, float y)
+{
+ const uint32_t n = 2;
+ const float vec [n] = {x, y};
+
+ return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_Translate, n, vec);
+}
+
+static inline LV2_Atom_Forge_Ref
+lv2_canvas_forge_scale(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
+ float w, float h)
+{
+ const uint32_t n = 2;
+ const float vec [n] = {w, h};
+
+ return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_Scale, n, vec);
+}
+
+static inline 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);
+}
+
+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_canvas_forge_fontSize(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
+ float size)
+{
+ return _lv2_canvas_forge_flt(forge, urid, urid->Canvas_FontSize, size);
+}
+
+static inline 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);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _LV2_CANVAS_FORGE_H
diff --git a/canvas.lv2/render.h b/canvas.lv2/render.h
new file mode 100644
index 0000000..86658e0
--- /dev/null
+++ b/canvas.lv2/render.h
@@ -0,0 +1,529 @@
+/*
+ * Copyright (c) 2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
+ *
+ * This is free software: you can redistribute it and/or modify
+ * it under the terms of the Artistic License 2.0 as published by
+ * The Perl Foundation.
+ *
+ * This source is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * Artistic License 2.0 for more details.
+ *
+ * You should have received a copy of the Artistic License 2.0
+ * along the source as a COPYING file. If not, obtain it from
+ * http://www.perlfoundation.org/artistic_license_2_0.
+ */
+
+#ifndef _LV2_CANVAS_RENDER_H
+#define _LV2_CANVAS_RENDER_H
+
+#include <assert.h>
+
+#include <canvas.lv2/canvas.h>
+
+#include <cairo.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LV2_CANVAS_NUM_METHODS 24
+
+typedef struct _LV2_Canvas_Meth LV2_Canvas_Meth;
+typedef struct _LV2_Canvas LV2_Canvas;
+typedef void (*LV2_Canvas_Func)(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body);
+
+struct _LV2_Canvas_Meth {
+ LV2_URID command;
+ LV2_Canvas_Func func;
+};
+
+struct _LV2_Canvas {
+ LV2_Canvas_URID urid;
+ LV2_Canvas_Meth methods [LV2_CANVAS_NUM_METHODS];
+};
+
+static inline const float *
+_lv2_canvas_render_get_float_vec(LV2_Canvas_URID *urid, const LV2_Atom *body, uint32_t N)
+{
+ const LV2_Atom_Vector *vec = (const LV2_Atom_Vector *)body;
+ const float *flt = LV2_ATOM_CONTENTS_CONST(LV2_Atom_Vector, vec);
+ const uint32_t n = (vec->atom.type == urid->forge.Vector)
+ && (vec->body.child_type == urid->forge.Float)
+ && (vec->body.child_size == sizeof(float))
+ ? (vec->atom.size - sizeof(LV2_Atom_Vector_Body)) / vec->body.child_size
+ : 0;
+
+ return n == N ? flt : NULL;
+}
+
+static inline const void *
+_lv2_canvas_render_get_type(const LV2_Atom *body, LV2_URID type)
+{
+ return body->type == type
+ ? LV2_ATOM_BODY_CONST(body)
+ : NULL;
+}
+
+static inline void
+_lv2_canvas_render_beginPath(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ cairo_new_sub_path(ctx);
+}
+
+static inline void
+_lv2_canvas_render_closePath(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ cairo_close_path(ctx);
+}
+
+static inline void
+_lv2_canvas_render_arc(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ const float *v = _lv2_canvas_render_get_float_vec(urid, body, 5);
+
+ if(v)
+ {
+ cairo_arc(ctx, v[0], v[1], v[2], v[3], v[4]);
+ }
+}
+
+static inline void
+_lv2_canvas_render_curveTo(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ const float *v = _lv2_canvas_render_get_float_vec(urid, body, 6);
+
+ if(v)
+ {
+ cairo_curve_to(ctx, v[0], v[1], v[2], v[3], v[4], v[5]);
+ }
+}
+
+static inline void
+_lv2_canvas_render_lineTo(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ const float *v = _lv2_canvas_render_get_float_vec(urid, body, 2);
+
+ if(v)
+ {
+ cairo_line_to(ctx, v[0], v[1]);
+ }
+}
+
+static inline void
+_lv2_canvas_render_moveTo(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ const float *v = _lv2_canvas_render_get_float_vec(urid, body, 2);
+
+ if(v)
+ {
+ cairo_move_to(ctx, v[0], v[1]);
+ }
+}
+
+static inline void
+_lv2_canvas_render_rectangle(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ const float *v = _lv2_canvas_render_get_float_vec(urid, body, 4);
+
+ if(v)
+ {
+ cairo_rectangle(ctx, v[0], v[1], v[2], v[3]);
+ }
+}
+
+static inline void
+_lv2_canvas_render_style(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ const int64_t *v = _lv2_canvas_render_get_type(body, urid->forge.Long);
+
+ if(v)
+ {
+ const float a = (float)((*v >> 24) & 0xff) / 0xff;
+ const float r = (float)((*v >> 16) & 0xff) / 0xff;
+ const float g = (float)((*v >> 8) & 0xff) / 0xff;
+ const float b = (float)((*v >> 0) & 0xff) / 0xff;
+
+ cairo_set_source_rgba(ctx, r, g, b, a);
+ }
+}
+
+static inline void
+_lv2_canvas_render_lineWidth(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ const float *v = _lv2_canvas_render_get_type(body, urid->forge.Float);
+
+ if(v)
+ {
+ cairo_set_line_width(ctx, *v);
+ }
+}
+
+static inline void
+_lv2_canvas_render_lineDash(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ const float *v = _lv2_canvas_render_get_float_vec(urid, body, 2);
+
+ if(v)
+ {
+ const double d[2] = {v[0], v[2]};
+ cairo_set_dash(ctx, d, 2, 0);
+ }
+}
+
+static inline void
+_lv2_canvas_render_lineCap(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ const LV2_URID *v = _lv2_canvas_render_get_type(body, urid->forge.URID);
+
+ if(v)
+ {
+ cairo_line_cap_t cap = CAIRO_LINE_CAP_BUTT;
+
+ if(*v == urid->Canvas_lineCapButt)
+ cap = CAIRO_LINE_CAP_BUTT;
+ else if(*v == urid->Canvas_lineCapRound)
+ cap = CAIRO_LINE_CAP_ROUND;
+ else if(*v == urid->Canvas_lineCapSquare)
+ cap = CAIRO_LINE_CAP_SQUARE;
+
+ cairo_set_line_cap(ctx, cap);
+ }
+}
+
+static inline void
+_lv2_canvas_render_lineJoin(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ const LV2_URID *v = _lv2_canvas_render_get_type(body, urid->forge.URID);
+
+ if(v)
+ {
+ cairo_line_join_t join = CAIRO_LINE_JOIN_MITER;
+
+ if(*v == urid->Canvas_lineJoinMiter)
+ join = CAIRO_LINE_JOIN_MITER;
+ else if(*v == urid->Canvas_lineJoinRound)
+ join = CAIRO_LINE_JOIN_ROUND;
+ else if(*v == urid->Canvas_lineJoinBevel)
+ join = CAIRO_LINE_JOIN_BEVEL;
+
+ cairo_set_line_join(ctx, join);
+ }
+}
+
+static inline void
+_lv2_canvas_render_miterLimit(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ const float *v = _lv2_canvas_render_get_type(body, urid->forge.Float);
+
+ if(v)
+ {
+ cairo_set_miter_limit(ctx, *v);
+ }
+}
+
+static inline void
+_lv2_canvas_render_stroke(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ cairo_stroke(ctx);
+}
+
+static inline void
+_lv2_canvas_render_fill(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ cairo_fill(ctx);
+}
+
+static inline void
+_lv2_canvas_render_clip(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ cairo_clip(ctx);
+}
+
+static inline void
+_lv2_canvas_render_save(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ cairo_save(ctx);
+}
+
+static inline void
+_lv2_canvas_render_restore(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ cairo_restore(ctx);
+}
+
+static inline void
+_lv2_canvas_render_translate(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ const float *v = _lv2_canvas_render_get_float_vec(urid, body, 2);
+
+ if(v)
+ {
+ cairo_translate(ctx, v[0], v[1]);
+ }
+}
+
+static inline void
+_lv2_canvas_render_scale(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ const float *v = _lv2_canvas_render_get_float_vec(urid, body, 2);
+
+ if(v)
+ {
+ cairo_scale(ctx, v[0], v[1]);
+ }
+}
+
+static inline void
+_lv2_canvas_render_rotate(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ const float *v = _lv2_canvas_render_get_type(body, urid->forge.Float);
+
+ if(v)
+ {
+ cairo_rotate(ctx, *v);
+ }
+}
+
+static inline void
+_lv2_canvas_render_reset(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ cairo_identity_matrix(ctx);
+}
+
+static inline void
+_lv2_canvas_render_fontSize(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ const float *v = _lv2_canvas_render_get_type(body, urid->forge.Float);
+
+ if(v)
+ {
+ cairo_set_font_size(ctx, *v);
+ }
+}
+
+static inline void
+_lv2_canvas_render_fillText(cairo_t *ctx,
+ LV2_Canvas_URID *urid, const LV2_Atom *body)
+{
+ const char *v = _lv2_canvas_render_get_type(body, urid->forge.String);
+
+ if(v)
+ {
+ cairo_text_extents_t extents;
+ cairo_text_extents(ctx, v, &extents);
+ const float dx = extents.width/2 + extents.x_bearing;
+ const float dy = extents.height/2 + extents.y_bearing;
+ cairo_rel_move_to(ctx, -dx, -dy);
+ cairo_show_text(ctx, v);
+ }
+}
+
+static inline void
+_lv2_canvas_qsort(LV2_Canvas_Meth *a, unsigned n)
+{
+ if(n < 2)
+ return;
+
+ const LV2_Canvas_Meth *p = &a[n/2];
+
+ unsigned i, j;
+ for(i=0, j=n-1; ; i++, j--)
+ {
+ while(a[i].command < p->command)
+ i++;
+
+ while(p->command < a[j].command)
+ j--;
+
+ if(i >= j)
+ break;
+
+ const LV2_Canvas_Meth t = a[i];
+ a[i] = a[j];
+ a[j] = t;
+ }
+
+ _lv2_canvas_qsort(a, i);
+ _lv2_canvas_qsort(&a[i], n - i);
+}
+
+static inline LV2_Canvas_Meth *
+_lv2_canvas_bsearch(LV2_URID p, LV2_Canvas_Meth *a, unsigned n)
+{
+ LV2_Canvas_Meth *base = a;
+
+ for(unsigned N = n, half; N > 1; N -= half)
+ {
+ half = N/2;
+ LV2_Canvas_Meth *dst = &base[half];
+ base = (dst->command > p) ? base : dst;
+ }
+
+ return (base->command == p) ? base : NULL;
+}
+
+static inline void
+lv2_canvas_init(LV2_Canvas *canvas, LV2_URID_Map *map)
+{
+ lv2_canvas_urid_init(&canvas->urid, map);
+
+ unsigned ptr = 0;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_BeginPath;
+ canvas->methods[ptr++].func = _lv2_canvas_render_beginPath;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_ClosePath;
+ canvas->methods[ptr++].func = _lv2_canvas_render_closePath;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_Arc;
+ canvas->methods[ptr++].func = _lv2_canvas_render_arc;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_CurveTo;
+ canvas->methods[ptr++].func = _lv2_canvas_render_curveTo;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_LineTo;
+ canvas->methods[ptr++].func = _lv2_canvas_render_lineTo;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_MoveTo;
+ canvas->methods[ptr++].func = _lv2_canvas_render_moveTo;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_Rectangle;
+ canvas->methods[ptr++].func = _lv2_canvas_render_rectangle;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_Style;
+ canvas->methods[ptr++].func = _lv2_canvas_render_style;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_LineWidth;
+ canvas->methods[ptr++].func = _lv2_canvas_render_lineWidth;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_LineDash;
+ canvas->methods[ptr++].func = _lv2_canvas_render_lineDash;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_LineCap;
+ canvas->methods[ptr++].func = _lv2_canvas_render_lineCap;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_LineJoin;
+ canvas->methods[ptr++].func = _lv2_canvas_render_lineJoin;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_MiterLimit;
+ canvas->methods[ptr++].func = _lv2_canvas_render_miterLimit;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_Stroke;
+ canvas->methods[ptr++].func = _lv2_canvas_render_stroke;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_Fill;
+ canvas->methods[ptr++].func = _lv2_canvas_render_fill;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_Clip;
+ canvas->methods[ptr++].func = _lv2_canvas_render_clip;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_Save;
+ canvas->methods[ptr++].func = _lv2_canvas_render_save;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_Restore;
+ canvas->methods[ptr++].func = _lv2_canvas_render_restore;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_Translate;
+ canvas->methods[ptr++].func = _lv2_canvas_render_translate;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_Scale;
+ canvas->methods[ptr++].func = _lv2_canvas_render_scale;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_Rotate;
+ canvas->methods[ptr++].func = _lv2_canvas_render_rotate;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_Reset;
+ canvas->methods[ptr++].func = _lv2_canvas_render_reset;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_FontSize;
+ canvas->methods[ptr++].func = _lv2_canvas_render_fontSize;
+
+ canvas->methods[ptr].command = canvas->urid.Canvas_FillText;
+ canvas->methods[ptr++].func = _lv2_canvas_render_fillText;
+
+ assert(ptr == LV2_CANVAS_NUM_METHODS);
+
+ _lv2_canvas_qsort(canvas->methods, LV2_CANVAS_NUM_METHODS);
+}
+
+static inline bool
+lv2_canvas_render(LV2_Canvas *canvas, cairo_t *ctx, const LV2_Atom_Tuple *tup)
+{
+ LV2_Canvas_URID *urid = &canvas->urid;
+
+ if(!tup || (tup->atom.type != urid->forge.Tuple) )
+ return false;
+
+ // save state
+ cairo_save(ctx);
+
+ // clear surface
+ cairo_set_operator(ctx, CAIRO_OPERATOR_CLEAR);
+ cairo_paint(ctx);
+
+ // default attributes
+ cairo_set_operator(ctx, CAIRO_OPERATOR_SOURCE);
+ cairo_set_font_size(ctx, 0.1);
+ cairo_set_line_width(ctx, 0.01);
+ cairo_set_source_rgba(ctx, 1.0, 1.0, 1.0, 1.0);
+
+ LV2_ATOM_TUPLE_FOREACH(tup, itm)
+ {
+ if(lv2_atom_forge_is_object_type(&urid->forge, itm->type))
+ {
+ const LV2_Atom_Object *obj = (const LV2_Atom_Object *)itm;
+ const LV2_Atom *body = NULL;
+
+ lv2_atom_object_get(obj, urid->Canvas_body, &body, 0);
+
+ LV2_Canvas_Meth *meth = _lv2_canvas_bsearch(obj->body.otype,
+ canvas->methods, LV2_CANVAS_NUM_METHODS);
+
+ if(meth)
+ {
+ meth->func(ctx, urid, body);
+ }
+ }
+ }
+
+ // save state
+ cairo_restore(ctx);
+
+ // flush
+ cairo_surface_t *surface = cairo_get_target(ctx);
+ cairo_surface_flush(surface);
+
+ return true;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // CANVAS_IMPLEMENTATION
diff --git a/canvas.c b/test/canvas.c
index 4d06252..ac88468 100644
--- a/canvas.c
+++ b/test/canvas.c
@@ -16,10 +16,13 @@
*/
#include <stdlib.h>
+#include <stdio.h>
#include <stdatomic.h>
-#include <math.h>
-#include <canvas.h>
+#include <lv2/lv2plug.in/ns/ext/patch/patch.h>
+
+#include <canvas.lv2/forge.h>
+#include <canvas.lv2/render.h>
#include <lv2_extensions.h>
@@ -33,9 +36,6 @@ struct _plughandle_t {
LV2_URID_Map *map;
LV2_Atom_Forge forge;
- LV2_Log_Log *log;
- LV2_Log_Logger logger;
-
const LV2_Atom_Sequence *control;
LV2_Atom_Sequence *notify;
@@ -77,15 +77,66 @@ _try_lock(atomic_flag *lock)
}
static inline void
-_unlock_lock(atomic_flag *lock)
+_unlock(atomic_flag *lock)
{
atomic_flag_clear_explicit(lock, memory_order_release);
}
-static inline void
-_init_lock(atomic_flag *lock)
+static inline LV2_Atom_Forge_Ref
+_lv2_logo_forge(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid)
{
- atomic_flag_clear_explicit(lock, memory_order_relaxed);
+ const uint32_t fg = 0xffbb6600;
+ LV2_Atom_Forge_Ref ref;
+
+ if( (ref = lv2_canvas_forge_beginPath(forge, urid))
+ && (ref = lv2_canvas_forge_moveTo(forge, urid, 0.05, 0.275))
+ && (ref = lv2_canvas_forge_lineTo(forge, urid, 0.05, 0.73463521816969))
+ && (ref = lv2_canvas_forge_lineTo(forge, urid, 0.39996786383766, 0.73463521816969))
+ && (ref = lv2_canvas_forge_lineTo(forge, urid, 0.35805418792799, 0.61981755929103))
+ && (ref = lv2_canvas_forge_lineTo(forge, urid, 0.16950515672412, 0.61981755929103))
+ && (ref = lv2_canvas_forge_lineTo(forge, urid, 0.16950515672412, 0.275))
+ && (ref = lv2_canvas_forge_lineTo(forge, urid, 0.05, 0.275))
+ && (ref = lv2_canvas_forge_style(forge, urid, fg))
+ && (ref = lv2_canvas_forge_stroke(forge, urid))
+
+ && (ref = lv2_canvas_forge_beginPath(forge, urid))
+ && (ref = lv2_canvas_forge_moveTo(forge, urid, 0.44035674587458, 0.73463521816969))
+ && (ref = lv2_canvas_forge_lineTo(forge, urid, 0.27321237521861, 0.275))
+ && (ref = lv2_canvas_forge_lineTo(forge, urid, 0.39612954205777, 0.275))
+ && (ref = lv2_canvas_forge_lineTo(forge, urid, 0.5215250619933, 0.61980400005209))
+ && (ref = lv2_canvas_forge_lineTo(forge, urid, 0.64678627651808, 0.275))
+ && (ref = lv2_canvas_forge_lineTo(forge, urid, 0.76999411666921, 0.275))
+ && (ref = lv2_canvas_forge_lineTo(forge, urid, 0.60269884777111, 0.73463521816969))
+ && (ref = lv2_canvas_forge_lineTo(forge, urid, 0.44035674587458, 0.73463521816969))
+ && (ref = lv2_canvas_forge_style(forge, urid, fg))
+ && (ref = lv2_canvas_forge_stroke(forge, urid))
+
+ && (ref = lv2_canvas_forge_beginPath(forge, urid))
+ && (ref = lv2_canvas_forge_moveTo(forge, urid, 0.92679577564592, 0.33745757758451))
+ && (ref = lv2_canvas_forge_curveTo(forge, urid, 0.95, 0.37544661222032, 0.9486097413556,
+ 0.42890103900541, 0.91866073788306, 0.46581025262318))
+ && (ref = lv2_canvas_forge_curveTo(forge, urid, 0.87662774067075, 0.51761178520021,
+ 0.84865149155459, 0.52351773004551, 0.8188709443895, 0.55088574387747))
+ && (ref = lv2_canvas_forge_lineTo(forge, urid, 0.93798338878322, 0.55088574387747))
+ && (ref = lv2_canvas_forge_lineTo(forge, urid, 0.93798338878322, 0.61972641362727))
+ && (ref = lv2_canvas_forge_lineTo(forge, urid, 0.68857649440815, 0.61972641362727))
+ && (ref = lv2_canvas_forge_curveTo(forge, urid, 0.70410821191941, 0.57897193773781,
+ 0.71568706655441, 0.55649255812279, 0.73505227967577, 0.53436493734023))
+ && (ref = lv2_canvas_forge_curveTo(forge, urid, 0.78431409785481, 0.47807598612821,
+ 0.88073913173375, 0.44149338929647, 0.87483180798279, 0.39074363998918))
+ && (ref = lv2_canvas_forge_curveTo(forge, urid, 0.8731729385169, 0.37649219041461,
+ 0.86900905711197, 0.34385128732334, 0.80655313421425, 0.34385128732334))
+ && (ref = lv2_canvas_forge_lineTo(forge, urid, 0.7834998081023, 0.34385128732334))
+ && (ref = lv2_canvas_forge_lineTo(forge, urid, 0.80849192152801, 0.275))
+ && (ref = lv2_canvas_forge_curveTo(forge, urid, 0.88098903540187, 0.275,
+ 0.90879494370618, 0.30798728419169, 0.92679577564592, 0.33745757758451))
+ && (ref = lv2_canvas_forge_style(forge, urid, fg))
+ && (ref = lv2_canvas_forge_stroke(forge, urid)) )
+ {
+ return ref;
+ }
+
+ return 0;
}
static LV2_Handle
@@ -100,8 +151,6 @@ instantiate(const LV2_Descriptor* descriptor, double rate,
{
if(!strcmp(features[i]->URI, LV2_URID__map))
handle->map = features[i]->data;
- else if(!strcmp(features[i]->URI, LV2_LOG__log))
- handle->log = features[i]->data;
else if(!strcmp(features[i]->URI, LV2_INLINEDISPLAY__queue_draw))
handle->queue_draw = features[i]->data;
}
@@ -119,18 +168,23 @@ instantiate(const LV2_Descriptor* descriptor, double rate,
handle->patch_property = handle->map->map(handle->map->handle, LV2_PATCH__property);
handle->patch_value = handle->map->map(handle->map->handle, LV2_PATCH__value);
- if(handle->log)
- lv2_log_logger_init(&handle->logger, handle->map, handle->log);
-
lv2_atom_forge_init(&handle->forge, handle->map);
- handle->graph.atom.size = 0;
- handle->graph.atom.type = handle->forge.Tuple;
-
- _init_lock(&handle->lock);
+ handle->lock = (atomic_flag)ATOMIC_FLAG_INIT;
lv2_canvas_init(&handle->canvas, handle->map);
+ LV2_Atom_Forge_Frame frame;
+ lv2_atom_forge_set_buffer(&handle->forge, handle->buf, MAX_GRAPH_BUF);
+ LV2_Atom_Forge_Ref ref = lv2_atom_forge_tuple(&handle->forge, &frame);
+ if(ref)
+ ref = _lv2_logo_forge(&handle->forge, &handle->canvas.urid);
+ if(ref)
+ lv2_atom_forge_pop(&handle->forge, &frame);
+
+ if(handle->queue_draw)
+ handle->queue_draw->queue_draw(handle->queue_draw->handle);
+
return handle;
}
@@ -147,6 +201,7 @@ connect_port(LV2_Handle instance, uint32_t port, void *data)
case 1:
handle->notify = data;
break;
+
default:
break;
}
@@ -178,6 +233,8 @@ run(LV2_Handle instance, uint32_t nsamples)
&& (property->atom.type == handle->forge.URID)
&& (property->body == handle->canvas.urid.Canvas_graph) )
{
+ const uint32_t szg = lv2_atom_total_size(&handle->graph.atom);
+
LV2_Atom_Forge_Frame obj_frame;
if(ref)
ref = lv2_atom_forge_frame_time(&handle->forge, ev->time.frames);
@@ -190,7 +247,7 @@ run(LV2_Handle instance, uint32_t nsamples)
if(ref)
ref = lv2_atom_forge_key(&handle->forge, handle->patch_value);
if(ref)
- ref = lv2_atom_forge_write(&handle->forge, &handle->graph, lv2_atom_total_size(&handle->graph.atom));
+ ref = lv2_atom_forge_write(&handle->forge, &handle->graph, szg);
if(ref)
lv2_atom_forge_pop(&handle->forge, &obj_frame);
}
@@ -209,13 +266,15 @@ run(LV2_Handle instance, uint32_t nsamples)
&& graph
&& (graph->atom.type == handle->forge.Tuple) )
{
- const uint32_t sz = lv2_atom_total_size(&graph->atom);
+ const uint32_t szo = lv2_atom_total_size(&obj->atom);
+ const uint32_t szg = lv2_atom_total_size(&graph->atom);
- if( (sz <= MAX_GRAPH_BUF) && _try_lock(&handle->lock))
+ if( (szg <= MAX_GRAPH_BUF)
+ && _try_lock(&handle->lock) )
{
- memcpy(&handle->graph, graph, sz);
+ memcpy(&handle->graph, graph, szg);
- _unlock_lock(&handle->lock);
+ _unlock(&handle->lock);
if(handle->queue_draw)
handle->queue_draw->queue_draw(handle->queue_draw->handle);
@@ -224,7 +283,7 @@ run(LV2_Handle instance, uint32_t nsamples)
if(ref)
ref = lv2_atom_forge_frame_time(&handle->forge, ev->time.frames);
if(ref)
- ref = lv2_atom_forge_write(&handle->forge, obj, lv2_atom_total_size(&obj->atom));
+ ref = lv2_atom_forge_write(&handle->forge, obj, szo);
}
}
}
@@ -308,9 +367,9 @@ _render(LV2_Handle instance, uint32_t w, uint32_t h)
_spin_lock(&handle->lock);
- lv2_canvas_render(&handle->canvas, handle->cairo.ctx, &handle->forge, &handle->graph);
+ lv2_canvas_render(&handle->canvas, handle->cairo.ctx, &handle->graph);
- _unlock_lock(&handle->lock);
+ _unlock(&handle->lock);
return surf;
}
@@ -328,7 +387,6 @@ cleanup(LV2_Handle instance)
if(handle->image_surface.data)
free(handle->image_surface.data);
- handle->image_surface.data = NULL;
free(handle);
}
@@ -360,6 +418,7 @@ lv2_descriptor(uint32_t index)
{
case 0:
return &canvas_canvas;
+
default:
return NULL;
}
diff --git a/canvas.ttl b/test/canvas.ttl
index 7cae841..fa76918 100644
--- a/canvas.ttl
+++ b/test/canvas.ttl
@@ -15,13 +15,9 @@
@prefix foaf: <http://xmlns.com/foaf/0.1/> .
@prefix doap: <http://usefulinc.com/ns/doap#> .
-@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
-@prefix rdf: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .
-@prefix log: <http://lv2plug.in/ns/ext/log#> .
-@prefix midi: <http://lv2plug.in/ns/ext/midi#> .
@prefix idisp: <http://harrisonconsoles.com/lv2/inlinedisplay#> .
@prefix lic: <http://opensource.org/licenses/> .
@@ -56,14 +52,13 @@ canvas:canvas
doap:license lic:Artistic-2.0 ;
lv2:project proj:canvas ;
lv2:requiredFeature urid:map ;
- lv2:optionalFeature lv2:isLive, lv2:hardRTCapable, log:log, idisp:queue_draw ;
+ lv2:optionalFeature lv2:isLive, lv2:hardRTCapable, idisp:queue_draw ;
lv2:extensionData idisp:interface ;
lv2:port [
a lv2:InputPort ,
atom:AtomPort ;
atom:bufferType atom:Sequence ;
- atom:supports midi:MidiEvent ;
lv2:index 0 ;
lv2:symbol "control" ;
lv2:name "Control" ;
@@ -72,7 +67,6 @@ canvas:canvas
a lv2:OutputPort ,
atom:AtomPort ;
atom:bufferType atom:Sequence ;
- atom:supports midi:MidiEvent ;
lv2:index 1 ;
lv2:symbol "notify" ;
lv2:name "Notify" ;
diff --git a/canvas_ui.c b/test/canvas_ui.c
index 7d9e22d..61b4b88 100644
--- a/canvas_ui.c
+++ b/test/canvas_ui.c
@@ -19,7 +19,11 @@
#include <stdio.h>
#include <math.h>
-#include <canvas.h>
+#include <lv2/lv2plug.in/ns/ext/patch/patch.h>
+#include <lv2/lv2plug.in/ns/extensions/ui/ui.h>
+
+#include <canvas.lv2/forge.h>
+#include <canvas.lv2/render.h>
#include <pugl/pugl.h>
@@ -31,9 +35,6 @@ struct _plughandle_t {
LV2_URID_Map *map;
LV2_Atom_Forge forge;
- LV2_Log_Log *log;
- LV2_Log_Logger logger;
-
PuglView *view;
int done;
@@ -46,7 +47,6 @@ struct _plughandle_t {
LV2_URID atom_eventTransfer;
LV2_Atom_Tuple *graph;
- bool dirty;
LV2UI_Write_Function writer;
LV2UI_Controller controller;
@@ -82,14 +82,16 @@ _expose(plughandle_t *handle)
#ifndef _WIN32 //FIXME
cairo_t *ctx = puglGetContext(handle->view);
- lv2_canvas_render(&handle->canvas, ctx, &handle->forge, handle->graph);
+ if(ctx)
+ {
+ lv2_canvas_render(&handle->canvas, ctx, handle->graph);
+ }
#endif
}
static inline void
_close(plughandle_t *handle)
{
-printf("_close\n");
handle->done = 1;
}
@@ -99,8 +101,11 @@ _configure(plughandle_t *handle, const PuglEventConfigure *e)
#ifndef _WIN32 //FIXME
cairo_t *ctx = puglGetContext(handle->view);
- cairo_surface_t *surf = cairo_get_target(ctx);
- cairo_surface_set_device_scale(surf, e->width, e->height);
+ if(ctx)
+ {
+ cairo_surface_t *surf = cairo_get_target(ctx);
+ cairo_surface_set_device_scale(surf, e->width, e->height);
+ }
#endif
}
@@ -111,29 +116,19 @@ _event_func(PuglView *view, const PuglEvent *e)
switch(e->type)
{
- case PUGL_NOTHING:
- break;
- case PUGL_BUTTON_PRESS:
- break;
- case PUGL_BUTTON_RELEASE:
- break;
case PUGL_CONFIGURE:
+ {
_configure(handle, (const PuglEventConfigure *)e);
- break;
+ puglPostRedisplay(handle->view);
+ } break;
case PUGL_EXPOSE:
+ {
_expose(handle);
- break;
+ } break;
case PUGL_CLOSE:
+ {
_close(handle);
- break;
- case PUGL_KEY_PRESS:
- break;
- case PUGL_KEY_RELEASE:
- break;
- case PUGL_MOTION_NOTIFY:
- break;
- case PUGL_SCROLL:
- break;
+ } break;
case PUGL_ENTER_NOTIFY:
// fall-through
case PUGL_LEAVE_NOTIFY:
@@ -141,8 +136,26 @@ _event_func(PuglView *view, const PuglEvent *e)
case PUGL_FOCUS_IN:
// fall-through
case PUGL_FOCUS_OUT:
+ {
puglPostRedisplay(handle->view);
- break;
+ } break;
+
+ case PUGL_NOTHING:
+ // fall-through
+ case PUGL_BUTTON_PRESS:
+ // fall-through
+ case PUGL_BUTTON_RELEASE:
+ // fall-through
+ case PUGL_KEY_PRESS:
+ // fall-through
+ case PUGL_KEY_RELEASE:
+ // fall-through
+ case PUGL_MOTION_NOTIFY:
+ // fall-through
+ case PUGL_SCROLL:
+ {
+ // nothing
+ } break;
}
}
@@ -166,8 +179,6 @@ instantiate(const LV2UI_Descriptor *descriptor, const char *plugin_uri,
host_resize = features[i]->data;
else if(!strcmp(features[i]->URI, LV2_URID__map))
handle->map = features[i]->data;
- else if(!strcmp(features[i]->URI, LV2_LOG__log))
- handle->log = features[i]->data;
}
if(!parent)
@@ -185,9 +196,6 @@ instantiate(const LV2UI_Descriptor *descriptor, const char *plugin_uri,
return NULL;
}
- if(handle->log)
- lv2_log_logger_init(&handle->logger, handle->map, handle->log);
-
lv2_atom_forge_init(&handle->forge, handle->map);
handle->patch_Get = handle->map->map(handle->map->handle, LV2_PATCH__Get);
@@ -280,7 +288,7 @@ port_event(LV2UI_Handle instance, uint32_t index, uint32_t size,
{
plughandle_t *handle = instance;
- if(index == 1) // notify
+ if( (index == 1) && (protocol == handle->atom_eventTransfer) ) // notify
{
const LV2_Atom_Object *obj = buf;
@@ -289,26 +297,28 @@ port_event(LV2UI_Handle instance, uint32_t index, uint32_t size,
if(obj->body.otype == handle->patch_Set)
{
const LV2_Atom_URID *property = NULL;
- const LV2_Atom_Tuple *body = NULL;
+ const LV2_Atom_Tuple *graph = NULL;
lv2_atom_object_get(obj,
handle->patch_property, &property,
- handle->patch_value, &body,
+ handle->patch_value, &graph,
0);
- if(property && body)
+ if( property
+ && (property->atom.type == handle->forge.URID)
+ && (property->body == handle->canvas.urid.Canvas_graph)
+ && graph
+ && (graph->atom.type == handle->forge.Tuple) )
{
- if( (property->body == handle->canvas.urid.Canvas_graph)
- && (body->atom.type == handle->forge.Tuple) )
- {
- if(handle->graph)
- free(handle->graph);
- const size_t sz = lv2_atom_total_size(&body->atom);
- handle->graph = malloc(sz);
- if(handle->graph)
- memcpy(handle->graph, body, sz);
- handle->dirty = true;
- }
+ if(handle->graph)
+ free(handle->graph);
+
+ const size_t sz = lv2_atom_total_size(&graph->atom);
+ handle->graph = malloc(sz);
+ if(handle->graph)
+ memcpy(handle->graph, graph, sz);
+
+ puglPostRedisplay(handle->view);
}
}
}
@@ -320,12 +330,6 @@ _idle(LV2UI_Handle instance)
{
plughandle_t *handle = instance;
- if(handle->dirty)
- {
- puglPostRedisplay(handle->view);
- handle->dirty = false;
- }
-
puglProcessEvents(handle->view);
return handle->done;
@@ -359,6 +363,7 @@ lv2ui_descriptor(uint32_t index)
{
case 0:
return &canvas_canvas_ui;
+
default:
return NULL;
}
diff --git a/canvas_ui.ttl b/test/canvas_ui.ttl
index e2efaae..53666dd 100644
--- a/canvas_ui.ttl
+++ b/test/canvas_ui.ttl
@@ -17,7 +17,6 @@
@prefix ui: <http://lv2plug.in/ns/extensions/ui#> .
@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
@prefix urid: <http://lv2plug.in/ns/ext/urid#> .
-@prefix log: <http://lv2plug.in/ns/ext/log#> .
@prefix canvas: <http://open-music-kontrollers.ch/lv2/canvas#> .
@@ -27,6 +26,5 @@ canvas:canvas_ui
lv2:symbol "notify" ;
ui:protocol atom:eventTransfer
] ;
- lv2:requiredFeature ui:idleInterface, urid:map ;
- lv2:optionalFeature log:log ;
- lv2:extensionData ui:idleInterface, ui:showInterface .
+ lv2:requiredFeature urid:map ;
+ lv2:extensionData ui:idleInterface .
diff --git a/manifest.ttl.in b/test/manifest.ttl.in
index 679b95a..679b95a 100644
--- a/manifest.ttl.in
+++ b/test/manifest.ttl.in