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, Grob *right_col)
26 /* the logic here is a little convoluted.
27 A {Staff,Note}_spacing doesn't copy left-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
33 Grob *orig = me->original () ? me->original () : me;
34 Drul_array<Direction> break_dirs (dynamic_cast<Item*> (me)->break_status_dir (),
35 dynamic_cast<Item*> (right_col)->break_status_dir ());
36 Drul_array<Skyline> skylines = Drul_array<Skyline> (Skyline (RIGHT), Skyline (LEFT));
37 Drul_array<vector<Grob*> > items (ly_scm2link_array (orig->get_object ("left-items")),
38 ly_scm2link_array (orig->get_object ("right-items")));
43 for (vsize i = 0; i < items[d].size (); i++)
45 Grob *g = items[d][i];
46 if (Item *it = dynamic_cast<Item*> (g))
47 if (Grob *piece = it->find_prebroken_piece (break_dirs[d]))
50 if (Separation_item::has_interface (g))
52 SCM sky_scm = g->get_property ("horizontal-skylines");
53 Skyline_pair *sky = Skyline_pair::unsmob (sky_scm);
55 skylines[d].merge ((*sky)[-d]);
57 programming_error ("separation item has no skyline");
59 if (d == RIGHT && items[LEFT].size ())
60 skylines[d].merge (Separation_item::conditional_skyline (items[d][i], items[LEFT][0]));
64 while (flip (&d) != LEFT);
66 return max (0.0, skylines[LEFT].distance (skylines[RIGHT]));
70 Compute the column of the right-items. This is a big function,
71 since RIGHT-ITEMS may span more columns (eg. if a clef is inserted,
72 this will add a new column to RIGHT-ITEMS. Here we look at the
73 columns, and return the left-most. If there are multiple columns, we
77 Spacing_interface::right_column (Grob *me)
82 Grob_array *a = unsmob_grob_array (me->get_object ("right-items"));
84 int min_rank = INT_MAX;
86 for (vsize i = 0; a && i < a->size (); i++)
88 Item *ri = a->item (i);
89 Item *col = ri->get_column ();
91 int rank = Paper_column::get_rank (col);
105 vector<Grob*> &right = a->array_reference ();
106 for (vsize i = right.size (); i--;)
108 if (dynamic_cast<Item *> (right[i])->get_column () != mincol)
109 right.erase (right.begin () + i);
117 Spacing_interface::left_column (Grob *me)
122 return dynamic_cast<Item *> (me)->get_column ();
126 get_note_columns (vector<Grob*> const &elts)
130 for (vsize i = 0; i < elts.size (); i++)
131 if (Note_column::has_interface (elts[i]))
132 ret.push_back (dynamic_cast<Item*> (elts[i]));
138 Spacing_interface::right_note_columns (Grob *me)
140 extract_grob_set (me, "right-items", elts);
141 return get_note_columns (elts);
145 Spacing_interface::left_note_columns (Grob *me)
147 extract_grob_set (me, "left-items", elts);
148 return get_note_columns (elts);
151 ADD_INTERFACE (Spacing_interface,
152 "This object calculates the desired and minimum distances between two columns.",