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:
| M | chord_diagram.c | | | 171 | +++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------- |
| M | chord_diagram.h | | | 2 | +- |
| M | chordpro.c | | | 88 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------- |
| M | chordpro.h | | | 1 | + |
| M | out_pdf.c | | | 154 | +++++++++++++++++++++++++++++++++++++++++++++++-------------------------------- |
| M | out_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;