From 1189408d94b05d31e77a98ebc00a94aad13b4651 Mon Sep 17 00:00:00 2001 From: Joe Neeman Date: Sun, 9 Nov 2008 11:34:42 -0800 Subject: [PATCH] Add systems-per-page variable in \paper. --- lily/include/constrained-breaking.hh | 8 +++--- lily/include/page-breaking.hh | 10 ++++--- lily/include/page-spacing.hh | 13 +++++++++ lily/optimal-page-breaking.cc | 20 +++++++++----- lily/page-breaking.cc | 41 +++++++++++++++++++++++----- lily/page-spacing.cc | 8 +++--- 6 files changed, 74 insertions(+), 26 deletions(-) diff --git a/lily/include/constrained-breaking.hh b/lily/include/constrained-breaking.hh index 62c5813dc4..48771545e4 100644 --- a/lily/include/constrained-breaking.hh +++ b/lily/include/constrained-breaking.hh @@ -55,8 +55,8 @@ struct Line_details { page_penalty_ = 0; turn_penalty_ = 0; title_ = false; - compressed_lines_count_ = 0; - compressed_nontitle_lines_count_ = 0; + compressed_lines_count_ = 1; + compressed_nontitle_lines_count_ = 1; } Line_details (Prob *pb) @@ -74,8 +74,8 @@ struct Line_details { page_penalty_ = robust_scm2double (pb->get_property ("page-break-penalty"), 0); turn_penalty_ = robust_scm2double (pb->get_property ("page-turn-penalty"), 0); title_ = to_boolean (pb->get_property ("is-title")); - compressed_lines_count_ = 0; - compressed_nontitle_lines_count_ = 0; + compressed_lines_count_ = 1; + compressed_nontitle_lines_count_ = title_ ? 0 : 1; } }; diff --git a/lily/include/page-breaking.hh b/lily/include/page-breaking.hh index 71aff9386e..73a0f59ccc 100644 --- a/lily/include/page-breaking.hh +++ b/lily/include/page-breaking.hh @@ -129,14 +129,16 @@ protected: vsize current_configuration_count () const; Line_division current_configuration (vsize configuration_index) const; Page_spacing_result space_systems_on_n_pages (vsize configuration_index, - vsize n, vsize first_page_num); + vsize n, vsize first_page_num, + int systems_per_page=0); Page_spacing_result space_systems_on_n_or_one_more_pages (vsize configuration_index, vsize n, - vsize first_page_num); + vsize first_page_num, + int systems_per_page=0); Page_spacing_result space_systems_on_best_pages (vsize configuration_index, vsize first_page_num); Page_spacing_result space_systems_with_fixed_number_per_page (vsize configuration_index, - int systems_per_page, - vsize first_page_num); + vsize first_page_num, + int systems_per_page); Page_spacing_result pack_systems_on_least_pages (vsize configuration_index, vsize first_page_num); vsize min_page_count (vsize configuration_index, vsize first_page_num); diff --git a/lily/include/page-spacing.hh b/lily/include/page-spacing.hh index 96dba0ffa6..bd64c31122 100644 --- a/lily/include/page-spacing.hh +++ b/lily/include/page-spacing.hh @@ -13,6 +13,19 @@ #include "constrained-breaking.hh" #include "page-spacing-result.hh" +/* This is a penalty that we add whenever a page breaking solution + is not bad enough to completely discard, but bad enough that + it is worse than any "proper" solution. For example, if we didn't + manage to fit systems on the desired number of pages or if there was + too big for a page. + + This constant is large enough that it dominates any reasonable penalty, + but small enough that nothing will overflow to infinity (so that we + can still distinguish bad spacings by the number of BAD_SPACING_PENALTYs + that they incur. +*/ +const Real BAD_SPACING_PENALTY = 200000; + /* for page_count > 2, we use a dynamic algorithm similar to constrained-breaking -- we have a class that stores the intermediate diff --git a/lily/optimal-page-breaking.cc b/lily/optimal-page-breaking.cc index 44e96602e8..f5e50ffa5b 100644 --- a/lily/optimal-page-breaking.cc +++ b/lily/optimal-page-breaking.cc @@ -39,6 +39,7 @@ Optimal_page_breaking::solve () vsize max_sys_count = max_system_count (0, end); vsize first_page_num = robust_scm2int (book_->paper_->c_variable ("first-page-number"), 1); SCM forced_page_count = book_->paper_->c_variable ("page-count"); + int systems_per_page = robust_scm2int (book_->paper_->c_variable ("systems-per-page"), 0); set_to_ideal_line_configuration (0, end); @@ -54,9 +55,12 @@ Optimal_page_breaking::solve () /* find out the ideal number of pages */ message (_ ("Finding the ideal number of pages...")); - best = space_systems_on_best_pages (0, first_page_num); - page_count = best.systems_per_page_.size (); + if (systems_per_page > 0) + best = space_systems_with_fixed_number_per_page (0, first_page_num, systems_per_page); + else + best = space_systems_on_best_pages (0, first_page_num); + page_count = best.systems_per_page_.size (); ideal_sys_count = best.system_count (); min_sys_count = ideal_sys_count - best.systems_per_page_.back (); @@ -67,9 +71,11 @@ Optimal_page_breaking::solve () } else { - /* todo: the following line will spit out programming errors if the + /* TODO: the following line will spit out programming errors if the ideal line spacing doesn't fit on PAGE_COUNT pages */ - best = space_systems_on_n_pages (0, page_count, first_page_num); + /* TODO: the interaction between systems_per_page and page_count needs to + be considered. */ + best = space_systems_on_n_pages (0, page_count, first_page_num, systems_per_page); min_sys_count = page_count; } @@ -93,9 +99,9 @@ Optimal_page_breaking::solve () Page_spacing_result cur; if (min_p_count == page_count || scm_is_integer (forced_page_count)) - cur = space_systems_on_n_pages (i, page_count, first_page_num); + cur = space_systems_on_n_pages (i, page_count, first_page_num, systems_per_page); else - cur = space_systems_on_n_or_one_more_pages (i, page_count-1, first_page_num); + cur = space_systems_on_n_or_one_more_pages (i, page_count-1, first_page_num, systems_per_page); if (cur.demerits_ < best_for_this_sys_count.demerits_ || isinf (best_for_this_sys_count.demerits_)) { @@ -137,7 +143,7 @@ Optimal_page_breaking::solve () if (min_p_count > page_count) continue; else - cur = space_systems_on_n_pages (i, page_count, first_page_num); + cur = space_systems_on_n_pages (i, page_count, first_page_num, systems_per_page); if (cur.demerits_ < best.demerits_ || isinf (best.demerits_)) { diff --git a/lily/page-breaking.cc b/lily/page-breaking.cc index 09307df0d5..fe59f55356 100644 --- a/lily/page-breaking.cc +++ b/lily/page-breaking.cc @@ -67,7 +67,7 @@ uncompress_solution (vector const &systems_per_page, { int compressed_count = 0; for (vsize j = start_sys; j < start_sys + systems_per_page[i]; j++) - compressed_count += compressed[j].compressed_lines_count_; + compressed_count += compressed[j].compressed_lines_count_ - 1; ret.push_back (systems_per_page[i] + compressed_count); start_sys += systems_per_page[i]; @@ -687,11 +687,23 @@ Page_breaking::min_page_count (vsize configuration, vsize first_page_num) return ret; } +// If systems_per_page is positive, we don't really try to space on N pages; +// we just put the requested number of systems on each page and penalize +// if the result doesn't have N pages. Page_spacing_result -Page_breaking::space_systems_on_n_pages (vsize configuration, vsize n, vsize first_page_num) +Page_breaking::space_systems_on_n_pages (vsize configuration, vsize n, vsize first_page_num, + int systems_per_page) { Page_spacing_result ret; + if (systems_per_page > 0) + { + Page_spacing_result ret = space_systems_with_fixed_number_per_page (configuration, first_page_num, + systems_per_page); + ret.demerits_ += (ret.force_.size () == n) ? 0 : BAD_SPACING_PENALTY; + return ret; + } + cache_line_details (configuration); bool valid_n = (n >= min_page_count (configuration, first_page_num) && n <= cached_line_details_.size ()); @@ -733,12 +745,23 @@ Page_breaking::blank_page_penalty () const return robust_scm2double (book_->paper_->lookup_variable (penalty_sym), 0.0); } +// If systems_per_page is positive, we don't really try to space on N +// or N+1 pages; see the comment to space_systems_on_n_pages. Page_spacing_result -Page_breaking::space_systems_on_n_or_one_more_pages (vsize configuration, vsize n, vsize first_page_num) +Page_breaking::space_systems_on_n_or_one_more_pages (vsize configuration, vsize n, vsize first_page_num, + int systems_per_page) { Page_spacing_result n_res; Page_spacing_result m_res; + if (systems_per_page > 0) + { + Page_spacing_result ret = space_systems_with_fixed_number_per_page (configuration, first_page_num, + systems_per_page); + ret.demerits_ += (ret.force_.size () == n || ret.force_.size () == (n-1)) ? 0 : BAD_SPACING_PENALTY; + return ret; + } + cache_line_details (configuration); vsize min_p_count = min_page_count (configuration, first_page_num); bool valid_n = n >= min_p_count || n <= cached_line_details_.size (); @@ -803,8 +826,8 @@ Page_breaking::space_systems_on_best_pages (vsize configuration, vsize first_pag Page_spacing_result Page_breaking::space_systems_with_fixed_number_per_page (vsize configuration, - int systems_per_page, - vsize first_page_num) + vsize first_page_num, + int systems_per_page) { Page_spacing_result res; Page_spacing space (page_height (first_page_num, false), page_top_space_); @@ -823,9 +846,13 @@ Page_breaking::space_systems_with_fixed_number_per_page (vsize configuration, while (system_count_on_this_page < systems_per_page && line < cached_line_details_.size ()) { - space.append_system (cached_line_details_[line]); - system_count_on_this_page += cached_line_details_[line].compressed_nontitle_lines_count_; + Line_details const &cur_line = cached_line_details_[line]; + space.append_system (cur_line); + system_count_on_this_page += cur_line.compressed_nontitle_lines_count_; line++; + + if (cur_line.page_permission_ == ly_symbol2scm ("force")) + break; } res.systems_per_page_.push_back (line - page_first_line); diff --git a/lily/page-spacing.cc b/lily/page-spacing.cc index 71e51fa685..d586fa8d98 100644 --- a/lily/page-spacing.cc +++ b/lily/page-spacing.cc @@ -154,13 +154,13 @@ Page_spacer::solve (vsize page_count) if (extra_systems) { ret.systems_per_page_.back () += extra_systems; - ret.demerits_ += 200000; + ret.demerits_ += BAD_SPACING_PENALTY; } if (extra_pages) { - ret.force_.insert (ret.force_.end (), extra_pages, 200000); + ret.force_.insert (ret.force_.end (), extra_pages, BAD_SPACING_PENALTY); ret.systems_per_page_.insert (ret.systems_per_page_.end (), extra_pages, 0); - ret.demerits_ += 200000; + ret.demerits_ += BAD_SPACING_PENALTY; } @@ -209,7 +209,7 @@ Page_spacer::calc_subproblem (vsize page, vsize line) /* we may have to deal with single lines that are taller than a page */ if (isinf (space.force_) && page_start == line) - space.force_ = -200000; + space.force_ = -BAD_SPACING_PENALTY; Real dem = fabs (space.force_) + (prev ? prev->demerits_ : 0); Real penalty = 0; -- 2.39.5