X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fligature-engraver.cc;h=8bd4d66137b4907c832bd0981ce739f507d81ed3;hb=0b544cfb7332615ef809b71b57ab656741311ae1;hp=fe680c7a7db8b352289d7b8b892ec00f0780366b;hpb=a1aebf5d6fccf7ab9a7106178e017c370484d40f;p=lilypond.git diff --git a/lily/ligature-engraver.cc b/lily/ligature-engraver.cc index fe680c7a7d..8bd4d66137 100644 --- a/lily/ligature-engraver.cc +++ b/lily/ligature-engraver.cc @@ -1,19 +1,31 @@ /* - 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 - (c) 2002--2005 Juergen Reuter + 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 "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 @@ -24,7 +36,7 @@ * * A concrete ligature engraver must subclass this class and provide * functions create_ligature_spanner () and typeset_ligature - * (Spanner *, Array). Subclasses of this class basically + * (Spanner *, vector). Subclasses of this class basically * fall into two categories. * * The first category consists of engravers that engrave ligatures in @@ -32,9 +44,14 @@ * 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 @@ -75,71 +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; -} - -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 () +Ligature_engraver::listen_ligature (Stream_event *ev) { - 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 () -{ - 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 @@ -148,93 +105,69 @@ 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 (); } } -void -Ligature_engraver::typeset_ligature (Spanner *, Array) -{ - 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_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; } @@ -265,32 +198,27 @@ Ligature_engraver::current_ligature () } void -Ligature_engraver::acknowledge_grob (Grob_info info) +Ligature_engraver::acknowledge_ligature_head (Grob_info info) { if (ligature_) { - if (Note_head::has_interface (info.grob ())) - { - primitives_.push (info); - info.grob ()->set_property ("print-function", - brew_ligature_primitive_proc); - } - if (Rest::has_interface (info.grob ())) - { - 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? - } + primitives_.push_back (info); + if (info.grob () && brew_ligature_primitive_proc != SCM_EOL) + info.grob ()->set_property ("stencil", brew_ligature_primitive_proc); } } -#include "translator.icc" +void +Ligature_engraver::acknowledge_rest (Grob_info info) +{ + 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? + } +} -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 */ "note-head-interface rest-interface", - /* reads */ "", - /* write */ ""); +// no ADD_ACKNOWLEDGER / ADD_ACKNOWLEDGER / ADD_TRANSLATOR macro calls +// since this class is abstract