]> git.donarmstrong.com Git - lilypond.git/blob - lily/spacing-interface.cc
cleanups in note-spacing
[lilypond.git] / lily / spacing-interface.cc
1 /*
2   spacing-interface.cc -- functionality that is shared between Note_spacing
3   and Staff_spacing
4
5   source file of the GNU LilyPond music typesetter
6
7   (c) 2007 Joe Neeman <joeneeman@gmail.com>
8 */
9
10 #include "spacing-interface.hh"
11
12 #include "grob.hh"
13 #include "grob-array.hh"
14 #include "item.hh"
15 #include "note-column.hh"
16 #include "pointer-group-interface.hh"
17 #include "paper-column.hh"
18 #include "separation-item.hh"
19 #include "skyline.hh"
20
21 /* return the minimum distance between the left-items and the right-items of
22    this spacing object */
23 Real
24 Spacing_interface::minimum_distance (Grob *me)
25 {
26   Drul_array<Skyline> skylines = Drul_array<Skyline> (Skyline (RIGHT), Skyline (LEFT));
27   Drul_array<vector<Grob*> > items (ly_scm2link_array (me->get_object ("left-items")),
28                                     ly_scm2link_array (me->get_object ("right-items")));
29
30   Direction d = LEFT;
31   do
32     {
33       for (vsize i = 0; i < items[d].size (); i++)
34         if (Separation_item::has_interface (items[d][i]))
35           {
36             SCM sky_scm = items[d][i]->get_property ("horizontal-skylines");
37             Skyline_pair *sky = Skyline_pair::unsmob (sky_scm);
38             if (sky)
39               skylines[d].merge ((*sky)[-d]);
40             else
41               programming_error ("separation item has no skyline");
42             
43             if (d == RIGHT && items[LEFT].size ())
44               skylines[d].merge (Separation_item::conditional_skyline (items[d][i], items[LEFT][0]));
45           }
46     }
47   while (flip (&d) != LEFT);
48
49   return skylines[LEFT].distance (skylines[RIGHT]);
50 }
51
52 /*
53   Compute the column of the right-items.  This is a big function,
54   since RIGHT-ITEMS may span more columns (eg. if a clef is inserted,
55   this will add a new column to RIGHT-ITEMS. Here we look at the
56   columns, and return the left-most. If there are multiple columns, we
57   prune RIGHT-ITEMS.
58 */
59 Item *
60 Spacing_interface::right_column (Grob *me)
61 {
62   if (!me->is_live ())
63     return 0;
64
65   Grob_array *a = unsmob_grob_array (me->get_object ("right-items"));
66   Item *mincol = 0;
67   int min_rank = INT_MAX;
68   bool prune = false;
69   for (vsize i = 0; a && i < a->size (); i++)
70     {
71       Item *ri = a->item (i);
72       Item *col = ri->get_column ();
73
74       int rank = Paper_column::get_rank (col);
75
76       if (rank < min_rank)
77         {
78           min_rank = rank;
79           if (mincol)
80             prune = true;
81
82           mincol = col;
83         }
84     }
85
86   if (prune && a)
87     {
88       vector<Grob*> &right = a->array_reference ();
89       for (vsize i = right.size (); i--;)
90         {
91           if (dynamic_cast<Item *> (right[i])->get_column () != mincol)
92             right.erase (right.begin () + i);
93         }
94     }
95
96   return mincol;
97 }
98
99 Item *
100 Spacing_interface::left_column (Grob *me)
101 {
102   if (!me->is_live ())
103     return 0;
104
105   return dynamic_cast<Item *> (me)->get_column ();
106 }
107
108 static vector<Item*>
109 get_note_columns (vector<Grob*> const &elts)
110 {
111   vector<Item*> ret;
112
113   for (vsize i = 0; i < elts.size (); i++)
114     if (Note_column::has_interface (elts[i]))
115       ret.push_back (dynamic_cast<Item*> (elts[i]));
116
117   return ret;
118 }
119
120 vector<Item*>
121 Spacing_interface::right_note_columns (Grob *me)
122 {
123   extract_grob_set (me, "right-items", elts);
124   return get_note_columns (elts);
125 }
126
127 vector<Item*>
128 Spacing_interface::left_note_columns (Grob *me)
129 {
130   extract_grob_set (me, "left-items", elts);
131   return get_note_columns (elts);
132 }
133
134 ADD_INTERFACE (Spacing_interface,
135                "This object calculates the desired and minimum distances between two columns.",
136
137                "left-items "
138                "right-items "
139                );