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