-/* for each forbidden page break, merge the systems around it into one system. */
-static vector<Line_details>
-compress_lines (const vector<Line_details> &orig)
-{
- vector<Line_details> ret;
-
- for (vsize i = 0; i < orig.size (); i++)
- {
- if (ret.size () && ret.back ().page_permission_ == SCM_EOL)
- {
- Line_details const &old = ret.back ();
- Line_details compressed = orig[i];
- compressed.extent_[DOWN] = old.extent_[DOWN];
- compressed.extent_[UP] = old.extent_[UP] + orig[i].extent_.length () + old.padding_;
- compressed.space_ += old.space_;
- compressed.inverse_hooke_ += old.inverse_hooke_;
-
- /* we don't need the force_ field for the vertical spacing,
- so we use force_ = n to signal that the line was compressed,
- reducing the number of lines by n (and force_ = 0 otherwise).
- This makes uncompression much easier. */
- compressed.force_ = old.force_ + 1;
- ret.back () = compressed;
- }
- else
- {
- ret.push_back (orig[i]);
- ret.back ().force_ = 0;
- }
- }
- return ret;
-}
-
-/* translate the number of systems-per-page into something meaningful for
- the uncompressed lines.
-*/
-static vector<vsize>
-uncompress_solution (vector<vsize> const &systems_per_page,
- vector<Line_details> const &compressed)
-{
- vector<vsize> ret;
- vsize start_sys = 0;
-
- for (vsize i = 0; i < systems_per_page.size (); i++)
- {
- int compressed_count = 0;
- for (vsize j = start_sys; j < start_sys + systems_per_page[i]; j++)
- compressed_count += (int)compressed[j].force_;
-
- ret.push_back (systems_per_page[i] + compressed_count);
- start_sys += systems_per_page[i];
- }
- return ret;
-}
-
-/* the cases for page_count = 1 or 2 can be done in O (n) time. Since they
- are by far the most common cases, we have special functions for them */
-static Spacing_result
-space_systems_on_1_page (vector<Line_details> const &lines, Real page_height, bool ragged)
-{
- Page_spacing space (page_height);
- Spacing_result ret;
-
- for (vsize i = 0; i < lines.size (); i++)
- space.append_system (lines[i]);
-
- ret.systems_per_page_.push_back (lines.size ());
- ret.force_.push_back (ragged ? min (space.force_, 0.0) : space.force_);
- ret.penalty_ = lines.back ().page_penalty_ + lines.back ().turn_penalty_;
- ret.demerits_ = ret.force_.back () * ret.force_.back () + ret.penalty_;
-
- return ret;
-}
-
-static Spacing_result
-space_systems_on_2_pages (vector<Line_details> const &lines,
- Real page_height,
- bool ragged,
- bool ragged_last)
-{
- /* if there is a forced break, this reduces to 2 1-page problems */
- for (vsize i = 0; i + 1 < lines.size (); i++)
- if (lines[i].page_permission_ == ly_symbol2scm ("force"))
- {
- vector<Line_details> lines1 (lines.begin (), lines.begin () + i + 1);
- vector<Line_details> lines2 (lines.begin () + i + 1, lines.end ());
- Spacing_result p1 = space_systems_on_1_page (lines1, page_height, ragged);
- Spacing_result p2 = space_systems_on_1_page (lines2, page_height, ragged || ragged_last);
-
- p1.systems_per_page_.push_back (p2.systems_per_page_[0]);
- p1.force_.push_back (p2.force_[0]);
- p1.penalty_ += p2.penalty_ - lines[i].turn_penalty_;
- p1.demerits_ += p2.demerits_ - lines[i].turn_penalty_;
- return p1;
- }
-
- vector<Real> page1_force;
- vector<Real> page2_force;
- Page_spacing page1 (page_height);
- Page_spacing page2 (page_height);
-
- page1_force.resize (lines.size () - 1, infinity_f);
- page2_force.resize (lines.size () - 1, infinity_f);
-
- for (vsize i = 0; i < page1_force.size (); i++)
- {
- page1.append_system (lines[i]);
- page2.prepend_system (lines[lines.size () - 1 - i]);
- page1_force[i] = (ragged && page1.force_ < 0 && i > 0) ? infinity_f : page1.force_;
-
- if (ragged || ragged_last)
- page2_force[page2_force.size () - 1 - i] =
- (page2.force_ < 0 && i + 1 < page1_force.size ()) ? infinity_f : 0;
- else
- page2_force[page2_force.size () - 1 - i] = page2.force_;
- }
-
- vsize best_sys_count = 1;
- Real best_demerits = infinity_f;
- for (vsize i = 0; i < page1_force.size (); i++)
- {
- Real dem = page1_force[i] * page1_force[i]
- + page2_force[i] * page2_force[i]
- + lines[i+1].page_penalty_
- + lines.back ().page_penalty_ + lines.back ().turn_penalty_;
- if (dem < best_demerits)
- {
- best_demerits = dem;
- best_sys_count = i+1;
- }
- }
-
- Spacing_result ret;
- ret.systems_per_page_.push_back (best_sys_count);
- ret.systems_per_page_.push_back (lines.size () - best_sys_count);
- ret.force_.push_back (page1_force[best_sys_count-1]);
- ret.force_.push_back (page2_force[best_sys_count-1]);
- ret.penalty_ = lines[best_sys_count-1].page_penalty_
- + lines.back ().page_penalty_
- + lines.back ().turn_penalty_;
- ret.demerits_ = best_demerits;