--- /dev/null
+\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 ]
+ }
+>>
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}."
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 ());
}
/* 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,
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);
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);
(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
(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