From 9ae52034113dcfbbc98fd7a0f8075ca3ea2cf3c9 Mon Sep 17 00:00:00 2001 From: Joe Neeman Date: Tue, 11 Nov 2008 13:25:28 -0800 Subject: [PATCH] Add support for max-systems-per-page. --- lily/include/page-breaking.hh | 5 ++++ lily/page-breaking.cc | 43 ++++++++++++++++++++++++++++++++++- lily/page-spacing.cc | 9 +++++++- 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/lily/include/page-breaking.hh b/lily/include/page-breaking.hh index 5768e4b109..d69fe1ce5f 100644 --- a/lily/include/page-breaking.hh +++ b/lily/include/page-breaking.hh @@ -103,9 +103,13 @@ public: bool ends_score () const; int systems_per_page () const; int max_systems_per_page () const; + int min_systems_per_page () const; Real page_height (int page_number, bool last) const; Real page_top_space () const; vsize system_count () const; + Real line_count_penalty (int line_count) const; + bool too_many_lines (int line_count) const; + bool too_few_lines (int line_count) const; protected: Paper_book *book_; @@ -156,6 +160,7 @@ private: bool ragged_last_; int systems_per_page_; int max_systems_per_page_; + int min_systems_per_page_; Real page_top_space_; vsize system_count_; diff --git a/lily/page-breaking.cc b/lily/page-breaking.cc index c8adcf64ad..12372c1e49 100644 --- a/lily/page-breaking.cc +++ b/lily/page-breaking.cc @@ -103,6 +103,7 @@ Page_breaking::Page_breaking (Paper_book *pb, Break_predicate is_break) page_top_space_ = robust_scm2double (pb->paper_->c_variable ("page-top-space"), 0); systems_per_page_ = robust_scm2int (pb->paper_->c_variable ("systems-per-page"), 0); max_systems_per_page_ = robust_scm2int (pb->paper_->c_variable ("max-systems-per-page"), 0); + min_systems_per_page_ = robust_scm2int (pb->paper_->c_variable ("min-systems-per-page"), 0); create_system_list (); find_chunks_and_breaks (is_break); @@ -136,6 +137,12 @@ Page_breaking::max_systems_per_page () const return max_systems_per_page_; } +int +Page_breaking::min_systems_per_page () const +{ + return min_systems_per_page_; +} + Real Page_breaking::page_top_space () const { @@ -148,6 +155,25 @@ Page_breaking::system_count () const return system_count_; } +bool +Page_breaking::too_many_lines (int line_count) const +{ + return max_systems_per_page () > 0 && line_count > max_systems_per_page (); +} + +bool +Page_breaking::too_few_lines (int line_count) const +{ + return line_count < min_systems_per_page (); +} + +Real +Page_breaking::line_count_penalty (int line_count) const +{ + // TODO: also check min_systems_per_page (once we support it in Page_spacer) + return too_many_lines (line_count) ? BAD_SPACING_PENALTY : 0; +} + /* translate indices into breaks_ into start-end parameters for the line breaker */ void Page_breaking::line_breaker_args (vsize sys, @@ -646,6 +672,7 @@ Page_breaking::min_page_count (vsize configuration, vsize first_page_num) Real cur_rod_height = 0; Real cur_spring_height = 0; Real cur_page_height = page_height (first_page_num, false); + int line_count = 0; cache_line_details (configuration); for (vsize i = 0; i < cached_line_details_.size (); i++) @@ -656,11 +683,14 @@ Page_breaking::min_page_count (vsize configuration, vsize first_page_num) Real next_spring_height = cur_spring_height + cached_line_details_[i].space_; Real next_height = next_rod_height + (ragged () ? next_spring_height : 0); + line_count += cached_line_details_[i].compressed_nontitle_lines_count_; if ((next_height > cur_page_height && cur_rod_height > 0) + || too_many_lines (line_count) || (i > 0 && 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_spring_height = cached_line_details_[i].space_; cur_page_height = page_height (first_page_num + ret, false); @@ -1028,6 +1058,8 @@ Page_breaking::space_systems_on_2_pages (vsize configuration, vsize first_page_n vector page2_force; Page_spacing page1 (page1_height, page_top_space_); Page_spacing page2 (page2_height, page_top_space_); + int page1_line_count = 0; + int page2_line_count = 0; page1_force.resize (cached_line_details_.size () - 1, infinity_f); page2_force.resize (cached_line_details_.size () - 1, infinity_f); @@ -1037,13 +1069,22 @@ Page_breaking::space_systems_on_2_pages (vsize configuration, vsize first_page_n { page1.append_system (cached_line_details_[i]); page2.prepend_system (cached_line_details_[cached_line_details_.size () - 1 - i]); - page1_force[i] = (ragged1 && page1.force_ < 0 && i > 0) ? infinity_f : page1.force_; + page1_line_count += cached_line_details_[i].compressed_nontitle_lines_count_; + page2_line_count += cached_line_details_[cached_line_details_.size () - 1 - i].compressed_nontitle_lines_count_; + + // NOTE: we treat max-systems-per-page and min-systems-per-page as soft + // constraints. That is, we penalize harshly when they don't happen + // but we don't completely reject. + page1_force[i] = line_count_penalty (page1_line_count) + + (ragged1 && page1.force_ < 0 && i > 0) ? infinity_f : page1.force_; if (ragged2) page2_force[page2_force.size () - 1 - i] = (page2.force_ < 0 && i + 1 < page1_force.size ()) ? infinity_f : 0; else page2_force[page2_force.size () - 1 - i] = page2.force_; + + page2_force[page2_force.size () - 1 - i] += line_count_penalty (page2_line_count); } /* find the position that minimises the sum of the page forces */ diff --git a/lily/page-spacing.cc b/lily/page-spacing.cc index a6d98d82ef..c4266935ce 100644 --- a/lily/page-spacing.cc +++ b/lily/page-spacing.cc @@ -193,10 +193,15 @@ Page_spacer::calc_subproblem (vsize page, vsize line) breaker_->page_top_space ()); Page_spacing_node &cur = state_.at (line, page); bool ragged = ragged_ || (ragged_last_ && last); + int line_count = 0; for (vsize page_start = line+1; page_start > page && page_start--;) { Page_spacing_node const *prev = page > 0 ? &state_.at (page_start-1, page-1) : 0; + line_count += lines_[page_start].compressed_nontitle_lines_count_; + + if (breaker_->too_many_lines (line_count)) + break; space.prepend_system (lines_[page_start]); if (page_start < line && (isinf (space.force_) || (space.force_ < 0 && ragged))) @@ -207,7 +212,9 @@ Page_spacer::calc_subproblem (vsize page, vsize line) if (line == lines_.size () - 1 && ragged_last_ && space.force_ > 0) space.force_ = 0; - /* we may have to deal with single lines that are taller than a page */ + /* we may have to deal with single lines that are taller than a page, in + which case we can't make the force infinite, but we should make + it very large. */ if (isinf (space.force_) && page_start == line) space.force_ = -BAD_SPACING_PENALTY; -- 2.39.2