]> git.donarmstrong.com Git - lilypond.git/blob - lily/note-column.cc
* lily/include/lily-guile.hh: many new ly_ functions. Thanks to
[lilypond.git] / lily / note-column.cc
1 /*
2   note-column.cc -- implement Note_column
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1997--2004 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8 #include <math.h>               // ceil
9
10 #include "axis-group-interface.hh"
11 #include "note-column.hh"
12 #include "stem.hh"
13 #include "warn.hh"
14 #include "paper-def.hh"
15 #include "group-interface.hh"
16 #include "staff-symbol-referencer.hh"
17 #include "rest.hh"
18 #include "note-head.hh"
19 #include "accidental-placement.hh"
20
21 /*
22   TODO: figure out if we can prune this class. This is just an
23   annoying layer between (rest)collision & (note-head + stem)
24  */
25
26 bool
27 Note_column::has_rests (Grob*me) 
28 {
29   return unsmob_grob (me->get_property ("rest"));
30 }
31
32 int
33 Note_column::shift_compare (Grob *const &p1, Grob *const&p2)
34 {
35   SCM s1 = p1->get_property ("horizontal-shift");
36   SCM s2 = p2->get_property ("horizontal-shift");
37
38   int h1 = (ly_number_p (s1))?  ly_scm2int (s1) :0;
39   int h2 = (ly_number_p (s2)) ? ly_scm2int (s2):0;
40   return h1 - h2;
41 }
42
43 Item *
44 Note_column::get_stem (Grob*me) 
45 {
46   SCM s = me->get_property ("stem");
47   return  unsmob_item (s);
48 }
49   
50 Slice
51 Note_column::head_positions_interval (Grob *me)
52 {
53   Slice  iv;
54
55   iv.set_empty ();
56
57   SCM h = me->get_property ("note-heads");
58   for (; ly_pair_p (h); h = ly_cdr (h))
59     {
60       Grob *se = unsmob_grob (ly_car (h));
61       
62       int j = Staff_symbol_referencer::get_rounded_position (se);
63       iv.unite (Slice (j,j));
64     }
65   return iv;
66 }
67
68 Direction
69 Note_column::dir (Grob*  me)
70 {
71   Grob *stem = unsmob_grob (me->get_property ("stem"));
72   if (stem && Stem::has_interface (stem))
73     return Stem::get_direction (stem);
74   else if (ly_pair_p (me->get_property ("note-heads")))
75     return (Direction)sign (head_positions_interval (me).center ());
76
77   programming_error ("Note column without heads and stem!");
78   return CENTER;
79 }
80
81
82 void
83 Note_column::set_stem (Grob*me,Grob * stem)
84 {
85   me->set_property ("stem", stem->self_scm ());
86   me->add_dependency (stem);
87   Axis_group_interface::add_element (me, stem);
88 }
89
90
91 Grob*
92 Note_column::get_rest (Grob*me)
93 {
94   return unsmob_grob (me->get_property ("rest"));
95 }
96   
97 void
98 Note_column::add_head (Grob*me,Grob *h)
99 {
100   bool both = false;
101   if (Rest::has_interface (h))
102     {
103       if (ly_pair_p (me->get_property ("note-heads")))
104         both = true;
105       else
106         me->set_property ("rest", h->self_scm ());
107     }
108   else if (Note_head::has_interface (h))
109     {
110       if (unsmob_grob (me->get_property ("rest")))
111         both = true;
112       Pointer_group_interface::add_grob (me, ly_symbol2scm ("note-heads"),h);
113     }
114
115   if (both)
116     me->warning ("Can't have rests and note heads together on a stem.");
117   else
118     Axis_group_interface::add_element (me, h);
119 }
120
121 /**
122   translate the rest symbols vertically by amount DY, but only if
123   they have no staff-position set.
124 */
125 void
126 Note_column::translate_rests (Grob*me, int dy)
127 {
128   Grob * r = unsmob_grob (me->get_property ("rest"));
129   if (r && !ly_number_p (r->get_property ("staff-position")))
130     {
131       r->translate_axis (dy * Staff_symbol_referencer::staff_space (r)/2.0, Y_AXIS);
132     }
133 }
134
135
136 void
137 Note_column::set_dotcol (Grob*me,Grob *d)
138 {
139   Axis_group_interface::add_element (me, d);
140 }
141
142
143
144
145 Grob*
146 Note_column::first_head (Grob*me) 
147 {
148   Grob * st = get_stem (me);
149   return st?  Stem::first_head (st): 0; 
150 }
151
152
153 /*
154   Return the first Accidentals grob that we find in a note-head. 
155  */
156 Grob* 
157 Note_column::accidentals (Grob *me)
158 {
159   SCM heads = me->get_property ("note-heads");
160   Grob * acc = 0;
161   for (;ly_pair_p (heads); heads =ly_cdr (heads))
162     {
163       Grob * h = unsmob_grob (ly_car (heads));
164       acc = h ? unsmob_grob (h->get_property ("accidental-grob")) : 0;
165       if (acc)
166         break;
167     }
168
169   if (!acc)
170     return 0;
171   
172   if (Accidental_placement::has_interface (acc->get_parent (X_AXIS)))
173     return acc->get_parent (X_AXIS);
174
175   /* compatibility. */
176   return  acc;
177 }
178
179
180
181 ADD_INTERFACE (Note_column,"note-column-interface",
182   "Stem and noteheads combined",
183   "arpeggio note-heads rest-collision rest horizontal-shift stem accidentals force-hshift");
184