-int
-Mensural_ligature_engraver::apply_transition (int state, int input, int i)
-{
- int output = transition_output[state][input];
- Item *last_last_primitive = (i > 1) ?
- dynamic_cast<Item*> (primitives_[i-2].grob_) : 0;
- Item *last_primitive = (i > 0) ?
- dynamic_cast<Item*> (primitives_[i-1].grob_) : 0;
- Item *primitive = (i < primitives_.size ()) ?
- dynamic_cast<Item*> (primitives_[i].grob_) : 0;
- switch (output)
- {
- case MLP_NONE:
- // skip note head, expecting a primitive with two note heads
- break;
- case MLP_sc:
- case MLP_ss:
- case MLP_cs:
- // primitive with single note head
- if (!last_primitive)
- {
- programming_error ("last_primitive undefined");
- break;
- }
- last_primitive->set_grob_property ("primitive", gh_int2scm (output));
- break;
- case MLP_BB:
- case MLP_LB:
- // primitive with two note heads
- if (!last_primitive)
- {
- programming_error ("last_primitive undefined");
- break;
- }
- if (!primitive)
- {
- programming_error ("primitive undefined");
- break;
- }
- last_primitive->set_grob_property ("primitive", gh_int2scm (output));
- primitive->set_grob_property ("primitive", gh_int2scm (MLP_NONE));
- break;
- case MLP_SS:
- // delayed primitive with two note heads
- if (!last_last_primitive)
- {
- programming_error ("last_last_primitive undefined");
- break;
- }
- if (!last_primitive)
- {
- programming_error ("last_primitive undefined");
- break;
- }
- last_last_primitive->set_grob_property ("primitive", gh_int2scm (output));
- last_primitive->set_grob_property ("primitive", gh_int2scm (MLP_NONE));
- break;
- default:
- programming_error (_f ("unexpected case fall-through"));
- break;
- }
- return transition_state[state][input];
-}
+ if (at_beginning)
+ {
+ if (i == s - 1)
+ {
+ // we can get here after invalid input
+ nr->origin ()->warning
+ (_ ("single note ligature - skipping"));
+ break;
+ }
+ prev_semibrevis = prev_brevis_shape = false;
+ prev_primitive = NULL;
+ }
+ else
+ {
+ if (pitch == prev_pitch)
+ {
+ nr->origin ()->warning
+ (_ ("prime interval within ligature -> skipping"));
+ at_beginning = true;
+ prim = MLP_NONE;
+ continue;
+ }
+ }
+
+ if (duration_log < -3 // is this possible at all???
+ || duration_log > 0)
+ {
+ nr->origin ()->warning
+ (_ ("mensural ligature: duration none of Mx, L, B, S -> skipping"));
+ prim = MLP_NONE;
+ at_beginning = true;
+ continue;
+ }
+
+ bool general_case = true;
+ bool make_flexa = false;
+ bool allow_flexa = true;
+
+ // first check special cases
+ // 1. beginning
+ if (at_beginning)
+ {
+ // a. semibreves
+ if (duration_log == 0)
+ {
+ prim = MLP_UP | MLP_BREVIS;
+ general_case = false;
+ }
+ // b. descendens longa or brevis
+ else if (i < s - 1
+ && (unsmob<Pitch> (primitives[i + 1].event_cause ()
+ ->get_property ("pitch"))->steps () < pitch)
+ && duration_log > -3)
+ {
+ int left_stem = duration_log == -1 ? MLP_DOWN : 0;
+ prim = left_stem | MLP_BREVIS;
+ general_case = false;
+ }
+ }
+ // 2. initial semibrevis must be followed by another one
+ else if (prev_semibrevis)
+ {
+ prev_semibrevis = false;
+ if (duration_log == 0)
+ {
+ prim = MLP_BREVIS;
+ general_case = false;
+ }
+ else
+ {
+ nr->origin ()->warning
+ (_ ("semibrevis must be followed by another one -> skipping"));
+ prim = MLP_NONE;
+ at_beginning = true;
+ continue;
+ }
+ }
+ // 3. semibreves are otherwise not allowed
+ else if (duration_log == 0)
+ {
+ nr->origin ()->warning
+ (_ ("semibreves can only appear at the beginning of a ligature,\n"
+ "and there may be only zero or two of them"));
+ prim = MLP_NONE;
+ at_beginning = true;
+ continue;
+ }
+ // 4. end, descendens
+ else if (i == s - 1 && pitch < prev_pitch)
+ {
+ // brevis; previous note must be turned into flexa
+ if (duration_log == -1)
+ {
+ if (prev_brevis_shape)
+ {
+ make_flexa = true;
+ general_case = false;
+ }
+ else
+ {
+ nr->origin ()->warning
+ (_ ("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"));
+ prim = MLP_NONE;
+ break;
+ }
+ }
+ // longa
+ else if (duration_log == -2)
+ {
+ prim = MLP_BREVIS;
+ general_case = allow_flexa = false;
+ }
+ // else maxima; fall through to regular case below
+ }
+
+ if (allow_flexa
+ && to_boolean (primitive->get_property ("ligature-flexa")))
+ {
+ /*
+ flexa requested, check whether allowed:
+ - there should be a previous note
+ - both of the notes must be of brevis shape
+ (i.e. can't be maxima or flexa;
+ longa is forbidden as well - it's nonexistent anyway)
+ - no compulsory flexa for the next note,
+ i.e. it's not an ultimate descending breve
+ */
+ make_flexa = !at_beginning && prev_brevis_shape && duration_log > -2;
+ if (make_flexa && i == s - 2)
+ {
+ /*
+ check last condition: look ahead to next note
+ */
+ Grob_info next_info = primitives[i + 1];
+ Item *next_primitive = dynamic_cast<Item *> (next_info.grob ());
+ if (Rhythmic_head::duration_log (next_primitive) == -1)
+ {
+ /*
+ breve: check whether descending
+ */
+ int const next_pitch = unsmob<Pitch>
+ (next_info.event_cause ()->get_property ("pitch"))->steps ();
+ if (next_pitch < pitch)
+ /*
+ sorry, forbidden
+ */
+ make_flexa = false;
+ }
+ }
+ }
+
+ if (general_case)
+ {
+ static int const shape[3] = {MLP_MAXIMA, MLP_LONGA, MLP_BREVIS};