Commit ca40c32a authored by Hanspeter Portner's avatar Hanspeter Portner

update canvas extension.

parent 61c288ae
Pipeline #20482394 (#) passed with stages
in 8 minutes and 25 seconds
......@@ -1722,6 +1722,7 @@ moony_open(moony_t *moony, moony_vm_t *vm, lua_State *L)
lua_newtable(L);
{
SET_MAP(L, CANVAS__, graph);
SET_MAP(L, CANVAS__, aspectRatio);
SET_MAP(L, CANVAS__, body);
SET_MAP(L, CANVAS__, BeginPath);
SET_MAP(L, CANVAS__, ClosePath);
......@@ -1730,6 +1731,7 @@ moony_open(moony_t *moony, moony_vm_t *vm, lua_State *L)
SET_MAP(L, CANVAS__, LineTo);
SET_MAP(L, CANVAS__, MoveTo);
SET_MAP(L, CANVAS__, Rectangle);
SET_MAP(L, CANVAS__, PolyLine);
SET_MAP(L, CANVAS__, Style);
SET_MAP(L, CANVAS__, LineWidth);
SET_MAP(L, CANVAS__, LineDash);
......
......@@ -1469,51 +1469,6 @@ _lforge_insert(lua_State *L)
return 1; // derived forge
}
__realtime static int
_lforge_canvas_graph(lua_State *L)
{
moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
lforge_t *lforge = lua_touserdata(L, 1);
const LV2_URID property = moony->canvas_urid.Canvas_graph;
const LV2_URID subject = luaL_optinteger(L, 2, 0);
const int32_t sequence_num = luaL_optinteger(L, 3, 0);
lforge_t *lframe = moony_newuserdata(L, moony, MOONY_UDATA_FORGE, lforge->lheader.cache);
lframe->depth = 2;
lframe->last.frames = lforge->last.frames;
lframe->forge = lforge->forge;
lua_pushvalue(L, 1); // lforge
lua_setuservalue(L, -2); // store parent as uservalue
if(!lv2_atom_forge_object(lforge->forge, &lframe->frame[0], 0, moony->uris.patch.set))
luaL_error(L, forge_buffer_overflow);
if(subject) // is optional
{
if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.subject))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_urid(lforge->forge, subject))
luaL_error(L, forge_buffer_overflow);
}
if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.sequence))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_int(lforge->forge, sequence_num))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.property))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_urid(lforge->forge, property))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_key(lforge->forge, moony->uris.patch.value))
luaL_error(L, forge_buffer_overflow);
if(!lv2_atom_forge_tuple(lforge->forge, &lframe->frame[1]))
luaL_error(L, forge_buffer_overflow);
return 1; // derived forge
}
__realtime static int
_lforge_canvas_begin_path(lua_State *L)
{
......@@ -1624,6 +1579,28 @@ _lforge_canvas_rectangle(lua_State *L)
return 1;
}
__realtime static int
_lforge_canvas_poly_line(lua_State *L)
{
moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
lforge_t *lforge = lua_touserdata(L, 1);
const uint32_t nvec = lua_gettop(L) - 1;
float *vec = alloca(sizeof(float) * nvec); //FIXME add floats one at a time
//FIXME handle table as single argument
for(unsigned pos = 0; pos < nvec; pos++)
{
vec[pos] = luaL_checknumber(L, 2 + pos);
}
if(!lv2_canvas_forge_polyLine(lforge->forge, &moony->canvas_urid, nvec, vec) )
luaL_error(L, forge_buffer_overflow);
lua_settop(L, 1);
return 1;
}
__realtime static int
_lforge_canvas_style(lua_State *L)
{
......@@ -2109,7 +2086,6 @@ const luaL_Reg lforge_mt [] = {
{"insert", _lforge_insert},
// canvas
{"graph", _lforge_canvas_graph},
{"beginPath", _lforge_canvas_begin_path},
{"closePath", _lforge_canvas_close_path},
{"arc", _lforge_canvas_arc},
......@@ -2117,6 +2093,7 @@ const luaL_Reg lforge_mt [] = {
{"lineTo", _lforge_canvas_line_to},
{"moveTo", _lforge_canvas_move_to},
{"rectangle", _lforge_canvas_rectangle},
{"polyLine", _lforge_canvas_poly_line},
{"style", _lforge_canvas_style},
{"lineWidth", _lforge_canvas_line_width},
{"lineDash", _lforge_canvas_line_dash},
......
......@@ -31,6 +31,7 @@ extern "C" {
#define CANVAS__graph CANVAS_PREFIX"graph"
#define CANVAS__body CANVAS_PREFIX"body"
#define CANVAS__aspectRatio CANVAS_PREFIX"aspectRatio"
// Graph properties and attributes
#define CANVAS__BeginPath CANVAS_PREFIX"BeginPath"
......@@ -40,6 +41,7 @@ extern "C" {
#define CANVAS__LineTo CANVAS_PREFIX"LineTo"
#define CANVAS__MoveTo CANVAS_PREFIX"MoveTo"
#define CANVAS__Rectangle CANVAS_PREFIX"Rectangle"
#define CANVAS__PolyLine CANVAS_PREFIX"PolyLine"
#define CANVAS__Style CANVAS_PREFIX"Style"
#define CANVAS__LineWidth CANVAS_PREFIX"LineWidth"
#define CANVAS__LineDash CANVAS_PREFIX"LineDash"
......@@ -82,6 +84,7 @@ typedef struct _LV2_Canvas_URID LV2_Canvas_URID;
struct _LV2_Canvas_URID {
LV2_URID Canvas_graph;
LV2_URID Canvas_body;
LV2_URID Canvas_aspectRatio;
LV2_URID Canvas_BeginPath;
LV2_URID Canvas_ClosePath;
......@@ -90,6 +93,7 @@ struct _LV2_Canvas_URID {
LV2_URID Canvas_LineTo;
LV2_URID Canvas_MoveTo;
LV2_URID Canvas_Rectangle;
LV2_URID Canvas_PolyLine;
LV2_URID Canvas_Style;
LV2_URID Canvas_LineWidth;
LV2_URID Canvas_LineDash;
......@@ -133,6 +137,7 @@ 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_aspectRatio = map->map(map->handle, CANVAS__aspectRatio);
urid->Canvas_BeginPath = map->map(map->handle, CANVAS__BeginPath);
urid->Canvas_ClosePath = map->map(map->handle, CANVAS__ClosePath);
......@@ -141,6 +146,7 @@ lv2_canvas_urid_init(LV2_Canvas_URID *urid, LV2_URID_Map *map)
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_PolyLine = map->map(map->handle, CANVAS__PolyLine);
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);
......
......@@ -184,6 +184,13 @@ lv2_canvas_forge_rectangle(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
return _lv2_canvas_forge_vec(forge, urid, urid->Canvas_Rectangle, 4, vec);
}
static inline 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);
}
static inline LV2_Atom_Forge_Ref
lv2_canvas_forge_style(LV2_Atom_Forge *forge, LV2_Canvas_URID *urid,
uint32_t style)
......
......@@ -28,7 +28,7 @@
extern "C" {
#endif
#define LV2_CANVAS_NUM_METHODS 24
#define LV2_CANVAS_NUM_METHODS 25
typedef struct _LV2_Canvas_Meth LV2_Canvas_Meth;
typedef struct _LV2_Canvas LV2_Canvas;
......@@ -46,16 +46,27 @@ struct _LV2_Canvas {
};
static inline const float *
_lv2_canvas_render_get_float_vec(LV2_Canvas_URID *urid, const LV2_Atom *body, uint32_t N)
_lv2_canvas_render_get_float_vecs(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)
*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 flt;
}
static inline const float *
_lv2_canvas_render_get_float_vec(LV2_Canvas_URID *urid, const LV2_Atom *body,
uint32_t n)
{
uint32_t N;
const float *flt = _lv2_canvas_render_get_float_vecs(urid, body, &N);
return n == N ? flt : NULL;
}
......@@ -141,6 +152,27 @@ _lv2_canvas_render_rectangle(cairo_t *ctx,
}
}
static inline void
_lv2_canvas_render_polyline(cairo_t *ctx,
LV2_Canvas_URID *urid, const LV2_Atom *body)
{
uint32_t N;
const float *v = _lv2_canvas_render_get_float_vecs(urid, body, &N);
if(v)
{
for(uint32_t i = 0; i < 2; i += 2)
{
cairo_move_to(ctx, v[i], v[i+1]);
}
for(uint32_t i = 2; i < N; i += 2)
{
cairo_line_to(ctx, v[i], v[i+1]);
}
}
}
static inline void
_lv2_canvas_render_style(cairo_t *ctx,
LV2_Canvas_URID *urid, const LV2_Atom *body)
......@@ -178,7 +210,7 @@ _lv2_canvas_render_lineDash(cairo_t *ctx,
if(v)
{
const double d[2] = {v[0], v[2]};
const double d[2] = {v[0], v[1]};
cairo_set_dash(ctx, d, 2, 0);
}
}
......@@ -420,6 +452,9 @@ lv2_canvas_init(LV2_Canvas *canvas, LV2_URID_Map *map)
canvas->methods[ptr].command = canvas->urid.Canvas_Rectangle;
canvas->methods[ptr++].func = _lv2_canvas_render_rectangle;
canvas->methods[ptr].command = canvas->urid.Canvas_PolyLine;
canvas->methods[ptr++].func = _lv2_canvas_render_polyline;
canvas->methods[ptr].command = canvas->urid.Canvas_Style;
canvas->methods[ptr++].func = _lv2_canvas_render_style;
......
......@@ -233,6 +233,7 @@ pre {
<li><a href="#forge-lineTo">LineTo</a></li>
<li><a href="#forge-moveTo">MoveTo</a></li>
<li><a href="#forge-rectangle">Rectangle</a></li>
<li><a href="#forge-polyLine">PolyLine</a></li>
<li><a href="#forge-style">Style</a></li>
<li><a href="#forge-lineWidth">LineWidth</a></li>
<li><a href="#forge-lineDash">LineDash</a></li>
......@@ -2119,7 +2120,7 @@ end</code></pre>
<pre><code data-ref="forge-graph">-- Forge Graph
function stash(forge)
for ctx in forge:time(0):graph():autopop() do
for ctx in forge:tuple():autopop() do
ctx:rectangle(0.1, 0.1, 0.8, 0.8):style(0xff000000):fill()
end
end</code></pre>
......@@ -2292,6 +2293,28 @@ function stash(ctx)
end</code></pre>
</div>
<!-- Forge PolyLine -->
<div class="api-section">
<h3 id="forge-polyLine">PolyLine</h3>
<p>Forge an atom object of type Canvas.PolyLine. Create polyline.</p>
<dl>
<dt class="func">forge:polyLine(x1, y1, ...)</dt>
<dt>x1 (number)</dt>
<dd>x coordinate of first point</dd>
<dt>y1 (number)</dt>
<dd>y coordinate of first poine</dd>
<dt class="ret">(userdata)</dt>
<dd>self forge object</dd>
</dl>
<pre><code data-ref="forge-polyLine">-- Forge PolyLine
function stash(ctx)
ctx:beginPath():polyLine(0.1, 0.1, 0.9, 0.1, 0.5, 0.9):closePath():fill()
end</code></pre>
</div>
<!-- Forge Style -->
<div class="api-section">
<h3 id="forge-style">Style</h3>
......
......@@ -689,6 +689,7 @@ local ui_lib = lib_const('Ui', {
local canvas_lib = lib_const('Canvas', {
'graph',
'aspectRatio',
'body',
'BeginPath',
'ClosePath',
......@@ -697,6 +698,7 @@ local canvas_lib = lib_const('Canvas', {
'LineTo',
'MoveTo',
'Rectangle',
'PolyLine',
'Style',
'LineWidth',
'LineDash',
......@@ -799,7 +801,6 @@ local field_func = token(T.OPERATOR, S('.:')) * token(T.FUNCTION, word_match(ord
'pop',
'autopop',
-- moony canvas
'graph',
'beginPath',
'closePath',
'arc',
......@@ -807,6 +808,7 @@ local field_func = token(T.OPERATOR, S('.:')) * token(T.FUNCTION, word_match(ord
'lineTo',
'moveTo',
'rectangle',
'polyLine',
'style',
'lineWidth',
'lineDash',
......
......@@ -612,62 +612,100 @@ moony:bank-canvas_lv2-logo
moony:code """local bg = 0x00000000 -- transparent black
local fg = 0xff0066ff -- purple
local function render(frames, forge)
local ctx = forge:time(frames):graph()
-- background
ctx:rectangle(0.0, 0.0, 1.0, 1.0):style(bg):fill()
-- 'L'
ctx:beginPath()
ctx:moveTo(0.05, 0.275)
ctx:lineTo(0.05, 0.73463521816969)
ctx:lineTo(0.39996786383766, 0.73463521816969)
ctx:lineTo(0.35805418792799, 0.61981755929103)
ctx:lineTo(0.16950515672412, 0.61981755929103)
ctx:lineTo(0.16950515672412, 0.275)
ctx:lineTo(0.05, 0.275)
ctx:closePath():style(fg):stroke()
-- 'V'
ctx:beginPath()
ctx:moveTo(0.44035674587458, 0.73463521816969)
ctx:lineTo(0.27321237521861, 0.275)
ctx:lineTo(0.39612954205777, 0.275)
ctx:lineTo(0.5215250619933, 0.61980400005209)
ctx:lineTo(0.64678627651808, 0.275)
ctx:lineTo(0.76999411666921, 0.275)
ctx:lineTo(0.60269884777111, 0.73463521816969)
ctx:lineTo(0.44035674587458, 0.73463521816969)
ctx:closePath():style(fg):stroke()
-- '2'
ctx:beginPath()
ctx:moveTo(0.92679577564592, 0.33745757758451)
ctx:curveTo(0.95, 0.37544661222032,
0.9486097413556, 0.42890103900541, 0.91866073788306, 0.46581025262318)
ctx:curveTo(0.87662774067075, 0.51761178520021,
0.84865149155459, 0.52351773004551, 0.8188709443895, 0.55088574387747)
ctx:lineTo(0.93798338878322, 0.55088574387747)
ctx:lineTo(0.93798338878322, 0.61972641362727)
ctx:lineTo(0.68857649440815, 0.61972641362727)
ctx:curveTo(0.70410821191941, 0.57897193773781,
0.71568706655441, 0.55649255812279, 0.73505227967577, 0.53436493734023)
ctx:curveTo(0.78431409785481, 0.47807598612821,
0.88073913173375, 0.44149338929647, 0.87483180798279, 0.39074363998918)
ctx:curveTo(0.8731729385169, 0.37649219041461,
0.86900905711197, 0.34385128732334, 0.80655313421425, 0.34385128732334)
ctx:lineTo(0.7834998081023, 0.34385128732334)
ctx:lineTo(0.80849192152801, 0.275)
ctx:curveTo(0.88098903540187, 0.275,
0.90879494370618, 0.30798728419169, 0.92679577564592, 0.33745757758451)
ctx:closePath():style(fg):stroke()
ctx:pop()
local ctx = Stash()
local function render()
ctx:tuple()
-- background
:rectangle(0.0, 0.0, 1.0, 1.0):style(bg):fill()
-- 'L'
ctx:beginPath()
ctx:polyLine(0.05, 0.275,
0.05, 0.73463521816969,
0.39996786383766, 0.73463521816969,
0.35805418792799, 0.61981755929103,
0.16950515672412, 0.61981755929103,
0.16950515672412, 0.275,
0.05, 0.275)
ctx:closePath():style(fg):stroke()
-- 'V'
ctx:beginPath()
ctx:polyLine(0.44035674587458, 0.73463521816969,
0.27321237521861, 0.275,
0.39612954205777, 0.275,
0.5215250619933, 0.61980400005209,
0.64678627651808, 0.275,
0.76999411666921, 0.275,
0.60269884777111, 0.73463521816969,
0.44035674587458, 0.73463521816969)
ctx:closePath():style(fg):stroke()
-- '2'
ctx:beginPath()
ctx:moveTo(0.92679577564592, 0.33745757758451)
ctx:curveTo(0.95, 0.37544661222032,
0.9486097413556, 0.42890103900541, 0.91866073788306, 0.46581025262318)
ctx:curveTo(0.87662774067075, 0.51761178520021,
0.84865149155459, 0.52351773004551, 0.8188709443895, 0.55088574387747)
ctx:lineTo(0.93798338878322, 0.55088574387747)
ctx:lineTo(0.93798338878322, 0.61972641362727)
ctx:lineTo(0.68857649440815, 0.61972641362727)
ctx:curveTo(0.70410821191941, 0.57897193773781,
0.71568706655441, 0.55649255812279, 0.73505227967577, 0.53436493734023)
ctx:curveTo(0.78431409785481, 0.47807598612821,
0.88073913173375, 0.44149338929647, 0.87483180798279, 0.39074363998918)
ctx:curveTo(0.8731729385169, 0.37649219041461,
0.86900905711197, 0.34385128732334, 0.80655313421425, 0.34385128732334)
ctx:lineTo(0.7834998081023, 0.34385128732334)
ctx:lineTo(0.80849192152801, 0.275)
ctx:curveTo(0.88098903540187, 0.275,
0.90879494370618, 0.30798728419169, 0.92679577564592, 0.33745757758451)
ctx:closePath():style(fg):stroke()
ctx:pop()
end
function once(n, control, notify, seq, forge)
render(0, forge)
render()
-- define single parameter
local graph = Parameter({
[RDFS.label] = 'Graph',
[RDFS.comment] = 'Canvas of graph as atom:Tuple',
[RDFS.range] = Atom.Tuple,
[RDF.value] = ctx:read()
})
local aspect = Parameter({
[RDFS.label] = 'AspectRatio',
[RDFS.comment] = 'Aspect ratio of canvas graph',
[RDFS.range] = Atom.Float,
[LV2.minimum] = 0.25,
[LV2.maximum] = 4.0,
[RDF.value] = 2.0
})
-- define a StateResponder object
local stateR = StateResponder({
[Patch.readable] = {
[Canvas.graph] = graph
},
[Patch.writable] = {
[Canvas.aspectRatio] = aspect
}
})
-- register parameters to UI
function once(n, control, notify)
stateR:register(0, notify)
end
function run(n, control, notify)
for frames, atom in control:foreach() do -- iterate over incoming events
local handled = stateR(frames, notify, atom)
end
end"""
] .
......
......@@ -2094,7 +2094,7 @@ do
local n = {0.125, 0.25, 0.375, 0.5, 0.625, 0.75}
local function producer(forge)
for ctx in forge:time(0):graph(subj, seqn):autopop() do
for ctx in forge:time(0):tuple():autopop() do
ctx:beginPath()
ctx:closePath()
ctx:arc(table.unpack(n, 1, 5))
......@@ -2119,6 +2119,7 @@ do
ctx:reset()
ctx:fontSize(table.unpack(n, 1, 1))
ctx:fillText('hello')
ctx:polyLine(table.unpack(n, 1, 4))
end
end
......@@ -2139,19 +2140,10 @@ do
local function consumer(seq)
assert(#seq == 1)
local set = seq[1]
assert(set.type == Atom.Object)
assert(set.otype == Patch.Set)
assert(#set == 4)
assert(set[Patch.subject].body == subj)
assert(set[Patch.sequenceNumber].body == seqn)
assert(set[Patch.property].body == Canvas.graph)
local graph = set[Patch.value]
local graph = seq[1]
assert(graph)
assert(graph.type == Atom.Tuple)
assert(#graph == 24)
assert(#graph == 25)
local beginPath = graph[1]
check_canvas_object(beginPath, Canvas.BeginPath)
......@@ -2272,6 +2264,11 @@ do
body = itm[Canvas.body]
assert(body.type == Atom.String)
assert(body.body == 'hello')
itm = graph[25]
check_canvas_object(itm, Canvas.PolyLine)
body = itm[Canvas.body]
check_canvas_vector(body, 4)
end
test(producer, consumer)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment