]> git.donarmstrong.com Git - lilypond.git/commitdiff
Fixes issue 786, "Extenders in lyrics stop prematurely if a single underscore is...
authorChris Snyder <csnyder@adoromusicpub.com>
Fri, 13 Nov 2009 20:11:24 +0000 (20:11 +0000)
committerNeil Puttock <n.puttock@gmail.com>
Fri, 13 Nov 2009 20:14:39 +0000 (20:14 +0000)
This commit changes the lyrics engraver to create LyricText objects
even for empty lyrics (underscores). This change is necessary because
the old behavior (pre-7531ea6b3 commit) relied on extenders continuing
until the presence of another lyric syllable, which was not always the case.
That commit changed the behavior to completize extenders when no more lyrics
were present, which fixed the neverending-extender bug but introduced the
extenders-stopping-prematurely bug.

By adding the empty LyricText objects, the extender engraver can now tell the
difference between melismas and the end of a block of lyrics.

lily/extender-engraver.cc
lily/hyphen-engraver.cc
lily/lyric-engraver.cc

index 041f9046ed470e9ee45a6ecbdfc0ff7d7c22784f..a46489be399ccf6f710a2e68b4e8652478894996 100644 (file)
@@ -7,7 +7,6 @@
   Han-Wen Nienhuys <hanwen@xs4all.nl>,
   Jan Nieuwenhuizen <janneke@gnu.org>
 */
-
 #include "context.hh"
 #include "engraver.hh"
 #include "international.hh"
@@ -18,6 +17,7 @@
 #include "stream-event.hh"
 #include "warn.hh"
 #include "spanner.hh"
+#include "paper-column.hh"
 
 #include "translator.icc"
 
@@ -28,6 +28,7 @@ class Extender_engraver : public Engraver
   Stream_event *ev_;
   Spanner *extender_;
   Spanner *pending_extender_;
+  bool current_lyric_is_skip_;
 
 public:
   TRANSLATOR_DECLARATIONS (Extender_engraver);
@@ -44,6 +45,7 @@ protected:
 
 Extender_engraver::Extender_engraver ()
 {
+  current_lyric_is_skip_ = false;
   extender_ = 0;
   pending_extender_ = 0;
   ev_ = 0;
@@ -70,7 +72,10 @@ Extender_engraver::acknowledge_lyric_syllable (Grob_info i)
   if (extender_)
     extender_->set_bound (LEFT, item);
 
-  if (pending_extender_)
+  SCM text = item->get_property ("text");
+  current_lyric_is_skip_ = ly_is_equal (text, scm_from_locale_string (" "));
+
+  if (pending_extender_ && !current_lyric_is_skip_)
     {
       pending_extender_->set_object ("next", item->self_scm ());
       completize_extender (pending_extender_);
@@ -94,17 +99,31 @@ Extender_engraver::stop_translation_timestep ()
                                                 ly_symbol2scm ("heads"), h);
            }
 
-         if (pending_extender_)
-           {
-             Pointer_group_interface::add_grob (pending_extender_,
-                                                ly_symbol2scm ("heads"), h);
-             if (!melisma_busy (voice))
-               {
-                 completize_extender (pending_extender_);
-                 pending_extender_ = 0;
-               }
-           }
-       }
+        if (pending_extender_)
+          {
+            Pointer_group_interface::add_grob (pending_extender_,
+                                              ly_symbol2scm ("heads"), h);
+            /*
+              The following check addresses the case where the lyrics end before
+              the associated voice. The current_lyric_is_skip_ check is
+              necessary to handle manual melismata, which should not result in
+              extenders being completized. We also need to make sure that we're not
+              in the middle of a note (happens when this function is called because
+              of an event in a voice other than our associated one).
+            */
+            if (!melisma_busy (voice) && !current_lyric_is_skip_)
+              {
+                Moment now = voice->now_mom ();
+                Paper_column *column = (dynamic_cast<Item *> (h))->get_column ();
+                Moment *start_mom = column ? unsmob_moment (column->get_property ("when")) : 0;
+                if (!column || (start_mom->main_part_ == now.main_part_))
+                  {
+                    completize_extender (pending_extender_);
+                    pending_extender_ = 0;
+                  }
+              }
+            }
+        }
       else
        {
          if (pending_extender_
index 3a1684491b208f711d75bd491b8cefdbedaaf983..27e85f3f59f880fc9c3d02f905014be9c428551f 100644 (file)
@@ -25,6 +25,7 @@ class Hyphen_engraver : public Engraver
 
   Spanner *hyphen_;
   Spanner *finished_hyphen_;
+  bool current_lyric_is_skip_;
 
 public:
   TRANSLATOR_DECLARATIONS (Hyphen_engraver);
@@ -42,6 +43,7 @@ protected:
 
 Hyphen_engraver::Hyphen_engraver ()
 {
+  current_lyric_is_skip_ = false;
   hyphen_ = 0;
   finished_hyphen_ = 0;
   finished_ev_ = 0;
@@ -52,14 +54,16 @@ void
 Hyphen_engraver::acknowledge_lyric_syllable (Grob_info i)
 {
   Item *item = i.item ();
+  SCM text = item->get_property ("text");
+  current_lyric_is_skip_ = ly_is_equal (text, scm_from_locale_string (" "));
   
-  if (!hyphen_)
+  if (!hyphen_ && !current_lyric_is_skip_)
     hyphen_ = make_spanner ("LyricSpace", item->self_scm ());
 
   if (hyphen_)
     hyphen_->set_bound (LEFT, item);
       
-  if (finished_hyphen_)
+  if (finished_hyphen_ && !current_lyric_is_skip_)
     finished_hyphen_->set_bound (RIGHT, item);
 }
 
@@ -127,7 +131,7 @@ Hyphen_engraver::stop_translation_timestep ()
       finished_ev_ = 0;
     }
   
-  if (finished_hyphen_ && hyphen_)
+  if (finished_hyphen_ && hyphen_ && !current_lyric_is_skip_)
     {
       programming_error ("hyphen not finished yet");
       finished_hyphen_ = 0;
index 74d15e4df1faedef65fddc857260b3fe33c46c5e..bf86b0a6b480094af82643e739e2232fc929aee8 100644 (file)
@@ -64,8 +64,11 @@ Lyric_engraver::process_music ()
          if (last_text_)
            last_text_->set_property ("self-alignment-X", scm_from_int (LEFT));
        }
-      else
-       text_ = make_item ("LyricText", event_->self_scm ());
+      /*
+        "Empty" LyricText objects are needed to allow the Extender_engraver to
+        distinguish between the end of a lyrics block and manual melismata.
+      */
+      text_ = make_item ("LyricText", event_->self_scm ());
     }
 }