/*
* Copyright (C) 2006-2015 The Gregorio Project (see CONTRIBUTORS.md)
*
* This file is part of Gregorio.
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see .
*/
#include "config.h"
#include
#include
#include "bool.h"
#include "struct.h"
#include "messages.h"
#include "gabc.h"
static __inline gregorio_scanner_location *copy_note_location(
const gregorio_note *const note, gregorio_scanner_location *const loc)
{
loc->first_line = note->src_line;
loc->first_column = note->src_column;
loc->first_offset = note->src_offset;
loc->last_line = note->src_line;
loc->last_column = note->src_column;
loc->last_offset = note->src_offset;
return loc;
}
/****************************
*
* First see the comments of
* gabc_det_glyphs_from_notes. This function is used when
* we have finished to determine a glyph. We have the last glyph that
* have been added: last_glyph. The glyph we want to add is given by
* glyph_type and liquescentia.
*
* The glyph we want to add goes from first_note to current_note, we
* isolate these notes from the notes that won't be in the glyph, and
* we add the glyph to the list_of_glyphs.
*
****************************/
static void close_glyph(gregorio_glyph **last_glyph,
gregorio_glyph_type glyph_type, gregorio_note **first_note,
gregorio_liquescentia liquescentia, gregorio_note *current_note)
{
gregorio_scanner_location loc;
/* a variable necessary for the patch for G_BIVIRGA & co. */
gregorio_note *added_notes = NULL;
/* patch to have good glyph type in the case where a glyph ends by a note
* with shape S_QUADRATUM */
if (glyph_type == G_PES_QUADRATUM_FIRST_PART
|| glyph_type == G_PES_QUILISMA_QUADRATUM_FIRST_PART) {
glyph_type = G_PUNCTUM;
}
gregorio_add_glyph(last_glyph, glyph_type, *first_note, liquescentia);
if (current_note->next) {
current_note->next->previous = NULL;
*first_note = current_note->next;
current_note->next = NULL;
}
/* here we "patch" the structure for bivirga, tristropha, etc. */
/* the idea is not to have a S_BIVIRGA in the shape of the note (which is
* dirty) but rather a G_BIVIRGA in the glyph (which is the case now) and
* two virgas */
if (glyph_type == G_BIVIRGA || glyph_type == G_DISTROPHA
|| glyph_type == G_TRIVIRGA || glyph_type == G_TRISTROPHA
|| glyph_type == G_DISTROPHA_AUCTA
|| glyph_type == G_TRISTROPHA_AUCTA) {
gregorio_go_to_first_note(¤t_note);
while (current_note) {
if (current_note->type == GRE_NOTE) {
switch (current_note->u.note.shape) {
case S_TRIVIRGA:
gregorio_add_note(&added_notes, current_note->u.note.pitch,
S_VIRGA, _NO_SIGN, L_NO_LIQUESCENTIA, current_note,
copy_note_location(current_note, &loc));
case S_BIVIRGA:
gregorio_add_note(&added_notes, current_note->u.note.pitch,
S_VIRGA, _NO_SIGN, L_NO_LIQUESCENTIA, current_note,
copy_note_location(current_note, &loc));
gregorio_add_note(&added_notes, current_note->u.note.pitch,
S_VIRGA, current_note->signs,
current_note->u.note.liquescentia, current_note,
copy_note_location(current_note, &loc));
break;
case S_TRISTROPHA:
gregorio_add_note(&added_notes, current_note->u.note.pitch,
S_STROPHA, _NO_SIGN, L_NO_LIQUESCENTIA,
current_note,
copy_note_location(current_note, &loc));
case S_DISTROPHA:
gregorio_add_note(&added_notes, current_note->u.note.pitch,
S_STROPHA, _NO_SIGN, L_NO_LIQUESCENTIA,
current_note,
copy_note_location(current_note, &loc));
gregorio_add_note(&added_notes, current_note->u.note.pitch,
S_STROPHA, current_note->signs,
current_note->u.note.liquescentia, current_note,
copy_note_location(current_note, &loc));
break;
case S_TRISTROPHA_AUCTA:
gregorio_add_note(&added_notes, current_note->u.note.pitch,
S_STROPHA, _NO_SIGN, L_NO_LIQUESCENTIA,
current_note,
copy_note_location(current_note, &loc));
case S_DISTROPHA_AUCTA:
gregorio_add_note(&added_notes, current_note->u.note.pitch,
S_STROPHA, _NO_SIGN, L_NO_LIQUESCENTIA,
current_note,
copy_note_location(current_note, &loc));
gregorio_add_note(&added_notes, current_note->u.note.pitch,
S_STROPHA_AUCTA, current_note->signs,
current_note->u.note.liquescentia, current_note,
copy_note_location(current_note, &loc));
break;
default:
break;
}
}
/* this is the case of two separate virga that have been spotted
* as a bivirga */
if (!added_notes) {
break;
}
/* now we have what we want, we set up the links and free the old
* note */
if (current_note->next) {
current_note->next->previous = added_notes;
added_notes->next = current_note->next;
}
gregorio_go_to_first_note(&added_notes);
if (current_note->previous) {
current_note->previous->next = added_notes;
added_notes->previous = current_note->previous;
}
if (!current_note->previous && !current_note->next) {
current_note = added_notes;
break;
} else {
gregorio_free_one_note(¤t_note);
/* automatically sets first_note to the next note */
}
}
gregorio_go_to_first_note(¤t_note);
/* finally we set the just added glyph first_note to current_note */
(*last_glyph)->u.notes.first_note = current_note;
}
}
/* a small function to automatically determine the pitch of a custo : it is
* the pitch of the next note, but we must take care of the clef changes, as
* custo are (normally and for now) only present before clef changes. */
/* TODO: there may be a side effect with the flated keys... */
static char gabc_determine_custo_pitch(gregorio_note *current_note,
int current_key)
{
int pitch_difference = 0;
int newkey;
while (current_note) {
if (current_note->type == GRE_C_KEY_CHANGE
|| current_note->type == GRE_C_KEY_CHANGE_FLATED) {
newkey = gregorio_calculate_new_key(C_KEY,
current_note->u.note.pitch - '0');
pitch_difference = newkey - current_key;
}
if (current_note->type == GRE_F_KEY_CHANGE
|| current_note->type == GRE_F_KEY_CHANGE_FLATED) {
newkey = gregorio_calculate_new_key(F_KEY,
current_note->u.note.pitch - '0');
pitch_difference = newkey - current_key;
}
if (current_note->type == GRE_NOTE) {
pitch_difference =
(int) current_note->u.note.pitch - pitch_difference;
while (pitch_difference < LOWEST_PITCH) {
pitch_difference += 7;
}
while (pitch_difference > HIGHEST_PITCH) {
pitch_difference -= 7;
}
assert(pitch_difference >= LOWEST_PITCH
&& pitch_difference <= HIGHEST_PITCH);
return (char) pitch_difference;
}
current_note = current_note->next;
}
return DUMMY_PITCH;
}
/****************************
*
* This function is the basis of all the determination of glyphs. The
* phylosophy of the function is to say : We have a glyph that we have
* determined, and we have the following note, can we "add" it to the
* glyph, or will it be the first note of another glyph ?
*
* current_glyph_type is the type of the current_glyph (current_glyph
* as meant in gabc_det_glyphs_from_notes). curent_pitch
* is the height of the note that we want to "add" to the glyph.
* last_pitch is the height of the last note of current_glyph. shape
* is the shape of the note we want to "add" to the glyph.
*
* The function returns a char, which meaning is explained below.
*
* end_of_glyph is a pointer to the result of the determination, here
* are the meanings :
*
* DET_NO_END: we have successfully added the note to the glyph, and
* we return the new type of the glyph. We may again add notes to the
* glyph.
*
* DET_END_OF_PREVIOUS: we have not been able to add the note to the
* glyph, so we will have to close the glyph.
*
* DET_END_OF_CURRENT: we have been able to add the note to the glyph,
* but we won't be able to add more notes to the glyph, we can close
* it. The new type is returned.
* DET_END_OF_BOTH: we have'nt been able to add the note to the glyph,
* and we won't be able to add notes to the new glyph. This special
* case is quite rare, we use it for trivirga, tristropha, etc.
* When we encouter a S_QUADRATUM (or S_QUILISMA_QUADRATUM), we build
* a new glyph with the (temporary) shape G_PES_QUADRATUM_FIRST_PART
* (or G_PES_QUILISMA_QUADRATUM_FIRST_PART), and we wait for the next
* note.
*
****************************/
static char gregorio_add_note_to_a_glyph(gregorio_glyph_type current_glyph_type,
char current_pitch, char last_pitch, gregorio_shape shape,
gregorio_liquescentia liquescentia,
gregorio_note *current_glyph_first_note,
gabc_determination * end_of_glyph)
{
/* next glyph type is the type of the glyph that will be returned (the
* new type of the glyph with the note added to it, or the type of the
* new glyph with the note alone. */
gregorio_glyph_type next_glyph_type = G_UNDETERMINED;
*end_of_glyph = DET_NO_END;
/* here we separate notes that would be logically in the same glyph
* but that are too far to be so */
if (last_pitch) {
if (current_pitch - last_pitch > MAX_INTERVAL
|| current_pitch - last_pitch < -MAX_INTERVAL) {
current_glyph_type = G_UNDETERMINED;
}
}
switch (shape) {
case S_PUNCTUM_CAVUM:
case S_LINEA_PUNCTUM:
case S_LINEA_PUNCTUM_CAVUM:
case S_LINEA:
next_glyph_type = G_PUNCTUM;
*end_of_glyph = DET_END_OF_BOTH;
break;
case S_PUNCTUM:
/*
* we determine here the shape of the thing if it is made of puncta
*/
if (current_pitch == last_pitch) {
next_glyph_type = G_PUNCTUM;
*end_of_glyph = DET_END_OF_PREVIOUS;
break;
}
switch (current_glyph_type) {
case G_PUNCTUM:
if (current_pitch > last_pitch) {
next_glyph_type = G_PODATUS;
} else {
next_glyph_type = G_FLEXA;
}
break;
case G_PODATUS:
if (current_pitch > last_pitch) {
if (current_glyph_first_note->u.note.shape == S_PUNCTUM &&
current_glyph_first_note->u.note.liquescentia !=
L_INITIO_DEBILIS) {
next_glyph_type = G_SCANDICUS;
*end_of_glyph = DET_END_OF_CURRENT;
} else {
next_glyph_type = G_PUNCTUM;
*end_of_glyph = DET_END_OF_PREVIOUS;
}
} else {
next_glyph_type = G_TORCULUS;
}
break;
case G_PES_QUADRATUM_FIRST_PART:
if (current_pitch > last_pitch) {
next_glyph_type = G_PES_QUADRATUM;
*end_of_glyph = DET_END_OF_CURRENT;
} else {
next_glyph_type = G_FLEXA;
}
break;
case G_PES_QUILISMA_QUADRATUM_FIRST_PART:
if (current_pitch > last_pitch) {
next_glyph_type = G_PES_QUADRATUM;
*end_of_glyph = DET_END_OF_CURRENT;
} else {
next_glyph_type = G_PUNCTUM;
*end_of_glyph = DET_END_OF_PREVIOUS;
}
break;
case G_VIRGA_STRATA:
if (current_pitch > last_pitch) {
next_glyph_type = G_SALICUS;
*end_of_glyph = DET_END_OF_CURRENT;
} else {
next_glyph_type = G_PUNCTUM;
*end_of_glyph = DET_END_OF_PREVIOUS;
}
break;
case G_FLEXA:
if (current_pitch > last_pitch) {
next_glyph_type = G_PORRECTUS;
} else {
*end_of_glyph = DET_END_OF_CURRENT;
next_glyph_type = G_ANCUS;
}
break;
case G_TORCULUS:
if (current_pitch > last_pitch) {
next_glyph_type = G_TORCULUS_RESUPINUS;
} else if (liquescentia == L_DEMINUTUS) {
*end_of_glyph = DET_END_OF_CURRENT;
next_glyph_type = G_TORCULUS_LIQUESCENS;
} else {
*end_of_glyph = DET_END_OF_PREVIOUS;
next_glyph_type = G_PUNCTUM;
}
break;
case G_TORCULUS_RESUPINUS:
if (current_pitch > last_pitch) {
*end_of_glyph = DET_END_OF_PREVIOUS;
next_glyph_type = G_PUNCTUM;
} else {
*end_of_glyph = DET_END_OF_CURRENT;
next_glyph_type = G_TORCULUS_RESUPINUS_FLEXUS;
}
break;
case G_PORRECTUS:
if (current_pitch > last_pitch) {
*end_of_glyph = DET_END_OF_PREVIOUS;
next_glyph_type = G_PUNCTUM;
} else {
*end_of_glyph = DET_END_OF_CURRENT;
next_glyph_type = G_PORRECTUS_FLEXUS;
}
break;
default:
*end_of_glyph = DET_END_OF_PREVIOUS;
next_glyph_type = G_PUNCTUM;
break;
}
break;
case S_ORISCUS:
*end_of_glyph = DET_END_OF_PREVIOUS;
next_glyph_type = G_PUNCTUM;
break;
case S_ORISCUS_AUCTUS:
*end_of_glyph = DET_END_OF_PREVIOUS;
next_glyph_type = G_PUNCTUM;
break;
case S_ORISCUS_DEMINUTUS:
*end_of_glyph = DET_END_OF_PREVIOUS;
next_glyph_type = G_PUNCTUM;
break;
case S_QUILISMA:
*end_of_glyph = DET_END_OF_PREVIOUS;
next_glyph_type = G_PUNCTUM;
break;
case S_VIRGA:
if (current_glyph_type == G_VIRGA && last_pitch == current_pitch) {
next_glyph_type = G_BIVIRGA;
} else {
if (current_glyph_type == G_BIVIRGA && last_pitch == current_pitch) {
next_glyph_type = G_TRIVIRGA;
} else {
*end_of_glyph = DET_END_OF_PREVIOUS;
next_glyph_type = G_VIRGA;
}
}
break;
case S_VIRGA_REVERSA:
*end_of_glyph = DET_END_OF_PREVIOUS;
next_glyph_type = G_VIRGA_REVERSA;
break;
case S_BIVIRGA:
if (current_glyph_type == G_VIRGA && last_pitch == current_pitch) {
next_glyph_type = G_TRIVIRGA;
} else {
*end_of_glyph = DET_END_OF_PREVIOUS;
next_glyph_type = G_BIVIRGA;
}
break;
case S_TRIVIRGA:
*end_of_glyph = DET_END_OF_BOTH;
next_glyph_type = G_TRIVIRGA;
break;
case S_QUADRATUM:
*end_of_glyph = DET_END_OF_PREVIOUS;
next_glyph_type = G_PES_QUADRATUM_FIRST_PART;
break;
case S_QUILISMA_QUADRATUM:
*end_of_glyph = DET_END_OF_PREVIOUS;
next_glyph_type = G_PES_QUILISMA_QUADRATUM_FIRST_PART;
break;
case S_ORISCUS_SCAPUS:
if (current_glyph_type == G_PUNCTUM && last_pitch < current_pitch) {
next_glyph_type = G_VIRGA_STRATA;
} else {
*end_of_glyph = DET_END_OF_PREVIOUS;
next_glyph_type = G_PUNCTUM;
}
break;
case S_PUNCTUM_INCLINATUM:
case S_PUNCTUM_CAVUM_INCLINATUM:
/*
* Warning : this part of the code is specific to the
* declarations of the header file
*/
if (current_glyph_type > G_PUNCTA_INCLINATA) {
/*
* meaning that the previous glyph is not a combination of puncta
* inclinata, see header file for details
*/
*end_of_glyph = DET_END_OF_PREVIOUS;
next_glyph_type = G_PUNCTUM_INCLINATUM;
break;
}
if (current_pitch == last_pitch) {
*end_of_glyph = DET_END_OF_PREVIOUS;
next_glyph_type = G_PUNCTUM_INCLINATUM;
break;
}
switch (current_glyph_type) {
case G_PUNCTUM_INCLINATUM:
if (last_pitch < current_pitch) {
next_glyph_type = G_2_PUNCTA_INCLINATA_ASCENDENS;
} else {
next_glyph_type = G_2_PUNCTA_INCLINATA_DESCENDENS;
}
break;
case G_2_PUNCTA_INCLINATA_ASCENDENS:
if (last_pitch < current_pitch) {
next_glyph_type = G_3_PUNCTA_INCLINATA_ASCENDENS;
} else {
next_glyph_type = G_TRIGONUS;
}
break;
case G_3_PUNCTA_INCLINATA_ASCENDENS:
if (last_pitch < current_pitch) {
next_glyph_type = G_4_PUNCTA_INCLINATA_ASCENDENS;
} else {
next_glyph_type = G_PUNCTA_INCLINATA;
}
break;
case G_4_PUNCTA_INCLINATA_ASCENDENS:
if (last_pitch < current_pitch) {
next_glyph_type = G_5_PUNCTA_INCLINATA_ASCENDENS;
} else {
next_glyph_type = G_PUNCTA_INCLINATA;
}
break;
case G_2_PUNCTA_INCLINATA_DESCENDENS:
if (last_pitch < current_pitch) {
next_glyph_type = G_TRIGONUS;
} else {
next_glyph_type = G_3_PUNCTA_INCLINATA_DESCENDENS;
}
break;
case G_3_PUNCTA_INCLINATA_DESCENDENS:
if (last_pitch < current_pitch) {
next_glyph_type = G_PUNCTA_INCLINATA;
} else {
next_glyph_type = G_4_PUNCTA_INCLINATA_DESCENDENS;
}
break;
case G_4_PUNCTA_INCLINATA_DESCENDENS:
if (last_pitch < current_pitch) {
next_glyph_type = G_PUNCTA_INCLINATA;
} else {
next_glyph_type = G_5_PUNCTA_INCLINATA_DESCENDENS;
}
break;
default:
next_glyph_type = G_PUNCTA_INCLINATA;
break;
}
break;
case S_STROPHA:
if (last_pitch != current_pitch) {
*end_of_glyph = DET_END_OF_PREVIOUS;
next_glyph_type = G_STROPHA;
break;
}
switch (current_glyph_type) {
case G_STROPHA:
next_glyph_type = G_DISTROPHA;
break;
case G_DISTROPHA:
*end_of_glyph = DET_END_OF_CURRENT;
next_glyph_type = G_TRISTROPHA;
break;
default:
*end_of_glyph = DET_END_OF_PREVIOUS;
next_glyph_type = G_STROPHA;
break;
}
break;
case S_DISTROPHA:
if (last_pitch == current_pitch && current_glyph_type == G_STROPHA) {
*end_of_glyph = DET_END_OF_CURRENT;
next_glyph_type = G_TRISTROPHA;
} else {
*end_of_glyph = DET_END_OF_PREVIOUS;
next_glyph_type = G_DISTROPHA;
}
break;
case S_TRISTROPHA:
*end_of_glyph = DET_END_OF_BOTH;
next_glyph_type = G_TRISTROPHA;
break;
default:
break;
}
/* end of the main switch */
if (current_glyph_type == G_UNDETERMINED) {
/*
* means that this is the first glyph or that the previous glyph has
* already been added
*/
if (*end_of_glyph == DET_END_OF_PREVIOUS) {
*end_of_glyph = DET_NO_END;
} else {
if (*end_of_glyph == DET_END_OF_BOTH) {
*end_of_glyph = DET_END_OF_CURRENT;
}
}
}
/*
* WARNING : Ugly section of the code, just some kind of patch for it to work
* with fonts that can't handle large intervals.
*/
/* here we separate notes that would be logically in the same glyph
* but that are too far to be so, we already said to the function that
* it was not the same glyph, there we must say that the previous
* glyph has ended. */
if (last_pitch) {
if (current_pitch - last_pitch > MAX_INTERVAL
|| current_pitch - last_pitch < -MAX_INTERVAL) {
if (*end_of_glyph == DET_END_OF_CURRENT
|| *end_of_glyph == DET_END_OF_BOTH) {
*end_of_glyph = DET_END_OF_BOTH;
} else {
*end_of_glyph = DET_END_OF_PREVIOUS;
}
}
}
return next_glyph_type;
}
/****************************
*
* Function called with a list of gregorio_notes as argument, this
* list is determined from gabc notation by the function
* gabc_det_notes_from_string.
*
* In this function we create a list of glyphs, by determining their
* type according to the sequence of notes (we look at their height,
* shape, etc.). Each glyph has a pointer gregorio_note *first_note
* that will be filled with the good note (and notes will be cut as
* explained in the comments on close_glyph function).
*
* Here is how it works :
* current_glyph is the glyph we are currently determining, that is to
* say a glyph whose type may change according to the note we will add
* to it.
* current_note is the note we are currently dealing with.
* Let's take an example, if the list of notes is ab, the first step
* (current_glyph: undetermined, current_note: a) will be to add a to
* nothing, that will give a glyph "punctum" containing only one note:
* a. In the second step (current_glyph: punctum, current_note: b) we
* transform the glyph in "pes".
* For special notes like a key change or something, we stop the
* determination of the current glyph, we delete the note and we add
* it as a glyph.
*
* When we determine the glyphs we can encounter the shapes
* S_QUADRATUM and S_QUILISMA_QUADRATUM, which means that the
* corresponding note is the first note of a pes quadratum (it can
* have the shape quilisma for very rare forms). But these shapes must
* not appear in the final form of the score, and we transform them
* respectively in punctum and quilisma (and the glyph type must be
* pes_quadratum, but it is done in gregorio_add_note_to_a_glyph).
*
****************************/
/* this function updates current_key with the new values (with clef changes) */
gregorio_glyph *gabc_det_glyphs_from_notes(gregorio_note *current_note,
int *current_key)
{
/* the first note of the current glyph, to be able to close it well:
* later we will cut the link (next_notes and previous_note) between
* this note and the previous one */
gregorio_note *current_glyph_first_note = current_note;
/* the last glyph we have totally determined. It is automatically
* updated by close_glyph(). */
gregorio_glyph *last_glyph = NULL;
/* type of the glyph we are currently determining */
gregorio_glyph_type current_glyph_type = G_UNDETERMINED;
gregorio_glyph_type next_glyph_type = G_UNDETERMINED;
char last_pitch = USELESS_VALUE;
/* a variable for the signs of bars and to tell if a key is flatted or
* not */
gregorio_note *next_note = NULL;
/* determination of end of glyphs, see comments on
* gregorio_add_note_to_a_glyph */
gabc_determination end_of_glyph = DET_NO_END;
/* a char representing the liquescentia of the current glyph */
gregorio_liquescentia liquescentia = L_NO_LIQUESCENTIA;
if (current_note == NULL) {
return NULL;
}
gregorio_go_to_first_note(¤t_note);
while (current_note) {
next_note = current_note->next;
if (current_note->type != GRE_NOTE) {
gregorio_type type = current_note->type;
char pitch = USELESS_VALUE;
bool flat = false;
bool force = false;
gregorio_sign sign = _NO_SIGN;
if (current_glyph_type != G_UNDETERMINED) {
close_glyph(&last_glyph, next_glyph_type,
¤t_glyph_first_note, liquescentia,
current_note->previous);
current_glyph_type = G_UNDETERMINED;
liquescentia = L_NO_LIQUESCENTIA;
}
switch (type) {
case GRE_C_KEY_CHANGE:
pitch = current_note->u.note.pitch;
*current_key = gregorio_calculate_new_key(C_KEY, pitch - '0');
break;
case GRE_F_KEY_CHANGE:
pitch = current_note->u.note.pitch;
*current_key = gregorio_calculate_new_key(F_KEY, pitch - '0');
break;
case GRE_C_KEY_CHANGE_FLATED:
pitch = current_note->u.note.pitch;
*current_key = gregorio_calculate_new_key(C_KEY, pitch - '0');
type = GRE_C_KEY_CHANGE;
flat = true;
break;
case GRE_F_KEY_CHANGE_FLATED:
pitch = current_note->u.note.pitch;
*current_key = gregorio_calculate_new_key(F_KEY, pitch - '0');
type = GRE_F_KEY_CHANGE;
flat = true;
break;
case GRE_CUSTOS:
pitch = gabc_determine_custo_pitch(current_note->next,
*current_key);
break;
case GRE_MANUAL_CUSTOS:
pitch = current_note->u.note.pitch;
type = GRE_CUSTOS;
force = true;
break;
case GRE_BAR:
/* we calculate the signs of the bars */
if (current_note->signs == _V_EPISEMUS) {
sign = _V_EPISEMUS;
} else {
sign = current_note->special_sign;
}
if (current_note->h_episemus_above) {
if (sign == _V_EPISEMUS) {
sign = _V_EPISEMUS_BAR_H_EPISEMUS;
} else {
sign = _BAR_H_EPISEMUS;
}
}
break;
case GRE_FLAT:
case GRE_SHARP:
case GRE_NATURAL:
pitch = current_note->u.note.pitch;
break;
default:
/* do nothing */
break;
}
if (pitch == USELESS_VALUE) {
gregorio_add_unpitched_element_as_glyph(&last_glyph, type,
current_note->u.other, sign, current_note->texverb);
} else {
gregorio_add_pitched_element_as_glyph(&last_glyph, type, pitch,
flat, force, current_note->texverb);
}
current_glyph_first_note = current_note->next;
current_note->texverb = NULL;
gregorio_free_one_note(¤t_note);
last_pitch = USELESS_VALUE;
continue;
}
/*
* first we do what must be done with liquescentia
*/
if (is_initio_debilis(current_note->u.note.liquescentia)) {
/*
* meaning that the note is an initio debilis, maybe more
*/
if (current_glyph_type != G_UNDETERMINED) {
/*
* if it is not the first glyph
*/
close_glyph(&last_glyph, current_glyph_type,
¤t_glyph_first_note,
liquescentia, current_note->previous);
current_glyph_type = G_UNDETERMINED;
}
liquescentia = L_INITIO_DEBILIS;
}
next_glyph_type =
gregorio_add_note_to_a_glyph(current_glyph_type,
current_note->u.note.pitch, last_pitch,
current_note->u.note.shape,
current_note->u.note.liquescentia,
current_glyph_first_note, &end_of_glyph);
/* patch to have good shapes in the special cases of pes quadratum and
* pes quilisma quadratum. */
switch (current_note->u.note.shape) {
case S_QUADRATUM:
current_note->u.note.shape = S_PUNCTUM;
break;
case S_QUILISMA_QUADRATUM:
current_note->u.note.shape = S_QUILISMA;
break;
default:
/* do nothing */
break;
}
/* see comments on gregorio_add_note_to_a_glyph for the meaning of
* end_of_glyph */
switch (end_of_glyph) {
case DET_NO_END:
current_glyph_type = next_glyph_type;
/*
* we deal with liquescentia
*/
if (is_liquescentia(current_note->u.note.liquescentia)) {
/* special cases of oriscus auctus, treated like normal oriscus
* in some cases. */
if (current_note->u.note.shape == S_ORISCUS_AUCTUS
&& current_note->next
&& current_note->next->type == GRE_NOTE
&& current_note->next->u.note.pitch <
current_note->u.note.pitch) {
last_pitch = current_note->u.note.pitch;
current_note->u.note.shape = S_ORISCUS;
current_note->u.note.liquescentia = L_NO_LIQUESCENTIA;
current_note = next_note;
continue;
}
/* special cases of the punctum inclinatum deminutus and
* auctus */
if (current_note->u.note.shape == S_PUNCTUM_INCLINATUM) {
if (current_note->u.note.liquescentia == L_DEMINUTUS) {
current_note->u.note.shape =
S_PUNCTUM_INCLINATUM_DEMINUTUS;
}
if (current_note->u.note.liquescentia == L_AUCTA
|| current_note->u.note.liquescentia ==
L_AUCTUS_DESCENDENS
|| current_note->u.note.liquescentia ==
L_AUCTUS_ASCENDENS) {
current_note->u.note.shape =
S_PUNCTUM_INCLINATUM_AUCTUS;
}
if (current_note->next
&& current_note->next->type == GRE_NOTE
&& current_note->next->u.note.shape ==
S_PUNCTUM_INCLINATUM
&& current_note->next->u.note.liquescentia ==
L_DEMINUTUS) {
last_pitch = current_note->u.note.pitch;
current_note = next_note;
continue;
}
}
if (current_note->u.note.shape == S_PUNCTUM_CAVUM_INCLINATUM) {
switch (current_note->u.note.liquescentia) {
case L_AUCTA:
case L_AUCTUS_DESCENDENS:
case L_AUCTUS_ASCENDENS:
case L_AUCTUS_DESCENDENS_INITIO_DEBILIS:
case L_AUCTUS_ASCENDENS_INITIO_DEBILIS:
current_note->u.note.shape =
S_PUNCTUM_CAVUM_INCLINATUM_AUCTUS;
break;
default:
/* do nothing */
break;
}
if (current_note->next
&& current_note->next->type == GRE_NOTE
&& current_note->next->u.note.shape ==
S_PUNCTUM_INCLINATUM
&& current_note->next->u.note.liquescentia ==
L_DEMINUTUS) {
last_pitch = current_note->u.note.pitch;
current_note = next_note;
continue;
}
}
liquescentia += current_note->u.note.liquescentia;
/* once again, only works with the good values in the header
* file */
close_glyph(&last_glyph, current_glyph_type,
¤t_glyph_first_note, liquescentia, current_note);
current_glyph_type = G_UNDETERMINED;
liquescentia = L_NO_LIQUESCENTIA;
}
break;
case DET_END_OF_PREVIOUS:
if (current_note->previous)
{
/* we don't want to close previous glyph twice */
close_glyph(&last_glyph, current_glyph_type,
¤t_glyph_first_note, liquescentia,
current_note->previous);
}
current_glyph_type = next_glyph_type;
liquescentia = L_NO_LIQUESCENTIA;
last_pitch = USELESS_VALUE;
/* we deal with liquescentia */
if (is_liquescentia(current_note->u.note.liquescentia))
/* not an initio debilis, because we considered it in the first
* part... */
{
/* special cases of the punctum inclinatum deminutus and
* auctus */
if (current_note->u.note.shape == S_PUNCTUM_INCLINATUM) {
if (current_note->u.note.liquescentia == L_DEMINUTUS) {
current_note->u.note.shape =
S_PUNCTUM_INCLINATUM_DEMINUTUS;
}
if (current_note->u.note.liquescentia == L_AUCTA
|| current_note->u.note.liquescentia ==
L_AUCTUS_DESCENDENS
|| current_note->u.note.liquescentia ==
L_AUCTUS_ASCENDENS) {
current_note->u.note.shape =
S_PUNCTUM_INCLINATUM_AUCTUS;
}
if (current_note->next
&& current_note->next->type == GRE_NOTE
&& current_note->next->u.note.shape ==
S_PUNCTUM_INCLINATUM
&& current_note->next->u.note.liquescentia ==
L_DEMINUTUS) {
current_note = next_note;
continue;
}
}
if (current_note->u.note.shape == S_PUNCTUM_CAVUM_INCLINATUM) {
switch (current_note->u.note.liquescentia) {
case L_AUCTA:
case L_AUCTUS_DESCENDENS:
case L_AUCTUS_ASCENDENS:
case L_AUCTUS_DESCENDENS_INITIO_DEBILIS:
case L_AUCTUS_ASCENDENS_INITIO_DEBILIS:
current_note->u.note.shape =
S_PUNCTUM_CAVUM_INCLINATUM_AUCTUS;
break;
default:
/* do nothing */
break;
}
if (current_note->next
&& current_note->next->type == GRE_NOTE
&& current_note->next->u.note.shape ==
S_PUNCTUM_INCLINATUM
&& current_note->next->u.note.liquescentia ==
L_DEMINUTUS) {
current_note = next_note;
continue;
}
}
close_glyph(&last_glyph, current_glyph_type,
¤t_glyph_first_note,
current_note->u.note.liquescentia, current_note);
current_glyph_type = G_UNDETERMINED;
}
break;
case DET_END_OF_CURRENT:
liquescentia += current_note->u.note.liquescentia;
/* once again, only works with the good values in the header file */
close_glyph(&last_glyph, next_glyph_type,
¤t_glyph_first_note, liquescentia, current_note);
current_glyph_type = G_UNDETERMINED;
liquescentia = L_NO_LIQUESCENTIA;
break;
default: /* case DET_END_OF_BOTH: */
if (current_note->previous)
{
/* we don't want to close previous glyph twice */
close_glyph(&last_glyph, current_glyph_type,
¤t_glyph_first_note, liquescentia,
current_note->previous);
}
current_glyph_type = G_UNDETERMINED;
liquescentia = L_NO_LIQUESCENTIA;
close_glyph(&last_glyph, next_glyph_type,
¤t_glyph_first_note,
current_note->u.note.liquescentia, current_note);
break;
}
if (!next_note && current_glyph_type != G_UNDETERMINED) {
/* we must end the determination here */
close_glyph(&last_glyph, current_glyph_type,
¤t_glyph_first_note, liquescentia, current_note);
}
last_pitch = current_note->u.note.pitch;
current_note = next_note;
}
/* end of while */
gregorio_go_to_first_glyph(&last_glyph);
return last_glyph;
}