/*
This file is part of LilyPond, the GNU music typesetter.
- Copyright (C) 2009--2011 Joe Neeman <joeneeman@gmail.com>
+ Copyright (C) 2009--2015 Joe Neeman <joeneeman@gmail.com>
LilyPond is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
#include "skyline-pair.hh"
#include "system.hh"
#include "text-interface.hh"
+#include "lily-imports.hh"
/*
- Returns the number of footntoes associated with a given line.
+ Returns the number of footnotes associated with a given line.
*/
-vsize
-Page_layout_problem::get_footnote_count (SCM lines)
+vector<Grob *>
+Page_layout_problem::get_footnote_grobs (SCM lines)
{
- vsize fn_count = 0;
+ vector<Grob *> footnotes;
for (SCM s = lines; scm_is_pair (s); s = scm_cdr (s))
{
- if (Grob *g = unsmob_grob (scm_car (s)))
+ if (Grob *g = unsmob<Grob> (scm_car (s)))
{
System *sys = dynamic_cast<System *> (g);
if (!sys)
programming_error ("got a grob for footnotes that wasn't a System");
continue;
}
- fn_count += sys->num_footnotes ();
+ extract_grob_set (sys, "footnotes-after-line-breaking", footnote_grobs);
+ footnotes.insert (footnotes.end (), footnote_grobs.begin (), footnote_grobs.end ());
}
- else if (Prob *p = unsmob_prob (scm_car (s)))
+ else if (Prob *p = unsmob<Prob> (scm_car (s)))
{
SCM stencils = p->get_property ("footnotes");
- if (stencils == SCM_EOL)
+ if (scm_is_null (stencils))
continue;
for (SCM st = stencils; scm_is_pair (st); st = scm_cdr (st))
- fn_count++;
+ footnotes.push_back (0);
}
}
- return fn_count;
+ return footnotes;
+}
+
+vsize
+Page_layout_problem::get_footnote_count (SCM lines)
+{
+ vector<Grob *> notes = get_footnote_grobs (lines);
+ return notes.size ();
}
SCM
return SCM_EOL;
bool footnotes_added;
- if (Grob *g = unsmob_grob (scm_car (lines)))
+ if (Grob *g = unsmob<Grob> (scm_car (lines)))
footnotes_added = !scm_is_null (g->get_property ("footnote-stencil"));
- else if (Prob *p = unsmob_prob (scm_car (lines)))
+ else if (Prob *p = unsmob<Prob> (scm_car (lines)))
footnotes_added = !scm_is_null (p->get_property ("footnote-stencil"));
else
{
SCM out = SCM_EOL;
for (SCM s = lines; scm_is_pair (s); s = scm_cdr (s))
{
- if (Grob *g = unsmob_grob (scm_car (s)))
+ if (Grob *g = unsmob<Grob> (scm_car (s)))
out = scm_cons (g->get_property ("footnote-stencil"), out);
- else if (Prob *p = unsmob_prob (scm_car (s)))
+ else if (Prob *p = unsmob<Prob> (scm_car (s)))
out = scm_cons (p->get_property ("footnote-stencil"), out);
else
programming_error ("Systems on a page must be a prob or grob.");
}
- return scm_reverse (out);
+ return scm_reverse_x (out, SCM_EOL);
}
/*
number_footnote_table = SCM_EOL;
SCM numbering_function = paper->c_variable ("footnote-numbering-function");
SCM layout = paper->self_scm ();
- SCM props = scm_call_1 (ly_lily_module_constant ("layout-extract-page-properties"),
- paper->self_scm ());
+ SCM props = Lily::layout_extract_page_properties (layout);
Real padding = robust_scm2double (paper->c_variable ("footnote-padding"), 0.0);
Real number_raise = robust_scm2double (paper->c_variable ("footnote-number-raise"), 0.0);
- vsize fn_count = get_footnote_count (lines);
+ vector<Grob *> fn_grobs = get_footnote_grobs (lines);
+ vsize fn_count = fn_grobs.size ();
// now, make the footnote stencils with the numbering function
SCM numbers = SCM_EOL;
in duplicated work, either by making this process less complicated or (preferably)
by passing its results downstream.
*/
- vector<SCM> footnote_number_markups; // Holds the numbering markups.
- vector<Stencil *> footnote_number_stencils; // Holds translated versions of the stencilized numbering markups.
+
+ // find the maximum X_AXIS length
+ Real max_length = -infinity_f;
+
for (vsize i = 0; i < fn_count; i++)
{
+ if (fn_grobs[i])
+ {
+ SCM assertion_function = fn_grobs[i]->get_property ("numbering-assertion-function");
+ if (ly_is_procedure (assertion_function))
+ (void) scm_call_1 (assertion_function, scm_from_int (counter));
+ }
SCM markup = scm_call_1 (numbering_function, scm_from_int (counter));
- Stencil *s = unsmob_stencil (Text_interface::interpret_markup (layout, props, markup));
- if (!s)
+ SCM stencil = Text_interface::interpret_markup (layout, props, markup);
+ Stencil *st = unsmob<Stencil> (stencil);
+ if (!st)
{
programming_error ("Your numbering function needs to return a stencil.");
markup = SCM_EOL;
- s = new Stencil (Box (Interval (0, 0), Interval (0, 0)), SCM_EOL);
+ stencil = Stencil (Box (Interval (0, 0), Interval (0, 0)), SCM_EOL).smobbed_copy ();
+ st = unsmob<Stencil> (stencil);
}
- footnote_number_markups.push_back (markup);
- footnote_number_stencils.push_back (s);
+ in_text_numbers = scm_cons (markup, in_text_numbers);
+ numbers = scm_cons (stencil, numbers);
+
+ if (!st->extent (X_AXIS).is_empty ())
+ max_length = max (max_length, st->extent (X_AXIS)[RIGHT]);
+
counter++;
}
- // find the maximum X_AXIS length
- Real max_length = -infinity_f;
- for (vsize i = 0; i < fn_count; i++)
- max_length = max (max_length, footnote_number_stencils[i]->extent (X_AXIS).length ());
+ in_text_numbers = scm_reverse_x (in_text_numbers, SCM_EOL);
+ numbers = scm_reverse_x (numbers, SCM_EOL);
/*
translate each stencil such that it attains the correct maximum length and bundle the
footnotes into a scheme object.
*/
- SCM *tail = &numbers;
- SCM *in_text_tail = &in_text_numbers;
- for (vsize i = 0; i < fn_count; i++)
+ for (SCM p = numbers; scm_is_pair (p); p = scm_cdr (p))
{
- *in_text_tail = scm_cons (footnote_number_markups[i], SCM_EOL);
- in_text_tail = SCM_CDRLOC (*in_text_tail);
- footnote_number_stencils[i]->translate_axis ((max_length
- - footnote_number_stencils[i]->extent (X_AXIS).length ()),
- X_AXIS);
- *tail = scm_cons (footnote_number_stencils[i]->smobbed_copy (), SCM_EOL);
- tail = SCM_CDRLOC (*tail);
+ Stencil *st = unsmob<Stencil> (scm_car (p));
+ if (!st->extent (X_AXIS).is_empty ())
+ st->translate_axis ((max_length - st->extent (X_AXIS)[RIGHT]),
+ X_AXIS);
}
+
// build the footnotes
for (SCM s = lines; scm_is_pair (s); s = scm_cdr (s))
{
// Take care of musical systems.
- if (Grob *g = unsmob_grob (scm_car (s)))
+ if (Grob *g = unsmob<Grob> (scm_car (s)))
{
System *sys = dynamic_cast<System *> (g);
if (!sys)
}
Stencil mol;
Stencil in_note_mol;
- for (vsize i = 0; i < sys->footnote_grobs ()->size (); i++)
+ extract_grob_set (sys, "footnotes-after-line-breaking", footnote_grobs);
+ for (vsize i = 0; i < footnote_grobs.size (); i++)
{
- Grob *footnote = sys->footnote_grobs ()->at (i);
+ Grob *footnote = footnote_grobs[i];
SCM footnote_markup = footnote->get_property ("footnote-text");
if (Spanner *orig = dynamic_cast<Spanner *>(footnote))
if (orig->is_broken ())
footnote_markup = orig->broken_intos_[0]->get_property ("footnote-text");
- SCM props = scm_call_1 (ly_lily_module_constant ("layout-extract-page-properties"),
- paper->self_scm ());
+ SCM props = Lily::layout_extract_page_properties (paper->self_scm ());
SCM footnote_stl = Text_interface::interpret_markup (paper->self_scm (),
props, footnote_markup);
- Stencil *footnote_stencil = unsmob_stencil (footnote_stl);
+ Stencil footnote_stencil = *unsmob<Stencil> (footnote_stl);
bool do_numbering = to_boolean (footnote->get_property ("automatically-numbered"));
if (Spanner *orig = dynamic_cast<Spanner *>(footnote))
{
if (orig->is_broken ())
for (vsize i = 0; i < orig->broken_intos_.size (); i++)
do_numbering = do_numbering
- || to_boolean (orig->broken_intos_[i]->get_property ("automatically-numbered"));
+ || to_boolean (orig->broken_intos_[i]->get_property ("automatically-numbered"));
}
if (do_numbering)
{
orig->broken_intos_[i]->set_property ("text", annotation_scm);
}
- Stencil *annotation = unsmob_stencil (scm_car (numbers));
- annotation->translate_axis ((footnote_stencil->extent (Y_AXIS)[UP]
- + number_raise
- - annotation->extent (Y_AXIS)[UP]),
- Y_AXIS);
- footnote_stencil->add_at_edge (X_AXIS, LEFT, *annotation, 0.0);
+ Stencil annotation = *unsmob<Stencil> (scm_car (numbers));
+ annotation.translate_axis ((footnote_stencil.extent (Y_AXIS)[UP]
+ + number_raise
+ - annotation.extent (Y_AXIS)[UP]),
+ Y_AXIS);
+ footnote_stencil.add_at_edge (X_AXIS, LEFT, annotation, 0.0);
numbers = scm_cdr (numbers);
in_text_numbers = scm_cdr (in_text_numbers);
}
- if (!footnote_stencil->is_empty ())
+ if (!footnote_stencil.is_empty ())
{
if (to_boolean (footnote->get_property ("footnote")))
- mol.add_at_edge (Y_AXIS, DOWN, *footnote_stencil, padding);
+ mol.add_at_edge (Y_AXIS, DOWN, footnote_stencil, padding);
else
- in_note_mol.add_at_edge (Y_AXIS, DOWN, *footnote_stencil, padding);
+ in_note_mol.add_at_edge (Y_AXIS, DOWN, footnote_stencil, padding);
}
}
sys->set_property ("in-note-stencil", in_note_mol.smobbed_copy ());
sys->set_property ("footnote-stencil", mol.smobbed_copy ());
}
// Take care of top-level markups
- else if (Prob *p = unsmob_prob (scm_car (s)))
+ else if (Prob *p = unsmob<Prob> (scm_car (s)))
{
SCM stencils = p->get_property ("footnotes");
Stencil mol;
for (SCM st = stencils; scm_is_pair (st); st = scm_cdr (st))
{
- Stencil footnote_stencil;
- Stencil *footnote = unsmob_stencil (scm_caddar (st));
- footnote_stencil.add_stencil (*footnote);
+ Stencil footnote_stencil = *unsmob<Stencil> (scm_caddar (st));
bool do_numbering = to_boolean (scm_cadar (st));
SCM in_text_stencil = Stencil ().smobbed_copy ();
if (do_numbering)
{
- Stencil *annotation = unsmob_stencil (scm_car (numbers));
+ Stencil annotation = *unsmob<Stencil> (scm_car (numbers));
SCM in_text_annotation = scm_car (in_text_numbers);
in_text_stencil = Text_interface::interpret_markup (layout,
props,
in_text_annotation);
- if (!unsmob_stencil (in_text_stencil))
+ if (!unsmob<Stencil> (in_text_stencil))
in_text_stencil = SCM_EOL;
- annotation->translate_axis ((footnote_stencil.extent (Y_AXIS)[UP]
- + number_raise
- - annotation->extent (Y_AXIS)[UP]),
- Y_AXIS);
- footnote_stencil.add_at_edge (X_AXIS, LEFT, *annotation, 0.0);
+ annotation.translate_axis ((footnote_stencil.extent (Y_AXIS)[UP]
+ + number_raise
+ - annotation.extent (Y_AXIS)[UP]),
+ Y_AXIS);
+ footnote_stencil.add_at_edge (X_AXIS, LEFT, annotation, 0.0);
numbers = scm_cdr (numbers);
in_text_numbers = scm_cdr (in_text_numbers);
}
pb->top_paper ()->set_variable (ly_symbol2scm ("number-footnote-table"), number_footnote_table);
}
-Stencil *
+Stencil
Page_layout_problem::get_footnote_separator_stencil (Output_def *paper)
{
- SCM props = scm_call_1 (ly_lily_module_constant ("layout-extract-page-properties"),
- paper->self_scm ());
+ SCM props = Lily::layout_extract_page_properties (paper->self_scm ());
SCM markup = paper->c_variable ("footnote-separator-markup");
if (!Text_interface::is_markup (markup))
- return NULL;
+ return Stencil ();
SCM footnote_stencil = Text_interface::interpret_markup (paper->self_scm (),
props, markup);
- Stencil *footnote_separator = unsmob_stencil (footnote_stencil);
+ Stencil *footnote_separator = unsmob<Stencil> (footnote_stencil);
- return footnote_separator;
+ return footnote_separator ? *footnote_separator : Stencil ();
}
-void
-Page_layout_problem::add_footnotes_to_footer (SCM footnotes, Stencil *foot, Paper_book *pb)
+Stencil
+Page_layout_problem::add_footnotes_to_footer (SCM footnotes, Stencil foot, Paper_book *pb)
{
- if (!foot && scm_is_pair (footnotes))
- {
- warning ("Must have a footer to add footnotes.");
- return;
- }
+
bool footnotes_found = false;
Real footnote_padding = robust_scm2double (pb->paper_->c_variable ("footnote-padding"), 0.0);
Real footnote_footer_padding = robust_scm2double (pb->paper_->c_variable ("footnote-footer-padding"), 0.0);
for (SCM s = footnotes; scm_is_pair (s); s = scm_cdr (s))
{
- Stencil *stencil = unsmob_stencil (scm_car (s));
+ Stencil *stencil = unsmob<Stencil> (scm_car (s));
if (!stencil)
continue;
if (!stencil->is_empty ())
{
- foot->add_at_edge (Y_AXIS, UP, *stencil, (!footnotes_found ? footnote_footer_padding : footnote_padding));
+ foot.add_at_edge (Y_AXIS, UP, *stencil, (!footnotes_found ? footnote_footer_padding : footnote_padding));
footnotes_found = true;
}
}
if (footnotes_found)
{
- Stencil *separator = get_footnote_separator_stencil (pb->paper_);
- if (separator)
- foot->add_at_edge (Y_AXIS, UP, *separator, footnote_padding);
+ Stencil separator = get_footnote_separator_stencil (pb->paper_);
+ if (!separator.is_empty ())
+ foot.add_at_edge (Y_AXIS, UP, separator, footnote_padding);
}
+
+ return foot;
}
Page_layout_problem::Page_layout_problem (Paper_book *pb, SCM page_scm, SCM systems)
: bottom_skyline_ (DOWN)
{
- Prob *page = unsmob_prob (page_scm);
+ Prob *page = unsmob<Prob> (page_scm);
+ bottom_loose_baseline_ = 0;
header_height_ = 0;
footer_height_ = 0;
header_padding_ = 0;
footer_padding_ = 0;
page_height_ = 100;
+ force_ = 0;
if (page)
{
- Stencil *head = unsmob_stencil (page->get_property ("head-stencil"));
- Stencil *foot = unsmob_stencil (page->get_property ("foot-stencil"));
+ Stencil *head = unsmob<Stencil> (page->get_property ("head-stencil"));
+ Stencil *foot = unsmob<Stencil> (page->get_property ("foot-stencil"));
+
+ Stencil foot_stencil = foot ? *foot : Stencil ();
if (pb && pb->paper_)
{
SCM footnotes = get_footnotes_from_lines (systems);
- add_footnotes_to_footer (footnotes, foot, pb);
+ foot_stencil = add_footnotes_to_footer (footnotes, foot_stencil, pb);
}
else
- warning ("A page layout problem has been initiated that cannot accommodate footnotes.");
+ warning (_ ("A page layout problem has been initiated that cannot accommodate footnotes."));
header_height_ = head ? head->extent (Y_AXIS).length () : 0;
- footer_height_ = foot ? foot->extent (Y_AXIS).length () : 0;
+ footer_height_ = foot_stencil.extent (Y_AXIS).length ();
page_height_ = robust_scm2double (page->get_property ("paper-height"), 100);
}
markup_markup_spacing = paper->c_variable ("markup-markup-spacing");
last_bottom_spacing = paper->c_variable ("last-bottom-spacing");
top_system_spacing = paper->c_variable ("top-system-spacing");
- if (scm_is_pair (systems) && unsmob_prob (scm_car (systems)))
+ if (scm_is_pair (systems) && unsmob<Prob> (scm_car (systems)))
top_system_spacing = paper->c_variable ("top-markup-spacing");
// Note: the page height here does _not_ reserve space for headers and
for (SCM s = systems; scm_is_pair (s); s = scm_cdr (s))
{
- bool first = (s == systems);
+ bool first = scm_is_eq (s, systems);
- if (Grob *g = unsmob_grob (scm_car (s)))
+ if (Grob *g = unsmob<Grob> (scm_car (s)))
{
System *sys = dynamic_cast<System *> (g);
if (!sys)
append_system (sys, spring, indent, padding);
last_system_was_title = false;
}
- else if (Prob *p = unsmob_prob (scm_car (s)))
+ else if (Prob *p = unsmob<Prob> (scm_car (s)))
{
SCM spec = first ? top_system_spacing
: (last_system_was_title ? markup_markup_spacing : score_markup_spacing);
void
Page_layout_problem::append_system (System *sys, Spring const &spring, Real indent, Real padding)
{
- Grob *align = sys->get_vertical_alignment ();
+ Grob *align = unsmob<Grob> (sys->get_object ("vertical-alignment"));
if (!align)
return;
build_system_skyline (elts, minimum_offsets_with_min_dist, &up_skyline, &down_skyline);
up_skyline.shift (indent);
down_skyline.shift (indent);
- Stencil *in_note_stencil = unsmob_stencil (sys->get_property ("in-note-stencil"));
+ Stencil *in_note_stencil = unsmob<Stencil> (sys->get_property ("in-note-stencil"));
if (in_note_stencil && in_note_stencil->extent (Y_AXIS).length () > 0)
{
Skyline *sky = in_note_direction_ == UP ? &up_skyline : &down_skyline;
sky->set_minimum_height (sky->max_height ()
+ in_note_direction_
- * (in_note_padding_
- + in_note_stencil->extent (Y_AXIS).length ()));
+ * (in_note_padding_
+ + in_note_stencil->extent (Y_AXIS).length ()));
}
/*
*/
Real minimum_distance = up_skyline.distance (bottom_skyline_,
robust_scm2double (sys->get_property ("skyline-horizontal-padding"),
- 0))
+ 0))
+ padding;
Spring spring_copy = spring;
spring_copy.ensure_min_distance (minimum_distance);
springs_.push_back (spring_copy);
+ if (elts.size () && !is_spaceable (elts[0]))
+ {
+ // store the minimum distance, considering relative indents,
+ // for a loose line
+ Skyline first_skyline (UP);
+ Skyline_pair *sky = unsmob<Skyline_pair> (elts[0]->get_property ("vertical-skylines"));
+ if (sky)
+ first_skyline.merge ((*sky)[UP]);
+ first_skyline.shift (indent);
+ minimum_distance = first_skyline.distance (bottom_skyline_) - bottom_loose_baseline_;
+ }
bottom_skyline_ = down_skyline;
- elements_.push_back (Element (elts, minimum_offsets, padding));
+ elements_.push_back (Element (elts, minimum_offsets, minimum_distance, padding));
// Add the springs for the VerticalAxisGroups in this system.
{
if (is_spaceable (elts[i]))
{
- // We don't add a spring for the first staff, since
- // we are only adding springs _between_ staves here.
if (!found_spaceable_staff)
{
+ // Ensure space for any loose lines above this system
+ if (i > 0)
+ springs_.back ().ensure_min_distance (bottom_loose_baseline_
+ - minimum_offsets_with_min_dist[i]
+ + padding);
found_spaceable_staff = true;
last_spaceable_staff = i;
+ // We don't add a spring for the first staff, since
+ // we are only adding springs _between_ staves here.
continue;
}
}
}
+ bottom_loose_baseline_ = found_spaceable_staff
+ ? ( minimum_offsets_with_min_dist[last_spaceable_staff]
+ - minimum_offsets_with_min_dist.back ())
+ : 0;
+
// Corner case: there was only one staff, and it wasn't spaceable.
- // Mark it spaceable, because we do not allow non-spaceable staves
- // to be at the top or bottom of a system.
if (!found_spaceable_staff && elts.size ())
mark_as_spaceable (elts[0]);
}
void
Page_layout_problem::append_prob (Prob *prob, Spring const &spring, Real padding)
{
- Skyline_pair *sky = Skyline_pair::unsmob (prob->get_property ("vertical-skylines"));
+ Skyline_pair *sky = unsmob<Skyline_pair> (prob->get_property ("vertical-skylines"));
Real minimum_distance = 0;
bool tight_spacing = to_boolean (prob->get_property ("tight-spacing"));
if (sky)
{
- minimum_distance = (*sky)[UP].distance (bottom_skyline_);
+ minimum_distance = max ((*sky)[UP].distance (bottom_skyline_),
+ bottom_loose_baseline_);
bottom_skyline_ = (*sky)[DOWN];
}
- else if (Stencil *sten = unsmob_stencil (prob->get_property ("stencil")))
+ else if (Stencil *sten = unsmob<Stencil> (prob->get_property ("stencil")))
{
Interval iv = sten->extent (Y_AXIS);
minimum_distance = iv[UP] - bottom_skyline_.max_height ();
bottom_skyline_.clear ();
bottom_skyline_.set_minimum_height (iv[DOWN]);
}
+ bottom_loose_baseline_ = 0.0;
Spring spring_copy = spring;
if (tight_spacing)
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 overflow = spacer.configuration_length (spacer.force ())
- page_height_;
if (ragged && overflow < 1e-6)
- warning (_ ("cannot fit music on page: ragged-spacing was requested, but page was compressed"));
+ warning (_ ("ragged-bottom was specified, but page must be compressed"));
else
{
- warning (_f ("cannot fit music on page: overflow is %f",
+ warning (_f ("compressing over-full page by %.1f staff-spaces",
overflow));
- warning (_ ("compressing music to fit"));
+ force_ = -infinity_f;
vsize space_count = solution_.size ();
Real spacing_increment = overflow / (space_count - 2);
for (vsize i = 2; i < space_count; i++)
}
}
+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
{
*tail = scm_cons (scm_from_double (solution_[spring_idx]), SCM_EOL);
tail = SCM_CDRLOC (*tail);
- Interval prob_extent = unsmob_stencil (elements_[i].prob->get_property ("stencil"))->extent (Y_AXIS);
+ Interval prob_extent = unsmob<Stencil> (elements_[i].prob->get_property ("stencil"))->extent (Y_AXIS);
// Lay out any non-spaceable lines between this line and
// the last one.
if (staff_idx)
loose_line_min_distances.push_back (min_offsets[staff_idx - 1] - min_offsets[staff_idx]);
else
- loose_line_min_distances.push_back (elements_[i].padding - min_offsets[staff_idx]);
+ {
+ // A null line to break any staff-affinity from the previous system
+ loose_line_min_distances.push_back (0.0);
+ loose_lines.push_back (0);
+ loose_line_min_distances.push_back (elements_[i].padding - min_offsets[0]);
+ }
loose_lines.push_back (staff);
distribute_loose_lines (loose_lines, loose_line_min_distances,
found_spaceable_staff = true;
spring_idx++;
}
- else
+ else // ! is_spaceable
{
+ if (staff->extent (staff, Y_AXIS).is_empty ())
+ continue;
+
if (loose_lines.empty ())
loose_lines.push_back (last_spaceable_line);
// this is the first line in a system
Real min_dist = 0;
if (loose_lines.back ())
- // distance to the final line in the preceding system,
- // including 'system-system-spacing 'padding
- min_dist = (Axis_group_interface::minimum_distance (loose_lines.back (),
- staff,
- Y_AXIS)
- + elements_[i].padding);
+ {
+ // distance to the final line in the preceding system,
+ // including 'system-system-spacing 'padding
+ min_dist = elements_[i].min_distance + elements_[i].padding;
+ // A null line to break any staff-affinity for the previous system
+ loose_line_min_distances.push_back (0.0);
+ loose_lines.push_back (0);
+ }
else if (!last_title_extent.is_empty ())
// distance to the preceding title,
- // including 'markup-system-spacing 'padding
+ // including 'markup-system-wg 'padding
min_dist = (staff->extent (staff, Y_AXIS)[UP] - last_title_extent[DOWN]
+ elements_[i].padding);
else // distance to the top margin
vector<Real> solution = spacer.spring_positions ();
for (vsize i = 1; i + 1 < solution.size (); ++i)
- {
- Real system_offset = scm_to_double (loose_lines[i]->get_property ("system-Y-offset"));
- loose_lines[i]->translate_axis (first_translation - solution[i] - system_offset, Y_AXIS);
- }
+ if (loose_lines[i])
+ {
+ Real system_offset = scm_to_double (loose_lines[i]->get_property ("system-Y-offset"));
+ loose_lines[i]->translate_axis (first_translation - solution[i] - system_offset, Y_AXIS);
+ }
+}
+
+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 ();
}
{
Real dy = minimum_translations[i] - first_translation;
Grob *g = staves[i];
- Skyline_pair *sky = Skyline_pair::unsmob (g->get_property ("vertical-skylines"));
+ Skyline_pair *sky = unsmob<Skyline_pair> (g->get_property ("vertical-skylines"));
if (sky)
{
up->raise (-dy);
Interval
Page_layout_problem::prob_extent (Prob *p)
{
- Stencil *sten = unsmob_stencil (p->get_property ("stencil"));
+ Stencil *sten = unsmob<Stencil> (p->get_property ("stencil"));
return sten ? sten->extent (Y_AXIS) : Interval (0, 0);
}
vector<Grob *> output;
for (vsize i = 0; i < input.size (); ++i)
{
- if (Hara_kiri_group_spanner::has_interface (input[i]))
+ if (has_interface<Hara_kiri_group_spanner> (input[i]))
Hara_kiri_group_spanner::consider_suicide (input[i]);
if (input[i]->is_live ())