From: Joe Neeman Date: Tue, 21 Nov 2006 07:30:44 +0000 (+0200) Subject: Add skyline-based collision resolving for grobs above and below the staff X-Git-Tag: release/2.11.0-1~11 X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=31a6b8c4e2cbcea4a968511cdf339ccb8473108c;p=lilypond.git Add skyline-based collision resolving for grobs above and below the staff (cherry picked from 6a75680e2a8144dabaf64fbe5551814bef3f35d5 commit) --- diff --git a/lily/axis-group-interface.cc b/lily/axis-group-interface.cc index 02e900164b..366519948d 100644 --- a/lily/axis-group-interface.cc +++ b/lily/axis-group-interface.cc @@ -9,6 +9,7 @@ #include "axis-group-interface.hh" #include "align-interface.hh" +#include "directional-element-interface.hh" #include "pointer-group-interface.hh" #include "grob.hh" #include "grob-array.hh" @@ -17,6 +18,7 @@ #include "item.hh" #include "paper-column.hh" #include "paper-score.hh" +#include "std-vector.hh" #include "system.hh" #include "warn.hh" @@ -251,6 +253,68 @@ Axis_group_interface::get_children (Grob *me, vector *found) } } +bool +staff_priority_less (Grob * const &g1, Grob * const &g2) +{ + int priority_1 = robust_scm2int (g1->get_property ("outside-staff-priority"), INT_MIN); + int priority_2 = robust_scm2int (g2->get_property ("outside-staff-priority"), INT_MIN); + + if (priority_1 < priority_2) + return true; + else if (priority_1 > priority_2) + return false; + + /* if there is no preference in staff priority, choose the one with the lower rank */ + int rank_1 = g1->spanned_rank_iv ()[LEFT]; + int rank_2 = g2->spanned_rank_iv ()[LEFT]; + return rank_1 < rank_2; +} + +MAKE_SCHEME_CALLBACK (Axis_group_interface, skyline_spacing, 1) +SCM +Axis_group_interface::skyline_spacing (SCM smob) +{ + Grob *me = unsmob_grob (smob); + extract_grob_set (me, "elements", ro_elements); + vector elements (ro_elements); + vector_sort (elements, staff_priority_less); + Grob *x_common = common_refpoint_of_array (elements, me, X_AXIS); + + vsize i = 0; + vector boxes; + for (i = 0; i < elements.size () + && !scm_is_number (elements[i]->get_property ("outside-staff-priority")); i++) + boxes.push_back (Box (elements[i]->extent (x_common, X_AXIS), + elements[i]->extent (me, Y_AXIS))); + + Drul_array skylines (Skyline (boxes, X_AXIS, DOWN), + Skyline (boxes, X_AXIS, UP)); + for (; i < elements.size (); i++) + { + Direction dir = get_grob_direction (elements[i]); + if (dir == CENTER) + { + warning (_ ("an outside-staff object should have a direction")); + continue; + } + + Box b (elements[i]->extent (x_common, X_AXIS), + elements[i]->extent (me, Y_AXIS)); + boxes.clear (); + boxes.push_back (b); + Skyline other = Skyline (boxes, X_AXIS, -dir); + Real dist = skylines[dir].distance (other); + + if (dist > 0) + { + b.translate (Offset (0, dir*dist)); + elements[i]->translate_axis (dir*dist, Y_AXIS); + } + skylines[dir].insert (b, X_AXIS); + } + return SCM_UNSPECIFIED; +} + ADD_INTERFACE (Axis_group_interface, "axis-group-interface", "An object that groups other layout objects.", diff --git a/lily/grob.cc b/lily/grob.cc index 28f665138c..1456a264ef 100644 --- a/lily/grob.cc +++ b/lily/grob.cc @@ -621,6 +621,7 @@ ADD_INTERFACE (Grob, "grob-interface", "meta " "minimum-X-extent " "minimum-Y-extent " + "outside-staff-priority " "rotation " "springs-and-rods " "staff-symbol " diff --git a/lily/include/axis-group-interface.hh b/lily/include/axis-group-interface.hh index 767271ad34..3f1dbb407d 100644 --- a/lily/include/axis-group-interface.hh +++ b/lily/include/axis-group-interface.hh @@ -22,6 +22,7 @@ struct Axis_group_interface DECLARE_SCHEME_CALLBACK (width, (SCM smob)); DECLARE_SCHEME_CALLBACK (height, (SCM smob)); DECLARE_SCHEME_CALLBACK (pure_height, (SCM smob, SCM start, SCM end)); + DECLARE_SCHEME_CALLBACK (skyline_spacing, (SCM smob)); static Interval relative_group_extent (vector const &list, Grob *common, Axis); static Interval relative_pure_height (Grob *me, vector const &list, diff --git a/lily/include/grob.hh b/lily/include/grob.hh index 5eb433921a..64fb7322a6 100644 --- a/lily/include/grob.hh +++ b/lily/include/grob.hh @@ -9,6 +9,7 @@ #ifndef GROB_HH #define GROB_HH +#include "box.hh" #include "virtual-methods.hh" #include "dimension-cache.hh" #include "grob-interface.hh" diff --git a/lily/skyline.cc b/lily/skyline.cc index 731652b505..4cb07fc65f 100644 --- a/lily/skyline.cc +++ b/lily/skyline.cc @@ -153,12 +153,14 @@ Skyline::internal_merge_skyline (list *s1, list *s2, Building b = s1->front (); while (s2->front ().iv_[RIGHT] < b.iv_[RIGHT] - && s2->front ().end_height_ <= b.height (s2->front ().iv_[RIGHT])) + && s2->front ().end_height_ <= b.height (s2->front ().iv_[RIGHT]) + EPS) s2->pop_front (); /* the front of s2 either intersects with b or it ends after b */ Real end = infinity_f; - if (s2->front ().end_height_ > b.height (s2->front ().iv_[RIGHT])) + Real s2_end_height = s2->front ().end_height_; + Real s1_end_height = b.height (s2->front ().iv_[RIGHT]); + if (s2_end_height > s1_end_height + EPS) end = b.intersection (s2->front ()); end = min (end, b.iv_[RIGHT]); Real height = b.height (end); @@ -267,10 +269,11 @@ void Skyline::insert (Box const &b, Axis a) { list other_bld; - list my_bld (buildings_); + list my_bld; Interval iv = b[a]; Real height = sky_ * b[other_axis (a)][sky_]; + my_bld.splice (my_bld.begin (), buildings_); single_skyline (Building (iv[LEFT], height, height, iv[RIGHT], max_slope_), &other_bld, max_slope_); internal_merge_skyline (&other_bld, &my_bld, &buildings_); assert (is_legal_skyline ()); diff --git a/scm/define-grob-properties.scm b/scm/define-grob-properties.scm index 47f0b8c47b..bd30ea9fb9 100644 --- a/scm/define-grob-properties.scm +++ b/scm/define-grob-properties.scm @@ -274,6 +274,9 @@ get stems extending to the middle staff line.") (non-musical ,boolean? "True if the grob belongs in a NonMusicalPaperColumn.") (number-type ,symbol? "Type of numbers to use in label. Choices include @code{roman-lower}, @code{roman-upper}, and @code{arabic}.") + (outside-staff-priority ,number? "When set, the grob will be positioned outside the staff +in such a way as to avoid all collisions. In case of a potential collision, the grob with +the smaller outside-staff-priority will be closer to the staff.") (packed-spacing ,boolean? "If set, the notes are spaced as tightly as possible.") (padding ,ly:dimension? "Add this much extra space between diff --git a/scm/define-grobs.scm b/scm/define-grobs.scm index bd5dee7706..5870f82dc4 100644 --- a/scm/define-grobs.scm +++ b/scm/define-grobs.scm @@ -1643,6 +1643,7 @@ (axes . (0 1)) (X-extent . ,ly:axis-group-interface::width) (Y-extent . ,ly:axis-group-interface::height) + (after-line-breaking . ,ly:axis-group-interface::skyline-spacing) (meta . ((class . System) (interfaces . (system-interface axis-group-interface)))))) @@ -1967,6 +1968,7 @@ (Y-offset . ,ly:hara-kiri-group-spanner::force-hara-kiri-callback) (Y-extent . ,ly:hara-kiri-group-spanner::y-extent) (X-extent . ,ly:axis-group-interface::width) + (after-line-breaking . ,ly:axis-group-interface::skyline-spacing) (meta . ((class . Spanner) (interfaces . (axis-group-interface hara-kiri-group-interface