commit 2997742861e389678c571664f4ba39f9363988c0
parent 8284135c6a93fa5726998f7ee5c2da78f38a320a
Author: nibo <nibo@relim.de>
Date: Sat, 10 Aug 2024 09:28:32 +0200
Allow markup tags inside annotations
Diffstat:
| M | chordpro.c | | | 79 | ++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------- |
| M | out_pdf.c | | | 19 | +++++++++++++++++++ |
2 files changed, 69 insertions(+), 29 deletions(-)
diff --git a/chordpro.c b/chordpro.c
@@ -580,21 +580,6 @@ const char *cho_linestyle_to_string(enum LineStyle linestyle)
}
}
-static const char *cho_style_property_type_to_string(enum StylePropertyType type)
-{
- switch (type) {
- case SPT_EMPTY:
- return "SPT_EMPTY";
- case SPT_FONT:
- return "SPT_FONT";
- case SPT_SIZE:
- return "SPT_SIZE";
- case SPT_COLOR:
- return "SPT_COLOR";
- }
- return "";
-}
-
static bool cho_style_property_apply_default(enum SongFragmentType current_ftype, enum StylePropertyType ptype, struct Style *style)
{
unsigned int i;
@@ -1919,7 +1904,6 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
char chord[15];
char tag_begin[6];
char tag_end[6];
- char annotation[512];
enum State state = STATE_LYRICS;
enum State prev_state = STATE_LYRICS;
unsigned int line_number = 1;
@@ -2368,6 +2352,14 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
break;
}
if (prev_buf == '[' && buf == '*') {
+ g_prev_ftype = g_current_ftype;
+ g_current_ftype = SF_ANNOT;
+ songs[so]->sections[se]->lines[li]->text_above = realloc(songs[so]->sections[se]->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *));
+ songs[so]->sections[se]->lines[li]->text_above[c] = malloc(sizeof(struct ChoLineItemAbove));
+ songs[so]->sections[se]->lines[li]->text_above[c]->is_chord = false;
+ chord_pos = cho_line_compute_chord_position(songs[so]->sections[se]->lines[li], ly, te);
+ songs[so]->sections[se]->lines[li]->text_above[c]->position = chord_pos;
+ songs[so]->sections[se]->lines[li]->text_above[c]->u.annot = cho_annotation_new();
state = STATE_ANNOTATION;
break;
}
@@ -2388,24 +2380,32 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
break;
case STATE_ANNOTATION:
if (buf == ']') {
- annotation[ann] = 0;
+ songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->text = realloc(songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->text, (ann+1) * sizeof(char));
+ songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->text[ann] = 0;
ann = 0;
- g_prev_ftype = g_current_ftype;
- g_current_ftype = SF_ANNOT;
- songs[so]->sections[se]->lines[li]->text_above = realloc(songs[so]->sections[se]->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *));
- songs[so]->sections[se]->lines[li]->text_above[c] = malloc(sizeof(struct ChoLineItemAbove));
- songs[so]->sections[se]->lines[li]->text_above[c]->is_chord = false;
- chord_pos = cho_line_compute_chord_position(songs[so]->sections[se]->lines[li], ly, te);
- songs[so]->sections[se]->lines[li]->text_above[c]->position = chord_pos;
- songs[so]->sections[se]->lines[li]->text_above[c]->u.annot = cho_annotation_new();
- songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->text = strdup(annotation);
- memset(annotation, 0, strlen(annotation));
c++;
g_current_ftype = g_prev_ftype;
state = STATE_LYRICS;
break;
}
- annotation[ann] = buf;
+ if (buf == '<') {
+ if (ann > 0) {
+ songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->text = realloc(songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->text, (ann+1) * sizeof(char));
+ songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->text[ann] = 0;
+ ann = 0;
+ c++;
+ songs[so]->sections[se]->lines[li]->text_above = realloc(songs[so]->sections[se]->lines[li]->text_above, (c+1) * sizeof(struct ChoLineItemAbove *));
+ songs[so]->sections[se]->lines[li]->text_above[c] = malloc(sizeof(struct ChoLineItemAbove));
+ songs[so]->sections[se]->lines[li]->text_above[c]->is_chord = false;
+ songs[so]->sections[se]->lines[li]->text_above[c]->position = chord_pos;
+ songs[so]->sections[se]->lines[li]->text_above[c]->u.annot = cho_annotation_new();
+ }
+ prev_state = STATE_ANNOTATION;
+ state = STATE_MARKUP_TAG;
+ break;
+ }
+ songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->text = realloc(songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->text, (ann+1) * sizeof(char));
+ songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->text[ann] = buf;
ann++;
break;
case STATE_MARKUP_TAG_BEGIN:
@@ -2430,6 +2430,8 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
songs[so]->sections[se]->lines[li]->text_above[c]->u.chord->style = cho_style_duplicate(tag_style);
break;
case STATE_ANNOTATION:
+ cho_style_free(songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->style);
+ songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->style = cho_style_duplicate(tag_style);
break;
default:
fprintf(stderr, "ERR: Invalid prev_state '%s'.\n", cho_state_to_string(prev_state));
@@ -2537,6 +2539,8 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
songs[so]->sections[se]->lines[li]->text_above[c]->u.chord->style = cho_style_duplicate(tag_style);
break;
case STATE_ANNOTATION:
+ cho_style_free(songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->style);
+ songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->style = cho_style_duplicate(tag_style);
break;
default:
fprintf(stderr, "ERR: Invalid prev_state '%s'.\n", cho_state_to_string(prev_state));
@@ -2607,6 +2611,8 @@ struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config)
songs[so]->sections[se]->lines[li]->text_above[c]->u.chord->style = cho_style_duplicate(tag_style);
break;
case STATE_ANNOTATION:
+ cho_style_free(songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->style);
+ songs[so]->sections[se]->lines[li]->text_above[c]->u.annot->style = cho_style_duplicate(tag_style);
break;
default:
fprintf(stderr, "ERR: Invalid prev_state '%s'.\n", cho_state_to_string(prev_state));
@@ -2764,6 +2770,21 @@ static const char *cho_debug_the_song_fragment_type(enum SongFragmentType ftype)
return "";
}
+static const char *cho_debug_style_property_type_to_string(enum StylePropertyType type)
+{
+ switch (type) {
+ case SPT_EMPTY:
+ return "SPT_EMPTY";
+ case SPT_FONT:
+ return "SPT_FONT";
+ case SPT_SIZE:
+ return "SPT_SIZE";
+ case SPT_COLOR:
+ return "SPT_COLOR";
+ }
+ return "";
+}
+
static void cho_debug_the_default_style_properties(void)
{
unsigned int i;
@@ -2771,7 +2792,7 @@ static void cho_debug_the_default_style_properties(void)
printf(
"%s %s ",
cho_debug_the_song_fragment_type(default_style_properties[i].ftype),
- cho_style_property_type_to_string(default_style_properties[i].type)
+ cho_debug_style_property_type_to_string(default_style_properties[i].type)
);
switch (default_style_properties[i].type) {
case SPT_FONT:
diff --git a/out_pdf.c b/out_pdf.c
@@ -540,6 +540,10 @@ static enum Bool out_pdf_text_above_is_enough_space(struct ChoLine *line, struct
if (prev == EMPTY) {
return B_ERROR;
}
+ if (prev == cur) {
+ return B_TRUE;
+ }
+ /* printf("cur: %.1f, prev: %.1f\n", prev, cur); */
double width_between = cur - prev;
char *name;
pdfio_obj_t *font_obj;
@@ -683,6 +687,7 @@ static struct Text **text_create(struct ChoSong **songs, struct Config *config)
for (li = 0; lines[li]; li++, tl++) {
text_above = songs[so]->sections[se]->lines[li]->text_above;
int text_above_len = cho_text_above_count(text_above);
+ // TODO: The code inside the if statement seems to me too complicated, so simplify if possible
if (text_above_len > 0) {
text[t]->lines = realloc(text[t]->lines, (tl+1) * sizeof(struct TextLine *));
text[t]->lines[tl] = malloc(sizeof(struct TextLine));
@@ -702,6 +707,20 @@ static struct Text **text_create(struct ChoSong **songs, struct Config *config)
} else {
text[t]->lines[tl]->items[tli]->x = PADDING + width_until + added_space;
}
+ if (ch > 0 && text_above[ch-1]->position == text_above[ch]->position) {
+ int b;
+ struct TextLineItem tmp;
+ for (b=ch-1; b >= 0 && text_above[b]->position == text_above[ch]->position; b--) {
+ tmp.style = text_above[b]->u.annot->style;
+ tmp.text = text_above[b]->u.annot->text;
+ width = text_width(&tmp);
+ if (width == EMPTY) {
+ fprintf(stderr, "text_width failed.\n");
+ return NULL;
+ }
+ text[t]->lines[tl]->items[tli]->x += width;
+ }
+ }
if (add_space_to_next_chord) {
added_space += space.amount;
text[t]->lines[tl]->items[tli]->x += space.amount;