Reviewers: ,
Message:
I think that this is sufficient to "fix" issue 36. As Graham points out
in the tracker, it is difficult to imagine what a good solution is, and
I have a feeling that the solution likely depends upon the user's
preferences. In certain situations I can see making the hairpin take up
less vertical space and using whiteout, in other situations I can see it
being rotated to follow the slope of the beam. In either of these
cases, in order to know if an intersection occurs, the hairpin needs to
know:
a) The cross staff beams that happen during it.
b) The left and right Y-positions of the beams.
c) The left and right X-positions of the beams.
d) Its own left and right X/Y positions.
(a) is currently impossible to calculate in all circumstances, and (c)
would require a code dup. I think by making these available as
properties, the user can then use this data to fix the problem. In the
example given in Issue 36, I would personally rotate the stencil
downwards, and this patch would give me all the data necessary to create
an override for Beam #'rotation.
Cheers,
MS
Please review this at http://codereview.appspot.com/4809051/
Affected files:
M lily/beam.cc
M lily/hairpin.cc
M lily/include/beam.hh
M lily/new-dynamic-engraver.cc
M scm/define-grob-properties.scm
M scm/define-grobs.scm
Index: lily/beam.cc
diff --git a/lily/beam.cc b/lily/beam.cc
index
1bb0a209a859666c271dfed1c955d556723ecfa0..e27844c1bb61f0a5ad912e61060032eee7514ce0
100644
--- a/lily/beam.cc
+++ b/lily/beam.cc
@@ -548,6 +548,29 @@ Beam::get_beam_segments (Grob *me_grob, Grob **common)
return segments;
}
+MAKE_SCHEME_CALLBACK (Beam, calc_x_positions, 1);
+SCM
+Beam::calc_x_positions (SCM grob)
+{
+ Spanner *me = unsmob_spanner (grob);
+ Grob *commonx = 0;
+
+ Interval span;
+ if (normal_stem_count (me))
+ {
+ span[LEFT] = first_normal_stem (me)->relative_coordinate (commonx,
X_AXIS);
+ span[RIGHT] = last_normal_stem (me)->relative_coordinate (commonx,
X_AXIS);
+ }
+ else
+ {
+ extract_grob_set (me, "stems", stems);
+ span[LEFT] = stems[0]->relative_coordinate (commonx, X_AXIS);
+ span[RIGHT] = stems.back ()->relative_coordinate (commonx, X_AXIS);
+ }
+
+ return ly_interval2scm (span);
+}
+
MAKE_SCHEME_CALLBACK (Beam, print, 1);
SCM
Beam::print (SCM grob)
@@ -558,7 +581,7 @@ Beam::print (SCM grob)
if (!segments.size ())
return SCM_EOL;
- Interval span;
+ Interval span = robust_scm2interval (me->get_property ("X-positions"),
Interval (0, 0));
if (normal_stem_count (me))
{
span[LEFT] = first_normal_stem (me)->relative_coordinate (commonx,
X_AXIS);
@@ -1876,4 +1899,5 @@ ADD_INTERFACE (Beam,
"quantized-positions "
"shorten "
"stems "
+ "X-positions "
);
Index: lily/hairpin.cc
diff --git a/lily/hairpin.cc b/lily/hairpin.cc
index
399b5d995e8876f37aec2622a947435bcdc35507..139446a70d62501a1b65e097bec2fd6998733d25
100644
--- a/lily/hairpin.cc
+++ b/lily/hairpin.cc
@@ -250,6 +250,7 @@ Hairpin::print (SCM smob)
mol.translate_axis (x_points[LEFT]
- bounds[LEFT]->relative_coordinate (common, X_AXIS),
X_AXIS);
+
return mol.smobbed_copy ();
}
@@ -259,6 +260,7 @@ ADD_INTERFACE (Hairpin,
/* properties */
"adjacent-spanners "
"circled-tip "
+ "cross-staff-beams "
"bound-padding "
"grow-direction "
"height "
Index: lily/include/beam.hh
diff --git a/lily/include/beam.hh b/lily/include/beam.hh
index
f541a216be2966b4732eedc1ed7ceb838fb4458e..1be7d7fde98d91fc58586bb68680a4015966dc95
100644
--- a/lily/include/beam.hh
+++ b/lily/include/beam.hh
@@ -77,6 +77,7 @@ public:
DECLARE_SCHEME_CALLBACK (calc_stem_shorten, (SCM));
DECLARE_SCHEME_CALLBACK (calc_direction, (SCM));
DECLARE_SCHEME_CALLBACK (calc_positions, (SCM));
+ DECLARE_SCHEME_CALLBACK (calc_x_positions, (SCM));
DECLARE_SCHEME_CALLBACK (calc_least_squares_positions, (SCM, SCM));
DECLARE_SCHEME_CALLBACK (calc_normal_stems, (SCM));
DECLARE_SCHEME_CALLBACK (calc_concaveness, (SCM));
Index: lily/new-dynamic-engraver.cc
diff --git a/lily/new-dynamic-engraver.cc b/lily/new-dynamic-engraver.cc
index
e225d97f1fd1bf4285988c27700839ebb3bca595..8d9ef01d087ea6216906fb74df4816e6f36a3f19
100644
--- a/lily/new-dynamic-engraver.cc
+++ b/lily/new-dynamic-engraver.cc
@@ -17,6 +17,7 @@
along with LilyPond. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "beam.hh"
#include "engraver.hh"
#include "hairpin.hh"
#include "international.hh"
@@ -34,6 +35,7 @@ class New_dynamic_engraver : public Engraver
{
TRANSLATOR_DECLARATIONS (New_dynamic_engraver);
DECLARE_ACKNOWLEDGER (note_column);
+ DECLARE_ACKNOWLEDGER (beam);
DECLARE_TRANSLATOR_LISTENER (absolute_dynamic);
DECLARE_TRANSLATOR_LISTENER (span_dynamic);
@@ -54,6 +56,9 @@ private:
Item *script_;
Stream_event *script_event_;
Stream_event *current_span_event_;
+
+ vector<Spanner *> cross_staff_beams_;
+ vector<Spanner *> hairpins_;
};
New_dynamic_engraver::New_dynamic_engraver ()
@@ -143,6 +148,7 @@ New_dynamic_engraver::process_music ()
}
current_spanner_ = make_spanner ("Hairpin",
current_span_event_->self_scm ());
+ hairpins_.push_back (current_spanner_);
}
if (finished_spanner_)
{
@@ -203,6 +209,41 @@ New_dynamic_engraver::finalize ()
current_spanner_->suicide ();
current_spanner_ = 0;
}
+
+ if (!cross_staff_beams_.size ())
+ return;
+
+ vector_sort (cross_staff_beams_, Grob::less);
+ vector_sort (hairpins_, Grob::less);
+ vsize start = 0;
+
+ for (vsize i = 0; i < hairpins_.size (); i++)
+ {
+ Grob *hairpin_grob = hairpins_[i];
+
+ Interval_t<int> hairpin_spanned_rank_ =
hairpin_grob->spanned_rank_interval ();
+ // Start considering grobs at the first grob whose end falls at or
after the hairpin's beginning.
+ while (cross_staff_beams_[start]->spanned_rank_interval ()[RIGHT] <
hairpin_spanned_rank_[LEFT])
+ start++;
+
+ // Stop when the grob's beginning comes after the hairpin's end.
+ for (vsize j = start; j < cross_staff_beams_.size (); j++)
+ {
+ Grob *cross_staff_beam = cross_staff_beams_[j];
+
+ Interval_t<int> cross_staff_beam_spanned_rank =
cross_staff_beam->spanned_rank_interval ();
+ if (cross_staff_beam_spanned_rank[LEFT] >
hairpin_spanned_rank_[RIGHT])
+ break;
+ /*
+ Only consider grobs whose end falls at or after the hairpin's
beginning.
+ If the grob is a hairpin, it cannot start before hairpins_[i].
+ Also, if the user wants to check for collisions only in the
hairpin's voice,
+ then make sure the hairpin and the cross_staff_beam are in
the same voice.
+ */
+ if (cross_staff_beam_spanned_rank[RIGHT] >=
hairpin_spanned_rank_[LEFT])
+ Pointer_group_interface::add_grob (hairpin_grob, ly_symbol2scm
("cross-staff-beams"), cross_staff_beam);
+ }
+ }
}
string
@@ -247,7 +288,15 @@ New_dynamic_engraver::acknowledge_note_column
(Grob_info info)
finished_spanner_->set_bound (RIGHT, info.grob ());
}
+void
+New_dynamic_engraver::acknowledge_beam (Grob_info info)
+{
+ if (Beam::is_cross_staff (info.grob ()))
+ cross_staff_beams_.push_back (dynamic_cast<Spanner *> (info.grob ()));
+}
+
ADD_ACKNOWLEDGER (New_dynamic_engraver, note_column);
+ADD_ACKNOWLEDGER (New_dynamic_engraver, beam);
ADD_TRANSLATOR (New_dynamic_engraver,
/* doc */
"Create hairpins, dynamic texts and dynamic text spanners.",
Index: scm/define-grob-properties.scm
diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm
index
40732d0e9d10997850ade1bc6b85a168fad765f8..9d4d65572aaf3dfc306577f4f82e0751ecb46110
100644
--- a/scm/define-grob-properties.scm
+++ b/scm/define-grob-properties.scm
@@ -937,6 +937,7 @@ texts.")
(X-extent ,number-pair? "Hard coded extent in X@tie{}direction.")
(X-offset ,number? "The horizontal amount that this object is
moved relative to its X-parent.")
+ (X-positions ,number-pair? "The X axis positions of a beam.")
;;
@@ -1000,6 +1001,8 @@ bounds are spaced.")
(conditional-elements ,ly:grob-array? "Internal use only.")
(covered-grobs ,ly:grob-array? "Grobs that could potentially collide
with a beam.")
+ (cross-staff-beams ,ly:grob-array? "Cross staff beams that potentially
+intersect with hairpins and other below-staff grobs.")
(direction-source ,ly:grob? "In case @code{side-relative-direction} is
set, which grob to get the direction from.")
Index: scm/define-grobs.scm
diff --git a/scm/define-grobs.scm b/scm/define-grobs.scm
index
a5c03a52755c7cc3bdfac07960833e799ba7730b..2f4854d97f7ec32ec9dafd903a6acaa776ed1758
100644
--- a/scm/define-grobs.scm
+++ b/scm/define-grobs.scm
@@ -396,7 +396,7 @@
(shorten . ,ly:beam::calc-stem-shorten)
(stencil . ,ly:beam::print)
-
+ (X-positions . ,ly:beam::calc-x-positions)
(meta . ((class . Spanner)
(object-callbacks . ((normal-stems .
,ly:beam::calc-normal-stems)))
(interfaces . (beam-interface
_______________________________________________
lilypond-devel mailing list
lilypond-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/lilypond-devel