]> git.donarmstrong.com Git - lilypond.git/blob - lily/stem.cc
release: 0.1.11
[lilypond.git] / lily / stem.cc
1 /*
2   stem.cc -- implement Stem
3
4   source file of the GNU LilyPond music typesetter
5
6   (c) 1996,1997 Han-Wen Nienhuys <hanwen@stack.nl>
7 */
8
9 #include "stem.hh"
10 #include "dimen.hh" 
11 #include "debug.hh"
12 #include "paper-def.hh"
13 #include "note-head.hh"
14 #include "lookup.hh"
15 #include "molecule.hh"
16 #include "p-col.hh"
17 #include "misc.hh"
18
19 const int STEMLEN=7;
20
21 int
22 Stem::min_head_i() const
23 {
24   int m = 1000;
25   for (int i =0; i < head_l_arr_.size(); i++)
26     m = m <? head_l_arr_[i]->position_i_;
27   return m;
28 }
29
30 int
31 Stem::max_head_i() const
32 {
33   int m = -1000;
34   for (int i =0; i < head_l_arr_.size(); i++)
35     m = m >? head_l_arr_[i]->position_i_;
36   return m;
37   
38 }
39 /*
40   TODO: staff-size
41  */
42 Stem::Stem () 
43 {
44   beams_left_i_ = 0;
45   beams_right_i_ = 0;
46
47   stem_bottom_f_ = stem_top_f_ = 0;
48   flag_i_ = 4;
49   dir_ =CENTER;
50   staff_size_i_ = 8;
51
52   print_flag_b_=true;
53   stem_xoffset_f_ =0;
54 }
55
56
57 IMPLEMENT_IS_TYPE_B1(Stem,Item);
58
59 void
60 Stem::do_print() const
61 {
62 #ifndef NPRINT
63   DOUT << "flag "<< flag_i_ << " print_flag_b_ " << print_flag_b_;
64 #endif
65 }
66
67 Real 
68 Stem::stem_length_f() const
69 {
70   return stem_top_f_-stem_bottom_f_ ;
71 }
72
73 Real
74 Stem::stem_start_f() const
75 {
76   return (dir_ < 0)? stem_top_f_ : stem_bottom_f_;
77 }
78
79 Real
80 Stem::stem_end_f() const
81 {
82   return (dir_ < 0)? stem_bottom_f_ : stem_top_f_;
83 }
84
85
86 void
87 Stem::set_stemend (Real se)
88 {
89   // todo: margins
90   if (!  ((dir_ > 0 && se >= max_head_i()) || 
91           (se <= min_head_i() && dir_ <0)))     
92     warning ("Weird stem size; check for narrow beams");
93
94   stem_top_f_  = (dir_ < 0) ? max_head_i()           : se;
95   stem_bottom_f_  = (dir_ < 0) ? se  : min_head_i();
96 }
97
98 void
99 Stem::add (Note_head *n)
100 {
101   n->add_dependency (this);
102   if (n->rest_b_) 
103     {
104       rest_l_arr_.push (n);
105     }
106   else if (n->balltype_i_ == 0) 
107     {
108       whole_l_arr_.push (n);
109       return;
110     }
111   else
112     {
113       head_l_arr_.push (n);
114     }
115 }
116
117 bool
118 Stem::invisible_b() const
119 {
120   return !head_l_arr_.size();
121 }
122
123 // if dir_ is set we return fake values.
124
125 int
126 Stem::get_center_distance_from_top()
127 {
128   if (dir_)
129     return (dir_ > 0) ? 0 : 1;
130
131   int staff_center = staff_size_i_ / 2;
132   int max = max_head_i() - staff_center;
133   return max >? 0;
134 }
135
136 // if dir_ is set we return fake values.
137 int
138 Stem::get_center_distance_from_bottom()
139 {
140   if (dir_)
141     return (dir_ > 0) ? 1 : 0;
142
143   int staff_center = staff_size_i_ / 2;
144   int min = staff_center - min_head_i();
145   return min >? 0;
146 }
147
148 Direction
149 Stem::get_default_dir()
150 {
151   if (dir_)
152     return dir_;
153   return (get_center_distance_from_top() >=
154           get_center_distance_from_bottom()) ? -1 : 1;
155 }
156
157
158 void
159 Stem::set_default_dir()
160 {
161   dir_ = get_default_dir();
162 }
163
164 void
165 Stem::set_default_stemlen()
166 {
167   if (!dir_)
168     set_default_dir();
169
170   
171   // ugh... how about non 5-line staffs?
172   if ((max_head_i() < -2 && dir_ == 1)
173       ||(min_head_i() > staff_size_i_ && dir_ == -1))
174     {
175       set_stemend (staff_size_i_ /2 -1);
176     }
177   else 
178     {
179       set_stemend ((dir_ > 0) ? max_head_i() + STEMLEN : 
180                    min_head_i() - STEMLEN);
181
182     }
183 }
184
185
186 void
187 Stem::set_default_extents()
188 {
189   if (!stem_length_f())
190     set_default_stemlen();
191
192   set_stemend ((dir_< 0) ? 
193                max_head_i()-stem_length_f (): min_head_i () +stem_length_f ());
194   if (dir_ > 0){        
195     stem_xoffset_f_ = paper()->note_width ()-paper ()->rule_thickness ();
196   }
197   else
198     stem_xoffset_f_ = 0;
199 }
200
201 /*
202   TODO
203   
204   move into note_column.cc
205
206   */
207 void
208 Stem::set_noteheads()
209 {
210   if (!head_l_arr_.size())
211     return;
212   head_l_arr_.sort (Note_head::compare);
213   if (dir_ < 0) 
214     head_l_arr_.reverse();
215   
216   head_l_arr_[0]->extremal_i_ = -1;
217   head_l_arr_.top()->extremal_i_ = 1;
218   int parity=1;
219   int lastpos = head_l_arr_[0]->position_i_;
220   for (int i=1; i < head_l_arr_.size(); i ++) 
221     {
222       int dy =abs (lastpos- head_l_arr_[i]->position_i_);
223         
224       if (dy <= 1) 
225         {
226           if (parity)
227             head_l_arr_[i]->x_dir_ = (stem_xoffset_f_>0) ? UP:DOWN;
228           parity = !parity;
229         }
230       else
231         parity = 0;
232       lastpos = head_l_arr_[i]->position_i_;
233     }
234 }
235
236 void
237 Stem::do_pre_processing()
238 {
239   if (stem_bottom_f_== stem_top_f_)
240     set_default_extents();
241   set_noteheads();
242   flag_i_ = dir_*abs (flag_i_);
243   transparent_b_ = invisible_b();
244   empty_b_ = invisible_b();
245 }
246
247
248 Interval
249 Stem::do_width() const
250 {
251   if (!print_flag_b_ || abs (flag_i_) <= 4)
252     return Interval (0,0);      // TODO!
253   Paper_def*p= paper();
254   Interval r (p->lookup_l()->flag (flag_i_).dim.x ());
255   r+= stem_xoffset_f_;
256   return r;
257 }
258
259 Molecule*
260 Stem::brew_molecule_p() const 
261 {
262   Molecule *out =0;
263       
264   Real bot  = stem_bottom_f_;
265   Real top = stem_top_f_;
266   
267   assert (bot!=top);
268  
269   Paper_def *p =paper();
270
271   Real dy = p->internote_f();
272   Symbol ss =p->lookup_l()->stem (bot*dy,top*dy);
273
274   out = new Molecule (Atom (ss));
275
276   if (print_flag_b_&&abs (flag_i_) > 4)
277     {
278       Symbol fl = p->lookup_l()->flag (flag_i_);
279       Molecule m (fl);
280       if (flag_i_ < -4){                
281         out->add_bottom (m);
282       }
283       else if (flag_i_ > 4) 
284         {
285           out->add_top (m);
286         }
287       else
288         assert (false); 
289     }
290
291   out->translate (stem_xoffset_f_, X_AXIS);
292   return out;
293 }
294
295 Real
296 Stem::hpos_f() const
297 {
298   return Item::hpos_f() + stem_xoffset_f_;
299 }
300
301
302 void
303 Stem::do_substitute_dependency (Score_elem*o,Score_elem*n)
304 {
305   Item * o_l = o->item();
306   Item * n_l = n? n->item():0;
307   whole_l_arr_.substitute ((Note_head*)o_l, (Note_head*)n_l);
308   head_l_arr_.substitute ((Note_head*)o_l, (Note_head*)n_l);
309   rest_l_arr_.substitute ((Note_head*)o_l, (Note_head*)n_l);
310 }