Page_layout_problem (Paper_book *, SCM page, SCM systems);
SCM solution (bool ragged);
+ SCM fixed_force_solution (Real force);
void set_header_height (Real);
void set_footer_height (Real);
+ Real force () const;
static bool read_spacing_spec (SCM spec, Real *dest, SCM sym);
static bool is_spaceable (Grob *g);
static SCM get_details (Grob *g);
void append_system (System *, Spring const &, Real indent, Real padding);
void append_prob (Prob *, Spring const &, Real padding);
- void solve_rod_spring_problem (bool ragged);
+ void solve_rod_spring_problem (bool ragged, Real fixed_force);
SCM find_system_offsets ();
void distribute_loose_lines (vector<Grob *> const &, vector<Real> const &, Real, Real);
vector<Spring> springs_;
vector<Element> elements_;
vector<Real> solution_;
+ Real force_;
Skyline bottom_skyline_;
Real page_height_;
Real header_height_;
Real configuration_length (Real) const;
vector<Real> spring_positions () const;
+ void set_force (Real force);
Real force () const;
Real line_len () const;
Real force_penalty (bool ragged) const;
if (label_page_table == SCM_UNDEFINED)
label_page_table = SCM_EOL;
- // Build a list of (systems . configuration) pairs. Note that we lay out
+ // Build a list of (systems configuration . footnote-count) triples.
+ // Note that we lay out
// the staves and find the configurations before drawing anything. Some
// grobs (like tuplet brackets) look at their neighbours while drawing
// themselves. If this happens before the neighbouring staves have
// Align_interface::align_to_ideal_distances might be called).
SCM systems_configs_fncounts = SCM_EOL;
vsize footnote_count = 0;
+ Real last_page_force = 0;
for (vsize i = 0; i < lines_per_page.size (); i++)
{
int fn_lines = Page_layout_problem::get_footnote_count (lines);
Page_layout_problem::add_footnotes_to_lines (lines, reset_footnotes_on_new_page ? 0 : footnote_count, book_);
- SCM config = get_page_configuration (lines, page_num, rag, bookpart_last_page);
+ SCM config = SCM_EOL;
+ SCM dummy_page = make_page (page_num, bookpart_last_page);
+ Page_layout_problem layout (book_, dummy_page, lines);
+ if (!scm_is_pair (systems))
+ config = SCM_EOL;
+ else if (rag && !ragged ())
+ // If we're ragged-last but not ragged, make the last page
+ // have the same force as the previous page.
+ config = layout.fixed_force_solution (last_page_force);
+ else
+ config = layout.solution (rag);
+
+ last_page_force = layout.force ();
systems_configs_fncounts = scm_cons (scm_cons (lines, config), systems_configs_fncounts);
footnote_count += fn_lines;
header_padding_ = 0;
footer_padding_ = 0;
page_height_ = 100;
+ force_ = 0;
if (page)
{
elements_.push_back (Element (prob, padding));
}
+/**
+ For ragged-last pages, we usually want to stretch the page so that it
+ is not much more compressed than the previous page. Here, if ragged is
+ true and you pass a value of fixed_force that !isinf, then I will try
+ to space this page using the given force. If it does not fit, I will
+ resort to just filling the page (non-raggedly).
+*/
void
-Page_layout_problem::solve_rod_spring_problem (bool ragged)
+Page_layout_problem::solve_rod_spring_problem (bool ragged, Real fixed_force)
{
Simple_spacer spacer;
for (vsize i = 0; i < springs_.size (); ++i)
spacer.add_spring (springs_[i]);
- spacer.solve (page_height_, ragged);
+ if (ragged && !isinf (fixed_force))
+ {
+ // We need to tell the spacer it isn't ragged. Otherwise, it will
+ // refuse to stretch.
+ spacer.solve (page_height_, false);
+
+ if (spacer.configuration_length (fixed_force) <= page_height_)
+ spacer.set_force (fixed_force);
+ }
+ else
+ spacer.solve (page_height_, ragged);
+
solution_ = spacer.spring_positions ();
+ force_ = spacer.force ();
if (!spacer.fits ())
{
}
}
+Real
+Page_layout_problem::force () const
+{
+ return force_;
+}
+
// The solution_ vector stores the position of every live VerticalAxisGroup
// and every title. From that information,
// 1) within each system, stretch the staves so they land at the right position
}
}
+SCM
+Page_layout_problem::fixed_force_solution (Real force)
+{
+ solve_rod_spring_problem (true, force);
+ return find_system_offsets ();
+}
+
SCM
Page_layout_problem::solution (bool ragged)
{
- solve_rod_spring_problem (ragged);
+ solve_rod_spring_problem (ragged, -infinity_f);
return find_system_offsets ();
}
return l;
}
+void
+Simple_spacer::set_force (Real force)
+{
+ force_ = force;
+}
+
void
Simple_spacer::solve (Real line_len, bool ragged)
{