From 5266aa98886211d4ac084029ce0362bb1ca5dce0 Mon Sep 17 00:00:00 2001 From: Joe Neeman Date: Thu, 26 Aug 2010 16:28:54 -0700 Subject: [PATCH] Fix 1240. Include fixed spacings in the calculation of minimum spacings. --- lily/align-interface.cc | 22 +++++++++++++++--- lily/grob.cc | 10 +++++++++ lily/include/align-interface.hh | 3 ++- lily/include/grob.hh | 1 + lily/include/page-layout-problem.hh | 1 + lily/include/system.hh | 2 ++ lily/page-layout-problem.cc | 35 ++++++++++++++++++++++++++++- lily/system.cc | 27 ++++++++++++++++++++-- 8 files changed, 94 insertions(+), 7 deletions(-) diff --git a/lily/align-interface.cc b/lily/align-interface.cc index 2385b035fd..d985a869c5 100644 --- a/lily/align-interface.cc +++ b/lily/align-interface.cc @@ -143,10 +143,17 @@ get_skylines (Grob *me, reverse (*ret); } +// If include_fixed_spacing is true, the manually fixed spacings +// induced by stretchable=0 or alignment-distances are included +// in the minimum translations here. If you want to find the minimum +// height of a system, include_fixed_spacing should be true. If you +// want to actually lay out the page, then it should be false (or +// else centered dynamics will break when there is a fixed alignment). vector Align_interface::get_minimum_translations (Grob *me, vector const &all_grobs, Axis a, + bool include_fixed_spacing, bool pure, int start, int end) { if (!pure && a == Y_AXIS && dynamic_cast (me) && !me->get_system ()) @@ -165,6 +172,7 @@ Align_interface::get_minimum_translations (Grob *me, Skyline down_skyline (stacking_dir); Real last_spaceable_element_pos = 0; Grob *last_spaceable_element = 0; + int spaceable_count = 0; for (vsize j = 0; j < elems.size (); j++) { Real dy = 0; @@ -184,9 +192,12 @@ Align_interface::get_minimum_translations (Grob *me, if (Page_layout_problem::read_spacing_spec (spec, &min_distance, ly_symbol2scm ("minimum-distance"))) dy = max (dy, min_distance); + if (include_fixed_spacing) + dy = max (dy, Page_layout_problem::get_fixed_spacing (elems[j-1], elems[j], spaceable_count, pure, start, end)); + if (Page_layout_problem::is_spaceable (elems[j]) && last_spaceable_element) { - // Spaceable staves may have min-distance and padding + // Spaceable staves may have // constraints coming from the previous spaceable staff // as well as from the previous staff. spec = Page_layout_problem::get_spacing_spec (last_spaceable_element, elems[j], pure, start, end); @@ -201,6 +212,10 @@ Align_interface::get_minimum_translations (Grob *me, &min_distance, ly_symbol2scm ("minimum-distance"))) dy = max (dy, min_distance + stacking_dir*(last_spaceable_element_pos - where)); + + if (include_fixed_spacing) + dy = max (dy, Page_layout_problem::get_fixed_spacing (last_spaceable_element, elems[j], spaceable_count, + pure, start, end)); } } @@ -214,6 +229,7 @@ Align_interface::get_minimum_translations (Grob *me, if (Page_layout_problem::is_spaceable (elems[j])) { + spaceable_count++; last_spaceable_element = elems[j]; last_spaceable_element_pos = where; } @@ -254,7 +270,7 @@ Align_interface::align_elements_to_minimum_distances (Grob *me, Axis a) { extract_grob_set (me, "elements", all_grobs); - vector translates = get_minimum_translations (me, all_grobs, a, false, 0, 0); + vector translates = get_minimum_translations (me, all_grobs, a, true, false, 0, 0); if (translates.size ()) for (vsize j = 0; j < all_grobs.size (); j++) all_grobs[j]->translate_axis (translates[j], a); @@ -264,7 +280,7 @@ Real Align_interface::get_pure_child_y_translation (Grob *me, Grob *ch, int start, int end) { extract_grob_set (me, "elements", all_grobs); - vector translates = get_minimum_translations (me, all_grobs, Y_AXIS, true, start, end); + vector translates = get_minimum_translations (me, all_grobs, Y_AXIS, true, true, start, end); if (translates.size ()) { diff --git a/lily/grob.cc b/lily/grob.cc index 882808180c..aa9c1d40f4 100644 --- a/lily/grob.cc +++ b/lily/grob.cc @@ -191,6 +191,16 @@ Grob::get_system () const return 0; } +/* This version of get_system is more reliable than this->get_system () + before line-breaking has been done, at which point there is only + one system in the whole score and we can find it just by following + parent pointers. */ +System * +Grob::get_system(Grob *me) +{ + Grob *p = me->get_parent (X_AXIS); + return p ? get_system (p) : dynamic_cast(me); +} void Grob::handle_broken_dependencies () diff --git a/lily/include/align-interface.hh b/lily/include/align-interface.hh index fc3dc12f5e..3cc04272a8 100644 --- a/lily/include/align-interface.hh +++ b/lily/include/align-interface.hh @@ -32,7 +32,8 @@ struct Align_interface static void align_elements_to_ideal_distances(Grob *); static vector get_minimum_translations (Grob *, vector const&, Axis a, - bool safe, int start, int end); + bool include_fixed_spacing, + bool pure, int start, int end); static void set_ordered (Grob *); static Axis axis (Grob *); static void add_element (Grob *, Grob *); diff --git a/lily/include/grob.hh b/lily/include/grob.hh index 96134a05d5..94da56e884 100644 --- a/lily/include/grob.hh +++ b/lily/include/grob.hh @@ -107,6 +107,7 @@ public: /* class hierarchy */ virtual System *get_system () const; + static System *get_system (Grob *); virtual void do_break_processing (); virtual Grob *find_broken_piece (System *) const; virtual void discretionary_processing (); diff --git a/lily/include/page-layout-problem.hh b/lily/include/page-layout-problem.hh index 0502ce8678..83fab7d616 100644 --- a/lily/include/page-layout-problem.hh +++ b/lily/include/page-layout-problem.hh @@ -35,6 +35,7 @@ public: static bool is_spaceable (Grob *g); static SCM get_details (Grob *g); static SCM get_spacing_spec (Grob *before, Grob *after, bool pure, int start, int end); + static Real get_fixed_spacing (Grob *before, Grob *after, int spaceable_index, bool pure, int start, int end); protected: void append_system (System*, Spring const&, Real padding); diff --git a/lily/include/system.hh b/lily/include/system.hh index 3bc7250d6f..ddaaf4ce00 100644 --- a/lily/include/system.hh +++ b/lily/include/system.hh @@ -41,6 +41,8 @@ public: Paper_score *paper_score () const; Grob *get_vertical_alignment (); Grob *get_extremal_staff (Direction dir, Interval const&); + Grob *get_pure_bound (Direction dir, int start, int end); + Grob *get_maybe_pure_bound (Direction dir, bool pure, int start, int end); int get_rank () const; void do_break_substitution_and_fixup_refpoints (); void post_processing (); diff --git a/lily/page-layout-problem.cc b/lily/page-layout-problem.cc index bf3395b2e3..7292126ddc 100644 --- a/lily/page-layout-problem.cc +++ b/lily/page-layout-problem.cc @@ -190,7 +190,7 @@ Page_layout_problem::append_system (System *sys, Spring const& spring, Real padd extract_grob_set (align, "elements", all_elts); vector elts = filter_dead_elements (all_elts); - vector minimum_offsets = Align_interface::get_minimum_translations (align, elts, Y_AXIS, + vector minimum_offsets = Align_interface::get_minimum_translations (align, elts, Y_AXIS, false, false, 0, 0); Skyline up_skyline (UP); @@ -627,6 +627,39 @@ Page_layout_problem::read_spacing_spec (SCM spec, Real* dest, SCM sym) return false; } +// 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) +{ + 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 ("space")); + + // 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)); + } + } + return ret; +} + static SCM add_stretchability (SCM alist, Real stretch) { diff --git a/lily/system.cc b/lily/system.cc index 8196736eca..dd3a46011f 100644 --- a/lily/system.cc +++ b/lily/system.cc @@ -581,7 +581,7 @@ System::pure_refpoint_extent (vsize start, vsize end) return Interval (); extract_grob_set (alignment, "elements", staves); - vector offsets = Align_interface::get_minimum_translations (alignment, staves, Y_AXIS, true, start, end); + vector offsets = Align_interface::get_minimum_translations (alignment, staves, Y_AXIS, true, true, start, end); for (vsize i = 0; i < offsets.size (); ++i) if (Page_layout_problem::is_spaceable (staves[i])) @@ -608,7 +608,7 @@ System::part_of_line_pure_height (vsize start, vsize end, bool begin) return Interval (); extract_grob_set (alignment, "elements", staves); - vector offsets = Align_interface::get_minimum_translations (alignment, staves, Y_AXIS, true, start, end); + vector offsets = Align_interface::get_minimum_translations (alignment, staves, Y_AXIS, true, true, start, end); Interval ret; for (vsize i = 0; i < staves.size (); ++i) @@ -704,6 +704,29 @@ System::calc_pure_height (SCM smob, SCM start_scm, SCM end_scm) return ly_interval2scm (begin); } +Grob* +System::get_pure_bound (Direction d, int start, int end) +{ + vector ranks = pscore_->get_break_ranks (); + vector indices = pscore_->get_break_indices (); + vector cols = pscore_->get_columns (); + + vsize target_rank = (d == LEFT ? start : end); + vector::const_iterator i = + lower_bound (ranks.begin (), ranks.end (), target_rank, std::less ()); + + if (i != ranks.end () && (*i) == target_rank) + return cols[indices[i - ranks.begin ()]]; + else + return 0; +} + +Grob* +System::get_maybe_pure_bound (Direction d, bool pure, int start, int end) +{ + return pure ? get_pure_bound (d, start, end) : get_bound (d); +} + ADD_INTERFACE (System, "This is the top-level object: Each object in a score" " ultimately has a @code{System} object as its X and" -- 2.39.2