]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/chord-tremolo-engraver.cc
Run grand-replace (issue 3765)
[lilypond.git] / lily / chord-tremolo-engraver.cc
index 805cb52554a864eb5e50bb8a71085314e492883d..0e7d79525f4c47027be0e5780e37d129769065d6 100644 (file)
@@ -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--2014 Han-Wen Nienhuys <hanwen@xs4all.nl>
+                 Erik Sandberg <mandolaerik@gmail.com>
 
-  (c) 2000--2007 Han-Wen Nienhuys <hanwen@xs4all.nl>
-                Erik Sandberg <mandolaerik@gmail.com>
+  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 <http://www.gnu.org/licenses/>.
 */
 
 #include "beam.hh"
@@ -43,13 +54,11 @@ 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 ();
@@ -61,9 +70,7 @@ Chord_tremolo_engraver::Chord_tremolo_engraver ()
 {
   beam_ = 0;
   repeat_ = 0;
-  flags_ = 0;
-  expected_beam_count_ = 0;
-  beam_dir_ = CENTER;
+  previous_stem_ = 0;
 }
 
 IMPLEMENT_TRANSLATOR_LISTENER (Chord_tremolo_engraver, tremolo_span);
@@ -73,23 +80,15 @@ Chord_tremolo_engraver::listen_tremolo_span (Stream_event *ev)
   Direction span_dir = to_dir (ev->get_property ("span-direction"));
   if (span_dir == START)
     {
-      if (ASSIGN_EVENT_ONCE (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"));
+        ev->origin ()->warning (_ ("No tremolo to end"));
       repeat_ = 0;
       beam_ = 0;
-      expected_beam_count_ = 0;
-      beam_dir_ = CENTER;
+      previous_stem_ = 0;
     }
 }
 
@@ -118,35 +117,58 @@ 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;
-         announce_end_grob (beam_, s->self_scm ());
-       }
-      
+        beam_->set_property ("gap-count", scm_from_int (gap_count));
+
       if (info.ultimate_event_cause ()->in_event_class ("rhythmic-event"))
-       Beam::add_stem (beam_, s);
+        Beam::add_stem (beam_, s);
       else
-       {
-         string s = _ ("stem must have Rhythmic structure");
-         if (info.event_cause ())
-           info.event_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);
 ADD_TRANSLATOR (Chord_tremolo_engraver,
-               /* doc */ "Generates beams for tremolo repeats.",
-               /* create */ "Beam",
-               /* read */ "",
-               /* write */ "");
+                /* doc */
+                "Generate beams for tremolo repeats.",
+
+                /* create */
+                "Beam ",
+
+                /* read */
+                "",
+
+                /* write */
+                ""
+               );