summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Knoop <mark@opus11.net>2016-09-08 18:56:16 +0100
committerJames Lowe <pkx166h@gmail.com>2016-09-08 18:56:40 +0100
commit5944d20489bb5b8e4c4907fa3b3bcae9ec275ccb (patch)
tree6ad0b84f5685085aab33faa42d43e4f26aff3d23
parent93f3d637efbc038b837cf64fae0872e873e4f039 (diff)
Keep a staff alive with multiple layers
This allows the `VerticalAxisGroup.remove-layer' property to accept a list of values. The layer will stay alive with any other member of the Keep_alive_together_engrave group with a remove-layer value in that list. The principal reason for this patch was to allow the use of MarkLine contexts in a Frenched score, where the context should stay alive with any single staff in a StaffGroup. This implementation should also allow additional flexibility with ossia and divisi staves.
-rw-r--r--Documentation/snippets/new/using-marklines-in-a-frenched-score.ly97
-rw-r--r--input/regression/remove-layer-symbol.ly65
-rw-r--r--lily/hara-kiri-group-spanner.cc8
-rw-r--r--lily/keep-alive-together-engraver.cc35
-rw-r--r--scm/define-grob-properties.scm16
5 files changed, 211 insertions, 10 deletions
diff --git a/Documentation/snippets/new/using-marklines-in-a-frenched-score.ly b/Documentation/snippets/new/using-marklines-in-a-frenched-score.ly
new file mode 100644
index 0000000000..0fdefc9138
--- /dev/null
+++ b/Documentation/snippets/new/using-marklines-in-a-frenched-score.ly
@@ -0,0 +1,97 @@
+\version "2.19.48"
+\header {
+ lsrtags = "contexts-and-engravers, staff-notation"
+ texidoc = "
+Using @{MarkLine} contexts (such as in
+@uref{http://lsr.di.unimi.it/LSR/Item?id=1010, LSR1010}) in a
+Frenched score can be problematic if all the staves between two
+@code{MarkLine}s are removed in one system. The
+@code{Keep_alive_together_engraver} can be used within each
+@code{StaffGroup} to keep the @code{MarkLine} alive only as long
+as the other staves in the group stay alive.
+"
+ doctitle = "Using marklines in a Frenched score"
+}
+bars = {
+ \tempo "Allegro" 4=120
+ s1*2
+ \repeat unfold 5 { \mark \default s1*2 }
+ \bar "||"
+ \tempo "Adagio" 4=40
+ s1*2
+ \repeat unfold 8 { \mark \default s1*2 }
+ \bar "|."
+}
+winds = \repeat unfold 120 { c''4 }
+trumpet = { \repeat unfold 8 g'2 R1*16 \repeat unfold 4 g'2 R1*8 }
+trombone = { \repeat unfold 4 c'1 R1*8 d'1 R1*17 }
+strings = \repeat unfold 240 { c''8 }
+
+#(set-global-staff-size 16)
+\paper {
+ systems-per-page = 5
+ ragged-last-bottom = ##f
+}
+
+\layout {
+ indent = 15\mm
+ short-indent = 5\mm
+ \context {
+ \name MarkLine
+ \type Engraver_group
+ \consists Output_property_engraver
+ \consists Axis_group_engraver
+ \consists Mark_engraver
+ \consists Metronome_mark_engraver
+ \override VerticalAxisGroup.remove-empty = ##t
+ \override VerticalAxisGroup.remove-layer = #'any
+ \override VerticalAxisGroup.staff-affinity = #DOWN
+ \override VerticalAxisGroup.nonstaff-relatedstaff-spacing.basic-distance = 1
+ keepAliveInterfaces = #'()
+ }
+ \context {
+ \Staff
+ \override VerticalAxisGroup.remove-empty = ##t
+ \override VerticalAxisGroup.remove-layer = ##f
+ }
+ \context {
+ \StaffGroup
+ \accepts MarkLine
+ \consists Keep_alive_together_engraver
+ }
+ \context {
+ \Score
+ \remove Mark_engraver
+ \remove Metronome_mark_engraver
+ }
+}
+
+\score {
+ <<
+ \new StaffGroup = "winds" \with {
+ instrumentName = "Winds"
+ shortInstrumentName = "Winds"
+ } <<
+ \new MarkLine \bars
+ \new Staff \winds
+ >>
+ \new StaffGroup = "brass" <<
+ \new MarkLine \bars
+ \new Staff = "trumpet" \with {
+ instrumentName = "Trumpet"
+ shortInstrumentName = "Tpt"
+ } \trumpet
+ \new Staff = "trombone" \with {
+ instrumentName = "Trombone"
+ shortInstrumentName = "Tbn"
+ } \trombone
+ >>
+ \new StaffGroup = "strings" \with {
+ instrumentName = "Strings"
+ shortInstrumentName = "Strings"
+ } <<
+ \new MarkLine \bars
+ \new Staff = "strings" { \strings }
+ >>
+ >>
+}
diff --git a/input/regression/remove-layer-symbol.ly b/input/regression/remove-layer-symbol.ly
new file mode 100644
index 0000000000..d6fa93dcdd
--- /dev/null
+++ b/input/regression/remove-layer-symbol.ly
@@ -0,0 +1,65 @@
+\version "2.19.48"
+
+\header {
+ texidoc = "The @code{VerticalAxisGroup.remove-layer} property
+ can be used to keep staves alive with reference to other staves
+ in the @code{Keep_alive_together_engraver} group."
+}
+
+\layout {
+ indent = 40\mm
+ short-indent = 15\mm
+}
+
+\score {
+ <<
+ \new Staff \with {
+ instrumentName = "Continuous"
+ shortInstrumentName = "cont"
+ } { \repeat unfold 104 g'4 \bar "|." }
+ \new StaffGroup \with {
+ \consists Keep_alive_together_engraver
+ } <<
+ \new Staff \with {
+ keepAliveInterfaces = #'()
+ instrumentName = \markup \center-column { "Alive with A or B" }
+ shortInstrumentName = "with A or B"
+ \override VerticalAxisGroup.remove-empty = ##t
+ \override VerticalAxisGroup.remove-first = ##t
+ \override VerticalAxisGroup.remove-layer = #'any
+ } { \repeat unfold 104 c''4 }
+ \new Staff \with {
+ instrumentName = "A"
+ shortInstrumentName = "A"
+ \override VerticalAxisGroup.remove-empty = ##t
+ \override VerticalAxisGroup.remove-first = ##t
+ \override VerticalAxisGroup.remove-layer = ##f
+ } {
+ \repeat unfold 16 c'4
+ R1*4
+ \repeat unfold 16 c'4
+ R1*14
+ }
+ \new Staff \with {
+ keepAliveInterfaces = #'()
+ instrumentName = \markup \center-column { "Alive with A" }
+ shortInstrumentName = "with A"
+ \override VerticalAxisGroup.remove-empty = ##t
+ \override VerticalAxisGroup.remove-first = ##t
+ \override VerticalAxisGroup.remove-layer = #'above
+ } { \repeat unfold 104 c''4 }
+ \new Staff \with {
+ instrumentName = "B"
+ shortInstrumentName = "B"
+ \override VerticalAxisGroup.remove-empty = ##t
+ \override VerticalAxisGroup.remove-first = ##t
+ \override VerticalAxisGroup.remove-layer = ##f
+ } {
+ R1*8
+ \repeat unfold 16 c'4
+ R1*13
+ c'1
+ }
+ >>
+ >>
+}
diff --git a/lily/hara-kiri-group-spanner.cc b/lily/hara-kiri-group-spanner.cc
index 06410786a6..76207a5c92 100644
--- a/lily/hara-kiri-group-spanner.cc
+++ b/lily/hara-kiri-group-spanner.cc
@@ -190,9 +190,11 @@ Hara_kiri_group_spanner::add_interesting_item (Grob *me, Grob *n)
ADD_INTERFACE (Hara_kiri_group_spanner,
"A group spanner that keeps track of interesting items. If it"
" doesn't contain any after line breaking, it removes itself"
- " and all its children. Children may be prioritized in layers"
- " via @code{remove-layer}, in which case only the"
- " lowest-numbered non-empty layer is retained.",
+ " and all its children. Greater control can be exercised via"
+ " @code{remove-layer} which can prioritize layers so only the"
+ " lowest-numbered non-empty layer is retained; make the layer"
+ " independent of the group; or make it dependent on any other"
+ " member of the group",
/* properties */
"items-worth-living "
diff --git a/lily/keep-alive-together-engraver.cc b/lily/keep-alive-together-engraver.cc
index 9b1cbe4a23..8931a819c6 100644
--- a/lily/keep-alive-together-engraver.cc
+++ b/lily/keep-alive-together-engraver.cc
@@ -22,6 +22,7 @@
#include "engraver.hh"
#include "grob.hh"
#include "grob-array.hh"
+#include "international.hh"
#include "translator.icc"
@@ -64,12 +65,44 @@ Keep_alive_together_engraver::finalize ()
{
if (i == j)
continue;
+
+ if (scm_is_symbol (this_layer))
+ {
+ if (scm_is_eq (this_layer, ly_symbol2scm ("any")))
+ {
+ // layer is kept alive by any other layer
+ live->add (group_spanners_[j]);
+ continue;
+ }
+ else if (scm_is_eq (this_layer, ly_symbol2scm ("above")))
+ {
+ // layer is kept alive by the layer preceding it
+ if (i == j + 1)
+ live->add (group_spanners_[j]);
+ continue;
+ }
+ else if (scm_is_eq (this_layer, ly_symbol2scm ("below")))
+ {
+ // layer is kept alive by the layer following it
+ if (i == j - 1)
+ live->add (group_spanners_[j]);
+ continue;
+ }
+ else
+ {
+ group_spanners_[i]->warning (_f ("unknown remove-layer value `%s'",
+ ly_symbol2string (this_layer).c_str ()));
+ continue;
+ }
+ }
+
SCM that_layer = group_spanners_[j]->get_property ("remove-layer");
+
if (scm_is_false (that_layer))
continue;
if (!scm_is_integer (this_layer))
{
- // Unspecified layers are kept alive by anything else
+ // unset layers are kept alive by all but ignored layers
live->add (group_spanners_[j]);
continue;
}
diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm
index 7ca44b6f3d..d55ab4c8c7 100644
--- a/scm/define-grob-properties.scm
+++ b/scm/define-grob-properties.scm
@@ -809,12 +809,16 @@ number, the quicker the slur attains its @code{height-limit}.")
interesting items.")
(remove-first ,boolean? "Remove the first staff of an orchestral
score?")
- (remove-layer ,integer? "The @code{Keep_alive_together_engraver}
-removes all @code{VerticalAxisGroup} grobs with a @code{remove-layer}
-larger than the smallest retained @code{remove-layer}. Set to
-@code{#f} to make a layer invisible to the
-@code{Keep_alive_together_engraver}, set to @code{'()} to have it not
-participate in the layering decisions.")
+ (remove-layer ,key? "When set as a positive integer, the
+@code{Keep_alive_together_engraver} removes all
+@code{VerticalAxisGroup} grobs with a @code{remove-layer} larger than
+the smallest retained @code{remove-layer}. Set to @code{#f} to make a
+layer independent of the @code{Keep_alive_together_engraver}. Set to
+@code{'()}, the layer does not participate in the layering decisions.
+The property can also be set as a symbol for common behaviors:
+@code{#'any} to keep the layer alive with any other layer in the
+group; @code{#'above} or @code{#'below} to keep the layer alive with
+the context immediately before or after it, respectively.")
(replacement-alist ,list? "Alist of strings.
The key is a string of the pattern to be replaced. The value is a
string of what should be displayed. Useful for ligatures.")