]> git.donarmstrong.com Git - lilypond.git/commitdiff
Adds a Flag grob to LilyPond.
authorMike Solomon <mike@apollinemike.com>
Sat, 27 Aug 2011 13:13:25 +0000 (15:13 +0200)
committerMike Solomon <mike@apollinemike.com>
Sat, 27 Aug 2011 13:13:25 +0000 (15:13 +0200)
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:
Documentation/learning/tweaks.itely
Documentation/notation/ancient.itely
Documentation/notation/changing-defaults.itely
Documentation/notation/keyboards.itely
Documentation/snippets/new/displaying-complex-chords.ly
Documentation/snippets/new/guitar-slides.ly
Documentation/snippets/new/unfretted-headword.ly
Documentation/web/ly-examples/granados.ly
input/regression/color.ly
input/regression/flags-default.ly
input/regression/flags-in-scheme.ly
input/regression/flags-straight-stockhausen-boulez.ly
input/regression/flags-straight.ly
input/regression/graphviz.ly
input/regression/grid-lines.ly
input/regression/les-nereides.ly
input/regression/mozart-hrn3-defs.ily
input/regression/quote-overrides.ly
lily/beam-quanting.cc
lily/dot-column.cc
lily/flag.cc [new file with mode: 0644]
lily/include/stem.hh
lily/rhythmic-column-engraver.cc
lily/stem-engraver.cc
lily/stem.cc
lily/tie-formatting-problem.cc
ly/engraver-init.ly
ly/grace-init.ly
ly/gregorian.ly
ly/property-init.ly
scm/define-grob-properties.scm
scm/define-grobs.scm
scm/flag-styles.scm
scm/music-functions.scm

index 9f1c5dd0b5d43c52a8746e7dbfc0a561a4286e8e..a13fff3fe00d44c8d13b86d672f8a860502d1ba1 100644 (file)
@@ -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
   }
index fe835fd077a41a19c6415da7536d34f607ff3a4c..55b4aead72d46b0d83e6e6bbd0e268099d40dff0 100644 (file)
@@ -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
index 0cd9812606d6b7455564c2589abb6d4767a690ee..e10986e7cffeeed7861b6f56846269834d8872f4 100644 (file)
@@ -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
index ef294318fbc5201e8a2b02329e12f4511d555d15..a7b3394417b9e13fd5b2afa3960d7efc1eb392e1 100644 (file)
@@ -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
       }
index f2426dcc4ce01a55047eb07af60b851946706d38..f3efe63b7c2d6f9a109eb1ca5b0ebed2c6b5416a 100644 (file)
@@ -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)
 }
 
index 4657d94b858b75b9c9e9c677cbccd0e2eb68744f..bf431fa9facab9c31fa4dfb6e54c082f8fd610ea 100644 (file)
@@ -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
 }
index 72ea357e5379016893d98533b969f658df80d5bf..b4d2729c1d7f63f98c70d675224edf67307459ba 100644 (file)
@@ -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
index 607732e3598f35e32e05a3509bf28c787d776027..4521e658d070b89168afe54b2cc9f1a3560a7fbf 100644 (file)
@@ -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
 }
index 8403fddfe131ebb443737e770cd54b21321b23f7..20cbd145d8c1d16fc139c6e5519661df3f683227 100644 (file)
@@ -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
 }
index c74e64e767b75457a3c5fcbafcff55b665bd2479..674ad78ed9fd1ee97bb33172b44da12e92112a9c 100644 (file)
@@ -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
 }
index b26f9b71d66d2087fb710fcaae749a8bb89e440a..75248fbcb90b882e129b2fdf1b263b8ac084ef3d 100644 (file)
@@ -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
 
 }
index 7a13d64bae81ad7304dfadf755ae035736fbcc5f..3190abd2fd69e14f2002d56c6ed99d9d72d4f9bb 100644 (file)
@@ -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 {
index 918985e6ef9d12ba071964ab58edaf27d3b0951c..f4b7a51dac0a5427560b9324f53346eee6e9c486 100644 (file)
@@ -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
 }
index 42fab60ad331a0c058926c36bbcf85b657e1f547..d302a7d9910aae0eeb387ca9feed487ca0c74bd4 100644 (file)
@@ -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
index 57d1eaf372c3a78ac677fbf7baa9ec41c2771c35..c58d56ef6012752e2eeb1a0b3e01ce7c65d33e71 100644 (file)
@@ -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
 
