]> git.donarmstrong.com Git - lilypond.git/blob - lily/note-column.cc
patch::: 1.3.9.hwn2
[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--1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 */
8 #include "dot-column.hh"
9 #include "note-column.hh"
10 #include "beam.hh"
11 #include "note-head.hh"
12 #include "stem.hh"
13 #include "rest.hh"
14 #include "debug.hh"
15 #include "paper-def.hh"
16
17 bool
18 Note_column::rest_b () const
19 {
20   return rest_l_arr_.size ();
21 }
22
23 int
24 Note_column::shift_compare (Note_column *const &p1, Note_column*const&p2)
25 {
26   SCM s1 = p1->get_elt_property ("horizontal-shift");
27   SCM s2 = p2->get_elt_property ("horizontal-shift");
28
29   int h1 = (s1 == SCM_UNDEFINED) ? 0 : gh_scm2int (s1);
30   int h2 = (s2 == SCM_UNDEFINED) ? 0 : gh_scm2int (s2);
31   return h1 - h2;
32 }
33
34 Note_column::Note_column()
35 {
36   set_axes (X_AXIS, Y_AXIS);
37   stem_l_ = 0;
38 }
39
40 void
41 Note_column::sort()
42 {
43   head_l_arr_.sort (Note_head::compare);
44 }
45   
46 Slice
47 Note_column::head_positions_interval() const
48 {
49   Slice  iv;
50
51   iv.set_empty ();
52   for (int i=0; i <head_l_arr_.size ();i ++)
53     {
54       int j = int (head_l_arr_[i]->position_f ());
55       iv.unite (Slice (j,j));
56     }
57   return iv;
58 }
59
60 Direction
61 Note_column::dir () const
62 {
63   if (stem_l_)
64     return stem_l_->get_direction ();
65   else if (head_l_arr_.size ())
66     return (Direction)sign (head_positions_interval().center ());
67
68   programming_error ("Note column without heads and stem!");
69   return CENTER;
70 }
71
72
73 void
74 Note_column::set_stem (Stem * stem_l)
75 {
76   stem_l_ = stem_l;
77   add_dependency (stem_l);
78   add_element (stem_l);
79 }
80
81
82 void
83 Note_column::do_substitute_element_pointer (Score_element*o, Score_element*n)
84 {
85   if (stem_l_ == o) 
86     {
87       stem_l_ = n ? dynamic_cast<Stem *> (n):0;
88     }
89   if (dynamic_cast<Note_head *> (o))
90     {
91       head_l_arr_.substitute (dynamic_cast<Note_head *> (o), 
92                               (n)? dynamic_cast<Note_head *> (n) : 0);
93     }
94
95   if (dynamic_cast<Rest *> (o)) 
96     {
97       rest_l_arr_.substitute (dynamic_cast<Rest *> (o), 
98                               (n)? dynamic_cast<Rest *> (n) : 0);
99     }
100 }
101
102 void
103 Note_column::add_head (Rhythmic_head *h)
104 {
105   if (Rest*r=dynamic_cast<Rest *> (h))
106     {
107       rest_l_arr_.push (r);
108     }
109   if (Note_head *nh=dynamic_cast<Note_head *> (h))
110     {
111       head_l_arr_.push (nh);
112     }
113   add_element (h);
114 }
115
116 /**
117   translate the rest symbols vertically by amount DY_I.
118  */
119 void
120 Note_column::translate_rests (int dy_i)
121 {
122   invalidate_cache (Y_AXIS);
123   for (int i=0; i < rest_l_arr_.size(); i++)
124     rest_l_arr_[i]->translate_axis (dy_i  * rest_l_arr_[i]->staff_line_leading_f ()/2.0,
125                                     Y_AXIS);
126 }
127
128 void
129 Note_column::do_print() const
130 {
131 #ifndef NPRINT
132   DEBUG_OUT << "rests: " << rest_l_arr_.size() << ", ";
133   DEBUG_OUT << "heads: " << head_l_arr_.size();
134 #endif
135 }
136
137 void
138 Note_column::set_dotcol (Dot_column *d)
139 {
140   add_element (d);
141 }
142
143 /*
144   [TODO]
145   handle rest under beam (do_post: beams are calculated now)
146   what about combination of collisions and rest under beam.
147
148   Should lookup
149     
150     rest -> stem -> beam -> interpolate_y_position ()
151     
152 */
153
154 void
155 Note_column::do_post_processing ()
156 {
157   if (!stem_l_ || !rest_b ())
158     return;
159
160   Beam * b = stem_l_->beam_l ();
161   if (!b || !b->stem_count ())
162     return;
163   
164   /* ugh. Should be done by beam. */
165   Direction d = stem_l_->get_direction ();
166   Real beamy = (stem_l_->hpos_f () - b->stem(0)->hpos_f ()) * b->slope_f_ + b->left_y_;
167
168   Real staff_space = rest_l_arr_[0]->staff_line_leading_f ();      
169   Real rest_dim = extent (Y_AXIS)[d]*2.0  /staff_space ;
170
171   Real minimum_dist
172     = paper_l ()->get_var ("restcollision_minimum_beamdist") ;
173   Real dist =
174     minimum_dist +  -d  * (beamy - rest_dim) >? 0;
175
176   int stafflines = rest_l_arr_[0]->lines_i ();
177
178   // move discretely by half spaces.
179   int discrete_dist = int (ceil (dist ));
180
181   // move by whole spaces inside the staff.
182   if (discrete_dist < stafflines+1)
183     discrete_dist = int (ceil (discrete_dist / 2.0)* 2.0);
184
185   translate_rests (-d *  discrete_dist);
186 }
187