]> git.donarmstrong.com Git - lilypond.git/blob - lily/stem.cc
release: 0.0.56
[lilypond.git] / lily / stem.cc
1 #include "stem.hh"
2 #include "dimen.hh" 
3 #include "debug.hh"
4 #include "paper-def.hh"
5 #include "notehead.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 void
77 Stem::set_stemend(Real se)
78 {
79     // todo: margins
80     if (!  ((dir_i_ > 0 && se >= max_head_i()) || 
81             (se <= min_head_i() && dir_i_ <0))  )       
82         warning("Weird stem size; check for narrow beams");
83
84     stem_top_f_  = (dir_i_ < 0) ? max_head_i()           : se;
85     stem_bottom_f_  = (dir_i_ < 0) ? se  : min_head_i();
86 }
87
88 void
89 Stem::add(Notehead *n)
90 {
91     n->add_dependency(this);
92     if (n->rest_b_) {
93         rest_l_arr_.push(n);
94     } else if (n->balltype_i_ == 1) {
95         whole_l_arr_.push(n);
96         return;
97     } else{
98         head_l_arr_.push(n);
99     }
100 }
101
102 bool
103 Stem::invisible_b()const
104 {
105     return !head_l_arr_.size();
106 }
107
108 int
109 Stem::get_default_dir()
110 {
111     int staff_center = staff_size_i_ /2;
112     if (dir_i_)
113         return dir_i_;
114     Real mean = (min_head_i() + max_head_i())/2;
115     return (mean > staff_center) ? -1: 1;
116 }
117
118 void
119 Stem::set_default_dir()
120 {
121     dir_i_ = get_default_dir();
122 }
123
124 void
125 Stem::set_default_stemlen()
126 {
127     if (!dir_i_)
128         set_default_dir();
129
130     
131     // uhh... how about non 5-line staffs?
132     if ((max_head_i() < -2 && dir_i_ == 1 )
133         ||(min_head_i() > staff_size_i_ + 2 && dir_i_ == -1) ){
134         set_stemend(    staff_size_i_ /2 );
135     } else {
136         set_stemend( (dir_i_ > 0) ? max_head_i() + STEMLEN : 
137                                      min_head_i() - STEMLEN);
138
139     }
140 }
141
142
143 void
144 Stem::set_default_extents()
145 {
146     if (!stem_length_f())
147         set_default_stemlen();
148
149     set_stemend((dir_i_< 0) ? 
150                 max_head_i()-stem_length_f(): min_head_i() +stem_length_f());
151     if (dir_i_ > 0){    
152         stem_xoffset_f_ = paper()->note_width()-paper()->rule_thickness();
153     } else
154         stem_xoffset_f_ = 0;
155 }
156
157 void
158 Stem::set_noteheads()
159 {
160     if(!head_l_arr_.size())
161         return;
162     head_l_arr_.sort(Notehead::compare);
163     head_l_arr_[0]->extremal_i_ = -1;
164     head_l_arr_.top()->extremal_i_ = 1;
165     int parity=1;
166     int lastpos = head_l_arr_[0]->position_i_;
167     for (int i=1; i < head_l_arr_.size(); i ++) {
168         int dy =abs(lastpos- head_l_arr_[i]->position_i_);
169         
170         if (dy <= 1) {
171             if (parity)
172                 head_l_arr_[i]->x_dir_i_ = (stem_xoffset_f_>0) ? 1:-1;
173             parity = !parity;
174         } else
175             parity = 0;
176         lastpos = head_l_arr_[i]->position_i_;
177     }
178 }
179
180 void
181 Stem::do_pre_processing()
182 {
183     if (stem_bottom_f_== stem_top_f_)
184         set_default_extents();
185     set_noteheads();
186     flag_i_ = dir_i_*abs(flag_i_);
187 }
188
189
190 Interval
191 Stem::do_width()const
192 {
193     if (!print_flag_b_ || abs(flag_i_) <= 4)
194         return Interval(0,0);   // TODO!
195     Paper_def*p= paper();
196     Interval r(p->lookup_l()->flag(flag_i_).dim.x);
197     r+= stem_xoffset_f_;
198     return r;
199 }
200
201 Molecule*
202 Stem::brew_molecule_p()const 
203 {
204     Molecule *out =0;
205     if ( invisible_b() )
206         return Staff_elem::brew_molecule_p();
207     
208     Real bot  = stem_bottom_f_;
209     Real top = stem_top_f_;
210     if (min_head_i() > max_head_i()) {
211         warning("Empty stem. Ugh!");
212         bot = -10;
213         top = 20;
214     }
215
216     assert(bot!=top);
217  
218     Paper_def *p =paper();
219
220     Real dy = p->internote();
221     Symbol ss =p->lookup_l()->stem(bot*dy,top*dy);
222
223     out = new Molecule(Atom(ss));
224
225     if (print_flag_b_&&abs(flag_i_) > 4){
226         Symbol fl = p->lookup_l()->flag(flag_i_);
227         Molecule m(fl);
228         if (flag_i_ < -4){              
229             out->add_bottom(m);
230         } else if (flag_i_ > 4) {
231             out->add_top(m);
232         } else
233             assert(false); 
234     }
235
236     out->translate(Offset(stem_xoffset_f_,0));
237     return out;
238 }
239
240 Real
241 Stem::hpos_f()const
242 {
243     return Item::hpos_f() + stem_xoffset_f_;
244 }
245
246