From d3032e8908ee5b68d2ab58e6ff594e8e4fed5277 Mon Sep 17 00:00:00 2001 From: Boris Shingarov Date: Thu, 22 Apr 2010 13:35:38 -0700 Subject: [PATCH] Fix 1053. Adds the begin-of-line/rest-of-line hack for spacing between systems, as well as within them. --- lily/constrained-breaking.cc | 58 +++++++++++++++++++++------- lily/include/constrained-breaking.hh | 22 ++++++++++- lily/include/page-breaking.hh | 1 + lily/include/system.hh | 6 +++ lily/page-breaking.cc | 51 +++++++++++++++++++----- lily/page-spacing.cc | 18 ++++++--- lily/system.cc | 37 ++++++++++++++++++ 7 files changed, 163 insertions(+), 30 deletions(-) diff --git a/lily/constrained-breaking.cc b/lily/constrained-breaking.cc index 0db98ccaaf..a22e105e4d 100644 --- a/lily/constrained-breaking.cc +++ b/lily/constrained-breaking.cc @@ -458,7 +458,8 @@ Constrained_breaking::fill_line_details (Line_details *const out, vsize start, v int start_rank = Paper_column::get_rank (all_[breaks_[start]]); int end_rank = Paper_column::get_rank (all_[breaks_[end]]); System *sys = pscore_->root_system (); - Interval extent = sys->pure_height (sys, start_rank, end_rank); + Interval begin_of_line_extent = sys->begin_of_line_pure_height (start_rank, end_rank); + Interval rest_of_line_extent = sys->rest_of_line_pure_height (start_rank, end_rank); Grob *c = all_[breaks_[end]]; out->last_column_ = c; @@ -476,20 +477,19 @@ Constrained_breaking::fill_line_details (Line_details *const out, vsize start, v out->turn_permission_ = min_permission (out->page_permission_, out->turn_permission_); - // TODO: see the hack regarding begin_of_line and - // rest_of_line extents in align-interface. Perhaps we - // should do the same thing here so that the effect extends - // between systems as well as within systems. It isn't as - // crucial here, however, because the effect is largest when - // dealing with large systems. - out->extent_ = (extent.is_empty () - || isnan (extent[LEFT]) - || isnan (extent[RIGHT])) - ? Interval (0, 0) : extent; + begin_of_line_extent = (begin_of_line_extent.is_empty () + || isnan (begin_of_line_extent[LEFT]) + || isnan (begin_of_line_extent[RIGHT])) + ? Interval (0, 0) : begin_of_line_extent; + rest_of_line_extent = (rest_of_line_extent.is_empty () + || isnan (rest_of_line_extent[LEFT]) + || isnan (rest_of_line_extent[RIGHT])) + ? Interval (0, 0) : rest_of_line_extent; + out->shape_ = Line_shape (begin_of_line_extent, rest_of_line_extent); out->padding_ = between_system_padding_; out->title_padding_ = before_title_padding_; out->space_ = between_system_space_; - out->inverse_hooke_ = extent.length () + between_system_space_; + out->inverse_hooke_ = out->full_height () + between_system_space_; } Real @@ -512,7 +512,9 @@ Line_details::Line_details (Prob *pb, Output_def *paper) last_column_ = 0; force_ = 0; - extent_ = unsmob_stencil (pb->get_property ("stencil")) ->extent (Y_AXIS); + Interval stencil_extent = unsmob_stencil (pb->get_property ("stencil"))->extent (Y_AXIS); + shape_ = Line_shape (stencil_extent, stencil_extent); // pretend it goes all the way across + tallness_ = 0; bottom_padding_ = 0; space_ = 0.0; inverse_hooke_ = 1.0; @@ -530,3 +532,33 @@ Line_details::Line_details (Prob *pb, Output_def *paper) SCM first_scm = pb->get_property ("first-markup-line"); first_markup_line_ = to_boolean (first_scm); } + +Real +Line_details::full_height () const +{ + Interval ret; + ret.unite(shape_.begin_); + ret.unite(shape_.rest_); + return ret.length(); +} + +Real +Line_details::tallness () const +{ + return tallness_; +} + +Line_shape::Line_shape (Interval begin, Interval rest) +{ + begin_ = begin; + rest_ = rest; +} + +Line_shape +Line_shape::piggyback (Line_shape mount, Real padding) const +{ + Real elevation = max (begin_[UP]-mount.begin_[DOWN], rest_[UP]-mount.rest_[DOWN]); + Interval begin = Interval (begin_[DOWN], elevation + mount.begin_[UP] + padding); + Interval rest = Interval (rest_[DOWN], elevation + mount.rest_[UP] + padding); + return Line_shape (begin, rest); +} diff --git a/lily/include/constrained-breaking.hh b/lily/include/constrained-breaking.hh index e6d898e6a0..ff84853749 100644 --- a/lily/include/constrained-breaking.hh +++ b/lily/include/constrained-breaking.hh @@ -24,10 +24,27 @@ #include "matrix.hh" #include "prob.hh" +/* + * Begin/rest-of-line hack. This geometrical shape is a crude approximation + * of Skyline, but it is better than a rectangle. + */ +struct Line_shape +{ + Interval begin_; + Interval rest_; + + Line_shape () + { + } + Line_shape (Interval begin, Interval rest); + Line_shape piggyback (Line_shape mount, Real padding) const; +}; + struct Line_details { Grob *last_column_; Real force_; - Interval extent_; /* Y-extent of the system */ + Line_shape shape_; + Real tallness_; /* Y-extent, adjusted according to begin/rest-of-line*/ Real padding_; /* compulsory space after this system (if we're not last on a page) */ @@ -75,9 +92,12 @@ struct Line_details { compressed_nontitle_lines_count_ = 1; last_markup_line_ = false; first_markup_line_ = false; + tallness_ = 0; } Line_details (Prob *pb, Output_def *paper); + Real full_height () const; + Real tallness () const; }; /* diff --git a/lily/include/page-breaking.hh b/lily/include/page-breaking.hh index b643a11c9c..3c4076c0da 100644 --- a/lily/include/page-breaking.hh +++ b/lily/include/page-breaking.hh @@ -189,6 +189,7 @@ private: vsize current_end_breakpoint_; void cache_line_details (vsize configuration_index); + void compute_line_heights (); void clear_line_details_cache (); vsize cached_configuration_index_; vector cached_line_details_; diff --git a/lily/include/system.hh b/lily/include/system.hh index 509a65db2c..b8fa6644d4 100644 --- a/lily/include/system.hh +++ b/lily/include/system.hh @@ -65,9 +65,15 @@ public: void typeset_grob (Grob *); void pre_processing (); + Interval begin_of_line_pure_height (vsize start, vsize end); + Interval rest_of_line_pure_height (vsize start, vsize end); + protected: virtual void derived_mark () const; virtual Grob *clone () const; + +private: + Interval part_of_line_pure_height (vsize start, vsize end, bool begin); }; void set_loose_columns (System *which, Column_x_positions const *posns); diff --git a/lily/page-breaking.cc b/lily/page-breaking.cc index 7dbac44278..0ef1a309e9 100644 --- a/lily/page-breaking.cc +++ b/lily/page-breaking.cc @@ -101,8 +101,7 @@ compress_lines (const vector &orig) Line_details compressed = orig[i]; Real padding = orig[i].title_ ? old.title_padding_ : old.padding_; - compressed.extent_[DOWN] = old.extent_[DOWN]; - compressed.extent_[UP] = old.extent_[UP] + orig[i].extent_.length () + padding; + compressed.shape_ = old.shape_.piggyback (orig[i].shape_, padding); compressed.space_ += old.space_; compressed.inverse_hooke_ += old.inverse_hooke_; @@ -836,6 +835,28 @@ Page_breaking::line_divisions_rec (vsize system_count, } } +void +Page_breaking::compute_line_heights () +{ + Real prev_hanging = 0; + Real prev_hanging_begin = 0; + Real prev_hanging_rest = 0; + for (vsize i = 0; i < cached_line_details_.size (); i++) + { + Line_shape shape = cached_line_details_[i].shape_; + Real a = shape.begin_[UP]; + Real b = shape.rest_[UP]; + Real midline_hanging = max (prev_hanging_begin + a, prev_hanging_rest + b); + Real hanging_begin = midline_hanging - shape.begin_[DOWN]; + Real hanging_rest = midline_hanging - shape.rest_[DOWN]; + Real hanging = max (hanging_begin, hanging_rest); + cached_line_details_[i].tallness_ = hanging - prev_hanging; + prev_hanging = hanging; + prev_hanging_begin = hanging_begin; + prev_hanging_rest = hanging_rest; + } +} + vsize Page_breaking::min_page_count (vsize configuration, vsize first_page_num) { @@ -847,18 +868,26 @@ Page_breaking::min_page_count (vsize configuration, vsize first_page_num) int line_count = 0; cache_line_details (configuration); + compute_line_heights (); if (cached_line_details_.size ()) cur_page_height -= min_whitespace_at_top_of_page (cached_line_details_[0]); for (vsize i = 0; i < cached_line_details_.size (); i++) { - Real ext_len = cached_line_details_[i].extent_.length (); Real padding = 0; + Real ext_len; if (cur_rod_height > 0) - padding = cached_line_details_[i].title_ ? - cached_line_details_[i-1].title_padding_ : cached_line_details_[i-1].padding_; - + { + padding = cached_line_details_[i].title_ ? + cached_line_details_[i-1].title_padding_ : + cached_line_details_[i-1].padding_; + ext_len = cached_line_details_[i].tallness_; + } + else + { + ext_len = cached_line_details_[i].full_height(); + } Real next_rod_height = cur_rod_height + ext_len + padding; Real next_spring_height = cur_spring_height + cached_line_details_[i].space_; Real next_height = next_rod_height + (ragged () ? next_spring_height : 0) @@ -871,7 +900,7 @@ Page_breaking::min_page_count (vsize configuration, vsize first_page_num) && cached_line_details_[i-1].page_permission_ == ly_symbol2scm ("force"))) { line_count = cached_line_details_[i].compressed_nontitle_lines_count_; - cur_rod_height = ext_len; + cur_rod_height = cached_line_details_[i].full_height(); cur_spring_height = cached_line_details_[i].space_; page_starter = i; @@ -909,7 +938,7 @@ Page_breaking::min_page_count (vsize configuration, vsize first_page_num) if (!too_few_lines (line_count - cached_line_details_.back ().compressed_nontitle_lines_count_) && cur_height > cur_page_height /* don't increase the page count if the last page had only one system */ - && cur_rod_height > cached_line_details_.back ().extent_.length ()) + && cur_rod_height > cached_line_details_.back ().full_height ()) ret++; assert (ret <= cached_line_details_.size ()); @@ -1388,7 +1417,8 @@ Page_breaking::min_whitespace_at_top_of_page (Line_details const &line) const ly_symbol2scm ("padding")); // FIXME: take into account the height of the header - return max (0.0, max (padding, min_distance - line.extent_[UP])); + Real translate = max (line.shape_.begin_[UP], line.shape_.rest_[UP]); + return max (0.0, max (padding, min_distance - translate)); } Real @@ -1406,7 +1436,8 @@ Page_breaking::min_whitespace_at_bottom_of_page (Line_details const &line) const ly_symbol2scm ("padding")); // FIXME: take into account the height of the footer - return max (0.0, max (padding, min_distance + line.extent_[DOWN])); + Real translate = min (line.shape_.begin_[DOWN], line.shape_.rest_[DOWN]); + return max (0.0, max (padding, min_distance + translate)); } int diff --git a/lily/page-spacing.cc b/lily/page-spacing.cc index f78cc1795a..ee9fbb3ee1 100644 --- a/lily/page-spacing.cc +++ b/lily/page-spacing.cc @@ -47,12 +47,16 @@ Page_spacing::resize (Real new_height) void Page_spacing::append_system (const Line_details &line) { - if (!rod_height_) - first_line_ = line; - + if (rod_height_) + { + rod_height_ += line.tallness_; + } + else + { + rod_height_ += line.full_height (); + first_line_ = line; + } rod_height_ += line.title_ ? last_line_.title_padding_ : last_line_.padding_; - - rod_height_ += line.extent_.length (); spring_len_ += line.space_; inverse_spring_k_ += line.inverse_hooke_; @@ -69,7 +73,9 @@ Page_spacing::prepend_system (const Line_details &line) else last_line_ = line; - rod_height_ += line.extent_.length (); + rod_height_ -= first_line_.full_height (); + rod_height_ += first_line_.tallness_; + rod_height_ += line.full_height(); spring_len_ += line.space_; inverse_spring_k_ += line.inverse_hooke_; diff --git a/lily/system.cc b/lily/system.cc index 1be38ea570..f938b8322e 100644 --- a/lily/system.cc +++ b/lily/system.cc @@ -570,6 +570,43 @@ System::get_extremal_staff (Direction dir, Interval const &iv) return 0; } +Interval +System::part_of_line_pure_height (vsize start, vsize end, bool begin) +{ + Grob *alignment = get_vertical_alignment (); + if (!alignment) + { + programming_error("system does not have a vertical alignment"); + return Interval(); + } + extract_grob_set (alignment, "elements", staves); + vector offsets = Align_interface::get_minimum_translations (alignment, staves, Y_AXIS, true, start, end); + + Interval ret; + for (vsize i = 0; i < staves.size(); ++i) + { + Interval iv = begin? + Axis_group_interface::begin_of_line_pure_height (staves[i], start) : + Axis_group_interface::rest_of_line_pure_height (staves[i], start, end); + if (i