+// If there is a forced, fixed spacing between BEFORE and AFTER, return it.
+// Otherwise, return -infinity_f.
+// If after is spaceable, it is the (spaceable_index + 1)th spaceable grob in
+// its alignment.
+Real
+Page_layout_problem::get_fixed_spacing (Grob *before, Grob *after, int spaceable_index, bool pure, int start, int end)
+{
+ Spanner *after_sp = dynamic_cast<Spanner*> (after);
+ SCM cache_symbol = (is_spaceable (before) && is_spaceable (after))
+ ? ly_symbol2scm ("spaceable-fixed-spacing")
+ : ly_symbol2scm ("loose-fixed-spacing");
+ if (pure)
+ {
+ // The result of this function doesn't depend on "end," so we can reduce the
+ // size of the cache by ignoring it.
+ SCM cached = after_sp->get_cached_pure_property (cache_symbol, start, 0);
+ if (scm_is_number (cached))
+ return robust_scm2double (cached, 0.0);
+ }
+
+ SCM spec = Page_layout_problem::get_spacing_spec (before, after, pure, start, end);
+ Real ret = -infinity_f;
+ Real stretchability = 0;
+ if (Page_layout_problem::read_spacing_spec (spec, &stretchability, ly_symbol2scm ("stretchability"))
+ && stretchability == 0)
+ Page_layout_problem::read_spacing_spec (spec, &ret, ly_symbol2scm ("basic-distance"));
+
+ // If we're pure, then paper-columns have not had their systems set,
+ // and so elts[i]->get_system () is unreliable.
+ System *sys = pure ? Grob::get_system (before) : before->get_system ();
+ Grob *left_bound = sys ? sys->get_maybe_pure_bound (LEFT, pure, start, end) : 0;
+
+ if (is_spaceable (before) && is_spaceable (after) && left_bound)
+ {
+ SCM details = left_bound->get_property ("line-break-system-details");
+ SCM manual_dists = ly_assoc_get (ly_symbol2scm ("alignment-distances"), details, SCM_EOL);
+ if (scm_is_pair (manual_dists))
+ {
+ SCM forced = robust_list_ref (spaceable_index - 1, manual_dists);
+ if (scm_is_number (forced))
+ ret = max (ret, scm_to_double (forced));
+ }
+ }
+
+ // Cache the result. As above, we ignore "end."
+ if (pure)
+ after_sp->cache_pure_property (cache_symbol, start, 0, scm_from_double (ret));
+
+ return ret;
+}
+
+static SCM
+add_stretchability (SCM alist, Real stretch)
+{
+ if (!scm_is_pair (scm_sloppy_assq (ly_symbol2scm ("stretchability"), alist)))
+ return scm_acons (ly_symbol2scm ("stretchability"), scm_from_double (stretch), alist);
+
+ return alist;
+}
+
+// We want to put a large stretch between a non-spaceable line and its
+// non-affinity staff. We want to put an even larger stretch between
+// a non-spaceable line and the top/bottom of the page. That way,
+// a spacing-affinity UP line at the bottom of the page will still be
+// placed close to its staff.
+const double LARGE_STRETCH = 10e5;
+const double HUGE_STRETCH = 10e7;
+
+// Returns the spacing spec connecting BEFORE to AFTER.