]> git.donarmstrong.com Git - lilypond.git/blob - lily/note-column.cc
release: 1.1.39
[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 Note_column::Note_column()
24 {
25   set_axes (X_AXIS,X_AXIS);
26   stem_l_ = 0;
27 }
28
29 void
30 Note_column::sort()
31 {
32   head_l_arr_.sort (Note_head::compare);
33 }
34   
35 Interval_t<int>
36 Note_column::head_positions_interval() const
37 {
38   ((Note_column*)this)->sort();
39   Interval_t<int>  iv;
40
41   iv.set_empty ();
42
43   if (head_l_arr_.size ())
44     iv = Interval_t<int>(head_l_arr_[0]->position_i_, 
45                          head_l_arr_.top()->position_i_);
46   
47   return iv;
48 }
49
50 Direction
51 Note_column::dir () const
52 {
53   if (stem_l_)
54     return stem_l_->dir_;
55   else if (head_l_arr_.size ())
56     return sign (head_positions_interval().center ());
57
58   assert (false);
59   return CENTER;
60 }
61
62
63 void
64 Note_column::set_stem (Stem * stem_l)
65 {
66   stem_l_ = stem_l;
67   add_dependency (stem_l);
68   add_element (stem_l);
69 }
70
71
72 void
73 Note_column::do_substitute_element_pointer (Score_element*o, Score_element*n)
74 {
75   if (stem_l_ == o) 
76     {
77       stem_l_ = n ? dynamic_cast<Stem *> (n):0;
78     }
79   if (dynamic_cast<Note_head *> (o))
80     {
81       head_l_arr_.substitute (dynamic_cast<Note_head *> (o), 
82                               (n)? dynamic_cast<Note_head *> (n) : 0);
83     }
84
85   if (dynamic_cast<Rest *> (o)) 
86     {
87       rest_l_arr_.substitute (dynamic_cast<Rest *> (o), 
88                               (n)? dynamic_cast<Rest *> (n) : 0);
89     }
90 }
91
92 void
93 Note_column::add_head (Rhythmic_head *h)
94 {
95   if (Rest*r=dynamic_cast<Rest *> (h))
96     {
97       rest_l_arr_.push (r);
98     }
99   if (Note_head *nh=dynamic_cast<Note_head *> (h))
100     {
101       head_l_arr_.push (nh);
102     }
103   add_element (h);
104 }
105
106 /**
107   translate the rest symbols
108  */
109 void
110 Note_column::translate_rests (int dy_i)
111 {
112   invalidate_cache (Y_AXIS);
113   for (int i=0; i < rest_l_arr_.size(); i++)
114     rest_l_arr_[i]->position_i_ += dy_i;
115 }
116
117 void
118 Note_column::do_print() const
119 {
120 #ifndef NPRINT
121   DOUT << "rests: " << rest_l_arr_.size() << ", ";
122   DOUT << "heads: " << head_l_arr_.size();
123 #endif
124 }
125
126 void
127 Note_column::set_dotcol (Dot_column *d)
128 {
129   add_element (d);
130 }
131
132   /*
133     [TODO]
134     handle rest under beam (do_post: beams are calculated now)
135     what about combination of collisions and rest under beam.
136
137     Should lookup
138     
139       rest -> stem -> beam -> interpolate_y_position ()
140     
141    */
142
143 void
144 Note_column::do_post_processing ()
145 {
146   if (!stem_l_ || !rest_b ())
147     return;
148
149   Beam * b = stem_l_->beam_l_;
150   if (!b)
151     return;
152       
153       /* ugh. Should be done by beam. */
154   Real x = stem_l_->hpos_f ();
155   Direction d = stem_l_->get_dir ();
156   Real beamy = x * b->slope_f_ + b->left_y_;
157   Interval restdim = extent (Y_AXIS);
158
159   Real staff_space = rest_l_arr_[0]->staff_line_leading_f ();      
160   Real internote_f = staff_space/2;
161   Real minimum_dist
162     = paper_l ()->get_var ("restcollision_minimum_beamdist") * internote_f;
163   Real dist =
164     minimum_dist +  -d  * (beamy - restdim[d]) >? 0;
165
166   int stafflines = rest_l_arr_[0]->lines_i ();
167       
168   // move discretely by half spaces.
169   int discrete_dist = int (ceil (dist / (0.5 *staff_space)));
170
171   // move by whole spaces inside the staff.
172   if (discrete_dist < stafflines+1)
173     discrete_dist = int (ceil (discrete_dist / 2.0)* 2.0);
174
175   translate_rests (-d *  discrete_dist);
176 }