]> git.donarmstrong.com Git - lilypond.git/commitdiff
Prevents cross-staff Stems from colliding with articulations.
authorMike Solomon <mike@apollinemike.com>
Mon, 19 Dec 2011 10:00:51 +0000 (11:00 +0100)
committerMike Solomon <mike@apollinemike.com>
Mon, 19 Dec 2011 10:00:51 +0000 (11:00 +0100)
Does so by creating a StemStub grob for each Stem whose only effect on
spacing comes from its extra-spacing-height, which blocks articulations
from bumping into the Stems.  Beamed stems cannot be considered in
extra-spacing-height because they trigger a circular dependency in the
calculation of direction.

input/regression/stem-cross-staff-articulation.ly [new file with mode: 0644]
lily/grob-scheme.cc
lily/score-engraver.cc
lily/stem-engraver.cc
lily/stem.cc
scm/define-grobs.scm
scm/output-lib.scm

diff --git a/input/regression/stem-cross-staff-articulation.ly b/input/regression/stem-cross-staff-articulation.ly
new file mode 100644 (file)
index 0000000..1d8ca55
--- /dev/null
@@ -0,0 +1,33 @@
+\version "2.15.22"
+
+\header {
+  texidoc = "Cross-staff stems avoid articulations.  Articulations that don't
+get in the way of stems do not cause unwanted horizontal space.
+"
+}
+
+\new GrandStaff <<
+  \new Staff = "a" { s1 }
+  \new Staff = "b" {
+    \stemDown
+    \clef bass
+    d'8^\prall^\espressivo [\change Staff="a" g'' ]
+    g'' [\change Staff="b" d'8^\prall^\espressivo ]
+    \stemUp
+    f, [\change Staff="a" b8_\prall_\espressivo ]
+    b_\prall_\espressivo [\change Staff="b" f,8 ]
+  }
+>>
+
+\new GrandStaff <<
+  \new Staff = "a" { s1 }
+  \new Staff = "b" {
+    \stemDown
+    \clef bass
+    d'8 [\change Staff="a" g'' ]
+    g'' [\change Staff="b" d'8 ]
+    \stemUp
+    f, [\change Staff="a" b8 ]
+    b [\change Staff="b" f,8 ]
+  }
+>>
index 92f755d7a77e3eb098d84f1c3fa031c13a558d0a..3983cac70c2f1f2a7ba2c83356b89e8a2c2e4802 100644 (file)
@@ -100,6 +100,27 @@ LY_DEFINE (ly_grob_pure_property, "ly:grob-pure-property",
   return retval;
 }
 
+LY_DEFINE (ly_grob_pure_height, "ly:grob-pure-height",
+           4, 1, 0, (SCM grob, SCM refp, SCM beg, SCM end, SCM val),
+           "Return the pure height of @var{grob} given refpoint @var{refp}."
+           "  If no value is found, return @var{val} or @code{'()}"
+           " if @var{val} is not specified.")
+{
+  Grob *sc = unsmob_grob (grob);
+  Grob *ref = unsmob_grob (refp);
+
+  LY_ASSERT_SMOB (Grob, grob, 1);
+  LY_ASSERT_SMOB (Grob, refp, 2);
+  LY_ASSERT_TYPE (scm_is_integer, beg, 3);
+  LY_ASSERT_TYPE (scm_is_integer, end, 4);
+  if (val == SCM_UNDEFINED)
+    val = SCM_EOL;
+
+  Interval retval = sc->pure_height (ref, scm_to_int (beg), scm_to_int (end));
+
+  return ly_interval2scm (retval);
+}
+
 LY_DEFINE (ly_grob_property, "ly:grob-property",
            2, 1, 0, (SCM grob, SCM sym, SCM val),
            "Return the value for property @var{sym} of @var{grob}."
index 227c86c41e29753a842f9260ca66e1ee34f67ffb..cb3808d948c6ae8b984b6f27201f152eff76ed88 100644 (file)
@@ -155,13 +155,13 @@ Score_engraver::one_time_step (SCM)
   precomputed_recurse_over_translators (context (), STOP_TRANSLATION_TIMESTEP, UP);
   typeset_all ();
 }
-
+#include <valgrind/valgrind.h>
 void
 Score_engraver::announce_grob (Grob_info info)
 {
   Engraver_group::announce_grob (info);
   if (info.start_end () == START)
-    {
+    {if (info.grob ()->name () == "StemStub") VALGRIND_PRINTF_BACKTRACE ("foo");
       pscore_->root_system ()->typeset_grob (info.grob ());
       elems_.push_back (info.grob ());
     }
index 04184a90203891e73fd53086ce50c34b8938b981..67a2bffb736a6c0181bef68a341ccf2fe51a9833 100644 (file)
@@ -68,6 +68,7 @@ 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 ());
+  (void) make_item ("StemStub", gi.grob ()->self_scm ());
   if (tremolo_ev_)
     {
       /* Stem tremolo is never applied to a note by default,
index 568e1846c376e7f57cd28fe5b55e47fb0ed1562c..c07a2164a5d691bf73ff70a5bbb0725001c78565 100644 (file)
@@ -302,7 +302,7 @@ Stem::internal_pure_height (Grob *me, bool calc_beam)
 
   if (!beam)
     return iv;
-  if (!to_boolean (me->get_property ("cross-staff")) && calc_beam)
+  if (calc_beam)
     {
       Interval overshoot;
       Direction dir = get_grob_direction (me);
@@ -315,12 +315,35 @@ Stem::internal_pure_height (Grob *me, bool calc_beam)
       vector<Grob *> my_stems;
       extract_grob_set (beam, "normal-stems", normal_stems);
       for (vsize i = 0; i < normal_stems.size (); i++)
-        if (normal_stems[i] != me && get_grob_direction (normal_stems[i]) == dir)
+        if (get_grob_direction (normal_stems[i]) == dir)
           {
-            heights.push_back (Stem::internal_pure_height (normal_stems[i], false));
+            if (normal_stems[i] != me)
+              heights.push_back (Stem::internal_pure_height (normal_stems[i], false));
+            else
+              heights.push_back (iv);
             my_stems.push_back (normal_stems[i]);
-            iv.unite (heights.back ());
           }
+      //iv.unite (heights.back ());
+      // look for cross staff effects
+      vector<Real> coords;
+      Grob *common = common_refpoint_of_array (my_stems, me, Y_AXIS);
+      Real min_pos = infinity_f;
+      Real max_pos = -infinity_f;
+      for (vsize i = 0; i < my_stems.size (); i++)
+        {
+          coords.push_back (my_stems[i]->pure_relative_y_coordinate (common, 0, INT_MAX));
+          min_pos = min (min_pos, coords[i]);
+          max_pos = max (max_pos, coords[i]);
+        }
+      for (vsize i = 0; i < heights.size (); i++)
+        {
+          heights[i][dir] += dir == DOWN
+                             ? coords[i] - max_pos
+                             : coords[i] - min_pos;
+        }
+
+      for (vsize i = 0; i < heights.size (); i++) iv.unite (heights[i]);
+
       for (vsize i = 0; i < my_stems.size (); i++)
         cache_pure_height (my_stems[i], iv, heights[i]);
       iv.intersect (overshoot);
index 08b3ff5f1416f87fe29f325937f6797d85d25a96..2009b46dee82a81b74b1d79ab01283edcb445ed0 100644 (file)
        (meta . ((class . Item)
                 (interfaces . (stem-interface))))))
 
+    (StemStub
+     . (
+        (X-extent . ,stem-stub::width)
+       (extra-spacing-height . ,stem-stub::extra-spacing-height)
+       (Y-extent . ,(ly:make-unpure-pure-container #f stem-stub::pure-height))
+       (meta . ((class . Item)
+                (interfaces . ())))))
+
     (StemTremolo
      . (
        (beam-thickness . 0.48) ; staff-space
index 84f9984b3399eb57b443da13b284d9f7be6b81d1..51a45aab5567b222a1c41a3a86d094fed9580610 100644 (file)
          (beg (ly:grob-pure-property grob 'stem-begin-position 0 1000)))
     (abs (- (ly:stem::pure-calc-stem-end-position grob 0 2147483646) beg))))
 
+(define (stem-stub::do-calculations grob)
+  (and (ly:grob-property (ly:grob-parent grob X) 'cross-staff)
+       (not (ly:grob-property (ly:grob-parent grob X) 'transparent))))
+
+(define-public (stem-stub::pure-height grob beg end)
+  (if (stem-stub::do-calculations grob)
+      '(0 . 0)
+      '(+inf.0 . -inf.0)))
+
+(define-public (stem-stub::width grob)
+  (if (stem-stub::do-calculations grob)
+      (grob::x-parent-width grob)
+      '(+inf.0 . -inf.0)))
+
+(define-public (stem-stub::extra-spacing-height grob)
+  (if (stem-stub::do-calculations grob)
+      (let* ((dad (ly:grob-parent grob X))
+             (refp (ly:grob-common-refpoint grob dad Y))
+             (stem_ph (ly:grob-pure-height dad refp 0 1000000))
+             (my_ph (ly:grob-pure-height grob refp 0 1000000))
+             ;; only account for distance if stem is on different staff than stub
+             (dist (if (grob::has-interface refp 'hara-kiri-group-spanner-interface)
+                       0
+                       (- (car my_ph) (car stem_ph)))))
+        (if (interval-empty? (interval-intersection stem_ph my_ph)) #f (coord-translate stem_ph dist)))
+      #f))
+
 (define-public (note-head::calc-duration-log grob)
   (min 2
        (ly:duration-log