2 spacing-interface.cc -- functionality that is shared between Note_spacing
5 source file of the GNU LilyPond music typesetter
7 (c) 2007 Joe Neeman <joeneeman@gmail.com>
10 #include "spacing-interface.hh"
13 #include "grob-array.hh"
15 #include "note-column.hh"
16 #include "pointer-group-interface.hh"
17 #include "paper-column.hh"
18 #include "separation-item.hh"
21 /* return the minimum distance between the left-items and the right-items of
22 this spacing object */
24 Spacing_interface::minimum_distance (Grob *me)
26 /* the logic here is a little convoluted.
27 A {Staff,Note}_spacing doesn't copy {left-,right-}items when it clones,
28 so in order to find the separation items, we need to use the original
29 spacing grob. But once we find the separation items, we need to get back
32 FIXME: this only works for the left column. There is only one spacing
33 grob for the original and non-original right column and we have no way
34 to tell which one we need */
36 Grob *orig = me->original () ? me->original () : me;
37 Direction break_dir = dynamic_cast<Item*> (me)->break_status_dir ();
38 Drul_array<Skyline> skylines = Drul_array<Skyline> (Skyline (RIGHT), Skyline (LEFT));
39 Drul_array<vector<Grob*> > items (ly_scm2link_array (orig->get_object ("left-items")),
40 ly_scm2link_array (orig->get_object ("right-items")));
45 for (vsize i = 0; i < items[d].size (); i++)
47 Grob *g = items[d][i];
49 if (Item *it = dynamic_cast<Item*> (g))
50 if (Grob *piece = it->find_prebroken_piece (break_dir))
53 if (Separation_item::has_interface (g))
55 SCM sky_scm = g->get_property ("horizontal-skylines");
56 Skyline_pair *sky = Skyline_pair::unsmob (sky_scm);
58 skylines[d].merge ((*sky)[-d]);
60 programming_error ("separation item has no skyline");
62 if (d == RIGHT && items[LEFT].size ())
63 skylines[d].merge (Separation_item::conditional_skyline (items[d][i], items[LEFT][0]));
67 while (flip (&d) != LEFT);
69 return skylines[LEFT].distance (skylines[RIGHT]);
73 Compute the column of the right-items. This is a big function,
74 since RIGHT-ITEMS may span more columns (eg. if a clef is inserted,
75 this will add a new column to RIGHT-ITEMS. Here we look at the
76 columns, and return the left-most. If there are multiple columns, we
80 Spacing_interface::right_column (Grob *me)
85 Grob_array *a = unsmob_grob_array (me->get_object ("right-items"));
87 int min_rank = INT_MAX;
89 for (vsize i = 0; a && i < a->size (); i++)
91 Item *ri = a->item (i);
92 Item *col = ri->get_column ();
94 int rank = Paper_column::get_rank (col);
108 vector<Grob*> &right = a->array_reference ();
109 for (vsize i = right.size (); i--;)
111 if (dynamic_cast<Item *> (right[i])->get_column () != mincol)
112 right.erase (right.begin () + i);
120 Spacing_interface::left_column (Grob *me)
125 return dynamic_cast<Item *> (me)->get_column ();
129 get_note_columns (vector<Grob*> const &elts)
133 for (vsize i = 0; i < elts.size (); i++)
134 if (Note_column::has_interface (elts[i]))
135 ret.push_back (dynamic_cast<Item*> (elts[i]));
141 Spacing_interface::right_note_columns (Grob *me)
143 extract_grob_set (me, "right-items", elts);
144 return get_note_columns (elts);
148 Spacing_interface::left_note_columns (Grob *me)
150 extract_grob_set (me, "left-items", elts);
151 return get_note_columns (elts);
154 ADD_INTERFACE (Spacing_interface,
155 "This object calculates the desired and minimum distances between two columns.",