lorid

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

commit 017d02ea42569d580c16d427f157a5e2909a7864
parent a44300eb8e15cea892c5542df86fdf7a4109a7f8
Author: nibo <nibo@relim.de>
Date:   Thu,  5 Dec 2024 16:02:08 +0100

Improve chord diagram parsing and rendering

Diffstat:
Mchord_diagram.c | 171+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Mchord_diagram.h | 2+-
Mchordpro.c | 88++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Mchordpro.h | 1+
Mout_pdf.c | 154+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Mout_pdf.h | 2++
6 files changed, 287 insertions(+), 131 deletions(-)

diff --git a/chord_diagram.c b/chord_diagram.c @@ -322,34 +322,33 @@ string_diagram_free(struct StringDiagram *d) } static struct StringDiagram * +string_diagram_copy(struct StringDiagram *diagram) +{ + struct StringDiagram *copy = emalloc(sizeof(struct StringDiagram)); + copy->name = strdup(diagram->name); + copy->base_fret = diagram->base_fret; + int i; + for (i = 0; i<12; i++) { + copy->frets[i] = diagram->frets[i]; + } + for (i = 0; i<12; i++) { + copy->fingers[i] = diagram->fingers[i]; + } + return copy; +} + +static struct StringDiagram * string_diagram_copy_all_but_name(struct StringDiagram *diagram) { struct StringDiagram *copy = emalloc(sizeof(struct StringDiagram)); copy->base_fret = diagram->base_fret; - copy->frets[0] = diagram->frets[0]; - copy->frets[1] = diagram->frets[1]; - copy->frets[2] = diagram->frets[2]; - copy->frets[3] = diagram->frets[3]; - copy->frets[4] = diagram->frets[4]; - copy->frets[5] = diagram->frets[5]; - copy->frets[6] = diagram->frets[6]; - copy->frets[7] = diagram->frets[7]; - copy->frets[8] = diagram->frets[8]; - copy->frets[9] = diagram->frets[9]; - copy->frets[10] = diagram->frets[10]; - copy->frets[11] = diagram->frets[11]; - copy->fingers[0] = diagram->fingers[0]; - copy->fingers[1] = diagram->fingers[1]; - copy->fingers[2] = diagram->fingers[2]; - copy->fingers[3] = diagram->fingers[3]; - copy->fingers[4] = diagram->fingers[4]; - copy->fingers[5] = diagram->fingers[5]; - copy->fingers[6] = diagram->fingers[6]; - copy->fingers[7] = diagram->fingers[7]; - copy->fingers[8] = diagram->fingers[8]; - copy->fingers[9] = diagram->fingers[9]; - copy->fingers[10] = diagram->fingers[10]; - copy->fingers[11] = diagram->fingers[11]; + int i; + for (i = 0; i<12; i++) { + copy->frets[i] = diagram->frets[i]; + } + for (i = 0; i<12; i++) { + copy->fingers[i] = diagram->fingers[i]; + } return copy; } @@ -377,6 +376,16 @@ string_diagram_is_valid(struct StringDiagram *d) return true; } +static size_t +string_diagram_fret_count(struct StringDiagram *d) +{ + int i = 0; + while (d->frets[i] != -2 && i < 12) { + i++; + } + return i; +} + static char finger_to_char(int8_t finger) { @@ -519,6 +528,18 @@ keyboard_diagram_free(struct KeyboardDiagram *d) free(d); } +static struct KeyboardDiagram * +keyboard_diagram_copy(struct KeyboardDiagram *diagram) +{ + struct KeyboardDiagram *copy = emalloc(sizeof(struct KeyboardDiagram)); + copy->name = strdup(diagram->name); + int i; + for (i = 0; i<24; i++) { + copy->keys[i] = diagram->keys[i]; + } + return copy; +} + struct ChordDiagram * chord_diagram_new(bool is_string_instrument) { @@ -544,6 +565,20 @@ chord_diagram_free(struct ChordDiagram *d) free(d); } +static struct ChordDiagram * +chord_diagram_copy(struct ChordDiagram *diagram) +{ + struct ChordDiagram *copy = emalloc(sizeof(struct ChordDiagram)); + if (diagram->is_string_instrument) { + copy->is_string_instrument = true; + copy->u.sd = string_diagram_copy(diagram->u.sd); + } else { + copy->is_string_instrument = false; + copy->u.kd = keyboard_diagram_copy(diagram->u.kd); + } + return copy; +} + void chord_diagrams_free(struct ChordDiagram **diagrams) { @@ -558,16 +593,70 @@ chord_diagrams_free(struct ChordDiagram **diagrams) free(diagrams); } +#ifdef DEBUG +void +debug_chord_diagram_print(struct ChordDiagram *diagram) +{ + int i; + printf("---- CHORD DIAGRAM BEGIN ----\n"); + if (diagram->is_string_instrument) { + printf("name: %s\n", diagram->u.sd->name); + printf("base-fret: %d\n", diagram->u.sd->base_fret); + printf("frets: "); + for (i = 0; i<12; i++) { + printf("%d ", diagram->u.sd->frets[i]); + } + printf("\n"); + printf("fingers: "); + for (i = 0; i<12; i++) { + printf("%d ", diagram->u.sd->fingers[i]); + } + printf("\n"); + } else { + printf("name: %s\n", diagram->u.kd->name); + printf("keys: "); + for (i = 0; i<24; i++) { + printf("%d ", diagram->u.kd->keys[i]); + } + printf("\n"); + } + printf("---- CHORD DIAGRAM END ------\n"); +} +#endif /* DEBUG */ + struct ChordDiagram ** -chord_diagrams_create(struct Config *config, struct ChoChord ***chords) +chord_diagrams_create( + struct Config *config, + struct ChoChord ***chords, + struct ChordDiagram **custom_diagrams +) { struct ChordDiagram **diagrams = NULL; + struct ChordDiagram **cd; struct ChoChord **c = *chords; int d = 0; size_t i; switch (config->output->diagram->instrument) { case INS_GUITAR: while (*c) { + cd = custom_diagrams; + while (*cd) { + if ( + (*cd)->is_string_instrument && + string_diagram_fret_count((*cd)->u.sd) == 6 && + !strcmp((*c)->name, (*cd)->u.sd->name) + ) { + diagrams = erealloc(diagrams, (d+1) * sizeof(struct ChordDiagram *)); + // diagrams[d] = chord_diagram_copy(*cd); + diagrams[d] = emalloc(sizeof(struct ChordDiagram)); + diagrams[d]->is_string_instrument = true; + diagrams[d]->u.sd = string_diagram_copy_all_but_name((*cd)->u.sd); + diagrams[d]->u.sd->name = cho_chord_name_generate(*c); + d++; + goto NEXT_CHORD; + } + cd++; + } for (i = 0; i<LENGTH(guitar_diagrams); i++) { if (!strcmp((*c)->name, guitar_diagrams[i].name)) { diagrams = erealloc(diagrams, (d+1) * sizeof(struct ChordDiagram *)); @@ -578,6 +667,7 @@ chord_diagrams_create(struct Config *config, struct ChoChord ***chords) d++; } } + NEXT_CHORD: c++; } break; @@ -614,34 +704,3 @@ chord_diagram_draw( } return true; } - -#ifdef DEBUG -void -debug_chord_diagram_print(struct ChordDiagram *diagram) -{ - int i; - printf("---- CHORD DIAGRAM BEGIN ----\n"); - if (diagram->is_string_instrument) { - printf("name: %s\n", diagram->u.sd->name); - printf("base-fret: %d\n", diagram->u.sd->base_fret); - printf("frets: "); - for (i = 0; i<12; i++) { - printf("%d ", diagram->u.sd->frets[i]); - } - printf("\n"); - printf("fingers: "); - for (i = 0; i<12; i++) { - printf("%d ", diagram->u.sd->fingers[i]); - } - printf("\n"); - } else { - printf("name: %s\n", diagram->u.kd->name); - printf("keys: "); - for (i = 0; i<24; i++) { - printf("%d ", diagram->u.kd->keys[i]); - } - printf("\n"); - } - printf("---- CHORD DIAGRAM END ------\n"); -} -#endif /* DEBUG */ diff --git a/chord_diagram.h b/chord_diagram.h @@ -35,5 +35,5 @@ struct ChordDiagram *chord_diagram_new(bool is_string_instrument); void chord_diagram_free(struct ChordDiagram *d); void chord_diagrams_free(struct ChordDiagram **diagrams); bool chord_diagram_draw(pdfio_stream_t *stream, struct ChordDiagram *diagram, double x, double y, double width); -struct ChordDiagram **chord_diagrams_create(struct Config *config, struct ChoChord ***chords); +struct ChordDiagram **chord_diagrams_create(struct Config *config, struct ChoChord ***chords, struct ChordDiagram **custom_diagram); void debug_chord_diagram_print(struct ChordDiagram *diagram); diff --git a/chordpro.c b/chordpro.c @@ -2630,16 +2630,30 @@ cho_image_tag_parse(struct Attr **attrs) return image; } -static -int8_t +static int8_t char_to_positive_int(char c) { - if (c > '0' && c <= '9') { + if (c >= '0' && c <= '9') { return c - 48; } return -1; } +static int8_t +finger_to_int(char c) +{ + if (c == '-' || c == 'x' || c == 'X' || c == 'N') { + return -1; + } + if (c >= '0' && c <= '9') { + return c - 48; + } + if (c >= 'A' && c <= 'Z') { + return c - 64; + } + return -2; +} + static struct ChordDiagram * cho_chord_diagram_parse(const char *str) { @@ -2647,6 +2661,7 @@ cho_chord_diagram_parse(const char *str) enum ChordDiagramState state = CDS_NAME; enum ChordDiagramContent current_content = CDC_EMPTY; enum ChordDiagramContent future_content = CDC_EMPTY; + bool is_maybe_minus_one = false; char c; char name[20]; char option[10]; @@ -2719,6 +2734,8 @@ cho_chord_diagram_parse(const char *str) diagram = chord_diagram_new(false); diagram->u.kd->name = strdup(name); break; + default: + cho_log(LOG_ERR, "'future_content' cannot be empty at this point.\n"); } } break; @@ -2740,6 +2757,11 @@ cho_chord_diagram_parse(const char *str) } number = char_to_positive_int(c); if (number == -1) { + LOG_DEBUG("char_to_positive_int failed."); + cho_log(LOG_ERR, "Invalid base-fret value '%c' in chord diagram.", c); + return NULL; + } + if (number == 0) { cho_log(LOG_ERR, "Invalid base-fret value '%c' in chord diagram.", c); return NULL; } @@ -2747,18 +2769,38 @@ cho_chord_diagram_parse(const char *str) state = CDS_OPTION_NAME; break; case CDS_FRETS: + number = -2; if (is_whitespace(c)) { break; } + if (c == '-') { + is_maybe_minus_one = true; + break; + } + if (is_maybe_minus_one) { + if (c == '1') { + number = -1; + is_maybe_minus_one = false; + } else { + cho_log(LOG_ERR, "Invalid frets value '-%c' in chord diagram.", c); + return NULL; + } + } + if (c == 'N' || c == 'x') { + number = -1; + } else if (isalpha(c)) { f = 0; state = CDS_OPTION_NAME; goto CDS_OPTION_NAME_LABEL; } - number = char_to_positive_int(c); - if (number == -1) { - cho_log(LOG_ERR, "Invalid frets value '%c' in chord diagram.", c); - return NULL; + if (number == -2) { + number = char_to_positive_int(c); + if (number == -1) { + LOG_DEBUG("char_to_positive_int failed."); + cho_log(LOG_ERR, "Invalid frets value '%c' in chord diagram.", c); + return NULL; + } } if (f > 11) { cho_log(LOG_ERR, "Too many fret values in chord diagram."); @@ -2772,13 +2814,13 @@ cho_chord_diagram_parse(const char *str) if (is_whitespace(c)) { break; } - if (isalpha(c)) { + if (c == 'b' || c == 'f') { f = 0; state = CDS_OPTION_NAME; goto CDS_OPTION_NAME_LABEL; } - number = char_to_positive_int(c); - if (number == -1) { + number = finger_to_int(c); + if (number == -2) { cho_log(LOG_ERR, "Invalid fingers value '%c' in chord diagram.", c); return NULL; } @@ -2799,6 +2841,7 @@ cho_chord_diagram_parse(const char *str) k = 0; l = str_to_number(key); if (l == -1) { + LOG_DEBUG("str_to_number failed."); cho_log(LOG_ERR, "Invalid number in keys in chord diagram."); return NULL; } @@ -2825,6 +2868,7 @@ cho_chord_diagram_parse(const char *str) if (strlen(key) > 0) { l = str_to_number(key); if (l == -1) { + LOG_DEBUG("str_to_number failed."); cho_log(LOG_ERR, "Invalid number in keys in chord diagram."); return NULL; } @@ -3064,6 +3108,7 @@ cho_song_new(void) struct ChoSong *song = emalloc(sizeof(struct ChoSong)); song->metadata = NULL; song->sections = NULL; + song->diagrams = NULL; return song; } @@ -3084,6 +3129,7 @@ cho_song_free(struct ChoSong *song) } struct ChoMetadata **start_meta = song->metadata; struct ChoSection **start_section = song->sections; + struct ChordDiagram **start_diagram = song->diagrams; while (*song->metadata) { cho_metadata_free(*song->metadata); song->metadata++; @@ -3092,6 +3138,11 @@ cho_song_free(struct ChoSong *song) cho_section_free(*song->sections); song->sections++; } + while (*song->diagrams) { + chord_diagram_free(*song->diagrams); + song->diagrams++; + } + free(start_diagram); free(start_meta); free(start_section); free(song); @@ -3603,6 +3654,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) int chord_pos; int transpose; int th = 0; + int dia = 0; size_t read; g_transpose_history = erealloc(g_transpose_history, (th+1) * sizeof(int *)); g_transpose_history[th] = 0; @@ -3883,6 +3935,8 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) se++; songs[so]->sections = erealloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *)); songs[so]->sections[se] = NULL; + songs[so]->diagrams = erealloc(songs[so]->diagrams, (dia+1) * sizeof(struct ChordDiagram *)); + songs[so]->diagrams[dia] = NULL; if (!cho_style_reset_default()) { LOG_DEBUG("cho_style_reset_default failed."); return NULL; @@ -3894,6 +3948,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) li = 0; ly = 0; m = 0; + dia = 0; songs[so]->sections = emalloc((se+1) * sizeof(struct ChoSection *)); songs[so]->sections[se] = cho_section_new(); songs[so]->sections[se]->lines = erealloc(songs[so]->sections[se]->lines, (li+1) * sizeof(struct ChoLine *)); @@ -4274,8 +4329,15 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) break; case DEFINE: diagram = cho_chord_diagram_parse(directive_value); - debug_chord_diagram_print(diagram); - chord_diagram_free(diagram); + if (!diagram) { + LOG_DEBUG("cho_chord_diagram_parse failed."); + return NULL; + } + songs[so]->diagrams = erealloc(songs[so]->diagrams, (dia+1) * sizeof(struct ChordDiagram *)); + songs[so]->diagrams[dia] = diagram; + dia++; + // debug_chord_diagram_print(diagram); + // chord_diagram_free(diagram); break; } break; @@ -4737,6 +4799,8 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) se++; songs[so]->sections = erealloc(songs[so]->sections, (se+1) * sizeof(struct ChoSection *)); songs[so]->sections[se] = NULL; + songs[so]->diagrams = erealloc(songs[so]->diagrams, (dia+1) * sizeof(struct ChordDiagram *)); + songs[so]->diagrams[dia] = NULL; so++; songs = erealloc(songs, (so+1) * sizeof(struct ChoSong *)); songs[so] = NULL; diff --git a/chordpro.h b/chordpro.h @@ -317,6 +317,7 @@ struct ChoSection { struct ChoSong { struct ChoMetadata **metadata; struct ChoSection **sections; + struct ChordDiagram **diagrams; }; struct ChoSong **cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config); diff --git a/out_pdf.c b/out_pdf.c @@ -814,31 +814,27 @@ out_pdf_load_chord_diagram_fonts(void) } static bool -out_pdf_get_chords(struct ChoSong **songs, struct ChoChord ***chords) +out_pdf_get_chords(struct ChoSong *song, struct ChoChord ***chords) { - struct ChoSong **s = songs; struct ChoSection **se; struct ChoLine **li; struct ChoLineItemAbove **above; - while (*s) { - se = (*s)->sections; - while (*se) { - li = (*se)->lines; - while (*li) { - above = (*li)->text_above; - while (*above) { - if ((*above)->is_chord) { - if (!cho_chords_has(*chords, (*above)->u.chord)) { - cho_chords_add(chords, (*above)->u.chord); - } + se = song->sections; + while (*se) { + li = (*se)->lines; + while (*li) { + above = (*li)->text_above; + while (*above) { + if ((*above)->is_chord) { + if (!cho_chords_has(*chords, (*above)->u.chord)) { + cho_chords_add(chords, (*above)->u.chord); } - above++; } - li++; + above++; } - se++; + li++; } - s++; + se++; } return true; } @@ -962,6 +958,7 @@ pdf_page_new(void) struct PDFPage *page = emalloc(sizeof(struct PDFPage)); page->texts = NULL; page->images = NULL; + page->diagrams = NULL; page->annots = pdfioArrayCreate(g_pdf_file); return page; } @@ -974,6 +971,7 @@ pdf_page_free(struct PDFPage *page) } struct PDFText **t; struct PDFImage **i; + struct ChordDiagram **d; t = page->texts; if (t) { while (*t) { @@ -990,6 +988,14 @@ pdf_page_free(struct PDFPage *page) } free(page->images); } + d = page->diagrams; + if (d) { + while (*d) { + chord_diagram_free(*d); + d++; + } + free(page->diagrams); + } free(page); } @@ -1444,6 +1450,7 @@ pdf_content_create( struct PDFText ***texts; struct PDFImage ***imgs; struct PDFContext ctx; + struct ChordDiagram ***diagrams, **dgrams, **dgrams_begin; double width, height, margin_bottom; if (config->output->diagram->show) { margin_bottom = 150.0; @@ -1454,6 +1461,7 @@ pdf_content_create( ctx.y = MEDIABOX_HEIGHT - MARGIN_TOP; ctx.text = 0; ctx.image = 0; + ctx.diagram = 0; ctx.page = 0; ctx.spaces = NULL; ctx.content = emalloc(sizeof(struct PDFContent)); @@ -1462,39 +1470,61 @@ pdf_content_create( s = songs; texts = &ctx.content->pages[ctx.page]->texts; imgs = &ctx.content->pages[ctx.page]->images; - m = (*s)->metadata; - while (*m) { - if (!strcmp((*m)->name, "title")) { - if (!pdf_texts_add_text(&ctx, (*m)->value, (*m)->style, A_CENTER)) { - LOG_DEBUG("pdf_texts_add_text failed."); + diagrams = &ctx.content->pages[ctx.page]->diagrams; + while (*s) { + if (config->output->diagram->show) { + struct ChoChord **chords = NULL; + if (!out_pdf_get_chords(*s, &chords)) { + LOG_DEBUG("out_pdf_get_chords failed."); return false; } + if (chords) { + qsort(chords, cho_chords_len(chords), sizeof(struct ChoChord *), cho_chord_compare); + dgrams = chord_diagrams_create(config, &chords, (*s)->diagrams); + dgrams_begin = dgrams; + while (*dgrams) { + // debug_chord_diagram_print(*dgrams); + *diagrams = erealloc(*diagrams, (ctx.diagram+1) * sizeof(struct ChordDiagram *)); + (*diagrams)[ctx.diagram] = *dgrams; + ctx.diagram++; + dgrams++; + } + free(dgrams_begin); + } + cho_chords_free(chords); } - m++; - } - m = (*s)->metadata; - while (*m) { - if (!strcmp((*m)->name, "subtitle")) { - /* - INFO: (*m)->style will be ignored and the config style will be - used because the subtitle style can only be manipulated from the - config file - */ - struct OutputStyle *output_style; - output_style = config_output_style_get(config->output->styles, "subtitle"); - if (!output_style) { - LOG_DEBUG("config_output_style_get failed."); - return NULL; + m = (*s)->metadata; + while (*m) { + if (!strcmp((*m)->name, "title")) { + if (!pdf_texts_add_text(&ctx, (*m)->value, (*m)->style, A_CENTER)) { + LOG_DEBUG("pdf_texts_add_text failed."); + return false; + } } - if (!pdf_texts_add_text(&ctx, (*m)->value, output_style->style, A_CENTER)) { - LOG_DEBUG("pdf_texts_add_text failed."); - return false; + m++; + } + m = (*s)->metadata; + while (*m) { + if (!strcmp((*m)->name, "subtitle")) { + /* + INFO: (*m)->style will be ignored and the config style will be + used because the subtitle style can only be manipulated from the + config file + */ + struct OutputStyle *output_style; + output_style = config_output_style_get(config->output->styles, "subtitle"); + if (!output_style) { + LOG_DEBUG("config_output_style_get failed."); + return NULL; + } + if (!pdf_texts_add_text(&ctx, (*m)->value, output_style->style, A_CENTER)) { + LOG_DEBUG("pdf_texts_add_text failed."); + return false; + } } + m++; } - m++; - } - ctx.y -= 30.0; - while (*s) { + ctx.y -= 30.0; se = (*s)->sections; while (*se) { if ((*se)->label) { @@ -1614,13 +1644,17 @@ pdf_content_create( (*texts)[ctx.text] = NULL; *imgs = erealloc(*imgs, (ctx.image+1) * sizeof(struct PDFImage *)); (*imgs)[ctx.image] = NULL; + *diagrams = erealloc(*diagrams, (ctx.diagram+1) * sizeof(struct ChordDiagram *)); + (*diagrams)[ctx.diagram] = NULL; ctx.text = 0; ctx.image = 0; + ctx.diagram = 0; ctx.page++; ctx.content->pages = erealloc(ctx.content->pages, (ctx.page+1) * sizeof(struct PDFPage *)); ctx.content->pages[ctx.page] = pdf_page_new(); texts = &ctx.content->pages[ctx.page]->texts; imgs = &ctx.content->pages[ctx.page]->images; + diagrams = &ctx.content->pages[ctx.page]->diagrams; for (int i=0; i<tm; i++) { *texts = erealloc(*texts, (ctx.text+1) * sizeof(struct PDFText *)); (*texts)[ctx.text] = tmp[i]; @@ -1696,13 +1730,17 @@ pdf_content_create( (*texts)[ctx.text] = NULL; *imgs = erealloc(*imgs, (ctx.image+1) * sizeof(struct PDFImage *)); (*imgs)[ctx.image] = NULL; + *diagrams = erealloc(*diagrams, (ctx.diagram+1) * sizeof(struct ChordDiagram *)); + (*diagrams)[ctx.diagram] = NULL; ctx.text = 0; ctx.image = 0; + ctx.diagram = 0; ctx.page++; ctx.content->pages = erealloc(ctx.content->pages, (ctx.page+1) * sizeof(struct PDFPage *)); ctx.content->pages[ctx.page] = pdf_page_new(); texts = &ctx.content->pages[ctx.page]->texts; imgs = &ctx.content->pages[ctx.page]->images; + diagrams = &ctx.content->pages[ctx.page]->diagrams; ctx.y = MEDIABOX_HEIGHT - MARGIN_TOP; } spaces_free(ctx.spaces); @@ -1716,13 +1754,17 @@ pdf_content_create( (*texts)[ctx.text] = NULL; *imgs = erealloc(*imgs, (ctx.image+1) * sizeof(struct PDFImage *)); (*imgs)[ctx.image] = NULL; + *diagrams = erealloc(*diagrams, (ctx.diagram+1) * sizeof(struct ChordDiagram *)); + (*diagrams)[ctx.diagram] = NULL; ctx.text = 0; ctx.image = 0; + ctx.diagram = 0; ctx.page++; ctx.content->pages = erealloc(ctx.content->pages, (ctx.page+1) * sizeof(struct PDFPage *)); ctx.content->pages[ctx.page] = pdf_page_new(); texts = &ctx.content->pages[ctx.page]->texts; imgs = &ctx.content->pages[ctx.page]->images; + diagrams = &ctx.content->pages[ctx.page]->diagrams; ctx.y = MEDIABOX_HEIGHT - MARGIN_TOP; } li++; @@ -1736,6 +1778,8 @@ pdf_content_create( (*texts)[ctx.text] = NULL; *imgs = erealloc(*imgs, (ctx.image+1) * sizeof(struct PDFImage *)); (*imgs)[ctx.image] = NULL; + *diagrams = erealloc(*diagrams, (ctx.diagram+1) * sizeof(struct ChordDiagram *)); + (*diagrams)[ctx.diagram] = NULL; ctx.page++; ctx.content->pages = erealloc(ctx.content->pages, (ctx.page+1) * sizeof(struct PDFPage *)); ctx.content->pages[ctx.page] = NULL; @@ -1760,7 +1804,7 @@ pdf_content_free(struct PDFContent *content) } static bool -pdf_content_render(struct PDFContent *content, pdfio_file_t *file, struct ChordDiagram **diagrams) +pdf_content_render(struct PDFContent *content, pdfio_file_t *file) { int p; struct PDFPage **pages; @@ -1799,12 +1843,12 @@ pdf_content_render(struct PDFContent *content, pdfio_file_t *file, struct ChordD } imgs++; } - if (p == 0 && diagrams) { + if (pages[p]->diagrams) { double x = MARGIN_HORIZONTAL; double y = 40.0; double size = 50.0; double padding = 20.0; - struct ChordDiagram **d = diagrams; + struct ChordDiagram **d = pages[p]->diagrams; /* TODO: Handle line break when too long */ while (*d) { if (!chord_diagram_draw(stream, *d, x, y, size)) { @@ -1831,7 +1875,6 @@ out_pdf_create( struct Config *config ) { - struct ChordDiagram **diagrams = NULL; struct Font **needed_fonts; struct Obj **img_objs = NULL; struct Obj *fnt; @@ -1840,7 +1883,6 @@ out_pdf_create( pdfio_rect_t crop_box = { 0.0, 0.0, MEDIABOX_WIDTH, MEDIABOX_HEIGHT }; int f = 0; char *dirpath, *fontpath, *pdf_filename; - struct ChoChord **chords = NULL; memset(&g_current_font_name, 0, sizeof(g_current_font_name)); memset(&g_cho_dirpath, 0, PATH_MAX); @@ -1892,26 +1934,14 @@ out_pdf_create( LOG_DEBUG("out_pdf_load_images failed."); return NULL; } - if (config->output->diagram->show) { - if (!out_pdf_get_chords(songs, &chords)) { - LOG_DEBUG("out_pdf_get_chords failed."); - return NULL; - } - if (chords) { - qsort(chords, cho_chords_len(chords), sizeof(struct ChoChord *), cho_chord_compare); - diagrams = chord_diagrams_create(config, &chords); - } - } if (!pdf_content_create(&pdf_content, songs, config, img_objs)) { LOG_DEBUG("pdf_content_create failed."); return NULL; } - if (!pdf_content_render(pdf_content, g_pdf_file, diagrams)) { + if (!pdf_content_render(pdf_content, g_pdf_file)) { LOG_DEBUG("pdf_content_render failed."); return NULL; } - cho_chords_free(chords); - chord_diagrams_free(diagrams); objs_free(img_objs); pdf_content_free(pdf_content); if (!pdfioFileClose(g_pdf_file)) { diff --git a/out_pdf.h b/out_pdf.h @@ -56,6 +56,7 @@ struct PDFPage { struct PDFText **texts; struct PDFImage **images; pdfio_array_t *annots; + struct ChordDiagram **diagrams; }; struct PDFContent { @@ -68,6 +69,7 @@ struct PDFContext { double y; int text; int image; + int diagram; int page; struct SpaceNeeded **spaces; double biggest_font_size;