]> git.donarmstrong.com Git - lilypond.git/blobdiff - lily/ligature-engraver.cc
Run grand-replace (issue 3765)
[lilypond.git] / lily / ligature-engraver.cc
index 1480a4d3c3985e8c0b4063b12144729cff4d0a92..8bd4d66137b4907c832bd0981ce739f507d81ed3 100644 (file)
@@ -1,20 +1,30 @@
 /*
-  ligature-engraver.cc -- implement Ligature_engraver
+  This file is part of LilyPond, the GNU music typesetter.
 
-  source file of the GNU LilyPond music typesetter
+  Copyright (C) 2002--2014 Juergen Reuter <reuter@ipd.uka.de>
 
-  (c) 2002--2005 Juergen Reuter <reuter@ipd.uka.de>
+  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 "ligature-engraver.hh"
 
-#include "spanner.hh"
-#include "score-engraver.hh"
+#include "context.hh"
+#include "international.hh"
 #include "note-head.hh"
 #include "rest.hh"
-#include "warn.hh"
-#include "context.hh"
-
+#include "spanner.hh"
+#include "stream-event.hh"
 #include "translator.icc"
 
 /*
@@ -26,7 +36,7 @@
  *
  * A concrete ligature engraver must subclass this class and provide
  * functions create_ligature_spanner () and typeset_ligature
- * (Spanner *, Array<Grob_info>).  Subclasses of this class basically
+ * (Spanner *, vector<Grob_info>).  Subclasses of this class basically
  * fall into two categories.
  *
  * The first category consists of engravers that engrave ligatures in
  * produce a single connected graphical object of fixed width,
  * consisting of noteheads and other primitives.  Space may be
  * inserted only after each ligature, if necessary, but in no case
- * between the primitives of the ligature.  Accidentals have to be put
+ * between the primitives of the ligature. The same approach is
+ * used for Kievan notation ligatures, or, rather melismas.
+ * Though these are not single connected objects, they behave much
+ * in the same way and have a fixed, small amount of space between
+ * noteheads. Except in Kievan "ligatures", accidentals have to be put
  * to the left of the ligature, and not to the left of individual
- * noteheads.  Class Coherent_ligature_engraver is the common
+ * noteheads. In Kievan ligatures, the B-flat may be part of the
+ * ligature itself. Class Coherent_ligature_engraver is the common
  * superclass for all of these engravers.
  *
  * The second category is for engravers that are relaxed in the sense
@@ -77,62 +92,11 @@ Ligature_engraver::Ligature_engraver ()
   brew_ligature_primitive_proc = SCM_EOL;
 }
 
-bool
-Ligature_engraver::try_music (Music *m)
-{
-  if (m->is_mus_type ("ligature-event"))
-    {
-      Direction d = to_dir (m->get_property ("span-direction"));
-      events_drul_[d] = m;
-      return true;
-    }
-  return false;
-}
-
-/*
- * This method should do something that comes close to the following
- * .ly snippet:
- *
- * \property Voice.NoteHead \override #'print-function =
- *     < value of #'ligature-primitive-callback of Voice.NoteHead >
- *
- * TODO: What we are doing here on the c++ level, should actually be
- * performed on the SCM level.  However, I do not know how to teach
- * lilypond to apply an \override and \revert on #'print-function,
- * whenever lily encounters a \[ and \] in an .ly file, respectively.
- * Also encounter, that lily should not crash if a user erronously
- * nests \[ and \].
- */
-void
-Ligature_engraver::override_stencil_callback ()
-{
-  SCM target_callback = ly_symbol2scm ("print-function");
-  SCM source_callback = ly_symbol2scm ("ligature-primitive-callback");
-  SCM noteHeadProperties = updated_grob_properties (context (), ly_symbol2scm ("NoteHead"));
-  SCM value = scm_cdr (scm_sloppy_assq (source_callback, noteHeadProperties));
-  execute_pushpop_property (context (), ly_symbol2scm ("NoteHead"),
-                           target_callback, value);
-}
-
-/*
- * This method should do something that comes close to the following
- * .ly snippet:
- *
- * \property Voice.NoteHead \revert #'print-function
- *
- * TODO: What we are doing here on the c++ level, should actually be
- * performed on the SCM level.  However, I do not know how to teach
- * lilypond to apply an \override and \revert on #'print-function,
- * whenever lily encounters a \[ and \] in an .ly file, respectively.
- * Also encounter, that lily should not crash if a user erronously
- * nests \[ and \].
- */
 void
-Ligature_engraver::revert_stencil_callback ()
+Ligature_engraver::listen_ligature (Stream_event *ev)
 {
-  SCM symbol = ly_symbol2scm ("NoteHead");
-  SCM key = ly_symbol2scm ("print-function");
-  execute_pushpop_property (context (), symbol, key, SCM_UNDEFINED);
+  Direction d = to_dir (ev->get_property ("span-direction"));
+  ASSIGN_EVENT_ONCE (events_drul_[d], ev);
 }
 
 void
