X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fstem.cc;h=09193e06471d17d6488f5b52ccae5c01f70f27b2;hb=31653bf1d61a33ef8bc8c871d60c6b3452d04d28;hp=01d33597d6401dc1df3168be1518fab061335516;hpb=7f0a3b682bebc864fbca295deba301238d805274;p=lilypond.git diff --git a/lily/stem.cc b/lily/stem.cc index 01d33597d6..09193e0647 100644 --- a/lily/stem.cc +++ b/lily/stem.cc @@ -1,202 +1,354 @@ +/* + stem.cc -- implement Stem + + source file of the GNU LilyPond music typesetter + + (c) 1996, 1997--1998 Han-Wen Nienhuys + + TODO: This is way too hairy +*/ + #include "stem.hh" -#include "dimen.hh" #include "debug.hh" #include "paper-def.hh" -#include "notehead.hh" +#include "note-head.hh" #include "lookup.hh" #include "molecule.hh" #include "p-col.hh" #include "misc.hh" +#include "beam.hh" +#include "rest.hh" -const int STEMLEN=7; +IMPLEMENT_IS_TYPE_B1 (Stem,Item); -Stem::Stem(int c) //, Moment len) +Stem::~Stem () { - beams_left = 0; - beams_right = 0; - minnote = 1000; // invalid values - maxnote = -1000; - bot = top = 0; - flag = 4; - dir_i_ =0; - staff_center=c; - stemlen=0; - print_flag=true; - stem_xoffset=0; } +Stem::Stem () +{ + /* + TODO: staff-size + */ + beam_l_ = 0; + beams_left_i_ = 0; + beams_right_i_ = 0; + mult_i_ = 0; -IMPLEMENT_STATIC_NAME(Stem); + yextent_drul_[DOWN] = yextent_drul_[UP] = 0; + flag_i_ = 2; + dir_ = CENTER; + beam_dir_ = CENTER; + dir_forced_b_ = false; + stem_xdir_ = LEFT; + staff_size_i_ = 8; + + beam_gap_i_ = 0; +} + +Interval_t +Stem::head_positions () const +{ + Interval_t r; + for (int i =0; i < head_l_arr_.size (); i++) + { + int p = head_l_arr_[i]->position_i_; + r[BIGGER] = r[BIGGER] >? p; + r[SMALLER] = r[SMALLER] internote_f (); +} + +Real +Stem::stem_end_f () const +{ + return yextent_drul_[dir_]; +} + void -Stem::set_stemend(Real se) +Stem::set_stemend (Real se) { + // todo: margins + if (dir_ && dir_ * head_positions()[dir_] >= se*dir_) + warning (_ ("weird stem size; check for narrow beams")); - // todo: margins - if (! ((dir_i_ > 0 && se >= maxnote) || (se <= minnote && dir_i_ <0)) ) - warning("Weird stem size; check for narrow beams"); - - top = (dir_i_ < 0) ? maxnote : se; - bot = (dir_i_ < 0) ? se : minnote; - flag = dir_i_*abs(flag); + + yextent_drul_[dir_] = se; + yextent_drul_[Direction(-dir_)] = head_positions()[-dir_]; +} + +int +Stem::type_i () const +{ + return head_l_arr_[0]->balltype_i_; } void -Stem::add(Notehead *n) +Stem::add_head (Rhythmic_head *n) { - assert(status < PRECALCED); - - if (n->balltype == 1) - return; - int p = n->position; - if (p < minnote) - minnote = p; - if (p > maxnote) - maxnote = p; - heads.push(n); - n->add_dependency(this); + n->add_dependency (this); // ? + if (dynamic_cast (n)) + { + head_l_arr_.push ((Note_head*)n); + } + else if (dynamic_cast (n)) + { + rest_l_arr_.push ((Rest*)n); + } } +bool +Stem::invisible_b () const +{ + return (!head_l_arr_.size () || + head_l_arr_[0]->balltype_i_ <= 0); +} int -Stem::get_default_dir() +Stem::get_center_distance (Direction d) const { - if (dir_i_) - return dir_i_; - Real mean = (minnote+maxnote)/2; - return (mean > staff_center) ? -1: 1; + int staff_center = 0; + int distance = d*(head_positions()[d] - staff_center); + return distance >? 0; +} + +Direction +Stem::get_default_dir () const +{ + return (get_center_distance (UP) > + get_center_distance (DOWN)) + ? DOWN + : UP; +} + +Direction +Stem::get_dir () const +{ + return dir_; } void -Stem::set_default_dir() +Stem::set_default_dir () { - dir_i_ = get_default_dir(); + dir_ = get_default_dir (); } void -Stem::set_default_stemlen() -{ - if (!dir_i_) - set_default_dir(); - - int stafftop = 2*staff_center; - stemlen = STEMLEN + (maxnote - minnote); - - // uhh... how about non 5-line staffs? - if (maxnote < -2 && dir_i_ == 1){ - int t = staff_center - staff_center/2; - stemlen = t - minnote +2; - } else if (minnote > stafftop + 2 && dir_i_ == -1) { - int t = staff_center + staff_center/2; - stemlen = maxnote -t +2; - } +Stem::set_default_stemlen () +{ + /* + TODO + urg; this should be handled by Stem_info + */ - assert(stemlen); -} + Real length_f = paper ()->get_var ("stem_length"); + Real shorten_f = paper ()->get_var ("forced_stem_shorten"); + + Real internote_f = paper ()->internote_f (); + length_f /= internote_f; + shorten_f /= internote_f; + Real len = length_f; + if (!dir_) + set_default_dir (); + /* + stems in unnatural (forced) direction should be shortened, + accoding to [Roush & Gourlay] + */ + else if (dir_ != get_default_dir ()) + len -= shorten_f / internote_f; + if (flag_i_ >= 5) + len += 2.0; + if (flag_i_ >= 6) + len += 1.0; + + set_stemend ((dir_ > 0) ? head_positions()[BIGGER] + len : + head_positions()[SMALLER] - len); + + if (dir_ * stem_end_f () < 0) + { + set_stemend (0); + } +} +//xxx void -Stem::set_default_extents() +Stem::set_default_extents () { - if (minnote > maxnote) { - warning("Empty stem. Ugh!"); - minnote = -10; - maxnote = 20; - } + if (!stem_length_f ()) + set_default_stemlen (); - if (!stemlen) - set_default_stemlen(); - set_stemend((dir_i_< 0) ? maxnote-stemlen: minnote +stemlen); - if (dir_i_ > 0){ - stem_xoffset = paper()->note_width()-paper()->rule_thickness(); - } else - stem_xoffset = 0; + if (dir_ == UP) + stem_xdir_ = RIGHT; + if (invisible_b ()) + stem_xdir_ = CENTER; } +/* + TODO + + move into note_column.cc + + */ void -Stem::set_noteheads() -{ - if(!heads.size()) - return; - heads.sort(Notehead::compare); - heads[0]->extremal = -1; - heads.top()->extremal = 1; - int parity=1; - int lastpos = heads[0]->position; - for (int i=1; i < heads.size(); i ++) { - int dy =abs(lastpos- heads[i]->position); - - if (dy <= 1) { - if (parity) - heads[i]->x_dir = (stem_xoffset>0) ? 1:-1; - parity = !parity; - } else - parity = 0; - lastpos = heads[i]->position; +Stem::set_noteheads () +{ + if (!head_l_arr_.size ()) + return; + head_l_arr_.sort (Note_head::compare); + if (dir_ < 0) + head_l_arr_.reverse (); + + head_l_arr_[0]->extremal_i_ = -1; + head_l_arr_.top ()->extremal_i_ = 1; + int parity=1; + int lastpos = head_l_arr_[0]->position_i_; + for (int i=1; i < head_l_arr_.size (); i ++) + { + int dy =abs (lastpos- head_l_arr_[i]->position_i_); + + if (dy <= 1) + { + if (parity) + head_l_arr_[i]->x_dir_ = (stem_xdir_ == LEFT) ? LEFT : RIGHT; + parity = !parity; + } + else + parity = 1; + lastpos = head_l_arr_[i]->position_i_; } } void -Stem::do_pre_processing() +Stem::do_pre_processing () { - if (bot == top) - set_default_extents(); - set_noteheads(); + if (yextent_drul_[DOWN]== yextent_drul_[UP]) + set_default_extents (); + set_noteheads (); + flag_i_ = flag_i_; + transparent_b_ = invisible_b (); + set_empty (invisible_b ()); } Interval -Stem::do_width()const +Stem::do_width () const { - if (!print_flag || abs(flag) <= 4) - return Interval(0,0); // TODO! - Paper_def*p= paper(); - Interval r(p->lookup_l()->flag(flag).dim.x); - r+= stem_xoffset; - return r; + Interval r (0, 0); + if (beam_l_ || abs (flag_i_) <= 2) + ; // TODO! + else + { + r = lookup_l ()->flag (flag_i_, dir_).dim_.x (); + r += note_delta_f (); + } + return r; } + + + +const Real ANGLE = 20* (2.0*M_PI/360.0); // ugh! + Molecule* -Stem::brew_molecule_p()const return out; -{ - assert(bot!=top); - - - Paper_def *p =paper(); - - Real dy = p->internote(); - Symbol ss =p->lookup_l()->stem(bot*dy,top*dy); - - - out = new Molecule(Atom(ss)); - - if (print_flag&&abs(flag) > 4){ - Symbol fl = p->lookup_l()->flag(flag); - Molecule m(fl); - if (flag < -4){ - out->add_bottom(m); - } else if (flag > 4) { - out->add_top(m); - } else - assert(false); +Stem::brew_molecule_p () const +{ + Molecule *mol_p =new Molecule; + Drul_array stem_y = yextent_drul_; + Real dy = paper ()->internote_f (); + + + Real head_wid = 0; + if (head_l_arr_.size ()) + head_wid = head_l_arr_[0]->width ().length (); + stem_y[Direction(-dir_)] += dir_ * head_wid * tan(ANGLE)/(2*dy); + + if (!invisible_b ()) + { + Atom ss =lookup_l ()->stem (stem_y[DOWN]*dy, + stem_y[UP]*dy); + mol_p->add_atom (ss); + } + + if (!beam_l_ && abs (flag_i_) > 2) + { + Atom fl = lookup_l ()->flag (flag_i_, dir_); + fl.translate_axis(stem_y[dir_]*dy, Y_AXIS); + mol_p->add_atom (fl); } - out->translate(Offset(stem_xoffset,0)); + if (head_l_arr_.size()) + { + mol_p->translate_axis (note_delta_f (), X_AXIS); + } + return mol_p; } Real -Stem::hindex()const +Stem::note_delta_f () const { - return pcol_l_->hpos + stem_xoffset; // hmm. + offset_.x; + Real r=0; + if (head_l_arr_.size()) + { + Interval head_wid(0, head_l_arr_[0]->width ().length ()); + Real rule_thick(paper ()->rule_thickness ()); + Interval stem_wid(-rule_thick/2, rule_thick/2); + if (stem_xdir_ == CENTER) +#define EGCS_ICE +#ifndef EGCS_ICE + r = head_wid.center (); +#else + r = (head_wid.min () + head_wid.max ()) / 2; +#endif + else + r = head_wid[stem_xdir_] - stem_wid[stem_xdir_]; + } + return r; } +Real +Stem::hpos_f () const +{ + return note_delta_f () + Item::hpos_f (); +} +/* + TODO: head_l_arr_/rest_l_arr_ in do_substitute_dependent () + */ +void + Stem::do_substitute_dependency (Score_element*o,Score_element*n) +{ + Item * o_l = dynamic_cast (o); + Item * n_l = n? dynamic_cast (n) : 0; + head_l_arr_.substitute ((Note_head*)o_l, (Note_head*)n_l); + rest_l_arr_.substitute ((Rest*)o_l, (Rest*)n_l); +}