From a0054fd2c048c13c5610468ecd7be209a6fb4717 Mon Sep 17 00:00:00 2001 From: David Chiang Date: Sat, 25 Jan 2025 22:17:07 -0500 Subject: [PATCH] Add "soft" flat (X), sharp (#*), and natural (Y), which appear only if they are the first on the line or different from the previous alteration. Remove the header option alteration-scope. --- src/gabc/gabc-glyphs-determination.c | 3 ++ src/gabc/gabc-notes-determination.l | 12 ++++++ src/gabc/gabc-write.c | 9 +++++ src/gregoriotex/gregoriotex-position.c | 12 ++++++ src/gregoriotex/gregoriotex-write.c | 33 ++++++++++++++++ src/gregoriotex/gregoriotex.h | 5 ++- src/struct.c | 3 ++ src/struct.h | 3 ++ tex/gregoriotex-main.tex | 14 ------- tex/gregoriotex-signs.tex | 53 +++++++++++++++++++++----- tex/gregoriotex-syllable.tex | 2 +- 11 files changed, 123 insertions(+), 26 deletions(-) diff --git a/src/gabc/gabc-glyphs-determination.c b/src/gabc/gabc-glyphs-determination.c index bf9b0a61..5d412975 100644 --- a/src/gabc/gabc-glyphs-determination.c +++ b/src/gabc/gabc-glyphs-determination.c @@ -138,10 +138,13 @@ static char add_note_to_a_glyph(gregorio_glyph_type current_glyph_type, break; case S_FLAT: case S_FLAT_PAREN: + case S_FLAT_SOFT: case S_SHARP: case S_SHARP_PAREN: + case S_SHARP_SOFT: case S_NATURAL: case S_NATURAL_PAREN: + case S_NATURAL_SOFT: next_glyph_type = G_ALTERATION; *end_of_glyph = DET_END_OF_BOTH; break; diff --git a/src/gabc/gabc-notes-determination.l b/src/gabc/gabc-notes-determination.l index 9fc185f3..da16d227 100644 --- a/src/gabc/gabc-notes-determination.l +++ b/src/gabc/gabc-notes-determination.l @@ -1302,6 +1302,10 @@ x\? { gregorio_change_shape(current_note, S_FLAT_PAREN, legacy_oriscus_orientation); } +X { + gregorio_change_shape(current_note, S_FLAT_SOFT, + legacy_oriscus_orientation); + } # { gregorio_change_shape(current_note, S_SHARP, legacy_oriscus_orientation); @@ -1310,6 +1314,10 @@ x\? { gregorio_change_shape(current_note, S_SHARP_PAREN, legacy_oriscus_orientation); } +#\* { + gregorio_change_shape(current_note, S_SHARP_SOFT, + legacy_oriscus_orientation); + } y { gregorio_change_shape(current_note, S_NATURAL, legacy_oriscus_orientation); @@ -1318,6 +1326,10 @@ y\? { gregorio_change_shape(current_note, S_NATURAL_PAREN, legacy_oriscus_orientation); } +Y { + gregorio_change_shape(current_note, S_NATURAL_SOFT, + legacy_oriscus_orientation); + } !?\/0 { gregorio_add_space_as_note(¤t_note, SP_HALF_SPACE, NULL, ¬es_lloc); diff --git a/src/gabc/gabc-write.c b/src/gabc/gabc-write.c index 9ebed376..0da6c5e7 100644 --- a/src/gabc/gabc-write.c +++ b/src/gabc/gabc-write.c @@ -631,18 +631,27 @@ static void gabc_write_gregorio_note(FILE *f, gregorio_note *note, case S_FLAT_PAREN: fprintf(f, "%cx?", pitch_letter(note->u.note.pitch)); break; + case S_FLAT_SOFT: + fprintf(f, "%cX", pitch_letter(note->u.note.pitch)); + break; case S_NATURAL: fprintf(f, "%cy", pitch_letter(note->u.note.pitch)); break; case S_NATURAL_PAREN: fprintf(f, "%cy?", pitch_letter(note->u.note.pitch)); break; + case S_NATURAL_SOFT: + fprintf(f, "%cY", pitch_letter(note->u.note.pitch)); + break; case S_SHARP: fprintf(f, "%c#", pitch_letter(note->u.note.pitch)); break; case S_SHARP_PAREN: fprintf(f, "%c#?", pitch_letter(note->u.note.pitch)); break; + case S_SHARP_SOFT: + fprintf(f, "%c#*", pitch_letter(note->u.note.pitch)); + break; case S_VIRGA: fprintf(f, "%cv", pitch_letter(note->u.note.pitch)); break; diff --git a/src/gregoriotex/gregoriotex-position.c b/src/gregoriotex/gregoriotex-position.c index 76c7765c..dca8dd9b 100644 --- a/src/gregoriotex/gregoriotex-position.c +++ b/src/gregoriotex/gregoriotex-position.c @@ -90,10 +90,13 @@ OFFSET_CASE(LeadingQuilisma); OFFSET_CASE(LeadingOriscus); OFFSET_CASE(Flat); OFFSET_CASE(FlatParen); +OFFSET_CASE(FlatSoft); OFFSET_CASE(Sharp); OFFSET_CASE(SharpParen); +OFFSET_CASE(SharpSoft); OFFSET_CASE(Natural); OFFSET_CASE(NaturalParen); +OFFSET_CASE(NaturalSoft); static __inline const char *note_before_last_note_case_ignoring_deminutus( const gregorio_note *const current_note) @@ -951,18 +954,27 @@ static gregorio_vposition advise_positioning(const gregorio_glyph *const glyph, case S_FLAT_PAREN: note->gtex_offset_case = FlatParen; break; + case S_FLAT_SOFT: + note->gtex_offset_case = FlatSoft; + break; case S_SHARP: note->gtex_offset_case = Sharp; break; case S_SHARP_PAREN: note->gtex_offset_case = SharpParen; break; + case S_SHARP_SOFT: + note->gtex_offset_case = SharpSoft; + break; case S_NATURAL: note->gtex_offset_case = Natural; break; case S_NATURAL_PAREN: note->gtex_offset_case = NaturalParen; break; + case S_NATURAL_SOFT: + note->gtex_offset_case = NaturalSoft; + break; default: note->gtex_offset_case = last_note_case(glyph, fused_single_note_case(glyph, FinalPunctum, LeadingPunctum), diff --git a/src/gregoriotex/gregoriotex-write.c b/src/gregoriotex/gregoriotex-write.c index ddf0537e..3714849d 100644 --- a/src/gregoriotex/gregoriotex-write.c +++ b/src/gregoriotex/gregoriotex-write.c @@ -90,6 +90,7 @@ SHAPE(DescendensOriscusScapusOpenqueue); SHAPE(DescendensPunctumInclinatum); SHAPE(Flat); SHAPE(FlatParen); +SHAPE(FlatSoft); SHAPE(Flexus); SHAPE(FlexusLongqueue); SHAPE(FlexusNobar); @@ -106,6 +107,7 @@ SHAPE(Linea); SHAPE(LineaPunctum); SHAPE(Natural); SHAPE(NaturalParen); +SHAPE(NaturalSoft); SHAPE(OriscusDeminutus); SHAPE(Pes); SHAPE(PesAscendensOriscus); @@ -145,6 +147,7 @@ SHAPE(SalicusLongqueue); SHAPE(Scandicus); SHAPE(Sharp); SHAPE(SharpParen); +SHAPE(SharpSoft); SHAPE(Stropha); SHAPE(StrophaAucta); SHAPE(StrophaAuctaLongtail); @@ -789,14 +792,20 @@ static const char *determine_note_glyph_name(const gregorio_note *const note, return SHAPE_Flat; case S_FLAT_PAREN: return SHAPE_FlatParen; + case S_FLAT_SOFT: + return SHAPE_FlatSoft; case S_SHARP: return SHAPE_Sharp; case S_SHARP_PAREN: return SHAPE_SharpParen; + case S_SHARP_SOFT: + return SHAPE_SharpSoft; case S_NATURAL: return SHAPE_Natural; case S_NATURAL_PAREN: return SHAPE_NaturalParen; + case S_NATURAL_SOFT: + return SHAPE_NaturalSoft; default: /* not reachable unless there's a programming error */ /* LCOV_EXCL_START */ @@ -2609,14 +2618,20 @@ static __inline const char *alteration_name( return "Flat"; case S_FLAT_PAREN: return "FlatParen"; + case S_FLAT_SOFT: + return "FlatSoft"; case S_SHARP: return "Sharp"; case S_SHARP_PAREN: return "SharpParen"; + case S_SHARP_SOFT: + return "SharpSoft"; case S_NATURAL: return "Natural"; case S_NATURAL_PAREN: return "NaturalParen"; + case S_NATURAL_SOFT: + return "NaturalSoft"; default: return ""; } @@ -2689,10 +2704,13 @@ static void write_note(FILE *f, gregorio_note *note, switch (note->u.note.shape) { case S_FLAT: case S_FLAT_PAREN: + case S_FLAT_SOFT: case S_NATURAL: case S_NATURAL_PAREN: + case S_NATURAL_SOFT: case S_SHARP: case S_SHARP_PAREN: + case S_SHARP_SOFT: fprintf(f, "\\Gre%s{%d}{0}", alteration_name(note->u.note.shape), pitch_value(note->u.note.pitch)); break; @@ -2783,18 +2801,27 @@ static void syllable_first_type(gregorio_syllable *syllable, case S_FLAT_PAREN: *alteration = ALT_FLAT_PAREN; break; + case S_FLAT_SOFT: + *alteration = ALT_FLAT_SOFT; + break; case S_NATURAL: *alteration = ALT_NATURAL; break; case S_NATURAL_PAREN: *alteration = ALT_NATURAL_PAREN; break; + case S_NATURAL_SOFT: + *alteration = ALT_NATURAL_SOFT; + break; case S_SHARP: *alteration = ALT_SHARP; break; case S_SHARP_PAREN: *alteration = ALT_SHARP_PAREN; break; + case S_SHARP_SOFT: + *alteration = ALT_SHARP_SOFT; + break; default: /* not reachable unless there's a programming error */ /* LCOV_EXCL_START */ @@ -3938,10 +3965,13 @@ static void write_default_end_of_element(FILE *f, switch(last_note->u.note.shape) { case S_FLAT: case S_FLAT_PAREN: + case S_FLAT_SOFT: case S_SHARP: case S_SHARP_PAREN: + case S_SHARP_SOFT: case S_NATURAL: case S_NATURAL_PAREN: + case S_NATURAL_SOFT: break; default: last_pitch = last_note->u.note.pitch; @@ -3955,10 +3985,13 @@ static void write_default_end_of_element(FILE *f, switch(next_note->u.note.shape) { case S_FLAT: case S_FLAT_PAREN: + case S_FLAT_SOFT: case S_SHARP: case S_SHARP_PAREN: + case S_SHARP_SOFT: case S_NATURAL: case S_NATURAL_PAREN: + case S_NATURAL_SOFT: break; default: if (next_note->u.note.pitch != NO_PITCH && diff --git a/src/gregoriotex/gregoriotex.h b/src/gregoriotex/gregoriotex.h index b61b26c5..7fc71f36 100644 --- a/src/gregoriotex/gregoriotex.h +++ b/src/gregoriotex/gregoriotex.h @@ -89,7 +89,10 @@ typedef enum gtex_alteration { ALT_SHARP = 3, ALT_FLAT_PAREN = 4, ALT_NATURAL_PAREN = 5, - ALT_SHARP_PAREN = 6 + ALT_SHARP_PAREN = 6, + ALT_FLAT_SOFT = 7, + ALT_NATURAL_SOFT = 8, + ALT_SHARP_SOFT = 9 } gtex_alteration; /* Here we define a function that will determine the number of the diff --git a/src/struct.c b/src/struct.c index 6871df42..a1fb0082 100644 --- a/src/struct.c +++ b/src/struct.c @@ -1301,10 +1301,13 @@ static __inline signed char next_pitch_from_glyph(const gregorio_glyph *glyph, switch (note->u.note.shape) { case S_FLAT: case S_FLAT_PAREN: + case S_FLAT_SOFT: case S_SHARP: case S_SHARP_PAREN: + case S_SHARP_SOFT: case S_NATURAL: case S_NATURAL_PAREN: + case S_NATURAL_SOFT: if (note->u.note.pitch >= LOWEST_PITCH && note->u.note.pitch <= MAX_PITCH) { alterations[note->u.note.pitch] = diff --git a/src/struct.h b/src/struct.h index 7c1e95e6..971eba70 100644 --- a/src/struct.h +++ b/src/struct.h @@ -123,10 +123,13 @@ ENUM(gregorio_clef, GREGORIO_CLEF); E(S_LINEA_PUNCTUM) \ E(S_FLAT) \ E(S_FLAT_PAREN) \ + E(S_FLAT_SOFT) \ E(S_SHARP) \ E(S_SHARP_PAREN) \ + E(S_SHARP_SOFT) \ E(S_NATURAL) \ E(S_NATURAL_PAREN) \ + E(S_NATURAL_SOFT) \ /* special shapes that must not appear in the final form of the score : * quadratum is the shape of the first note of a punctum quadratum * and quilisma quadratum is the shape of the first note of a pes diff --git a/tex/gregoriotex-main.tex b/tex/gregoriotex-main.tex index b49cefa7..57b9031e 100644 --- a/tex/gregoriotex-main.tex +++ b/tex/gregoriotex-main.tex @@ -2142,18 +2142,4 @@ % We load the default space configuration. \greloadspaceconf{default}% -\newif\ifgre@alteration@line -\gre@alteration@linefalse -\def\gresetalterationscope#1{% - \IfStrEqCase{#1}{% - {none}% - {\gre@alteration@linefalse}% - {line}% - {\gre@alteration@linetrue}% - }[% all other cases - \gre@error{Unrecognized option "#1" for \protect\gresetalterationscope\MessageBreak Possible options are: 'none' and 'line'}% - ]% -} -\gresetheadercapture{alteration-scope}{gresetalterationscope}{} - \input gregoriotex-nabc.tex diff --git a/tex/gregoriotex-signs.tex b/tex/gregoriotex-signs.tex index a90321ea..34b358e1 100644 --- a/tex/gregoriotex-signs.tex +++ b/tex/gregoriotex-signs.tex @@ -2698,8 +2698,8 @@ % the top level macro: % #1 is the height % #2 is the alteration type: 0 = none, 1 = flat, 2 = natural, 3 = sharp, -% 4 = parenthesized flat, 5 = parenthesized natural, -% 6 = parenthesized flat +% 4/5/6 = parenthesized flat/natural/sharp, +% 7 = soft flat % #3 is 1 if the alteration is the flat in a clef % #4 are the signs to typeset before the glyph (typically additional bars, as they must be "behind" the glyph) % #5 are the signs to typeset after the glyph (almost all signs) @@ -2707,30 +2707,35 @@ \def\gre@alteration#1#2#3#4#5#6{% \gre@trace{gre@alteration{#1}{#2}{#3}{#4}{#5}{#6}}% \global\advance\gre@attr@alteration@id by 1\relax - \gre@alteration@isvisible{0}% + \def\gre@alteration@type{#2}% + \gre@alteration@isvisible{0}{\gre@alteration@type}% + \ifnum\gre@alteration@type>6\relax % treat soft alterations like hard + \edef\gre@alteration@type{\numexpr\gre@alteration@type-6\relax}% + \fi \ifgre@alteration@isvisible - \gre@alteration@visible{#1}{#2}{#3}{#4}{#5}{#6}% + \gre@alteration@visible{#1}{\gre@alteration@type}{#3}{#4}{#5}{#6}% \else % ignore #4 (ledger line) and #5 (not used anyway?) \hbox attr \gre@attrid@alteration@height=#1\relax - attr \gre@attrid@alteration@type=#2\relax + attr \gre@attrid@alteration@type=\gre@alteration@type\relax {}% \fi } % Test whether an alteration should be visible. -% #1 = 0 for current alteration, 1 for next alteration. +% #1: 0 for current alteration, 1 for next alteration. +% #2: alteration type % Sets \ifgre@alteration@isvisibletrue or \ifgre@alteration@isvisiblefalse. \newif\ifgre@alteration@isvisible -\def\gre@alteration@isvisible#1{% - \ifgre@alteration@line +\def\gre@alteration@isvisible#1#2{% + \ifnum#2>6 % soft: depends on whether it's the first \ifcase\directlua{gregoriotex.is_first_alteration(#1)}\relax \global\gre@alteration@isvisibletrue \else \global\gre@alteration@isvisiblefalse \fi - \else + \else % hard: always visible \global\gre@alteration@isvisibletrue \fi } @@ -2744,6 +2749,7 @@ \or\def\gre@alteration@char{\gre@fontchar@flatparen}\def\gre@alteration@hole{\gre@fontchar@flatparenhole}% parenthesized flat \or\def\gre@alteration@char{\gre@fontchar@naturalparen}\def\gre@alteration@hole{\gre@fontchar@naturalparenhole}% parenthesized natural \or\def\gre@alteration@char{\gre@fontchar@sharpparen}\def\gre@alteration@hole{\gre@fontchar@sharpparenhole}% parenthesized sharp + \else\gre@error{Invalid alteration type}% soft alterations should have been changed to hard \fi \setbox\gre@box@temp@width=\hbox attr \gre@attrid@alteration@height=#1\relax @@ -2807,6 +2813,15 @@ \gre@trace@end% }% +% Same as the one before, but for soft flats. + +\def\GreFlatSoft#1#2#3#4#5{% + \gre@trace{GreFlatSoft{#1}{#2}{#3}{#4}{#5}}% + \gre@alteration{#1}{7}{#2}{#3}{#4}{#5}% + \relax% + \gre@trace@end% +}% + % Same as the one before, but for naturals. \def\GreNatural#1#2#3#4#5{% @@ -2825,6 +2840,15 @@ \gre@trace@end% }% +% Same as the one before, but for soft naturals. + +\def\GreNaturalSoft#1#2#3#4#5{% + \gre@trace{GreNaturalSoft{#1}{#2}{#3}{#4}{#5}}% + \gre@alteration{#1}{8}{#2}{#3}{#4}{#5}% + \relax% + \gre@trace@end% +}% + % Same as the one before, but for sharps. \def\GreSharp#1#2#3#4#5{% @@ -2834,7 +2858,7 @@ \gre@trace@end% }% -% Same as the one before, but for sharps. +% Same as the one before, but for parenthesized sharps. \def\GreSharpParen#1#2#3#4#5{% \gre@trace{GreSharpParen{#1}{#2}{#3}{#4}{#5}}% @@ -2843,6 +2867,15 @@ \gre@trace@end% }% +% Same as the one before, but for soft sharps. + +\def\GreSharpSoft#1#2#3#4#5{% + \gre@trace{GreSharpSoft{#1}{#2}{#3}{#4}{#5}}% + \gre@alteration{#1}{9}{#2}{#3}{#4}{#5}% + \relax% + \gre@trace@end% +}% + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% macros for typesetting punctum cavum %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% diff --git a/tex/gregoriotex-syllable.tex b/tex/gregoriotex-syllable.tex index cacbeaa9..8dc57b61 100644 --- a/tex/gregoriotex-syllable.tex +++ b/tex/gregoriotex-syllable.tex @@ -911,7 +911,7 @@ \def\gre@nextalignment{\gre@arg@oftwo@first#7}% \def\gre@nextalteration{\gre@arg@oftwo@second#7}% \ifnum\gre@nextalteration>0\relax - \gre@alteration@isvisible{1}% if the notes contain an alteration, the id was incremented, so this checks the alteration after the notes + \gre@alteration@isvisible{1}{\gre@nextalteration}% if the notes contain an alteration, the id was incremented, so this checks the alteration after the notes \ifgre@alteration@isvisible \else \def\gre@nextalteration{0}%