@@ -141,57 +105,51 @@ Ligature_engraver::process_music ()
   if (events_drul_[STOP])
     {
       if (!ligature_)
-       {
-         events_drul_[STOP]->origin ()->warning (_ ("can't find start of ligature"));
-         return;
-       }
+        {
+          events_drul_[STOP]->origin ()->warning (_ ("cannot find start of ligature"));
+          return;
+        }
 
       if (!last_bound_)
-       events_drul_[STOP]->origin ()->warning (_ ("no right bound"));
+        events_drul_[STOP]->origin ()->warning (_ ("no right bound"));
       else
-       ligature_->set_bound (RIGHT, last_bound_);
+        ligature_->set_bound (RIGHT, last_bound_);
 
       prev_start_event_ = 0;
       finished_primitives_ = primitives_;
       finished_ligature_ = ligature_;
       primitives_.clear ();
       ligature_ = 0;
-      revert_stencil_callback ();
     }
   last_bound_ = unsmob_grob (get_property ("currentMusicalColumn"));
 
   if (ligature_)
     {
       // TODO: maybe forbid breaks only if not transcribing
-      get_score_engraver ()->forbid_breaks ();
+      context ()->get_score_context ()->set_property ("forbidBreak", SCM_BOOL_T);
     }
 
   if (events_drul_[START])
     {
       if (ligature_)
-       {
-         events_drul_[START]->origin ()->warning (_ ("already have a ligature"));
-         return;
-       }
+        {
+          events_drul_[START]->origin ()->warning (_ ("already have a ligature"));
+          return;
+        }
 
       prev_start_event_ = events_drul_[START];
       ligature_ = create_ligature_spanner ();
-      brew_ligature_primitive_proc
-       = ligature_->get_property ("ligature-primitive-callback");
-      if (brew_ligature_primitive_proc == SCM_EOL)
-       programming_error ("Ligature_engraver: ligature-primitive-callback undefined");
 
       Grob *bound = unsmob_grob (get_property ("currentMusicalColumn"));
       if (!bound)
-       events_drul_[START]->origin ()->warning (_ ("no left bound"));
+        events_drul_[START]->origin ()->warning (_ ("no left bound"));
       else
-       ligature_->set_bound (LEFT, bound);
+        ligature_->set_bound (LEFT, bound);
 
       ligature_start_mom_ = now_mom ();
 
-      // TODO: dump cause into make_item/spanner. 
+      // TODO: dump cause into make_item/spanner.
       // announce_grob (ligature_, events_drul_[START]->self_scm ());
-      override_stencil_callback ();
     }
 }
 
@@ -201,15 +159,15 @@ Ligature_engraver::stop_translation_timestep ()
   if (finished_ligature_)
     {
       if (!finished_primitives_.size ())
-       {
-         finished_ligature_->programming_error ("Ligature_engraver::stop_translation_timestep (): "
-                                                "junking empty ligature");
-       }
+        {
+          finished_ligature_->programming_error ("Ligature_engraver::stop_translation_timestep ():"
+                                                 " junking empty ligature");
+        }
       else
-       {
-         typeset_ligature (finished_ligature_, finished_primitives_);
-         finished_primitives_.clear ();
-       }
+        {
+          typeset_ligature (finished_ligature_, finished_primitives_);
+          finished_primitives_.clear ();
+        }
       finished_ligature_ = 0;
     }
 
@@ -240,16 +198,13 @@ Ligature_engraver::current_ligature ()
 }
 
 void
-Ligature_engraver::acknowledge_note_head (Grob_info info)
+Ligature_engraver::acknowledge_ligature_head (Grob_info info)
 {
   if (ligature_)
     {
-      primitives_.push (info);
-      if (info.grob ())
-       {
-         info.grob ()->set_callback (ly_symbol2scm ("stencil"),
-                                     brew_ligature_primitive_proc);
-       }
+      primitives_.push_back (info);
+      if (info.grob () && brew_ligature_primitive_proc != SCM_EOL)
+        info.grob ()->set_property ("stencil", brew_ligature_primitive_proc);
     }
 }
 
@@ -258,7 +213,7 @@ Ligature_engraver::acknowledge_rest (Grob_info info)
 {
   if (ligature_)
     {
-      info.music_cause ()->origin ()->warning (_ ("ignoring rest: ligature may not contain rest"));
+      info.event_cause ()->origin ()->warning (_ ("ignoring rest: ligature may not contain rest"));
       prev_start_event_->origin ()->warning (_ ("ligature was started here"));
       // TODO: maybe better should stop ligature here rather than
       // ignoring the rest?