+ Grob *e = *it;
+
+ // In the case of a stem, we will find a note head as well
+ // ignoring the stem solves cyclic dependencies if the stem is
+ // attached to a cross-staff beam.
+ bool cross_staff = to_boolean (e->get_property ("cross-staff"));
+
+ // avoid cyclic dependency for direction
+ if (a == Y_AXIS
+ && pure
+ && Stem::has_interface (e)
+ && cross_staff
+ && !is_direction (e->get_property_data ("direction")))
+ continue;
+
+ // avoid unnecessary stem look up (if pointing away, it is not
+ // supporting anything)
+ if (a == Y_AXIS
+ && Stem::has_interface (e)
+ && dir == - get_grob_direction (e))
+ continue;
+
+ if (e)
+ {
+
+
+ Skyline_pair *sp = Skyline_pair::unsmob
+ (e->get_maybe_pure_property (a == X_AXIS
+ ? "horizontal-skylines"
+ : "vertical-skylines",
+ pure || cross_staff,
+ start,
+ end));
+
+ aligns_to_cross_staff |= cross_staff;
+ if (sp)
+ {
+ Real xc = pure && dynamic_cast<Spanner *> (e)
+ ? e->get_parent (X_AXIS)->relative_coordinate (common[X_AXIS], X_AXIS)
+ : e->relative_coordinate (common[X_AXIS], X_AXIS);
+ // same logic as above
+ // we assume horizontal spacing is always pure
+ Real yc = a == X_AXIS
+ ? e->pure_relative_y_coordinate (common[Y_AXIS], start, end)
+ : e->maybe_pure_coordinate (common[Y_AXIS], Y_AXIS, pure, start, end);
+ Skyline_pair copy = Skyline_pair (*sp);
+ if (a == Y_AXIS
+ && Stem::has_interface (e)
+ && to_boolean (me->get_maybe_pure_property ("add-stem-support", pure, start, end)))
+ copy[dir].set_minimum_height (copy[dir].max_height ());
+ copy.shift (a == X_AXIS ? yc : xc);
+ copy.raise (a == X_AXIS ? xc : yc);
+ max_raise = minmax (dir, max_raise, a == X_AXIS ? xc : yc);
+ skyps.push_back (copy);
+ }
+ else { /* no warning*/ }
+ }
+ }
+
+ Skyline dim (boxes, other_axis (a), dir);
+ if (skyps.size ())
+ {
+ Skyline_pair merged (skyps);
+ dim.merge (merged[dir]);
+ }
+
+ if (include_staff)
+ {
+ Interval staff_extents;
+ common[Y_AXIS] = staff_symbol->common_refpoint (common[Y_AXIS], Y_AXIS);
+ staff_extents = staff_symbol->maybe_pure_extent (common[Y_AXIS], Y_AXIS, pure, start, end);
+ dim.set_minimum_height (staff_extents[dir]);
+ }
+
+ // Sometimes, we want to side position for grobs but they
+ // don't position against anything. Some cases where this is true:
+ // - StanzaNumber if the supporting lyrics are hara-kiri'd
+ // SystemStartBracket
+ // InstrumentName
+ // In all these cases, we set the height of the support to 0.
+ // This becomes then like the self-alignment-interface with the
+ // caveat that there is padding added.
+ // TODO: if there is a grob that never has side-support-elements
+ // (like InstrumentName), why are we using this function? Isn't it
+ // overkill? A function like self-alignment-interface with padding
+ // works just fine.
+ // One could even imagine the two interfaces merged, as the only
+ // difference is that in self-alignment-interface we align on the parent
+ // where as here we align on a group of grobs.
+ if (dim.is_empty ())
+ {
+ dim = Skyline (dim.direction ());
+ dim.set_minimum_height (0.0);
+ }
+
+ // Many cross-staff grobs do not have good height estimations.
+ // We give the grob the best chance of not colliding by shifting
+ // it to the maximum height in the case of cross-staff alignment.
+ // This means, in other words, that the old way things were done
+ // (using boxes instead of skylines) is just reactivated for
+ // alignment to cross-staff grobs.
+ if (aligns_to_cross_staff)
+ dim.set_minimum_height (dim.max_height ());
+
+ Real ss = Staff_symbol_referencer::staff_space (me);
+ Real dist = dim.distance (my_dim, robust_scm2double (me->get_maybe_pure_property ("horizon-padding", pure, start, end), 0.0));
+ Real total_off = !isinf (dist) ? dir * dist : 0.0;
+
+ total_off += dir * ss * robust_scm2double (me->get_maybe_pure_property ("padding", pure, start, end), 0.0);
+
+ Real minimum_space = ss * robust_scm2double (me->get_maybe_pure_property ("minimum-space", pure, start, end), -1);
+
+ if (minimum_space >= 0
+ && dir
+ && total_off * dir < minimum_space)
+ total_off = minimum_space * dir;
+
+ if (current_off)
+ total_off = dir * max (dir * total_off,
+ dir * (*current_off));
+
+ /* FIXME: 1000 should relate to paper size. */
+ if (fabs (total_off) > 1000)
+ {
+ string msg
+ = String_convert::form_string ("Improbable offset for grob %s: %f",
+ me->name ().c_str (), total_off);
+
+ programming_error (msg);
+ if (strict_infinity_checking)
+ scm_misc_error (__FUNCTION__, "Improbable offset.", SCM_EOL);