]> git.donarmstrong.com Git - lilypond.git/blob - lily/note-column.cc
release: 1.1.50
[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_scm_sym);
27   SCM s2 = p2->get_elt_property (horizontal_shift_scm_sym);
28
29   int h1 = (s1 == SCM_BOOL_F) ? 0 : gh_scm2int (SCM_CDR(s1));
30   int h2 = (s2 == SCM_BOOL_F) ? 0 : gh_scm2int (SCM_CDR(s2));
31   return h1 - h2;
32 }
33
34 Note_column::Note_column()
35 {
36   set_axes (X_AXIS,X_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 = head_l_arr_[i]->position_i_;
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_->dir_;
65   else if (head_l_arr_.size ())
66     return sign (head_positions_interval().center ());
67
68   assert (false);
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]->position_i_ += dy_i;
125 }
126
127 void
128 Note_column::do_print() const
129 {
130 #ifndef NPRINT
131   DOUT << "rests: " << rest_l_arr_.size() << ", ";
132   DOUT << "heads: " << head_l_arr_.size();
133 #endif
134 }
135
136 void
137 Note_column::set_dotcol (Dot_column *d)
138 {
139   add_element (d);
140 }
141
142 /*
143   [TODO]
144   handle rest under beam (do_post: beams are calculated now)
145   what about combination of collisions and rest under beam.
146
147   Should lookup
148     
149     rest -> stem -> beam -> interpolate_y_position ()
150     
151 */
152
153 void
154 Note_column::do_post_processing ()
155 {
156   if (!stem_l_ || !rest_b ())
157     return;
158
159   Beam * b = stem_l_->beam_l_;
160   if (!b || !b->stems_.size ())
161     return;
162   
163   /* ugh. Should be done by beam. */
164   Direction d = stem_l_->get_dir ();
165   Real beamy = (stem_l_->hpos_f () - b->stems_[0]->hpos_f ()) * b->slope_f_ + b->left_y_;
166
167   Real staff_space = rest_l_arr_[0]->staff_line_leading_f ();      
168   Real rest_dim = extent (Y_AXIS)[d]*2.0  /staff_space ;
169
170   Real minimum_dist
171     = paper_l ()->get_var ("restcollision_minimum_beamdist") ;
172   Real dist =
173     minimum_dist +  -d  * (beamy - rest_dim) >? 0;
174
175   int stafflines = rest_l_arr_[0]->lines_i ();
176
177   // move discretely by half spaces.
178   int discrete_dist = int (ceil (dist ));
179
180   // move by whole spaces inside the staff.
181   if (discrete_dist < stafflines+1)
182     discrete_dist = int (ceil (discrete_dist / 2.0)* 2.0);
183
184   translate_rests (-d *  discrete_dist);
185 }