From 4a6773dd60ef6ef481e37b00049c9eedcb5b8193 Mon Sep 17 00:00:00 2001 From: Joe Neeman Date: Mon, 14 Jun 2010 19:30:55 +0300 Subject: [PATCH] Fix 1112. Add support for minimum-distance into the page-breaker. --- .../regression/page-breaking-min-distance.ly | 18 +++++++ lily/constrained-breaking.cc | 33 ++++++++++-- lily/include/constrained-breaking.hh | 13 ++++- lily/page-breaking.cc | 51 +++++++++++-------- lily/page-spacing.cc | 7 +-- 5 files changed, 93 insertions(+), 29 deletions(-) create mode 100644 input/regression/page-breaking-min-distance.ly diff --git a/input/regression/page-breaking-min-distance.ly b/input/regression/page-breaking-min-distance.ly new file mode 100644 index 0000000000..ad8dbdb20a --- /dev/null +++ b/input/regression/page-breaking-min-distance.ly @@ -0,0 +1,18 @@ +\version "2.13.22" + +\header { + texidoc = "minimum-distance is correctly accounted for in page breaking." +} + +\book { + \paper { + between-scores-system-spacing #'minimum-distance = #'20 + paper-height = 8\cm + } + + \score { c'1 } + \score { c'1 } + \score { c'1 } + \score { c'1 } +} + diff --git a/lily/constrained-breaking.cc b/lily/constrained-breaking.cc index 8e08d1fc87..0779c133a1 100644 --- a/lily/constrained-breaking.cc +++ b/lily/constrained-breaking.cc @@ -383,30 +383,51 @@ Constrained_breaking::initialize () /* NOTE: currently, we aren't using the space_ field of a Line_details for anything. That's because the approximations used for scoring a page configuration don't actually space things - properly (for speed reasong) using springs anchored at the staff + properly (for speed reasons) using springs anchored at the staff refpoints. Rather, the "space" is placed between the extent boxes. To get a good result, therefore, the "space" value for page breaking needs to be much smaller than the "space" value for - page layout. Currently, we just make it zero always. + page layout. Currently, we just make it zero always, which means + that we will always prefer a tighter vertical layout. */ between_system_space_ = 0; between_system_padding_ = 0; + between_system_min_distance_ = 0; + between_scores_system_padding_ = 0; + between_scores_system_min_distance_ = 0; before_title_padding_ = 0; + before_title_min_distance_ = 0; Output_def *l = pscore_->layout (); SCM spacing_spec = l->c_variable ("between-system-spacing"); + SCM between_scores_spec = l->c_variable ("between-scores-system-spacing"); SCM title_spec = l->c_variable ("before-title-spacing"); SCM page_breaking_spacing_spec = l->c_variable ("page-breaking-between-system-spacing"); Page_layout_problem::read_spacing_spec (spacing_spec, &between_system_padding_, ly_symbol2scm ("padding")); + Page_layout_problem::read_spacing_spec (between_scores_spec, + &between_scores_system_padding_, + ly_symbol2scm ("padding")); Page_layout_problem::read_spacing_spec (page_breaking_spacing_spec, &between_system_padding_, ly_symbol2scm ("padding")); Page_layout_problem::read_spacing_spec (title_spec, &before_title_padding_, ly_symbol2scm ("padding")); + Page_layout_problem::read_spacing_spec (between_scores_spec, + &between_scores_system_min_distance_, + ly_symbol2scm ("minimum-distance")); + Page_layout_problem::read_spacing_spec (spacing_spec, + &between_system_min_distance_, + ly_symbol2scm ("minimum-distance")); + Page_layout_problem::read_spacing_spec (page_breaking_spacing_spec, + &between_system_min_distance_, + ly_symbol2scm ("minimum-distance")); + Page_layout_problem::read_spacing_spec (title_spec, + &before_title_min_distance_, + ly_symbol2scm ("minimum-distance")); Interval first_line = line_dimensions_int (pscore_->layout (), 0); Interval other_lines = line_dimensions_int (pscore_->layout (), 1); @@ -460,6 +481,7 @@ Constrained_breaking::fill_line_details (Line_details *const out, vsize start, v System *sys = pscore_->root_system (); 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); + bool last = (end == breaks_.size () - 1); Grob *c = all_[breaks_[end]]; out->last_column_ = c; @@ -486,8 +508,10 @@ Constrained_breaking::fill_line_details (Line_details *const out, vsize start, v || 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->padding_ = last ? between_scores_system_padding_ : between_system_padding_; out->title_padding_ = before_title_padding_; + out->min_distance_ = last ? between_scores_system_min_distance_ : between_system_min_distance_; + out->title_min_distance_ = before_title_min_distance_; out->space_ = between_system_space_; out->inverse_hooke_ = out->full_height () + between_system_space_; } @@ -509,6 +533,8 @@ Line_details::Line_details (Prob *pb, Output_def *paper) title_padding_ = 0; Page_layout_problem::read_spacing_spec (spec, &padding_, ly_symbol2scm ("padding")); Page_layout_problem::read_spacing_spec (title_spec, &title_padding_, ly_symbol2scm ("padding")); + Page_layout_problem::read_spacing_spec (spec, &min_distance_, ly_symbol2scm ("minimum-distance")); + Page_layout_problem::read_spacing_spec (title_spec, &title_min_distance_, ly_symbol2scm ("minimum-distance")); last_column_ = 0; force_ = 0; @@ -532,6 +558,7 @@ 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); tight_spacing_ = to_boolean (pb->get_property ("tight-spacing")); + first_refpoint_offset_ = 0; } Real diff --git a/lily/include/constrained-breaking.hh b/lily/include/constrained-breaking.hh index fbe12eb05b..c461859f7c 100644 --- a/lily/include/constrained-breaking.hh +++ b/lily/include/constrained-breaking.hh @@ -49,6 +49,8 @@ struct Line_details { Real padding_; /* compulsory space after this system (if we're not last on a page) */ Real title_padding_; + Real min_distance_; + Real title_min_distance_; Real bottom_padding_; Real space_; /* spring length */ Real inverse_hooke_; @@ -72,6 +74,7 @@ struct Line_details { bool last_markup_line_; bool first_markup_line_; bool tight_spacing_; + Real first_refpoint_offset_; Line_details () { @@ -80,6 +83,8 @@ struct Line_details { padding_ = 0; title_padding_ = 0; bottom_padding_ = 0; + min_distance_ = 0; + title_min_distance_ = 0; space_ = 0; inverse_hooke_ = 1; tight_spacing_ = false; @@ -95,6 +100,7 @@ struct Line_details { last_markup_line_ = false; first_markup_line_ = false; tallness_ = 0; + first_refpoint_offset_ = 0; } Line_details (Prob *pb, Output_def *paper); @@ -150,9 +156,14 @@ private: vsize systems_; bool ragged_right_; bool ragged_last_; + + Real between_system_min_distance_; + Real between_system_padding_; Real between_system_space_; + Real between_scores_system_min_distance_; + Real between_scores_system_padding_; + Real before_title_min_distance_; Real before_title_padding_; - Real between_system_padding_; /* the (i,j)th entry is the configuration for breaking between columns i and j */ diff --git a/lily/page-breaking.cc b/lily/page-breaking.cc index 83ffd90fd5..aeeb7bb1b7 100644 --- a/lily/page-breaking.cc +++ b/lily/page-breaking.cc @@ -100,17 +100,17 @@ compress_lines (const vector &orig) Line_details const &old = ret.back (); Line_details compressed = orig[i]; /* - "padding" is the padding below the current line. The padding below - "old" (taking into account whether "old" is a title) is already - accounted for in the extent of the compressed line. The padding - below the compressed line, therefore, should depend on whether its - bottom-most line is a title or not. + We must account for the padding between the lines that we are compressing. + The padding values come from "old," which is the upper system here. Note + the meaning of tight-spacing: if a system has tight-spacing, then the padding + _before_ it is ignored. */ Real padding = 0; if (!orig[i].tight_spacing_) padding = orig[i].title_ ? old.title_padding_ : old.padding_; compressed.shape_ = old.shape_.piggyback (orig[i].shape_, padding); + compressed.first_refpoint_offset_ += compressed.shape_.rest_[UP] - old.shape_.rest_[UP]; compressed.space_ += old.space_; compressed.inverse_hooke_ += old.inverse_hooke_; @@ -858,19 +858,38 @@ Page_breaking::compute_line_heights () Real prev_hanging = 0; Real prev_hanging_begin = 0; Real prev_hanging_rest = 0; + Real prev_refpoint_hanging = 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]; + bool title = cached_line_details_[i].title_; + Real refpoint_hanging = max (prev_hanging_begin + a, prev_hanging_rest + b); + + if (i > 0) + { + Real padding = 0; + if (!cached_line_details_[i].tight_spacing_) + padding = title + ? cached_line_details_[i-1].title_padding_ + : cached_line_details_[i-1].padding_; + Real min_dist = title + ? cached_line_details_[i-1].title_min_distance_ + : cached_line_details_[i-1].min_distance_; + refpoint_hanging = max (refpoint_hanging + padding, + prev_refpoint_hanging + min_dist + + cached_line_details_[i].first_refpoint_offset_); + } + + Real hanging_begin = refpoint_hanging - shape.begin_[DOWN]; + Real hanging_rest = refpoint_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; + prev_refpoint_hanging = refpoint_hanging; } } @@ -892,21 +911,13 @@ Page_breaking::min_page_count (vsize configuration, vsize first_page_num) for (vsize i = 0; i < cached_line_details_.size (); i++) { - Real padding = 0; Real ext_len; if (cur_rod_height > 0) - { - if (!cached_line_details_[i].tight_spacing_) - 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_; - } + 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; + ext_len = cached_line_details_[i].full_height(); + + Real next_rod_height = cur_rod_height + ext_len; Real next_spring_height = cur_spring_height + cached_line_details_[i].space_; Real next_height = next_rod_height + (ragged () ? next_spring_height : 0) + min_whitespace_at_bottom_of_page (cached_line_details_[i]); diff --git a/lily/page-spacing.cc b/lily/page-spacing.cc index 4120afb514..33cf18a3fe 100644 --- a/lily/page-spacing.cc +++ b/lily/page-spacing.cc @@ -56,8 +56,7 @@ Page_spacing::append_system (const Line_details &line) rod_height_ += line.full_height (); first_line_ = line; } - if (!line.tight_spacing_) - rod_height_ += line.title_ ? last_line_.title_padding_ : last_line_.padding_; + spring_len_ += line.space_; inverse_spring_k_ += line.inverse_hooke_; @@ -69,9 +68,7 @@ Page_spacing::append_system (const Line_details &line) void Page_spacing::prepend_system (const Line_details &line) { - if (rod_height_ && !first_line_.tight_spacing_) - rod_height_ += first_line_.title_ ? line.title_padding_ : line.padding_; - else + if (!rod_height_) last_line_ = line; rod_height_ -= first_line_.full_height (); -- 2.39.2