smallpond

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/smallpond
Log | Files | Refs

commit 9a7d9432a68e27dcd8ed9c65becac4c763891acf
parent 3c5a952dd157d81e0d644a2fd3accb84d70f60b0
Author: Nihal Jere <nihal@nihaljere.xyz>
Date:   Wed,  7 Sep 2022 15:03:32 -0500

add basic stem drawing

Diffstat:
Mmain.c | 31+++++++++++++++++++++++--------
Msmallpond.lua | 63+++++++++++++++++++++++++++++++++++++++++++++------------------
2 files changed, 68 insertions(+), 26 deletions(-)

diff --git a/main.c b/main.c @@ -18,6 +18,7 @@ cairo_font_face_t *cface; int draw_line(lua_State *L) { + double t = lua_tonumber(L, -5); double x1 = lua_tonumber(L, -4); double y1 = lua_tonumber(L, -3); double x2 = lua_tonumber(L, -2); @@ -27,7 +28,7 @@ draw_line(lua_State *L) cairo_move_to(cr, x1, y1); cairo_line_to(cr, x2, y2); - cairo_set_line_width(cr, 1); + cairo_set_line_width(cr, t); cairo_stroke(cr); return 0; @@ -36,26 +37,38 @@ draw_line(lua_State *L) int draw_glyph(lua_State *L) { - unsigned int glyph = lua_tonumber(L, -3); + unsigned int val = lua_tonumber(L, -3); double x = lua_tonumber(L, -2); double y = lua_tonumber(L, -1); - int index = FT_Get_Char_Index(face, glyph); - cairo_glyph_t treble_clef = {index, x, y}; - - cairo_text_extents_t extents; - cairo_glyph_extents(cr, &treble_clef, 1, &extents); + int index = FT_Get_Char_Index(face, val); + cairo_glyph_t glyph = {index, x, y}; cairo_set_font_face(cr, cface); cairo_set_font_size(cr, 32.0); cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); - cairo_show_glyphs(cr, &treble_clef, 1); + cairo_show_glyphs(cr, &glyph, 1); return 0; } int +glyph_extents(lua_State *L) +{ + unsigned int val = lua_tonumber(L, -1); + cairo_text_extents_t extents; + int index = FT_Get_Char_Index(face, val); + cairo_glyph_t glyph = {index, 0, 0}; + cairo_glyph_extents(cr, &glyph, 1, &extents); + + lua_pushnumber(L, extents.width); + lua_pushnumber(L, extents.height); + + return 2; +} + +int main(int argc, char *argv[]) { lua_State *L = luaL_newstate(); @@ -64,6 +77,8 @@ main(int argc, char *argv[]) lua_setglobal(L, "draw_glyph"); lua_pushcfunction(L, draw_line); lua_setglobal(L, "draw_line"); + lua_pushcfunction(L, glyph_extents); + lua_setglobal(L, "glyph_extents"); FT_Library library; int error = FT_Init_FreeType(&library); diff --git a/smallpond.lua b/smallpond.lua @@ -1,7 +1,12 @@ -- parse local em = 8 -local noteheadBlock = 0xE0A4 +local Glyph = { + ["noteheadWhole"] = 0xE0A2, + ["noteheadHalf"] = 0xE0A3, + ["noteheadBlack"] = 0xE0A4 +} + local gClef = 0xE050 local fClef = 0xE062 local numerals = { @@ -19,6 +24,7 @@ local numerals = { local treble = { glyph = gClef, + yoff = 3*em, place = function(char) local NOTES = "abcdefg" local s, _ = string.find(NOTES, char) @@ -28,6 +34,7 @@ local treble = { local bass = { glyph = fClef, + yoff = em, place = function(char) local NOTES = "abcdefg" local s, _ = string.find(NOTES, char) @@ -74,10 +81,10 @@ function parse(text) return data end - local s, e, note = string.find(text, "^([abcdefg])", i) + local s, e, note, count = string.find(text, "^([abcdefg])([1248]?)", i) if note then i = i + e - s + 1 - return {command="newnote", note=note} + return {command="newnote", note=note, count=tonumber(count)} end error("unknown token") @@ -86,13 +93,27 @@ end f = assert(io.open("score.sp")) -local x = 10 +local time = 0 -- time in increments of denom staff = {} command_dispatch = { newnote = function(data) local i = staff.clef.place(data.note) - table.insert(staff, {kind="notehead", x=x, y=(em*i) / 2}) - x = x + 20 + if data.count == 1 then + table.insert(staff, {kind="notehead", glyph="noteheadWhole", time=time, y=(em*i) / 2}) + elseif data.count == 2 then + local head = {kind="notehead", glyph="noteheadHalf", time=time, y=(em*i) / 2} + table.insert(staff, head) + table.insert(staff, {kind="stem", head=head}) + elseif data.count == 4 then + local head = {kind="notehead", glyph="noteheadBlack", time=time, y=(em*i) / 2} + table.insert(staff, head) + table.insert(staff, {kind="stem", head=head}) + elseif data.count == 8 then + table.insert(staff, {kind="notehead", glyph="noteheadBlack", time=time, y=(em*i) / 2}) + else + error("oops") + end + time = time + data.count * 10 end, changeclef = function(data) if data.kind == "treble" then @@ -102,11 +123,9 @@ command_dispatch = { staff.clef = bass table.insert(staff, {kind="clef", class=bass, x=x, y=em}) end - x = x + 40 end, changetime = function(data) table.insert(staff, {kind="time", x=x, y=em, num=data.num, denom=data.denom}) - x = x + 30 end } @@ -116,23 +135,31 @@ for tok in parse(f:read("*a")) do end -- determine staff width, the +20 is a hack, should be determined from notehead width + some padding -local staff_width = staff[#staff].x + 20 local yoffset = 20 local xoffset = 20 - --- draw staff -for y=0,em*4,em do - draw_line(xoffset, y + yoffset, staff_width + xoffset, y + yoffset) -end +local x = 10 +local lasttime = 0 for i, el in ipairs(staff) do if el.kind == "notehead" then - draw_glyph(noteheadBlock, xoffset + el.x, yoffset + el.y) + draw_glyph(Glyph[el.glyph], xoffset + x, yoffset + el.y) + el.x = x + x = x + (el.time - lasttime) + lasttime = el.time + elseif el.kind == "stem" then + draw_line(1, el.head.x + xoffset + 0.5, yoffset + el.head.y + .188*em, el.head.x + xoffset + 0.5, el.head.y + yoffset + 3.5*em) elseif el.kind == "clef" then - draw_glyph(el.class.glyph, xoffset + el.x, yoffset + el.y) + draw_glyph(el.class.glyph, xoffset + x, yoffset + el.y) + x = x + 30 elseif el.kind == "time" then -- TODO: draw multidigit time signatures properly - draw_glyph(numerals[el.num], xoffset + el.x, yoffset + el.y) - draw_glyph(numerals[el.denom], xoffset + el.x, yoffset + el.y + 2*em) + draw_glyph(numerals[el.num], xoffset + x, yoffset + el.y) + draw_glyph(numerals[el.denom], xoffset + x, yoffset + el.y + 2*em) + x = x + 30 end end + +-- draw staff +for y=0,em*4,em do + draw_line(1, xoffset, y + yoffset, x + xoffset, y + yoffset) +end