2 stem.cc -- implement Stem
4 source file of the GNU LilyPond music typesetter
6 (c) 1996, 1997--1999 Han-Wen Nienhuys <hanwen@cs.uu.nl>
8 TODO: This is way too hairy
13 #include "paper-def.hh"
14 #include "note-head.hh"
16 #include "molecule.hh"
28 beams_i_drul_[LEFT] = beams_i_drul_[RIGHT] = -1;
29 yextent_drul_[DOWN] = yextent_drul_[UP] = 0;
36 Stem::head_positions () const
39 Mysterious FreeBSD fix by John Galbraith. Somehow, the empty intervals
40 trigger FP exceptions on FreeBSD. Fix: do not return infinity
43 if (!head_l_arr_.size ())
45 return Interval_t<int> (100,-100);
49 for (int i =0; i < head_l_arr_.size (); i++)
51 int p = head_l_arr_[i]->position_i_;
52 r[BIGGER] = r[BIGGER] >? p;
53 r[SMALLER] = r[SMALLER] <? p;
59 Stem::do_print () const
62 DOUT << "flag "<< flag_i_;
69 Stem::stem_length_f () const
71 return yextent_drul_[UP]-yextent_drul_[DOWN] ;
75 Stem::stem_begin_f () const
77 return yextent_drul_[Direction(-dir_)];
81 Stem::chord_start_f () const
83 return head_positions()[dir_] * staff_line_leading_f ()/2.0;
87 Stem::stem_end_f () const
89 return yextent_drul_[dir_];
93 Stem::set_stemend (Real se)
96 if (dir_ && dir_ * head_positions()[dir_] >= se*dir_)
97 warning (_ ("weird stem size; check for narrow beams"));
100 yextent_drul_[dir_] = se;
101 yextent_drul_[Direction(-dir_)] = head_positions()[-dir_];
105 Stem::type_i () const
107 return head_l_arr_[0]->balltype_i_;
111 Stem::add_head (Rhythmic_head *n)
113 n->add_dependency (this); // ?
114 if (Note_head *nh = dynamic_cast<Note_head *> (n))
116 head_l_arr_.push (nh);
118 else if (Rest *r = dynamic_cast<Rest *> (n))
120 rest_l_arr_.push (r);
125 Stem::invisible_b () const
127 return (!head_l_arr_.size () ||
128 head_l_arr_[0]->balltype_i_ <= 0);
132 Stem::get_center_distance (Direction d) const
134 int staff_center = 0;
135 int distance = d*(head_positions()[d] - staff_center);
136 return distance >? 0;
140 Stem::get_default_dir () const
142 return (get_center_distance (UP) >
143 get_center_distance (DOWN))
149 Stem::get_dir () const
155 Stem::set_default_dir ()
157 dir_ = get_default_dir ();
161 Stem::set_default_stemlen ()
163 Real internote_f = staff_line_leading_f ()/2.0;
164 Real length_f = paper_l ()->get_var ("stem_length0") / internote_f;
165 Real shorten_f = paper_l ()->get_var ("forced_stem_shorten0") / internote_f;
170 stems in unnatural (forced) direction should be shortened,
171 according to [Roush & Gourlay]
173 if (((int)chord_start_f ())
174 && (dir_ != get_default_dir ()))
175 length_f -= shorten_f;
182 set_stemend ((dir_ > 0) ? head_positions()[BIGGER] + length_f:
183 head_positions()[SMALLER] - length_f);
185 if (dir_ * stem_end_f () < 0)
191 Stem::set_default_extents ()
193 if (!stem_length_f ())
194 set_default_stemlen ();
199 Stem::set_noteheads ()
201 if (!head_l_arr_.size ())
203 head_l_arr_.sort (Note_head::compare);
205 head_l_arr_.reverse ();
207 Note_head * beginhead = head_l_arr_[0];
208 beginhead->set_elt_property (extremal_scm_sym, SCM_BOOL_T);
209 if (beginhead != head_l_arr_.top ())
210 head_l_arr_.top ()->set_elt_property (extremal_scm_sym, SCM_BOOL_T);
213 int lastpos = beginhead->position_i_;
214 for (int i=1; i < head_l_arr_.size (); i ++)
216 int dy =abs (lastpos- head_l_arr_[i]->position_i_);
221 head_l_arr_[i]->flip_around_stem (dir_);
226 lastpos = head_l_arr_[i]->position_i_;
231 Stem::do_pre_processing ()
233 if (yextent_drul_[DOWN]== yextent_drul_[UP])
234 set_default_extents ();
239 set_elt_property (transparent_scm_sym, SCM_BOOL_T);
241 set_empty (invisible_b ());
246 Stem::do_width () const
249 if (beam_l_ || abs (flag_i_) <= 2)
253 r = lookup_l ()->flag (flag_i_, dir_).dim_.x ();
254 r += note_delta_f ();
262 const Real ANGLE = 20* (2.0*M_PI/360.0); // ugh!
265 Stem::do_brew_molecule_p () const
267 Molecule *mol_p =new Molecule;
268 Drul_array<Real> stem_y = yextent_drul_;
269 Real dy = staff_line_leading_f ()/2.0;
272 if (head_l_arr_.size ())
273 head_wid = head_l_arr_[0]->extent (X_AXIS).length ();
274 stem_y[Direction(-dir_)] += dir_ * head_wid * tan(ANGLE)/(2*dy);
278 Molecule ss =lookup_l ()->stem (stem_y[DOWN]*dy,
280 mol_p->add_molecule (ss);
283 if (!beam_l_ && abs (flag_i_) > 2)
285 Molecule fl = lookup_l ()->flag (flag_i_, dir_);
286 fl.translate_axis(stem_y[dir_]*dy, Y_AXIS);
287 mol_p->add_molecule (fl);
290 if (head_l_arr_.size())
292 mol_p->translate_axis (note_delta_f (), X_AXIS);
298 Stem::note_delta_f () const
301 if (head_l_arr_.size())
303 Interval head_wid(0, head_l_arr_[0]->extent (X_AXIS).length ());
304 Real rule_thick(paper_l ()->rule_thickness ());
305 Interval stem_wid(-rule_thick/2, rule_thick/2);
307 r = head_wid.center ();
309 r = head_wid[dir_] - stem_wid[dir_];
315 Stem::hpos_f () const
317 return note_delta_f () + Item::hpos_f ();
321 Stem::do_substitute_element_pointer (Score_element*o,Score_element*n)
323 if (Note_head*h=dynamic_cast<Note_head*> (o))
324 head_l_arr_.substitute (h, dynamic_cast<Note_head*>(n));
325 if (Rest *r=dynamic_cast<Rest*> (o))
326 rest_l_arr_.substitute (r, dynamic_cast<Rest*>(n));
327 if (Beam* b = dynamic_cast<Beam*> (o))
330 beam_l_ = dynamic_cast<Beam*> (n);
332 Staff_symbol_referencer::do_substitute_element_pointer (o,n);