]> git.donarmstrong.com Git - lilypond.git/blob - lily/spacing-interface.cc
use the new spacing-interface stuff in staff-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             skylines[d].merge ((*sky)[-d]);
39             
40             if (d == RIGHT && items[LEFT].size ())
41               skylines[d].merge (Separation_item::conditional_skyline (items[d][i], items[LEFT][0]));
42           }
43     }
44   while (flip (&d) != LEFT);
45
46   return skylines[LEFT].distance (skylines[RIGHT]);
47 }
48
49 /*
50   Compute the column of the right-items.  This is a big function,
51   since RIGHT-ITEMS may span more columns (eg. if a clef is inserted,
52   this will add a new column to RIGHT-ITEMS. Here we look at the
53   columns, and return the left-most. If there are multiple columns, we
54   prune RIGHT-ITEMS.
55 */
56 Item *
57 Spacing_interface::right_column (Grob *me)
58 {
59   if (!me->is_live ())
60     return 0;
61
62   Grob_array *a = unsmob_grob_array (me->get_object ("right-items"));
63   Item *mincol = 0;
64   int min_rank = INT_MAX;
65   bool prune = false;
66   for (vsize i = 0; a && i < a->size (); i++)
67     {
68       Item *ri = a->item (i);
69       Item *col = ri->get_column ();
70
71       int rank = Paper_column::get_rank (col);
72
73       if (rank < min_rank)
74         {
75           min_rank = rank;
76           if (mincol)
77             prune = true;
78
79           mincol = col;
80         }
81     }
82
83   if (prune && a)
84     {
85       vector<Grob*> &right = a->array_reference ();
86       for (vsize i = right.size (); i--;)
87         {
88           if (dynamic_cast<Item *> (right[i])->get_column () != mincol)
89             right.erase (right.begin () + i);
90         }
91     }
92
93   return mincol;
94 }
95
96 Item *
97 Spacing_interface::left_column (Grob *me)
98 {
99   if (!me->is_live ())
100     return 0;
101
102   return dynamic_cast<Item *> (me)->get_column ();
103 }
104
105 static vector<Item*>
106 get_note_columns (vector<Grob*> const &elts)
107 {
108   vector<Item*> ret;
109
110   for (vsize i = 0; i < elts.size (); i++)
111     if (Note_column::has_interface (elts[i]))
112       ret.push_back (dynamic_cast<Item*> (elts[i]));
113
114   return ret;
115 }
116
117 vector<Item*>
118 Spacing_interface::right_note_columns (Grob *me)
119 {
120   extract_grob_set (me, "right-items", elts);
121   return get_note_columns (elts);
122 }
123
124 vector<Item*>
125 Spacing_interface::left_note_columns (Grob *me)
126 {
127   extract_grob_set (me, "left-items", elts);
128   return get_note_columns (elts);
129 }
130
131 ADD_INTERFACE (Spacing_interface,
132                "This object calculates the desired and minimum distances between two columns.",
133
134                "left-items "
135                "right-items "
136                );