]> git.donarmstrong.com Git - lilypond.git/blob - lily/page-breaking.cc
Web-ja: update introduction
[lilypond.git] / lily / page-breaking.cc
1 /*
2   This file is part of LilyPond, the GNU music typesetter.
3
4   Copyright (C) 2006--2015 Joe Neeman <joeneeman@gmail.com>
5
6   LilyPond is free software: you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation, either version 3 of the License, or
9   (at your option) any later version.
10
11   LilyPond is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   GNU General Public License for more details.
15
16   You should have received a copy of the GNU General Public License
17   along with LilyPond.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 /*
21   This is a utility class for page-breaking algorithms. There are some complex
22   parts of this class, some of which are useful to understand if you intend
23   to write a page breaking algorithm (ie. a subclass of Page_breaking). Most
24   of these complexities were introduced in order to break the problem of
25   page-breaking into simpler subproblems and to hide some of the bookkeeping
26   complexities of page breaking from the page breaking algorithms.
27
28   COMPRESSED LINES
29   There are several functions that actually distribute systems across pages
30   (for example, the space_systems_XXX and pack_systems_XXX functions). If
31   each of these functions had to handle \noPageBreak, it would be a mess.
32   Therefore, we handle \noPageBreak by "compressing" the list of systems
33   before doing any layout: we concatenate any two systems separated by a
34   \noPageBreak into a single system. The page-breaking functions can do their
35   magic without encountering a \noPageBreak; we then "uncompress" the systems
36   at the end. We almost always work with cached_line_details_, which are
37   "compressed."
38
39   CHUNKS
40   The basic operation of a page breaking algorithm is to repeatedly request
41   some systems from the line-breaker and place those systems on some pages.
42   With each repetition, the page breaking algorithm asks the line-breaker for
43   some systems that it thinks will help it achieve a better layout. The
44   Page_breaking class provides functionality to facilitate this in the case
45   that the page breaking algorithm only cares about the number of systems.
46
47   Even if a page breaking algorithm only cares number of systems, there may
48   be many ways to satisfy its request. For example, in a piece with 2 scores
49   and a request for 10 systems, we could return 5 systems from each score or
50   4 from the first and 6 from the second. Even within a score, we might
51   want to try several different line breaking configurations with a fixed
52   system count; if there is a forced \pageBreak, for example, we might wish
53   to tweak the number of systems on both sides of the \pageBreak independently.
54
55   The Page_breaking class takes care of finding these configurations. It
56   divides the piece into "chunks" and sets up the line-breaker in such a way
57   that the number of systems in each chunk can be modified independently.
58   Chunks never cross score boundaries; each title and markup is its own chunk.
59   When a page breaking algorithm requests a number of systems, the Page_breaker
60   stores an array of potential configurations, which the page breaking
61   algorithm can iterate over using current_configuration(vsize).
62
63   LINE_DIVISION
64   A Line_division is simply a way of storing the exact way in which the
65   total number of systems is distributed among chunks. Note that a
66   Line_division may not (in fact, usually will not) describe all of the chunks
67   in the entire book. Rather, it will describe the subset of chunks that lie
68   between some fixed starting and ending point. This subset of chunks changes
69   whenever a page breaking algorithm asks to consider a different pair of
70   starting and ending breakpoints. In particular, a Line_division should be
71   discarded after a call to set_current_breakpoints, since that Line_division
72   refers to a subset of chunks which might be different from the current
73   subset of chunks under consideration.
74
75   HOW TO WRITE A PAGE BREAKING ALGORITHM
76   All page breakers supported by this class work more-or-less in the same way.
77   First, they request a particular number of systems by saying
78     set_current_breakpoints (0, last_break_position (), system_count)
79   (never mind what the first two arguments do, I'll get to them later).
80   Alternatively, you can do
81     set_to_ideal_line_configuration (0, last_break_position ()),
82   and the number of systems will be automatically chosen according to what
83   the line breaker wants.
84
85   If there are multiple scores, there will be many different ways to achieve
86   a certain number of lines.  You can see how many alternatives are available
87   with current_configuration_count ().  For every i from 0 to
88   current_configuration_count ()-1, you can see the line division of the
89   corresponding configuration with current_configuration (i), or you can try
90   out various page configurations with one of the space_systems_xxx or
91   pack_systems_xxx functions.  The first argument to each of these functions
92   is the configuration index.
93
94   When you're done trying out configurations and you've picked the one
95   you want, do
96     break_into_pieces (0, last_break_position (), line_division_that_you_want);
97     return make_pages (systems_per_page, systems ());
98   where systems_per_page is a vector of numbers telling how many systems are
99   on each page.  You can get your systems_per_page vector by looking inside
100   the Page_spacing_results that are returned by space_systems_xxx or
101   pack_systems_xxx.
102
103   A note on performance: set_current_breakpoints is EXPONENTIALLY SLOW unless
104   you constrain it by giving it a lower or an upper bound on the configurations
105   it looks for.  Optimal_page_breaking, for example, works by trying
106   out a bunch of configurations, increasing the system count by one, trying
107   again and so on.  Each time we increase the system count, we assume that the
108   best new configurations are going to be elementwise larger than the
109   best configuration for the previous system count (in other words, we're going
110   to get a new configuration just by adding an extra line to sone score
111   and leaving the rest the same).  Therefore, we pass the best previous line
112   division as an lower bound to set_current_breakpoints.
113
114   Now you should be in a position to understand Optimal_page_breaking::solve.
115   Go ahead and read that before finding out, in the next paragraph,
116   what the first two arguments to set_current_breakpoints do.
117
118   "BREAKS"
119   Sometimes, it's useful to run this whole page-breaking machinery on a subset
120   of the book.  To do this, you can mark certain "breaks" in the book (a poor
121   choice of name, perhaps, since a "break" here is different from a page break)
122   and you can run page breaking between any two breaks.  You mark your breaks
123   by providing a Break_predicate (and, if you want, a Prob_break_predicate)
124   to Page_breaking's constructor.  You then choose a subset of your book
125   by passing the starting and ending breaks to set_current_breakpoints.  You
126   can see an example of this in Page_turn_page_breaking, where there is a break
127   everywhere that a page turn is allowed.
128 */
129
130 #include "page-breaking.hh"
131
132 #include "international.hh"
133 #include "item.hh"
134 #include "line-interface.hh"
135 #include "output-def.hh"
136 #include "page-layout-problem.hh"
137 #include "page-spacing.hh"
138 #include "paper-book.hh"
139 #include "paper-score.hh"
140 #include "paper-system.hh"
141 #include "text-interface.hh"
142 #include "system.hh"
143 #include "warn.hh"
144
145 /* for each forbidden page break, merge the systems around it into one
146    system. */
147 static vector<Line_details>
148 compress_lines (const vector<Line_details> &orig)
149 {
150   vector<Line_details> ret;
151
152   for (vsize i = 0; i < orig.size (); i++)
153     {
154       if (ret.size () && !scm_is_symbol (ret.back ().page_permission_))
155         {
156           Line_details const &old = ret.back ();
157           Line_details compressed = orig[i];
158           /*
159             We must account for the padding between the lines that we are compressing.
160             The padding values come from "old," which is the upper system here. Note
161             the meaning of tight-spacing: if a system has tight-spacing, then the padding
162             _before_ it is ignored.
163           */
164           Real padding = 0;
165           if (!orig[i].tight_spacing_)
166             padding = orig[i].title_ ? old.title_padding_ : old.padding_;
167
168           // FIXME: double check these. Doesn't foo.piggyback (bar) mean
169           // that foo goes on top?
170           // TODO: break out a Line_details::piggyback from here?
171           compressed.shape_ = old.shape_.piggyback (orig[i].shape_, padding);
172           compressed.refpoint_extent_[UP] = old.refpoint_extent_[UP];
173           compressed.refpoint_extent_[DOWN] += compressed.shape_.rest_[UP] - old.shape_.rest_[UP];
174           compressed.space_ += old.space_;
175           compressed.inverse_hooke_ += old.inverse_hooke_;
176
177           compressed.compressed_lines_count_ = old.compressed_lines_count_ + 1;
178           compressed.compressed_nontitle_lines_count_
179             = old.compressed_nontitle_lines_count_ + (compressed.title_ ? 0 : 1);
180
181           // compressed.title_ is true if and only if the first of its
182           // compressed lines was a title.
183           compressed.title_ = old.title_;
184
185           // adds footnotes of one line to the footnotes of another
186           compressed.footnote_heights_.insert (compressed.footnote_heights_.begin (),
187                                                old.footnote_heights_.begin (),
188                                                old.footnote_heights_.end ());
189           compressed.in_note_heights_.insert (compressed.in_note_heights_.begin (),
190                                               old.in_note_heights_.begin (),
191                                               old.in_note_heights_.end ());
192
193           ret.back () = compressed;
194         }
195       else
196         {
197           ret.push_back (orig[i]);
198         }
199     }
200   return ret;
201 }
202
203 /* translate the number of systems-per-page into something meaningful for
204    the uncompressed lines.
205 */
206 static vector<vsize>
207 uncompress_solution (vector<vsize> const &systems_per_page,
208                      vector<Line_details> const &compressed)
209 {
210   vector<vsize> ret;
211   vsize start_sys = 0;
212
213   for (vsize i = 0; i < systems_per_page.size (); i++)
214     {
215       int compressed_count = 0;
216       for (vsize j = start_sys; j < start_sys + systems_per_page[i]; j++)
217         compressed_count += compressed[j].compressed_lines_count_ - 1;
218
219       ret.push_back (systems_per_page[i] + compressed_count);
220       start_sys += systems_per_page[i];
221     }
222   return ret;
223 }
224
225 /* for Page_breaking, the start index (when we are dealing with the stuff
226    between a pair of breakpoints) refers to the break_ index of the end of
227    the previous page. So the system index of the start of the current page
228    could either be the same as the end of the previous page or one more than
229    it. */
230
231 /* Turn a break index into the sys index that starts the next page */
232 vsize
233 Page_breaking::next_system (Break_position const &break_pos) const
234 {
235   vsize sys = break_pos.system_spec_index_;
236
237   if (sys == VPOS) /* beginning of the book */
238     return 0;
239   if (system_specs_[sys].pscore_ && !break_pos.score_ender_)
240     return sys; /* the score overflows the previous page */
241   return sys + 1; /* this page starts with a new System_spec */
242 }
243
244 Page_breaking::Page_breaking (Paper_book *pb, Break_predicate is_break, Prob_break_predicate prob_break)
245 {
246   book_ = pb;
247   system_count_ = 0;
248   paper_height_ = robust_scm2double (pb->paper_->c_variable ("paper-height"), 1.0);
249   ragged_ = to_boolean (pb->paper_->c_variable ("ragged-bottom"));
250   ragged_last_ = to_boolean (pb->paper_->c_variable ("ragged-last-bottom"));
251   systems_per_page_ = max (0, robust_scm2int (pb->paper_->c_variable ("systems-per-page"), 0));
252   max_systems_per_page_ = max (0, robust_scm2int (pb->paper_->c_variable ("max-systems-per-page"), 0));
253   min_systems_per_page_ = max (0, robust_scm2int (pb->paper_->c_variable ("min-systems-per-page"), 0));
254   orphan_penalty_ = robust_scm2int (pb->paper_->c_variable ("orphan-penalty"), 100000);
255
256   Stencil footnote_separator = Page_layout_problem::get_footnote_separator_stencil (pb->paper_);
257
258   if (!footnote_separator.is_empty ())
259     {
260       Interval separator_extent = footnote_separator.extent (Y_AXIS);
261       Real separator_span = separator_extent.length ();
262
263       footnote_separator_stencil_height_ = separator_span;
264     }
265   else
266     footnote_separator_stencil_height_ = 0.0;
267
268   footnote_padding_ = robust_scm2double (pb->paper_->c_variable ("footnote-padding"), 0.0);
269   in_note_padding_ = robust_scm2double (pb->paper_->c_variable ("in-note-padding"), 0.0);
270   footnote_footer_padding_ = robust_scm2double (pb->paper_->c_variable ("footnote-footer-padding"), 0.0);
271
272   footnote_number_raise_ = robust_scm2double (pb->paper_->c_variable ("footnote-number-raise"), 0.0);
273
274   if (systems_per_page_ && (max_systems_per_page_ || min_systems_per_page_))
275     {
276       warning (_f ("ignoring min-systems-per-page and max-systems-per-page because systems-per-page was set"));
277       min_systems_per_page_ = max_systems_per_page_ = 0;
278     }
279   if (max_systems_per_page_ && min_systems_per_page_ > max_systems_per_page_)
280     {
281       warning (_f ("min-systems-per-page is larger than max-systems-per-page, ignoring both values"));
282       min_systems_per_page_ = max_systems_per_page_ = 0;
283     }
284
285   create_system_list ();
286   find_chunks_and_breaks (is_break, prob_break);
287 }
288
289 Page_breaking::~Page_breaking ()
290 {
291 }
292
293 bool
294 Page_breaking::ragged () const
295 {
296   return ragged_;
297 }
298
299 bool
300 Page_breaking::ragged_last () const
301 {
302   return ragged_last_;
303 }
304
305 int
306 Page_breaking::systems_per_page () const
307 {
308   return systems_per_page_;
309 }
310
311 int
312 Page_breaking::max_systems_per_page () const
313 {
314   if (systems_per_page_)
315     return systems_per_page_;
316   return max_systems_per_page_;
317 }
318
319 int
320 Page_breaking::min_systems_per_page () const
321 {
322   if (systems_per_page_)
323     return systems_per_page_;
324   return min_systems_per_page_;
325 }
326
327 vsize
328 Page_breaking::system_count () const
329 {
330   return system_count_;
331 }
332
333 Real
334 Page_breaking::footnote_separator_stencil_height () const
335 {
336   return footnote_separator_stencil_height_;
337 }
338
339 Real
340 Page_breaking::in_note_padding () const
341 {
342   return in_note_padding_;
343 }
344
345 Real
346 Page_breaking::footnote_padding () const
347 {
348   return footnote_padding_;
349 }
350
351 Real
352 Page_breaking::footnote_footer_padding () const
353 {
354   return footnote_footer_padding_;
355 }
356
357 Real
358 Page_breaking::footnote_number_raise () const
359 {
360   return footnote_number_raise_;
361 }
362
363 bool
364 Page_breaking::too_many_lines (int line_count) const
365 {
366   return max_systems_per_page () > 0 && line_count > max_systems_per_page ();
367 }
368
369 bool
370 Page_breaking::too_few_lines (int line_count) const
371 {
372   return line_count < min_systems_per_page ();
373 }
374
375 Real
376 Page_breaking::line_count_penalty (int line_count) const
377 {
378   if (too_many_lines (line_count))
379     return (line_count - max_systems_per_page ()) * TERRIBLE_SPACING_PENALTY;
380   if (too_few_lines (line_count))
381     return (min_systems_per_page () - line_count) * TERRIBLE_SPACING_PENALTY;
382
383   return 0;
384 }
385
386 int
387 Page_breaking::line_count_status (int line_count) const
388 {
389   if (too_many_lines (line_count))
390     return SYSTEM_COUNT_TOO_MANY;
391   if (too_few_lines (line_count))
392     return SYSTEM_COUNT_TOO_FEW;
393
394   return SYSTEM_COUNT_OK;
395 }
396
397 /* translate indices into breaks_ into start-end parameters for the line breaker */
398 void
399 Page_breaking::line_breaker_args (vsize sys,
400                                   Break_position const &start,
401                                   Break_position const &end,
402                                   vsize *line_breaker_start,
403                                   vsize *line_breaker_end)
404 {
405   assert (system_specs_[sys].pscore_);
406   assert (next_system (start) <= sys && sys <= end.system_spec_index_);
407
408   if (start.system_spec_index_ == sys)
409     *line_breaker_start = start.score_break_;
410   else
411     *line_breaker_start = 0;
412
413   if (end.system_spec_index_ == sys)
414     *line_breaker_end = end.score_break_;
415   else
416     *line_breaker_end = VPOS;
417 }
418
419 void
420 Page_breaking::break_into_pieces (vsize start_break, vsize end_break,
421                                   Line_division const &div)
422 {
423   vector<Break_position> chunks = chunk_list (start_break, end_break);
424   bool ignore_div = false;
425   if (chunks.size () != div.size () + 1)
426     {
427       programming_error ("did not find a valid page breaking configuration");
428       ignore_div = true;
429     }
430
431   for (vsize i = 0; i + 1 < chunks.size (); i++)
432     {
433       vsize sys = next_system (chunks[i]);
434       if (system_specs_[sys].pscore_)
435         {
436           vsize start;
437           vsize end;
438           line_breaker_args (sys, chunks[i], chunks[i + 1], &start, &end);
439
440           vector<Column_x_positions> pos = ignore_div
441                                            ? line_breaking_[sys].best_solution (start, end)
442                                            : line_breaking_[sys].solve (start, end, div[i]);
443           system_specs_[sys].pscore_->root_system ()->break_into_pieces (pos);
444         }
445     }
446 }
447
448 SCM
449 Page_breaking::systems ()
450 {
451   SCM ret = SCM_EOL;
452   for (vsize sys = 0; sys < system_specs_.size (); sys++)
453     {
454       if (system_specs_[sys].pscore_)
455         {
456           system_specs_[sys].pscore_->root_system ()
457           ->do_break_substitution_and_fixup_refpoints ();
458           SCM lines = system_specs_[sys].pscore_->root_system ()
459                       ->get_broken_system_grobs ();
460           ret = scm_cons (lines, ret);
461         }
462       else if (Prob *pb = system_specs_[sys].prob_)
463         {
464           ret = scm_cons (scm_list_1 (pb->self_scm ()), ret);
465           pb->unprotect ();
466         }
467     }
468   return scm_append (scm_reverse_x (ret, SCM_EOL));
469 }
470
471 SCM
472 Page_breaking::make_page (int page_num, bool last) const
473 {
474   bool last_part = ly_scm2bool (book_->paper_->c_variable ("is-last-bookpart"));
475   SCM mod = scm_c_resolve_module ("scm page");
476   SCM make_page_scm = scm_c_module_lookup (mod, "make-page");
477
478   make_page_scm = scm_variable_ref (make_page_scm);
479
480   return scm_apply_0 (make_page_scm,
481                       scm_list_n (book_->self_scm (),
482                                   ly_symbol2scm ("page-number"), scm_from_int (page_num),
483                                   ly_symbol2scm ("is-last-bookpart"), scm_from_bool (last_part),
484                                   ly_symbol2scm ("is-bookpart-last-page"), scm_from_bool (last),
485                                   SCM_UNDEFINED));
486 }
487
488 // Returns the total height of the paper, including margins and
489 // space for the header/footer.  This is an upper bound on
490 // page_height, and it doesn't depend on the current page.
491 Real
492 Page_breaking::paper_height () const
493 {
494   return paper_height_;
495 }
496
497 Real
498 Page_breaking::page_height (int page_num, bool last) const
499 {
500   // The caches allow us to store the page heights for any
501   // non-negative page numbers.  We use a negative value in the
502   // cache to signal that that position has not yet been initialized.
503   // This means that we won't cache properly if page_num is negative or
504   // if calc_height returns a negative number.  But that's likely to
505   // be rare, so it shouldn't affect performance.
506   vector<Real> &cache = last ? last_page_height_cache_ : page_height_cache_;
507   if (page_num >= 0 && (int) cache.size () > page_num && cache[page_num] >= 0)
508     return cache[page_num];
509   else
510     {
511       SCM mod = scm_c_resolve_module ("scm page");
512       SCM page = make_page (page_num, last);
513       SCM calc_height = scm_c_module_lookup (mod, "calc-printable-height");
514       calc_height = scm_variable_ref (calc_height);
515
516       SCM height_scm = scm_apply_1 (calc_height, page, SCM_EOL);
517       Real height = scm_to_double (height_scm);
518
519       if (page_num >= 0)
520         {
521           if ((int) cache.size () <= page_num)
522             cache.resize (page_num + 1, -1);
523           cache[page_num] = height;
524         }
525       return height;
526     }
527 }
528
529 SCM
530 Page_breaking::breakpoint_property (vsize breakpoint, char const *str)
531 {
532   Break_position const &pos = breaks_[breakpoint];
533
534   if (pos.system_spec_index_ == VPOS)
535     return SCM_EOL;
536   if (system_specs_[pos.system_spec_index_].pscore_)
537     return pos.col_->get_property (str);
538   return system_specs_[pos.system_spec_index_].prob_->get_property (str);
539 }
540
541 SCM
542 Page_breaking::get_page_configuration (SCM systems, int page_num, bool ragged, bool last)
543 {
544   SCM dummy_page = make_page (page_num, last);
545   Page_layout_problem layout (book_, dummy_page, systems);
546   return scm_is_pair (systems) ? layout.solution (ragged) : SCM_EOL;
547 }
548
549 SCM
550 Page_breaking::draw_page (SCM systems, SCM configuration, int page_num, bool last)
551 {
552   // Create a stencil for each system.
553   SCM paper_systems = SCM_EOL;
554   for (SCM s = systems; scm_is_pair (s); s = scm_cdr (s))
555     {
556       SCM paper_system = scm_car (s);
557       if (Grob *g = unsmob<Grob> (scm_car (s)))
558         {
559           System *sys = dynamic_cast<System *> (g);
560           paper_system = sys->get_paper_system ();
561         }
562
563       paper_systems = scm_cons (paper_system, paper_systems);
564     }
565   paper_systems = scm_reverse_x (paper_systems, SCM_EOL);
566
567   // Create the page and draw it.
568   SCM page = make_page (page_num, last);
569
570   Prob *p = unsmob<Prob> (page);
571   p->set_property ("lines", paper_systems);
572   p->set_property ("configuration", configuration);
573
574   Stencil *foot_p = unsmob<Stencil> (p->get_property ("foot-stencil"));
575   Stencil foot = foot_p ? *foot_p : Stencil ();
576
577   SCM footnotes = Page_layout_problem::get_footnotes_from_lines (systems);
578
579   foot = Page_layout_problem::add_footnotes_to_footer (footnotes, foot, book_);
580
581   p->set_property ("foot-stencil", foot.smobbed_copy ());
582
583   return page;
584 }
585
586 SCM
587 Page_breaking::make_pages (vector<vsize> lines_per_page, SCM systems)
588 {
589   if (scm_is_null (systems))
590     return SCM_EOL;
591
592   int first_page_number
593     = robust_scm2int (book_->paper_->c_variable ("first-page-number"), 1);
594   SCM ret = SCM_EOL;
595   bool reset_footnotes_on_new_page = to_boolean (book_->top_paper ()->c_variable ("reset-footnotes-on-new-page"));
596   SCM label_page_table = book_->top_paper ()->c_variable ("label-page-table");
597   if (SCM_UNBNDP (label_page_table))
598     label_page_table = SCM_EOL;
599
600   // Build a list of (systems configuration . footnote-count) triples.
601   // Note that we lay out the staves and find the configurations,
602   // but we do not draw anything in this function.  It is important
603   // that all staves are laid out vertically before any are drawn; some
604   // grobs (like tuplet brackets) look at their neighbours while drawing
605   // themselves.  If this happens before the neighbouring staves have
606   // been laid out, bad side-effects could happen (in particular,
607   // Align_interface::align_to_ideal_distances might be called).
608   SCM systems_configs_fncounts = SCM_EOL;
609   vsize footnote_count = 0;
610   Real last_page_force = 0;
611
612   for (vsize i = 0; i < lines_per_page.size (); i++)
613     {
614       int page_num = i + first_page_number;
615       bool bookpart_last_page = (i == lines_per_page.size () - 1);
616       bool rag = ragged () || (bookpart_last_page && ragged_last ());
617       SCM line_count = scm_from_int (lines_per_page[i]);
618       SCM lines = scm_list_head (systems, line_count);
619       int fn_lines = Page_layout_problem::get_footnote_count (lines);
620       Page_layout_problem::add_footnotes_to_lines (lines, reset_footnotes_on_new_page ? 0 : footnote_count, book_);
621
622       SCM config = SCM_EOL;
623       SCM dummy_page = make_page (page_num, bookpart_last_page);
624       Page_layout_problem layout (book_, dummy_page, lines);
625       if (!scm_is_pair (systems))
626         config = SCM_EOL;
627       else if (rag && !ragged ())
628         // If we're ragged-last but not ragged, make the last page
629         // have the same force as the previous page.
630         config = layout.fixed_force_solution (last_page_force);
631       else
632         config = layout.solution (rag);
633
634       if ((ragged () && layout.force () < 0.0)
635           || isinf (layout.force ()))
636         warning (_f ("page %d has been compressed", page_num));
637       else
638         last_page_force = layout.force ();
639
640       systems_configs_fncounts = scm_cons (scm_cons (lines, config), systems_configs_fncounts);
641       footnote_count += fn_lines;
642       systems = scm_list_tail (systems, line_count);
643     }
644
645   // TODO: previously, the following loop caused the systems to be
646   // drawn.  Now that we no longer draw anything in Page_breaking,
647   // it is safe to merge these two loops.
648   int page_num = first_page_number + lines_per_page.size () - 1;
649   for (SCM s = systems_configs_fncounts; scm_is_pair (s); s = scm_cdr (s))
650     {
651       SCM lines = scm_caar (s);
652       SCM config = scm_cdar (s);
653
654       bool bookpart_last_page = scm_is_eq (s, systems_configs_fncounts);
655       SCM page = draw_page (lines, config, page_num, bookpart_last_page);
656       /* collect labels */
657       SCM page_num_scm = scm_from_int (page_num);
658       for (SCM l = lines; scm_is_pair (l); l = scm_cdr (l))
659         {
660           SCM labels = SCM_EOL;
661           if (Grob *line = unsmob<Grob> (scm_car (l)))
662             {
663               System *system = dynamic_cast<System *> (line);
664               labels = system->get_property ("labels");
665             }
666           else if (Prob *prob = unsmob<Prob> (scm_car (l)))
667             labels = prob->get_property ("labels");
668
669           for (SCM lbls = labels; scm_is_pair (lbls); lbls = scm_cdr (lbls))
670             label_page_table = scm_cons (scm_cons (scm_car (lbls), page_num_scm),
671                                          label_page_table);
672         }
673
674       ret = scm_cons (page, ret);
675       --page_num;
676     }
677
678   // By reversing the table, we ensure that duplicated labels (eg. those
679   // straddling a page turn) will appear in the table with their last
680   // occurence first.
681   label_page_table = scm_reverse_x (label_page_table, SCM_EOL);
682   book_->top_paper ()->set_variable (ly_symbol2scm ("label-page-table"), label_page_table);
683   return ret;
684 }
685
686 void
687 Page_breaking::create_system_list ()
688 {
689   SCM specs = book_->get_system_specs ();
690   for (SCM s = specs; scm_is_pair (s); s = scm_cdr (s))
691     {
692       if (Paper_score *ps = unsmob<Paper_score> (scm_car (s)))
693         {
694           system_specs_.push_back (System_spec (ps));
695         }
696       else
697         {
698           Prob *pb = unsmob<Prob> (scm_car (s));
699           assert (pb);
700
701           pb->protect ();
702           system_specs_.push_back (System_spec (pb));
703         }
704     }
705   if (!system_specs_.size ())
706     system_specs_.push_back (System_spec ());
707 }
708
709 /* The page-turn-page-breaker needs to have a line-breaker between any two
710    columns with non-NULL page-turn-permission.
711
712    The optimal-breaker needs to have a line-breaker between any two columns
713    with page-break-permission = 'force.
714
715    By using a grob predicate, we can accommodate both of these uses.
716 */
717 void
718 Page_breaking::find_chunks_and_breaks (Break_predicate is_break, Prob_break_predicate prob_is_break)
719 {
720   SCM force_sym = ly_symbol2scm ("force");
721
722   chunks_.push_back (Break_position ());
723   breaks_.push_back (Break_position ());
724
725   for (vsize i = 0; i < system_specs_.size (); i++)
726     {
727       if (system_specs_[i].pscore_)
728         {
729           vector<Grob *> cols = system_specs_[i].pscore_->root_system ()->used_columns ();
730           vector<Grob *> forced_line_break_cols;
731
732           SCM system_count = system_specs_[i].pscore_->layout ()->c_variable ("system-count");
733           if (scm_is_number (system_count))
734             {
735               // With system-count given, the line configuration for
736               // this score is fixed.  We need to ensure that chunk
737               // boundaries only occur at line breaks.
738               Constrained_breaking breaking (system_specs_[i].pscore_);
739               vector<Line_details> details = breaking.line_details (0, VPOS, scm_to_int (system_count));
740
741               for (vsize j = 0; j < details.size (); j++)
742                 forced_line_break_cols.push_back (details[j].last_column_);
743             }
744
745           int last_forced_line_break_idx = 0;
746           vsize forced_line_break_idx = 0;
747           vector<vsize> line_breaker_columns;
748           line_breaker_columns.push_back (0);
749
750           for (vsize j = 0; j < cols.size (); j++)
751             {
752               if (forced_line_break_cols.size ())
753                 {
754                   if (forced_line_break_idx >= forced_line_break_cols.size ()
755                       || forced_line_break_cols[forced_line_break_idx] != cols[j])
756                     continue;
757                   else
758                     forced_line_break_idx++;
759                 }
760
761               bool last = (j == cols.size () - 1);
762               bool break_point = is_break && is_break (cols[j]);
763               bool chunk_end = scm_is_eq (cols[j]->get_property ("page-break-permission"), force_sym);
764               Break_position cur_pos = Break_position (i,
765                                                        line_breaker_columns.size (),
766                                                        cols[j],
767                                                        last);
768
769               // NOTE: even in the breaks_ list, forced_line_count_
770               // refers to the number of lines between a
771               // Break_position and the start of that /chunk/.  This
772               // is needed for system_count_bounds to work correctly,
773               // since it mixes Break_positions from breaks_ and
774               // chunks_.
775               if (scm_is_number (system_count))
776                 cur_pos.forced_line_count_ = forced_line_break_idx - last_forced_line_break_idx;
777
778               if (break_point || (i == system_specs_.size () - 1 && last))
779                 breaks_.push_back (cur_pos);
780               if (chunk_end || last)
781                 {
782                   chunks_.push_back (cur_pos);
783                   last_forced_line_break_idx = forced_line_break_idx;
784                 }
785
786               if ((break_point || chunk_end) && !last)
787                 line_breaker_columns.push_back (j);
788             }
789           line_breaking_.push_back (Constrained_breaking (system_specs_[i].pscore_, line_breaker_columns));
790         }
791       else if (system_specs_[i].prob_)
792         {
793           bool break_point = prob_is_break && prob_is_break (system_specs_[i].prob_);
794           if (break_point || i == system_specs_.size () - 1)
795             breaks_.push_back (Break_position (i));
796
797           chunks_.push_back (Break_position (i));
798
799           /* FIXME: shouldn't we push a Null_breaker or similar dummy
800              class? --hwn */
801           line_breaking_.push_back (Constrained_breaking (NULL));
802         }
803     }
804 }
805
806 vector<Break_position>
807 Page_breaking::chunk_list (vsize start_index, vsize end_index)
808 {
809   Break_position start = breaks_[start_index];
810   Break_position end = breaks_[end_index];
811
812   vsize i = 0;
813   for (; i < chunks_.size () && chunks_[i] <= start; i++)
814     ;
815
816   vector<Break_position> ret;
817   ret.push_back (start);
818   for (; i < chunks_.size () && chunks_[i] < end; i++)
819     ret.push_back (chunks_[i]);
820   ret.push_back (end);
821   return ret;
822 }
823
824 // Returns the minimum number of _non-title_ lines.
825 vsize
826 Page_breaking::min_system_count (vsize start, vsize end)
827 {
828   vector<Break_position> chunks = chunk_list (start, end);
829   Line_division div = system_count_bounds (chunks, true);
830   vsize ret = 0;
831
832   for (vsize i = 0; i < div.size (); i++)
833     ret += div[i];
834   return ret;
835 }
836
837 // Returns the maximum number of _non-title_ lines.
838 vsize
839 Page_breaking::max_system_count (vsize start, vsize end)
840 {
841   vector<Break_position> chunks = chunk_list (start, end);
842   Line_division div = system_count_bounds (chunks, false);
843   vsize ret = 0;
844
845   for (vsize i = 0; i < div.size (); i++)
846     ret += div[i];
847   return ret;
848 }
849
850 // The numbers returned by this function represent either
851 // the maximum or minimum number of _non-title_ lines
852 // per chunk.
853 Page_breaking::Line_division
854 Page_breaking::system_count_bounds (vector<Break_position> const &chunks,
855                                     bool min)
856 {
857   assert (chunks.size () >= 2);
858
859   Line_division ret;
860   ret.resize (chunks.size () - 1, 0);
861
862   for (vsize i = 0; i + 1 < chunks.size (); i++)
863     {
864       vsize sys = next_system (chunks[i]);
865
866       if (chunks[i + 1].forced_line_count_)
867         ret[i] = chunks[i + 1].forced_line_count_;
868       else if (system_specs_[sys].pscore_)
869         {
870           vsize start;
871           vsize end;
872           line_breaker_args (sys, chunks[i], chunks[i + 1], &start, &end);
873           ret[i] = min
874                    ? line_breaking_[sys].min_system_count (start, end)
875                    : line_breaking_[sys].max_system_count (start, end);
876         }
877     }
878
879   return ret;
880 }
881
882 void
883 Page_breaking::set_current_breakpoints (vsize start,
884                                         vsize end,
885                                         vsize system_count,
886                                         Line_division lower_bound,
887                                         Line_division upper_bound)
888 {
889   system_count_ = system_count;
890   current_chunks_ = chunk_list (start, end);
891   current_start_breakpoint_ = start;
892   current_end_breakpoint_ = end;
893   clear_line_details_cache ();
894
895   if (!lower_bound.size ())
896     lower_bound = system_count_bounds (current_chunks_, true);
897   if (!upper_bound.size ())
898     upper_bound = system_count_bounds (current_chunks_, false);
899
900   assert (lower_bound.size () == current_chunks_.size () - 1);
901   assert (upper_bound.size () == current_chunks_.size () - 1);
902
903   Line_division work_in_progress;
904   current_configurations_.clear ();
905   line_divisions_rec (system_count,
906                       lower_bound,
907                       upper_bound,
908                       &work_in_progress);
909
910   /* we only consider a constant number of configurations. Otherwise,
911      this becomes slow when there are many small scores. The constant
912      5 is somewhat arbitrary. */
913   if (current_configurations_.size () > 5)
914     {
915       vector<pair<Real, vsize> > dems_and_indices;
916
917       for (vsize i = 0; i < current_configurations_.size (); i++)
918         {
919           cache_line_details (i);
920           Real dem = 0;
921           for (vsize j = 0; j < cached_line_details_.size (); j++)
922             dem += cached_line_details_[j].force_ * cached_line_details_[j].force_
923                    + cached_line_details_[j].break_penalty_;
924
925           dems_and_indices.push_back (pair<Real, vsize> (dem, i));
926         }
927       vector_sort (dems_and_indices, less<pair<Real, vsize> > ());
928
929       vector<Line_division> best_5_configurations;
930       for (vsize i = 0; i < 5; i++)
931         best_5_configurations.push_back (current_configurations_[dems_and_indices[i].second]);
932
933       clear_line_details_cache ();
934       current_configurations_ = best_5_configurations;
935     }
936 }
937
938 void
939 Page_breaking::set_to_ideal_line_configuration (vsize start, vsize end)
940 {
941   current_chunks_ = chunk_list (start, end);
942   current_start_breakpoint_ = start;
943   current_end_breakpoint_ = end;
944   clear_line_details_cache ();
945   system_count_ = 0;
946
947   Line_division div;
948   for (vsize i = 0; i + 1 < current_chunks_.size (); i++)
949     {
950       vsize sys = next_system (current_chunks_[i]);
951
952       if (current_chunks_[i + 1].forced_line_count_)
953         div.push_back (current_chunks_[i + 1].forced_line_count_);
954       else if (system_specs_[sys].pscore_)
955         {
956           line_breaker_args (sys, current_chunks_[i], current_chunks_[i + 1], &start, &end);
957           div.push_back (line_breaking_[sys].best_solution (start, end).size ());
958         }
959       else
960         div.push_back (0);
961
962       system_count_ += div.back ();
963     }
964   current_configurations_.clear ();
965   current_configurations_.push_back (div);
966 }
967
968 vsize
969 Page_breaking::current_configuration_count () const
970 {
971   return current_configurations_.size ();
972 }
973
974 void
975 Page_breaking::cache_line_details (vsize configuration_index)
976 {
977   if (cached_configuration_index_ != configuration_index)
978     {
979       cached_configuration_index_ = configuration_index;
980
981       Line_division &div = current_configurations_[configuration_index];
982       uncompressed_line_details_.clear ();
983       for (vsize i = 0; i + 1 < current_chunks_.size (); i++)
984         {
985           vsize sys = next_system (current_chunks_[i]);
986           if (system_specs_[sys].pscore_)
987             {
988               vsize start;
989               vsize end;
990               line_breaker_args (sys, current_chunks_[i], current_chunks_[i + 1], &start, &end);
991
992               vector<Line_details> details = line_breaking_[sys].line_details (start, end, div[i]);
993               uncompressed_line_details_.insert (uncompressed_line_details_.end (), details.begin (), details.end ());
994             }
995           else
996             {
997               assert (div[i] == 0);
998               uncompressed_line_details_.push_back (system_specs_[sys].prob_
999                                                     ? Line_details (system_specs_[sys].prob_, book_->paper_)
1000                                                     : Line_details ());
1001             }
1002         }
1003       cached_line_details_ = compress_lines (uncompressed_line_details_);
1004       compute_line_heights ();
1005     }
1006 }
1007
1008 void
1009 Page_breaking::clear_line_details_cache ()
1010 {
1011   cached_configuration_index_ = VPOS;
1012   cached_line_details_.clear ();
1013   uncompressed_line_details_.clear ();
1014 }
1015
1016 void
1017 Page_breaking::line_divisions_rec (vsize system_count,
1018                                    Line_division const &min_sys,
1019                                    Line_division const &max_sys,
1020                                    Line_division *cur_division)
1021 {
1022   vsize my_index = cur_division->size ();
1023   int others_min = 0;
1024   int others_max = 0;
1025
1026   for (vsize i = my_index + 1; i < min_sys.size (); i++)
1027     {
1028       others_min += min_sys[i];
1029       others_max += max_sys[i];
1030     }
1031   others_max = min (others_max, (int) system_count);
1032   int real_min = max ((int) min_sys[my_index], (int) system_count - others_max);
1033   int real_max = min ((int) max_sys[my_index], (int) system_count - others_min);
1034
1035   if (real_min > real_max || real_min < 0)
1036     {
1037       /* this should never happen within a recursive call. If it happens
1038          at all, it means that we were called with an unsolvable problem
1039          and we should return an empty result */
1040       assert (my_index == 0);
1041       return;
1042     }
1043
1044   for (int i = real_min; i <= real_max; i++)
1045     {
1046       cur_division->push_back (i);
1047       if (my_index == min_sys.size () - 1)
1048         current_configurations_.push_back (*cur_division);
1049       else
1050         line_divisions_rec (system_count - i, min_sys, max_sys, cur_division);
1051       cur_division->pop_back ();
1052     }
1053 }
1054
1055 void
1056 Page_breaking::compute_line_heights ()
1057 {
1058   Real prev_hanging = 0;
1059   Real prev_hanging_begin = 0;
1060   Real prev_hanging_rest = 0;
1061
1062   // refpoint_hanging is the y coordinate of the origin of this system.
1063   // It may not be the same as refpoint_extent[UP], which is the
1064   // refpoint of the first spaceable staff in this system.
1065   Real prev_refpoint_hanging = 0;
1066   for (vsize i = 0; i < cached_line_details_.size (); i++)
1067     {
1068       Line_details &cur = cached_line_details_[i];
1069       Line_shape shape = cur.shape_;
1070       Real a = shape.begin_[UP];
1071       Real b = shape.rest_[UP];
1072       bool title = cur.title_;
1073       Real refpoint_hanging = max (prev_hanging_begin + a, prev_hanging_rest + b);
1074
1075       if (i > 0)
1076         {
1077           Real padding = 0;
1078           Line_details const &prev = cached_line_details_[i - 1];
1079           if (!cur.tight_spacing_)
1080             padding = title
1081                       ? prev.title_padding_
1082                       : prev.padding_;
1083           Real min_dist = title
1084                           ? prev.title_min_distance_
1085                           : prev.min_distance_;
1086           refpoint_hanging = max (refpoint_hanging + padding,
1087                                   prev_refpoint_hanging - prev.refpoint_extent_[DOWN]
1088                                   + cur.refpoint_extent_[UP] + min_dist);
1089         }
1090
1091       Real hanging_begin = refpoint_hanging - shape.begin_[DOWN];
1092       Real hanging_rest = refpoint_hanging - shape.rest_[DOWN];
1093       Real hanging = max (hanging_begin, hanging_rest);
1094       cur.tallness_ = hanging - prev_hanging;
1095       prev_hanging = hanging;
1096       prev_hanging_begin = hanging_begin;
1097       prev_hanging_rest = hanging_rest;
1098       prev_refpoint_hanging = refpoint_hanging;
1099     }
1100 }
1101
1102 vsize
1103 Page_breaking::min_page_count (vsize configuration, vsize first_page_num)
1104 {
1105   vsize ret = 1;
1106   vsize page_starter = 0;
1107   Real cur_rod_height = 0;
1108   Real cur_spring_height = 0;
1109   Real cur_page_height = page_height (first_page_num, false);
1110   int line_count = 0;
1111
1112   cache_line_details (configuration);
1113
1114   if (cached_line_details_.size ())
1115     cur_page_height -= min_whitespace_at_top_of_page (cached_line_details_[0]);
1116
1117   for (vsize i = 0; i < cached_line_details_.size (); i++)
1118     {
1119       Line_details const &cur = cached_line_details_[i];
1120       Line_details const *const prev = (i > 0) ? &cached_line_details_[i - 1] : 0;
1121       Real ext_len;
1122       if (cur_rod_height > 0)
1123         ext_len = cur.tallness_;
1124       else
1125         ext_len = cur.full_height ();
1126
1127       Real spring_len = (i > 0) ? prev->spring_length (cur) : 0;
1128       Real next_rod_height = cur_rod_height + ext_len;
1129       Real next_spring_height = cur_spring_height + spring_len;
1130       Real next_height = next_rod_height + (ragged () ? next_spring_height : 0)
1131                          + min_whitespace_at_bottom_of_page (cur);
1132       int next_line_count = line_count + cur.compressed_nontitle_lines_count_;
1133
1134       if ((!too_few_lines (line_count) && (next_height > cur_page_height && cur_rod_height > 0))
1135           || too_many_lines (next_line_count)
1136           || (prev && scm_is_eq (prev->page_permission_, ly_symbol2scm ("force"))))
1137         {
1138           line_count = cur.compressed_nontitle_lines_count_;
1139           cur_rod_height = cur.full_height ();
1140           cur_spring_height = 0;
1141           page_starter = i;
1142
1143           cur_page_height = page_height (first_page_num + ret, false);
1144           cur_page_height -= min_whitespace_at_top_of_page (cur);
1145
1146           ret++;
1147         }
1148       else
1149         {
1150           cur_rod_height = next_rod_height;
1151           cur_spring_height = next_spring_height;
1152           line_count = next_line_count;
1153         }
1154     }
1155
1156   /* there are two potential problems with the last page (because we didn't know
1157      it was the last page until after we managed to fit all the systems to it):
1158      - we are ragged-last but the last page has a compressed spring
1159      - the value returned by page_height (num, true) is smaller than the
1160        value returned by page_height (num, false) and it causes the page not to
1161        fit.
1162
1163      In either case, we just need to add one more page. This is because the last
1164      line will always fit on the extra page and by adding one more page to the
1165      end, the previous page is no longer the last page, so our previous
1166      calculations that treated it as a non-last page were ok.
1167   */
1168
1169   if (is_last ())
1170     {
1171       cur_page_height = page_height (first_page_num + ret - 1, true);
1172       cur_page_height -= min_whitespace_at_top_of_page (cached_line_details_[page_starter]);
1173       cur_page_height -= min_whitespace_at_bottom_of_page (cached_line_details_.back ());
1174
1175       if (!too_few_lines (line_count - cached_line_details_.back ().compressed_nontitle_lines_count_)
1176           && cur_rod_height > cur_page_height
1177           /* don't increase the page count if the last page had only one system */
1178           && cur_rod_height > cached_line_details_.back ().full_height ())
1179         ret++;
1180       assert (ret <= cached_line_details_.size ());
1181     }
1182
1183   return ret;
1184 }
1185
1186 // If systems_per_page_ is positive, we don't really try to space on N pages;
1187 // we just put the requested number of systems on each page and penalize
1188 // if the result doesn't have N pages.
1189 Page_spacing_result
1190 Page_breaking::space_systems_on_n_pages (vsize configuration, vsize n, vsize first_page_num)
1191 {
1192   Page_spacing_result ret;
1193
1194   if (systems_per_page_ > 0)
1195     {
1196       Page_spacing_result ret = space_systems_with_fixed_number_per_page (configuration, first_page_num);
1197       ret.demerits_ += (ret.force_.size () == n) ? 0 : BAD_SPACING_PENALTY;
1198       return ret;
1199     }
1200
1201   cache_line_details (configuration);
1202   bool valid_n = (n >= min_page_count (configuration, first_page_num)
1203                   && n <= cached_line_details_.size ());
1204
1205   if (!valid_n)
1206     programming_error ("number of pages is out of bounds");
1207
1208   if (n == 1 && valid_n)
1209     ret = space_systems_on_1_page (cached_line_details_,
1210                                    page_height (first_page_num, is_last ()),
1211                                    ragged () || (is_last () && ragged_last ()));
1212   else if (n == 2 && valid_n)
1213     ret = space_systems_on_2_pages (configuration, first_page_num);
1214   else
1215     {
1216       Page_spacer ps (cached_line_details_, first_page_num, this);
1217       ret = ps.solve (n);
1218     }
1219
1220   return finalize_spacing_result (configuration, ret);
1221 }
1222
1223 Real
1224 Page_breaking::blank_page_penalty () const
1225 {
1226   SCM penalty_sym;
1227
1228   if (is_last ())
1229     penalty_sym = ly_symbol2scm ("blank-last-page-penalty");
1230   else if (ends_score ())
1231     penalty_sym = ly_symbol2scm ("blank-after-score-page-penalty");
1232   else
1233     penalty_sym = ly_symbol2scm ("blank-page-penalty");
1234
1235   Break_position const &pos = breaks_[current_end_breakpoint_];
1236   if (Paper_score *ps = system_specs_[pos.system_spec_index_].pscore_)
1237     return robust_scm2double (ps->layout ()->lookup_variable (penalty_sym), 0.0);
1238
1239   return robust_scm2double (book_->paper_->lookup_variable (penalty_sym), 0.0);
1240 }
1241
1242 // If systems_per_page_ is positive, we don't really try to space on N
1243 // or N+1 pages; see the comment to space_systems_on_n_pages.
1244 Page_spacing_result
1245 Page_breaking::space_systems_on_n_or_one_more_pages (vsize configuration, vsize n, vsize first_page_num,
1246                                                      Real penalty_for_fewer_pages)
1247 {
1248   Page_spacing_result n_res;
1249   Page_spacing_result m_res;
1250
1251   if (systems_per_page_ > 0)
1252     {
1253       Page_spacing_result ret = space_systems_with_fixed_number_per_page (configuration, first_page_num);
1254       ret.demerits_ += (ret.force_.size () == n || ret.force_.size () == (n - 1)) ? 0 : BAD_SPACING_PENALTY;
1255       return ret;
1256     }
1257
1258   cache_line_details (configuration);
1259   vsize min_p_count = min_page_count (configuration, first_page_num);
1260   bool valid_n = n >= min_p_count || n <= cached_line_details_.size ();
1261
1262   if (!valid_n)
1263     programming_error ("both page counts are out of bounds");
1264
1265   if (n == 1 && valid_n)
1266     {
1267       bool rag = ragged () || (is_last () && ragged_last ());
1268       Real height = page_height (first_page_num, is_last ());
1269
1270       if (1 >= min_p_count)
1271         n_res = space_systems_on_1_page (cached_line_details_, height, rag);
1272       if (1 < cached_line_details_.size ())
1273         m_res = space_systems_on_2_pages (configuration, first_page_num);
1274     }
1275   else
1276     {
1277       Page_spacer ps (cached_line_details_, first_page_num, this);
1278
1279       if (n >= min_p_count || !valid_n)
1280         n_res = ps.solve (n);
1281       if (n < cached_line_details_.size () || !valid_n)
1282         m_res = ps.solve (n + 1);
1283     }
1284
1285   m_res = finalize_spacing_result (configuration, m_res);
1286   n_res = finalize_spacing_result (configuration, n_res);
1287
1288   Real page_spacing_weight = robust_scm2double (book_->paper_->c_variable ("page-spacing-weight"), 10);
1289   n_res.demerits_ += penalty_for_fewer_pages * page_spacing_weight;
1290
1291   if (n_res.force_.size ())
1292     n_res.force_.back () += penalty_for_fewer_pages;
1293
1294   return (m_res.demerits_ < n_res.demerits_) ? m_res : n_res;
1295 }
1296
1297 Page_spacing_result
1298 Page_breaking::space_systems_on_best_pages (vsize configuration, vsize first_page_num)
1299 {
1300   if (systems_per_page_ > 0)
1301     return space_systems_with_fixed_number_per_page (configuration, first_page_num);
1302
1303   cache_line_details (configuration);
1304   Page_spacer ps (cached_line_details_, first_page_num, this);
1305
1306   return finalize_spacing_result (configuration, ps.solve ());
1307 }
1308
1309 Page_spacing_result
1310 Page_breaking::space_systems_with_fixed_number_per_page (vsize configuration,
1311                                                          vsize first_page_num)
1312 {
1313   Page_spacing_result res;
1314   Page_spacing space (page_height (first_page_num, false), this);
1315   vsize line = 0;
1316   vsize page = 0;
1317   vsize page_first_line = 0;
1318
1319   cache_line_details (configuration);
1320   while (line < cached_line_details_.size ())
1321     {
1322       page++;
1323       space.clear ();
1324       space.resize (page_height (first_page_num + page, false));
1325
1326       int system_count_on_this_page = 0;
1327       while (system_count_on_this_page < systems_per_page_
1328              && line < cached_line_details_.size ())
1329         {
1330           Line_details const &cur_line = cached_line_details_[line];
1331           space.append_system (cur_line);
1332           system_count_on_this_page += cur_line.compressed_nontitle_lines_count_;
1333           line++;
1334
1335           if (scm_is_eq (cur_line.page_permission_, ly_symbol2scm ("force")))
1336             break;
1337         }
1338
1339       res.systems_per_page_.push_back (line - page_first_line);
1340
1341       res.force_.push_back (space.force_);
1342       res.penalty_ += cached_line_details_[line - 1].page_penalty_;
1343       if (system_count_on_this_page != systems_per_page_)
1344         {
1345           res.penalty_ += abs (system_count_on_this_page - systems_per_page_) * TERRIBLE_SPACING_PENALTY;
1346           res.system_count_status_ |= ((system_count_on_this_page < systems_per_page_))
1347                                       ? SYSTEM_COUNT_TOO_FEW : SYSTEM_COUNT_TOO_MANY;
1348         }
1349
1350       page_first_line = line;
1351     }
1352
1353   /* Recalculate forces for the last page because we know now that is
1354      really the last page. */
1355   space.resize (page_height (first_page_num + page, true));
1356   res.force_.back () = space.force_;
1357   return finalize_spacing_result (configuration, res);
1358 }
1359
1360 Page_spacing_result
1361 Page_breaking::pack_systems_on_least_pages (vsize configuration, vsize first_page_num)
1362 {
1363   // TODO: add support for min/max-systems-per-page.
1364   Page_spacing_result res;
1365   vsize page = 0;
1366   vsize page_first_line = 0;
1367   Page_spacing space (page_height (first_page_num, false), this);
1368
1369   cache_line_details (configuration);
1370   for (vsize line = 0; line < cached_line_details_.size (); line++)
1371     {
1372       Real prev_force = space.force_;
1373       space.append_system (cached_line_details_[line]);
1374       if ((line > page_first_line)
1375           && (isinf (space.force_)
1376               || ((line > 0)
1377                   && scm_is_eq (cached_line_details_[line - 1].page_permission_,
1378                                 ly_symbol2scm ("force")))))
1379         {
1380           res.systems_per_page_.push_back (line - page_first_line);
1381           res.force_.push_back (prev_force);
1382           res.penalty_ += cached_line_details_[line - 1].page_penalty_;
1383           page++;
1384           space.resize (page_height (first_page_num + page, false));
1385           space.clear ();
1386           space.append_system (cached_line_details_[line]);
1387           page_first_line = line;
1388         }
1389
1390       if (line == cached_line_details_.size () - 1)
1391         {
1392           /* This is the last line */
1393           /* When the last page height was computed, we did not know yet that it
1394            * was the last one. If the systems put on it don't fit anymore, the last
1395            * system is moved to a new page */
1396           space.resize (page_height (first_page_num + page, true));
1397           if ((line > page_first_line) && (isinf (space.force_)))
1398             {
1399               res.systems_per_page_.push_back (line - page_first_line);
1400               res.force_.push_back (prev_force);
1401               /* the last page containing the last line */
1402               space.resize (page_height (first_page_num + page + 1, true));
1403               space.clear ();
1404               space.append_system (cached_line_details_[line]);
1405               res.systems_per_page_.push_back (1);
1406               res.force_.push_back (space.force_);
1407               res.penalty_ += cached_line_details_[line - 1].page_penalty_;
1408               res.penalty_ += cached_line_details_[line].page_penalty_;
1409             }
1410           else
1411             {
1412               res.systems_per_page_.push_back (line + 1 - page_first_line);
1413               res.force_.push_back (space.force_);
1414               res.penalty_ += cached_line_details_[line].page_penalty_;
1415             }
1416         }
1417     }
1418   return finalize_spacing_result (configuration, res);
1419 }
1420
1421 /* Calculate demerits and fix res.systems_per_page_ so that
1422    it refers to the original line numbers, not the ones given by compress_lines (). */
1423 Page_spacing_result
1424 Page_breaking::finalize_spacing_result (vsize configuration, Page_spacing_result res)
1425 {
1426   if (res.force_.empty ())
1427     return res;
1428
1429   cache_line_details (configuration);
1430   res.systems_per_page_ = uncompress_solution (res.systems_per_page_, cached_line_details_);
1431
1432   Real line_force = 0;
1433   Real line_penalty = 0;
1434   Real page_demerits = res.penalty_;
1435   Real page_weighting = robust_scm2double (book_->paper_->c_variable ("page-spacing-weight"), 10);
1436
1437   for (vsize i = 0; i < uncompressed_line_details_.size (); i++)
1438     {
1439       line_force += uncompressed_line_details_[i].force_ * uncompressed_line_details_[i].force_;
1440       line_penalty += uncompressed_line_details_[i].break_penalty_;
1441     }
1442
1443   for (vsize i = ragged () ? res.force_.size () - 1 : 0;
1444        i < res.force_.size () - (is_last () && ragged_last ());
1445        i++)
1446     {
1447       Real f = res.force_[i];
1448
1449       page_demerits += min (f * f, BAD_SPACING_PENALTY);
1450     }
1451
1452   /* for a while we tried averaging page and line forces across pages instead
1453      of summing them, but it caused a problem: if there is a single page
1454      with a very bad page force (for example because of a forced page break),
1455      the page breaker will put in a _lot_ of pages so that the bad force
1456      becomes averaged out over many pages. */
1457   res.demerits_ = line_force + line_penalty + page_demerits * page_weighting;
1458   return res;
1459
1460 }
1461
1462 /* the cases for page_count = 1 or 2 can be done in O (n) time. Since they
1463    are by far the most common cases, we have special functions for them.
1464
1465    space_systems_on_1_page has a different calling convention than most of the
1466    space_systems functions. This is because space_systems_on_1_page is (unlike
1467    the other space_systems functions) sometimes called on subsets of a full
1468    configuration. */
1469 Page_spacing_result
1470 Page_breaking::space_systems_on_1_page (vector<Line_details> const &lines, Real page_height, bool ragged)
1471 {
1472   Page_spacing space (page_height, this);
1473   Page_spacing_result ret;
1474   int line_count = 0;
1475
1476   for (vsize i = 0; i < lines.size (); i++)
1477     {
1478       space.append_system (lines[i]);
1479       line_count += lines[i].compressed_nontitle_lines_count_;
1480     }
1481
1482   ret.systems_per_page_.push_back (lines.size ());
1483   ret.force_.push_back (ragged ? min (space.force_, 0.0) : space.force_);
1484   ret.penalty_ = line_count_penalty (line_count) + lines.back ().page_penalty_ + lines.back ().turn_penalty_;
1485   ret.system_count_status_ |= line_count_status (line_count);
1486
1487   /* don't do finalize_spacing_result () because we are only an internal function */
1488   return ret;
1489 }
1490
1491 Page_spacing_result
1492 Page_breaking::space_systems_on_2_pages (vsize configuration, vsize first_page_num)
1493 {
1494   Real page1_height = page_height (first_page_num, false);
1495   Real page2_height = page_height (first_page_num + 1, is_last ());
1496   bool ragged1 = ragged ();
1497   bool ragged2 = ragged () || (is_last () && ragged_last ());
1498
1499   /* if there is a forced break, this reduces to 2 1-page problems */
1500   cache_line_details (configuration);
1501   for (vsize i = 0; i + 1 < cached_line_details_.size (); i++)
1502     if (scm_is_eq (cached_line_details_[i].page_permission_,
1503         ly_symbol2scm ("force")))
1504       {
1505         vector<Line_details> lines1 (cached_line_details_.begin (), cached_line_details_.begin () + i + 1);
1506         vector<Line_details> lines2 (cached_line_details_.begin () + i + 1, cached_line_details_.end ());
1507         Page_spacing_result p1 = space_systems_on_1_page (lines1, page1_height, ragged1);
1508         Page_spacing_result p2 = space_systems_on_1_page (lines2, page2_height, ragged2);
1509
1510         p1.systems_per_page_.push_back (p2.systems_per_page_[0]);
1511         p1.force_.push_back (p2.force_[0]);
1512         p1.penalty_ += p2.penalty_ - cached_line_details_[i].turn_penalty_;
1513         p1.system_count_status_ |= p2.system_count_status_;
1514         return p1;
1515       }
1516
1517   vector<Real> page1_force;
1518   vector<Real> page2_force;
1519
1520   // page1_penalty and page2_penalty store the penalties based
1521   // on min-systems-per-page and max-systems-per-page.
1522   vector<Real> page1_penalty;
1523   vector<Real> page2_penalty;
1524
1525   // page1_status and page2_status keep track of whether the min-systems-per-page
1526   // and max-systems-per-page constraints are satisfied.
1527   vector<int> page1_status;
1528   vector<int> page2_status;
1529
1530   Page_spacing page1 (page1_height, this);
1531   Page_spacing page2 (page2_height, this);
1532   int page1_line_count = 0;
1533   int page2_line_count = 0;
1534
1535   page1_force.resize (cached_line_details_.size () - 1, infinity_f);
1536   page2_force.resize (cached_line_details_.size () - 1, infinity_f);
1537   page1_penalty.resize (cached_line_details_.size () - 1, infinity_f);
1538   page2_penalty.resize (cached_line_details_.size () - 1, infinity_f);
1539   page1_status.resize (cached_line_details_.size () - 1, 0);
1540   page2_status.resize (cached_line_details_.size () - 1, 0);
1541
1542   /* find the page 1 and page 2 forces for each page-breaking position */
1543   for (vsize i = 0; i < page1_force.size (); i++)
1544     {
1545       page1.append_system (cached_line_details_[i]);
1546       page2.prepend_system (cached_line_details_[cached_line_details_.size () - 1 - i]);
1547       page1_line_count += cached_line_details_[i].compressed_nontitle_lines_count_;
1548       page2_line_count += cached_line_details_[cached_line_details_.size () - 1 - i].compressed_nontitle_lines_count_;
1549
1550       page1_force[i] = (ragged1 && page1.force_ < 0 && i > 0) ? infinity_f : page1.force_;
1551       page1_penalty[i] = line_count_penalty (page1_line_count);
1552       page1_status[i] = line_count_status (page1_line_count);
1553
1554       if (ragged1)
1555         page2_force[page2_force.size () - 1 - i]
1556           = (page2.force_ < 0 && i + 1 < page1_force.size ()) ? infinity_f : 0;
1557       else if (ragged2 && page2.force_ > 0)
1558         page2_force[page2_force.size () - 1 - i] = 0.0;
1559       else
1560         page2_force[page2_force.size () - 1 - i] = page2.force_;
1561       page2_penalty[page2_penalty.size () - 1 - i] = line_count_penalty (page2_line_count);
1562       page2_status[page2_penalty.size () - 1 - i] = line_count_status (page2_line_count);
1563     }
1564
1565   /* find the position that minimises the sum of the page forces */
1566   vsize best_sys_count = 1;
1567   Real best_demerits = infinity_f;
1568   for (vsize i = 0; i < page1_force.size (); i++)
1569     {
1570       Real f = page1_force[i] * page1_force[i] + page2_force[i] * page2_force[i];
1571
1572       // NOTE: we treat max-systems-per-page and min-systems-per-page as soft
1573       // constraints. That is, we penalize harshly when they don't happen
1574       // but we don't completely reject.
1575       Real dem = f
1576                  + page1_penalty[i] + page2_penalty[i]
1577                  + cached_line_details_[i + 1].page_penalty_
1578                  + cached_line_details_.back ().page_penalty_ + cached_line_details_.back ().turn_penalty_;
1579       if (dem < best_demerits)
1580         {
1581           best_demerits = dem;
1582           best_sys_count = i + 1;
1583         }
1584     }
1585
1586   Page_spacing_result ret;
1587   ret.systems_per_page_.push_back (best_sys_count);
1588   ret.systems_per_page_.push_back (cached_line_details_.size () - best_sys_count);
1589   ret.force_.push_back (page1_force[best_sys_count - 1]);
1590   ret.force_.push_back (page2_force[best_sys_count - 1]);
1591   ret.system_count_status_ = page1_status[best_sys_count - 1] | page2_status[best_sys_count - 1];
1592   ret.penalty_ = cached_line_details_[best_sys_count - 1].page_penalty_
1593                  + cached_line_details_.back ().page_penalty_
1594                  + cached_line_details_.back ().turn_penalty_
1595                  + page1_penalty[best_sys_count - 1] + page2_penalty[best_sys_count - 1];
1596
1597   /* don't do finalize_spacing_result () because we are only an internal function */
1598   return ret;
1599 }
1600
1601 bool
1602 Page_breaking::all_lines_stretched (vsize configuration)
1603 {
1604   cache_line_details (configuration);
1605   for (vsize i = 0; i < cached_line_details_.size (); i++)
1606     if (cached_line_details_[i].force_ < 0)
1607       return false;
1608
1609   return true;
1610 }
1611
1612 Page_breaking::Line_division
1613 Page_breaking::current_configuration (vsize configuration_index) const
1614 {
1615   return current_configurations_[configuration_index];
1616 }
1617
1618 bool
1619 Page_breaking::is_last () const
1620 {
1621   return current_end_breakpoint_ == last_break_position ();
1622 }
1623
1624 bool
1625 Page_breaking::ends_score () const
1626 {
1627   return breaks_[current_end_breakpoint_].score_ender_;
1628 }
1629
1630 vsize
1631 Page_breaking::last_break_position () const
1632 {
1633   return breaks_.size () - 1;
1634 }
1635
1636 // This gives the minimum distance between the top of the
1637 // printable area (ie. the bottom of the top-margin) and
1638 // the extent box of the topmost system.
1639 Real
1640 Page_breaking::min_whitespace_at_top_of_page (Line_details const &line) const
1641 {
1642   SCM first_system_spacing = book_->paper_->c_variable ("top-system-spacing");
1643   if (line.title_)
1644     first_system_spacing = book_->paper_->c_variable ("top-markup-spacing");
1645
1646   Real min_distance = -infinity_f;
1647   Real padding = 0;
1648
1649   Page_layout_problem::read_spacing_spec (first_system_spacing,
1650                                           &min_distance,
1651                                           ly_symbol2scm ("minimum-distance"));
1652   Page_layout_problem::read_spacing_spec (first_system_spacing,
1653                                           &padding,
1654                                           ly_symbol2scm ("padding"));
1655
1656   // FIXME: take into account the height of the header
1657   Real translate = max (line.shape_.begin_[UP], line.shape_.rest_[UP]);
1658   return max (0.0, max (padding, min_distance - translate));
1659 }
1660
1661 Real
1662 Page_breaking::min_whitespace_at_bottom_of_page (Line_details const &line) const
1663 {
1664   SCM last_system_spacing = book_->paper_->c_variable ("last-bottom-spacing");
1665   Real min_distance = -infinity_f;
1666   Real padding = 0;
1667
1668   Page_layout_problem::read_spacing_spec (last_system_spacing,
1669                                           &min_distance,
1670                                           ly_symbol2scm ("minimum-distance"));
1671   Page_layout_problem::read_spacing_spec (last_system_spacing,
1672                                           &padding,
1673                                           ly_symbol2scm ("padding"));
1674
1675   // FIXME: take into account the height of the footer
1676   Real translate = min (line.shape_.begin_[DOWN], line.shape_.rest_[DOWN]);
1677   return max (0.0, max (padding, min_distance + translate));
1678 }
1679
1680 int
1681 Page_breaking::orphan_penalty () const
1682 {
1683   return orphan_penalty_;
1684 }