Skip to content

Commit

Permalink
Suppressed clefs at the end of lines.
Browse files Browse the repository at this point in the history
Part of the implementation for gregorio-project#1190.
  • Loading branch information
henryso committed Aug 7, 2016
1 parent 6d6af20 commit f95d597
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 71 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ As of v3.0.0 this project adheres to [Semantic Versioning](http://semver.org/).
[Unreleased][unreleased]
## Changed
- Notes are now left-aligned as if all clefs had the same width as the largest clef in the score. You can get previous behavior back with `\grebolshiftcleftype{current}`, or temporary force alignment until the end of a score with `\grelocalbolshiftcleftype`. See Documentation of these functions and [#1189](https://github.com/gregorio-project/gregorio/issues/1189).
- If only bars and clefs are between an explicit custos `(z0)` and a line break `(z)`, the explicit custos will be suppressed (see [1190](https://github.com/gregorio-project/gregorio/issues/1190)).
- A clef change immediately before a line break `(z)` will now typeset the new clef at the beginning of the next line. An explicit custos `(z0)` immediately before such a clef change (or separated by only a bar) will be suppressed. See [1190](https://github.com/gregorio-project/gregorio/issues/1190).

### Added
- More cavum shapes are now available. To use them, simply add `r` in gabc to any note in a glyph. See [#844](https://github.com/gregorio-project/gregorio/issues/844).
Expand Down
94 changes: 53 additions & 41 deletions src/gabc/gabc-score-determination.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,58 +76,70 @@ void gabc_fix_custos_pitches(gregorio_score *score_to_check)
gregorio_syllable *current_syllable;
gregorio_element *current_element;
gregorio_element *custos_element;
char pitch = 0;
char pitch_difference = 0;
int newkey;
int current_key;

if (!score_to_check || !score_to_check->first_syllable
|| !score_to_check->first_voice_info) {
return;
}

current_key = gregorio_calculate_new_key(
score_to_check->first_voice_info->initial_clef);
current_syllable = score_to_check->first_syllable;
while (current_syllable) {
current_element = (current_syllable->elements)[0];
while (current_element) {
if (current_element->type == GRE_CUSTOS) {
custos_element = current_element;
pitch = custos_element->u.misc.pitched.pitch;
/* we look for the key */
while (current_element) {
if (current_element->type == GRE_CLEF) {
pitch = gregorio_determine_next_pitch(current_syllable,
current_element, NULL, NULL);
newkey = gregorio_calculate_new_key(
current_element->u.misc.clef);
pitch_difference = (char) newkey - (char) current_key;
pitch -= pitch_difference;
current_key = newkey;
}
if (!custos_element->u.misc.pitched.force_pitch) {
while (pitch < LOWEST_PITCH) {
pitch += 7;
}
while (pitch > score_to_check->highest_pitch) {
pitch -= 7;
}
custos_element->u.misc.pitched.pitch = pitch;
}
assert(custos_element->u.misc.pitched.pitch >= LOWEST_PITCH
&& custos_element->u.misc.pitched.pitch
<= score_to_check->highest_pitch);
current_element = current_element->next;
}
for (current_syllable = score_to_check->first_syllable; current_syllable;
current_syllable = current_syllable->next_syllable) {
for (current_element = (current_syllable->elements)[0]; current_element;
current_element = current_element->next) {
if (current_element->type == GRE_CLEF) {
newkey = gregorio_calculate_new_key(
current_element->u.misc.clef);
current_element->u.misc.clef.pitch_difference =
(signed char) newkey - (signed char) current_key;
current_key = newkey;
}
if (current_element) {
if (current_element->type == GRE_CLEF) {
current_key = gregorio_calculate_new_key(
current_element->u.misc.clef);
}
}

custos_element = NULL;
for (current_syllable = score_to_check->first_syllable; current_syllable;
current_syllable = current_syllable->next_syllable) {
for (current_element = (current_syllable->elements)[0]; current_element;
current_element = current_element->next) {
switch (current_element->type) {
case GRE_CUSTOS:
if (current_element->u.misc.pitched.force_pitch) {
/* forget about the preceding custos if a forced one is
* encountered */
custos_element = NULL;
} else {
/* the pitch is not forced, so it may need to be adjusted */
custos_element = current_element;
custos_element->u.misc.pitched.pitch =
gregorio_determine_next_pitch(current_syllable,
current_element, NULL, NULL);
}
current_element = current_element->next;
break;

case GRE_ELEMENT:
/* if it's an element, forget any preceding custos */
custos_element = NULL;
break;

case GRE_CLEF:
if (custos_element) {
/* adjust the preceding custos for the clef */
custos_element->u.misc.pitched.pitch =
gregorio_adjust_pitch_into_staff(score_to_check,
custos_element->u.misc.pitched.pitch
- current_element->u.misc.clef.pitch_difference);
}
break;

default:
/* to prevent the warning */
break;
}
}
current_syllable = current_syllable->next_syllable;
}
}

Expand Down Expand Up @@ -389,7 +401,7 @@ void gabc_determine_punctum_inclinatum_orientation(
};

gregorio_for_each_note(score, punctum_inclinatum_orientation_visit, &v);

if (v.first.note) {
v.orientation = (v.running > 0)
? S_PUNCTUM_INCLINATUM_ASCENDENS
Expand Down
100 changes: 71 additions & 29 deletions src/gregoriotex/gregoriotex-write.c
Original file line number Diff line number Diff line change
Expand Up @@ -2873,7 +2873,7 @@ static void write_signs(FILE *f, gtex_type type,
fprintf(f, "}%%\n");
}

static char *determine_leading_shape(gregorio_glyph *glyph)
static char *determine_leading_shape(const gregorio_glyph *const glyph)
{
static char buf[BUFSIZE];
int ambitus = compute_ambitus(glyph->u.notes.first_note);
Expand Down Expand Up @@ -2928,8 +2928,9 @@ static __inline void write_composed_multinote_glyph(FILE *const f,
}
}

static void write_glyph(FILE *f, gregorio_syllable *syllable,
gregorio_element *element, gregorio_glyph *glyph,
static void write_glyph(FILE *const f, const gregorio_syllable *const syllable,
const gregorio_element *const element,
gregorio_glyph *const glyph,
gregoriotex_status *const status, const gregorio_score *const score)
{
static char cpbuf[96], cpbuf2[96];
Expand Down Expand Up @@ -3137,8 +3138,10 @@ static __inline unsigned int glyph_note_units(const gregorio_glyph *glyph)
/* here we absolutely need to pass the syllable as an argument, because we
* will need the next note, that may be contained in the next syllable */

static unsigned int write_element(FILE *f, gregorio_syllable *syllable,
gregorio_element *element, gregoriotex_status *status,
static unsigned int write_element(FILE *const f,
const gregorio_syllable *const syllable,
const gregorio_element *const element,
gregoriotex_status *const status,
const gregorio_score *const score)
{
unsigned int note_unit_count = 0;
Expand Down Expand Up @@ -3265,7 +3268,7 @@ static void write_text(FILE *const f, const gregorio_character *const text)
* \GreChangeClef.
*/
static void gregoriotex_print_change_line_clef(FILE *f,
gregorio_element *current_element)
const gregorio_element *const current_element)
{
if (current_element->type == GRE_CLEF) {
/* the third argument is 0 or 1 according to the need for a space
Expand Down Expand Up @@ -3564,6 +3567,30 @@ static __inline void handle_last_of_voice(FILE *const f,
}
}

static bool is_before_linebreak(const gregorio_syllable *syllable,
const gregorio_element *element)
{
if (element) {
element = element->next;
}

while (syllable) {
if (element) {
if (element->type == GRE_END_OF_LINE) {
return true;
}
break;
}

syllable = syllable->next_syllable;
if (syllable) {
element = syllable->elements[0];
}
}

return false;
}

/*
* Arguments are relatively obvious. The most obscure is certainly first_of_disc
* which is 0 all the time, except in the case of a "clef change syllable". In
Expand All @@ -3584,7 +3611,7 @@ static void write_syllable(FILE *f, gregorio_syllable *syllable,
void (*const write_this_syllable_text)
(FILE *, const char *, bool, const gregorio_character *, bool))
{
gregorio_element *clef_change_element = NULL, *element;
const gregorio_element *clef_change_element = NULL, *element;
const char *syllable_type = NULL;
bool anticipated_event_written = false;
bool end_of_word;
Expand All @@ -3606,13 +3633,13 @@ static void write_syllable(FILE *f, gregorio_syllable *syllable,
if (syllable->euouae == EUOUAE_BEGINNING) {
fprintf(f, "\\GreBeginEUOUAE{%hu}%%\n", syllable->euouae_id);
}
/*
* first we check if the syllable is only a end of line. If it is the case,
* we don't print anything but a comment (to be able to read it if we read
* GregorioTeX). The end of lines are treated separately in GregorioTeX, it
* is buit inside the TeX structure.
*/
if (syllable->elements && *(syllable->elements)) {
/*
* first we check if the syllable is only a end of line. If it is the
* case, we don't print anything but a comment (to be able to read it
* if we read GregorioTeX). The end of lines are treated separately in
* GregorioTeX, it is buit inside the TeX structure.
*/
if ((syllable->elements)[0]->type == GRE_END_OF_LINE) {
gregorio_assert(syllable != score->first_syllable, write_syllable,
"line break is not supported on the first syllable",
Expand Down Expand Up @@ -3835,22 +3862,37 @@ static void write_syllable(FILE *f, gregorio_syllable *syllable,
case GRE_CLEF:
/* We don't print clef changes at the end of a line */
if (first_of_disc != 1) {
/* the third argument is 0 or 1 according to the need
* for a space before the clef */
fprintf(f, "\\GreChangeClef{%c}{%d}{%c}{%d}{%c}{%d}{%d}%%\n",
gregorio_clef_to_char(element->u.misc.clef.clef),
element->u.misc.clef.line,
(!element->previous || element->previous->type
== GRE_BAR)? '0' : '1',
clef_flat_height(element->u.misc.clef.clef,
element->u.misc.clef.line,
element->u.misc.clef.flatted),
gregorio_clef_to_char(
element->u.misc.clef.secondary_clef),
element->u.misc.clef.secondary_line,
clef_flat_height(element->u.misc.clef.secondary_clef,
element->u.misc.clef.secondary_line,
element->u.misc.clef.secondary_flatted));
if (is_before_linebreak(syllable, element)) {
signed char next_note_pitch;
gregorio_shape next_note_alteration;

next_note_pitch = gregorio_adjust_pitch_into_staff(
score, gregorio_determine_next_pitch(
syllable, element, NULL, &next_note_alteration)
- element->u.misc.clef.pitch_difference);

fputs(next_custos(next_note_pitch,
next_note_alteration), f);
gregoriotex_print_change_line_clef(f, element);
} else {
/* the third argument is 0 or 1 according to the need
* for a space before the clef */
fprintf(f, "\\GreChangeClef{%c}{%d}{%c}{%d}{%c}{%d}{%d}%%\n",
gregorio_clef_to_char(element->u.misc.clef.clef),
element->u.misc.clef.line,
(!element->previous || element->previous->type
== GRE_BAR)? '0' : '1',
clef_flat_height(element->u.misc.clef.clef,
element->u.misc.clef.line,
element->u.misc.clef.flatted),
gregorio_clef_to_char(
element->u.misc.clef.secondary_clef),
element->u.misc.clef.secondary_line,
clef_flat_height(
element->u.misc.clef.secondary_clef,
element->u.misc.clef.secondary_line,
element->u.misc.clef.secondary_flatted));
}
}
break;

Expand Down
1 change: 1 addition & 0 deletions src/struct.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ unsigned short tex_position_id = 0;
gregorio_clef_info gregorio_default_clef = {
/*.line =*/ 3,
/*.secondary_line =*/ 0,
/*.pitch_difference =*/ 0,
/*.clef =*/ CLEF_C,
/*.flatted =*/ false,
/*.secondary_clef =*/ CLEF_C, /* not used since secondary_line is 0 */
Expand Down
15 changes: 15 additions & 0 deletions src/struct.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#ifndef STRUCT_H
#define STRUCT_H

#include <assert.h>
#include "enum_generator.h"
#include "bool.h"
#include "sha1.h"
Expand Down Expand Up @@ -386,6 +387,7 @@ typedef struct gregorio_extra_info {
typedef struct gregorio_clef_info {
signed char line;
signed char secondary_line;
signed char pitch_difference;
ENUM_BITFIELD(gregorio_clef) clef:1;
bool flatted:1;
ENUM_BITFIELD(gregorio_clef) secondary_clef:1;
Expand Down Expand Up @@ -943,4 +945,17 @@ static __inline char gregorio_clef_to_char(gregorio_clef clef)
return (clef == CLEF_C)? 'c' : 'f';
}

static __inline signed char gregorio_adjust_pitch_into_staff(
const gregorio_score *score, signed char pitch)
{
while (pitch < LOWEST_PITCH) {
pitch += 7;
}
while (pitch > score->highest_pitch) {
pitch -= 7;
}
assert(pitch >= LOWEST_PITCH && pitch <= score->highest_pitch);
return pitch;
}

#endif

0 comments on commit f95d597

Please sign in to comment.