-/*
- Hairy function to put elements where they should be. Can be tweaked
- from the outside by setting extra-space in its
- children
-
- We assume that the children the refpoints of the children are still
- found at 0.0 -- we will fuck up with thresholds if children's
- extents are already moved to locations such as (-16, -8), since the
- dy needed to put things in a row doesn't relate to the distances
- between original refpoints.
-
- TODO: maybe we should rethink and throw out thresholding altogether.
- The original function has been taken over by
- align_to_fixed_distance ().
-*/
+/* for each grob, find its upper and lower skylines. If the grob has
+ an empty extent, delete it from the list instead. If the extent is
+ non-empty but there is no skyline available (or pure is true), just
+ create a flat skyline from the bounding box */
+static void
+get_skylines (Grob *me,
+ vector<Grob*> *const elements,
+ Axis a,
+ bool pure, int start, int end,
+ vector<Skyline_pair> *const ret)
+{
+ /* each child's skyline was calculated according to the common refpoint of its
+ elements. Here we need all the skylines to be positioned with respect to
+ a single refpoint, so we need the common refpoint of the common refpoints
+ of the elements of the children */
+ vector<Grob*> child_refpoints;
+ for (vsize i = 0; i < elements->size (); i++)
+ {
+ Grob *elt = (*elements)[i];
+ Grob *child_common = unsmob_grob ((a == Y_AXIS)
+ ? elt->get_object ("X-common")
+ : elt->get_object ("Y-common"));
+
+ if (!child_common)
+ {
+ extract_grob_set (elt, "elements", child_elts);
+ child_common = common_refpoint_of_array (child_elts, elt, other_axis (a));
+ }
+
+ child_refpoints.push_back (child_common);
+ }
+ Grob *common_refpoint = common_refpoint_of_array (child_refpoints, me, other_axis (a));
+
+ for (vsize i = elements->size (); i--;)
+ {
+ Grob *g = (*elements)[i];
+ Interval extent = g->maybe_pure_extent (g, a, pure, start, end);
+ Interval other_extent = pure ? Interval (-infinity_f, infinity_f)
+ : g->extent (common_refpoint, other_axis (a));
+ Box b;
+ b[a] = extent;
+ b[other_axis (a)] = other_extent;
+
+ if (extent.is_empty ())
+ {
+ elements->erase (elements->begin () + i);
+ continue;
+ }
+
+ Skyline_pair skylines;
+ if (!pure
+ && Skyline_pair::unsmob (g->get_property ("skylines")))
+ skylines = *Skyline_pair::unsmob (g->get_property ("skylines"));
+ else
+ {
+ if (!pure)
+ programming_error ("no skylines for alignment-child\n");
+
+ skylines = Skyline_pair (b, 0, other_axis (a));
+ }
+
+ /* each skyline is calculated relative to (potentially) a different other_axis
+ coordinate. In order to compare the skylines effectively, we need to shift them
+ to some absolute reference point */
+ if (!pure)
+ {
+ /* this is perhaps an abuse of minimum-?-extent: maybe we should create
+ another property? But it seems that the only (current) use of
+ minimum-Y-extent is to separate vertically-aligned elements */
+ SCM min_extent = g->get_property (a == X_AXIS ? "minimum-X-extent" : "minimum-Y-extent");
+ if (is_number_pair (min_extent))
+ {
+ b[a] = ly_scm2interval (min_extent);
+ skylines.insert (b, 0, other_axis (a));
+ }
+
+ Real offset = child_refpoints[i]->relative_coordinate (common_refpoint, other_axis (a));
+ skylines.shift (offset);
+ }
+
+
+ ret->push_back (skylines);
+ }
+ reverse (*ret);
+}