#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"
#include "item.hh"
#include "paper-column.hh"
#include "paper-score.hh"
+#include "std-vector.hh"
#include "system.hh"
#include "warn.hh"
}
}
+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<Grob*> elements (ro_elements);
+ vector_sort (elements, staff_priority_less);
+ Grob *x_common = common_refpoint_of_array (elements, me, X_AXIS);
+
+ vsize i = 0;
+ vector<Box> 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<Skyline> 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.",
"meta "
"minimum-X-extent "
"minimum-Y-extent "
+ "outside-staff-priority "
"rotation "
"springs-and-rods "
"staff-symbol "
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<Grob*> const &list,
Grob *common, Axis);
static Interval relative_pure_height (Grob *me, vector<Grob*> const &list,
#ifndef GROB_HH
#define GROB_HH
+#include "box.hh"
#include "virtual-methods.hh"
#include "dimension-cache.hh"
#include "grob-interface.hh"
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);
Skyline::insert (Box const &b, Axis a)
{
list<Building> other_bld;
- list<Building> my_bld (buildings_);
+ list<Building> 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 ());
(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
(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))))))
(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