]> git.donarmstrong.com Git - lilypond.git/commitdiff
Issue 3518: Support temporary divisi staves
authorDavid Kastrup <dak@gnu.org>
Wed, 20 Aug 2014 12:27:55 +0000 (14:27 +0200)
committerDavid Kastrup <dak@gnu.org>
Sun, 24 Aug 2014 11:27:26 +0000 (13:27 +0200)
This provides the low-level support for temporary divisi staves by
adding a `VerticalAxisGroup.remove-layer' property of type integer that
interacts with the "Keep_alive_together_engraver": when set to a numeric
value, staves with the same numeric value are kept alive together as one
group.  Of several such groups with live staves, only the one with the
lowest common numeric `remove-layer' is retained.

lily/hara-kiri-group-spanner.cc
lily/keep-alive-together-engraver.cc
scm/define-grob-properties.scm

index b7c55b5045f903b0b22ec46c3b5cd10a707b0dc5..8afef8f5ea9000df79896b278051181b14621207 100644 (file)
@@ -77,6 +77,11 @@ bool find_in_range (SCM vector, int low, int hi, int min, int max)
 bool
 Hara_kiri_group_spanner::request_suicide (Grob *me, int start, int end)
 {
+  extract_grob_set (me, "make-dead-when", foes);
+  for (vsize i = 0; i < foes.size (); i++)
+    if (foes[i]->is_live () && !request_suicide_alone (foes[i], start, end))
+      return true;
+
   if (!request_suicide_alone (me, start, end))
     return false;
 
@@ -185,13 +190,16 @@ 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.",
+               " 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.",
 
                /* properties */
                "items-worth-living "
                "important-column-ranks "
                "keep-alive-with "
+               "make-dead-when "
                "remove-empty "
                "remove-first "
+               "remove-layer "
               );
-
index 78a10050cd24ff55544f52c65618084d166aa0ba..c65ff455313f382a74a1f3c28504da924fbdc5f4 100644 (file)
@@ -51,14 +51,40 @@ Keep_alive_together_engraver::finalize ()
 {
   for (vsize i = 0; i < group_spanners_.size (); ++i)
     {
-      SCM grob_array_scm = Grob_array::make_array ();
-      Grob_array *ga = Grob_array::unsmob (grob_array_scm);
-
-      // It would make Hara_kiri_group_spanner::request_suicide a _little_
-      // faster if we removed each grob from its own array. It seems
-      // unnecessary for now, though.
-      ga->set_array (group_spanners_);
-      group_spanners_[i]->set_object ("keep-alive-with", grob_array_scm);
+      SCM this_layer = group_spanners_[i]->get_property ("remove-layer");
+      if (scm_is_false (this_layer))
+        continue;
+
+      SCM live_scm = Grob_array::make_array ();
+      Grob_array *live = Grob_array::unsmob (live_scm);
+      SCM dead_scm = Grob_array::make_array ();
+      Grob_array *dead = Grob_array::unsmob (dead_scm);
+
+      for (vsize j = 0; j < group_spanners_.size (); ++j)
+        {
+          if (i == j)
+            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
+              live->add (group_spanners_[j]);
+              continue;
+            }
+          // an explicit layer is only affected by explicit layers
+          if (!scm_is_integer (that_layer))
+            continue;
+          if (scm_is_true (scm_num_eq_p (that_layer, this_layer)))
+            live->add (group_spanners_[j]);
+          else if (scm_is_true (scm_less_p (that_layer, this_layer)))
+            dead->add (group_spanners_[j]);
+        }
+      if (!live->empty ())
+        group_spanners_[i]->set_object ("keep-alive-with", live_scm);
+      if (!dead->empty ())
+        group_spanners_[i]->set_object ("make-dead-when", dead_scm);
     }
 }
 
index 485c3519dc857e51f01cf4def623e4984d4175ad..a81eed50092532ff51f15dac177a062e2edc8386 100644 (file)
@@ -788,6 +788,12 @@ 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.")
      (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.")
@@ -1241,6 +1247,8 @@ empty in a particular staff, then that staff is erased.")
      (left-neighbor ,ly:grob? "The right-most column that has a spacing-wish
 for this column.")
 
+     (make-dead-when ,ly:grob-array? "An array of other
+@code{VerticalAxisGroup}s.  If any of them are alive, then we will turn dead.")
      (melody-spanner ,ly:grob? "The @code{MelodyItem} object for a stem.")
      (minimum-translations-alist ,list? "An list of translations for a given
 start and end point.")