X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fslur-engraver.cc;h=b88afa21b03dde92b030f19788a2323c54f91e78;hb=14d74ac262744d16fc753ee41042d32860d58633;hp=3daf274d6b8144e08cea3e7c7db757f1cdb9d54b;hpb=e37010af17faa8b185de836664b6544bd29dc1d0;p=lilypond.git diff --git a/lily/slur-engraver.cc b/lily/slur-engraver.cc index 3daf274d6b..b88afa21b0 100644 --- a/lily/slur-engraver.cc +++ b/lily/slur-engraver.cc @@ -4,25 +4,26 @@ (c) 1997--2004 Han-Wen Nienhuys */ -#include "event.hh" #include "slur.hh" -#include "warn.hh" #include "note-column.hh" #include "context.hh" - +#include "directional-element-interface.hh" #include "engraver.hh" #include "spanner.hh" +#include "tie.hh" /* - TODO: junk nested slur functionality. - */ + It is possible that a slur starts and ends on the same note. At + least, it is for phrasing slurs: a note can be both beginning and + ending of a phrase. +*/ + class Slur_engraver : public Engraver { - Link_array events_; - Link_array new_slur_evs_; - Link_array slur_stack_; + Drul_array events_; + Music * running_slur_start_; + Link_array slurs_; Link_array end_slurs_; - Moment last_start_; void set_melisma (bool); @@ -39,46 +40,23 @@ public: Slur_engraver::Slur_engraver () { - last_start_ = Moment (-1); + events_[START] = events_[STOP] = 0; } bool -Slur_engraver::try_music (Music *ev) +Slur_engraver::try_music (Music *m) { - if (ev->is_mus_type ("slur-event")) + if (m->is_mus_type ("slur-event")) { - /* - Let's not start more than one slur per moment. - */ - Direction d = to_dir (ev->get_mus_property ("span-direction")); + Direction d = to_dir (m->get_property ("span-direction")); if (d == START) { - if (now_mom () > last_start_) - { - new_slur_evs_.push (ev); - last_start_ = now_mom (); - } - - /* - But we swallow other slur events. - */ - + events_[START] = m; return true; } else if (d == STOP) { - /* - Swallow other events. - */ - for (int j = new_slur_evs_.size(); j--;) - { - Direction nd = to_dir (new_slur_evs_[j]->get_mus_property ("span-direction")); - - if (nd == STOP) - return true; - } - - new_slur_evs_.push (ev); + events_[STOP] = m; return true; } } @@ -88,106 +66,102 @@ Slur_engraver::try_music (Music *ev) void Slur_engraver::set_melisma (bool m) { - daddy_context_->set_property ("slurMelismaBusy", m ? SCM_BOOL_T :SCM_BOOL_F); + context ()->set_property ("slurMelismaBusy", m ? SCM_BOOL_T :SCM_BOOL_F); } void Slur_engraver::acknowledge_grob (Grob_info info) { + Grob *e = info.grob_; if (Note_column::has_interface (info.grob_)) { - Grob *e =info.grob_; - for (int i = 0; i < slur_stack_.size (); i++) - Slur::add_column (slur_stack_[i], e); - for (int i = 0; i < end_slurs_.size (); i++) + for (int i = slurs_.size (); i--; ) + Slur::add_column (slurs_[i], e); + for (int i = end_slurs_.size (); i-- ; ) Slur::add_column (end_slurs_[i], e); } + else + { + SCM inside = e->get_property ("inside-slur"); + if (Tie::has_interface (e) + || to_boolean (inside)) + { + for (int i = slurs_.size (); i--; ) + Slur::add_extra_encompass (slurs_[i], e); + for (int i = end_slurs_.size (); i--; ) + Slur::add_extra_encompass (end_slurs_[i], e); + } + else if (inside == SCM_BOOL_F) + { + Grob *slur = slurs_.size()?slurs_[0] : 0; + slur = (end_slurs_.size () && !slur) + ? end_slurs_[0] : slur; + + if (slur) + { + e->add_offset_callback (Slur::outside_slur_callback_proc, Y_AXIS); + e->set_property ("slur", slur->self_scm()); + } + } + } } void Slur_engraver::finalize () { - for (int i = 0; i < slur_stack_.size (); i++) - { - /* - Let's not typeset unterminated stuff - */ - slur_stack_[i]->suicide (); - } - slur_stack_.clear (); - - for (int i=0; i < events_.size (); i++) - { - events_[i]->origin ()->warning (_ ("unterminated slur")); - } + if (slurs_.size ()) + slurs_[0]->warning (_("unterminated slur")); } void Slur_engraver::process_music () { - Link_array start_slurs; - for (int i=0; i< new_slur_evs_.size (); i++) + if (events_[STOP]) { - Music* slur_ev = new_slur_evs_[i]; - // end slur: move the slur to other array - Direction d = to_dir (slur_ev->get_mus_property ("span-direction")); - if (d== STOP) - { - if (slur_stack_.is_empty ()) - /* How to shut up this warning, when Voice_devnull_engraver has - eaten start event? */ - slur_ev->origin ()->warning (_f ("can't find start of slur")); - else - { - Grob* slur = slur_stack_.pop (); - - end_slurs_.push (slur); - events_.pop (); - } - } - else if (d == START) + if (slurs_.size() == 0) { - // push a new slur onto stack. - // (use temp. array to wait for all slur STOPs) - Grob* slur = make_spanner ("Slur"); - Slur::set_interface (slur); // cannot remove yet! - - - if (Direction updown = to_dir (slur_ev->get_mus_property ("direction"))) - { - slur->set_grob_property ("direction", gh_int2scm (updown)); - } - - start_slurs.push (slur); - events_.push (slur_ev); - announce_grob (slur, slur_ev->self_scm ()); + events_[STOP]->origin()->warning (_ ("No slur to end")); } + + end_slurs_ = slurs_; + slurs_.clear (); } + + if (events_[START] && slurs_.is_empty ()) + { + Music *ev = events_[START]; + + bool double_slurs = to_boolean (get_property ("doubleSlurs")); - slur_stack_.concat (start_slurs); + Grob * slur = make_spanner ("Slur", events_[START]->self_scm ()); + Direction updown = to_dir (ev->get_property ("direction")); + if (updown && !double_slurs) + set_grob_direction (slur, updown); - set_melisma (slur_stack_.size ()); + slurs_.push (slur); - new_slur_evs_.clear (); + if (double_slurs) + { + set_grob_direction (slur, DOWN); + slur = make_spanner ("Slur", events_[START]->self_scm ()); + set_grob_direction (slur, UP); + slurs_.push (slur); + } + } + set_melisma (slurs_.size ()); } void Slur_engraver::stop_translation_timestep () { - for (int i = 0; i < end_slurs_.size (); i++) - { - typeset_grob (end_slurs_[i]); - } end_slurs_.clear (); - new_slur_evs_.clear (); + events_[START] = events_[STOP] = 0; } - - -ENTER_DESCRIPTION (Slur_engraver, -/* descr */ "Build slurs from Slur_evs", -/* creats*/ "Slur", -/* accepts */ "slur-event", -/* acks */ "note-column-interface", -/* reads */ "slurMelismaBusy", -/* write */ ""); +ADD_TRANSLATOR (Slur_engraver, + /* descr */ "Build slurs grobs from slur events", + /* creats*/ "Slur", + /* accepts */ "slur-event", + /* acks */ "note-column-interface accidental-interface fingering-interface script-interface tie-interface text-script-interface", + /* reads */ "slurMelismaBusy doubleSlurs", + /* write */ "");