+/* We want to avoid situations like this:
+ still more text
+ more text
+ text
+ -------------------
+ staff
+ -------------------
+
+ The point is that "still more text" should be positioned under
+ "more text". In order to achieve this, we place the grobs in several
+ passes. We keep track of the right-most horizontal position that has been
+ affected by the current pass so far (actually we keep track of 2
+ positions, one for above the staff, one for below).
+
+ In each pass, we loop through the unplaced grobs from left to right.
+ If the grob overlaps the right-most affected position, we place it
+ (and then update the right-most affected position to point to the right
+ edge of the just-placed grob). Otherwise, we skip it until the next pass.
+*/
+static void
+add_grobs_of_one_priority (Drul_array<Skyline> *const skylines,
+ vector<Grob*> elements,
+ Grob *x_common,
+ Grob *y_common)
+{
+ vector<Box> boxes;
+ Drul_array<Real> last_affected_position;
+
+ reverse (elements);
+ while (!elements.empty ())
+ {
+ last_affected_position[UP] = -infinity_f;
+ last_affected_position[DOWN] = -infinity_f;
+ /* do one pass */
+ for (vsize i = elements.size (); i--;)
+ {
+ Direction dir = get_grob_direction (elements[i]);
+ if (dir == CENTER)
+ {
+ warning (_ ("an outside-staff object should have a direction, defaulting to up"));
+ dir = UP;
+ }
+
+ Box b (elements[i]->extent (x_common, X_AXIS),
+ elements[i]->extent (y_common, Y_AXIS));
+ SCM horizon_padding_scm = elements[i]->get_property ("outside-staff-horizontal-padding");
+ Real horizon_padding = robust_scm2double (horizon_padding_scm, 0.0);
+
+ if (b[X_AXIS][LEFT] - 2*horizon_padding < last_affected_position[dir])
+ continue;
+
+ if (b[X_AXIS].is_empty () || b[Y_AXIS].is_empty ())
+ warning (_f ("outside-staff object %s has an empty extent", elements[i]->name ().c_str ()));
+ else
+ {
+ boxes.clear ();
+ boxes.push_back (b);
+ Skyline other = Skyline (boxes, horizon_padding, X_AXIS, -dir);
+ Real padding = robust_scm2double (elements[i]->get_property ("outside-staff-padding"), 0.5);
+ Real dist = (*skylines)[dir].distance (other) + padding;
+
+ if (dist > 0)
+ {
+ b.translate (Offset (0, dir*dist));
+ elements[i]->translate_axis (dir*dist, Y_AXIS);
+ }
+ (*skylines)[dir].insert (b, 0, X_AXIS);
+ elements[i]->del_property ("outside-staff-padding");
+ last_affected_position[dir] = b[X_AXIS][RIGHT];
+ }
+ elements.erase (elements.begin () + i);
+ }
+ }
+}
+