#include "separation-item.hh"
#include "skyline.hh"
-/* return the minimum distance between the left-items and the right-items of
- this spacing object */
-Real
-Spacing_interface::minimum_distance (Grob *me)
+/* return the right-pointing skyline of the left-items and the left-pointing
+ skyline of the right-items (with the skyline of the left-items in
+ ret[LEFT]) */
+Drul_array<Skyline>
+Spacing_interface::skylines (Grob *me, Grob *right_col)
{
/* the logic here is a little convoluted.
- A {Staff,Note}_spacing doesn't copy {left-,right-}items when it clones,
+ A {Staff,Note}_spacing doesn't copy left-items when it clones,
so in order to find the separation items, we need to use the original
spacing grob. But once we find the separation items, we need to get back
the broken piece.
-
- FIXME: this only works for the left column. There is only one spacing
- grob for the original and non-original right column and we have no way
- to tell which one we need */
+ */
Grob *orig = me->original () ? me->original () : me;
- Direction break_dir = dynamic_cast<Item*> (me)->break_status_dir ();
+ Drul_array<Direction> break_dirs (dynamic_cast<Item*> (me)->break_status_dir (),
+ dynamic_cast<Item*> (right_col)->break_status_dir ());
Drul_array<Skyline> skylines = Drul_array<Skyline> (Skyline (RIGHT), Skyline (LEFT));
Drul_array<vector<Grob*> > items (ly_scm2link_array (orig->get_object ("left-items")),
ly_scm2link_array (orig->get_object ("right-items")));
Direction d = LEFT;
do
{
+ skylines[d].set_minimum_height (0.0);
+
for (vsize i = 0; i < items[d].size (); i++)
{
Grob *g = items[d][i];
- if (d == LEFT)
- if (Item *it = dynamic_cast<Item*> (g))
- if (Grob *piece = it->find_prebroken_piece (break_dir))
- g = piece;
+ if (Item *it = dynamic_cast<Item*> (g))
+ if (Grob *piece = it->find_prebroken_piece (break_dirs[d]))
+ g = piece;
if (Separation_item::has_interface (g))
{
}
while (flip (&d) != LEFT);
+ return skylines;
+}
+
+Real
+Spacing_interface::minimum_distance (Grob *me, Grob *right)
+{
+ Drul_array<Skyline> skylines = Spacing_interface::skylines (me, right);
+
return max (0.0, skylines[LEFT].distance (skylines[RIGHT]));
}
vector<Item*> ret;
for (vsize i = 0; i < elts.size (); i++)
- if (Note_column::has_interface (elts[i]))
- ret.push_back (dynamic_cast<Item*> (elts[i]));
+ {
+ if (Note_column::has_interface (elts[i]))
+ ret.push_back (dynamic_cast<Item*> (elts[i]));
+ else if (Separation_item::has_interface (elts[i]))
+ {
+ extract_grob_set (elts[i], "elements", more_elts);
+ vector<Item*> ncs = get_note_columns (more_elts);
+
+ ret.insert (ret.end (), ncs.begin (), ncs.end ());
+ }
+ }
return ret;
}
return get_note_columns (elts);
}
+/*
+ Try to find the break-aligned symbol that belongs on the D-side
+ of ME, sticking out in direction -D. The x size is put in LAST_EXT
+*/
+Grob *
+Spacing_interface::extremal_break_aligned_grob (Grob *me,
+ Direction d,
+ Direction break_dir,
+ Interval *last_ext)
+{
+ Grob *col = 0;
+ last_ext->set_empty ();
+ Grob *last_grob = 0;
+
+ extract_grob_set (me, d == LEFT ? "left-break-aligned" : "right-break-aligned", elts);
+
+ for (vsize i = elts.size (); i--;)
+ {
+ Item *break_item = dynamic_cast<Item*> (elts[i]);
+
+ if (break_item->break_status_dir () != break_dir)
+ break_item = break_item->find_prebroken_piece (break_dir);
+
+ if (!break_item || !scm_is_pair (break_item->get_property ("space-alist")))
+ continue;
+
+ if (!col)
+ col = dynamic_cast<Item*> (elts[0])->get_column ()->find_prebroken_piece (break_dir);
+
+ Interval ext = break_item->extent (col, X_AXIS);
+
+ if (ext.is_empty ())
+ continue;
+
+ if (!last_grob
+ || (last_grob && d * (ext[-d]- (*last_ext)[-d]) < 0))
+ {
+ *last_ext = ext;
+ last_grob = break_item;
+ }
+ }
+
+ return last_grob;
+}
+
+
ADD_INTERFACE (Spacing_interface,
"This object calculates the desired and minimum distances between two columns.",