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 skylines[d].set_minimum_height (0.0);
45 for (vsize i = 0; i < items[d].size (); i++)
47 Grob *g = items[d][i];
48 if (Item *it = dynamic_cast<Item*> (g))
49 if (Grob *piece = it->find_prebroken_piece (break_dirs[d]))
52 if (Separation_item::has_interface (g))
54 SCM sky_scm = g->get_property ("horizontal-skylines");
55 Skyline_pair *sky = Skyline_pair::unsmob (sky_scm);
57 skylines[d].merge ((*sky)[-d]);
59 programming_error ("separation item has no skyline");
61 if (d == RIGHT && items[LEFT].size ())
62 skylines[d].merge (Separation_item::conditional_skyline (items[d][i], items[LEFT][0]));
66 while (flip (&d) != LEFT);
68 return max (0.0, skylines[LEFT].distance (skylines[RIGHT]));
72 Compute the column of the right-items. This is a big function,
73 since RIGHT-ITEMS may span more columns (eg. if a clef is inserted,
74 this will add a new column to RIGHT-ITEMS. Here we look at the
75 columns, and return the left-most. If there are multiple columns, we
79 Spacing_interface::right_column (Grob *me)
84 Grob_array *a = unsmob_grob_array (me->get_object ("right-items"));
86 int min_rank = INT_MAX;
88 for (vsize i = 0; a && i < a->size (); i++)
90 Item *ri = a->item (i);
91 Item *col = ri->get_column ();
93 int rank = Paper_column::get_rank (col);
107 vector<Grob*> &right = a->array_reference ();
108 for (vsize i = right.size (); i--;)
110 if (dynamic_cast<Item *> (right[i])->get_column () != mincol)
111 right.erase (right.begin () + i);
119 Spacing_interface::left_column (Grob *me)
124 return dynamic_cast<Item *> (me)->get_column ();
128 get_note_columns (vector<Grob*> const &elts)
132 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]));
136 else if (Separation_item::has_interface (elts[i]))
138 extract_grob_set (elts[i], "elements", more_elts);
139 vector<Item*> ncs = get_note_columns (more_elts);
141 ret.insert (ret.end (), ncs.begin (), ncs.end ());
149 Spacing_interface::right_note_columns (Grob *me)
151 extract_grob_set (me, "right-items", elts);
152 return get_note_columns (elts);
156 Spacing_interface::left_note_columns (Grob *me)
158 extract_grob_set (me, "left-items", elts);
159 return get_note_columns (elts);
162 ADD_INTERFACE (Spacing_interface,
163 "This object calculates the desired and minimum distances between two columns.",