Skip to content

Commit

Permalink
Implemented tail virga fusion.
Browse files Browse the repository at this point in the history
Part of the implementation for #1558
  • Loading branch information
henryso committed Jan 22, 2022
1 parent 7ec5d32 commit cb5b46d
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 27 deletions.
5 changes: 3 additions & 2 deletions doc/Gabc.tex
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ \subsection{File Structure}
mode-modifier: t.;
annotation: IN.;
annotation: 6;

%%

(clef) text(notes)
% another comment
com(notes)plex(notes) word(notes)
Expand Down Expand Up @@ -579,6 +579,7 @@ \subsubsection{Neume Fusion}
\texttt{gf} & flexus & if not at the end, must be followed by a higher note to fuse \\
\texttt{gh} & pes & at the end only; in non-liquescent form, the previous note must be lower to fuse \\
\texttt{gfg} & porrectus & at the end only, previous note must be lower to fuse \\
\texttt{gv} & virga & at the end only, previous note must be lower to fuse \\
\end{tabularx}

In the above table, \texttt{f}, \texttt{g}, and \texttt{h} are representative
Expand Down
8 changes: 7 additions & 1 deletion fonts/squarize.py
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,9 @@ def get_width(glyphName):
S_VIRGA = 'Virga'
S_VIRGA_LONGQUEUE = 'VirgaLongqueue'
S_VIRGA_OPENQUEUE = 'VirgaOpenqueue'
S_UPPER_VIRGA = 'UpperVirga'
S_UPPER_VIRGA_LONGQUEUE = 'UpperVirgaLongqueue'
S_UPPER_VIRGA_OPENQUEUE = 'UpperVirgaOpenqueue'
S_VIRGA_REVERSA = 'VirgaReversa'
S_VIRGA_REVERSA_LONGQUEUE = 'VirgaReversaLongqueue'
S_VIRGA_REVERSA_OPENQUEUE = 'VirgaReversaOpenqueue'
Expand Down Expand Up @@ -813,7 +816,7 @@ def set_width(width):
"Set the width of a glyph"
global newfont, glyphnumber
if glyphnumber in newfont:
newfont[glyphnumber].width = width
newfont[glyphnumber].width = int(width)

