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