X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Finclude%2Fpage-spacing.hh;h=4775baf67439da958720aec320e885aa1733f4a4;hb=c6758d6d12e33779fc81218693d5650682d8a1ca;hp=e7e3b4888ab38cf7c63a95cf6d51c8ff9f4b4277;hpb=6224c5c3bfe0a4c7aef15a060a323c77c99bd3f0;p=lilypond.git diff --git a/lily/include/page-spacing.hh b/lily/include/page-spacing.hh index e7e3b4888a..4775baf674 100644 --- a/lily/include/page-spacing.hh +++ b/lily/include/page-spacing.hh @@ -1,37 +1,126 @@ /* - page-spacing.hh -- routines for spacing systems - vertically across pages + This file is part of LilyPond, the GNU music typesetter. - source file of the GNU LilyPond music typesetter + Copyright (C) 2006--2015 Joe Neeman - (c) 2006 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 . */ #ifndef PAGE_SPACING_HH #define PAGE_SPACING_HH #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. + + BAD_SPACING_PENALTY is for occasions where the spacing is bad. + TERRIBLE_SPACING_PENALTY is for when we are disregarding a user override + (for example, we are failing to satisfy min-systems-per-page). These user + overrides are more important than getting good spacing, so they get a + larger penalty. +*/ +const Real BAD_SPACING_PENALTY = 1e6; +const Real TERRIBLE_SPACING_PENALTY = 1e8; -struct Spacing_result { - vector systems_per_page_; - vector force_; - Real penalty_; - Real demerits_; +/* for page_count > 2, we use a dynamic algorithm similar to + constrained-breaking -- we have a class that stores the intermediate + calculations so they can be reused for querying different page counts. +*/ +class Page_spacer +{ +public: + Page_spacer (vector const &lines, vsize first_page_num, Page_breaking const *); + Page_spacing_result solve (vsize page_count); + Page_spacing_result solve (); - Spacing_result () +private: + struct Page_spacing_node { - penalty_ = 0; - demerits_ = 0; - } + Page_spacing_node () + { + demerits_ = infinity_f; + force_ = infinity_f; + penalty_ = infinity_f; + prev_ = VPOS; + system_count_status_ = SYSTEM_COUNT_OK; + page_ = 0; + } + + Real demerits_; + Real force_; + Real penalty_; + vsize prev_; + vsize page_; + int system_count_status_; + }; + + Page_breaking const *breaker_; + vsize first_page_num_; + vector lines_; + + // If a page-count is requested, we use state_, which + // is indexed by page*system, for our dynamic programming + // intermediate storage. Otherwise, we use simple_state_, + // which is indexed only by system. + Matrix state_; + vector simple_state_; + vsize max_page_count_; + + bool ragged_; + bool ragged_last_; + + void resize (vsize page_count); + bool calc_subproblem (vsize page, vsize lines); }; -Spacing_result -space_systems_on_min_pages (vector const&, - Real page_height, - Real odd_pages_penalty); -Spacing_result -space_systems_on_best_pages (vector const&, - Real page_height, - Real odd_pages_penalty); +struct Page_spacing +{ + Real force_; + Real page_height_; + Real rod_height_; + Real spring_len_; + Real inverse_spring_k_; + bool has_footnotes_; + + Line_details last_line_; + Line_details first_line_; + Page_breaking const *breaker_; + + Page_spacing (Real page_height, Page_breaking const *breaker) + { + page_height_ = page_height; + breaker_ = breaker; + has_footnotes_ = false; + clear (); + } + + void calc_force (); + void resize (Real new_height); + Real account_for_footnotes (Line_details const &line); + void append_system (const Line_details &line); + void prepend_system (const Line_details &line); + void clear (); +}; #endif /* PAGE_SPACING_HH */