index fad2500f5be59590e126c1804ad2d4356dd67e3e..6dc79306c8a3a1cbe28b7401325c929e864d570d 100644 (file)
@@ -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)
 
index 78ef6ab122c9878b4fa1578af34f0a5c4d32b59f..fb87ca910758b1c0e8aa4f47d32f20c7515cd790 100644 (file)
@@ -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"
index 043864ed30b1c75d7e8e0f21033abc1258b3f4d6..be3dc3caf660292bcf1d157964def9ebe5eb14d2 100644 (file)
@@ -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 ->
index 8b0c9f2abc1facdfa332f4507102df9c0a31316c..106fffc74134713cbd74fc181ec48b7e44dd2857 100644 (file)
@@ -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);
     }
index fff2359cc0376f774e46ab531798213e0dd62e40..daa318bb4e75cb4a673c9c6fbc8973ade543f14f 100644 (file)
@@ -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 (file)
index 0000000..a349a20
--- /dev/null
@@ -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
index b18b39e53a0035769da90726590c3a631363d1b6..0e3e0f06d1b7f3a0d4f3ed0384feeee5ec533f8f 100644 (file)
@@ -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
index 985b7b08a76ba51e0c0748dc926c043133491af8..ca767cc7af5bbfd68468dc7adb41d6eb73b9b423 100644 (file)
@@ -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_);
     }
 }
 
@@ -114,6 +119,12 @@ Rhythmic_column_engraver::acknowledge_stem (Grob_info i)
   stem_ = i.grob ();
 }
 
+void
+Rhythmic_column_engraver::acknowledge_flag (Grob_info i)
+{
+  flag_ = i.grob ();
+}
+
 void
 Rhythmic_column_engraver::acknowledge_rhythmic_head (Grob_info i)
 {
@@ -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);
 
index 6890b5b041c410f56186d1c8733eb4613e313179..04184a90203891e73fd53086ce50c34b8938b981 100644 (file)
@@ -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 */
                 ""
index e83ffd9893226a95672f70ebf284d7cd8d926733..d4456817c6023915c5efe3b716803f01b22c2247 100644 (file)
@@ -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 "
               );
index 3e76c120b1a0468cc15df15637202c80e098b5d9..b157d4794c114f9845c24978fe84d182592e2ab0 100644 (file)
@@ -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
index badb701e08579e8aa7bb4f70ec8b027eaaae0380..aab1317a9083cc87fb7cc07ae2cd7416e85cece6 100644 (file)
@@ -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)
index 6850541afaeb1c8bb209c42208f0a68b1955ffdd..4ee3be0179e3a6c155d035eb557d19bc5f78bf8f 100644 (file)
@@ -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
 }
index 0b8e0680beb76ecb72f1d005b37b1c4921ba54f6..6475a719c1b1de20a6ed03fede4fffd224deb9dd 100644 (file)
@@ -301,6 +301,7 @@ neumeDemoLayout = \layout {
        \consists Vaticana_ligature_engraver
        \override NoteHead #'style = #'vaticana.punctum
        \override Stem #'transparent = ##t
+       \override Flag #'transparent = ##t
     }
 }
 
index 0175bb798fe405134afd05236f81f182001af729..02acc1b4e6c50f263e44496f6ba14b6a864265ac 100644 (file)
@@ -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
 }
 
index a45f1053d178aa69bee605845be3c4ca7a7931a0..11493d87e4eadf8066988277050dc5bec7c992aa 100644 (file)
@@ -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.")
index 3055af219bfb916547a7e1e1b9bad26fa48e2c4a..4beeb04dbf6c9d60433ea19ccdcd1096f3a71d0b 100644 (file)
        (clip-edges . #t)
        (collision-interfaces . (beam-interface
                                 clef-interface
+                                flag-interface
                                 inline-accidental-interface
                                 key-signature-interface
                                 note-head-interface
                                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)
 
        (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)
        (Y-extent . ,ly:stem::height)
        (Y-offset . ,ly:staff-symbol-referencer::callback)
        (meta . ((class . Item)
-                (interfaces . (font-interface
-                               stem-interface))))))
+                (interfaces . (stem-interface))))))
 
     (StemTremolo
      . (
    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
   (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))
index 9e1a268e4d54ca8e9f91fc2c9a67589467835cde..bce6cab5db494f2811a0782fa3943170874376e6 100644 (file)
@@ -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)))))
index 8cdd53955f61790bd5e4b3378c7bcc6c74ac9f9b..d7fedb689d9cf3e69a445ec7c4731ce176fe75b0 100644 (file)
@@ -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)