/*
This file is part of LilyPond, the GNU music typesetter.
- Copyright (C) 1996--2011 Han-Wen Nienhuys <hanwen@xs4all.nl>
+ Copyright (C) 1996--2014 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 "all-font-metrics.hh"
#include "axis-group-interface.hh"
#include "break-align-interface.hh"
-#include "column-description.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 "system-start-delimiter.hh"
#include "text-interface.hh"
#include "warn.hh"
#include "unpure-pure-container.hh"
SCM ret = SCM_EOL;
for (vsize i = 0; i < broken_intos_.size (); i++)
ret = scm_cons (broken_intos_[i]->self_scm (), ret);
- return scm_reverse (ret);
+ return scm_reverse_x (ret, SCM_EOL);
}
SCM
scm_vector_set_x (lines, scm_from_int (i),
system->get_paper_system ());
- debug_output (to_string (i) + "]", false);
+ debug_output (::to_string (i) + "]", false);
}
return lines;
}
if (Item *item = dynamic_cast<Item *>(at_bat))
{
+ /*
+ We use this to weed out grobs that fall at the end
+ of the line when we want grobs at the beginning.
+ */
+ end_of_line_visible = item->break_status_dir () == LEFT;
+
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
continue;
if (!at_bat->is_live ())
continue;
+ /*
+ TODO
+ Sometimes, there are duplicate entries in the all_elements_
+ list. In a separate patch, this practice should be squashed
+ so that the check below can be eliminated.
+ */
+ if (find (out.begin (), out.end (), at_bat) != out.end ())
+ continue;
out.push_back (at_bat);
}
bool
grob_2D_less (Grob *g1, Grob *g2)
{
- int sri[] = {0,0};
+ int sri[] = {0, 0};
Grob *gs[] = {g1, g2};
for (int i = 0; i < 2; i++)
if (sri[0] == sri[1])
return Grob::vertical_less (gs[0], gs[1]);
- return sri[0] < sri[1];
+ return sri[0] < sri[1];
}
MAKE_SCHEME_CALLBACK (System, footnotes_before_line_breaking, 1);
return grobs_scm;
}
+MAKE_SCHEME_CALLBACK (System, vertical_skyline_elements, 1);
+SCM
+System::vertical_skyline_elements (SCM smob)
+{
+ Grob *me_grob = unsmob_grob (smob);
+ vector<Grob *> vertical_skyline_grobs;
+ extract_grob_set (me_grob, "elements", my_elts);
+ for (vsize i = 0; i < my_elts.size (); i++)
+ if (System_start_delimiter::has_interface (my_elts[i]))
+ vertical_skyline_grobs.push_back (my_elts[i]);
+
+ System *me = dynamic_cast<System *> (me_grob);
+ Grob *align = unsmob_grob (me->get_object ("vertical-alignment"));
+ if (!align)
+ {
+ SCM grobs_scm = Grob_array::make_array ();
+ unsmob_grob_array (grobs_scm)->set_array (vertical_skyline_grobs);
+ return grobs_scm;
+ }
+
+ extract_grob_set (align, "elements", elts);
+
+ for (vsize i = 0; i < elts.size (); i++)
+ if (Hara_kiri_group_spanner::has_interface (elts[i]))
+ vertical_skyline_grobs.push_back (elts[i]);
+
+ SCM grobs_scm = Grob_array::make_array ();
+ unsmob_grob_array (grobs_scm)->set_array (vertical_skyline_grobs);
+ return grobs_scm;
+}
+
void
System::break_into_pieces (vector<Column_x_positions> const &breaking)
{
anyway. */
vector<Grob *> all_elts_sorted (all_elements_->array ());
- vector_sort (all_elts_sorted, std::less<Grob *> ());
- uniq (all_elts_sorted);
+ uniquify (all_elts_sorted);
this->get_stencil ();
for (vsize i = all_elts_sorted.size (); i--;)
{
pl->set_property ("page-break-penalty", right_bound->get_property ("page-break-penalty"));
pl->set_property ("page-turn-penalty", right_bound->get_property ("page-turn-penalty"));
- if (right_bound->original () == dynamic_cast<System*> (original ())->get_bound (RIGHT))
+ if (right_bound->original () == dynamic_cast<System *> (original ())->get_bound (RIGHT))
pl->set_property ("last-in-score", SCM_BOOL_T);
Interval staff_refpoints;
- if (Grob *align = get_vertical_alignment ())
+ if (Grob *align = unsmob_grob (get_object ("vertical-alignment")))
{
extract_grob_set (align, "elements", staves);
for (vsize i = 0; i < staves.size (); i++)
return dynamic_cast<System *> (system_grob);
}
-Grob *
-System::get_vertical_alignment ()
+MAKE_SCHEME_CALLBACK (System, get_vertical_alignment, 1);
+SCM
+System::get_vertical_alignment (SCM smob)
{
- extract_grob_set (this, "elements", elts);
+ Grob *me = unsmob_grob (smob);
+ extract_grob_set (me, "elements", elts);
Grob *ret = 0;
for (vsize i = 0; i < elts.size (); i++)
if (Align_interface::has_interface (elts[i]))
{
if (ret)
- programming_error ("found multiple vertical alignments in this system");
+ me->programming_error ("found multiple vertical alignments in this system");
ret = elts[i];
}
if (!ret)
- programming_error ("didn't find a vertical alignment in this system");
- return ret;
+ {
+ me->programming_error ("didn't find a vertical alignment in this system");
+ return SCM_EOL;
+ }
+ return ret->self_scm ();
}
// Finds the furthest staff in the given direction whose x-extent
Grob *
System::get_extremal_staff (Direction dir, Interval const &iv)
{
- Grob *align = get_vertical_alignment ();
+ Grob *align = unsmob_grob (get_object ("vertical-alignment"));
if (!align)
return 0;
return 0;
}
-vector<Simple_spacer>
-System::get_simple_spacers (Real line_len, Real indent, bool ragged)
+// Finds the neighboring staff in the given direction over bounds
+Grob *
+System::get_neighboring_staff (Direction dir, Grob *vertical_axis_group, Interval_t<int> bounds)
{
- if (!simple_spacers_.size ())
- gen_simple_spacers (line_len, indent, ragged);
-
- return simple_spacers_;
-}
+ Grob *align = unsmob_grob (get_object ("vertical-alignment"));
+ if (!align)
+ return 0;
-void
-System::gen_simple_spacers (Real line_len, Real indent, bool ragged)
-{
- vector<vsize> breaks;
- vector<Grob *> non_loose;
- vector<Column_description> cols;
- SCM force_break = ly_symbol2scm ("force");
- vector<Grob *> columns = used_columns ();
-
- for (vsize i = 0; i < columns.size (); i++)
- if (!Paper_column::is_loose (columns[i])
- || Paper_column::is_breakable (columns[i]))
- non_loose.push_back (columns[i]);
-
- breaks.clear ();
- breaks.push_back (0);
- cols.push_back (Column_description ());
- for (vsize i = 1; i + 1 < non_loose.size (); i++)
- {
- if (Paper_column::is_breakable (non_loose[i]))
- breaks.push_back (cols.size ());
+ extract_grob_set (align, "elements", elts);
+ vsize start = (dir == UP) ? 0 : elts.size () - 1;
+ vsize end = (dir == UP) ? elts.size () : VPOS;
- cols.push_back (Column_description::get_column_description (non_loose, i, false));
- }
- breaks.push_back (cols.size ());
- simple_spacers_.resize (breaks.size () * breaks.size (), Simple_spacer ());
+ Grob *out = 0;
- for (vsize b = 0; b + 1 < breaks.size (); b++)
+ for (vsize i = start; i != end; i += dir)
{
- cols[breaks[b]] = Column_description::get_column_description (non_loose, breaks[b], true);
- vsize st = breaks[b];
+ if (elts[i] == vertical_axis_group)
+ return out;
- for (vsize c = b + 1; c < breaks.size (); c++)
- {
- vsize end = breaks[c];
- Simple_spacer spacer;
-
- for (vsize i = breaks[b]; i < end - 1; i++)
- spacer.add_spring (cols[i].spring_);
- spacer.add_spring (cols[end - 1].end_spring_);
+ if (Hara_kiri_group_spanner::has_interface (elts[i]))
+ Hara_kiri_group_spanner::consider_suicide (elts[i]);
- for (vsize i = breaks[b]; i < end; i++)
- {
- for (vsize r = 0; r < cols[i].rods_.size (); r++)
- if (cols[i].rods_[r].r_ < end)
- spacer.add_rod (i - st, cols[i].rods_[r].r_ - st, cols[i].rods_[r].dist_);
- for (vsize r = 0; r < cols[i].end_rods_.size (); r++)
- if (cols[i].end_rods_[r].r_ == end)
- spacer.add_rod (i - st, end - st, cols[i].end_rods_[r].dist_);
- if (!cols[i].keep_inside_line_.is_empty ())
- {
- spacer.add_rod (i - st, end - st, cols[i].keep_inside_line_[RIGHT]);
- spacer.add_rod (0, i - st, -cols[i].keep_inside_line_[LEFT]);
- }
- }
- spacer.solve ((b == 0) ? line_len - indent : line_len, ragged);
- spacer.minimal_ = c == b + 1;
- simple_spacers_[b * breaks.size () + c] = spacer;
-
- if (!spacer.fits ()
- || (end < cols.size ()
- && cols[end].break_permission_ == force_break))
- break;
- }
+ bounds.intersect (elts[i]->spanned_rank_interval ());
+ if (elts[i]->is_live () && !bounds.is_empty ())
+ out = elts[i];
}
+
+ return 0;
}
Interval
System::pure_refpoint_extent (vsize start, vsize end)
{
Interval ret;
- Grob *alignment = get_vertical_alignment ();
+ Grob *alignment = unsmob_grob (get_object ("vertical-alignment"));
if (!alignment)
return Interval ();
Interval
System::part_of_line_pure_height (vsize start, vsize end, bool begin)
{
- Grob *alignment = get_vertical_alignment ();
+ Grob *alignment = unsmob_grob (get_object ("vertical-alignment"));
if (!alignment)
return Interval ();
extract_grob_set (me, "elements", elts);
vector<Grob *> relevant_grobs;
- SCM pure_relevant_p = ly_lily_module_constant ("pure-relevant?");
for (vsize i = 0; i < elts.size (); ++i)
{
if (!Axis_group_interface::has_interface (elts[i]))
{
- if (to_boolean (scm_apply_1 (pure_relevant_p, elts[i]->self_scm (), SCM_EOL)))
- relevant_grobs.push_back (elts[i]);
+ relevant_grobs.push_back (elts[i]);
if (Item *it = dynamic_cast<Item *> (elts[i]))
{
- Direction d = LEFT;
- do
+ for (LEFT_and_RIGHT (d))
{
Item *piece = it->find_prebroken_piece (d);
- if (piece && to_boolean (scm_apply_1 (pure_relevant_p, piece->self_scm (), SCM_EOL)))
+ if (piece && piece->is_live ())
relevant_grobs.push_back (piece);
}
- while (flip (&d) != LEFT);
}
}
}
return pure ? get_pure_bound (d, start, end) : get_bound (d);
}
-enum {
+enum
+{
SPACEABLE_STAVES,
NONSPACEABLE_STAVES,
ALL_STAVES
static SCM
get_maybe_spaceable_staves (SCM smob, int filter)
{
- System *me = dynamic_cast<System*> (unsmob_grob (smob));
- Grob *align = me->get_vertical_alignment ();
+ System *me = dynamic_cast<System *> (unsmob_grob (smob));
+ Grob *align = unsmob_grob (me->get_object ("vertical_alignment"));
SCM ret = SCM_EOL;
if (align)
for (vsize i = 0; i < staves.size (); ++i)
{
bool spaceable = Page_layout_problem::is_spaceable (staves[i]);
- if (staves[i]->is_live () &&
- ((filter == ALL_STAVES)
- || (filter == SPACEABLE_STAVES && spaceable)
- || (filter == NONSPACEABLE_STAVES && !spaceable)))
+ if (staves[i]->is_live ()
+ && ((filter == ALL_STAVES)
+ || (filter == SPACEABLE_STAVES && spaceable)
+ || (filter == NONSPACEABLE_STAVES && !spaceable)))
{
*tail = scm_cons (staves[i]->self_scm (), SCM_EOL);
tail = SCM_CDRLOC (*tail);
return get_maybe_spaceable_staves (smob, NONSPACEABLE_STAVES);
}
-
ADD_INTERFACE (System,
"This is the top-level object: Each object in a score"
" ultimately has a @code{System} object as its X and"
"in-note-stencil "
"labels "
"pure-Y-extent "
- "skyline-horizontal-padding "
+ "vertical-alignment "
);