- 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 ())
- {
- 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->insert (b, 0, X_AXIS);
- elements[i]->set_property ("outside-staff-priority", SCM_BOOL_F);
- last_affected_position[dir] = b[X_AXIS][RIGHT];
- }
-
- /*
- Ugh: quadratic. --hwn
- */
- elements.erase (elements.begin () + i);
- }
+ Drul_array<Real> last_end (-infinity_f, -infinity_f);
+ vector<Grob *> skipped_elements;
+ for (vsize i = l2r ? 0 : elements.size ();
+ l2r ? i < elements.size () : i--;
+ l2r ? i++ : 0)
+ {
+ Grob *elt = elements[i];
+ Real padding
+ = robust_scm2double (elt->get_property ("outside-staff-padding"),
+ Axis_group_interface
+ ::get_default_outside_staff_padding ());
+ Real horizon_padding
+ = robust_scm2double (elt->get_property ("outside-staff-horizontal-padding"), 0.0);
+ Interval x_extent = elt->extent (x_common, X_AXIS);
+ x_extent.widen (horizon_padding);
+
+ Direction dir = get_grob_direction (elt);
+ if (dir == CENTER)
+ {
+ warning (_ ("an outside-staff object should have a direction, defaulting to up"));
+ dir = UP;
+ }
+
+ if (x_extent[LEFT] <= last_end[dir] && polite)
+ {
+ skipped_elements.push_back (elt);
+ continue;
+ }
+ last_end[dir] = x_extent[RIGHT];
+
+ Skyline_pair *v_orig = unsmob<Skyline_pair> (elt->get_property ("vertical-skylines"));
+ if (!v_orig || v_orig->is_empty ())
+ continue;
+
+ // Find the riders associated with this grob, and merge their
+ // skylines with elt's skyline.
+ typedef multimap<Grob *, Grob *>::const_iterator GrobMapIterator;
+ pair<GrobMapIterator, GrobMapIterator> range = riders.equal_range (elt);
+ vector<Skyline_pair> rider_v_skylines;
+ for (GrobMapIterator j = range.first; j != range.second; j++)
+ {
+ Grob *rider = j->second;
+ Skyline_pair *v_rider = unsmob<Skyline_pair> (rider->get_property ("vertical-skylines"));
+ if (v_rider)
+ {
+ Skyline_pair copy (*v_rider);
+ copy.shift (rider->relative_coordinate (x_common, X_AXIS));
+ copy.raise (rider->relative_coordinate (y_common, Y_AXIS));
+ rider_v_skylines.push_back (copy);
+ }
+ }
+ Skyline_pair v_skylines (*v_orig);
+ v_skylines.shift (elt->relative_coordinate (x_common, X_AXIS));
+ v_skylines.raise (elt->relative_coordinate (y_common, Y_AXIS));
+ v_skylines.merge (Skyline_pair (rider_v_skylines));
+
+ avoid_outside_staff_collisions (elt,
+ &v_skylines,
+ padding,
+ horizon_padding,
+ (*all_v_skylines)[dir],
+ (*all_paddings)[dir],
+ (*all_horizon_paddings)[dir],
+ dir);
+
+ elt->set_property ("outside-staff-priority", SCM_BOOL_F);
+ (*all_v_skylines)[dir].push_back (v_skylines);
+ (*all_paddings)[dir].push_back (padding);
+ (*all_horizon_paddings)[dir].push_back (horizon_padding);
+ }
+ swap (elements, skipped_elements);
+ skipped_elements.clear ();