X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fcompletion-note-heads-engraver.cc;h=a2c606f472897c58c6c17d221aa806902114a9dc;hb=e90f0536f9be39ada0bef0aeb0d275dec3b2fb5b;hp=b4c4afb0877a7a945e2c385d2eb6cb0fbee262be;hpb=a8c9e8a7ca320ab0df5fd32e717fd62cd7635ce6;p=lilypond.git diff --git a/lily/completion-note-heads-engraver.cc b/lily/completion-note-heads-engraver.cc index b4c4afb087..a2c606f472 100644 --- a/lily/completion-note-heads-engraver.cc +++ b/lily/completion-note-heads-engraver.cc @@ -1,7 +1,20 @@ /* - completion-note-heads-engraver.cc -- Completion_heads_engraver + This file is part of LilyPond, the GNU music typesetter. - (c) 1997--2009 Han-Wen Nienhuys + Copyright (C) 1997--2011 Han-Wen Nienhuys + + LilyPond is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + LilyPond is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with LilyPond. If not, see . */ #include @@ -14,33 +27,17 @@ using namespace std; #include "item.hh" #include "output-def.hh" #include "pitch.hh" -#include "pqueue.hh" #include "rhythmic-head.hh" #include "score-engraver.hh" #include "spanner.hh" #include "staff-symbol-referencer.hh" #include "stream-event.hh" #include "tie.hh" +#include "tie-column.hh" #include "warn.hh" #include "translator.icc" -/* - TODO: make matching rest engraver. -*/ -struct Pending_tie -{ - Moment when_; - Stream_event* tie_event_; - Pending_tie() { tie_event_ = 0; } -}; - -int compare(Pending_tie const &a, Pending_tie const &b) -{ - return compare(a.when_, b.when_); -} - - /* How does this work? @@ -58,24 +55,22 @@ int compare(Pending_tie const &a, Pending_tie const &b) class Completion_heads_engraver : public Engraver { - vector notes_; - vector prev_notes_; - + vector notes_; + vector prev_notes_; // Must remember notes for explicit ties. - vector tie_note_candidates_; - vector tie_note_candidate_events_; - vector ties_; - PQueue pending_ties_; - vector note_events_; - - Stream_event *current_tie_event_; + vector tie_note_candidates_; + vector tie_note_candidate_events_; + vector ties_; + vector note_events_; + Spanner *tie_column_; Moment note_end_mom_; bool is_first_; Rational left_to_do_; Rational do_nothing_until_; + Rational factor_; Moment next_barline_moment (); - Item *make_note_head (Stream_event*); + Item *make_note_head (Stream_event *); public: TRANSLATOR_DECLARATIONS (Completion_heads_engraver); @@ -87,14 +82,12 @@ protected: void process_music (); void stop_translation_timestep (); DECLARE_TRANSLATOR_LISTENER (note); - DECLARE_TRANSLATOR_LISTENER (tie); }; void Completion_heads_engraver::initialize () { is_first_ = false; - current_tie_event_ = 0; } IMPLEMENT_TRANSLATOR_LISTENER (Completion_heads_engraver, note); @@ -102,7 +95,7 @@ void Completion_heads_engraver::listen_note (Stream_event *ev) { note_events_.push_back (ev); - + is_first_ = true; Moment now = now_mom (); Moment musiclen = get_event_length (ev, now); @@ -111,16 +104,8 @@ Completion_heads_engraver::listen_note (Stream_event *ev) do_nothing_until_ = Rational (0, 0); } -IMPLEMENT_TRANSLATOR_LISTENER (Completion_heads_engraver, tie); -void -Completion_heads_engraver::listen_tie (Stream_event *ev) -{ - is_first_ = true; - current_tie_event_ = ev; -} - /* - The duration _until_ the next barline. + The duration _until_ the next bar line. */ Moment Completion_heads_engraver::next_barline_moment () @@ -135,7 +120,7 @@ Completion_heads_engraver::next_barline_moment () return (*l - *e); } -Item* +Item * Completion_heads_engraver::make_note_head (Stream_event *ev) { Item *note = make_item ("NoteHead", ev->self_scm ()); @@ -157,14 +142,6 @@ Completion_heads_engraver::process_music () if (!is_first_ && !left_to_do_) return; - if (current_tie_event_) - { - Pending_tie pending; - pending.when_ = note_end_mom_; - pending.tie_event_ = current_tie_event_; - pending_ties_.insert (pending); - } - is_first_ = false; Moment now = now_mom (); @@ -174,22 +151,33 @@ Completion_heads_engraver::process_music () Duration note_dur; Duration *orig = 0; if (left_to_do_) - note_dur = Duration (left_to_do_, false); + { + /* + note that note_dur may be strictly less than left_to_do_ + (say, if left_to_do_ == 5/8) + */ + if (factor_.denominator () == 1 && factor_ > Rational (1, 1)) + note_dur = Duration (left_to_do_, false); + else + note_dur = Duration (left_to_do_ / factor_, false).compressed (factor_); + } else { orig = unsmob_duration (note_events_[0]->get_property ("duration")); note_dur = *orig; + factor_ = note_dur.factor (); + left_to_do_ = orig->get_length (); } Moment nb = next_barline_moment (); if (nb.main_part_ && nb < note_dur.get_length ()) { - note_dur = Duration (nb.main_part_, false); - - do_nothing_until_ = now.main_part_ + note_dur.get_length (); + if (factor_.denominator () == 1 && factor_ > Rational (1, 1)) + note_dur = Duration (nb.main_part_, false); + else + note_dur = Duration (nb.main_part_ / factor_, false).compressed (factor_); } - if (orig) - left_to_do_ = orig->get_length (); + do_nothing_until_ = now.main_part_ + note_dur.get_length (); for (vsize i = 0; left_to_do_ && i < note_events_.size (); i++) { @@ -200,41 +188,42 @@ Completion_heads_engraver::process_music () event = event->clone (); SCM pits = note_events_[i]->get_property ("pitch"); - event->set_property ("pitch", pits); event->set_property ("duration", note_dur.smobbed_copy ()); event->set_property ("length", Moment (note_dur.get_length ()).smobbed_copy ()); event->set_property ("duration-log", scm_from_int (note_dur.duration_log ())); + /* + The Completion_heads_engraver splits an event into a group of consecutive events. + For each event in the group, the property "autosplit-end" denotes whether the current event + was truncated during splitting. Based on "autosplit-end", the Tie_engraver decides whether a + tie event should be processed. + */ + event->set_property ("autosplit-end", + ly_bool2scm (left_to_do_ - note_dur.get_length () > Rational (0))); + Item *note = make_note_head (event); if (need_clone) event->unprotect (); notes_.push_back (note); } - - if (pending_ties_.size () - && pending_ties_.front().when_ == now_mom()) - { - for (vsize i = 0; i < tie_note_candidate_events_.size(); i++) - for (vsize j = 0; j < note_events_.size(); j++) - { - Pitch *p = unsmob_pitch (note_events_[j]->get_property ("pitch")); - Pitch *p_last - = unsmob_pitch (tie_note_candidate_events_[j]->get_property ("pitch")); - if (p && p_last && *p == *p_last) - make_tie (tie_note_candidates_[i], notes_[j]); - } - } - + if (prev_notes_.size () == notes_.size ()) { for (vsize i = 0; i < notes_.size (); i++) make_tie (prev_notes_[i], notes_[i]); } + if (ties_.size () && !tie_column_) + tie_column_ = make_spanner ("TieColumn", ties_[0]->self_scm ()); + + if (tie_column_) + for (vsize i = ties_.size (); i--;) + Tie_column::add_tie (tie_column_, ties_[i]); + left_to_do_ -= note_dur.get_length (); if (left_to_do_) - get_global_context ()->add_moment_to_process (now.main_part_ + note_dur.get_length()); + get_global_context ()->add_moment_to_process (now.main_part_ + note_dur.get_length ()); /* don't do complicated arithmetic with grace notes. */ @@ -250,11 +239,12 @@ Completion_heads_engraver::make_tie (Grob *left, Grob *right) Tie::set_head (p, RIGHT, right); ties_.push_back (p); } - + void Completion_heads_engraver::stop_translation_timestep () { ties_.clear (); + tie_column_ = 0; if (notes_.size ()) prev_notes_ = notes_; @@ -265,11 +255,6 @@ void Completion_heads_engraver::start_translation_timestep () { Moment now = now_mom (); - while (pending_ties_.size() && pending_ties_.front().when_ < now) - { - pending_ties_.delmin(); - } - current_tie_event_ = 0; if (note_end_mom_.main_part_ <= now.main_part_) { tie_note_candidate_events_ = note_events_; @@ -284,6 +269,7 @@ Completion_heads_engraver::start_translation_timestep () Completion_heads_engraver::Completion_heads_engraver () { + tie_column_ = 0; } ADD_TRANSLATOR (Completion_heads_engraver, @@ -294,13 +280,14 @@ ADD_TRANSLATOR (Completion_heads_engraver, /* create */ "NoteHead " - "Dots " - "Tie ", + "Tie " + "TieColumn ", /* read */ - "middleCPosition " + "measureLength " "measurePosition " - "measureLength ", + "middleCPosition " + "timing ", /* write */ "completionBusy "