% Feta (not the Font-En-Tja) music font -- Accidentals % This file is part of LilyPond, the GNU music typesetter. % % Copyright (C) 1997--2022 Han-Wen Nienhuys % Copyright (C) 2013--2022 Janek WarchoĊ‚ % % The LilyPond font is free software: you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation, either version 3 of the License, or % (at your option) any later version, or you can redistribute it under % the SIL Open Font License. % % LilyPond 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 % GNU General Public License for more details. % % You should have received a copy of the GNU General Public License % along with LilyPond. If not, see . % % Dedicated to my mom. (3/10/97) % % Mamma, ik hou van je; kom je alsjeblieft terug? % -- HW % % % TODO: remove crook_fatness % TODO: document, simplify! % def draw_meta_flat (expr xcenter, glyph_width, crook_fatness, arrowup, arrowdown, smaller_hole, figured_bass) = save x_offset, y_offset; save crook_thinness; save bottom_overshoot, bot_crook_dir; save top_stem_thick, top_stem_thick_orig; save bottom_stem_thick, hair, hole_adjustment; save top_crook_thinness; save zwiep; pair bot_crook_dir; save clearing, clearing_orig; clearxy; % the stem shouldn't reach the top staff line. %% TODO: should take from height. if smaller_hole: hole_adjustment = 0; else: hole_adjustment = 0.35 stafflinethickness; fi; crook_thinness = .7 stafflinethickness + .06 staff_space; top_crook_thinness = 1 stafflinethickness + .065 staff_space; clearing = 1.7 stafflinethickness; clearing_orig = clearing; if arrowup: clearing := 0.5 staff_space; fi; bottom_overshoot = stafflinethickness; bottom_stem_thick# = 0.06 staff_space# + 0.6 stafflinethickness#; top_stem_thick# = 0.1 staff_space# + 1.2 stafflinethickness#; top_stem_thick_orig# = top_stem_thick#; if arrowup: % to look nice, arrowed stems should be less brushed top_stem_thick# := top_stem_thick# * 0.8; fi; define_whole_blacker_pixels (bottom_stem_thick, top_stem_thick, top_stem_thick_orig); if odd (top_stem_thick - bottom_stem_thick): top_stem_thick := top_stem_thick - 1; fi; if odd (top_stem_thick_orig - bottom_stem_thick): top_stem_thick_orig := top_stem_thick_orig - 1; fi; if figured_bass: % left-align if xcenter = -1: x_offset := hround (.5 top_stem_thick); % right-align elseif xcenter = 1: x_offset := hround (w - glyph_width); % center else: x_offset := hround ((w - glyph_width) / 2 + .25 top_stem_thick); fi; else: x_offset := xcenter; fi; % z16 and the `*_orig' variables are needed for arrowed accidentals % because their inner part should be unchanged from plain ones but % the points z3l, z3r, and z10 depend on values that are different % for arrowed accidentals x1l = hround (x_offset - .5 top_stem_thick); x2l = hround (x_offset - .5 bottom_stem_thick); x16l = hround (x_offset - .5 top_stem_thick_orig); if figured_bass: y1 = y16 = h; y2 = 0; y_offset := .5 (staff_space + stafflinethickness) + bottom_overshoot - d; else: y1 = vround (2 staff_space - clearing); y2 = -.5 (staff_space + stafflinethickness); y16 = vround (2 staff_space - clearing_orig); y_offset := 0; fi; penpos1 (top_stem_thick, 0); penpos16 (top_stem_thick_orig, 0); penpos2 (bottom_stem_thick, 0); y3l = vfloor (.5 (staff_space - stafflinethickness) + y_offset); z3l = whatever [z2r, z1r]; z3r = .3 [z2r, (z16r shifted (0, clearing_orig - 1.7 stafflinethickness))] + (hole_adjustment, 0); x3r := hceiling x3r; % we insert z3l to get better conversion with mf2pt1 fill simple_serif (z1r, z1l, 30) -- z2l -- z2r -- z3l -- cycle; z10 = whatever [z2r, z16r] + (hole_adjustment, 0); y10 = -1/10 staff_space + y_offset; x10 := hceiling x10; x11 = x_offset + bottom_overshoot / 3; y11 = -vround (.5 (staff_space + stafflinethickness) + bottom_overshoot - y_offset); x2a = 0.2[x2r, x7]; y2a = 1.5[y2, y11]; penpos4 (whatever, 53); y4l - y4r = top_crook_thinness; y5r = .15 staff_space + y_offset; x5l = hround (glyph_width + x_offset); y4 = staff_space / 2 + y_offset; x4r = .45 [x5r, x3r]; y4l := vround y4l; penpos5 (crook_fatness, -175); bot_crook_dir = unitvector ((x5l, y_offset) - z11); z8 = z11 + whatever * bot_crook_dir; y8 = -staff_space / 2 + y_offset; z7 = z8 + whatever * bot_crook_dir + crook_thinness * (bot_crook_dir rotated 90); x7 = .1 [x3r, x8]; unfill z3r{z3r - z10} .. z4r{right} .. z5r{down} .. z7{-bot_crook_dir} & z7 .. z10{z3r - z10} -- cycle; if arrowdown: fill z2l{down} .. z2a{up} .. z8{bot_crook_dir} .. z5l{up} .. z4l{left} .. z3l -- cycle; else: fill z2l{down} .. z11{right} .. z8{bot_crook_dir} .. z5l{up} .. z4l{left} .. z3l -- cycle; fi; if arrowup: fill draw_arrow (z1, top_stem_thick, z1l - z2l, 0.5 stafflinethickness, false) -- cycle; fi; if arrowdown: fill draw_arrow ((0.5 [x2l, x2a], y2), x2a - x2l, up, staff_space / 2, true) -- cycle; fi; enddef; def draw_arrowed_meta_flat (expr arrowup, arrowdown, figured_bass) = save width, depth, height, breapth; save glyph_width; if figured_bass: width# := figbass_width#; % synchronized with vertical position of point z11 but with less overshoot depth# := figbass_y#; % synchronized with vertical position of point z1 height# := number_design_size + figbass_y#; breapth# := 0; glyph_width# := 0.7 width#; else: width# := 0.8 staff_space#; % synchronized with vertical position of point z11 but with less overshoot depth# := 0.5 staff_space# + 1.3 stafflinethickness#; % synchronized with vertical position of point z1 height# := 2 staff_space# - 1.7 stafflinethickness#; breapth# := 1.2 stafflinethickness#; glyph_width# := width#; fi; define_whole_pixels (glyph_width); if arrowup: % synchronized with point z4 of the arrow height# := 2 staff_space# - .5 staff_space# % y1 + .1 staff_space# + .5 stafflinethickness# % upshift + .85 staff_space# + stafflinethickness#; % htip breapth# := .3 staff_space#; fi; if arrowdown: % synchronized with point z4 of the arrow depth# := .5 staff_space# + .5 stafflinethickness# % y2 + .1 staff_space# + .5 staff_space# % upshift + .85 staff_space# + stafflinethickness#; % htip breapth# := .3 staff_space#; fi; set_char_box (breapth#, width#, depth#, height#); draw_meta_flat (0, glyph_width, 0.31 staff_space, arrowup, arrowdown, false, figured_bass); enddef; % % unfortunately, 600dpi is not enough to show the brush of the stem. % fet_beginchar ("flat", "flat"); draw_arrowed_meta_flat (false, false, false); penlabels (range 0 thru 16); labels (2a); draw_staff_if_debugging (-2, 2); fet_endchar; fet_beginchar ("figured bass flat", "flat.figbass"); draw_arrowed_meta_flat (false, false, true); penlabels (range 0 thru 16); labels (2a); fet_endchar; fet_beginchar ("arrowed flat (arrow up)", "flat.arrowup"); draw_arrowed_meta_flat (true, false, false); penlabels (range 0 thru 23); labels (2a); draw_staff_if_debugging (-2, 2); fet_endchar; fet_beginchar ("arrowed flat (arrow down)", "flat.arrowdown"); draw_arrowed_meta_flat (false, true, false); penlabels (range 0 thru 23); labels (2a); draw_staff_if_debugging (-2, 2); fet_endchar; fet_beginchar ("arrowed flat (arrow up and down)", "flat.arrowboth"); draw_arrowed_meta_flat (true, true, false); penlabels (range 0 thru 23); labels (2a); draw_staff_if_debugging (-2, 2); fet_endchar; fet_beginchar ("flat (slashed)", "flat.slash"); save depth, height; depth# := 0.5 staff_space# + 1.3 stafflinethickness#; height# := 2 staff_space# - 1.7 stafflinethickness#; % use same value for breapth as for arrowed flats set_char_box (.3 staff_space#, .8 staff_space#, depth#, height#); draw_meta_flat (0, w, 0.31 staff_space, false, false, false, false); clearxy; save slope, slash_width; slope = 0.5; slash_width = w; z11 = (0, staff_space_rounded); z12 = z11 - (slash_width, slash_width * slope) / 2; z13 = z11 + (slash_width, slash_width * slope) / 2; penpos12 (1.5 stafflinethickness, angle (z13 - z12) - 90); penpos13 (1.5 stafflinethickness, angle (z13 - z12) - 90); z14 = z12 - .75 stafflinethickness * unitvector (z13 - z12); z15 = z13 + .75 stafflinethickness * unitvector (z13 - z12); fill z13r .. z15 .. z13l -- z12l .. z14 .. z12r -- z13r .. cycle; penlabels (12, 13); labels (11, 14, 15); draw_staff_if_debugging (-2, 2); fet_endchar; fet_beginchar ("flat (slashed twice)", "flat.slashslash"); save depth, height; depth# := 0.5 staff_space# + 1.3 stafflinethickness#; height# := 2 staff_space# - 1.7 stafflinethickness#; % use same value for breapth as for arrowed flats set_char_box (.3 staff_space#, .8 staff_space#, depth#, height#); draw_meta_flat (0, w, 0.31 staff_space, false, false, false, false); clearxy; save slope, slash_width, slash_distance; slope = 0.5; slash_width = w; slash_distance = vround (.5 staff_space_rounded); z11 = (0, staff_space_rounded - .5 slash_distance); z12 = z11 - (slash_width, slash_width * slope) / 2; z13 = z11 + (slash_width, slash_width * slope) / 2; penpos12 (1.5 stafflinethickness, angle (z13 - z12) - 90); penpos13 (1.5 stafflinethickness, angle (z13 - z12) - 90); z14 = z12 - .75 stafflinethickness * unitvector (z13 - z12); z15 = z13 + .75 stafflinethickness * unitvector (z13 - z12); fill z13r .. z15 .. z13l -- z12l .. z14 .. z12r -- z13r .. cycle; penlabels (12, 13); labels (11, 14, 15); z21 = (0, staff_space_rounded + .5 slash_distance); z22 = z21 - (slash_width, slash_width * slope) / 2; z23 = z21 + (slash_width, slash_width * slope) / 2; penpos22 (1.5 stafflinethickness, angle (z23 - z22) - 90); penpos23 (1.5 stafflinethickness, angle (z23 - z22) - 90); z24 = z22 - .75 stafflinethickness * unitvector (z23 - z22); z25 = z23 + .75 stafflinethickness * unitvector (z23 - z22); fill z23r .. z25 .. z23l -- z22l .. z24 .. z22r -- z23r .. cycle; penlabels (22, 23); labels (21, 24, 25); draw_staff_if_debugging (-2, 2); fet_endchar; fet_beginchar ("flatflat (mirrored)", "mirroredflat.flat"); save depth, height; depth# := 0.5 staff_space# + 1.3 stafflinethickness#; height# := 2 staff_space# - 1.7 stafflinethickness#; set_char_box (0, 1.6 staff_space#, depth#, height#); % This is a modified version of `draw_meta_flat'. save crook_thinness, crook_fatness; save bottom_overshoot, bot_crook_dir; save top_stem_thick, bottom_stem_thick, hair, hole_adjustment; save top_crook_thinness; save zwiep; pair bot_crook_dir; save clearing, wid; save mirror_offset; save pat; path pat; clearxy; wid = w / 2; % the stem shouldn't reach the top staff line. %% TODO: should take from height. hole_adjustment = 0.35 stafflinethickness; clearing = 1.7 stafflinethickness; crook_thinness = .7 stafflinethickness + .06 staff_space; crook_fatness = 0.31 staff_space; top_crook_thinness = 1 stafflinethickness + .065 staff_space; bottom_overshoot = stafflinethickness; bottom_stem_thick# = 0.06 staff_space# + 0.6 stafflinethickness#; top_stem_thick# = 0.1 staff_space# + 1.2 stafflinethickness#; define_whole_blacker_pixels (bottom_stem_thick, top_stem_thick); if odd (top_stem_thick - bottom_stem_thick): top_stem_thick := top_stem_thick - 1; fi; if odd top_stem_thick: mirror_offset := 1; else: mirror_offset := 0; fi; x1l = hround (-.5 top_stem_thick); y1 = vround (2 staff_space - clearing); x2l = hround (-.5 bottom_stem_thick); y2 = -.5 staff_space - .5 stafflinethickness; penpos1 (top_stem_thick, 0); penpos2 (bottom_stem_thick, 0); y3l = vfloor ((staff_space - stafflinethickness) / 2); z3l = whatever [z2r, z1r]; z3r = .3 [z2r, z1r] + (hole_adjustment, 0); x3r := hceiling x3r; z10 = whatever [z2r, z1r] + (hole_adjustment, 0); y10 = -1/10 staff_space; x10 := hceiling x10; x11 = bottom_overshoot / 3; y11 = -vround (.5 (staff_space + stafflinethickness) + bottom_overshoot); penpos4 (whatever, 53); y4l - y4r = top_crook_thinness; y5r = .15 staff_space; x5l = hround (wid); y4 = staff_space / 2; x4r = .45 [x5r, x3r]; y4l := vround y4l; penpos5 (crook_fatness, -175); bot_crook_dir = unitvector ((x5l, 0) - z11); z8 = z11 + whatever * bot_crook_dir; y8 = -staff_space / 2; z7 = z8 + whatever * bot_crook_dir + crook_thinness * (bot_crook_dir rotated 90); x7 = .1 [x3r, x8]; pat := z3r{z3r - z10} .. z4r{right} .. z5r{down} .. z7{-bot_crook_dir} & z7 .. z10{z3r - z10} -- cycle; unfill pat; unfill pat xscaled -1; pat := z11{right} .. z8{bot_crook_dir} .. z5l{up} .. z4l{left} .. z3l; fill pat -- simple_serif (z1r, z1l, 30) -- reverse pat xscaled -1 shifted (-feta_eps + mirror_offset, 0) -- cycle; currentpicture := currentpicture shifted (w/2, 0); draw_staff_if_debugging (-2, 2); fet_endchar; fet_beginchar ("semi flat", "mirroredflat"); save depth, height; depth# := 0.5 staff_space# + 1.3 stafflinethickness#; height# := 2 staff_space# - 1.7 stafflinethickness#; set_char_box (1.2 stafflinethickness#, .8 staff_space#, depth#, height#); draw_meta_flat (0, w, 0.31 staff_space, false, false, false, false); currentpicture := currentpicture xscaled -1 shifted (w - b, 0); draw_staff_if_debugging (-2, 2); fet_endchar; fet_beginchar ("semi flat (slashed)", "mirroredflat.backslash"); save depth, height; depth# := 0.5 staff_space# + 1.3 stafflinethickness#; height# := 2 staff_space# - 1.7 stafflinethickness#; set_char_box (.4 staff_space#, .8 staff_space#, depth#, height#); draw_meta_flat (0, w, 0.31 staff_space, false, false, false, false); clearxy; save slope, slash_width; slope = 0.5; slash_width = w; z11 = (0, vround (h / 2)); z12 = z11 - (slash_width, slash_width * slope) / 2; z13 = z11 + (slash_width, slash_width * slope) / 2; penpos12 (1.5 stafflinethickness, angle (z13 - z12) - 90); penpos13 (1.5 stafflinethickness, angle (z13 - z12) - 90); z14 = z12 - .75 stafflinethickness * unitvector (z13 - z12); z15 = z13 + .75 stafflinethickness * unitvector (z13 - z12); fill z13r .. z15 .. z13l -- z12l .. z14 .. z12r -- z13r .. cycle; currentpicture := currentpicture xscaled -1 shifted (w - b, 0); labels (1, 2, 3); draw_staff_if_debugging (-2, 2); fet_endchar; fet_beginchar ("double flat", "flatflat"); save depth, height; save left_wid, overlap, right_wid; depth# := 0.5 staff_space# + 1.3 stafflinethickness#; height# := 2 staff_space# - 1.7 stafflinethickness#; left_wid = .7; right_wid = .8; overlap = .05; set_char_box (1.2 stafflinethickness#, (left_wid + right_wid - overlap) * staff_space#, depth#, height#); draw_meta_flat (0, left_wid * staff_space, 1/3 staff_space, false, false, true, false); draw_meta_flat (hround ((left_wid - overlap) * staff_space), right_wid * staff_space, 1/3 staff_space, false, false, false, false); draw_staff_if_debugging (-2, 2); fet_endchar; fet_beginchar ("figured bass double flat", "flatflat.figbass"); save depth, height; save left_wid, right_wid, extra_wid; depth# := figbass_y#; height# := number_design_size + figbass_y#; left_wid := .65; right_wid := .75; extra_wid := .1; define_pixels (figbass_width); set_char_box (0, (left_wid + right_wid + extra_wid) * figbass_width#, depth#, height#); draw_meta_flat (-1, left_wid * figbass_width, 1/3 staff_space, false, false, true, true); draw_meta_flat (1, right_wid * figbass_width, 1/3 staff_space, false, false, false, true); fet_endchar; fet_beginchar ("3/4 flat", "flatflat.slash"); save depth, height; save left_wid, overlap, right_wid; depth# := 0.5 staff_space# + 1.3 stafflinethickness#; height# := 2 staff_space# - 1.7 stafflinethickness#; left_wid = .7; right_wid = .8; overlap = .05; set_char_box (0.45 staff_space#, (left_wid + right_wid - overlap) * staff_space#, depth#, height#); draw_meta_flat (0, left_wid * staff_space, 1/3 staff_space, false, false, true, false); draw_meta_flat (hround ((left_wid - overlap) * staff_space), right_wid * staff_space, 1/3 staff_space, false, false, false, false); %% maybe we should clip part of the stems? %% or make the 1st flat smaller? %% or reverse it? pickup pencircle scaled 2 stafflinethickness; z12 = round (-.53 staff_space, .55 staff_space) + feta_offset; z13 = round (.75 w, 1.45 staff_space) + feta_offset; penpos12 (2 stafflinethickness, angle (z13 - z12) - 90); penpos13 (2 stafflinethickness, angle (z13 - z12) - 90); z14 = z12 - stafflinethickness * unitvector (z13 - z12); z15 = z13 + stafflinethickness * unitvector (z13 - z12); fill z13r .. z15 .. z13l -- z12l .. z14 .. z12r -- z13r .. cycle; penlabels (12, 13); labels (14, 15); draw_staff_if_debugging (-2, 2); fet_endchar;