/*
This file is part of LilyPond, the GNU music typesetter.
- Copyright (C) 1996--2010 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ Copyright (C) 1996--2011 Han-Wen Nienhuys <hanwen@xs4all.nl>
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 "align-interface.hh"
#include "all-font-metrics.hh"
#include "axis-group-interface.hh"
+#include "break-align-interface.hh"
#include "grob-array.hh"
#include "hara-kiri-group-spanner.hh"
#include "international.hh"
#include "pointer-group-interface.hh"
#include "skyline-pair.hh"
#include "staff-symbol-referencer.hh"
+#include "text-interface.hh"
#include "warn.hh"
System::System (System const &src)
all_elements_ = 0;
pscore_ = 0;
rank_ = 0;
+ checked_footnotes_ = false;
init_elements ();
}
{
all_elements_ = 0;
rank_ = 0;
+ checked_footnotes_ = false;
init_elements ();
}
Grob *g = all_elts[j];
g->fixup_refpoint ();
}
-
+
count += all_elts.size ();
}
return lines;
}
+void
+System::populate_footnote_grob_vector ()
+{
+ extract_grob_set (this, "all-elements", all_elts);
+ for (vsize i = 0; i < all_elts.size (); i++)
+ if (all_elts[i]->internal_has_interface (ly_symbol2scm ("footnote-interface")))
+ footnote_grobs_.push_back (all_elts[i]);
+
+ sort (footnote_grobs_.begin (), footnote_grobs_.end (), Grob::less);
+ checked_footnotes_ = true;
+}
+
+void
+System::get_footnote_grobs_in_range (vector<Grob *> &out, vsize start, vsize end)
+{
+ if (!checked_footnotes_)
+ populate_footnote_grob_vector ();
+
+ for (vsize i = 0; i < footnote_grobs_.size (); i++)
+ {
+ int pos = footnote_grobs_[i]->spanned_rank_interval ()[LEFT];
+ bool end_of_line_visible = true;
+ if (Spanner *s = dynamic_cast<Spanner *>(footnote_grobs_[i]))
+ {
+ Direction spanner_placement = robust_scm2dir (s->get_property ("spanner-placement"), LEFT);
+ if (spanner_placement == CENTER)
+ spanner_placement = LEFT;
+
+ pos = s->spanned_rank_interval ()[spanner_placement];
+ }
+
+ if (Item *item = dynamic_cast<Item *>(footnote_grobs_[i]))
+ {
+ if (!Item::break_visible (item))
+ continue;
+ // safeguard to bring down the column rank so that end of line footnotes show up on the correct line
+ end_of_line_visible = (LEFT == item->break_status_dir ());
+ }
+
+ if (pos < int (start))
+ continue;
+ if (pos > int (end))
+ break;
+ if (pos == int (start) && end_of_line_visible)
+ continue;
+ if (pos == int (end) && !end_of_line_visible)
+ continue;
+ if (!footnote_grobs_[i]->is_live ())
+ continue;
+
+ out.push_back (footnote_grobs_[i]);
+ }
+}
+
+vector<Stencil *>
+System::get_footnotes_in_range (vsize start, vsize end)
+{
+ vector<Grob *> footnote_grobs;
+ get_footnote_grobs_in_range (footnote_grobs, start, end);
+ vector<Stencil *> out;
+
+ for (vsize i = 0; i < footnote_grobs.size (); i++)
+ {
+ SCM footnote_markup = footnote_grobs[i]->get_property ("footnote-text");
+
+ if (!Text_interface::is_markup (footnote_markup))
+ continue;
+
+ SCM props = scm_call_1 (ly_lily_module_constant ("layout-extract-page-properties"),
+ pscore_->layout ()->self_scm ());
+
+ SCM footnote_stl = Text_interface::interpret_markup (pscore_->layout ()->self_scm (),
+ props, footnote_markup);
+
+ Stencil *footnote_stencil = unsmob_stencil (footnote_stl);
+ out.push_back (footnote_stencil);
+ }
+
+ return out;
+}
+
+vsize
+System::num_footnotes ()
+{
+ return footnote_grobs_.size ();
+}
+
+vector<Grob *>*
+System::footnote_grobs ()
+{
+ return &footnote_grobs_;
+}
+
void
System::break_into_pieces (vector<Column_x_positions> const &breaking)
{
Interval iv (pure_height (this, st, end));
system->set_property ("pure-Y-extent", ly_interval2scm (iv));
+ get_footnote_grobs_in_range (system->footnote_grobs_, st, end);
+
system->set_bound (LEFT, c[0]);
system->set_bound (RIGHT, c.back ());
SCM system_labels = SCM_EOL;
c[j]->translate_axis (breaking[i].config_[j], X_AXIS);
dynamic_cast<Paper_column *> (c[j])->set_system (system);
/* collect the column labels */
- SCM col_labels = c[j]->get_property ("labels");
- if (scm_is_pair (col_labels))
- system_labels = scm_append (scm_list_2 (col_labels, system_labels));
+ collect_labels (c[j], &system_labels);
}
+ /*
+ Collect labels from any loose columns too: theses will be set on
+ an empty bar line or a column which is otherwise unused mid-line
+ */
+ vector<Grob *> loose (breaking[i].loose_cols_);
+ for (vsize j = 0; j < loose.size (); j++)
+ collect_labels (loose[j], &system_labels);
+
system->set_property ("labels", system_labels);
set_loose_columns (system, &breaking[i]);
}
}
+void
+System::collect_labels (Grob const *col, SCM *labels)
+{
+ SCM col_labels = col->get_property ("labels");
+ if (scm_is_pair (col_labels))
+ *labels = scm_append (scm_list_2 (col_labels, *labels));
+}
+
void
System::add_column (Paper_column *p)
{
return Interval ();
extract_grob_set (alignment, "elements", staves);
- vector<Real> offsets = Align_interface::get_minimum_translations (alignment, staves, Y_AXIS, true, start, end);
+ vector<Real> offsets = Align_interface::get_pure_minimum_translations (alignment, staves, Y_AXIS, start, end);
for (vsize i = 0; i < offsets.size (); ++i)
if (Page_layout_problem::is_spaceable (staves[i]))
return Interval ();
extract_grob_set (alignment, "elements", staves);
- vector<Real> offsets = Align_interface::get_minimum_translations (alignment, staves, Y_AXIS, true, start, end);
+ vector<Real> offsets = Align_interface::get_pure_minimum_translations (alignment, staves, Y_AXIS, start, end);
Interval ret;
for (vsize i = 0; i < staves.size (); ++i)
return ly_interval2scm (begin);
}
+Grob*
+System::get_pure_bound (Direction d, int start, int end)
+{
+ vector<vsize> ranks = pscore_->get_break_ranks ();
+ vector<vsize> indices = pscore_->get_break_indices ();
+ vector<Grob*> cols = pscore_->get_columns ();
+
+ vsize target_rank = (d == LEFT ? start : end);
+ vector<vsize>::const_iterator i =
+ lower_bound (ranks.begin (), ranks.end (), target_rank, std::less<vsize> ());
+
+ if (i != ranks.end () && (*i) == target_rank)
+ return cols[indices[i - ranks.begin ()]];
+ else
+ return 0;
+}
+
+Grob*
+System::get_maybe_pure_bound (Direction d, bool pure, int start, int end)
+{
+ return pure ? get_pure_bound (d, start, end) : get_bound (d);
+}
+
ADD_INTERFACE (System,
"This is the top-level object: Each object in a score"
" ultimately has a @code{System} object as its X and"