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