X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fpage-breaking.cc;h=cf483bdcb3488e49fe22c1335dbc41a611feace1;hb=43995ba0ef51445e9d9c983e47368225491de488;hp=1b61f3825846964b80f4a275b7af4f225a411faf;hpb=957d942e2c0fb0a1bdbdaef610961bdd3b23ebdd;p=lilypond.git diff --git a/lily/page-breaking.cc b/lily/page-breaking.cc index 1b61f38258..cf483bdcb3 100644 --- a/lily/page-breaking.cc +++ b/lily/page-breaking.cc @@ -1,10 +1,20 @@ /* - page-breaking.cc -- implement a superclass and utility - functions shared by various page-breaking algorithms + This file is part of LilyPond, the GNU music typesetter. - source file of the GNU LilyPond music typesetter + Copyright (C) 2006--2010 Joe Neeman - (c) 2006--2009 Joe Neeman + LilyPond is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LilyPond is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LilyPond. If not, see . */ /* @@ -89,8 +99,18 @@ compress_lines (const vector &orig) { Line_details const &old = ret.back (); Line_details compressed = orig[i]; - compressed.extent_[DOWN] = old.extent_[DOWN]; - compressed.extent_[UP] = old.extent_[UP] + orig[i].extent_.length () + old.padding_; + /* + "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. + */ + 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.space_ += old.space_; compressed.inverse_hooke_ += old.inverse_hooke_; @@ -162,6 +182,7 @@ Page_breaking::Page_breaking (Paper_book *pb, Break_predicate is_break) systems_per_page_ = max (0, robust_scm2int (pb->paper_->c_variable ("systems-per-page"), 0)); max_systems_per_page_ = max (0, robust_scm2int (pb->paper_->c_variable ("max-systems-per-page"), 0)); min_systems_per_page_ = max (0, robust_scm2int (pb->paper_->c_variable ("min-systems-per-page"), 0)); + orphan_penalty_ = robust_scm2int (pb->paper_->c_variable ("orphan-penalty"), 100000); if (systems_per_page_ && (max_systems_per_page_ || min_systems_per_page_)) { @@ -524,13 +545,14 @@ Page_breaking::find_chunks_and_breaks (Break_predicate is_break) Constrained_breaking breaking (system_specs_[i].pscore_); vector details = breaking.line_details (0, VPOS, scm_to_int (system_count)); + cols.push_back (system_specs_[i].pscore_->root_system ()->used_columns ()[0]); for (vsize j = 0; j < details.size (); j++) cols.push_back (details[j].last_column_); } else cols = system_specs_[i].pscore_->root_system ()->used_columns (); - int last_chunk_idx = -1; + int last_chunk_idx = 0; vector line_breaker_columns; line_breaker_columns.push_back (0); @@ -750,11 +772,6 @@ Page_breaking::cache_line_details (vsize configuration_index) if (cached_configuration_index_ != configuration_index) { cached_configuration_index_ = configuration_index; - Real padding = 0; - SCM spacing_spec = book_->paper_->c_variable ("between-system-spacing"); - SCM page_breaking_spacing_spec = book_->paper_->c_variable ("page-breaking-between-system-spacing"); - Page_layout_problem::read_spacing_spec (spacing_spec, &padding, ly_symbol2scm ("padding")); - Page_layout_problem::read_spacing_spec (page_breaking_spacing_spec, &padding, ly_symbol2scm ("padding")); Line_division &div = current_configurations_[configuration_index]; uncompressed_line_details_.clear (); @@ -773,10 +790,7 @@ Page_breaking::cache_line_details (vsize configuration_index) else { assert (div[i] == 1); - uncompressed_line_details_.push_back (Line_details (system_specs_[sys].prob_)); - uncompressed_line_details_.back ().padding_ = - robust_scm2double (system_specs_[sys].prob_->get_property ("next-padding"), - padding); + uncompressed_line_details_.push_back (Line_details (system_specs_[sys].prob_, book_->paper_)); } } cached_line_details_ = compress_lines (uncompressed_line_details_); @@ -830,6 +844,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) { @@ -841,15 +877,28 @@ 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 next_rod_height = cur_rod_height + ext_len - + ((cur_rod_height > 0) ? cached_line_details_[i].padding_: 0); + 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_; + } + 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) + min_whitespace_at_bottom_of_page (cached_line_details_[i]); @@ -861,7 +910,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; @@ -899,7 +948,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 ()); @@ -965,7 +1014,8 @@ Page_breaking::blank_page_penalty () const // 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, + Real penalty_for_fewer_pages) { Page_spacing_result n_res; Page_spacing_result m_res; @@ -1007,11 +1057,11 @@ Page_breaking::space_systems_on_n_or_one_more_pages (vsize configuration, vsize m_res = finalize_spacing_result (configuration, m_res); n_res = finalize_spacing_result (configuration, n_res); - Real penalty = blank_page_penalty (); - n_res.demerits_ += penalty; + Real page_spacing_weight = robust_scm2double (book_->paper_->c_variable ("page-spacing-weight"), 10); + n_res.demerits_ += penalty_for_fewer_pages * page_spacing_weight; if (n_res.force_.size ()) - n_res.force_.back () += penalty; + n_res.force_.back () += penalty_for_fewer_pages; return (m_res.demerits_ < n_res.demerits_) ? m_res : n_res; } @@ -1020,23 +1070,20 @@ Page_spacing_result Page_breaking::space_systems_on_best_pages (vsize configuration, vsize first_page_num) { vsize min_p_count = min_page_count (configuration, first_page_num); - Real odd_pages_penalty = blank_page_penalty (); cache_line_details (configuration); Page_spacer ps (cached_line_details_, first_page_num, this); Page_spacing_result best = ps.solve (min_p_count); - best.force_.back () += (min_p_count % 2) ? odd_pages_penalty : 0; - best.demerits_ += (min_p_count % 2) ? odd_pages_penalty : 0; for (vsize i = min_p_count+1; i <= cached_line_details_.size (); i++) { Page_spacing_result cur = ps.solve (i); - cur.demerits_ += (i % 2) ? odd_pages_penalty : 0; if (cur.demerits_ < best.demerits_) best = cur; } - return finalize_spacing_result (configuration, best); + Page_spacing_result ret = finalize_spacing_result (configuration, best); + return ret; } Page_spacing_result @@ -1100,6 +1147,7 @@ Page_breaking::pack_systems_on_least_pages (vsize configuration, vsize first_pag Page_spacing space (page_height (first_page_num, false), this); cache_line_details (configuration); + compute_line_heights (); for (vsize line = 0; line < cached_line_details_.size (); line++) { Real prev_force = space.force_; @@ -1380,7 +1428,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 @@ -1398,5 +1447,12 @@ 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 +Page_breaking::orphan_penalty () const +{ + return orphan_penalty_; }