def get_queue_glyph(height, rev = False):
"Creates the asked line glyph in tmpglyph"
Expand Down Expand Up @@ -1009,6 +1012,9 @@ def virga():
write_virga(S_VIRGA, L_NOTHING, True, 'virgabase', 'short', S_VIRGA)
write_virga(S_VIRGA_LONGQUEUE, L_NOTHING, True, 'virgabase', 'long', S_VIRGA)
write_virga(S_VIRGA_OPENQUEUE, L_NOTHING, True, 'virgabase', 'open', S_VIRGA)
write_virga(S_UPPER_VIRGA, L_NOTHING, True, 'VirgaBaseLineBL', 'short', S_VIRGA)
write_virga(S_UPPER_VIRGA_LONGQUEUE, L_NOTHING, True, 'VirgaBaseLineBL', 'long', S_VIRGA)
write_virga(S_UPPER_VIRGA_OPENQUEUE, L_NOTHING, True, 'VirgaBaseLineBL', 'open', S_VIRGA)
write_virga(S_VIRGA_REVERSA, L_NOTHING, False, 'rvirgabase', 'short',
S_VIRGA_REVERSA)
write_virga(S_VIRGA_REVERSA_LONGQUEUE, L_NOTHING, False, 'rvirgabase',
Expand Down
7 changes: 6 additions & 1 deletion src/gabc/gabc-glyphs-determination.c
Original file line number Diff line number Diff line change
Expand Up @@ -1097,6 +1097,7 @@ gregorio_glyph *gabc_det_glyphs_from_notes(gregorio_note *current_note,
case S_QUILISMA:
case S_QUADRATUM:
case S_QUILISMA_QUADRATUM:
case S_VIRGA:
/* these are fusible */
if (current_glyph_type <= G_PUNCTA_INCLINATA
|| current_note->u.note.shape != S_PUNCTUM) {
Expand Down Expand Up @@ -1289,11 +1290,15 @@ gregorio_glyph *gabc_det_glyphs_from_notes(gregorio_note *current_note,
}
}

if (!next_note && current_glyph_type != G_UNDETERMINED) {
if ((!next_note && current_glyph_type != G_UNDETERMINED)
|| (autofuse && current_note
&& current_note->u.note.shape == S_VIRGA)) {
/* we must end the determination here */
current_note = close_glyph(&last_glyph, current_glyph_type,
&current_glyph_first_note, liquescentia, current_note,
punctum_inclinatum_orientation);
next_glyph_type = current_glyph_type = G_UNDETERMINED;
liquescentia = L_NO_LIQUESCENTIA;
}

last_pitch = current_note->u.note.pitch;
Expand Down
20 changes: 13 additions & 7 deletions src/gregoriotex/gregoriotex-position.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@
* Copyright (C) 2008-2021 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
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>. */

#include "config.h"
Expand Down Expand Up @@ -140,7 +140,7 @@ static __inline const char *last_note_case(
if (current_glyph->u.notes.liquescentia & L_DEMINUTUS) {
/*
* may seem strange, but it is unlogical to typeset a small horizontal
* episema at the end of a flexus deminutus
* episema at the end of a flexus deminutus
*/
return FinalDeminutus;
}
Expand Down Expand Up @@ -382,7 +382,7 @@ static gregorio_vposition advise_positioning(const gregorio_glyph *const glyph,
case T_PES:
case T_QUILISMA_PES:
/*
* in the case of a pes, we put the episema just under the bottom note
* in the case of a pes, we put the episema just under the bottom note
*/
if (i == 1) {
if (glyph->u.notes.liquescentia & L_INITIO_DEBILIS) {
Expand Down Expand Up @@ -436,7 +436,7 @@ static gregorio_vposition advise_positioning(const gregorio_glyph *const glyph,
if (type == T_FLEXUS_ORISCUS) {
note->gtex_offset_case = InitialConnectedOriscus;
} else {
if (note->next && note->u.note.pitch -
if (note->next && note->u.note.pitch -
note->next->u.note.pitch == 1) {
note->gtex_offset_case = InitialVirga;
} else {
Expand Down Expand Up @@ -1549,6 +1549,7 @@ static __inline int compute_fused_shift(const gregorio_glyph *glyph)

case G_PUNCTUM:
case G_FLEXA:
case G_VIRGA:
/* these may be fused to the previous note */
break;

Expand Down Expand Up @@ -1588,6 +1589,11 @@ static __inline int compute_fused_shift(const gregorio_glyph *glyph)
gregorio_assert(prev_note->type == GRE_NOTE, compute_fused_shift,
"previous note wasn't a note", return 0);

if (prev_note->u.note.shape == S_VIRGA) {
/* cannot fuse after a virga */
return 0;
}

shift = first_note->u.note.pitch - prev_note->u.note.pitch;
gregorio_assert(shift >= -MAX_AMBITUS && shift <= MAX_AMBITUS,
compute_fused_shift, "ambitus too large to fuse", return 0);
Expand Down
49 changes: 33 additions & 16 deletions src/gregoriotex/gregoriotex-write.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,15 +340,22 @@ static const char *compute_glyph_name(const gregorio_glyph *const glyph,

fuse_to_next_note = glyph->u.notes.fuse_to_next_glyph;

/*
* Note: due to the way auto fusion is computed, a virga inside auto fusion
* will have glyph type G_PUNCTUM and note shape S_VIRGA here. However, a
* fused virga outside auto fusion will have glyph type G_VIRGA.
*/
switch (glyph->u.notes.glyph_type) {
case G_PODATUS:
case G_PUNCTUM:
case G_FLEXA:
case G_VIRGA:
/* directionally head-fusible */
if (fuse_from_previous_note < 0) {
if (glyph->u.notes.first_note->u.note.shape != S_QUILISMA
&& glyph->u.notes.first_note->u.note.shape
!= S_QUILISMA_QUADRATUM) {
!= S_QUILISMA_QUADRATUM
&& glyph->u.notes.first_note->u.note.shape != S_VIRGA) {
if (fuse_from_previous_note < -1) {
fuse_head = FUSE_Lower;
} else if (glyph->u.notes.first_note->u.note.shape
Expand Down Expand Up @@ -386,17 +393,19 @@ static const char *compute_glyph_name(const gregorio_glyph *const glyph,
/* else fall through */
case G_VIRGA_REVERSA:
case G_PUNCTUM:
/* tail-fusible */
if (fuse_to_next_note < 0) {
fuse_tail = FUSE_Down;
fuse_ambitus = -fuse_to_next_note;
} else if (fuse_to_next_note > 0) {
fuse_tail = FUSE_Up;
fuse_ambitus = fuse_to_next_note;
}
if (glyph->u.notes.first_note->u.note.shape != S_VIRGA) {
/* tail-fusible */
if (fuse_to_next_note < 0) {
fuse_tail = FUSE_Down;
fuse_ambitus = -fuse_to_next_note;
} else if (fuse_to_next_note > 0) {
fuse_tail = FUSE_Up;
fuse_ambitus = fuse_to_next_note;
}

if (*fuse_tail && liquescentia == LIQ_Nothing) {
liquescentia = "";
if (*fuse_tail && liquescentia == LIQ_Nothing) {
liquescentia = "";
}
}
break;

Expand Down Expand Up @@ -450,7 +459,10 @@ static const char *compute_glyph_name(const gregorio_glyph *const glyph,
shape = SHAPE_DescendensOriscusLineTL;
}
}
fuse_head = "";
if (shape != SHAPE_Virga && shape != SHAPE_VirgaLongqueue &&
shape != SHAPE_VirgaOpenqueue) {
fuse_head = "";
}
}
gregorio_snprintf(buf, BUFSIZE, "%s%s%s%s%s", fuse_head, shape,
tex_ambitus[fuse_ambitus], liquescentia, fuse_tail);
Expand Down Expand Up @@ -626,15 +638,20 @@ static const char *determine_note_glyph_name(const gregorio_note *const note,
case S_LINEA_PUNCTUM:
return SHAPE_LineaPunctum;
case S_VIRGA:
return fusible_queued_shape(note, glyph, SHAPE_Virga,
SHAPE_VirgaLongqueue, SHAPE_VirgaOpenqueue);
/*
switch (queuetype_of(note)) {
case Q_ON_SPACE_ABOVE_BOTTOM_LINE:
return SHAPE_Virga;
return compute_glyph_name(glyph, SHAPE_Virga, LG_NONE, true);
case Q_ON_SPACE_BELOW_BOTTOM_LINE:
case Q_ON_BOTTOM_LINE:
return SHAPE_VirgaOpenqueue;
return compute_glyph_name(glyph, SHAPE_VirgaOpenqueue, LG_NONE,
true);
case Q_ON_LINE_ABOVE_BOTTOM_LINE:
return SHAPE_VirgaLongqueue;
} /* all cases return, so this line is not hit; LCOV_EXCL_LINE */
return compute_glyph_name(glyph, SHAPE_VirgaLongqueue, LG_NONE,
true);
}*/ /* all cases return, so this line is not hit; LCOV_EXCL_LINE */
/* LCOV_EXCL_START */
gregorio_fail2(determine_note_glyph_name, "unknown queuetype: %d",
queuetype_of(note));
Expand Down

0 comments on commit cb5b46d

Please sign in to comment.