diff options
author | Mike Solomon <mike@apollinemike.com> | 2011-08-27 15:13:25 +0200 |
---|---|---|
committer | Mike Solomon <mike@apollinemike.com> | 2011-08-27 15:13:25 +0200 |
commit | f0978ed121192fee9bdf2453a325d98693148acf (patch) | |
tree | 6a9f9d645204136158ca439262ce038df27af483 | |
parent | e6ccd1c536b89e965e0bde1d298bd9388fb5dea9 (diff) |
Adds a Flag grob to LilyPond.
This results in more flexibility with the control of flags and their
attachment to stems.
It also results in more accurate skylines for horizontal spacing, which
tightens up certain loose spacing situations, especially ones involving
grace notes that are close in pitch to the notes that follow them.
Note that this patch prolongs a problem with the calculations of flag
widths, which are artificially set at a half stem width skinnier than
they are actually. The same problem existed in the old Stem::width
function by using Stem::flag instead of Stem::get_translated_flag
to determine the width of the stem grob. This can be fixed in one
of several ways, but my recommendation would be to fix it in the
Feta font by adjusting the set_char_box for flags.
34 files changed, 391 insertions, 250 deletions
diff --git a/Documentation/learning/tweaks.itely b/Documentation/learning/tweaks.itely index 9f1c5dd0b5..a13fff3fe0 100644 --- a/Documentation/learning/tweaks.itely +++ b/Documentation/learning/tweaks.itely @@ -3466,6 +3466,7 @@ cross voices: << { \once \override Stem #'transparent = ##t + \once \override Flag #'transparent = ##t b8~ b\noBeam } \\ @@ -3481,6 +3482,7 @@ too much, we can lengthen the stem by setting the << { \once \override Stem #'transparent = ##t + \once \override Flag #'transparent = ##t \once \override Stem #'length = #8 b8~ b\noBeam } diff --git a/Documentation/notation/ancient.itely b/Documentation/notation/ancient.itely index fe835fd077..55b4aead72 100644 --- a/Documentation/notation/ancient.itely +++ b/Documentation/notation/ancient.itely @@ -732,7 +732,7 @@ select ancient flags. Besides the @code{default} flag style, only the @code{mensural} style is supported. @lilypond[quote,fragment,ragged-right,verbatim] -\override Stem #'flag-style = #'mensural +\override Flag #'style = #'mensural \override Stem #'thickness = #1.0 \override NoteHead #'style = #'mensural \autoBeamOff @@ -1116,6 +1116,7 @@ Editio Vaticana style do clef \override Staff.StaffSymbol #'color = #red \override Staff.LedgerLineSpanner #'color = #red \override Voice.Stem #'transparent = ##t + \override Voice.Flag #'transparent = ##t \override NoteHead #'style = #'vaticana.punctum \clef "vaticana-do2" c @@ -1131,6 +1132,7 @@ Editio Vaticana style fa clef \override Staff.StaffSymbol #'color = #red \override Staff.LedgerLineSpanner #'color = #red \override Voice.Stem #'transparent = ##t + \override Voice.Flag #'transparent = ##t \override NoteHead #'style = #'vaticana.punctum \clef "vaticana-fa2" c @@ -1147,6 +1149,7 @@ Editio Medicaea style do clef \override Staff.StaffSymbol #'color = #red \override Staff.LedgerLineSpanner #'color = #red \override Voice.Stem #'transparent = ##t + \override Voice.Flag #'transparent = ##t \override NoteHead #'style = #'medicaea.punctum \clef "medicaea-do2" c @@ -1162,6 +1165,7 @@ Editio Medicaea style fa clef \override Staff.StaffSymbol #'color = #red \override Staff.LedgerLineSpanner #'color = #red \override Voice.Stem #'transparent = ##t + \override Voice.Flag #'transparent = ##t \override NoteHead #'style = #'medicaea.punctum \clef "medicaea-fa2" c @@ -1178,6 +1182,7 @@ hufnagel style do clef \override Staff.StaffSymbol #'color = #red \override Staff.LedgerLineSpanner #'color = #red \override Voice.Stem #'transparent = ##t + \override Voice.Flag #'transparent = ##t \override NoteHead #'style = #'hufnagel.punctum \clef "hufnagel-do2" c @@ -1193,6 +1198,7 @@ hufnagel style fa clef \override Staff.StaffSymbol #'color = #red \override Staff.LedgerLineSpanner #'color = #red \override Voice.Stem #'transparent = ##t + \override Voice.Flag #'transparent = ##t \override NoteHead #'style = #'hufnagel.punctum \clef "hufnagel-fa2" c @@ -1207,6 +1213,7 @@ hufnagel style combined do/fa clef \override Staff.StaffSymbol #'color = #red \override Staff.LedgerLineSpanner #'color = #red \override Voice.Stem #'transparent = ##t + \override Voice.Flag #'transparent = ##t \override NoteHead #'style = #'hufnagel.punctum \clef "hufnagel-do-fa" c @@ -2501,7 +2508,9 @@ single-tone recitative to a fixed melodic gesture. In these cases, one can use either @code{\override Stem #'transparent = ##t} or @code{\override Stem #'length = #0} instead, and restore the stem when needed with the corresponding @code{\once \override Stem -#'transparent = ##f} (see example below). +#'transparent = ##f} (see example below). When using stems that +carry flags, make sure to set @code{\override Flag #'transparent += ##t} as well. @b{Timing.} For unmetered chant, there are several alternatives. @@ -2638,6 +2647,7 @@ spirLyr = \lyricmode { \remove "Time_signature_engraver" \override BarLine #'X-extent = #'(-1 . 1) \override Stem #'transparent = ##t + \override Flag #'transparent = ##t \override Beam #'transparent = ##t \override BarLine #'transparent = ##t \override TupletNumber #'transparent = ##t diff --git a/Documentation/notation/changing-defaults.itely b/Documentation/notation/changing-defaults.itely index 0cd9812606..e10986e7cf 100644 --- a/Documentation/notation/changing-defaults.itely +++ b/Documentation/notation/changing-defaults.itely @@ -854,6 +854,7 @@ The notes look like a slash, and have no stem, @example \override NoteHead #'style = #'slash \override Stem #'transparent = ##t +\override Flag #'transparent = ##t @end example All these plug-ins have to cooperate, and this is achieved with a @@ -876,6 +877,7 @@ Put together, we get squashedPosition = #0 \override NoteHead #'style = #'slash \override Stem #'transparent = ##t + \override Flag #'transparent = ##t \alias Voice @} @end example diff --git a/Documentation/notation/keyboards.itely b/Documentation/notation/keyboards.itely index ef294318fb..a7b3394417 100644 --- a/Documentation/notation/keyboards.itely +++ b/Documentation/notation/keyboards.itely @@ -437,7 +437,7 @@ Chords that cross staves may be produced: % extend the stems to reach the other staff \override Stem #'length = #12 % do not print extra flags - \override Stem #'flag-style = #'no-flag + \override Flag #'style = #'no-flag % prevent beaming as needed a8 g4 f8 f bes\noBeam g4 } diff --git a/Documentation/snippets/new/displaying-complex-chords.ly b/Documentation/snippets/new/displaying-complex-chords.ly index f2426dcc4c..f3efe63b7c 100644 --- a/Documentation/snippets/new/displaying-complex-chords.ly +++ b/Documentation/snippets/new/displaying-complex-chords.ly @@ -16,7 +16,7 @@ fixB = { \once \override NoteHead #'X-offset = #1.7 \once \override Stem #'rotation = #'(45 0 0) \once \override Stem #'extra-offset = #'(-0.2 . -0.2) - \once \override Stem #'flag-style = #'no-flag + \once \override Flag #'style = #'no-flag \once \override Accidental #'extra-offset = #'(4 . 0) } diff --git a/Documentation/snippets/new/guitar-slides.ly b/Documentation/snippets/new/guitar-slides.ly index 4657d94b85..bf431fa9fa 100644 --- a/Documentation/snippets/new/guitar-slides.ly +++ b/Documentation/snippets/new/guitar-slides.ly @@ -18,6 +18,7 @@ hideFretNumber = { \once \override TabNoteHead #'transparent = ##t \once \override NoteHead #'transparent = ##t \once \override Stem #'transparent = ##t + \once \override Flag #'transparent = ##t \once \override NoteHead #'no-ledgers = ##t \once \override Glissando #'(bound-details left padding) = #0.3 } diff --git a/Documentation/snippets/new/unfretted-headword.ly b/Documentation/snippets/new/unfretted-headword.ly index 72ea357e53..b4d2729c1d 100644 --- a/Documentation/snippets/new/unfretted-headword.ly +++ b/Documentation/snippets/new/unfretted-headword.ly @@ -92,7 +92,7 @@ tupletbp = \once \override Staff.TupletBracket #'padding = #2.25 %% Flag [Note Head - Stem] %% -noflag = \once \override Stem #'flag-style = #'no-flag +noflag = \once \override Flag #'style = #'no-flag %%% %%% Functions diff --git a/Documentation/web/ly-examples/granados.ly b/Documentation/web/ly-examples/granados.ly index 607732e359..4521e658d0 100644 --- a/Documentation/web/ly-examples/granados.ly +++ b/Documentation/web/ly-examples/granados.ly @@ -57,14 +57,14 @@ upperVoiceTwo = \relative c'' { s32 s32_\appassmolto s8. \voiceOne r8 <bes'' es bes'>-> s4 \override Stem #'cross-staff = ##t \override Stem #'length = #28 - \override Stem #'flag-style = #'no-flag + \override Flag #'style = #'no-flag s8 \voiceTwo g,8 aes4 s4 } middleVoiceOne = \relative c' { \override Stem #'cross-staff = ##t \override Stem #'length = #32 - \override Stem #'flag-style = #'no-flag + \override Flag #'style = #'no-flag d!8\noBeam s8 s8 s8_\crmolto s4 % 1 s4 <g bes\arpeggio>8[ <es' g>] \voiceOne e,8( dis16 e) | % 2 \revert Stem #'length @@ -78,7 +78,7 @@ middleVoiceTwo = \relative c' { s2. | % 1 \override Stem #'cross-staff = ##t \override Stem #'length = #24 - \override Stem #'flag-style = #'no-flag + \override Flag #'style = #'no-flag s2 \voiceTwo e!4 | % 2 s4 \voiceTwo <bes c es f>8 <f' aes es'>16 d' <bes, f' aes c>8 <bes' fis'> | % 3 } diff --git a/input/regression/color.ly b/input/regression/color.ly index 8403fddfe1..20cbd145d8 100644 --- a/input/regression/color.ly +++ b/input/regression/color.ly @@ -21,5 +21,6 @@ Use the @code{\\override} and @code{\\revert} expressions to set the b \override NoteHead #'color = #green \override Stem #'color = #blue + \override Flag #'color = #magenta e8 es d dis e4 r } diff --git a/input/regression/flags-default.ly b/input/regression/flags-default.ly index c74e64e767..674ad78ed9 100644 --- a/input/regression/flags-default.ly +++ b/input/regression/flags-default.ly @@ -3,8 +3,8 @@ \header { texidoc = "Default flag styles: '(), 'mensural and 'no-flag. - Compare all three methods to print them: (1) C++ default implementation, - (2) Scheme implementation using the 'flag-style grob property and + Compare all three methods to print them: (1) C++ default implementation, + (2) Scheme implementation using the 'style grob property and (3) setting the 'flag property explicitly to the desired Scheme function. All three systems should be absolutely identical." } @@ -19,7 +19,7 @@ testnotes = { \autoBeamOff c''8 d''16 c''32 d''64 \acciaccatura {c''8} d''64 } -% Old settings: flag-style set to default, 'mensural, 'no-flag; using the +% Old settings: style set to default, 'mensural, 'no-flag; using the % default C++ function ly:stem::calc-stem { \override Score.RehearsalMark #'self-alignment-X = #LEFT @@ -29,11 +29,11 @@ testnotes = { \autoBeamOff \testnotes \mark "Symbol: 'mensural (C++)" - \override Stem #'flag-style = #'mensural + \override Flag #'style = #'mensural \testnotes \mark "Symbol: 'no-flag (C++)" - \override Stem #'flag-style = #'no-flag + \override Flag #'style = #'no-flag \testnotes } @@ -42,17 +42,17 @@ testnotes = { \autoBeamOff \override Score.RehearsalMark #'self-alignment-X = #LEFT \time 2/4 - \override Stem #'flag = #default-flag - \revert Stem #'flag-style + \override Flag #'stencil = #default-flag + \revert Flag #'style \mark "Default flags (Scheme)" \testnotes \mark "Symbol: 'mensural (Scheme)" - \override Stem #'flag-style = #'mensural + \override Flag #'style = #'mensural \testnotes \mark "Symbol: 'no-flag (Scheme)" - \override Stem #'flag-style = #'no-flag + \override Flag #'style = #'no-flag \testnotes } @@ -62,14 +62,14 @@ testnotes = { \autoBeamOff \time 2/4 \mark "Function: normal-flag" - \override Stem #'flag = #normal-flag + \override Flag #'stencil = #normal-flag \testnotes \mark "Function: mensural-flag" - \override Stem #'flag = #mensural-flag + \override Flag #'stencil = #mensural-flag \testnotes \mark "Function: no-flag" - \override Stem #'flag = #no-flag + \override Flag #'stencil = #no-flag \testnotes } diff --git a/input/regression/flags-in-scheme.ly b/input/regression/flags-in-scheme.ly index b26f9b71d6..75248fbcb9 100644 --- a/input/regression/flags-in-scheme.ly +++ b/input/regression/flags-in-scheme.ly @@ -1,7 +1,7 @@ \version "2.14.0" \header { - texidoc = "The 'flag property of the Stem grob can be set to a custom + texidoc = "The 'stencil property of the Flag grob can be set to a custom scheme function to generate the glyph for the flag." } @@ -9,26 +9,28 @@ scheme function to generate the glyph for the flag." % test notes, which will be shown in different style: testnotes = { \autoBeamOff c'8 d'16 c'32 d'64 \acciaccatura {c'8} d'64 c''8 d''16 c''32 d''64 \acciaccatura {c''8} d''64 } -#(define-public (weight-flag stem-grob) - (let* ((log (- (ly:grob-property stem-grob 'duration-log) 2)) +#(define-public (weight-flag grob) + (let* ((stem-grob (ly:grob-parent grob X)) + (log (- (ly:grob-property stem-grob 'duration-log) 2)) (is-up (eqv? (ly:grob-property stem-grob 'direction) UP)) (yext (if is-up (cons (* log -0.8) 0) (cons 0 (* log 0.8)))) (flag-stencil (make-filled-box-stencil '(-0.4 . 0.4) yext)) - (stroke-style (ly:grob-property stem-grob 'stroke-style)) + (stroke-style (ly:grob-property grob 'stroke-style)) (stroke-stencil (if (equal? stroke-style "grace") (make-line-stencil 0.2 -0.9 -0.4 0.9 -0.4) empty-stencil))) (ly:stencil-add flag-stencil stroke-stencil))) % Create a flag stencil by looking up the glyph from the font -#(define (inverted-flag stem-grob) - (let* ((dir (if (eqv? (ly:grob-property stem-grob 'direction) UP) "d" "u")) - (flag (retrieve-glyph-flag "" dir "" stem-grob)) - (line-thickness (ly:staff-symbol-line-thickness stem-grob)) +#(define (inverted-flag grob) + (let* ((stem-grob (ly:grob-parent grob X)) + (dir (if (eqv? (ly:grob-property stem-grob 'direction) UP) "d" "u")) + (flag (retrieve-glyph-flag "" dir "" grob)) + (line-thickness (ly:staff-symbol-line-thickness grob)) (stem-thickness (ly:grob-property stem-grob 'thickness)) (stem-width (* line-thickness stem-thickness)) - (stroke-style (ly:grob-property stem-grob 'stroke-style)) + (stroke-style (ly:grob-property grob 'stroke-style)) (stencil (if (null? stroke-style) flag - (add-stroke-glyph flag stem-grob dir stroke-style ""))) + (add-stroke-glyph flag grob dir stroke-style ""))) (rotated-flag (ly:stencil-rotate-absolute stencil 180 0 0))) (ly:stencil-translate rotated-flag (cons (- (/ stem-width 2)) 0)))) @@ -36,11 +38,11 @@ testnotes = { \autoBeamOff c'8 d'16 c'32 d'64 \acciaccatura {c'8} d'64 c''8 d''1 \override Score.RehearsalMark #'self-alignment-X = #LEFT \time 2/4 \mark "Function: weight-flag (custom)" - \override Stem #'flag = #weight-flag + \override Flag #'stencil = #weight-flag \testnotes \mark "Function: inverted-flag (custom)" - \override Stem #'flag = #inverted-flag + \override Flag #'stencil = #inverted-flag \testnotes } diff --git a/input/regression/flags-straight-stockhausen-boulez.ly b/input/regression/flags-straight-stockhausen-boulez.ly index 7a13d64bae..3190abd2fd 100644 --- a/input/regression/flags-straight-stockhausen-boulez.ly +++ b/input/regression/flags-straight-stockhausen-boulez.ly @@ -17,7 +17,7 @@ stemLength = #(define-music-function (parser location length) (number?) { \autoBeamOff \time 3/8 - \override Stem #'flag = #modern-straight-flag + \override Flag #'stencil = #modern-straight-flag \override Stem #'length-fraction = #'1.5 r8 \acciaccatura { diff --git a/input/regression/flags-straight.ly b/input/regression/flags-straight.ly index 918985e6ef..f4b7a51dac 100644 --- a/input/regression/flags-straight.ly +++ b/input/regression/flags-straight.ly @@ -13,11 +13,11 @@ testnotes = { \autoBeamOff c'8 d'16 c'32 d'64 \acciaccatura {c'8} d'64 \override Score.RehearsalMark #'self-alignment-X = #LEFT \time 2/4 \mark "modern straight" - \override Stem #'flag = #modern-straight-flag + \override Flag #'stencil = #modern-straight-flag \testnotes \mark "old straight (large angles)" - \override Stem #'flag = #old-straight-flag + \override Flag #'stencil = #old-straight-flag \testnotes % % \mark "custom slant" @@ -25,6 +25,6 @@ testnotes = { \autoBeamOff c'8 d'16 c'32 d'64 \acciaccatura {c'8} d'64 % % flag thickness and spacing % % up-flag angle and length % % down-flag angle and length -% \override Stem #'flag = #(straight-flag 0.35 0.8 -5 0.5 60 2.0) +% \override Flag #'stencil = #(straight-flag 0.35 0.8 -5 0.5 60 2.0) % \testnotes } diff --git a/input/regression/graphviz.ly b/input/regression/graphviz.ly index 42fab60ad3..d302a7d991 100644 --- a/input/regression/graphviz.ly +++ b/input/regression/graphviz.ly @@ -8,8 +8,10 @@ #(whitelist-grob 'NoteHead) #(whitelist-grob 'Stem) +#(whitelist-grob 'Flag) #(whitelist-grob "NoteHead") #(whitelist-grob "Stem") +#(whitelist-grob "Flag") #(map whitelist-symbol '(stencil style duration-log stem-attachment end-position staff-position diff --git a/input/regression/grid-lines.ly b/input/regression/grid-lines.ly index 57d1eaf372..c58d56ef60 100644 --- a/input/regression/grid-lines.ly +++ b/input/regression/grid-lines.ly @@ -74,6 +74,7 @@ skips = \override NoteHead #'transparent = ##t \override NoteHead #'no-ledgers = ##t \override Stem #'transparent = ##t + \override Flag #'transparent = ##t \override Beam #'transparent = ##t << \skips diff --git a/input/regression/les-nereides.ly b/input/regression/les-nereides.ly index fad2500f5b..6dc79306c8 100644 --- a/input/regression/les-nereides.ly +++ b/input/regression/les-nereides.ly @@ -154,7 +154,7 @@ bass = \new Voice \relative c{ >> \grace { - \override Stem #'stroke-style = #"grace" + \override Flag #'stroke-style = #"grace" s8 s16 s s @@ -163,7 +163,7 @@ bass = \new Voice \relative c{ \clef bass <e,,, e,>32(\sustainOff\sustainOn - \revert Stem #'stroke-style + \revert Flag #'stroke-style } <gis' e>2) diff --git a/input/regression/mozart-hrn3-defs.ily b/input/regression/mozart-hrn3-defs.ily index 78ef6ab122..fb87ca9107 100644 --- a/input/regression/mozart-hrn3-defs.ily +++ b/input/regression/mozart-hrn3-defs.ily @@ -1,7 +1,7 @@ % -longgrace = \override Stem #'stroke-style = #'() -endlonggrace = \revert Stem #'stroke-style +longgrace = \override Flag #'stroke-style = #'() +endlonggrace = \revert Flag #'stroke-style ritenuto = \markup { \italic "rit." } \version "2.14.0" diff --git a/input/regression/quote-overrides.ly b/input/regression/quote-overrides.ly index 043864ed30..be3dc3caf6 100644 --- a/input/regression/quote-overrides.ly +++ b/input/regression/quote-overrides.ly @@ -12,7 +12,7 @@ } mus = \relative c' { - % Acciaccaturas contain a slur and \override Stem #'stroke-style + % Acciaccaturas contain a slur and \override Flag #'stroke-style % Thus, we're checking \override here c4 \acciaccatura d8 c4 % Checking \set and \unset @@ -23,12 +23,12 @@ mus = \relative c' { % Checking \once \override \once \override Stem #'thickness = #8.0 d8 % Checking two overrides - \override Stem #'thickness = #8.0 \override Stem #'stroke-style = "grace" + \override Stem #'thickness = #8.0 \override Flag #'stroke-style = "grace" d8 % reverting one of them \revert Stem #'thickness d8 % and the other - \revert Stem #'stroke-style c8 + \revert Flag #'stroke-style c8 % checking tweaks c2-\tweak #'color #red -> diff --git a/lily/beam-quanting.cc b/lily/beam-quanting.cc index 8b0c9f2abc..106fffc741 100644 --- a/lily/beam-quanting.cc +++ b/lily/beam-quanting.cc @@ -232,8 +232,7 @@ void Beam_scoring_problem::init_collisions (vector<Grob *> grobs) - beam->relative_coordinate (common[Y_AXIS], Y_AXIS); Real factor = parameters.STEM_COLLISION_FACTOR; - if (!unsmob_grob (s->get_object ("beam")) - && !Stem::flag (s).is_empty ()) + if (!unsmob_grob (s->get_object ("beam"))) factor = 1.0; add_collision (x, y, factor); } diff --git a/lily/dot-column.cc b/lily/dot-column.cc index fff2359cc0..daa318bb4e 100644 --- a/lily/dot-column.cc +++ b/lily/dot-column.cc @@ -132,15 +132,13 @@ Dot_column::calc_positioning_done (SCM smob) i != stems.end (); i++) { Grob *stem = (*i); - Stencil flag = Stem::flag (stem); - if (!flag.is_empty ()) + Grob *flag = Stem::flag (stem); + if (flag) { - Interval y = flag.extent (Y_AXIS) - * (2 / ss) - + Stem::stem_end_position (stem); + Grob *commony = stem->common_refpoint (flag, Y_AXIS); + Interval y = flag->extent (commony, Y_AXIS) * (2 / ss); - Interval x = stem->relative_coordinate (commonx, X_AXIS) - + flag.extent (X_AXIS); + Interval x = flag->extent (commonx, X_AXIS); boxes.push_back (Box (x, y)); } diff --git a/lily/flag.cc b/lily/flag.cc new file mode 100644 index 0000000000..a349a205d9 --- /dev/null +++ b/lily/flag.cc @@ -0,0 +1,175 @@ +/* + This file is part of LilyPond, the GNU music typesetter. + + Copyright (C) 1996--2011 Han-Wen Nienhuys <hanwen@xs4all.nl> + Jan Nieuwenhuizen <janneke@gnu.org> + + 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 <http://www.gnu.org/licenses/>. +*/ + +#include "stem.hh" + +#include "directional-element-interface.hh" +#include "font-interface.hh" +#include "grob.hh" +#include "international.hh" +#include "output-def.hh" +#include "staff-symbol-referencer.hh" +#include "stencil.hh" +#include "warn.hh" + +class Flag +{ +public: + DECLARE_SCHEME_CALLBACK (print, (SCM)); + DECLARE_SCHEME_CALLBACK (width, (SCM)); + DECLARE_SCHEME_CALLBACK (calc_y_offset, (SCM)); + DECLARE_SCHEME_CALLBACK (calc_x_offset, (SCM)); + DECLARE_GROB_INTERFACE (); +}; + + + +MAKE_SCHEME_CALLBACK (Flag, width, 1); +SCM +Flag::width (SCM smob) +{ + Grob *me = unsmob_grob (smob); + Stencil *sten = unsmob_stencil (me->get_property ("stencil")); + if (!sten) + return ly_interval2scm (Interval (0.0, 0.0)); + + Grob *stem = me->get_parent (X_AXIS); + + /* + TODO: + This reproduces a bad hard-coding that has been in the code for quite some time: + the bounding boxes for the flags are slightly off and need to be fixed. + */ + + return ly_interval2scm (sten->extent (X_AXIS) - stem->extent (stem, X_AXIS)[RIGHT]); +} +MAKE_SCHEME_CALLBACK (Flag, print, 1); +SCM +Flag::print (SCM smob) +{ + Grob *me = unsmob_grob (smob); + Grob *stem = me->get_parent (X_AXIS); + + int log = Stem::duration_log (stem); + string flag_style; + + SCM flag_style_scm = me->get_property ("style"); + if (scm_is_symbol (flag_style_scm)) + flag_style = ly_symbol2string (flag_style_scm); + + if (flag_style == "no-flag") + return Stencil ().smobbed_copy (); + + bool adjust = true; + + string staffline_offs; + if (flag_style == "mensural") + /* Mensural notation: For notes on staff lines, use different + flags than for notes between staff lines. The idea is that + flags are always vertically aligned with the staff lines, + regardless if the note head is on a staff line or between two + staff lines. In other words, the inner end of a flag always + touches a staff line. + */ + { + if (adjust) + { + int p = (int) (rint (Stem::stem_end_position (stem))); + staffline_offs + = Staff_symbol_referencer::on_line (stem, p) ? "0" : "1"; + } + else + staffline_offs = "2"; + } + else + staffline_offs = ""; + + char dir = (get_grob_direction (stem) == UP) ? 'u' : 'd'; + string font_char = flag_style + + to_string (dir) + staffline_offs + to_string (log); + Font_metric *fm = Font_interface::get_default_font (me); + Stencil flag = fm->find_by_name ("flags." + font_char); + if (flag.is_empty ()) + me->warning (_f ("flag `%s' not found", font_char)); + + /* + TODO: maybe property stroke-style should take different values, + e.g. "" (i.e. no stroke), "single" and "double" (currently, it's + '() or "grace"). */ + SCM stroke_style_scm = me->get_property ("stroke-style"); + if (scm_is_string (stroke_style_scm)) + { + string stroke_style = ly_scm2string (stroke_style_scm); + if (!stroke_style.empty ()) + { + string font_char = flag_style + to_string (dir) + stroke_style; + Stencil stroke = fm->find_by_name ("flags." + font_char); + if (stroke.is_empty ()) + { + font_char = to_string (dir) + stroke_style; + stroke = fm->find_by_name ("flags." + font_char); + } + if (stroke.is_empty ()) + me->warning (_f ("flag stroke `%s' not found", font_char)); + else + flag.add_stencil (stroke); + } + } + + return flag.smobbed_copy (); +} + +MAKE_SCHEME_CALLBACK (Flag, calc_y_offset, 1); +SCM +Flag::calc_y_offset (SCM smob) +{ + Grob *me = unsmob_grob (smob); + Grob *stem = me->get_parent (X_AXIS); + Direction d = get_grob_direction (stem); + + Real blot + = me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter")); + Real half_space = Staff_symbol_referencer::staff_space (me) * 0.5; + Real y2 = robust_scm2double (stem->get_property ("stem-end-position"), 0.0); + + return scm_from_double (y2 * half_space - d * blot / 2); +} + +MAKE_SCHEME_CALLBACK (Flag, calc_x_offset, 1); +SCM +Flag::calc_x_offset (SCM smob) +{ + Grob *me = unsmob_grob (smob); + Grob *stem = me->get_parent (X_AXIS); + return scm_from_double (stem->extent (stem, X_AXIS)[RIGHT]); +} + +ADD_INTERFACE (Flag, + "A flag that gets attached to a stem." + "The style property is symbol determining" + " what style of flag glyph is typeset on a" + " @code{Stem}. Valid options include @code{'()}" + " for standard flags, @code{'mensural} and" + " @code{'no-flag}, which switches off the flag.", + + /* properties */ + "style " + "stroke-style " + );
\ No newline at end of file diff --git a/lily/include/stem.hh b/lily/include/stem.hh index b18b39e53a..0e3e0f06d1 100644 --- a/lily/include/stem.hh +++ b/lily/include/stem.hh @@ -50,10 +50,9 @@ public: static bool is_cross_staff (Grob *); static Interval head_positions (Grob *); static Real stem_end_position (Grob *); - static Stencil flag (Grob *); - static Stencil get_translated_flag (Grob *); DECLARE_GROB_INTERFACE (); static void set_spacing_hints (Grob *); + static Grob *flag (Grob *); DECLARE_SCHEME_CALLBACK (print, (SCM)); DECLARE_SCHEME_CALLBACK (calc_default_direction, (SCM)); @@ -69,6 +68,5 @@ public: DECLARE_SCHEME_CALLBACK (pure_height, (SCM, SCM, SCM)); DECLARE_SCHEME_CALLBACK (height, (SCM)); DECLARE_SCHEME_CALLBACK (calc_cross_staff, (SCM)); - DECLARE_SCHEME_CALLBACK (calc_flag, (SCM)); }; #endif diff --git a/lily/rhythmic-column-engraver.cc b/lily/rhythmic-column-engraver.cc index 985b7b08a7..ca767cc7af 100644 --- a/lily/rhythmic-column-engraver.cc +++ b/lily/rhythmic-column-engraver.cc @@ -55,6 +55,7 @@ class Rhythmic_column_engraver : public Engraver { vector<Grob *> rheads_; Grob *stem_; + Grob *flag_; Grob *note_column_; Grob *arpeggio_; @@ -62,6 +63,7 @@ class Rhythmic_column_engraver : public Engraver protected: DECLARE_ACKNOWLEDGER (stem); + DECLARE_ACKNOWLEDGER (flag); DECLARE_ACKNOWLEDGER (rhythmic_head); DECLARE_ACKNOWLEDGER (arpeggio); void process_acknowledged (); @@ -72,6 +74,7 @@ Rhythmic_column_engraver::Rhythmic_column_engraver () { stem_ = 0; + flag_ = 0; note_column_ = 0; arpeggio_ = 0; } @@ -105,6 +108,8 @@ Rhythmic_column_engraver::process_acknowledged () Pointer_group_interface::add_grob (note_column_, ly_symbol2scm ("elements"), arpeggio_); note_column_->set_object ("arpeggio", arpeggio_->self_scm ()); } + if (flag_) + Pointer_group_interface::add_grob (note_column_, ly_symbol2scm ("elements"), flag_); } } @@ -115,6 +120,12 @@ Rhythmic_column_engraver::acknowledge_stem (Grob_info i) } void +Rhythmic_column_engraver::acknowledge_flag (Grob_info i) +{ + flag_ = i.grob (); +} + +void Rhythmic_column_engraver::acknowledge_rhythmic_head (Grob_info i) { rheads_.push_back (i.grob ()); @@ -132,9 +143,11 @@ Rhythmic_column_engraver::stop_translation_timestep () note_column_ = 0; stem_ = 0; arpeggio_ = 0; + flag_ = 0; } ADD_ACKNOWLEDGER (Rhythmic_column_engraver, stem); +ADD_ACKNOWLEDGER (Rhythmic_column_engraver, flag); ADD_ACKNOWLEDGER (Rhythmic_column_engraver, rhythmic_head); ADD_ACKNOWLEDGER (Rhythmic_column_engraver, arpeggio); diff --git a/lily/stem-engraver.cc b/lily/stem-engraver.cc index 6890b5b041..04184a9020 100644 --- a/lily/stem-engraver.cc +++ b/lily/stem-engraver.cc @@ -38,6 +38,7 @@ class Stem_engraver : public Engraver { Grob *stem_; Grob *tremolo_; + vector <Grob *> maybe_flags_; Stream_event *rhythmic_ev_; Stream_event *tremolo_ev_; @@ -49,6 +50,8 @@ protected: DECLARE_TRANSLATOR_LISTENER (tremolo); DECLARE_ACKNOWLEDGER (rhythmic_head); void stop_translation_timestep (); + void finalize (); + void kill_unused_flags (); }; Stem_engraver::Stem_engraver () @@ -65,7 +68,6 @@ Stem_engraver::make_stem (Grob_info gi) /* Announce the cause of the head as cause of the stem. The stem needs a rhythmic structure to fit it into a beam. */ stem_ = make_item ("Stem", gi.grob ()->self_scm ()); - if (tremolo_ev_) { /* Stem tremolo is never applied to a note by default, @@ -158,11 +160,37 @@ Stem_engraver::acknowledge_rhythmic_head (Grob_info gi) } Stem::add_head (stem_, gi.grob ()); + + if (Stem::is_normal_stem (stem_) + && Stem::duration_log (stem_) > 2) + { + Item *flag = make_item ("Flag", stem_->self_scm ()); + flag->set_parent (stem_, X_AXIS); + stem_->set_object ("flag", flag->self_scm ()); + maybe_flags_.push_back (flag); + } +} + +void +Stem_engraver::kill_unused_flags () +{ + for (vsize i = 0; i < maybe_flags_.size (); i++) + if (unsmob_grob (maybe_flags_[i]->get_parent (X_AXIS)->get_object ("beam"))) + maybe_flags_[i]->suicide (); +} + +void +Stem_engraver::finalize () +{ + kill_unused_flags (); } void Stem_engraver::stop_translation_timestep () { + if (scm_is_string (get_property ("whichBar"))) + kill_unused_flags (); + tremolo_ = 0; if (stem_) { @@ -205,7 +233,8 @@ ADD_TRANSLATOR (Stem_engraver, /* read */ "tremoloFlags " "stemLeftBeamCount " - "stemRightBeamCount ", + "stemRightBeamCount " + "whichBar ", /* write */ "" diff --git a/lily/stem.cc b/lily/stem.cc index e83ffd9893..d4456817c6 100644 --- a/lily/stem.cc +++ b/lily/stem.cc @@ -599,106 +599,6 @@ Stem::stem_end_position (Grob *me) return robust_scm2double (me->get_property ("stem-end-position"), 0); } -MAKE_SCHEME_CALLBACK (Stem, calc_flag, 1); -SCM -Stem::calc_flag (SCM smob) -{ - Grob *me = unsmob_grob (smob); - - int log = duration_log (me); - /* - TODO: maybe property stroke-style should take different values, - e.g. "" (i.e. no stroke), "single" and "double" (currently, it's - '() or "grace"). */ - string flag_style; - - SCM flag_style_scm = me->get_property ("flag-style"); - if (scm_is_symbol (flag_style_scm)) - flag_style = ly_symbol2string (flag_style_scm); - - if (flag_style == "no-flag") - return Stencil ().smobbed_copy (); - - bool adjust = true; - - string staffline_offs; - if (flag_style == "mensural") - /* Mensural notation: For notes on staff lines, use different - flags than for notes between staff lines. The idea is that - flags are always vertically aligned with the staff lines, - regardless if the note head is on a staff line or between two - staff lines. In other words, the inner end of a flag always - touches a staff line. - */ - { - if (adjust) - { - int p = (int) (rint (stem_end_position (me))); - staffline_offs - = Staff_symbol_referencer::on_line (me, p) ? "0" : "1"; - } - else - staffline_offs = "2"; - } - else - staffline_offs = ""; - - char dir = (get_grob_direction (me) == UP) ? 'u' : 'd'; - string font_char = flag_style - + to_string (dir) + staffline_offs + to_string (log); - Font_metric *fm = Font_interface::get_default_font (me); - Stencil flag = fm->find_by_name ("flags." + font_char); - if (flag.is_empty ()) - me->warning (_f ("flag `%s' not found", font_char)); - - SCM stroke_style_scm = me->get_property ("stroke-style"); - if (scm_is_string (stroke_style_scm)) - { - string stroke_style = ly_scm2string (stroke_style_scm); - if (!stroke_style.empty ()) - { - string font_char = flag_style + to_string (dir) + stroke_style; - Stencil stroke = fm->find_by_name ("flags." + font_char); - if (stroke.is_empty ()) - { - font_char = to_string (dir) + stroke_style; - stroke = fm->find_by_name ("flags." + font_char); - } - if (stroke.is_empty ()) - me->warning (_f ("flag stroke `%s' not found", font_char)); - else - flag.add_stencil (stroke); - } - } - - return flag.smobbed_copy (); -} - -Stencil -Stem::flag (Grob *me) -{ - int log = duration_log (me); - if (log < 3 - || unsmob_grob (me->get_object ("beam"))) - return Stencil (); - - if (!is_normal_stem (me)) - return Stencil (); - - // This get_property call already evaluates the scheme function with - // the grob passed as argument! Thus, we only have to check if a valid - // stencil is returned. - SCM flag_style_scm = me->get_property ("flag"); - if (Stencil *flag = unsmob_stencil (flag_style_scm)) - { - return *flag; - } - else - { - return Stencil (); - } -} - MAKE_SCHEME_CALLBACK (Stem, width, 1); SCM Stem::width (SCM e) @@ -709,17 +609,12 @@ Stem::width (SCM e) if (is_invisible (me)) r.set_empty (); - else if (unsmob_grob (me->get_object ("beam")) - || abs (duration_log (me)) <= 2) + else { r = Interval (-1, 1); r *= thickness (me) / 2; } - else - { - r = Interval (-1, 1) * thickness (me) * 0.5; - r.unite (flag (me).extent (X_AXIS)); - } + return ly_interval2scm (r); } @@ -820,29 +715,9 @@ Stem::print (SCM smob) Stencil ss = Lookup::round_filled_box (b, blot); mol.add_stencil (ss); - mol.add_stencil (get_translated_flag (me)); - return mol.smobbed_copy (); } -Stencil -Stem::get_translated_flag (Grob *me) -{ - Stencil fl = flag (me); - if (!fl.is_empty ()) - { - Direction d = get_grob_direction (me); - Real blot - = me->layout ()->get_dimension (ly_symbol2scm ("blot-diameter")); - Real stem_width = thickness (me); - Real half_space = Staff_symbol_referencer::staff_space (me) * 0.5; - Real y2 = robust_scm2double (me->get_property ("stem-end-position"), 0.0); - fl.translate_axis (y2 * half_space - d * blot / 2, Y_AXIS); - fl.translate_axis (stem_width / 2, X_AXIS); - } - return fl; -} - /* move the stem to right of the notehead if it is up. */ @@ -1070,6 +945,12 @@ Stem::calc_cross_staff (SCM smob) return scm_from_bool (is_cross_staff (unsmob_grob (smob))); } +Grob* +Stem::flag (Grob *me) +{ + return unsmob_grob (me->get_object ("flag")); +} + /* FIXME: Too many properties */ ADD_INTERFACE (Stem, "The stem represents the graphical stem. In addition, it" @@ -1108,7 +989,6 @@ ADD_INTERFACE (Stem, "direction " "duration-log " "flag " - "flag-style " "french-beaming " "length " "length-fraction " @@ -1122,7 +1002,6 @@ ADD_INTERFACE (Stem, "stem-end-position " "stem-info " "stemlet-length " - "stroke-style " "thickness " "tremolo-flag " ); diff --git a/lily/tie-formatting-problem.cc b/lily/tie-formatting-problem.cc index 3e76c120b1..b157d4794c 100644 --- a/lily/tie-formatting-problem.cc +++ b/lily/tie-formatting-problem.cc @@ -170,9 +170,13 @@ Tie_formatting_problem::set_column_chord_outline (vector<Item *> bounds, if (dir == LEFT) { - Box flag_box = Stem::get_translated_flag (stem).extent_box (); - flag_box.translate ( Offset (x[RIGHT], X_AXIS)); - boxes.push_back (flag_box); + Grob *flag = Stem::flag (stem); + if (flag) + { + Grob* commony = stem->common_refpoint (flag, Y_AXIS); + boxes.push_back (Box (flag->extent (x_refpoint_, X_AXIS), + flag->extent (commony, Y_AXIS))); + } } } else diff --git a/ly/engraver-init.ly b/ly/engraver-init.ly index badb701e08..aab1317a90 100644 --- a/ly/engraver-init.ly +++ b/ly/engraver-init.ly @@ -675,6 +675,7 @@ automatically when an output definition (a @code{\score} or graceSettings = #`( (Voice Stem direction ,UP) (Voice Stem font-size -3) + (Voice Flag font-size -3) (Voice NoteHead font-size -3) (Voice TabNoteHead font-size -4) (Voice Dots font-size -3) @@ -783,7 +784,7 @@ context." %% on the slur::calc-control-points routine \override Stem #'length = #0 \override Stem #'no-stem-extend = ##t - \override Stem #'flag-style = #'no-flag + \override Flag #'style = #'no-flag \override Stem #'details = #'((lengths 0 0 0 0 0 0) (beamed-lengths 0 0 0) (beamed-minimum-free-lengths 0 0 0) diff --git a/ly/grace-init.ly b/ly/grace-init.ly index 6850541afa..4ee3be0179 100644 --- a/ly/grace-init.ly +++ b/ly/grace-init.ly @@ -21,18 +21,18 @@ stopAppoggiaturaMusic = { startAcciaccaturaMusic = { s1*0\startGraceSlur - \override Stem #'stroke-style = #"grace" + \override Flag #'stroke-style = #"grace" } stopAcciaccaturaMusic = { - \revert Stem #'stroke-style + \revert Flag #'stroke-style s1*0\stopGraceSlur } startSlashedGraceMusic = { - \override Stem #'stroke-style = #"grace" + \override Flag #'stroke-style = #"grace" } stopSlashedGraceMusic = { - \revert Stem #'stroke-style + \revert Flag #'stroke-style } diff --git a/ly/gregorian.ly b/ly/gregorian.ly index 0b8e0680be..6475a719c1 100644 --- a/ly/gregorian.ly +++ b/ly/gregorian.ly @@ -301,6 +301,7 @@ neumeDemoLayout = \layout { \consists Vaticana_ligature_engraver \override NoteHead #'style = #'vaticana.punctum \override Stem #'transparent = ##t + \override Flag #'transparent = ##t } } diff --git a/ly/property-init.ly b/ly/property-init.ly index 0175bb798f..02acc1b4e6 100644 --- a/ly/property-init.ly +++ b/ly/property-init.ly @@ -233,6 +233,7 @@ hideNotes = { \override NoteHead #'transparent = ##t \override NoteHead #'no-ledgers = ##t \override Stem #'transparent = ##t + \override Flag #'transparent = ##t \override Beam #'transparent = ##t \override Accidental #'transparent = ##t } @@ -240,6 +241,7 @@ unHideNotes = { \revert Accidental #'transparent \revert Beam #'transparent \revert Stem #'transparent + \revert Flag #'transparent \revert NoteHead #'transparent \revert NoteHead #'no-ledgers \revert Dots #'transparent @@ -424,7 +426,7 @@ tabFullNotation = { % stems (the half note gets a double stem) \revert TabVoice.Stem #'length \revert TabVoice.Stem #'no-stem-extend - \revert TabVoice.Stem #'flag-style + \revert TabVoice.Flag #'style \revert TabVoice.Stem #'details \revert TabVoice.Stem #'transparent \override TabVoice.Stem #'stencil = #tabvoice::draw-double-stem-for-half-notes @@ -544,30 +546,35 @@ voiceOneStyle = { \override NoteHead #'style = #'diamond \override NoteHead #'color = #red \override Stem #'color = #red + \override Flag #'color = #red \override Beam #'color = #red } voiceTwoStyle = { \override NoteHead #'style = #'triangle \override NoteHead #'color = #blue \override Stem #'color = #blue + \override Flag #'color = #blue \override Beam #'color = #blue } voiceThreeStyle = { \override NoteHead #'style = #'xcircle \override NoteHead #'color = #green \override Stem #'color = #green + \override Flag #'color = #green \override Beam #'color = #green } voiceFourStyle = { \override NoteHead #'style = #'cross \override NoteHead #'color = #magenta \override Stem #'color = #magenta + \override Flag #'color = #magenta \override Beam #'color = #magenta } voiceNeutralStyle = { \revert NoteHead #'style \revert NoteHead #'color \revert Stem #'color + \revert Flag #'color \revert Beam #'color } diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm index a45f1053d1..11493d87e4 100644 --- a/scm/define-grob-properties.scm +++ b/scm/define-grob-properties.scm @@ -272,17 +272,7 @@ Y@tie{}dimension by this much.") ;; ;; f ;; - (flag ,ly:stencil? "A function returning the full flag stencil -for the @code{Stem}, which is passed to the function as the only -argument. The default ly:stem::calc-stencil function uses the -@code{flag-style} property to determine the correct glyph for the -flag. By providing your own function, you can create arbitrary -flags.") (flag-count ,number? "The number of tremolo beams.") - (flag-style ,symbol? "A symbol determining what style of flag -glyph is typeset on a @code{Stem}. Valid options include @code{'()} -for standard flags, @code{'mensural} and @code{'no-flag}, which -switches off the flag.") (font-encoding ,symbol? "The font encoding is the broadest category for selecting a font. Currently, only lilypond's system fonts (Emmentaler) are using this property. Available @@ -1020,6 +1010,7 @@ the grob where this is set in.") in addition to notes and stems.") (figures ,ly:grob-array? "Figured bass objects for continuation line.") + (flag ,ly:grob? "A pointer to a @code{Flag} object.") (glissando-index ,integer? "The index of a glissando in its note column.") diff --git a/scm/define-grobs.scm b/scm/define-grobs.scm index 3055af219b..4beeb04dbf 100644 --- a/scm/define-grobs.scm +++ b/scm/define-grobs.scm @@ -351,6 +351,7 @@ (clip-edges . #t) (collision-interfaces . (beam-interface clef-interface + flag-interface inline-accidental-interface key-signature-interface note-head-interface @@ -876,6 +877,16 @@ text-interface text-script-interface)))))) + (Flag + . ( + (stencil . ,ly:flag::print) + (X-extent . ,ly:flag::width) + (X-offset . ,ly:flag::calc-x-offset) + (Y-offset . ,ly:flag::calc-y-offset) + (meta . ((class . Item) + (interfaces . (flag-interface + font-interface)))))) + (FootnoteItem . ( (annotation-balloon . #f) @@ -1918,7 +1929,6 @@ (direction . ,ly:stem::calc-direction) (duration-log . ,stem::calc-duration-log) - (flag . ,ly:stem::calc-flag) (length . ,ly:stem::calc-length) (neutral-direction . ,DOWN) (positioning-done . ,ly:stem::calc-positioning-done) @@ -1932,8 +1942,7 @@ (Y-extent . ,ly:stem::height) (Y-offset . ,ly:staff-symbol-referencer::callback) (meta . ((class . Item) - (interfaces . (font-interface - stem-interface)))))) + (interfaces . (stem-interface)))))) (StemTremolo . ( @@ -2577,6 +2586,13 @@ ly:note-head::print ly:dots::print ly:clef::print + ly:flag::print + default-flag + normal-flag + mensural-flag + no-flag + modern-straight-flag + old-straight-flag ly:key-signature-interface::print ly:percent-repeat-item-interface::beat-slash ly:text-interface::print @@ -2634,6 +2650,7 @@ (list parenthesize-elements laissez-vibrer::print + ly:flag::calc-y-offset ly:rest::y-offset-callback ly:staff-symbol-referencer::callback ly:staff-symbol::height)) diff --git a/scm/flag-styles.scm b/scm/flag-styles.scm index 9e1a268e4d..bce6cab5db 100644 --- a/scm/flag-styles.scm +++ b/scm/flag-styles.scm @@ -19,7 +19,7 @@ ;;;; notably the old-straight-flag and the modern-straight-flag styles. -(define-public (no-flag stem-grob) +(define-public (no-flag grob) "No flag: Simply return empty stencil." empty-stencil) @@ -29,7 +29,7 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(define-public (add-stroke-straight stencil stem-grob dir log stroke-style +(define-public (add-stroke-straight stencil grob dir log stroke-style offset length thickness stroke-thickness) "Add the stroke for acciaccatura to the given flag stencil. The stroke starts for up-flags at `upper-end-of-flag + (0,length/2)' @@ -39,7 +39,8 @@ whole length, while `flag-x-width' is just the x-extent and thus depends on the angle! Other combinations don't look as good. For down-stems the y-coordinates are simply mirrored." - (let* ((start (offset-add offset (cons 0 (* (/ length 2) dir)))) + (let* ((stem-grob (ly:grob-parent grob X)) + (start (offset-add offset (cons 0 (* (/ length 2) dir)))) (end (offset-add (cons 0 (cdr offset)) (cons (- (/ (car offset) 2)) (* (- (+ thickness (car offset))) dir)))) (stroke (make-line-stencil stroke-thickness (car start) (cdr start) (car end) (cdr end)))) @@ -65,13 +66,14 @@ For down-stems the y-coordinates are simply mirrored." All lengths are scaled according to the font size of the note." - (lambda (stem-grob) - (let* ((log (ly:grob-property stem-grob 'duration-log)) + (lambda (grob) + (let* ((stem-grob (ly:grob-parent grob X)) + (log (ly:grob-property stem-grob 'duration-log)) (dir (ly:grob-property stem-grob 'direction)) (stem-up (eqv? dir UP)) - (layout (ly:grob-layout stem-grob)) + (layout (ly:grob-layout grob)) ; scale with the note size (e.g. for grace notes) - (factor (magstep (ly:grob-property stem-grob 'font-size 0))) + (factor (magstep (ly:grob-property grob 'font-size 0))) (grob-stem-thickness (ly:grob-property stem-grob 'thickness)) (line-thickness (ly:output-def-lookup layout 'line-thickness)) (half-stem-thickness (/ (* grob-stem-thickness line-thickness) 2)) @@ -95,9 +97,9 @@ All lengths are scaled according to the font size of the note." (stencil (ly:round-filled-polygon points half-stem-thickness)) ; Log for 1/8 is 3, so we need to subtract 3 (flag-stencil (buildflag stencil (- log 3) stencil spacing)) - (stroke-style (ly:grob-property stem-grob 'stroke-style))) + (stroke-style (ly:grob-property grob 'stroke-style))) (if (equal? stroke-style "grace") - (add-stroke-straight flag-stencil stem-grob + (add-stroke-straight flag-stencil grob dir log stroke-style flag-end flag-length @@ -105,16 +107,16 @@ All lengths are scaled according to the font size of the note." (* half-stem-thickness 2)) flag-stencil)))) -(define-public (modern-straight-flag stem-grob) +(define-public (modern-straight-flag grob) "Modern straight flag style (for composers like Stockhausen, Boulez, etc.). The angles are 18 and 22 degrees and thus smaller than for the ancient style of Bach, etc." - ((straight-flag 0.55 1 -18 1.1 22 1.2) stem-grob)) + ((straight-flag 0.55 1 -18 1.1 22 1.2) grob)) -(define-public (old-straight-flag stem-grob) +(define-public (old-straight-flag grob) "Old straight flag style (for composers like Bach). The angles of the flags are both 45 degrees." - ((straight-flag 0.55 1 -45 1.2 45 1.4) stem-grob)) + ((straight-flag 0.55 1 -45 1.2 45 1.4) grob)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -122,23 +124,24 @@ flags are both 45 degrees." ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -; NOTE: By default, lilypond uses the C++ method Stem::calc-flag -; (ly:stem::calc-flag is the corresponding Scheme interface) to generate the +; NOTE: By default, lilypond uses the C++ method Flag::stencil +; (ly:flag::stencil is the corresponding Scheme interface) to generate the ; flag stencil. The following functions are simply a reimplementation in ; Scheme, so that one has that functionality available in Scheme, if one ; wants to write a flag style, which modifies one of the standard flags ; by some stencil operations. -(define-public (add-stroke-glyph stencil stem-grob dir stroke-style flag-style) +(define-public (add-stroke-glyph stencil grob dir stroke-style flag-style) "Load and add a stroke (represented by a glyph in the font) to the given flag stencil." (if (not (string? stroke-style)) stencil ; Otherwise: look up the stroke glyph and combine it with the flag - (let* ((font-char (string-append "flags." flag-style dir stroke-style)) + (let* ((stem-grob (ly:grob-parent grob X)) + (font-char (string-append "flags." flag-style dir stroke-style)) (alt-font-char (string-append "flags." dir stroke-style)) - (font (ly:grob-default-font stem-grob)) + (font (ly:grob-default-font grob)) (tmpstencil (ly:font-get-glyph font font-char)) (stroke-stencil (if (ly:stencil-empty? tmpstencil) (ly:font-get-glyph font alt-font-char) @@ -150,10 +153,11 @@ flag stencil." (ly:stencil-add stencil stroke-stencil))))) -(define-public (retrieve-glyph-flag flag-style dir dir-modifier stem-grob) +(define-public (retrieve-glyph-flag flag-style dir dir-modifier grob) "Load the correct flag glyph from the font." - (let* ((log (ly:grob-property stem-grob 'duration-log)) - (font (ly:grob-default-font stem-grob)) + (let* ((stem-grob (ly:grob-parent grob X)) + (log (ly:grob-property stem-grob 'duration-log)) + (font (ly:grob-default-font grob)) (font-char (string-append "flags." flag-style dir dir-modifier (number->string log))) (flag (ly:font-get-glyph font font-char))) (if (ly:stencil-empty? flag) @@ -161,18 +165,19 @@ flag stencil." flag)) -(define-public (create-glyph-flag flag-style dir-modifier stem-grob) +(define-public (create-glyph-flag flag-style dir-modifier grob) "Create a flag stencil by looking up the glyph from the font." - (let* ((dir (if (eqv? (ly:grob-property stem-grob 'direction) UP) "u" "d")) - (flag (retrieve-glyph-flag flag-style dir dir-modifier stem-grob)) - (stroke-style (ly:grob-property stem-grob 'stroke-style))) + (let* ((stem-grob (ly:grob-parent grob X)) + (dir (if (eqv? (ly:grob-property stem-grob 'direction) UP) "u" "d")) + (flag (retrieve-glyph-flag flag-style dir dir-modifier grob)) + (stroke-style (ly:grob-property grob 'stroke-style))) (if (null? stroke-style) flag - (add-stroke-glyph flag stem-grob dir stroke-style flag-style)))) + (add-stroke-glyph flag grob dir stroke-style flag-style)))) -(define-public (mensural-flag stem-grob) +(define-public (mensural-flag grob) "Mensural flags: Create the flag stencil by loading the glyph from the font. Flags are always aligned with staff lines, so we need to check the end point of the stem: For stems ending on staff lines, use different flags than for @@ -181,48 +186,50 @@ aligned with the staff lines, regardless of whether the note head is on a staff line or between two staff lines. In other words, the inner end of a flag always touches a staff line." - (let* ((adjust #t) + (let* ((stem-grob (ly:grob-parent grob X)) + (adjust #t) (stem-end (inexact->exact (round (ly:grob-property stem-grob 'stem-end-position)))) ; For some reason the stem-end is a real instead of an integer... (dir-modifier (if (ly:position-on-line? stem-grob stem-end) "1" "0")) (modifier (if adjust dir-modifier "2"))) - (create-glyph-flag "mensural" modifier stem-grob))) + (create-glyph-flag "mensural" modifier grob))) -(define-public ((glyph-flag flag-style) stem-grob) +(define-public ((glyph-flag flag-style) grob) "Simulatesthe default way of generating flags: Look up glyphs @code{flags.style[ud][1234]} from the feta font and use it for the flag stencil." - (create-glyph-flag flag-style "" stem-grob)) + (create-glyph-flag flag-style "" grob)) -(define-public (normal-flag stem-grob) +(define-public (normal-flag grob) "Create a default flag." - (create-glyph-flag "" "" stem-grob)) + (create-glyph-flag "" "" grob)) -(define-public (default-flag stem-grob) +(define-public (default-flag grob) "Create a flag stencil for the stem. Its style will be derived from the -@code{'flag-style} Stem property. By default, @code{lilypond} uses a +@code{'style} Flag property. By default, @code{lilypond} uses a C++ Function (which is slightly faster) to do exactly the same as this function. However, if one wants to modify the default flags, this function can be used to obtain the default flag stencil, which can then be modified at will. The correct way to do this is: @example -\\override Stem #'flag = #default-flag -\\override Stem #'flag-style = #'mensural +\\override Flag #'stencil = #default-flag +\\override Flag #'style = #'mensural @end example " - (let* ((flag-style-symbol (ly:grob-property stem-grob 'flag-style)) + (let* ((stem-grob (ly:grob-parent grob X)) + (flag-style-symbol (ly:grob-property grob 'style)) (flag-style (if (symbol? flag-style-symbol) (symbol->string flag-style-symbol) ""))) (cond - ((equal? flag-style "") (normal-flag stem-grob)) - ((equal? flag-style "mensural") (mensural-flag stem-grob)) - ((equal? flag-style "no-flag") (no-flag stem-grob)) - (else ((glyph-flag flag-style) stem-grob))))) + ((equal? flag-style "") (normal-flag grob)) + ((equal? flag-style "mensural") (mensural-flag grob)) + ((equal? flag-style "no-flag") (no-flag grob)) + (else ((glyph-flag flag-style) grob))))) diff --git a/scm/music-functions.scm b/scm/music-functions.scm index 8cdd53955f..d7fedb689d 100644 --- a/scm/music-functions.scm +++ b/scm/music-functions.scm @@ -424,6 +424,7 @@ in @var{grob}." (make-property-set 'graceSettings ;; TODO: take this from voicedGraceSettings or similar. '((Voice Stem font-size -3) + (Voice Flag font-size -3) (Voice NoteHead font-size -3) (Voice TabNoteHead font-size -4) (Voice Dots font-size -3) |