/*
- 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--2011 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"
/*
* This abstract class provides the general framework for ligatures of
*
* 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
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;
-}
-
-Spanner *
-Ligature_engraver::create_ligature_spanner ()
-{
- programming_error ("Ligature_engraver::create_ligature_spanner (): "
- "this is an abstract method that should not be called, "
- "but overridden by a subclass");
- return 0;
-}
-
-/*
- * 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
{
if (!ligature_)
{
- events_drul_[STOP]->origin ()->warning (_ ("can't find start of ligature"));
+ 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])
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 ();
}
}
-void
-Ligature_engraver::typeset_ligature (Spanner *, Array<Grob_info>)
-{
- programming_error ("Ligature_engraver::typeset_ligature (): "
- "this is an abstract method that should not be called, "
- "but overridden by a subclass");
-}
-
void
Ligature_engraver::stop_translation_timestep ()
{
{
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
{
}
void
-Ligature_engraver::acknowledge_note_head (Grob_info info)
+Ligature_engraver::acknowledge_ligature_head (Grob_info info)
{
if (ligature_)
{
- primitives_.push (info);
- info.grob ()->set_property ("print-function",
- 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);
}
}
void
Ligature_engraver::acknowledge_rest (Grob_info info)
{
- info.music_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?
+ if (ligature_)
+ {
+ 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?
+ }
}
-
-#include "translator.icc"
-
-ADD_ACKNOWLEDGER(Ligature_engraver, rest);
-ADD_ACKNOWLEDGER(Ligature_engraver, note_head);
-ADD_TRANSLATOR (Ligature_engraver,
- /* descr */ "Abstract class; a concrete subclass handles Ligature_events by engraving Ligatures in a concrete style.",
- /* creats */ "",
- /* accepts */ "ligature-event",
- /* acks */ "",
- /* reads */ "",
- /* write */ "");
+// no ADD_ACKNOWLEDGER / ADD_ACKNOWLEDGER / ADD_TRANSLATOR macro calls
+// since this class is abstract