% 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 . % % The beams of most sharps have horizontal endings (as if drawn with % a square pen). [Wanske] does not mention this, so we'll just ignore % this fact. % save default_width, default_height, onestemmed_height; save default_interbeam_dist, triples_interbeam_dist; save default_beam_thickness, stem_thickness; default_width# := 1.1 staff_space#; default_height# := 3 staff_space#; onestemmed_height# := 2.66 staff_space#; define_pixels (default_width); default_interbeam_dist := 1.05 staff_space_rounded; triples_interbeam_dist := 1.2 staff_space_rounded; default_beam_thickness# := 0.3 staff_space# + stafflinethickness#; stem_thickness# := stafflinethickness# + .05 staff_space#; define_whole_blacker_pixels (stem_thickness); def draw_sharp_beam (expr xcenter, length, y_offset) = save ne_beam_dir, nw_dist; pair ne_beam_dir, nw_dist; clearxy; pickup pencircle scaled 2 blot_diameter; % use a fractional pixel value to get a uniform slant... define_pixels (default_beam_thickness); ne_beam_dir = unitvector (length, default_beam_thickness); nw_dist = (ne_beam_dir rotated 90) * blot_diameter; rt x2 - lft x1 = length; z2 = z1 + whatever * ne_beam_dir; .5 [z1, z3] = (xcenter, y_offset); x3 = x2; % ... but use an integer pixel value for actually drawing the beam define_whole_vertical_blacker_pixels (default_beam_thickness); top y2 - bot y3 = default_beam_thickness; x4 = x1; top y1 - bot y4 = default_beam_thickness; % shift beam vertically to be aligned with the pixel grid y1 := good.y (y1); y2 := good.y (y2); y3 := good.y (y3); y4 := good.y (y4); fill lft z1{up} ... (z1 + nw_dist){ne_beam_dir} -- (z2 + nw_dist){ne_beam_dir} ... rt z2{down} -- rt z3{down} ... (z3 - nw_dist){-ne_beam_dir} -- (z4 - nw_dist){-ne_beam_dir} ... lft z4{up} -- cycle; labels (1, 2, 3, 4); enddef; def draw_sharp (expr arrowup, arrowdown, figured_bass) = save depth, height, width; save dist_between_stems, offset; save outer_space; save half_height, interbeam_dist, stem_correction; save beam_length, beam_xcenter; dist_between_stems# := 7 / 16 * default_width#; define_whole_pixels (dist_between_stems); outer_space# := .5 (default_width# - dist_between_stems# - stem_thickness#); define_whole_pixels (outer_space); width# := 2 outer_space# + dist_between_stems# + stem_thickness#; if figured_bass: % The next two lines are global assignments; we use these values % for other figured bass accidentals, too. (This works because % `draw_sharp` is called only once with `figured_bass` set to % true.) figbass_y# := dist_between_stems# / width# * default_beam_thickness#; figbass_width# := width#; half_height# := .5 number_design_size + figbass_y#; offset# := .5 number_design_size; % The stems for the text variant are much shorter; additionally, % the top and bottom end parts of the stems are half-circles, % contrary to the top and bottom parts of the natural and the flat % glyph. We thus slightly increase the stem lengths to let them % stick out of the bounding box. stem_correction := .5 stem_thickness; else: half_height# := .5 default_height#; offset# := 0; stem_correction := 0; fi; define_pixels (half_height, offset); depth# := half_height# - offset#; height# := half_height# + offset#; beam_length := 2 outer_space + dist_between_stems + stem_thickness; beam_xcenter := .5 beam_length; if arrowup: % synchronized with point z4 of the arrow height# := half_height# - .5 stem_thickness# % y8 + .1 staff_space# + .5 stafflinethickness# + .5 stem_thickness# % upshift + .85 staff_space# + stafflinethickness#; % htip fi; if arrowdown: % synchronized with point z4 of the arrow depth# := half_height# - .5 stem_thickness# % y5 + .1 staff_space# + .5 stafflinethickness# + .5 stem_thickness# % upshift + .85 staff_space# + stafflinethickness#; % htip fi; set_char_box (0, width#, depth#, height#); d := d - feta_space_shift; if figured_bass: interbeam_dist := .9 default_interbeam_dist; else: interbeam_dist := default_interbeam_dist; fi; draw_sharp_beam (beam_xcenter, beam_length, -.5 interbeam_dist + offset); draw_sharp_beam (beam_xcenter, beam_length, -.5 interbeam_dist + offset + vround interbeam_dist); pickup pencircle scaled stem_thickness; lft x5 = lft x6 = outer_space; lft x7 = lft x8 = outer_space + dist_between_stems; bot y5 = -(half_height + stem_correction) + offset; top y8 = half_height + stem_correction + offset; z6 = z8 + whatever * ne_beam_dir; bot y7 - offset = -(top y6 - offset) + feta_space_shift; fill lft z7{down} .. bot z7{right} .. rt z7{up} if arrowup: -- draw_arrow (z8, stem_thickness, up, stafflinethickness / 2 + stem_thickness / 2, false) else: -- rt z8{up} .. top z8{left} .. lft z8{down} fi -- cycle; fill rt z6{up} .. top z6{left} .. lft z6{down} if arrowdown: -- draw_arrow (z5, stem_thickness, up, stafflinethickness / 2 + stem_thickness / 2, true) else: -- lft z5{down} .. bot z5{right} .. rt z5{up} fi -- cycle; labels (5, 6, 7, 8); draw_staff_if_debugging (-2, 2); enddef; fet_beginchar ("sharp", "sharp"); draw_sharp (false, false, false); fet_endchar; fet_beginchar ("figured bass sharp", "sharp.figbass"); draw_sharp (false, false, true); fet_endchar; fet_beginchar ("arrowed sharp (arrow up)", "sharp.arrowup"); draw_sharp (true, false, false); fet_endchar; fet_beginchar ("arrowed sharp (arrow down)", "sharp.arrowdown"); draw_sharp (false, true, false); fet_endchar; fet_beginchar ("arrowed sharp (arrows up and down)", "sharp.arrowboth"); draw_sharp (true, true, false); fet_endchar; fet_beginchar ("1/2 sharp", "sharp.slashslash.stem"); save width; save outer_space; save half_height, interbeam_dist; save beam_length, beam_xcenter; half_height# := .5 onestemmed_height#; define_pixels (half_height); outer_space# := .5 (.7 staff_space# - stem_thickness#); define_whole_pixels (outer_space); width# := 2 outer_space# + stem_thickness#; beam_length := 2 outer_space + stem_thickness; beam_xcenter := .5 beam_length; set_char_box (0, width#, half_height#, half_height#); d := d - feta_space_shift; interbeam_dist := default_interbeam_dist; draw_sharp_beam (beam_xcenter, beam_length, -.5 interbeam_dist); draw_sharp_beam (beam_xcenter, beam_length, -.5 interbeam_dist + vround interbeam_dist); pickup pencircle scaled stem_thickness; lft x5 = lft x6 = outer_space; top y6 = half_height; bot y5 = -top y6 + feta_space_shift; draw_gridline (z5, z6, stem_thickness); labels (5, 6); draw_staff_if_debugging (-2, 2); fet_endchar; fet_beginchar ("sharp (3 beams)", "sharp.slashslashslash.stemstem"); save width; save dist_between_stems; save outer_space; save half_height, interbeam_dist; save default_beam_thickness; save beam_length, beam_xcenter; half_height# := .5 default_height#; define_pixels (half_height); dist_between_stems# := 7 / 16 * default_width#; define_whole_pixels (dist_between_stems); outer_space# := .5 (default_width# - dist_between_stems# - stem_thickness#); define_whole_pixels (outer_space); width# := 2 outer_space# + dist_between_stems# + stem_thickness#; beam_length := 2 outer_space + dist_between_stems + stem_thickness; beam_xcenter := .5 beam_length; set_char_box (0, width#, half_height#, half_height#); d := d - feta_space_shift; interbeam_dist := triples_interbeam_dist; default_beam_thickness# := .22 staff_space# + stafflinethickness#; draw_sharp_beam (beam_xcenter, .88 beam_length, -.5 interbeam_dist); draw_sharp_beam (beam_xcenter, .88 beam_length, -.5 interbeam_dist + vround interbeam_dist); default_beam_thickness# := 1/.88 default_beam_thickness#; draw_sharp_beam (beam_xcenter, beam_length, 0); pickup pencircle scaled stem_thickness; lft x5 = lft x6 = outer_space; lft x7 = lft x8 = outer_space + dist_between_stems; bot y5 = -half_height; top y8 = half_height; z6 = z8 + whatever * ne_beam_dir; bot y7 = -top y6 + feta_space_shift; draw_gridline (z5, z6, stem_thickness); draw_gridline (z7, z8, stem_thickness); labels (5, 6, 7, 8); draw_staff_if_debugging (-2, 2); fet_endchar; fet_beginchar ("1/2 sharp (3 beams)", "sharp.slashslashslash.stem"); save width; save outer_space; save half_height, interbeam_dist; save default_beam_thickness; save beam_length, beam_xcenter; half_height# := .5 onestemmed_height#; define_pixels (half_height); outer_space# := .5 (.95 staff_space# - stem_thickness#); define_whole_pixels (outer_space); width# := 2 outer_space# + stem_thickness#; beam_length := 2 outer_space + stem_thickness; beam_xcenter := .5 beam_length; set_char_box (0, width#, half_height#, half_height#); d := d - feta_space_shift; interbeam_dist := triples_interbeam_dist; default_beam_thickness# := .22 staff_space# + stafflinethickness#; draw_sharp_beam (beam_xcenter, .8 beam_length, -.5 interbeam_dist); draw_sharp_beam (beam_xcenter, .8 beam_length, -.5 interbeam_dist + vround interbeam_dist); default_beam_thickness# := 1/.8 default_beam_thickness#; draw_sharp_beam (beam_xcenter, beam_length, 0); pickup pencircle scaled stem_thickness; lft x5 = lft x6 = outer_space; top y6 = half_height; bot y5 = -top y6 + feta_space_shift; draw_gridline (z5, z6, stem_thickness); labels (5, 6); draw_staff_if_debugging (-2, 2); fet_endchar; fet_beginchar ("1/2 sharp (1 beam)", "sharp.slash.stem"); save width; save outer_space; save half_height, interbeam_dist; save beam_length, beam_xcenter; half_height# := .5 onestemmed_height#; define_pixels (half_height); outer_space# := .5 (.95 staff_space# - stem_thickness#); define_whole_pixels (outer_space); width# := 2 outer_space# + stem_thickness#; beam_length := 2 outer_space + stem_thickness; beam_xcenter := .5 beam_length; set_char_box (0, width#, half_height#, half_height#); d := d - feta_space_shift; draw_sharp_beam (beam_xcenter, beam_length, 0); pickup pencircle scaled stem_thickness; lft x5 = lft x6 = outer_space; top y6 = half_height; bot y5 = -top y6 + feta_space_shift; draw_gridline (z5, z6, stem_thickness); labels (5, 6); draw_staff_if_debugging (-2, 2); fet_endchar; fet_beginchar ("3/4 sharp", "sharp.slashslash.stemstemstem"); save width; save dist_between_stems; save outer_space; save half_height, interbeam_dist; save beam_length, beam_xcenter; half_height# := 0.5 default_height#; define_pixels (half_height); dist_between_stems# := 9 / 32 * 1.6 staff_space#; define_whole_pixels (dist_between_stems); outer_space# := .5 (1.6 staff_space# - 2 dist_between_stems# - stem_thickness#); define_whole_pixels (outer_space); width# := 2 outer_space# + 2 dist_between_stems# + stem_thickness#; beam_length := 2 outer_space + 2 dist_between_stems + stem_thickness; beam_xcenter := .5 beam_length; set_char_box (0, width#, half_height#, half_height#); d := d - feta_space_shift; interbeam_dist := default_interbeam_dist; draw_sharp_beam (beam_xcenter, beam_length, -.5 interbeam_dist); draw_sharp_beam (beam_xcenter, beam_length, -.5 interbeam_dist + vround interbeam_dist); pickup pencircle scaled stem_thickness; lft x5 = lft x6 = outer_space; lft x9 = lft x10 = outer_space + dist_between_stems; lft x7 = lft x8 = outer_space + 2 dist_between_stems; bot y5 = -half_height; top y8 = half_height; z6 = z8 + whatever * ne_beam_dir; bot y7 = -top y6 + feta_space_shift; y9 = .5 [y5, y7]; y10 = .5 [y6, y8]; draw_gridline (z5, z6, stem_thickness); draw_gridline (z7, z8, stem_thickness); draw_gridline (z9, z10, stem_thickness); labels (5, 6, 7, 8, 9, 10); draw_staff_if_debugging (-2, 2); fet_endchar; def draw_double_sharp (expr figured_bass) = save depth, height, width; save klaverblad, klaversteel; save glyph_height, offset; save pat; path pat; klaversteel = 1/15 staff_space; klaverblad = .4 staff_space - .5 stafflinethickness; if figured_bass: width# := figbass_width#; offset# := .5 number_design_size; else: width# := staff_space#; offset# := 0; fi; define_pixels (offset); glyph_height# := .5 width#; define_whole_vertical_blacker_pixels (glyph_height); depth# := glyph_height# - offset#; height# := glyph_height# + offset#; set_char_box (0, width#, depth#, height#); z1 = (klaversteel, 0); z2 = (w / 2 - klaverblad / 10, glyph_height - klaverblad); z3 = (w / 2, glyph_height); z4 = z2 reflectedabout ((0, 0), (1, 1)); z5 = z1 reflectedabout ((0, 0), (1, 1)); pickup pencircle scaled blot_diameter; x2 := hfloor (rt x2) - blot_diameter / 2; x3 := hfloor (rt x3) - blot_diameter / 2; y3 := vfloor (top y3) - blot_diameter / 2; y4 := vfloor (top y4) - blot_diameter / 2; pat = (rt z1){dir45} .. {right}(bot z2) .. rt z2 -- rt z3{z3 - z2} .. top z3{z4 - z3} -- top z4{z4 - z3} .. (lft z4){down} .. {dir 225}(top z5); pat := pat -- reverse pat xscaled -1 shifted (-feta_eps, 0); % assure symmetry -- it's more important to center the glyph on the % staff line than centering it between staff lines, so we use % feta_shift, not feta_space_shift. h := h + feta_shift; fill pat shifted (0, feta_shift) -- reverse pat yscaled -1 shifted (0, -feta_eps) -- cycle; % ugh currentpicture := currentpicture shifted (hround (w / 2), vround (offset)); labels (1, 2, 3, 4, 5); draw_staff_if_debugging (-2, 2); enddef; fet_beginchar ("double sharp", "doublesharp"); draw_double_sharp (false); fet_endchar; fet_beginchar ("figured bass double sharp", "doublesharp.figbass"); draw_double_sharp (true); fet_endchar;