/*
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 a stencil for the footnote of each system. This stencil may
- itself be comprised of several footnotes.
+ Returns the number of footnotes associated with a given line.
*/
-SCM
-Page_layout_problem::get_footnotes_from_lines (SCM lines, Real padding)
+vector<Grob *>
+Page_layout_problem::get_footnote_grobs (SCM lines)
{
- SCM footnotes = SCM_EOL;
- // ugh...code dup from the Page_layout_problem constructor
+ vector<Grob *> footnotes;
for (SCM s = lines; scm_is_pair (s); s = scm_cdr (s))
{
- if (Grob *g = unsmob_grob (scm_car (s)))
- {
- System *sys = dynamic_cast<System *> (g);
- if (!sys)
+ 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;
}
- footnotes = scm_cons (sys->make_footnote_stencil (padding).smobbed_copy (), 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;
- Stencil footnote_stencil;
-
for (SCM st = stencils; scm_is_pair (st); st = scm_cdr (st))
- footnote_stencil.add_at_edge (Y_AXIS, DOWN, *unsmob_stencil (scm_car (st)), padding);
- footnotes = scm_cons (footnote_stencil.smobbed_copy (), footnotes);
+ footnotes.push_back (0);
}
}
- if (!scm_is_pair (footnotes))
+ return footnotes;
+}
+
+vsize
+Page_layout_problem::get_footnote_count (SCM lines)
+{
+ vector<Grob *> notes = get_footnote_grobs (lines);
+ return notes.size ();
+}
+
+SCM
+Page_layout_problem::get_footnotes_from_lines (SCM lines)
+{
+ if (!scm_is_pair (lines))
return SCM_EOL;
- return scm_reverse (footnotes);
+ bool footnotes_added;
+ 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)))
+ footnotes_added = !scm_is_null (p->get_property ("footnote-stencil"));
+ else
+ {
+ programming_error ("Systems on a page must be a prob or grob.");
+ return SCM_EOL;
+ }
+ if (!footnotes_added)
+ {
+ programming_error ("Footnotes must be added to lines before they are retrieved.");
+ return SCM_EOL;
+ }
+
+ SCM out = SCM_EOL;
+ for (SCM s = lines; scm_is_pair (s); s = scm_cdr (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)))
+ 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_x (out, SCM_EOL);
+}
+
+/*
+ Adds a footnote stencil to each system. This stencil may
+ itself be comprised of several footnotes.
+
+ This is a long function, but it seems better to keep it intact rather than
+ splitting it into parts.
+*/
+
+void
+Page_layout_problem::add_footnotes_to_lines (SCM lines, int counter, Paper_book *pb)
+{
+ /*
+ first, we have to see how many footnotes are on this page.
+ we need to do this first so that we can line them up
+ */
+
+ Output_def *paper = pb->paper_;
+
+ if (!paper)
+ {
+ programming_error ("Cannot get footnotes because there is no valid paper block.");
+ return;
+ }
+
+ SCM number_footnote_table = pb->top_paper ()->c_variable ("number-footnote-table");
+ if (!scm_is_pair (number_footnote_table))
+ number_footnote_table = SCM_EOL;
+ SCM numbering_function = paper->c_variable ("footnote-numbering-function");
+ SCM layout = 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);
+
+ 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;
+ SCM in_text_numbers = SCM_EOL;
+ /*
+ TODO: This recalculates numbering every time this function is called, including once
+ after the balloon prints are called. Although it is not a huge computational drain,
+ it'd be more elegant to turn this calculation off when it is no longer needed.
+
+ In a separate commit, it'd be nice to streamline the way that page layout property
+ is handled so that the process of building `config's in page-breaking does result
+ in duplicated work, either by making this process less complicated or (preferably)
+ by passing its results downstream.
+ */
+
+ // 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));
+ 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;
+ stencil = Stencil (Box (Interval (0, 0), Interval (0, 0)), SCM_EOL).smobbed_copy ();
+ st = unsmob<Stencil> (stencil);
+ }
+ 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++;
+ }
+
+ 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.
+ */
+
+ for (SCM p = numbers; scm_is_pair (p); p = scm_cdr (p))
+ {
+ 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)))
+ {
+ System *sys = dynamic_cast<System *> (g);
+ if (!sys)
+ {
+ programming_error ("got a grob for footnotes that wasn't a System");
+ continue;
+ }
+ Stencil mol;
+ Stencil in_note_mol;
+ extract_grob_set (sys, "footnotes-after-line-breaking", footnote_grobs);
+ for (vsize i = 0; i < footnote_grobs.size (); 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 = 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);
+ 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"));
+ }
+ if (do_numbering)
+ {
+ SCM annotation_scm = scm_car (in_text_numbers);
+ footnote->set_property ("text", annotation_scm);
+ if (Spanner *orig = dynamic_cast<Spanner *>(footnote))
+ {
+ orig->set_property ("text", annotation_scm);
+ if (orig->is_broken ())
+ for (vsize i = 0; i < orig->broken_intos_.size (); i++)
+ 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);
+ numbers = scm_cdr (numbers);
+ in_text_numbers = scm_cdr (in_text_numbers);
+ }
+ if (!footnote_stencil.is_empty ())
+ {
+ if (to_boolean (footnote->get_property ("footnote")))
+ mol.add_at_edge (Y_AXIS, DOWN, footnote_stencil, padding);
+ else
+ 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)))
+ {
+ SCM stencils = p->get_property ("footnotes");
+ Stencil mol;
+
+ for (SCM st = stencils; scm_is_pair (st); st = scm_cdr (st))
+ {
+ 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));
+ 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))
+ 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);
+ numbers = scm_cdr (numbers);
+ in_text_numbers = scm_cdr (in_text_numbers);
+ }
+ number_footnote_table = scm_cons (scm_cons (scm_caar (st),
+ in_text_stencil),
+ number_footnote_table);
+ if (!footnote_stencil.is_empty ())
+ mol.add_at_edge (Y_AXIS, DOWN, footnote_stencil, padding);
+ }
+ p->set_property ("footnote-stencil", mol.smobbed_copy ());
+ }
+ }
+
+ // note that this line of code doesn't do anything if numbering isn't turned on
+ 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)
{
+
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);
-
+
footnotes = scm_reverse (footnotes);
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"));
-
- Real footnote_padding = 0.0;
+ 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_)
- footnote_padding = robust_scm2double (pb->paper_->c_variable ("footnote-padding"), 0.0);
- SCM footnotes = get_footnotes_from_lines (systems, footnote_padding);
- add_footnotes_to_footer (footnotes, foot, pb);
-
+ {
+ SCM footnotes = get_footnotes_from_lines (systems);
+ foot_stencil = add_footnotes_to_footer (footnotes, foot_stencil, pb);
+ }
+ else
+ 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)))
- top_system_spacing = paper->c_variable ("top-markup-spacing");
+ 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
// footers. This is because we want to anchor the top-system-spacing
// spring at the _top_ of the header.
page_height_ -= robust_scm2double (paper->c_variable ("top-margin"), 0)
- + robust_scm2double (paper->c_variable ("bottom-margin"), 0);
+ + robust_scm2double (paper->c_variable ("bottom-margin"), 0);
read_spacing_spec (top_system_spacing, &header_padding_, ly_symbol2scm ("padding"));
read_spacing_spec (last_bottom_spacing, &footer_padding_, ly_symbol2scm ("padding"));
+ in_note_padding_ = robust_scm2double (paper->c_variable ("in-note-padding"), 0.5);
+ in_note_direction_ = robust_scm2dir (paper->c_variable ("in-note-direction"), UP);
}
bool last_system_was_title = false;
-
for (SCM s = systems; scm_is_pair (s); s = scm_cdr (s))
{
- bool first = (s == systems);
-
- if (Grob *g = unsmob_grob (scm_car (s)))
- {
- System *sys = dynamic_cast<System*> (g);
- if (!sys)
- {
- programming_error ("got a grob for vertical spacing that wasn't a System");
- continue;
- }
-
- SCM spec = system_system_spacing;
- if (first)
- spec = top_system_spacing;
- else if (last_system_was_title)
- spec = markup_system_spacing;
- else if (0 == Paper_column::get_rank (sys->get_bound (LEFT)))
- spec = score_system_spacing;
-
- Spring spring (0, 0);
- Real padding = 0.0;
- Real indent = line_dimensions_int (sys->paper_score ()->layout (), sys->get_rank ())[LEFT];
- alter_spring_from_spacing_spec (spec, &spring);
- read_spacing_spec (spec, &padding, ly_symbol2scm ("padding"));
-
- append_system (sys, spring, indent, padding);
- last_system_was_title = false;
- }
- 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);
- Spring spring (0, 0);
- Real padding = 0.0;
- alter_spring_from_spacing_spec (spec, &spring);
- read_spacing_spec (spec, &padding, ly_symbol2scm ("padding"));
-
- append_prob (p, spring, padding);
- last_system_was_title = true;
- }
+ bool first = scm_is_eq (s, systems);
+
+ if (Grob *g = unsmob<Grob> (scm_car (s)))
+ {
+ System *sys = dynamic_cast<System *> (g);
+ if (!sys)
+ {
+ programming_error ("got a grob for vertical spacing that wasn't a System");
+ continue;
+ }
+
+ SCM spec = system_system_spacing;
+ if (first)
+ spec = top_system_spacing;
+ else if (last_system_was_title)
+ spec = markup_system_spacing;
+ else if (0 == Paper_column::get_rank (sys->get_bound (LEFT)))
+ spec = score_system_spacing;
+
+ Spring spring (0, 0);
+ Real padding = 0.0;
+ Real indent = line_dimensions_int (sys->paper_score ()->layout (), sys->get_rank ())[LEFT];
+ alter_spring_from_spacing_spec (spec, &spring);
+ read_spacing_spec (spec, &padding, ly_symbol2scm ("padding"));
+
+ append_system (sys, spring, indent, padding);
+ last_system_was_title = false;
+ }
+ 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);
+ Spring spring (0, 0);
+ Real padding = 0.0;
+ alter_spring_from_spacing_spec (spec, &spring);
+ read_spacing_spec (spec, &padding, ly_symbol2scm ("padding"));
+
+ append_prob (p, spring, padding);
+ last_system_was_title = true;
+ }
else
- programming_error ("got a system that was neither a Grob nor a Prob");
+ programming_error ("got a system that was neither a Grob nor a Prob");
}
Spring last_spring (0, 0);
// bottom-space has the flexibility that one can do it per-system.
// NOTE: bottom-space is misnamed since it is not stretchable space.
if (Prob *p = elements_.back ().prob)
- bottom_padding = robust_scm2double (p->get_property ("bottom-space"), 0);
+ bottom_padding = robust_scm2double (p->get_property ("bottom-space"), 0);
else if (elements_.back ().staves.size ())
- {
- SCM details = get_details (elements_.back ());
- bottom_padding = robust_scm2double (ly_assoc_get (ly_symbol2scm ("bottom-space"),
- details,
- SCM_BOOL_F),
- 0.0);
- }
+ {
+ SCM details = get_details (elements_.back ());
+ bottom_padding = robust_scm2double (ly_assoc_get (ly_symbol2scm ("bottom-space"),
+ details,
+ SCM_BOOL_F),
+ 0.0);
+ }
page_height_ -= bottom_padding;
}
}
}
void
-Page_layout_problem::append_system (System *sys, Spring const& spring, Real indent, Real padding)
+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;
align->set_property ("positioning-done", SCM_BOOL_T);
extract_grob_set (align, "elements", all_elts);
- vector<Grob*> elts = filter_dead_elements (all_elts);
+ vector<Grob *> elts = filter_dead_elements (all_elts);
vector<Real> minimum_offsets = Align_interface::get_minimum_translations_without_min_dist (align, elts, Y_AXIS);
vector<Real> minimum_offsets_with_min_dist = Align_interface::get_minimum_translations (align, elts, Y_AXIS);
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"));
+
+ if (in_note_stencil && in_note_stencil->extent (Y_AXIS).length () > 0)
+ {
+ sys->set_property ("in-note-padding", scm_from_double (in_note_padding_));
+ sys->set_property ("in-note-direction", scm_from_int (in_note_direction_));
+ 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 ()));
+ }
/*
We need to call distance with skyline-horizontal-padding because
of an individual staff. So we add the padding for the distance check
at the time of adding in the system.
*/
- Real minimum_distance = up_skyline.distance (bottom_skyline_, robust_scm2double (sys->get_property ("skyline-horizontal-padding"), 0)) + padding;
+ Real minimum_distance = up_skyline.distance (bottom_skyline_,
+ robust_scm2double (sys->get_property ("skyline-horizontal-padding"),
+ 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.
for (vsize i = 0; i < elts.size (); ++i)
{
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)
- {
- found_spaceable_staff = true;
- last_spaceable_staff = i;
- continue;
- }
-
- Spring spring (0.5, 0.0);
- SCM spec = elts[last_spaceable_staff]->get_property ("staff-staff-spacing");
- alter_spring_from_spacing_spec (spec, &spring);
-
- springs_.push_back (spring);
- Real min_distance = (found_spaceable_staff ? minimum_offsets_with_min_dist[last_spaceable_staff] : 0) - minimum_offsets_with_min_dist[i];
- springs_.back ().ensure_min_distance (min_distance);
-
- if (scm_is_pair (manual_dists))
- {
- if (scm_is_number (scm_car (manual_dists)))
- {
- Real dy = scm_to_double (scm_car (manual_dists));
-
- springs_.back ().set_distance (dy);
- springs_.back ().set_min_distance (dy);
- springs_.back ().set_inverse_stretch_strength (0);
- }
- manual_dists = scm_cdr (manual_dists);
- }
- last_spaceable_staff = i;
- }
+ {
+ 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;
+ }
+
+ Spring spring (0.5, 0.0);
+ SCM spec = elts[last_spaceable_staff]->get_property ("staff-staff-spacing");
+ alter_spring_from_spacing_spec (spec, &spring);
+
+ springs_.push_back (spring);
+ Real min_distance = (found_spaceable_staff ? minimum_offsets_with_min_dist[last_spaceable_staff] : 0) - minimum_offsets_with_min_dist[i];
+ springs_.back ().ensure_min_distance (min_distance);
+
+ if (scm_is_pair (manual_dists))
+ {
+ if (scm_is_number (scm_car (manual_dists)))
+ {
+ Real dy = scm_to_double (scm_car (manual_dists));
+
+ springs_.back ().set_distance (dy);
+ springs_.back ().set_min_distance (dy);
+ springs_.back ().set_inverse_stretch_strength (0);
+ }
+ manual_dists = scm_cdr (manual_dists);
+ }
+ last_spaceable_staff = i;
+ }
}
+ 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)
+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_;
+ - 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",
- overflow));
- warning (_ ("compressing music to fit"));
- vsize space_count = solution_.size ();
- Real spacing_increment = overflow / (space_count - 2);
- for (vsize i = 2; i < space_count; i++)
- solution_[i] -= (i-1) * spacing_increment;
- }
+ {
+ warning (_f ("compressing over-full page by %.1f staff-spaces",
+ overflow));
+ force_ = -infinity_f;
+ vsize space_count = solution_.size ();
+ Real spacing_increment = overflow / (space_count - 2);
+ for (vsize i = 2; i < space_count; i++)
+ solution_[i] -= (i - 1) * spacing_increment;
+ }
}
}
+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
// spring_idx 0 is the top of the page. Interesting values start from 1.
vsize spring_idx = 1;
- vector<Grob*> loose_lines;
+ vector<Grob *> loose_lines;
vector<Real> loose_line_min_distances;
Grob *last_spaceable_line = 0;
Real last_spaceable_line_translation = 0;
for (vsize i = 0; i < elements_.size (); ++i)
{
if (elements_[i].prob)
- {
- *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);
-
- // Lay out any non-spaceable lines between this line and
- // the last one.
- if (loose_lines.size ())
- {
- Interval loose_extent = loose_lines.back ()->extent (loose_lines.back (), Y_AXIS);
- Real min_distance = (-loose_extent[DOWN] + prob_extent[UP]
- + elements_[i].padding);
-
- loose_line_min_distances.push_back (min_distance);
- loose_lines.push_back (0);
-
- distribute_loose_lines (loose_lines, loose_line_min_distances,
- last_spaceable_line_translation, -solution_[spring_idx]);
- loose_lines.clear ();
- loose_line_min_distances.clear ();
- }
-
- last_spaceable_line = 0;
- last_spaceable_line_translation = -solution_[spring_idx];
- last_title_extent = prob_extent;
- spring_idx++;
- }
+ {
+ *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);
+
+ // Lay out any non-spaceable lines between this line and
+ // the last one.
+ if (loose_lines.size ())
+ {
+ Interval loose_extent = loose_lines.back ()->extent (loose_lines.back (), Y_AXIS);
+ Real min_distance = (-loose_extent[DOWN] + prob_extent[UP]
+ + elements_[i].padding);
+
+ loose_line_min_distances.push_back (min_distance);
+ loose_lines.push_back (0);
+
+ distribute_loose_lines (loose_lines, loose_line_min_distances,
+ last_spaceable_line_translation, -solution_[spring_idx]);
+ loose_lines.clear ();
+ loose_line_min_distances.clear ();
+ }
+
+ last_spaceable_line = 0;
+ last_spaceable_line_translation = -solution_[spring_idx];
+ last_title_extent = prob_extent;
+ spring_idx++;
+ }
else
- {
- // Getting this signs right here is a little tricky. The configuration
- // we return has zero at the top of the page and positive numbers further
- // down, as does the solution_ vector. Within a staff, however, positive
- // numbers are up.
- // TODO: perhaps change the way the page 'configuration variable works so
- // that it is consistent with the usual up/down sign conventions in
- // Lilypond. Then this would be less confusing.
-
- // These two positions are relative to the page (with positive numbers being
- // down).
- Real first_staff_position = solution_[spring_idx];
- Real first_staff_min_translation = elements_[i].min_offsets.size () ? elements_[i].min_offsets[0] : 0;
- Real system_position = first_staff_position + first_staff_min_translation;
-
- // Position the staves within this system.
- vector<Real> const& min_offsets = elements_[i].min_offsets;
- bool found_spaceable_staff = false;
- for (vsize staff_idx = 0; staff_idx < elements_[i].staves.size (); ++staff_idx)
- {
- Grob *staff = elements_[i].staves[staff_idx];
- staff->set_property ("system-Y-offset", scm_from_double (-system_position));
-
- if (is_spaceable (staff))
- {
- // this is relative to the system: negative numbers are down.
- staff->translate_axis (system_position - solution_[spring_idx], Y_AXIS);
-
- // Lay out any non-spaceable lines between this line and
- // the last one.
- if (loose_lines.size ())
- {
- 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]);
- loose_lines.push_back (staff);
-
- distribute_loose_lines (loose_lines, loose_line_min_distances,
- last_spaceable_line_translation, -solution_[spring_idx]);
- loose_lines.clear ();
- loose_line_min_distances.clear ();
- }
- last_spaceable_line = staff;
- last_spaceable_line_translation = -solution_[spring_idx];
- found_spaceable_staff = true;
- spring_idx++;
- }
- else
- {
- if (loose_lines.empty ())
- loose_lines.push_back (last_spaceable_line);
-
- if (staff_idx)
- // NOTE: the way we do distances between loose lines (and other lines too, actually)
- // is not the most accurate way possible: we only insert rods between adjacent
- // lines. To be more accurate, we could insert rods between non-adjacent lines
- // using a scheme similar to the one in set_column_rods.
- loose_line_min_distances.push_back (min_offsets[staff_idx-1] - min_offsets[staff_idx]);
- else
- { // 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);
- else if (!last_title_extent.is_empty ())
- // distance to the preceding title,
- // including 'markup-system-spacing 'padding
- min_dist = (staff->extent (staff, Y_AXIS)[UP] - last_title_extent[DOWN]
- + elements_[i].padding);
- else // distance to the top margin
- min_dist = header_padding_ + header_height_ + staff->extent (staff, Y_AXIS)[UP];
-
- loose_line_min_distances.push_back (min_dist);
- }
- loose_lines.push_back (staff);
- }
- }
-
- // Corner case: even if a system has no live staves, it still takes up
- // one spring (a system with one live staff also takes up one spring),
- // which we need to increment past.
- if (!found_spaceable_staff)
- spring_idx++;
-
- *tail = scm_cons (scm_from_double (system_position), SCM_EOL);
- tail = SCM_CDRLOC (*tail);
- }
+ {
+ // Getting this signs right here is a little tricky. The configuration
+ // we return has zero at the top of the page and positive numbers further
+ // down, as does the solution_ vector. Within a staff, however, positive
+ // numbers are up.
+ // TODO: perhaps change the way the page 'configuration variable works so
+ // that it is consistent with the usual up/down sign conventions in
+ // Lilypond. Then this would be less confusing.
+
+ // These two positions are relative to the page (with positive numbers being
+ // down).
+ Real first_staff_position = solution_[spring_idx];
+ Real first_staff_min_translation = elements_[i].min_offsets.size () ? elements_[i].min_offsets[0] : 0;
+ Real system_position = first_staff_position + first_staff_min_translation;
+
+ // Position the staves within this system.
+ vector<Real> const &min_offsets = elements_[i].min_offsets;
+ bool found_spaceable_staff = false;
+ for (vsize staff_idx = 0; staff_idx < elements_[i].staves.size (); ++staff_idx)
+ {
+ Grob *staff = elements_[i].staves[staff_idx];
+ staff->set_property ("system-Y-offset", scm_from_double (-system_position));
+
+ if (is_spaceable (staff))
+ {
+ // this is relative to the system: negative numbers are down.
+ staff->translate_axis (system_position - solution_[spring_idx], Y_AXIS);
+
+ // Lay out any non-spaceable lines between this line and
+ // the last one.
+ if (loose_lines.size ())
+ {
+ if (staff_idx)
+ loose_line_min_distances.push_back (min_offsets[staff_idx - 1] - min_offsets[staff_idx]);
+ else
+ {
+ // 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,
+ last_spaceable_line_translation, -solution_[spring_idx]);
+ loose_lines.clear ();
+ loose_line_min_distances.clear ();
+ }
+ last_spaceable_line = staff;
+ last_spaceable_line_translation = -solution_[spring_idx];
+ found_spaceable_staff = true;
+ spring_idx++;
+ }
+ else // ! is_spaceable
+ {
+ if (staff->extent (staff, Y_AXIS).is_empty ())
+ continue;
+
+ if (loose_lines.empty ())
+ loose_lines.push_back (last_spaceable_line);
+
+ if (staff_idx)
+ // NOTE: the way we do distances between loose lines (and other lines too, actually)
+ // is not the most accurate way possible: we only insert rods between adjacent
+ // lines. To be more accurate, we could insert rods between non-adjacent lines
+ // using a scheme similar to the one in set_column_rods.
+ loose_line_min_distances.push_back (min_offsets[staff_idx - 1] - min_offsets[staff_idx]);
+ else
+ {
+ // 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 = 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-wg 'padding
+ min_dist = (staff->extent (staff, Y_AXIS)[UP] - last_title_extent[DOWN]
+ + elements_[i].padding);
+ else // distance to the top margin
+ min_dist = header_padding_ + header_height_ + staff->extent (staff, Y_AXIS)[UP];
+
+ loose_line_min_distances.push_back (min_dist);
+ }
+ loose_lines.push_back (staff);
+ }
+ }
+
+ // Corner case: even if a system has no live staves, it still takes up
+ // one spring (a system with one live staff also takes up one spring),
+ // which we need to increment past.
+ if (!found_spaceable_staff)
+ spring_idx++;
+
+ *tail = scm_cons (scm_from_double (system_position), SCM_EOL);
+ tail = SCM_CDRLOC (*tail);
+ }
}
if (loose_lines.size ())
loose_lines.push_back (0);
distribute_loose_lines (loose_lines, loose_line_min_distances,
- last_spaceable_line_translation, -page_height_);
+ last_spaceable_line_translation, -page_height_);
}
// them.
// first_translation and last_translation are relative to the page.
void
-Page_layout_problem::distribute_loose_lines (vector<Grob*> const &loose_lines,
- vector<Real> const &min_distances,
- Real first_translation, Real last_translation)
+Page_layout_problem::distribute_loose_lines (vector<Grob *> const &loose_lines,
+ vector<Real> const &min_distances,
+ Real first_translation, Real last_translation)
{
Simple_spacer spacer;
for (vsize i = 0; i + 1 < loose_lines.size (); ++i)
{
- SCM spec = get_spacing_spec (loose_lines[i], loose_lines[i+1], false, 0, INT_MAX);
+ SCM spec = get_spacing_spec (loose_lines[i], loose_lines[i + 1], false, 0, INT_MAX);
Spring spring (1.0, 0.0);
alter_spring_from_spacing_spec (spec, &spring);
spring.ensure_min_distance (min_distances[i]);
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 ();
}
// The upper skyline is relative to the top staff; the lower skyline is relative to
// the bottom staff.
void
-Page_layout_problem::build_system_skyline (vector<Grob*> const& staves,
- vector<Real> const& minimum_translations,
- Skyline *up,
- Skyline *down)
+Page_layout_problem::build_system_skyline (vector<Grob *> const &staves,
+ vector<Real> const &minimum_translations,
+ Skyline *up,
+ Skyline *down)
{
if (minimum_translations.empty ())
return;
{
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);
- up->merge ((*sky)[UP]);
- up->raise (dy);
-
- down->raise (-dy);
- down->merge ((*sky)[DOWN]);
- down->raise (dy);
- }
+ {
+ up->raise (-dy);
+ up->merge ((*sky)[UP]);
+ up->raise (dy);
+
+ down->raise (-dy);
+ down->merge ((*sky)[DOWN]);
+ down->raise (dy);
+ }
if (is_spaceable (staves[i]))
- {
- if (!found_spaceable_staff)
- {
- found_spaceable_staff = true;
- first_spaceable_dy = dy;
- }
- last_spaceable_dy = dy;
- }
+ {
+ if (!found_spaceable_staff)
+ {
+ found_spaceable_staff = true;
+ first_spaceable_dy = dy;
+ }
+ last_spaceable_dy = dy;
+ }
}
// Leave the up skyline at a position relative
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);
}
Interval
-Page_layout_problem::first_staff_extent (Element const& e)
+Page_layout_problem::first_staff_extent (Element const &e)
{
if (e.prob)
return prob_extent (e.prob);
}
Interval
-Page_layout_problem::last_staff_extent (Element const& e)
+Page_layout_problem::last_staff_extent (Element const &e)
{
if (e.prob)
return prob_extent (e.prob);
}
SCM
-Page_layout_problem::get_details (Element const& elt)
+Page_layout_problem::get_details (Element const &elt)
{
if (elt.staves.empty ())
return SCM_EOL;
SCM
Page_layout_problem::get_details (Grob *g)
{
- Grob *left_bound = dynamic_cast<Spanner*> (g)->get_bound (LEFT);
+ Grob *left_bound = dynamic_cast<Spanner *> (g)->get_bound (LEFT);
return left_bound->get_property ("line-break-system-details");
}
}
bool
-Page_layout_problem::read_spacing_spec (SCM spec, Real* dest, SCM sym)
+Page_layout_problem::read_spacing_spec (SCM spec, Real *dest, SCM sym)
{
SCM pair = scm_sloppy_assq (sym, spec);
if (scm_is_pair (pair) && scm_is_number (scm_cdr (pair)))
Real
Page_layout_problem::get_fixed_spacing (Grob *before, Grob *after, int spaceable_index, bool pure, int start, int end)
{
- Spanner *after_sp = dynamic_cast<Spanner*> (after);
+ Spanner *after_sp = dynamic_cast<Spanner *> (after);
SCM cache_symbol = (is_spaceable (before) && is_spaceable (after))
- ? ly_symbol2scm ("spaceable-fixed-spacing")
- : ly_symbol2scm ("loose-fixed-spacing");
+ ? ly_symbol2scm ("spaceable-fixed-spacing")
+ : ly_symbol2scm ("loose-fixed-spacing");
if (pure)
{
// The result of this function doesn't depend on "end," so we can reduce the
// size of the cache by ignoring it.
SCM cached = after_sp->get_cached_pure_property (cache_symbol, start, 0);
if (scm_is_number (cached))
- return robust_scm2double (cached, 0.0);
+ return robust_scm2double (cached, 0.0);
}
- SCM spec = Page_layout_problem::get_spacing_spec (before, after, pure, start, end);
Real ret = -infinity_f;
- Real stretchability = 0;
- if (Page_layout_problem::read_spacing_spec (spec, &stretchability, ly_symbol2scm ("stretchability"))
- && stretchability == 0)
- Page_layout_problem::read_spacing_spec (spec, &ret, ly_symbol2scm ("basic-distance"));
// If we're pure, then paper-columns have not had their systems set,
// and so elts[i]->get_system () is unreliable.
SCM details = left_bound->get_property ("line-break-system-details");
SCM manual_dists = ly_assoc_get (ly_symbol2scm ("alignment-distances"), details, SCM_EOL);
if (scm_is_pair (manual_dists))
- {
- SCM forced = robust_list_ref (spaceable_index - 1, manual_dists);
- if (scm_is_number (forced))
- ret = max (ret, scm_to_double (forced));
- }
+ {
+ SCM forced = robust_list_ref (spaceable_index - 1, manual_dists);
+ if (scm_is_number (forced))
+ ret = max (ret, scm_to_double (forced));
+ }
}
// Cache the result. As above, we ignore "end."
if (pure)
after_sp->cache_pure_property (cache_symbol, start, 0, scm_from_double (ret));
-
+
return ret;
}
if (is_spaceable (before))
{
if (is_spaceable (after))
- return before->get_maybe_pure_property ("staff-staff-spacing", pure, start, end);
+ return before->get_maybe_pure_property ("staff-staff-spacing", pure, start, end);
else
- {
- Direction affinity = to_dir (after->get_maybe_pure_property ("staff-affinity", pure, start, end));
- return (affinity == DOWN)
- ? add_stretchability (after->get_maybe_pure_property ("nonstaff-unrelatedstaff-spacing", pure, start, end),
- LARGE_STRETCH)
- : after->get_maybe_pure_property ("nonstaff-relatedstaff-spacing", pure, start, end);
- }
+ {
+ Direction affinity = to_dir (after->get_maybe_pure_property ("staff-affinity", pure, start, end));
+ return (affinity == DOWN)
+ ? add_stretchability (after->get_maybe_pure_property ("nonstaff-unrelatedstaff-spacing", pure, start, end),
+ LARGE_STRETCH)
+ : after->get_maybe_pure_property ("nonstaff-relatedstaff-spacing", pure, start, end);
+ }
}
else
{
if (is_spaceable (after))
- {
- Direction affinity = to_dir (before->get_maybe_pure_property ("staff-affinity", pure, start, end));
- return (affinity == UP)
- ? add_stretchability (before->get_maybe_pure_property ("nonstaff-unrelatedstaff-spacing", pure, start, end),
- LARGE_STRETCH)
- : before->get_maybe_pure_property ("nonstaff-relatedstaff-spacing", pure, start, end);
- }
+ {
+ Direction affinity = to_dir (before->get_maybe_pure_property ("staff-affinity", pure, start, end));
+ return (affinity == UP)
+ ? add_stretchability (before->get_maybe_pure_property ("nonstaff-unrelatedstaff-spacing", pure, start, end),
+ LARGE_STRETCH)
+ : before->get_maybe_pure_property ("nonstaff-relatedstaff-spacing", pure, start, end);
+ }
else
- {
- Direction before_affinity = to_dir (before->get_maybe_pure_property ("staff-affinity", pure, start, end));
- Direction after_affinity = to_dir (after->get_maybe_pure_property ("staff-affinity", pure, start, end));
- static bool warned = false;
- if (after_affinity > before_affinity
- && !warned && !pure)
- {
- warning (_ ("staff-affinities should only decrease"));
- warned = true;
- }
- if (before_affinity != UP)
- return before->get_maybe_pure_property ("nonstaff-nonstaff-spacing", pure, start, end);
- else if (after_affinity != DOWN)
- return before->get_maybe_pure_property ("nonstaff-nonstaff-spacing", pure, start, end);
- return add_stretchability (before->get_maybe_pure_property ("nonstaff-unrelatedstaff-spacing", pure, start, end),
- LARGE_STRETCH);
- }
+ {
+ Direction before_affinity = to_dir (before->get_maybe_pure_property ("staff-affinity", pure, start, end));
+ Direction after_affinity = to_dir (after->get_maybe_pure_property ("staff-affinity", pure, start, end));
+ static bool warned = false;
+ if (after_affinity > before_affinity
+ && !warned && !pure)
+ {
+ warning (_ ("staff-affinities should only decrease"));
+ warned = true;
+ }
+ if (before_affinity != UP)
+ return before->get_maybe_pure_property ("nonstaff-nonstaff-spacing", pure, start, end);
+ else if (after_affinity != DOWN)
+ return before->get_maybe_pure_property ("nonstaff-nonstaff-spacing", pure, start, end);
+ return add_stretchability (before->get_maybe_pure_property ("nonstaff-unrelatedstaff-spacing", pure, start, end),
+ LARGE_STRETCH);
+ }
}
assert (0);
}
void
-Page_layout_problem::alter_spring_from_spacing_spec (SCM spec, Spring* spring)
+Page_layout_problem::alter_spring_from_spacing_spec (SCM spec, Spring *spring)
{
Real space;
Real stretch;
spring->set_default_strength ();
if (read_spacing_spec (spec, &stretch, ly_symbol2scm ("stretchability")))
- {
- spring->set_inverse_stretch_strength (stretch);
- spring->set_inverse_compress_strength (stretch);
- }
+ spring->set_inverse_stretch_strength (stretch);
}
-vector<Grob*>
-Page_layout_problem::filter_dead_elements (vector<Grob*> const& input)
+vector<Grob *>
+Page_layout_problem::filter_dead_elements (vector<Grob *> const &input)
{
- vector<Grob*> output;
+ vector<Grob *> output;
for (vsize i = 0; i < input.size (); ++i)
{
- if (Hara_kiri_group_spanner::has_interface (input[i]))
- Hara_kiri_group_spanner::consider_suicide (input[i]);
+ if (has_interface<Hara_kiri_group_spanner> (input[i]))
+ Hara_kiri_group_spanner::consider_suicide (input[i]);
if (input[i]->is_live ())
- output.push_back (input[i]);
+ output.push_back (input[i]);
}
return output;