- Page_spacing_result in separate file.
- declare variables at init.
vector<Column_x_positions>
Constrained_breaking::best_solution (vsize start, vsize end)
{
- vsize min_systems = min_system_count (start, end);
+ vsize min_systems = min_system_count (start, end);
vsize max_systems = max_system_count (start, end);
Real best_demerits = infinity_f;
vector<Column_x_positions> best_so_far;
class Object_key_undumper;
class Open_type_font;
class Output_property;
+class Page_breaking;
class Pango_font;
class Paper_book;
class Paper_column;
struct Break_position
{
+ /*
+ index in system_spec_index_, if VPOS start of book.
+ */
vsize system_spec_index_;
/* if system_spec_index_ is a score, then we start at the score_brk_'th possible
vsize current_configuration_count () const;
Line_division current_configuration (vsize configuration_index) const;
- Spacing_result space_systems_on_n_pages (vsize configuration_index,
+ Page_spacing_result space_systems_on_n_pages (vsize configuration_index,
vsize n, vsize first_page_num);
- Spacing_result space_systems_on_n_or_one_more_pages (vsize configuration_index, vsize n,
+ Page_spacing_result space_systems_on_n_or_one_more_pages (vsize configuration_index, vsize n,
vsize first_page_num);
- Spacing_result space_systems_on_best_pages (vsize configuration_index,
+ Page_spacing_result space_systems_on_best_pages (vsize configuration_index,
vsize first_page_num);
vsize min_page_count (vsize configuration_index, vsize first_page_num);
bool all_lines_stretched (vsize configuration_index);
Line_division *cur);
vector<Line_details> line_details (vsize start, vsize end, Line_division const &div);
- Spacing_result space_systems_on_1_page (vector<Line_details> const &lines, Real page_height, bool ragged);
- Spacing_result space_systems_on_2_pages (vsize configuration_index, vsize first_page_num);
- Spacing_result finalize_spacing_result (vsize configuration_index, Spacing_result);
+ Page_spacing_result space_systems_on_1_page (vector<Line_details> const &lines, Real page_height, bool ragged);
+ Page_spacing_result space_systems_on_2_pages (vsize configuration_index, vsize first_page_num);
+ Page_spacing_result finalize_spacing_result (vsize configuration_index, Page_spacing_result);
void create_system_list ();
void find_chunks_and_breaks (Break_predicate);
};
--- /dev/null
+/*
+ page-spacing-result.hh -- declare Page_spacing_result
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2007 Han-Wen Nienhuys <hanwen@lilypond.org>
+
+*/
+
+#ifndef PAGE_SPACING_RESULT_HH
+#define PAGE_SPACING_RESULT_HH
+
+#include "std-vector.hh"
+#include "lily-proto.hh"
+
+struct Page_spacing_result {
+ vector<vsize> systems_per_page_;
+ vector<Real> force_;
+ Real penalty_;
+ Real demerits_;
+
+ vsize system_count () const;
+ Page_spacing_result ();
+};
+
+#endif /* PAGE_SPACING_RESULT_HH */
#define PAGE_SPACING_HH
#include "constrained-breaking.hh"
+#include "page-spacing-result.hh"
-struct Spacing_result {
- vector<vsize> systems_per_page_;
- vector<Real> force_;
- Real penalty_;
- Real demerits_;
-
- Spacing_result ()
- {
- penalty_ = 0;
- demerits_ = infinity_f;
- }
-};
/* for page_count > 2, we use a dynamic algorithm similar to
constrained-breaking -- we have a class that stores the intermediate
calculations so they can be reused for querying different page counts.
*/
-
-class Page_breaking;
-
class Page_spacer
{
public:
Page_spacer (vector<Line_details> const &lines, vsize first_page_num, Page_breaking const*);
- Spacing_result solve (vsize page_count);
+ Page_spacing_result solve (vsize page_count);
private:
struct Page_spacing_node
Optimal_page_breaking::solve ()
{
vsize end = last_break_position ();
- vsize min_sys_count = 0;
- vsize ideal_sys_count = 0;
vsize max_sys_count = max_system_count (0, end);
- vsize page_count = 0;
-
- Line_division ideal_line_division;
- Line_division best_division;
- Line_division bound;
vsize first_page_num = robust_scm2int (book_->paper_->c_variable ("first-page-number"), 1);
/* find out the ideal number of pages */
message (_ ("Finding the ideal number of pages..."));
set_to_ideal_line_configuration (0, end);
- ideal_line_division = current_configuration (0);
-
- Spacing_result best = space_systems_on_best_pages (0, first_page_num);
- page_count = best.systems_per_page_.size ();
- best_division = ideal_line_division;
-
- for (vsize i = 0; i < page_count; i++)
- ideal_sys_count += best.systems_per_page_[i];
+
+ Line_division ideal_line_division = current_configuration (0);
+ Page_spacing_result best = space_systems_on_best_pages (0, first_page_num);
+ vsize page_count = best.systems_per_page_.size ();
+ Line_division best_division = ideal_line_division;
- min_sys_count = ideal_sys_count - best.systems_per_page_.back ();
+ vsize ideal_sys_count = best.system_count ();
+ vsize min_sys_count = ideal_sys_count - best.systems_per_page_.back ();
+
if (page_count > 1)
min_sys_count -= best.systems_per_page_[page_count - 2];
message (_f ("Fitting music on %d or %d pages...", (int)page_count-1, (int)page_count));
/* try a smaller number of systems than the ideal number for line breaking */
- bound = ideal_line_division;
+ Line_division bound = ideal_line_division;
for (vsize sys_count = ideal_sys_count; --sys_count >= min_sys_count;)
{
- Spacing_result best_for_this_sys_count;
+ Page_spacing_result best_for_this_sys_count;
set_current_breakpoints (0, end, sys_count, Line_division (), bound);
for (vsize i = 0; i < current_configuration_count (); i++)
{
vsize min_p_count = min_page_count (i, first_page_num);
- Spacing_result cur;
+ Page_spacing_result cur;
if (min_p_count > page_count)
continue;
for (vsize i = 0; i < current_configuration_count (); i++)
{
vsize min_p_count = min_page_count (i, first_page_num);
- Spacing_result cur;
+ Page_spacing_result cur;
if (min_p_count > page_count)
continue;
return 0;
if (system_specs_[sys].pscore_ && !break_pos.score_ender_)
return sys; /* the score overflows the previous page */
- return sys + 1; /* this page starts with a new sys */
+ return sys + 1; /* this page starts with a new System_spec */
}
Page_breaking::Page_breaking (Paper_book *pb, Break_predicate is_break)
{
if (system_specs_[i].pscore_)
{
- vector<Grob*> cols = system_specs_[i].pscore_->root_system ()->used_columns ();
+ vector<Grob*> cols
+ = system_specs_[i].pscore_->root_system ()->used_columns ();
vector<vsize> line_breaker_columns;
line_breaker_columns.push_back (0);
for (vsize j = 1; j < cols.size (); j++)
{
- bool last = j == cols.size () - 1;
+ bool last = (j == cols.size () - 1);
bool break_point = is_break (cols[j]);
bool chunk_end = cols[j]->get_property ("page-break-permission") == force_sym;
Break_position cur_pos = Break_position (i,
breaks_.push_back (Break_position (i));
chunks_.push_back (Break_position (i));
+
+ /* FIXME: shouldn't we push a Null_breaker or similar dummy
+ class? --hwn */
line_breaking_.push_back (Constrained_breaking (NULL));
}
}
Break_position start = breaks_[start_index];
Break_position end = breaks_[end_index];
- vsize i;
- for (i = 0; i < chunks_.size () && chunks_[i] <= start; i++)
+ vsize i = 0;
+ for (; i < chunks_.size () && chunks_[i] <= start; i++)
;
vector<Break_position> ret;
return ret;
}
-Spacing_result
+Page_spacing_result
Page_breaking::space_systems_on_n_pages (vsize configuration, vsize n, vsize first_page_num)
{
- Spacing_result ret;
+ Page_spacing_result ret;
assert (n >= min_page_count (configuration, first_page_num));
cache_line_details (configuration);
if (n > cached_line_details_.size ())
- return Spacing_result ();
+ return Page_spacing_result ();
if (n == 1)
ret = space_systems_on_1_page (cached_line_details_,
page_height (first_page_num, is_last ()),
return robust_scm2double (book_->paper_->lookup_variable (penalty_sym), 0.0);
}
-Spacing_result
+Page_spacing_result
Page_breaking::space_systems_on_n_or_one_more_pages (vsize configuration, vsize n, vsize first_page_num)
{
- Spacing_result n_res;
- Spacing_result m_res;
+ Page_spacing_result n_res;
+ Page_spacing_result m_res;
if (n <= 2)
{
return n_res;
}
-Spacing_result
+Page_spacing_result
Page_breaking::space_systems_on_best_pages (vsize configuration, vsize first_page_num)
{
vsize min_p_count = min_page_count (configuration, first_page_num);
cache_line_details (configuration);
Page_spacer ps (cached_line_details_, first_page_num, this);
- Spacing_result best = ps.solve (min_p_count);
+ Page_spacing_result best = ps.solve (min_p_count);
best.force_.back () += (min_p_count % 2) ? odd_pages_penalty : 0;
best.demerits_ += (min_p_count % 2) ? odd_pages_penalty : 0;
for (vsize i = min_p_count+1; i <= cached_line_details_.size (); i++)
{
- Spacing_result cur = ps.solve (i);
+ Page_spacing_result cur = ps.solve (i);
cur.demerits_ += (i % 2) ? odd_pages_penalty : 0;
if (cur.demerits_ < best.demerits_)
best = cur;
/* Calculate demerits and fix res.systems_per_page_ so that
it refers to the original line numbers, not the ones given by compress_lines (). */
-Spacing_result
-Page_breaking::finalize_spacing_result (vsize configuration, Spacing_result res)
+Page_spacing_result
+Page_breaking::finalize_spacing_result (vsize configuration, Page_spacing_result res)
{
cache_line_details (configuration);
res.systems_per_page_ = uncompress_solution (res.systems_per_page_, cached_line_details_);
space_systems functions. This is because space_systems_on_1_page is (unlike
the other space_systems functions) sometimes called on subsets of a full
configuration. */
-Spacing_result
+Page_spacing_result
Page_breaking::space_systems_on_1_page (vector<Line_details> const &lines, Real page_height, bool ragged)
{
Page_spacing space (page_height);
- Spacing_result ret;
+ Page_spacing_result ret;
for (vsize i = 0; i < lines.size (); i++)
space.append_system (lines[i]);
return ret;
}
-Spacing_result
+Page_spacing_result
Page_breaking::space_systems_on_2_pages (vsize configuration, vsize first_page_num)
{
Real page1_height = page_height (first_page_num, false);
{
vector<Line_details> lines1 (cached_line_details_.begin (), cached_line_details_.begin () + i + 1);
vector<Line_details> lines2 (cached_line_details_.begin () + i + 1, cached_line_details_.end ());
- Spacing_result p1 = space_systems_on_1_page (lines1, page1_height, ragged1);
- Spacing_result p2 = space_systems_on_1_page (lines2, page2_height, ragged2);
+ Page_spacing_result p1 = space_systems_on_1_page (lines1, page1_height, ragged1);
+ Page_spacing_result p2 = space_systems_on_1_page (lines2, page2_height, ragged2);
p1.systems_per_page_.push_back (p2.systems_per_page_[0]);
p1.force_.push_back (p2.force_[0]);
}
}
- Spacing_result ret;
+ Page_spacing_result ret;
ret.systems_per_page_.push_back (best_sys_count);
ret.systems_per_page_.push_back (cached_line_details_.size () - best_sys_count);
ret.force_.push_back (page1_force[best_sys_count-1]);
--- /dev/null
+/*
+ page-spacing-result.cc -- implement Page_spacing_result
+
+ source file of the GNU LilyPond music typesetter
+
+ (c) 2007 Han-Wen Nienhuys <hanwen@lilypond.org>
+
+*/
+
+#include "page-spacing-result.hh"
+
+Page_spacing_result::Page_spacing_result ()
+{
+ penalty_ = 0;
+ demerits_ = infinity_f;
+}
+
+vsize
+Page_spacing_result::system_count () const
+{
+ vsize total = 0;
+ for (vsize i = 0; i < systems_per_page_.size(); i++)
+ total += systems_per_page_[i];
+
+ return total;
+}
ragged_last_ = breaker->is_last () && breaker->ragged_last ();
}
-Spacing_result
+Page_spacing_result
Page_spacer::solve (vsize page_count)
{
if (page_count > max_page_count_)
resize (page_count);
- Spacing_result ret;
+ Page_spacing_result ret;
ret.force_.resize (page_count);
ret.systems_per_page_.resize (page_count);
system = i;
}
else
- return Spacing_result (); /* couldn't salvage it -- probably going to crash */
+ return Page_spacing_result (); /* couldn't salvage it -- probably going to crash */
}
ret.penalty_ = state_.at (system, page_count-1).penalty_
min_p_count has that evenness. (For example, if PAGE-NUMBER is even and
min_p_count is even, we don't even consider the blank page option). */
- Spacing_result result;
+ Page_spacing_result result;
if (start == 0 && auto_first)
{
if (min_p_count % 2)