From af7da386c206a537fdc77a07431851b9545480a4 Mon Sep 17 00:00:00 2001 From: Carl Sorensen Date: Mon, 5 Apr 2010 22:42:54 -0600 Subject: [PATCH] Add improved shape note support Add Christian Harmony, Sacred Harp, and Southern Harmony styles Add variable-thickness open note shapes to the shape note font Change the starting character value for the Feta font to accomodate the extra characters. Add new commands to base shape note scale degrees on the relative major. Add regression tests for various note styles. Update docs to reflect new settings. Move noteheads to separate sub-font to allow space for shape note heads --- Documentation/included/font-table.ly | 2 +- Documentation/notation/pitches.itely | 44 +- input/regression/note-head-aiken.ly | 15 + input/regression/note-head-sacred-harp.ly | 15 + input/regression/note-head-shape-minor.ly | 18 + input/regression/note-head-solfa.ly | 2 +- .../regression/note-head-southern-harmony.ly | 15 + ly/property-init.ly | 9 +- mf/GNUmakefile | 11 + mf/bigcheese.pe.in | 1 + mf/feta-autometric.mf | 2 +- mf/feta-generic.mf | 5 +- mf/feta-noteheads-generic.mf | 56 +++ mf/feta-noteheads-test-generic.mf | 6 + mf/feta-noteheads.mf | 430 ++++++++++++++---- mf/feta-noteheads11.mf | 13 + mf/feta-noteheads13.mf | 13 + mf/feta-noteheads14.mf | 13 + mf/feta-noteheads16.mf | 13 + mf/feta-noteheads18.mf | 13 + mf/feta-noteheads20.mf | 13 + mf/feta-noteheads23.mf | 13 + mf/feta-noteheads26.mf | 13 + mf/feta-test-generic.mf | 1 - 24 files changed, 643 insertions(+), 93 deletions(-) create mode 100644 input/regression/note-head-aiken.ly create mode 100644 input/regression/note-head-sacred-harp.ly create mode 100644 input/regression/note-head-shape-minor.ly create mode 100644 input/regression/note-head-southern-harmony.ly create mode 100644 mf/feta-noteheads-generic.mf create mode 100644 mf/feta-noteheads-test-generic.mf create mode 100644 mf/feta-noteheads11.mf create mode 100644 mf/feta-noteheads13.mf create mode 100644 mf/feta-noteheads14.mf create mode 100644 mf/feta-noteheads16.mf create mode 100644 mf/feta-noteheads18.mf create mode 100644 mf/feta-noteheads20.mf create mode 100644 mf/feta-noteheads23.mf create mode 100644 mf/feta-noteheads26.mf diff --git a/Documentation/included/font-table.ly b/Documentation/included/font-table.ly index 3bdb80a6c8..3a5f6ebd88 100644 --- a/Documentation/included/font-table.ly +++ b/Documentation/included/font-table.ly @@ -63,7 +63,7 @@ (define shape-note-noteheads (get-group glyph-list - "^noteheads.[dsu][012](do|re|mi|fa|sol|la|ti)$")) + "^noteheads.[dsu][012](do|re|mi|fa|sol|la|ti)(Thin|Mirror)*$")) (define clefs (get-group glyph-list "^clefs\\.")) (define timesig (get-group glyph-list "^timesig\\.")) diff --git a/Documentation/notation/pitches.itely b/Documentation/notation/pitches.itely index 31af761a7e..7e33d7a91c 100644 --- a/Documentation/notation/pitches.itely +++ b/Documentation/notation/pitches.itely @@ -2681,33 +2681,65 @@ Internals Reference: @cindex shape notes @cindex Aiken shape note heads @cindex sacred harp note heads +@cindex note heads, Southern Harmony +@cindex Southern Harmony note heads -@funindex \key -@funindex key @funindex \aikenHeads @funindex aikenHeads @funindex \sacredHarpHeads @funindex sacredHarpHeads +@funindex \southernHarmonyHeads +@funindex southernHarmonyHeads In shape note head notation, the shape of the note head corresponds to the harmonic function of a note in the scale. This notation was popular in nineteenth-century American song books. -Shape note heads can be produced: +Shape note heads can be produced in Sacred Harp, Southern Harmony, +and Aiken (Christian Harmony) styles: @lilypond[verbatim,quote,relative=2] \aikenHeads -c, d e f g a b c +c, d e f g2 a b1 c \break \sacredHarpHeads -c, d e f g a b c +c,4 d e f g2 a b1 c \break +\southernHarmonyHeads +c,4 d e f g2 a b1 c \break @end lilypond +@funindex \key +@funindex key +@funindex \aikenHeadsMinor +@funindex aikenHeadsMinor +@funindex \sacredHarpHeadsMinor +@funindex sacredHarpHeadsMinor +@funindex \southernHarmonyHeadsMinor +@funindex southernHarmonyHeadsMinor + Shapes are typeset according to the step in the scale, where the base of the scale is determined by the @code{\key} command. +When when writing in a minor key, the scale step can be determined +from the relative major: + +@lilypond[verbatim,quote,relative=2] +\key a \minor +\aikenHeads +a b c d e2 f g1 a \break +\aikenHeadsMinor +a,4 b c d e2 f g1 a \break +\sacredHarpHeadsMinor +a,2 b c d \break +\southernHarmonyHeadsMinor +a2 b c d \break +@end lilypond @predefined @code{\aikenHeads}, -@code{\sacredHarpHeads}. +@code{\aikenHeadsMinor}, +@code{\sacredHarpHeads}, +@code{\sacredHarpHeadsMinor}, +@code{\southernHarmonyHeads}, +@code{\southernHarmonyHeadsMinor}. @endpredefined diff --git a/input/regression/note-head-aiken.ly b/input/regression/note-head-aiken.ly new file mode 100644 index 0000000000..30134ffa46 --- /dev/null +++ b/input/regression/note-head-aiken.ly @@ -0,0 +1,15 @@ +\header { + + texidoc = "Notes can be set in the Aiken (Christian Harmony) style." + +} +\version "2.12.0" + +\relative c' { + \key c \major + \aikenHeads + c1 d e f g a b c d e f g a b c + c,,2 d e f g a b c d e f g a b c + c,,4 d e f g a b c d e f g a b c +} + diff --git a/input/regression/note-head-sacred-harp.ly b/input/regression/note-head-sacred-harp.ly new file mode 100644 index 0000000000..fdd2eb108f --- /dev/null +++ b/input/regression/note-head-sacred-harp.ly @@ -0,0 +1,15 @@ +\header { + + texidoc = "Notes can be set in the Sacred Harp style." + +} +\version "2.12.0" + +\relative c' { + \key c \major + \sacredHarpHeads + c1 d e f g a b c d e f g a b c + c,,2 d e f g a b c d e f g a b c + c,,4 d e f g a b c d e f g a b c +} + diff --git a/input/regression/note-head-shape-minor.ly b/input/regression/note-head-shape-minor.ly new file mode 100644 index 0000000000..d7356d3e82 --- /dev/null +++ b/input/regression/note-head-shape-minor.ly @@ -0,0 +1,18 @@ +\header { + + texidoc = "Shape notes can be set to work properly in minor keys." + +} +\version "2.12.0" + +\relative c' { + \key c \major + \sacredHarpHeads + c2^"C major" d | e f | g a | b c | + \key a \minor + \sacredHarpHeadsMinor + a2^"A minor" b | c d | e f | g a | + \sacredHarpHeads + c,,2^"A minor with major heads" d | e f | g a | b c | +} + diff --git a/input/regression/note-head-solfa.ly b/input/regression/note-head-solfa.ly index b4d24ca852..d6b163dfcb 100644 --- a/input/regression/note-head-solfa.ly +++ b/input/regression/note-head-solfa.ly @@ -9,7 +9,7 @@ to the @code{tonic} property." fragment = { \key c \major - \set shapeNoteStyles = #'#(do re mi fa #f la ti) + \set shapeNoteStyles = #'#(do re mi fa sol la ti) c1 d e f g a b c d e f g a b c c,,2 d e f g a b c d e f g a b c c,,4 d e f g a b c d e f g a b c diff --git a/input/regression/note-head-southern-harmony.ly b/input/regression/note-head-southern-harmony.ly new file mode 100644 index 0000000000..3e20a018bc --- /dev/null +++ b/input/regression/note-head-southern-harmony.ly @@ -0,0 +1,15 @@ +\header { + + texidoc = "Notes can be set in the Southern Harmony style." + +} +\version "2.12.0" + +\relative c' { + \key c \major + \southernHarmonyHeads + c1 d e f g a b c d e f g a b c + c,,2 d e f g a b c d e f g a b c + c,,4 d e f g a b c d e f g a b c +} + diff --git a/ly/property-init.ly b/ly/property-init.ly index 4238dd14e0..0b1f2a2ea7 100644 --- a/ly/property-init.ly +++ b/ly/property-init.ly @@ -342,8 +342,15 @@ predefinedFretboardsOn = %% shape note heads -aikenHeads = \set shapeNoteStyles = #'#(do re mi fa sol la ti) +aikenHeads = \set shapeNoteStyles = #'#(do re miMirror fa sol la ti) +aikenHeadsMinor = \set shapeNoteStyles = #'#(la ti do re miMirror fa sol) sacredHarpHeads = \set shapeNoteStyles = #'#(fa sol la fa sol la mi) +sacredHarpHeadsMinor = \set shapeNoteStyles = #'#(la mi fa sol la fa sol) +southernHarmonyHeads = + \set shapeNoteStyles = #'#(faThin sol laThin faThin sol laThin miThin) +southernHarmonyHeadsMinor = + \set shapeNoteStyles = #'#(laThin miThin faThin sol laThin faThin sol) + %% shifts diff --git a/mf/GNUmakefile b/mf/GNUmakefile index 956c8fa47c..329d673bfb 100644 --- a/mf/GNUmakefile +++ b/mf/GNUmakefile @@ -16,6 +16,7 @@ EXTRA_DIST_FILES += README mf2pt1.mp FETA_MF_FILES = $(call src-wildcard,feta[0-9]*.mf) \ $(call src-wildcard,feta-braces-[a-z].mf) \ $(call src-wildcard,feta-alphabet*[0-9].mf) \ + $(call src-wildcard,feta-notehead*[0-9].mf) \ $(call src-wildcard,parmesan[0-9]*.mf) STAFF_SIZES = 11 13 14 16 18 20 23 26 @@ -61,6 +62,7 @@ $(outdir)/emmentaler-brace.otf-gtable: $(BRACES:%=$(outdir)/feta-braces-%.otf-gt $(outdir)/emmentaler-%.otf \ $(outdir)/emmentaler-%.svg: $(outdir)/emmentaler-%.pe \ $(outdir)/feta%.pfb \ + $(outdir)/feta-noteheads%.pfb \ $(outdir)/feta-alphabet%.pfb \ $(outdir)/parmesan%.pfb \ $(outdir)/feta%.otf-table \ @@ -77,32 +79,41 @@ $(outdir)/%.pfb: $(outdir)/%.log $(outdir)/%.otf-table: $(outdir)/%.lisp cat $< $(if $(findstring brace,$<),,$(subst feta,parmesan,$<)) \ + $(if $(findstring brace,$<),,$(subst feta,feta-noteheads,$<)) \ $(if $(findstring brace,$<),,$(subst feta,feta-alphabet,$<)) > $@ ## ugh -- we want this to prevent failing -j2 compiles. $(outdir)/feta26.otf-table: $(outdir)/feta26.lisp \ + $(outdir)/feta-noteheads26.lisp \ $(outdir)/parmesan26.lisp \ $(outdir)/feta-alphabet26.lisp $(outdir)/feta23.otf-table: $(outdir)/feta23.lisp \ + $(outdir)/feta-noteheads23.lisp \ $(outdir)/parmesan23.lisp \ $(outdir)/feta-alphabet23.lisp $(outdir)/feta20.otf-table: $(outdir)/feta20.lisp \ + $(outdir)/feta-noteheads23.lisp \ $(outdir)/parmesan20.lisp \ $(outdir)/feta-alphabet20.lisp $(outdir)/feta18.otf-table: $(outdir)/feta18.lisp \ + $(outdir)/feta-noteheads18.lisp \ $(outdir)/parmesan18.lisp \ $(outdir)/feta-alphabet18.lisp $(outdir)/feta16.otf-table: $(outdir)/feta16.lisp \ + $(outdir)/feta-noteheads16.lisp \ $(outdir)/parmesan16.lisp \ $(outdir)/feta-alphabet16.lisp $(outdir)/feta14.otf-table: $(outdir)/feta14.lisp \ + $(outdir)/feta-noteheads14.lisp \ $(outdir)/parmesan14.lisp \ $(outdir)/feta-alphabet14.lisp $(outdir)/feta13.otf-table: $(outdir)/feta13.lisp \ + $(outdir)/feta-noteheads13.lisp \ $(outdir)/parmesan13.lisp \ $(outdir)/feta-alphabet13.lisp $(outdir)/feta11.otf-table: $(outdir)/feta11.lisp \ + $(outdir)/feta-noteheads11.lisp \ $(outdir)/parmesan11.lisp \ $(outdir)/feta-alphabet11.lisp diff --git a/mf/bigcheese.pe.in b/mf/bigcheese.pe.in index 46b74f0abf..e1d1843ba4 100644 --- a/mf/bigcheese.pe.in +++ b/mf/bigcheese.pe.in @@ -10,6 +10,7 @@ New(); SetFontNames("bigcheese20", "LilyPond", "LilyPond BigCheese 20", "20", "GNU GPL", "@TOPLEVEL_VERSION@"); MergeFonts("feta20.pfa"); +MergeFonts("feta-noteheads20.pfa"); MergeFonts("parmesan20.pfa"); # load nummer/din after setting PUA. diff --git a/mf/feta-autometric.mf b/mf/feta-autometric.mf index b77e4827db..c5c7e4836d 100644 --- a/mf/feta-autometric.mf +++ b/mf/feta-autometric.mf @@ -196,7 +196,7 @@ enddef; % -% we leave the ctrl characters alone. +% we leave the ctrl characters alone % code := 32; diff --git a/mf/feta-generic.mf b/mf/feta-generic.mf index 5006b1f99d..3472715e16 100644 --- a/mf/feta-generic.mf +++ b/mf/feta-generic.mf @@ -2,7 +2,7 @@ % This file is part of LilyPond, the GNU music typesetter. % % Copyright (C) 1997--2010 Han-Wen Nienhuys -% +% % % LilyPond is free software: you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by @@ -38,12 +38,11 @@ black_notehead_width# := 1.0 staff_space#; fet_beginfont ("feta", design_size, "fetaMusic"); -if test = 0: +if test = 0: input feta-rests; input feta-accidentals; input feta-arrowheads; input feta-dots; - input feta-noteheads; input feta-scripts; input feta-flags; input feta-clefs; diff --git a/mf/feta-noteheads-generic.mf b/mf/feta-noteheads-generic.mf new file mode 100644 index 0000000000..89de7d06a2 --- /dev/null +++ b/mf/feta-noteheads-generic.mf @@ -0,0 +1,56 @@ +% Feta (not the Font-En-Tja) music font -- generic stuff: include lots of files, but don't +% This file is part of LilyPond, the GNU music typesetter. +% +% Copyright (C) 1997--2010 Han-Wen Nienhuys +% +% +% LilyPond 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. +% +% 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 . + + +if test = -1: + mode := smoke; +fi + +staffsize# := design_size * pt#; + +mode_setup; + +input feta-macros; + +input feta-params; + +font_x_height staff_space#; + +%% this is a fallback so we can run the font without +%% including feta-noteheads. +black_notehead_width# := 1.0 staff_space#; + + +fet_beginfont ("feta", design_size, "fetaMusic"); + +if test = 0: + input feta-noteheads; +else: + input feta-noteheads-test-generic.mf; +fi + +autometric_parameter ("staffsize", staffsize#); +autometric_parameter ("stafflinethickness", stafflinethickness#); +autometric_parameter ("staff_space", staff_space#); +autometric_parameter ("linethickness", linethickness#); +autometric_parameter ("black_notehead_width", black_notehead_width#); +autometric_parameter ("ledgerlinethickness", ledgerlinethickness#); +autometric_parameter ("blot_diameter", blot_diameter#); + +fet_endfont; diff --git a/mf/feta-noteheads-test-generic.mf b/mf/feta-noteheads-test-generic.mf new file mode 100644 index 0000000000..7baeb9b29d --- /dev/null +++ b/mf/feta-noteheads-test-generic.mf @@ -0,0 +1,6 @@ +% +% test stuff. +% in a separate file to avoid tainting non-test font files for testing. +% + +input feta-noteheads; diff --git a/mf/feta-noteheads.mf b/mf/feta-noteheads.mf index c413eac33e..8b7068ed1f 100644 --- a/mf/feta-noteheads.mf +++ b/mf/feta-noteheads.mf @@ -13,11 +13,11 @@ % % 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 +% 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 . +% along with LilyPond. If not, see . test_outlines := 0; @@ -1004,7 +1004,7 @@ fi; % save solfa_pen_thick; -solfa_pen_thick# = 1.75 stafflinethickness#; +solfa_pen_thick# = 1.3 stafflinethickness#; define_blacker_pixels (solfa_pen_thick); @@ -1015,17 +1015,25 @@ solfa_whole_width := 1.0; solfa_half_width := 1.0; solfa_quarter_width := 1.0; -def draw_do_head (expr width_factor, dir) = +def draw_do_head (expr width_factor, dir, thickness_factor) = save p_in, p_out; - save left_dist, right_dist; + save left_dist, right_dist, bottom_dist; path p_in, p_out; - pair left_dist, right_dist; + pair left_dist, right_dist, bottom_dist; set_char_box (0, width_factor * solfa_base_notewidth#, 0.5 solfa_noteheight#, 0.5 solfa_noteheight#); pickup pencircle scaled solfa_pen_thick; + + bottom_thick_factor := thickness_factor; + % no different thickness for left side if we want uniform thickness + left_thick_factor := if thickness_factor = 1 : + 1; + else : + 0.7 * thickness_factor; + fi bot y1 = -d; y1 = y2; lft x1 = 0; @@ -1035,14 +1043,25 @@ def draw_do_head (expr width_factor, dir) = left_dist = (unitvector (z3 - z1) rotated 90) * 0.5 solfa_pen_thick; right_dist = (unitvector (z2 - z3) rotated 90) * 0.5 solfa_pen_thick; + bottom_dist = (0,1) * 0.5 solfa_pen_thick; - p_in := (((z1 - left_dist) -- (z3 - left_dist)) intersectionpoint - (top z1 -- top z2)) - -- ((top z1 -- top z2) intersectionpoint - ((z2 - right_dist) -- (z3 - right_dist))) - -- (((z2 - right_dist) -- (z3 - right_dist)) intersectionpoint - ((z1 - left_dist) -- (z3 - left_dist))) - -- cycle; + save pa, pb, pc; + path pa, pb, pc; + save point_a, point_b, point_c; + pair point_a, point_b, point_c; + + pa := (z1 - left_thick_factor * left_dist) -- + (z3 - left_thick_factor * left_dist); + pb := (z1 + bottom_thick_factor * bottom_dist) -- + (z2 + bottom_thick_factor * bottom_dist); + pc := (z2 - right_dist) -- (z3 - right_dist); + + + point_a := pa intersectionpoint pb; + point_b := pb intersectionpoint pc; + point_c := pc intersectionpoint pa; + + p_in := point_a -- point_b -- point_c -- cycle; p_out := bot z1 -- bot z2{right} @@ -1055,7 +1074,6 @@ def draw_do_head (expr width_factor, dir) = .. lft z1{down} .. {right}cycle; - labels (1, 2, 3); charwx := charwd; @@ -1067,47 +1085,86 @@ enddef; fet_beginchar ("Whole dohead", "s0do"); - draw_do_head (solfa_whole_width, 1); + draw_do_head (solfa_whole_width, 1, 3.25); fill p_out; unfill p_in; fet_endchar; fet_beginchar ("Half dohead", "d1do"); - draw_do_head (solfa_half_width, -1); + draw_do_head (solfa_half_width, -1, 3.25); fill p_out; unfill p_in; fet_endchar; fet_beginchar ("Half dohead", "u1do"); - draw_do_head (solfa_half_width, 1); + draw_do_head (solfa_half_width, 1, 3.25); fill p_out; unfill p_in; fet_endchar; fet_beginchar ("Quart dohead", "d2do"); - draw_do_head (solfa_quarter_width, -1); + draw_do_head (solfa_quarter_width, -1, 3.25); fill p_out; fet_endchar; fet_beginchar ("Quart dohead", "u2do"); - draw_do_head (solfa_quarter_width, 1); + draw_do_head (solfa_quarter_width, 1, 3.25); + fill p_out; +fet_endchar; + + + +fet_beginchar ("Whole thin dohead", "s0doThin"); + draw_do_head (solfa_whole_width, 1, 1); + fill p_out; + unfill p_in; +fet_endchar; + + +fet_beginchar ("Half thin dohead", "d1doThin"); + draw_do_head (solfa_half_width, -1, 1); + fill p_out; + unfill p_in; +fet_endchar; + + +fet_beginchar ("Half thin dohead", "u1doThin"); + draw_do_head (solfa_half_width, 1, 1); + fill p_out; + unfill p_in; +fet_endchar; + + +fet_beginchar ("Quart thin dohead", "d2doThin"); + draw_do_head (solfa_quarter_width, -1, 1); fill p_out; fet_endchar; +fet_beginchar ("Quart thin dohead", "u2doThin"); + draw_do_head (solfa_quarter_width, 1, 1); + fill p_out; +fet_endchar; + + + % % re - flat top, curved bottom: -% (0,h/2) {dir -90} .. (w/2,-h/2) .. {dir 90} (w,h/2) -- cycle; +% (0,h/2) {dir -90} .. (w/2,-h/2) .. {dir 90} (w,h/2) -- cycle; % (broader along the base and with more vertical sides for half and % whole notes) +% +% Note: According to some shape-note singers, there should be no size +% differences for half and whole notes, contrary to the comment above +% % stem attachment: h/2 % -def draw_re_head (expr width_factor, dir) = +def draw_re_head (expr width_factor, dir, thickness_factor) = save p_in, p_out; path p_in, p_out; @@ -1116,6 +1173,7 @@ def draw_re_head (expr width_factor, dir) = pickup pencircle scaled solfa_pen_thick; + save curve_start; curve_start = 0.7; lft x1 = 0; @@ -1131,11 +1189,11 @@ def draw_re_head (expr width_factor, dir) = labels (range 1 thru 5); - p_in := (z1 + 0.5 solfa_pen_thick * (1, -1)) + p_in := (z1 + 0.5 solfa_pen_thick * (1, -1 * thickness_factor)) -- rt z2{down} - .. top z3 + .. ((top z3) + (0, thickness_factor * 0.5 solfa_pen_thick)) .. lft z4{up} - -- (z5 + 0.5 solfa_pen_thick * (-1, -1)) + -- (z5 + 0.5 solfa_pen_thick * (-1, -1 * thickness_factor)) -- cycle; p_out := lft z1 @@ -1157,43 +1215,84 @@ enddef; fet_beginchar ("Whole rehead", "s0re"); - draw_re_head (solfa_whole_width, 1); + draw_re_head (solfa_whole_width, 1, 2.5); fill p_out; unfill p_in; fet_endchar; fet_beginchar ("Half up rehead", "u1re"); - draw_re_head (solfa_half_width, 1); + draw_re_head (solfa_half_width, 1, 2.5); fill p_out; unfill p_in; fet_endchar; fet_beginchar ("Half down rehead", "d1re"); - draw_re_head (solfa_half_width, -1); + draw_re_head (solfa_half_width, -1, 2.5); fill p_out; unfill p_in; fet_endchar; fet_beginchar ("Quart rehead", "u2re"); - draw_re_head (solfa_quarter_width, 1); + draw_re_head (solfa_quarter_width, 1, 2.5); fill p_out; fet_endchar; fet_beginchar ("Quart rehead", "d2re"); - draw_re_head (solfa_quarter_width, -1); + draw_re_head (solfa_quarter_width, -1, 2.5); fill p_out; fet_endchar; -def draw_mi_head (expr width_factor) = +fet_beginchar ("Whole thin rehead", "s0reThin"); + draw_re_head (solfa_whole_width, 1, 1); + fill p_out; + unfill p_in; +fet_endchar; + + +fet_beginchar ("Half up thin rehead", "u1reThin"); + draw_re_head (solfa_half_width, 1, 1); + fill p_out; + unfill p_in; +fet_endchar; + + +fet_beginchar ("Half down thin rehead", "d1reThin"); + draw_re_head (solfa_half_width, -1, 1); + fill p_out; + unfill p_in; +fet_endchar; + + +fet_beginchar ("Quart thin rehead", "u2reThin"); + draw_re_head (solfa_quarter_width, 1, 1); + fill p_out; +fet_endchar; + + +fet_beginchar ("Quart thin rehead", "d2reThin"); + draw_re_head (solfa_quarter_width, -1, 1); + fill p_out; +fet_endchar; + + + + +%%%% mi head -- diamond shape + +def draw_mi_head (expr width_factor, thickness_factor, mirror) = save path_out, path_in; save ne_dist, se_dist, ne, se; + save path_a, path_b, path_c, path_d; path path_out, path_in; pair ne_dist, se_dist, ne, se; + path path_a, path_b, path_c, path_d; + save inner_path; + path inner_path; set_char_box (0, width_factor * solfa_base_notewidth#, 0.5 solfa_noteheight#, 0.5 solfa_noteheight#); @@ -1209,6 +1308,7 @@ def draw_mi_head (expr width_factor) = y3 = y1; top y4 = h; + % inner sides are parallel to outer sides z6 - z5 = whatever * (z2 - z1); z8 - z7 = whatever * (z2 - z1); z8 - z5 = whatever * (z4 - z1); @@ -1220,19 +1320,30 @@ def draw_mi_head (expr width_factor) = ne_dist = (ne rotated 90) * 0.5 solfa_pen_thick; se_dist = (se rotated 90) * 0.5 solfa_pen_thick; - z5 = whatever [z1, z4] - ne_dist; - z5 = whatever [z1, z2] - 1.5 se_dist; + path_a := (z1 - se_dist) -- (z2 - se_dist); + path_b := (z2 + (ne_dist * thickness_factor)) -- + (z3 + (ne_dist * thickness_factor)); + path_c := (z3 + se_dist) -- (z4 + se_dist); + path_d := (z4 - (ne_dist * thickness_factor)) -- + (z1 - (ne_dist * thickness_factor)); - z5 - z1 = -(z7 - z3); + z5 = path_a intersectionpoint path_d; + z7 = path_b intersectionpoint path_c; labels (range 1 thru 8); - path_in := z5 + inner_path := z5 -- z6 -- z7 -- z8 -- cycle; + path_in := if mirror: + inner_path; + else: + inner_path reflectedabout (z2, z4); + fi + path_out := lft z1 .. (z1 + se_dist){-se} -- (z2 + se_dist){-se} @@ -1250,31 +1361,75 @@ enddef; fet_beginchar ("Whole mihead", "s0mi"); - draw_mi_head (solfa_whole_width); + draw_mi_head (solfa_whole_width, 3, false); fill path_out; unfill path_in; fet_endchar; fet_beginchar ("Half mihead", "s1mi"); - draw_mi_head (solfa_quarter_width); + draw_mi_head (solfa_quarter_width, 3, false); fill path_out; unfill path_in; fet_endchar; - fet_beginchar ("Quart mihead", "s2mi"); - draw_mi_head (solfa_quarter_width); + draw_mi_head (solfa_quarter_width, 3, false); fill path_out; fet_endchar; -def draw_fa_head (expr width_factor) = + +fet_beginchar ("Whole mirror mihead", "s0miMirror"); + draw_mi_head (solfa_whole_width, 3, true); + fill path_out; + unfill path_in; +fet_endchar; + +fet_beginchar ("Half mirror mihead", "s1miMirror"); + draw_mi_head (solfa_quarter_width, 3, true); + fill path_out; + unfill path_in; +fet_endchar; + +fet_beginchar ("Quart mirror mihead", "s2miMirror"); + draw_mi_head (solfa_quarter_width, 3, true); + fill path_out; +fet_endchar; + + + +fet_beginchar ("Whole thin mihead", "s0miThin"); + draw_mi_head (solfa_whole_width, 1, false); + fill path_out; + unfill path_in; +fet_endchar; + + +fet_beginchar ("Half thin mihead", "s1miThin"); + draw_mi_head (solfa_quarter_width, 1, false); + fill path_out; + unfill path_in; +fet_endchar; + + +fet_beginchar ("Quart thin mihead", "s2miThin"); + draw_mi_head (solfa_quarter_width, 1, false); + fill path_out; +fet_endchar; + + + +%%%% fa head + +def draw_fa_head (expr width_factor, thickness_factor) = set_char_box (0, width_factor * solfa_base_notewidth#, 0.5 solfa_noteheight#, 0.5 solfa_noteheight#); save p_down_in, p_down_out, p_up_in, p_up_out, nw_dist, nw; path p_down_in, p_down_out, p_up_in, p_up_out; + save path_a, path_b, path_c; + path path_a, path_b, path_c; pair nw_dist, nw; pickup pencircle scaled solfa_pen_thick; @@ -1295,12 +1450,16 @@ def draw_fa_head (expr width_factor) = nw = unitvector (z1 - z3); nw_dist = (nw rotated 90) * 0.5 solfa_pen_thick; - p_up_in := (((z1 - nw_dist) -- (z3 - nw_dist)) intersectionpoint - (bot z1 -- bot z2)) - -- (((z1 - nw_dist) -- (z3 - nw_dist)) intersectionpoint - (lft z3 -- lft z2)) - -- (z2 + 0.5 solfa_pen_thick * (-1, -1)) - -- cycle; + path_a := (z1 - (0,1) * thickness_factor * solfa_pen_thick) -- + (z2 - (0,1) * thickness_factor * solfa_pen_thick); + path_b := (z2 - (1,0) * 0.5 solfa_pen_thick) -- + (z3 - (1,0) * 0.5 solfa_pen_thick); + path_c := (z3 - nw_dist) -- (z1 - nw_dist); + + p_up_in := (path_a intersectionpoint path_b) -- + (path_b intersectionpoint path_c) -- + (path_c intersectionpoint path_a) -- + cycle; p_up_out := lft z1{down} .. (z1 + nw_dist){-nw} @@ -1321,51 +1480,99 @@ enddef; fet_beginchar ("Whole fa up head", "u0fa"); - draw_fa_head (solfa_whole_width); + draw_fa_head (solfa_whole_width, 1.5); fill p_up_out; unfill p_up_in; fet_endchar; fet_beginchar ("Whole fa down head", "d0fa"); - draw_fa_head (solfa_whole_width); + draw_fa_head (solfa_whole_width, 1.5); fill p_down_out; unfill p_down_in; fet_endchar; fet_beginchar ("half fa up head", "u1fa"); - draw_fa_head (solfa_half_width); + draw_fa_head (solfa_half_width, 1.5); fill p_up_out; unfill p_up_in; fet_endchar; fet_beginchar ("Half fa down head", "d1fa"); - draw_fa_head (solfa_half_width); + draw_fa_head (solfa_half_width, 1.5); fill p_down_out; unfill p_down_in; fet_endchar; fet_beginchar ("Quarter fa up head", "u2fa"); - draw_fa_head (solfa_quarter_width); + draw_fa_head (solfa_quarter_width, 1.5); fill p_up_out; fet_endchar; fet_beginchar ("Quarter fa down head", "d2fa"); - draw_fa_head (solfa_quarter_width); + draw_fa_head (solfa_quarter_width, 1.5); + fill p_down_out; +fet_endchar; + + +fet_beginchar ("Whole thin fa up head", "u0faThin"); + draw_fa_head (solfa_whole_width, 1); + fill p_up_out; + unfill p_up_in; +fet_endchar; + + +fet_beginchar ("Whole thin fa down head", "d0faThin"); + draw_fa_head (solfa_whole_width, 1); fill p_down_out; + unfill p_down_in; fet_endchar; +fet_beginchar ("half thin fa up head", "u1faThin"); + draw_fa_head (solfa_half_width, 1); + fill p_up_out; + unfill p_up_in; +fet_endchar; + + +fet_beginchar ("Half thin fa down head", "d1faThin"); + draw_fa_head (solfa_half_width, 1); + fill p_down_out; + unfill p_down_in; +fet_endchar; + + +fet_beginchar ("Quarter thin fa up head", "u2faThin"); + draw_fa_head (solfa_quarter_width, 1); + fill p_up_out; +fet_endchar; + + +fet_beginchar ("Quarter thin fa down head", "d2faThin"); + draw_fa_head (solfa_quarter_width, 1); + fill p_down_out; +fet_endchar; + + + +%%%% sol head +%% +%% Note -- sol head is the same shape as a standard music +%% head, and doesn't vary from style to style. +%% However, width is constant with duration, so we +%% can't just use the standard note font. + def draw_sol_head (expr filled) = draw_outside_ellipse (1.53 - puff_up_factor / 3.0, 34, 0.66, 0.17); - if not filled: + if not filled: undraw_inside_ellipse (3.25, 33, 0.81, 2.5 stafflinethickness#); - fi - draw_staff (-2, 2, 0); + fi + draw_staff (-2, 2, 0); enddef; fet_beginchar ("Whole solhead", "s0sol"); @@ -1384,9 +1591,9 @@ fet_endchar; +%%%% la head - -def draw_la_head (expr width_factor) = +def draw_la_head (expr width_factor, thickness_factor) = set_char_box (0, width_factor * solfa_base_notewidth#, 0.5 solfa_noteheight#, 0.5 solfa_noteheight#); save p_in, p_out; @@ -1407,10 +1614,10 @@ def draw_la_head (expr width_factor) = labels (range 1 thru 4); - p_in := (z1 + 0.5 solfa_pen_thick * (1, -1)) - -- (z2 + 0.5 solfa_pen_thick * (-1, -1)) - -- (z3 + 0.5 solfa_pen_thick * (-1, 1)) - -- (z4 + 0.5 solfa_pen_thick * (1, 1)) + p_in := (z1 + 0.5 solfa_pen_thick * (1, -thickness_factor)) + -- (z2 + 0.5 solfa_pen_thick * (-1, -thickness_factor)) + -- (z3 + 0.5 solfa_pen_thick * (-1, thickness_factor)) + -- (z4 + 0.5 solfa_pen_thick * (1, thickness_factor)) -- cycle; p_out := top z1 @@ -1426,31 +1633,54 @@ enddef; fet_beginchar ("Whole lahead", "s0la"); - draw_la_head (solfa_whole_width); + draw_la_head (solfa_whole_width, 3); fill p_out; unfill p_in; fet_endchar; fet_beginchar ("Half lahead", "s1la"); - draw_la_head (solfa_half_width); + draw_la_head (solfa_half_width, 3); fill p_out; unfill p_in; fet_endchar; fet_beginchar ("Quart lahead", "s2la"); - draw_la_head (solfa_quarter_width); + draw_la_head (solfa_quarter_width, 3); + fill p_out; +fet_endchar; + + +fet_beginchar ("Whole thin lahead", "s0laThin"); + draw_la_head (solfa_whole_width, 1); + fill p_out; + unfill p_in; +fet_endchar; + + +fet_beginchar ("Half thin lahead", "s1laThin"); + draw_la_head (solfa_half_width, 1); + fill p_out; + unfill p_in; +fet_endchar; + + +fet_beginchar ("Quart lahead", "s2laThin"); + draw_la_head (solfa_quarter_width, 1); fill p_out; fet_endchar; -def draw_ti_head (expr width_factor, dir) = + +%%%% ti head + +def draw_ti_head (expr width_factor, dir, thickness_factor) = set_char_box (0, width_factor * solfa_base_notewidth#, 0.5 solfa_noteheight#, 0.5 solfa_noteheight#); - save p_in, p_out, p_top; + save p_in, p_out, p_top, p_top_in; save nw_dist, sw_dist, nw, sw; - path p_in, p_out, p_top; + path p_in, p_out, p_top, p_top_in; pair nw_dist, sw_dist, nw, sw; save cone_height; cone_height = 0.64; @@ -1465,6 +1695,8 @@ def draw_ti_head (expr width_factor, dir) = y4 = y2; x3 = x1; top y3 = h; + x5 = x1; + y5 = y1 + thickness_factor * 0.5 * solfa_pen_thick; labels (range 1 thru 4); @@ -1478,14 +1710,19 @@ def draw_ti_head (expr width_factor, dir) = .. (top z3){right} .. (z4 - nw_dist); - p_in := (((z1 - nw_dist) -- (z2 - nw_dist)) intersectionpoint - ((z1 - sw_dist) -- (z4 - sw_dist))) - -- (((z1 - nw_dist) -- (z2 - nw_dist)) intersectionpoint - ((z2 + sw_dist) .. {right}(bot z3))) - .. bot z3 - .. (((bot z3){right} .. (z4 + nw_dist)) intersectionpoint - ((z1 - sw_dist) -- (z4 - sw_dist))) - -- cycle; + p_top_in := (z2 + sw_dist * thickness_factor) {- sw} + .. ((top z3) - (0,1) * thickness_factor * 0.5 solfa_pen_thick) {right} + .. (z4 + nw_dist * thickness_factor){- nw}; + + save path_a, path_b; + path path_a, path_b; + path_a := z2 -- z5; + path_b := z5 -- z4; + + z6 = path_a intersectionpoint p_top_in; + z7 = path_b intersectionpoint p_top_in; + + p_in := z5 -- z6 .. bot z3 .. z7 -- cycle; p_out := bot z1 .. (z1 + nw_dist) @@ -1508,41 +1745,76 @@ enddef; fet_beginchar ("Whole up tihead", "s0ti"); - draw_ti_head (solfa_whole_width, 1); + draw_ti_head (solfa_whole_width, 1, 3); fill p_out; unfill p_in; fet_endchar; fet_beginchar ("Half up tihead", "u1ti"); - draw_ti_head (solfa_half_width, 1); + draw_ti_head (solfa_half_width, 1, 3); fill p_out; unfill p_in; fet_endchar; fet_beginchar ("Half down tihead", "d1ti"); - draw_ti_head (solfa_half_width, -1); + draw_ti_head (solfa_half_width, -1, 3); fill p_out; unfill p_in; fet_endchar; fet_beginchar ("Quart up tihead", "u2ti"); - draw_ti_head (solfa_quarter_width, 1); + draw_ti_head (solfa_quarter_width, 1, 3); fill p_out; fet_endchar; fet_beginchar ("Quart down tihead", "d2ti"); - draw_ti_head (solfa_quarter_width, -1); + draw_ti_head (solfa_quarter_width, -1, 3); fill p_out; fet_endchar; +fet_beginchar ("Whole thin up tihead", "s0tiThin"); + draw_ti_head (solfa_whole_width, 1, 1); + fill p_out; + unfill p_in; +fet_endchar; + + +fet_beginchar ("Half thin up tihead", "u1tiThin"); + draw_ti_head (solfa_half_width, 1, 1); + fill p_out; + unfill p_in; +fet_endchar; + + +fet_beginchar ("Half thin down tihead", "d1tiThin"); + draw_ti_head (solfa_half_width, -1, 1); + fill p_out; + unfill p_in; +fet_endchar; + + +fet_beginchar ("Quart thin up tihead", "u2tiThin"); + draw_ti_head (solfa_quarter_width, 1, 1); + fill p_out; +fet_endchar; + + +fet_beginchar ("Quart thin down tihead", "d2tiThin"); + draw_ti_head (solfa_quarter_width, -1, 1); + fill p_out; +fet_endchar; + + + fet_endgroup ("noteheads"); + % % we derive black_notehead_width# from the quarter head, % so we have to define black_notehead_width (pixel qty) diff --git a/mf/feta-noteheads11.mf b/mf/feta-noteheads11.mf new file mode 100644 index 0000000000..b02844a196 --- /dev/null +++ b/mf/feta-noteheads11.mf @@ -0,0 +1,13 @@ +% feta-noteheads11.mf +% part of LilyPond's pretty-but-neat music font + +input feta-autometric; + +design_size := 11.22; +test := 0; + + +input feta-noteheads-generic; + +end. + diff --git a/mf/feta-noteheads13.mf b/mf/feta-noteheads13.mf new file mode 100644 index 0000000000..e010769f4b --- /dev/null +++ b/mf/feta-noteheads13.mf @@ -0,0 +1,13 @@ +% feta-noteheads13.mf +% part of LilyPond's pretty-but-neat music font + +input feta-autometric; + +design_size := 12.60; +test := 0; + + +input feta-noteheads-generic; + +end. + diff --git a/mf/feta-noteheads14.mf b/mf/feta-noteheads14.mf new file mode 100644 index 0000000000..7d25cb2a60 --- /dev/null +++ b/mf/feta-noteheads14.mf @@ -0,0 +1,13 @@ +% feta-noteheads14.mf +% part of LilyPond's pretty-but-neat music font + +input feta-autometric; + +design_size := 14.14; +test := 0; + + +input feta-noteheads-generic; + +end. + diff --git a/mf/feta-noteheads16.mf b/mf/feta-noteheads16.mf new file mode 100644 index 0000000000..755f9ffdd5 --- /dev/null +++ b/mf/feta-noteheads16.mf @@ -0,0 +1,13 @@ +% feta-noteheads16.mf +% part of LilyPond's pretty-but-neat music font + +input feta-autometric; + +design_size := 15.87; +test := 0; + + +input feta-noteheads-generic; + +end. + diff --git a/mf/feta-noteheads18.mf b/mf/feta-noteheads18.mf new file mode 100644 index 0000000000..bdc6918bf3 --- /dev/null +++ b/mf/feta-noteheads18.mf @@ -0,0 +1,13 @@ +% feta-noteheads18.mf +% part of LilyPond's pretty-but-neat music font + +input feta-autometric; + +design_size := 17.82; +test := 0; + + +input feta-noteheads-generic; + +end. + diff --git a/mf/feta-noteheads20.mf b/mf/feta-noteheads20.mf new file mode 100644 index 0000000000..072f99207c --- /dev/null +++ b/mf/feta-noteheads20.mf @@ -0,0 +1,13 @@ +% feta-noteheads20.mf +% part of LilyPond's pretty-but-neat music font + +input feta-autometric; + +design_size := 20; +test := 0; + + +input feta-noteheads-generic; + +end. + diff --git a/mf/feta-noteheads23.mf b/mf/feta-noteheads23.mf new file mode 100644 index 0000000000..ab0154832e --- /dev/null +++ b/mf/feta-noteheads23.mf @@ -0,0 +1,13 @@ +% feta-noteheads23.mf +% part of LilyPond's pretty-but-neat music font + +input feta-autometric; + +design_size := 22.45; +test := 0; + + +input feta-noteheads-generic; + +end. + diff --git a/mf/feta-noteheads26.mf b/mf/feta-noteheads26.mf new file mode 100644 index 0000000000..b25d21495c --- /dev/null +++ b/mf/feta-noteheads26.mf @@ -0,0 +1,13 @@ +% feta-noteheads26.mf +% part of LilyPond's pretty-but-neat music font + +input feta-autometric; + +design_size := 25.20; +test := 0; + + +input feta-noteheads-generic; + +end. + diff --git a/mf/feta-test-generic.mf b/mf/feta-test-generic.mf index c18061b15a..00265fc475 100644 --- a/mf/feta-test-generic.mf +++ b/mf/feta-test-generic.mf @@ -6,7 +6,6 @@ %input feta-rests; input feta-accidentals; %input feta-dots; -%input feta-noteheads; %input feta-arrowheads; %input feta-scripts; %input feta-flags; -- 2.39.2