- return new Spanner (get_property ("MensuralLigature"));
-}
-
-/*
- * The following lines implement a finite state automat. Given a
- * sequence of durations (Longa, Brevis, Semibrevis) or
- * end-of-ligature-event as input, the automat outputs a sequence of
- * events for grobs that form a proper ligature.
- */
-
-/*
- * This enumeration represents the set of possible input values to the
- * automat. There may (potentially) be any sequence of Longa, Brevis,
- * and Semibrevis duration symbols fed into the automat, with a final
- * EndOfLigature symbol to terminate the ligature. Other durations
- * are explicitly prohibited. Depending on the note's pitch of the
- * preceding and the current input, the melodic line may be ascending
- * or descending. Per definition, the melodic line must either ascend
- * or descend, because if the pitches were twice the same, the two
- * notes would be merged into a single one (as long as not resulting
- * in a prohibited duration). In the case of the EndOfLigature
- * symbol, the melodic line is undefined (but we still have ascending
- * and descending case for the sake of consistency, making the automat
- * simpler).
- */
-enum Ligature_input
-{
- // Ascending/Descending Longa/Brevis/Semibrevis/EndOfLigature
- INPUT_AL = 0,
- INPUT_DL,
- INPUT_AB,
- INPUT_DB,
- INPUT_AS,
- INPUT_DS,
- INPUT_AE,
- INPUT_DE,
-};
-
-/*
- * This enumeration represents all possible internal states of the
- * automat. Besides the generic states START, ERROR, and END, the
- * remaining states L, B, S, and SS describe pending values from the
- * sequence of input values that have not yet been transformed to
- * proper output values, including the melodic direction
- * (ascending/descending) for state L.
- */
-enum Ligature_state
-{
- // aL = ascending Longa, dL descending Longa, B = Brevis, S =
- // Semibrevis, SS = 2 Semibreves
- STATE_START = 0,
- STATE_aL,
- STATE_dL,
- STATE_B,
- STATE_S,
- STATE_SS,
- STATE_ERROR,
- STATE_END,
-};
-
-/*
- * The following array represents the transitions of the automat:
- * given some state and input, it maps to a new state, according (with
- * the limitations as described above) to the rules of Franco of
- * Cologne.
- */
-const int/*new state*/ transition_state[/*old state*/][8/*input*/] =
-{
- {STATE_aL, STATE_dL, STATE_B, STATE_B,
- STATE_S, STATE_S, STATE_ERROR, STATE_ERROR}, // was: STATE_START
- {STATE_aL, STATE_dL, STATE_B, STATE_START,
- STATE_ERROR, STATE_ERROR, STATE_END, STATE_END}, // was: STATE_aL
- {STATE_aL, STATE_dL, STATE_B, STATE_START,
- STATE_ERROR, STATE_ERROR, STATE_END, STATE_END}, // was: STATE_dL
- {STATE_aL, STATE_dL, STATE_B, STATE_START,
- STATE_ERROR, STATE_ERROR, STATE_END, STATE_END}, // was: STATE_B
- {STATE_ERROR, STATE_ERROR, STATE_ERROR, STATE_ERROR,
- STATE_SS, STATE_SS, STATE_ERROR, STATE_ERROR}, // was: STATE_S
- {STATE_aL, STATE_dL, STATE_B, STATE_B,
- STATE_S, STATE_S, STATE_END, STATE_END}, // was: STATE_SS
- {STATE_ERROR, STATE_ERROR, STATE_ERROR, STATE_ERROR,
- STATE_ERROR, STATE_ERROR, STATE_ERROR, STATE_ERROR}, // was: STATE_ERROR
- {STATE_ERROR, STATE_ERROR, STATE_ERROR, STATE_ERROR,
- STATE_ERROR, STATE_ERROR, STATE_ERROR, STATE_ERROR}, // was: STATE_END
-};
-
-/*
- * The following array represents the output of the automat while
- * switching from one state to another: given some state and input, it
- * maps to the output produced when switching to the next state,
- * according (with the limitations as described above) to the rules of
- * Franco of Cologne.
- */
-const int/*output*/ transition_output[/*old state*/][8/*input*/] =
-{
- {MLP_NONE, MLP_NONE, MLP_NONE, MLP_NONE,
- MLP_NONE, MLP_NONE, MLP_NONE, MLP_NONE}, // was: STATE_START
- {MLP_sc, MLP_ss, MLP_sc, MLP_LB,
- MLP_NONE, MLP_NONE, MLP_sc, MLP_sc}, // was: STATE_aL
- {MLP_sc, MLP_ss, MLP_sc, MLP_LB,
- MLP_NONE, MLP_NONE, MLP_ss, MLP_ss}, // was: STATE_dL
- {MLP_ss, MLP_cs, MLP_ss, MLP_BB,
- MLP_NONE, MLP_NONE, MLP_ss, MLP_ss} , // was: STATE_B
- {MLP_NONE, MLP_NONE, MLP_NONE, MLP_NONE,
- MLP_NONE, MLP_NONE, MLP_NONE, MLP_NONE}, // was: STATE_S
- {MLP_SS, MLP_SS, MLP_SS, MLP_SS,
- MLP_SS, MLP_SS, MLP_SS, MLP_SS} , // was: STATE_SS
- {MLP_NONE, MLP_NONE, MLP_NONE, MLP_NONE,
- MLP_NONE, MLP_NONE, MLP_NONE, MLP_NONE}, // was: STATE_ERROR
- {MLP_NONE, MLP_NONE, MLP_NONE, MLP_NONE,
- MLP_NONE, MLP_NONE, MLP_NONE, MLP_NONE}, // was: STATE_END
-};
-
-int
-Mensural_ligature_engraver::apply_transition (Array<Grob_info> primitives,
- 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];