lorid

convert chordpro to pdf
git clone git://git.relim.de/lorid.git
Log | Files | Refs | README | LICENSE

commit 2997742861e389678c571664f4ba39f9363988c0
parent 8284135c6a93fa5726998f7ee5c2da78f38a320a
Author: nibo <nibo@relim.de>
Date:   Sat, 10 Aug 2024 09:28:32 +0200

Allow markup tags inside annotations

Diffstat:
Mchordpro.c | 79++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Mout_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;