X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=lily%2Fmensural-ligature-engraver.cc;h=906ace106ca689f8f93082dae7b5418a541efc26;hb=5b4b0d6e9a197e8f9eb085b7c2ad78b8be3e5cfc;hp=5adc44122c27406832319d8d226d9f055da5a666;hpb=31568c504806f35aac420a394c9eab07abd9faa7;p=lilypond.git diff --git a/lily/mensural-ligature-engraver.cc b/lily/mensural-ligature-engraver.cc index 5adc44122c..906ace106c 100644 --- a/lily/mensural-ligature-engraver.cc +++ b/lily/mensural-ligature-engraver.cc @@ -3,7 +3,7 @@ source file of the GNU LilyPond music typesetter - (c) 2002--2006 Juergen Reuter , + (c) 2002--2008 Juergen Reuter , Pal Benko */ @@ -11,16 +11,19 @@ #include "font-interface.hh" #include "international.hh" #include "mensural-ligature.hh" -#include "music.hh" #include "note-column.hh" #include "note-head.hh" #include "output-def.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; * they must appear ahead. @@ -28,14 +31,11 @@ * 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. * - * TODO: enhance robustness: in case of an illegal ligature (e.g. the + * TODO: enhance robustness: in case of an invalid ligature (e.g. the * input specifies a ligature that contains a minima), automatically * break the ligature into smaller, valid pieces. Such a piece may be * a single note. @@ -47,7 +47,8 @@ class Mensural_ligature_engraver : public Coherent_ligature_engraver protected: virtual Spanner *create_ligature_spanner (); virtual void build_ligature (Spanner *ligature, vector primitives); - + DECLARE_TRANSLATOR_LISTENER (ligature); + public: TRANSLATOR_DECLARATIONS (Mensural_ligature_engraver); @@ -57,6 +58,13 @@ private: 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 = @@ -74,7 +82,7 @@ Mensural_ligature_engraver::transform_heads (vector primitives) { if (primitives.size () < 2) { - warning (_f ("ligature with less than 2 heads -> skipping")); + warning (_ ("ligature with less than 2 heads -> skipping")); return; } int prev_pitch = 0; @@ -91,17 +99,17 @@ Mensural_ligature_engraver::transform_heads (vector primitives) { 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")); + (_ ("cannot determine pitch of ligature primitive -> skipping")); at_beginning = true; continue; } @@ -115,7 +123,7 @@ Mensural_ligature_engraver::transform_heads (vector primitives) { // we can get here after invalid input nr->origin ()->warning - (_f ("single note ligature - skipping")); + (_ ("single note ligature - skipping")); break; } prev_semibrevis = prev_brevis_shape = false; @@ -127,7 +135,7 @@ Mensural_ligature_engraver::transform_heads (vector primitives) if (delta_pitch == 0) { nr->origin ()->warning - (_f ("prime interval within ligature -> skipping")); + (_ ("prime interval within ligature -> skipping")); at_beginning = true; primitive->set_property ("primitive", scm_from_int (MLP_NONE)); @@ -139,7 +147,7 @@ Mensural_ligature_engraver::transform_heads (vector primitives) || duration_log > 0) { nr->origin ()->warning - (_f ("mensural ligature: duration none of Mx, L, B, S -> skipping")); + (_ ("mensural ligature: duration none of Mx, L, B, S -> skipping")); primitive->set_property ("primitive", scm_from_int (MLP_NONE)); at_beginning = true; @@ -163,7 +171,7 @@ Mensural_ligature_engraver::transform_heads (vector primitives) } // 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) { @@ -187,7 +195,7 @@ Mensural_ligature_engraver::transform_heads (vector primitives) else { nr->origin ()->warning - (_f ("semibrevis must be followed by another one -> skipping")); + (_ ("semibrevis must be followed by another one -> skipping")); primitive->set_property ("primitive", scm_from_int (MLP_NONE)); at_beginning = true; @@ -198,8 +206,8 @@ Mensural_ligature_engraver::transform_heads (vector primitives) else if (duration_log == 0) { nr->origin ()->warning - (_f ("semibreves can only appear at the beginning of a ligature,\n" - "and there may be only zero or two of them")); + (_ ("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_from_int (MLP_NONE)); at_beginning = true; @@ -225,10 +233,10 @@ Mensural_ligature_engraver::transform_heads (vector primitives) else { nr->origin ()->warning - (_f ("invalid ligatura ending:\n" - "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")); + (_ ("invalid ligatura ending:\n" + "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_from_int (MLP_NONE)); break; } @@ -267,7 +275,7 @@ Mensural_ligature_engraver::transform_heads (vector primitives) // instead of number 6 // the legth of the longa stem should be queried something like // Font_interface::get_default_font (ligature)->find_by_name - // ("noteheads.s-2mensural").extent (Y_AXIS).length () + // ("noteheads.sM2mensural").extent (Y_AXIS).length () } prev_primitive->set_property ("join-right-amount", scm_from_int (delta_pitch)); @@ -305,12 +313,12 @@ Mensural_ligature_engraver::propagate_properties (Spanner *ligature, Real head_width = Font_interface::get_default_font (ligature)-> - find_by_name ("noteheads.s-1mensural").extent (X_AXIS).length (); + find_by_name ("noteheads.sM1mensural").extent (X_AXIS).length (); Real flexa_width = robust_scm2double (ligature->get_property ("flexa-width"), 2); Real maxima_head_width = Font_interface::get_default_font (ligature)-> - find_by_name ("noteheads.s-1neomensural").extent (X_AXIS).length (); + find_by_name ("noteheads.sM1neomensural").extent (X_AXIS).length (); flexa_width *= Staff_symbol_referencer::staff_space (ligature); @@ -345,7 +353,7 @@ Mensural_ligature_engraver::propagate_properties (Spanner *ligature, scm_from_double (flexa_width)); break; default: - programming_error (_f ("unexpected case fall-through")); + programming_error (_ ("unexpected case fall-through")); break; } } @@ -355,21 +363,45 @@ void Mensural_ligature_engraver::fold_up_primitives (vector primitives) { Item *first = 0; - Real distance = 0; + 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; - - get_set_column (current, first->get_column ()); + { + first = current; + dot_shift = 1.5 * Staff_symbol_referencer::staff_space (first); + } - 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 + 1 < primitives.size ()) + // 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); + } + } } } @@ -382,13 +414,20 @@ Mensural_ligature_engraver::build_ligature (Spanner *ligature, fold_up_primitives (primitives); } -#include "translator.icc" - ADD_ACKNOWLEDGER (Mensural_ligature_engraver, rest); ADD_ACKNOWLEDGER (Mensural_ligature_engraver, note_head); + ADD_TRANSLATOR (Mensural_ligature_engraver, - /* doc */ "Handles Mensural_ligature_events by glueing special ligature heads together.", - /* create */ "MensuralLigature", - /* accept */ "ligature-event", - /* read */ "", - /* write */ ""); + /* doc */ + "Handle @code{Mensural_ligature_events} by glueing special" + " ligature heads together.", + + /* create */ + "MensuralLigature ", + + /* read */ + "", + + /* write */ + "" + );