X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fchord-tremolo-engraver.cc;h=9e48a1a4908d5a21bf0c0e59a9242483979f4dd3;hb=a6a51abfd0195a3cf7d6ea095cf69808852f21ce;hp=b0f17352baa49915e771c4b92d8d23f1fe34b60e;hpb=c4c0ba811cd526f047de3f4d3c77abcc32a3e076;p=lilypond.git diff --git a/lily/chord-tremolo-engraver.cc b/lily/chord-tremolo-engraver.cc index b0f17352ba..9e48a1a490 100644 --- a/lily/chord-tremolo-engraver.cc +++ b/lily/chord-tremolo-engraver.cc @@ -1,10 +1,21 @@ /* - chord-tremolo-engraver.cc -- implement Chord_tremolo_engraver + This file is part of LilyPond, the GNU music typesetter. - source file of the GNU LilyPond music typesetter + Copyright (C) 2000--2015 Han-Wen Nienhuys + Erik Sandberg - (c) 2000--2006 Han-Wen Nienhuys - Erik Sandberg + 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 "beam.hh" @@ -43,49 +54,41 @@ class Chord_tremolo_engraver : public Engraver protected: Stream_event *repeat_; - int flags_; - // number of beams for short tremolos - int expected_beam_count_; - // current direction of beam (first RIGHT, then LEFT) - Direction beam_dir_; - Spanner *beam_; + // Store the pointer to the previous stem, so we can create a beam if + // necessary and end the spanner + Grob *previous_stem_; + protected: virtual void finalize (); void process_music (); - DECLARE_TRANSLATOR_LISTENER (tremolo_span); - DECLARE_ACKNOWLEDGER (stem); + void listen_tremolo_span (Stream_event *); + void acknowledge_stem (Grob_info); }; -Chord_tremolo_engraver::Chord_tremolo_engraver () +Chord_tremolo_engraver::Chord_tremolo_engraver (Context *c) + : Engraver (c) { beam_ = 0; repeat_ = 0; - flags_ = 0; - expected_beam_count_ = 0; - beam_dir_ = CENTER; + previous_stem_ = 0; } -IMPLEMENT_TRANSLATOR_LISTENER (Chord_tremolo_engraver, tremolo_span); void Chord_tremolo_engraver::listen_tremolo_span (Stream_event *ev) { Direction span_dir = to_dir (ev->get_property ("span-direction")); if (span_dir == START) { - repeat_ = ev; - int type = scm_to_int (ev->get_property ("tremolo-type")); - /* e.g. 1 for type 8, 2 for type 16 */ - flags_ = intlog2 (type) - 2; - expected_beam_count_ = scm_to_int (ev->get_property ("expected-beam-count")); - beam_dir_ = RIGHT; + ASSIGN_EVENT_ONCE (repeat_, ev); } else if (span_dir == STOP) { + if (!repeat_) + ev->origin ()->warning (_ ("No tremolo to end")); repeat_ = 0; beam_ = 0; - expected_beam_count_ = 0; - beam_dir_ = CENTER; + previous_stem_ = 0; } } @@ -104,6 +107,7 @@ Chord_tremolo_engraver::finalize () if (beam_) { repeat_->origin ()->warning (_ ("unterminated chord tremolo")); + announce_end_grob (beam_, SCM_EOL); beam_->suicide (); } } @@ -113,33 +117,64 @@ Chord_tremolo_engraver::acknowledge_stem (Grob_info info) { if (beam_) { - Grob *s = info.grob (); + int tremolo_type = robust_scm2int (repeat_->get_property ("tremolo-type"), 1); + int flags = max (0, intlog2 (tremolo_type) - 2); + int repeat_count = robust_scm2int (repeat_->get_property ("repeat-count"), 1); + int gap_count = min (flags, intlog2 (repeat_count) + 1); - Stem::set_beaming (s, flags_, beam_dir_); + Grob *s = info.grob (); + if (previous_stem_) + { + // FIXME: We know that the beam has ended only in listen_tremolo_span + // but then it is too late for Spanner_break_forbid_engraver + // to allow a line break... So, as a nasty hack, announce the + // spanner's end after each note except the first. The only + // "drawback" is that for multi-note tremolos a break would + // theoretically be allowed after the second note (but since + // that note is typically not at a barline, I don't think + // anyone will ever notice!) + announce_end_grob (beam_, previous_stem_->self_scm ()); + // Create the whole beam between previous and current note + Stem::set_beaming (previous_stem_, flags, RIGHT); + Stem::set_beaming (s, flags, LEFT); + } if (Stem::duration_log (s) != 1) - beam_->set_property ("gap-count", scm_from_int (flags_ - expected_beam_count_)); - - if (beam_dir_ == RIGHT) - beam_dir_ = LEFT; + beam_->set_property ("gap-count", scm_from_int (gap_count)); - if (info.ultimate_music_cause ()->is_mus_type ("rhythmic-event")) - Beam::add_stem (beam_, s); + if (info.ultimate_event_cause ()->in_event_class ("rhythmic-event")) + Beam::add_stem (beam_, s); else - { - string s = _ ("stem must have Rhythmic structure"); - if (info.music_cause ()) - info.music_cause ()->origin ()->warning (s); - else - ::warning (s); - } + { + string s = _ ("stem must have Rhythmic structure"); + if (info.event_cause ()) + info.event_cause ()->origin ()->warning (s); + else + ::warning (s); + } + // Store current grob, so we can possibly end the spanner here (and + // reset the beam direction to RIGHT) + previous_stem_ = s; } } -ADD_ACKNOWLEDGER (Chord_tremolo_engraver, stem); +void +Chord_tremolo_engraver::boot () +{ + ADD_LISTENER (Chord_tremolo_engraver, tremolo_span); + ADD_ACKNOWLEDGER (Chord_tremolo_engraver, stem); +} + ADD_TRANSLATOR (Chord_tremolo_engraver, - /* doc */ "Generates beams for tremolo repeats.", - /* create */ "Beam", - /* accept */ "tremolo-span-event", - /* read */ "", - /* write */ ""); + /* doc */ + "Generate beams for tremolo repeats.", + + /* create */ + "Beam ", + + /* read */ + "", + + /* write */ + "" + );