X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fmensural-ligature-engraver.cc;h=a6a48a8f188f4bf92537576453a9b90f6c9e8160;hb=89db5c71c36627cfc7d9bd9754a014b8bc95c6c2;hp=59c65531fea618bcf50e6bd0124ccec9ca9a63a4;hpb=02c656d3b0cb895cc81b428d699d960746800e45;p=lilypond.git diff --git a/lily/mensural-ligature-engraver.cc b/lily/mensural-ligature-engraver.cc index 59c65531fe..a6a48a8f18 100644 --- a/lily/mensural-ligature-engraver.cc +++ b/lily/mensural-ligature-engraver.cc @@ -3,22 +3,26 @@ source file of the GNU LilyPond music typesetter - (c) 2002--2005 Juergen Reuter , + (c) 2002--2006 Juergen Reuter , Pal Benko */ #include "coherent-ligature-engraver.hh" +#include "font-interface.hh" +#include "international.hh" #include "mensural-ligature.hh" -#include "event.hh" -#include "warn.hh" -#include "spanner.hh" -#include "paper-column.hh" #include "note-column.hh" -#include "rhythmic-head.hh" #include "note-head.hh" -#include "staff-symbol-referencer.hh" #include "output-def.hh" -#include "font-interface.hh" +#include "paper-column.hh" +#include "pitch.hh" +#include "rhythmic-head.hh" +#include "spanner.hh" +#include "staff-symbol-referencer.hh" +#include "stream-event.hh" +#include "warn.hh" + +#include "translator.icc" /* * TODO: accidentals are aligned with the first note; @@ -27,9 +31,6 @@ * TODO: prohibit ligatures having notes differing only in accidentals * (like \[ a\breve g as \]) * - * TODO: dotted heads: avoid next note colliding with the dot, e.g. by - * putting it *above* (rather than after) the affected ligature head. - * * TODO: do something with multiple voices within a ligature. See * for example: * Ockeghem: Missa Ecce ancilla domini, bassus part, end of Christe. @@ -45,19 +46,29 @@ class Mensural_ligature_engraver : public Coherent_ligature_engraver protected: virtual Spanner *create_ligature_spanner (); - virtual void build_ligature (Spanner *ligature, Array primitives); - + virtual void build_ligature (Spanner *ligature, vector primitives); + DECLARE_TRANSLATOR_LISTENER (ligature); + public: TRANSLATOR_DECLARATIONS (Mensural_ligature_engraver); private: - void transform_heads (Array primitives); - void propagate_properties (Spanner *ligature, Array primitives); - void fold_up_primitives (Array primitives); + void transform_heads (vector primitives); + void propagate_properties (Spanner *ligature, vector primitives); + void fold_up_primitives (vector primitives); }; +IMPLEMENT_TRANSLATOR_LISTENER (Mensural_ligature_engraver, ligature); +void +Mensural_ligature_engraver::listen_ligature (Stream_event *ev) +{ + Ligature_engraver::listen_ligature (ev); +} + Mensural_ligature_engraver::Mensural_ligature_engraver () { + brew_ligature_primitive_proc = + Mensural_ligature::brew_ligature_primitive_proc; } Spanner * @@ -67,7 +78,7 @@ Mensural_ligature_engraver::create_ligature_spanner () } void -Mensural_ligature_engraver::transform_heads (Array primitives) +Mensural_ligature_engraver::transform_heads (vector primitives) { if (primitives.size () < 2) { @@ -84,18 +95,18 @@ Mensural_ligature_engraver::transform_heads (Array primitives) bool prev_semibrevis = false; Item *prev_primitive = NULL; - for (int i = 0, s = primitives.size (); i < s; i++) + for (vsize i = 0, s = primitives.size (); i < s; i++) { Grob_info info = primitives[i]; Item *primitive = dynamic_cast (info.grob ()); - int duration_log = Note_head::get_balltype (primitive); + int duration_log = Rhythmic_head::duration_log (primitive); - Music *nr = info.music_cause (); + Stream_event *nr = info.event_cause (); /* ugh. why not simply check for pitch? */ - if (!nr->is_mus_type ("note-event")) + if (!nr->in_event_class ("note-event")) { nr->origin ()->warning (_f ("cannot determine pitch of ligature primitive -> skipping")); @@ -127,7 +138,7 @@ Mensural_ligature_engraver::transform_heads (Array primitives) (_f ("prime interval within ligature -> skipping")); at_beginning = true; primitive->set_property ("primitive", - scm_int2num (MLP_NONE)); + scm_from_int (MLP_NONE)); continue; } } @@ -138,7 +149,7 @@ Mensural_ligature_engraver::transform_heads (Array primitives) nr->origin ()->warning (_f ("mensural ligature: duration none of Mx, L, B, S -> skipping")); primitive->set_property ("primitive", - scm_int2num (MLP_NONE)); + scm_from_int (MLP_NONE)); at_beginning = true; continue; } @@ -154,20 +165,20 @@ Mensural_ligature_engraver::transform_heads (Array primitives) if (duration_log == 0) { primitive->set_property ("primitive", - scm_int2num (MLP_UP | MLP_BREVIS)); + scm_from_int (MLP_UP | MLP_BREVIS)); prev_semibrevis = prev_brevis_shape = true; general_case = false; } // b. descendens longa or brevis else if (i < s - 1 - && (unsmob_pitch (primitives[i + 1].music_cause () + && (unsmob_pitch (primitives[i + 1].event_cause () ->get_property ("pitch"))->steps () < pitch) && duration_log > -3) { int left_stem = duration_log == -1 ? MLP_DOWN : 0; primitive->set_property ("primitive", - scm_int2num (left_stem | MLP_BREVIS)); + scm_from_int (left_stem | MLP_BREVIS)); prev_brevis_shape = true; prev_semibrevis = general_case = false; } @@ -178,7 +189,7 @@ Mensural_ligature_engraver::transform_heads (Array primitives) prev_semibrevis = false; if (duration_log == 0) { - primitive->set_property ("primitive", scm_int2num (MLP_BREVIS)); + primitive->set_property ("primitive", scm_from_int (MLP_BREVIS)); general_case = false; } else @@ -186,7 +197,7 @@ Mensural_ligature_engraver::transform_heads (Array primitives) nr->origin ()->warning (_f ("semibrevis must be followed by another one -> skipping")); primitive->set_property ("primitive", - scm_int2num (MLP_NONE)); + scm_from_int (MLP_NONE)); at_beginning = true; continue; } @@ -198,7 +209,7 @@ Mensural_ligature_engraver::transform_heads (Array primitives) (_f ("semibreves can only appear at the beginning of a ligature,\n" "and there may be only zero or two of them")); primitive->set_property ("primitive", - scm_int2num (MLP_NONE)); + scm_from_int (MLP_NONE)); at_beginning = true; continue; } @@ -212,11 +223,11 @@ Mensural_ligature_engraver::transform_heads (Array primitives) { prev_primitive->set_property ("primitive", - scm_int2num + scm_from_int (MLP_FLEXA | (scm_to_int (prev_primitive->get_property ("primitive")) & MLP_DOWN))); - primitive->set_property ("primitive", scm_int2num (MLP_NONE)); + primitive->set_property ("primitive", scm_from_int (MLP_NONE)); break; // no more notes, no join } else @@ -226,14 +237,14 @@ Mensural_ligature_engraver::transform_heads (Array primitives) "when the last note is a descending brevis,\n" "the penultimate note must be another one,\n" "or the ligatura must be LB or SSB")); - primitive->set_property ("primitive", scm_int2num (MLP_NONE)); + primitive->set_property ("primitive", scm_from_int (MLP_NONE)); break; } } // longa else if (duration_log == -2) { - primitive->set_property ("primitive", scm_int2num (MLP_BREVIS)); + primitive->set_property ("primitive", scm_from_int (MLP_BREVIS)); general_case = false; } // else maxima; fall through regular case below @@ -244,7 +255,7 @@ Mensural_ligature_engraver::transform_heads (Array primitives) static int const shape[3] = {MLP_MAXIMA, MLP_LONGA, MLP_BREVIS}; primitive->set_property ("primitive", - scm_int2num (shape[duration_log + 3])); + scm_from_int (shape[duration_log + 3])); prev_brevis_shape = duration_log == -1; } @@ -267,7 +278,7 @@ Mensural_ligature_engraver::transform_heads (Array primitives) // ("noteheads.s-2mensural").extent (Y_AXIS).length () } prev_primitive->set_property ("join-right-amount", - scm_int2num (delta_pitch)); + scm_from_int (delta_pitch)); // perhaps set add-join as well } at_beginning = false; @@ -293,12 +304,12 @@ Mensural_ligature_engraver::transform_heads (Array primitives) */ void Mensural_ligature_engraver::propagate_properties (Spanner *ligature, - Array primitives) + vector primitives) { Real thickness = robust_scm2double (ligature->get_property ("thickness"), 1.4); thickness - *= ligature->get_layout ()->get_dimension (ly_symbol2scm ("linethickness")); + *= ligature->layout ()->get_dimension (ly_symbol2scm ("line-thickness")); Real head_width = Font_interface::get_default_font (ligature)-> @@ -313,33 +324,33 @@ Mensural_ligature_engraver::propagate_properties (Spanner *ligature, Real half_flexa_width = 0.5 * (flexa_width + thickness); - for (int i = 0; i < primitives.size (); i++) + for (vsize i = 0; i < primitives.size (); i++) { Item *primitive = dynamic_cast (primitives[i].grob ()); int output = scm_to_int (primitive->get_property ("primitive")); primitive->set_property ("thickness", - scm_make_real (thickness)); + scm_from_double (thickness)); switch (output & MLP_ANY) { case MLP_NONE: primitive->set_property ("head-width", - scm_make_real (half_flexa_width)); + scm_from_double (half_flexa_width)); break; case MLP_BREVIS: case MLP_LONGA: primitive->set_property ("head-width", - scm_make_real (head_width)); + scm_from_double (head_width)); break; case MLP_MAXIMA: primitive->set_property ("head-width", - scm_make_real (maxima_head_width)); + scm_from_double (maxima_head_width)); break; case MLP_FLEXA: primitive->set_property ("head-width", - scm_make_real (half_flexa_width)); + scm_from_double (half_flexa_width)); primitive->set_property ("flexa-width", - scm_make_real (flexa_width)); + scm_from_double (flexa_width)); break; default: programming_error (_f ("unexpected case fall-through")); @@ -349,44 +360,64 @@ Mensural_ligature_engraver::propagate_properties (Spanner *ligature, } void -Mensural_ligature_engraver::fold_up_primitives (Array primitives) +Mensural_ligature_engraver::fold_up_primitives (vector primitives) { Item *first = 0; - Real distance = 0; - for (int i = 0; i < primitives.size (); i++) + Real distance = 0.0; + Real dot_shift = 0.0; + for (vsize i = 0; i < primitives.size (); i++) { Item *current = dynamic_cast (primitives[i].grob ()); if (i == 0) { first = current; + dot_shift = 1.5 * Staff_symbol_referencer::staff_space (first); } - get_set_column (current, first->get_column ()); - - if (i > 0) - { - current->translate_axis (distance, X_AXIS); - } + move_related_items_to_column (current, first->get_column (), + distance); distance += scm_to_double (current->get_property ("head-width")) - scm_to_double (current->get_property ("thickness")); + + if (Rhythmic_head::dot_count (current) > 0) + // Move dots above/behind the ligature. + { + if (i < primitives.size () - 1) + // dot in the midst => move above head + { + // FIXME: Amount of vertical dot-shift should depend on + // pitch. + // + // FIXME: dot placement is horizontally slightly off. + Rhythmic_head::get_dots (current)->translate_axis (dot_shift, Y_AXIS); + } + else + // trailing dot => move behind head + { + double head_width = + scm_to_double (current->get_property ("head-width")); + Rhythmic_head::get_dots (current)-> + translate_axis (head_width, X_AXIS); + } + } } } void Mensural_ligature_engraver::build_ligature (Spanner *ligature, - Array primitives) + vector primitives) { transform_heads (primitives); propagate_properties (ligature, primitives); fold_up_primitives (primitives); } +ADD_ACKNOWLEDGER (Mensural_ligature_engraver, rest); +ADD_ACKNOWLEDGER (Mensural_ligature_engraver, note_head); ADD_TRANSLATOR (Mensural_ligature_engraver, - /* descr */ "Handles Mensural_ligature_events by glueing special ligature heads together.", - /* creats*/ "MensuralLigature", - /* accepts */ "ligature-event", - /* acks */ "note-head-interface rest-interface", - /* reads */ "", + /* doc */ "Handles Mensural_ligature_events by glueing special ligature heads together.", + /* create */ "MensuralLigature", + /* read */ "", /* write */ "");