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"
34 beams_i_drul_[LEFT] = beams_i_drul_[RIGHT] = -1;
37 yextent_drul_[DOWN] = yextent_drul_[UP] = 0;
41 dir_forced_b_ = false;
49 Stem::head_positions () const
52 Mysterious FreeBSD fix by John Galbraith. Somehow, the empty intervals
53 trigger FP exceptions on FreeBSD. Fix: do not return infinity
56 if (!head_l_arr_.size ())
58 return Interval_t<int> (100,-100);
62 for (int i =0; i < head_l_arr_.size (); i++)
64 int p = head_l_arr_[i]->position_i_;
65 r[BIGGER] = r[BIGGER] >? p;
66 r[SMALLER] = r[SMALLER] <? p;
72 Stem::do_print () const
75 DOUT << "flag "<< flag_i_;
82 Stem::stem_length_f () const
84 return yextent_drul_[UP]-yextent_drul_[DOWN] ;
88 Stem::stem_begin_f () const
90 return yextent_drul_[Direction(-dir_)];
94 Stem::chord_start_f () const
96 return head_positions()[dir_] * staff_line_leading_f ()/2.0;
100 Stem::stem_end_f () const
102 return yextent_drul_[dir_];
106 Stem::set_stemend (Real se)
109 if (dir_ && dir_ * head_positions()[dir_] >= se*dir_)
110 warning (_ ("weird stem size; check for narrow beams"));
113 yextent_drul_[dir_] = se;
114 yextent_drul_[Direction(-dir_)] = head_positions()[-dir_];
118 Stem::type_i () const
120 return head_l_arr_[0]->balltype_i_;
124 Stem::add_head (Rhythmic_head *n)
126 n->add_dependency (this); // ?
127 if (Note_head *nh = dynamic_cast<Note_head *> (n))
129 head_l_arr_.push (nh);
131 else if (Rest *r = dynamic_cast<Rest *> (n))
133 rest_l_arr_.push (r);
138 Stem::invisible_b () const
140 return (!head_l_arr_.size () ||
141 head_l_arr_[0]->balltype_i_ <= 0);
145 Stem::get_center_distance (Direction d) const
147 int staff_center = 0;
148 int distance = d*(head_positions()[d] - staff_center);
149 return distance >? 0;
153 Stem::get_default_dir () const
155 return (get_center_distance (UP) >
156 get_center_distance (DOWN))
162 Stem::get_dir () const
168 Stem::set_default_dir ()
170 dir_ = get_default_dir ();
174 Stem::set_default_stemlen ()
176 Real internote_f = staff_line_leading_f ()/2.0;
177 Real length_f = paper_l ()->get_var ("stem_length0") / internote_f;
178 Real shorten_f = paper_l ()->get_var ("forced_stem_shorten0") / internote_f;
183 stems in unnatural (forced) direction should be shortened,
184 accoding to [Roush & Gourlay]
186 if (((int)chord_start_f ())
187 && (dir_ != get_default_dir ()))
188 length_f -= shorten_f;
195 set_stemend ((dir_ > 0) ? head_positions()[BIGGER] + length_f:
196 head_positions()[SMALLER] - length_f);
198 if (dir_ * stem_end_f () < 0)
204 Stem::set_default_extents ()
206 if (!stem_length_f ())
207 set_default_stemlen ();
219 move into note_column.cc
223 Stem::set_noteheads ()
225 if (!head_l_arr_.size ())
227 head_l_arr_.sort (Note_head::compare);
229 head_l_arr_.reverse ();
231 head_l_arr_[0]->extremal_i_ = -1;
232 head_l_arr_.top ()->extremal_i_ = 1;
234 int lastpos = head_l_arr_[0]->position_i_;
235 for (int i=1; i < head_l_arr_.size (); i ++)
237 int dy =abs (lastpos- head_l_arr_[i]->position_i_);
242 head_l_arr_[i]->x_dir_ = (stem_xdir_ == LEFT) ? LEFT : RIGHT;
247 lastpos = head_l_arr_[i]->position_i_;
252 Stem::do_pre_processing ()
254 if (yextent_drul_[DOWN]== yextent_drul_[UP])
255 set_default_extents ();
260 set_elt_property (transparent_scm_sym, SCM_BOOL_T);
262 set_empty (invisible_b ());
267 Stem::do_width () const
270 if (beam_l_ || abs (flag_i_) <= 2)
274 r = lookup_l ()->flag (flag_i_, dir_).dim_.x ();
275 r += note_delta_f ();
283 const Real ANGLE = 20* (2.0*M_PI/360.0); // ugh!
286 Stem::do_brew_molecule_p () const
288 Molecule *mol_p =new Molecule;
289 Drul_array<Real> stem_y = yextent_drul_;
290 Real dy = staff_line_leading_f ()/2.0;
293 if (head_l_arr_.size ())
294 head_wid = head_l_arr_[0]->extent (X_AXIS).length ();
295 stem_y[Direction(-dir_)] += dir_ * head_wid * tan(ANGLE)/(2*dy);
299 Molecule ss =lookup_l ()->stem (stem_y[DOWN]*dy,
301 mol_p->add_molecule (ss);
304 if (!beam_l_ && abs (flag_i_) > 2)
306 Molecule fl = lookup_l ()->flag (flag_i_, dir_);
307 fl.translate_axis(stem_y[dir_]*dy, Y_AXIS);
308 mol_p->add_molecule (fl);
311 if (head_l_arr_.size())
313 mol_p->translate_axis (note_delta_f (), X_AXIS);
319 Stem::note_delta_f () const
322 if (head_l_arr_.size())
324 Interval head_wid(0, head_l_arr_[0]->extent (X_AXIS).length ());
325 Real rule_thick(paper_l ()->rule_thickness ());
326 Interval stem_wid(-rule_thick/2, rule_thick/2);
327 if (stem_xdir_ == CENTER)
328 r = head_wid.center ();
330 r = head_wid[stem_xdir_] - stem_wid[stem_xdir_];
336 Stem::hpos_f () const
338 return note_delta_f () + Item::hpos_f ();
342 TODO: head_l_arr_/rest_l_arr_ in
345 Stem::do_substitute_element_pointer (Score_element*o,Score_element*n)
347 if (Note_head*h=dynamic_cast<Note_head*> (o))
348 head_l_arr_.substitute (h, dynamic_cast<Note_head*>(n));
349 if (Rest *r=dynamic_cast<Rest*> (o))
350 rest_l_arr_.substitute (r, dynamic_cast<Rest*>(n));
351 if (Beam* b = dynamic_cast<Beam*> (o))
355 beam_l_ = dynamic_cast<Beam*> (n);
358 beams_i_drul_[LEFT] = 0;
359 beams_i_drul_[RIGHT] = 0;
364 Staff_symbol_referencer::do_substitute_element_pointer (o,n);