X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fgregorian-ligature-engraver.cc;h=049d89d9cf9d1fdac01732705d744bf4ffe6a5da;hb=5b4b0d6e9a197e8f9eb085b7c2ad78b8be3e5cfc;hp=82bf403316a3a8267c92ab2fda57ae089e80091e;hpb=6d14ec9744ef91579b0c77e4a39602bab712c324;p=lilypond.git diff --git a/lily/gregorian-ligature-engraver.cc b/lily/gregorian-ligature-engraver.cc index 82bf403316..049d89d9cf 100644 --- a/lily/gregorian-ligature-engraver.cc +++ b/lily/gregorian-ligature-engraver.cc @@ -1,88 +1,48 @@ /* gregorian-ligature-engraver.cc -- implement Gregorian_ligature_engraver - + source file of the GNU LilyPond music typesetter - - (C) 2003 Juergen Reuter - */ + + (c) 2003--2008 Juergen Reuter +*/ #include "gregorian-ligature-engraver.hh" + #include "gregorian-ligature.hh" -#include "item.hh" -#include "warn.hh" -#include "staff-symbol-referencer.hh" -#include "spanner.hh" +#include "international.hh" #include "paper-column.hh" +#include "pitch.hh" +#include "spanner.hh" +#include "staff-symbol-referencer.hh" +#include "stream-event.hh" +#include "warn.hh" + +/* ASSIGN_EVENT_ONCE */ +#include "translator.icc" /* - * TODO: This class shares some code with Mensural_ligature_engraver. - * Maybe we should create a common super class "Rod_ligature_engraver" - * and derive all shared code from it. + * This abstract class is the common superclass for all ligature + * engravers for Gregorian chant notation. It cares for the musical + * handling of the neumes, such as checking for valid combinations of + * neumes and providing context information. Notational aspects such + * as the glyphs to use or calculating the total width of a ligature, + * are left to the concrete subclass. Currently, there is only a + * single subclass, Vaticana_ligature_engraver. Other ligature + * engravers for Gregorian chant will be added in the future, such as + * Medicaea_ligature_engraver or Hufnagel_ligature_engraver. */ - Gregorian_ligature_engraver::Gregorian_ligature_engraver () { - porrectus_req_ = 0; + pes_or_flexa_req_ = 0; } void -Gregorian_ligature_engraver::transform_heads (Spanner *, Array) +Gregorian_ligature_engraver::listen_pes_or_flexa (Stream_event *ev) { - programming_error ("Gregorian_ligature_engraver::transform_heads (): " - "this is an abstract method that should not be called, " - "but overridden by a subclass"); -} - -bool -Gregorian_ligature_engraver::try_music (Music *m) -{ - if (m->is_mus_type ("porrectus-event")) - { - porrectus_req_ = m; - return true; - } - else - return Ligature_engraver::try_music (m); -} - -/* - * TODO: move this function to class Item? - */ -void -Gregorian_ligature_engraver::get_set_column (Item *item, Paper_column *column) -{ - Item *parent = dynamic_cast (item->get_parent (X_AXIS)); - if (!parent) - { - programming_error ("failed tweaking paper column in ligature"); - return; - } - - String name = parent->name (); - if (!String::compare (name, "PaperColumn")) - { - // Change column not only for targeted item (NoteColumn), but - // also for all associated grobs (NoteSpacing, SeparationItem). - Grob *sl = Staff_symbol_referencer::get_staff_symbol (item); - for (SCM tail = parent->get_grob_property ("elements"); - gh_pair_p (tail); - tail = ly_cdr (tail)) - { - Item *sibling = unsmob_item (ly_car (tail)); - if ((sibling) && - (Staff_symbol_referencer::get_staff_symbol (sibling) == sl)) - { - sibling->set_parent (column, X_AXIS); - } - } - } - else - { - get_set_column (parent, column); - } + ASSIGN_EVENT_ONCE (pes_or_flexa_req_, ev); } -void fix_prefix (char *name, int mask, +void fix_prefix (char const *name, int mask, int *current_set, int min_set, int max_set, Grob *primitive) { @@ -116,195 +76,189 @@ void fix_prefix_set (int *current_set, int min_set, int max_set, Grob *primitive fix_prefix ("ascendens", ASCENDENS, current_set, min_set, max_set, primitive); fix_prefix ("oriscus", ORISCUS, current_set, min_set, max_set, primitive); fix_prefix ("quilisma", QUILISMA, current_set, min_set, max_set, primitive); - fix_prefix ("deminutus", DEMINUTUM, current_set, min_set, max_set, primitive); - fix_prefix ("semivocalis", SEMIVOCALIS, current_set, min_set, max_set, primitive); + fix_prefix ("deminutum", DEMINUTUM, current_set, min_set, max_set, primitive); fix_prefix ("cavum", CAVUM, current_set, min_set, max_set, primitive); fix_prefix ("linea", LINEA, current_set, min_set, max_set, primitive); fix_prefix ("pes_or_flexa", LINEA, current_set, min_set, max_set, primitive); } -void check_and_fix_all_prefixes (Array primitives) +void check_and_fix_all_prefixes (vector primitives) { - /* Check for illegal head modifier combinations */ - for (int i = 0; i < primitives.size(); i++) + /* Check for invalid head modifier combinations */ + for (vsize i = 0; i < primitives.size (); i++) { - Grob *primitive = primitives[i].grob_; + Grob *primitive = primitives[i].grob (); - /* compute head prefix set by inspecting primitive grob properties */ - int prefix_set = - (VIRGA * to_boolean (primitive->get_grob_property ("virga"))) | - (STROPHA * to_boolean (primitive->get_grob_property ("stropha"))) | - (INCLINATUM * to_boolean (primitive->get_grob_property ("inclinatum"))) | - (AUCTUM * to_boolean (primitive->get_grob_property ("auctum"))) | - (DESCENDENS * to_boolean (primitive->get_grob_property ("descendens"))) | - (ASCENDENS * to_boolean (primitive->get_grob_property ("ascendens"))) | - (ORISCUS * to_boolean (primitive->get_grob_property ("oriscus"))) | - (QUILISMA * to_boolean (primitive->get_grob_property ("quilisma"))) | - (DEMINUTUM * to_boolean (primitive->get_grob_property ("deminutum"))) | - (SEMIVOCALIS * to_boolean (primitive->get_grob_property ("semivocalis"))) | - (CAVUM * to_boolean (primitive->get_grob_property ("cavum"))) | - (LINEA * to_boolean (primitive->get_grob_property ("linea"))) | - (PES_OR_FLEXA * to_boolean (primitive->get_grob_property ("pes-or-flexa"))); + /* compute head prefix set by inspecting primitive grob properties */ + int prefix_set + = (VIRGA *to_boolean (primitive->get_property ("virga"))) + | (STROPHA *to_boolean (primitive->get_property ("stropha"))) + | (INCLINATUM *to_boolean (primitive->get_property ("inclinatum"))) + | (AUCTUM *to_boolean (primitive->get_property ("auctum"))) + | (DESCENDENS *to_boolean (primitive->get_property ("descendens"))) + | (ASCENDENS *to_boolean (primitive->get_property ("ascendens"))) + | (ORISCUS *to_boolean (primitive->get_property ("oriscus"))) + | (QUILISMA *to_boolean (primitive->get_property ("quilisma"))) + | (DEMINUTUM *to_boolean (primitive->get_property ("deminutum"))) + | (CAVUM *to_boolean (primitive->get_property ("cavum"))) + | (LINEA *to_boolean (primitive->get_property ("linea"))) + | (PES_OR_FLEXA *to_boolean (primitive->get_property ("pes-or-flexa"))); - /* check: ascendens and descendens exclude each other; same with - auctum and diminutum */ - if (prefix_set & DESCENDENS) - { - fix_prefix_set (&prefix_set, - prefix_set & ~ASCENDENS, - prefix_set & ~ASCENDENS, - primitive); - } - if (prefix_set & AUCTUM) - { - fix_prefix_set (&prefix_set, - prefix_set & ~DEMINUTUM, - prefix_set & ~DEMINUTUM, - primitive); - } - - /* check: virga, quilisma and oriscus can not be combined with any - other prefix, but may be part of a pes or flexa */ - if (prefix_set & VIRGA) - { - fix_prefix_set (&prefix_set, - VIRGA, - VIRGA | PES_OR_FLEXA, - primitive); - } - if (prefix_set & QUILISMA) - { - fix_prefix_set (&prefix_set, - QUILISMA, - QUILISMA | PES_OR_FLEXA, - primitive); - } - if (prefix_set & ORISCUS) - { - fix_prefix_set (&prefix_set, - ORISCUS, - ORISCUS | PES_OR_FLEXA, - primitive); - } + /* check: ascendens and descendens exclude each other; same with + auctum and deminutum */ + if (prefix_set & DESCENDENS) + { + fix_prefix_set (&prefix_set, + prefix_set & ~ASCENDENS, + prefix_set & ~ASCENDENS, + primitive); + } + if (prefix_set & AUCTUM) + { + fix_prefix_set (&prefix_set, + prefix_set & ~DEMINUTUM, + prefix_set & ~DEMINUTUM, + primitive); + } - /* check: auctum is the only valid optional prefix for stropha */ - if (prefix_set & STROPHA) - { - fix_prefix_set (&prefix_set, - STROPHA, - STROPHA | AUCTUM, - primitive); - } + /* check: virga, quilisma and oriscus cannot be combined with any + other prefix, but may be part of a pes or flexa */ + if (prefix_set & VIRGA) + { + fix_prefix_set (&prefix_set, + VIRGA, + VIRGA | PES_OR_FLEXA, + primitive); + } + if (prefix_set & QUILISMA) + { + fix_prefix_set (&prefix_set, + QUILISMA, + QUILISMA | PES_OR_FLEXA, + primitive); + } + if (prefix_set & ORISCUS) + { + fix_prefix_set (&prefix_set, + ORISCUS, + ORISCUS | PES_OR_FLEXA, + primitive); + } - /* check: semivocalis must occur in combination with and only with - pes or flexa */ - if (prefix_set & SEMIVOCALIS) - { - fix_prefix_set (&prefix_set, - SEMIVOCALIS | PES_OR_FLEXA, - SEMIVOCALIS | PES_OR_FLEXA, - primitive); - } + /* check: auctum is the only valid optional prefix for stropha */ + if (prefix_set & STROPHA) + { + fix_prefix_set (&prefix_set, + STROPHA, + STROPHA | AUCTUM, + primitive); + } - /* check: inclinatum may be prefixed with auctum or diminutum only */ - if (prefix_set & INCLINATUM) - { - fix_prefix_set (&prefix_set, - INCLINATUM, - INCLINATUM | AUCTUM | DEMINUTUM, - primitive); - } + /* check: inclinatum may be prefixed with auctum or deminutum only */ + if (prefix_set & INCLINATUM) + { + fix_prefix_set (&prefix_set, + INCLINATUM, + INCLINATUM | AUCTUM | DEMINUTUM, + primitive); + } + /* check: semivocalis (deminutum but not inclinatum) must occur in + combination with and only with pes or flexa */ + else if (prefix_set & DEMINUTUM) + { + fix_prefix_set (&prefix_set, + DEMINUTUM | PES_OR_FLEXA, + DEMINUTUM | PES_OR_FLEXA, + primitive); + } - /* check: cavum and linea (either or both) may be applied only - upon core punctum */ - if (prefix_set & (CAVUM | LINEA)) - { - fix_prefix_set (&prefix_set, - 0, - CAVUM | LINEA, - primitive); - } + /* check: cavum and linea (either or both) may be applied only + upon core punctum */ + if (prefix_set & (CAVUM | LINEA)) + { + fix_prefix_set (&prefix_set, + 0, + CAVUM | LINEA, + primitive); + } - /* all other combinations should be valid (unless I made a - mistake) */ + /* all other combinations should be valid (unless I made a + mistake) */ - primitive->set_grob_property ("prefix-set", gh_int2scm (prefix_set)); - } + primitive->set_property ("prefix-set", scm_from_int (prefix_set)); + } } /* * Marks those heads that participate in a pes or flexa. */ void -provide_context_info (Array primitives) +provide_context_info (vector primitives) { Grob *prev_primitive = 0; + int prev_prefix_set = 0; int prev_context_info = 0; int prev_pitch = 0; - for (int i = 0; i < primitives.size(); i++) { - Grob *primitive = primitives[i].grob_; - Music *music_cause = primitives[i].music_cause (); - int context_info = 0; - int pitch = unsmob_pitch (music_cause->get_mus_property ("pitch"))->steps (); - int prefix_set = gh_scm2int (primitive->get_grob_property ("prefix-set")); + for (vsize i = 0; i < primitives.size (); i++) + { + Grob *primitive = primitives[i].grob (); + Stream_event *event_cause = primitives[i].event_cause (); + int context_info = 0; + int pitch = unsmob_pitch (event_cause->get_property ("pitch"))->steps (); + int prefix_set = scm_to_int (primitive->get_property ("prefix-set")); - if (prefix_set & PES_OR_FLEXA) - if (pitch > prev_pitch) // pes + if (prefix_set & PES_OR_FLEXA) { - prev_context_info |= PES_LOWER; - context_info |= PES_UPPER; - } - else if (pitch < prev_pitch) // flexa - { - prev_context_info |= FLEXA_LEFT; - context_info |= FLEXA_RIGHT; - } - else // (pitch == prev_pitch) - { - primitive->warning ("may not apply `\\~' on heads with " - "identical pitch; ignoring `\\~'"); + if (!i) // ligature may not start with 2nd head of pes or flexa + primitive->warning (_ ("cannot apply `\\~' on first head of ligature")); + else if (pitch > prev_pitch) // pes + { + prev_context_info |= PES_LOWER; + context_info |= PES_UPPER; + } + else if (pitch < prev_pitch) // flexa + { + prev_context_info |= FLEXA_LEFT; + context_info |= FLEXA_RIGHT; + } + else // (pitch == prev_pitch) + primitive->warning (_ ("cannot apply `\\~' on heads with identical pitch")); } - if (prev_primitive) - prev_primitive->set_grob_property ("context-info", - gh_int2scm (prev_context_info)); - prev_primitive = primitive; - prev_context_info = context_info; - prev_pitch = pitch; - } + if (prev_prefix_set & DEMINUTUM) + context_info |= AFTER_DEMINUTUM; + + if (prev_primitive) + prev_primitive->set_property ("context-info", + scm_from_int (prev_context_info)); + prev_primitive = primitive; + prev_prefix_set = prefix_set; + prev_context_info = context_info; + prev_pitch = pitch; + } if (prev_primitive) - prev_primitive->set_grob_property ("context-info", - gh_int2scm (prev_context_info)); + prev_primitive->set_property ("context-info", + scm_from_int (prev_context_info)); } void -Gregorian_ligature_engraver::typeset_ligature (Spanner *ligature, - Array primitives) +Gregorian_ligature_engraver::build_ligature (Spanner *ligature, + vector primitives) { // apply style-independent checking and transformation check_and_fix_all_prefixes (primitives); provide_context_info (primitives); - // apply style-specific transformation (including line-up) + // apply style-specific transformation (including line-up); to be + // implemented by subclass transform_heads (ligature, primitives); - - // typeset - for (int i = 0; i < primitives.size (); i++) - { - typeset_grob (primitives[i].grob_); - } } void -Gregorian_ligature_engraver::start_translation_timestep () +Gregorian_ligature_engraver::stop_translation_timestep () { - Ligature_engraver::start_translation_timestep (); - porrectus_req_ = 0; + Ligature_engraver::stop_translation_timestep (); + pes_or_flexa_req_ = 0; } -ENTER_DESCRIPTION (Gregorian_ligature_engraver, -/* descr */ "This is an abstract class. Subclasses such as Vaticana_ligature_engraver handle ligatures by glueing special ligature heads together.", -/* creats*/ "", -/* accepts */ "ligature-event abort-event", -/* acks */ "ligature-head-interface note-head-interface rest-interface", -/* reads */ "", -/* write */ ""); +// no ADD_ACKNOWLEDGER / ADD_ACKNOWLEDGER / ADD_TRANSLATOR macro calls +// since this class is abstract