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;
31 yextent_drul_[DOWN] = yextent_drul_[UP] = 0;
41 Stem::head_positions () const
44 Mysterious FreeBSD fix by John Galbraith. Somehow, the empty intervals
45 trigger FP exceptions on FreeBSD. Fix: do not return infinity
48 if (!head_l_arr_.size ())
50 return Interval_t<int> (100,-100);
54 for (int i =0; i < head_l_arr_.size (); i++)
56 int p = head_l_arr_[i]->position_i_;
57 r[BIGGER] = r[BIGGER] >? p;
58 r[SMALLER] = r[SMALLER] <? p;
64 Stem::do_print () const
67 DOUT << "flag "<< flag_i_;
74 Stem::stem_length_f () const
76 return yextent_drul_[UP]-yextent_drul_[DOWN] ;
80 Stem::stem_begin_f () const
82 return yextent_drul_[Direction(-dir_)];
86 Stem::chord_start_f () const
88 return head_positions()[dir_] * staff_line_leading_f ()/2.0;
92 Stem::stem_end_f () const
94 return yextent_drul_[dir_];
98 Stem::set_stemend (Real se)
101 if (dir_ && dir_ * head_positions()[dir_] >= se*dir_)
102 warning (_ ("weird stem size; check for narrow beams"));
105 yextent_drul_[dir_] = se;
106 yextent_drul_[Direction(-dir_)] = head_positions()[-dir_];
110 Stem::type_i () const
112 return head_l_arr_[0]->balltype_i_;
116 Stem::add_head (Rhythmic_head *n)
118 n->add_dependency (this); // ?
119 if (Note_head *nh = dynamic_cast<Note_head *> (n))
121 head_l_arr_.push (nh);
123 else if (Rest *r = dynamic_cast<Rest *> (n))
125 rest_l_arr_.push (r);
130 Stem::invisible_b () const
132 return (!head_l_arr_.size () ||
133 head_l_arr_[0]->balltype_i_ <= 0);
137 Stem::get_center_distance (Direction d) const
139 int staff_center = 0;
140 int distance = d*(head_positions()[d] - staff_center);
141 return distance >? 0;
145 Stem::get_default_dir () const
147 return (get_center_distance (UP) >
148 get_center_distance (DOWN))
154 Stem::get_dir () const
160 Stem::set_default_dir ()
162 dir_ = get_default_dir ();
166 Stem::set_default_stemlen ()
168 Real internote_f = staff_line_leading_f ()/2.0;
169 Real length_f = paper_l ()->get_var ("stem_length0") / internote_f;
170 Real shorten_f = paper_l ()->get_var ("forced_stem_shorten0") / internote_f;
175 stems in unnatural (forced) direction should be shortened,
176 accoding to [Roush & Gourlay]
178 if (((int)chord_start_f ())
179 && (dir_ != get_default_dir ()))
180 length_f -= shorten_f;
187 set_stemend ((dir_ > 0) ? head_positions()[BIGGER] + length_f:
188 head_positions()[SMALLER] - length_f);
190 if (dir_ * stem_end_f () < 0)
196 Stem::set_default_extents ()
198 if (!stem_length_f ())
199 set_default_stemlen ();
211 move into note_column.cc
215 Stem::set_noteheads ()
217 if (!head_l_arr_.size ())
219 head_l_arr_.sort (Note_head::compare);
221 head_l_arr_.reverse ();
223 head_l_arr_[0]->extremal_i_ = -1;
224 head_l_arr_.top ()->extremal_i_ = 1;
226 int lastpos = head_l_arr_[0]->position_i_;
227 for (int i=1; i < head_l_arr_.size (); i ++)
229 int dy =abs (lastpos- head_l_arr_[i]->position_i_);
234 head_l_arr_[i]->x_dir_ = (stem_xdir_ == LEFT) ? LEFT : RIGHT;
239 lastpos = head_l_arr_[i]->position_i_;
244 Stem::do_pre_processing ()
246 if (yextent_drul_[DOWN]== yextent_drul_[UP])
247 set_default_extents ();
252 set_elt_property (transparent_scm_sym, SCM_BOOL_T);
254 set_empty (invisible_b ());
259 Stem::do_width () const
262 if (beam_l_ || abs (flag_i_) <= 2)
266 r = lookup_l ()->flag (flag_i_, dir_).dim_.x ();
267 r += note_delta_f ();
275 const Real ANGLE = 20* (2.0*M_PI/360.0); // ugh!
278 Stem::do_brew_molecule_p () const
280 Molecule *mol_p =new Molecule;
281 Drul_array<Real> stem_y = yextent_drul_;
282 Real dy = staff_line_leading_f ()/2.0;
285 if (head_l_arr_.size ())
286 head_wid = head_l_arr_[0]->extent (X_AXIS).length ();
287 stem_y[Direction(-dir_)] += dir_ * head_wid * tan(ANGLE)/(2*dy);
291 Molecule ss =lookup_l ()->stem (stem_y[DOWN]*dy,
293 mol_p->add_molecule (ss);
296 if (!beam_l_ && abs (flag_i_) > 2)
298 Molecule fl = lookup_l ()->flag (flag_i_, dir_);
299 fl.translate_axis(stem_y[dir_]*dy, Y_AXIS);
300 mol_p->add_molecule (fl);
303 if (head_l_arr_.size())
305 mol_p->translate_axis (note_delta_f (), X_AXIS);
311 Stem::note_delta_f () const
314 if (head_l_arr_.size())
316 Interval head_wid(0, head_l_arr_[0]->extent (X_AXIS).length ());
317 Real rule_thick(paper_l ()->rule_thickness ());
318 Interval stem_wid(-rule_thick/2, rule_thick/2);
319 if (stem_xdir_ == CENTER)
320 r = head_wid.center ();
322 r = head_wid[stem_xdir_] - stem_wid[stem_xdir_];
328 Stem::hpos_f () const
330 return note_delta_f () + Item::hpos_f ();
334 TODO: head_l_arr_/rest_l_arr_ in
337 Stem::do_substitute_element_pointer (Score_element*o,Score_element*n)
339 if (Note_head*h=dynamic_cast<Note_head*> (o))
340 head_l_arr_.substitute (h, dynamic_cast<Note_head*>(n));
341 if (Rest *r=dynamic_cast<Rest*> (o))
342 rest_l_arr_.substitute (r, dynamic_cast<Rest*>(n));
343 if (Beam* b = dynamic_cast<Beam*> (o))
347 beam_l_ = dynamic_cast<Beam*> (n);
350 beams_i_drul_[LEFT] = 0;
351 beams_i_drul_[RIGHT] = 0;
356 Staff_symbol_referencer::do_substitute_element_pointer (o,n);