lorid

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

commit 6073e681b35c177f1ffac50ec67b25411c49c268
parent 93df4ecc41846e02c500324862682557b87edca4
Author: nibo <nibo@relim.de>
Date:   Fri,  6 Sep 2024 16:12:48 +0200

'make lib' support

Diffstat:
MMakefile | 3+++
Mlorid.c | 18+++++++++++++++++-
Alorid.h | 297+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mout_pdf.c | 31+++++++++++++++++++------------
Mout_pdf.h | 2+-
Aout_pdf.o | 0
6 files changed, 337 insertions(+), 14 deletions(-)

diff --git a/Makefile b/Makefile @@ -13,4 +13,7 @@ fontconfig: $(CC) -g chordpro.c fontconfig.c -o fontconfig -lfontconfig parser: $(CC) ${CFLAGS} -g util.c config.c chordpro.c lorid.c -o parser -ltoml +lib: + $(CC) -fpic -c util.c fontconfig.c config.c chordpro.c out_pdf.c + $(CC) -shared ${LDFLAGS} -o liblorid.so *.o .PHONY: all debug fontconfig parser diff --git a/lorid.c b/lorid.c @@ -67,10 +67,26 @@ int main(int argc, char *argv[]) fprintf(stderr, "cho_parse failed.\n"); return 1; } - if (!out_pdf_new(argc == optind+1 ? argv[argc-1] : NULL, output ? output : NULL, songs, config)) { + int m; + for (m = 0; songs[0]->metadata[m]; m++) { + printf("'%s' => ", songs[0]->metadata[m]->name); + int i; + for (i = 0; songs[0]->metadata[m]->value[i] != 0; i++) { + printf("[%02X|%c] ", songs[0]->metadata[m]->value[i], songs[0]->metadata[m]->value[i]); + } + printf("\n"); + } + char *pdf_filename = out_pdf_new(argc == optind+1 ? argv[argc-1] : NULL, output ? output : NULL, songs, config); + if (!pdf_filename) { fprintf(stderr, "out_pdf_new failed.\n"); return 1; } + fprintf(stderr, "INFO: Writing pdf to file: '%s'\n", pdf_filename); + free(pdf_filename); + /* if (!out_pdf_new(argc == optind+1 ? argv[argc-1] : NULL, output ? output : NULL, songs, config)) { + fprintf(stderr, "out_pdf_new failed.\n"); + return 1; + } */ free(output); cho_songs_free(songs); config_free(config); diff --git a/lorid.h b/lorid.h @@ -0,0 +1,297 @@ +#include <stdint.h> +#include <stdbool.h> +#include <stdlib.h> + +enum FontFamily { + FF_EMPTY = -1, + FF_NORMAL, + FF_SANS, + FF_SERIF, + FF_MONOSPACE +}; + +enum FontStyle { + FS_EMPTY = -1, + FS_ROMAN, + FS_OBLIQUE, + FS_ITALIC +}; + +enum FontWeight { + FW_EMPTY = -1, + FW_REGULAR, + FW_BOLD +}; + +struct Font { + char *name; + enum FontFamily family; + enum FontStyle style; + enum FontWeight weight; + double size; +}; + +enum LineStyle { + LS_EMPTY = -1, + LS_SINGLE, + LS_DOUBLE, + LS_NONE +}; + +struct RGBColor { + uint8_t red; + uint8_t green; + uint8_t blue; +}; + +struct Style { + struct Font *font; + struct RGBColor *foreground_color; + struct RGBColor *background_color; + enum LineStyle underline_style; + struct RGBColor *underline_color; + enum LineStyle overline_style; + struct RGBColor *overline_color; + bool strikethrough; + struct RGBColor *strikethrough_color; + bool boxed; + struct RGBColor *boxed_color; + double rise; + char *href; +}; + +struct Attr { + char *name; + char *value; +}; + +struct Tag { + char *name; + struct Style *style; + struct Attr **attrs; + bool is_closed; +}; + +enum AttrValueSyntax { + AVS_NO, + AVS_QUOTATION_MARK, + AVS_APOSTROPHE, + AVS_UNQUOTED +}; + +enum State { + STATE_LYRICS, + STATE_DIRECTIVE_NAME, + STATE_DIRECTIVE_VALUE, + STATE_CHORD, + STATE_ANNOTATION, + STATE_MARKUP_TAG_BEGIN, + STATE_MARKUP_TAG_END, + STATE_MARKUP_TAG, + STATE_MARKUP_ATTR_NAME, + STATE_MARKUP_ATTR_VALUE, + STATE_COMMENT +}; + +/* Similar to SectionType but different enough for a separate type */ +enum SongFragmentType { + SF_EMPTY = -1, + SF_CHORD, + SF_ANNOT, + SF_CHORUS, + SF_FOOTER, + SF_GRID, + SF_TAB, + SF_TOC, + SF_TEXT, + SF_TITLE, + SF_LABEL +}; + +enum StylePropertyType { + SPT_EMPTY = -1, + SPT_FONT, + SPT_SIZE, + SPT_COLOR +}; + +union StylePropertyValue { + char *font_name; + double font_size; + struct RGBColor *foreground_color; +}; + +struct StyleProperty { + enum SongFragmentType ftype; + enum StylePropertyType type; + union StylePropertyValue u; +}; + +enum DirectiveType { + DT_EMPTY = -1, + DT_ENVIRONMENT, + DT_METADATA, + DT_FORMATTING, + DT_PREAMBLE, + DT_FONT, + DT_OUTPUT, + DT_CUSTOM +}; + +enum SectionType { + ST_EMPTY = -1, + ST_NEWSONG, + ST_CHORUS, + ST_VERSE, + ST_BRIDGE, + ST_TAB, + ST_GRID, + ST_CUSTOM +}; + +enum Position { + POS_EMPTY = -1, + POS_START, + POS_END +}; + +enum ChordQualifier { + CQ_EMPTY = -1, + CQ_MIN, + CQ_MAJ, + CQ_AUG, + CQ_DIM +}; + +enum BreakType { + BT_EMPTY = -1, + BT_LINE, + BT_PAGE, + BT_COLUMN +}; + +struct ChoDirective { + enum DirectiveType dtype; + enum SectionType stype; + enum Position position; + enum StylePropertyType sprop; + enum SongFragmentType ftype; + enum BreakType btype; + struct Style *style; +}; + +struct ChoMetadata { + char *name; + char *value; + struct Style *style; +}; + +struct ChoChord { + struct Style *style; + bool is_canonical; + char *name; + char *root; + enum ChordQualifier qual; + char *ext; + char *bass; +}; + +struct ChoAnnotation { + struct Style *style; + char *text; +}; + +struct ChoLineItem { + struct Style *style; + char *text; +}; + +struct ChoLineItemAbove { + int position; + bool is_chord; + union { + struct ChoChord *chord; + struct ChoAnnotation *annot; + } u; +}; + +struct ChoLine { + struct ChoLineItemAbove **text_above; + struct ChoLineItem **lyrics; + enum BreakType btype; +}; + +struct ChoLabel { + char *name; + struct Style *style; +}; + +struct ChoSection { + enum SectionType type; + struct ChoLabel *label; + struct ChoLine **lines; +}; + +struct ChoSong { + struct ChoMetadata **metadata; + struct ChoSection **sections; +}; + +struct PrintableItem { + char *name; + struct Style *style; +}; + +enum NamingSystem { + NS_COMMON, + NS_GERMAN, + NS_SCANDINAVIAN, + NS_LATIN, + NS_ROMAN, + NS_NASHVILLE, + NS_CUSTOM +}; + +enum ParseMode { + PM_STRICT, + PM_RELAXED +}; + +struct Note { + char *note; + char *sharp; + char *flat; +}; + +struct ConfigChords { + enum NamingSystem system; + enum ParseMode mode; + // struct Note **notes; +}; + +/* struct Config { + struct PrintableItem **printable_items; + struct ConfigChords *chords; +}; */ + +struct ConfigParser { + struct ConfigChords *chords; + struct Note **notes; +}; + +struct ConfigOutput { + enum NamingSystem system; + struct PrintableItem **printable_items; + struct Note **notes; +}; + +struct Config { + struct ConfigOutput *output; + struct ConfigParser *parser; +}; + +extern struct ChoSong **cho_songs_parse(FILE *fp, struct Config *config); +extern void cho_songs_free(struct ChoSong **song); +extern char *out_pdf_new(const char *cho_filename, const char *output_folder_or_file, struct ChoSong **songs, struct Config *config); +extern struct Config *config_load(const char *filepath); +extern void config_free(struct Config *config); diff --git a/out_pdf.c b/out_pdf.c @@ -361,6 +361,13 @@ static double text_width(struct TextLineItem *item) return -1.0; } free(name); + /* int i = 0; + while (item->text[i] != 0) { + printf("%02X ", item->text[i]); + i++; + } + printf("\n"); */ + // printf("size: %.1f\n", item->style->font->size); return pdfioContentTextMeasure(font_obj, item->text, item->style->font->size); } @@ -630,6 +637,7 @@ static struct Text **text_create(struct ChoSong **songs, struct Config *config) text[t]->lines[tl]->items = malloc(2 * sizeof(struct TextLineItem *)); text[t]->lines[tl]->items[0] = malloc(sizeof(struct TextLineItem)); text[t]->lines[tl]->items[0]->text = strdup(songs[so]->metadata[m]->value); + printf("strdup text: %s\n", text[t]->lines[tl]->items[0]->text); text[t]->lines[tl]->items[0]->style = cho_style_duplicate(songs[so]->metadata[m]->style); width = text_width(text[t]->lines[tl]->items[0]); if (width == EMPTY) { @@ -1021,22 +1029,20 @@ static pdfio_stream_t *out_pdf_page_create(pdfio_file_t *pdf, pdfio_array_t *ann return page_stream; } -bool out_pdf_new(const char *cho_filepath, const char *output_folder_or_file, struct ChoSong **songs, struct Config *config) +char *out_pdf_new(const char *cho_filepath, const char *output_folder_or_file, struct ChoSong **songs, struct Config *config) { memset(&g_current_font_name, 0, sizeof(g_current_font_name)); char *pdf_filename = out_pdf_filename_create(songs, cho_filepath, output_folder_or_file); if (!pdf_filename) { fprintf(stderr, "out_pdf_filename_create failed.\n"); - return false; + return NULL; } pdfio_rect_t media_box_a4 = { 0.0, 0.0, MEDIABOX_WIDTH, MEDIABOX_HEIGHT }; pdfio_rect_t crop_box = { 36.0, 36.0, MEDIABOX_WIDTH, MEDIABOX_HEIGHT }; - fprintf(stderr, "INFO: Writing pdf to file: '%s'\n", pdf_filename); pdfio_file_t *pdf = pdfioFileCreate(pdf_filename, "2.0", &media_box_a4, &crop_box, NULL, NULL); - free(pdf_filename); if (!out_pdf_set_title(pdf, songs)) { fprintf(stderr, "out_pdf_set_title failed.\n"); - return false; + return NULL; } struct Font **needed_fonts = out_pdf_font_get_all(songs, config); struct Fnt *fnt; @@ -1061,7 +1067,7 @@ bool out_pdf_new(const char *cho_filepath, const char *output_folder_or_file, st } else { fprintf(stderr, "ERR: Didn't find font file for following font:\n"); cho_font_print(needed_fonts[f]); - return false; + return NULL; } } f++; @@ -1070,12 +1076,12 @@ bool out_pdf_new(const char *cho_filepath, const char *output_folder_or_file, st struct Text **text = text_create(songs, config); if (!text) { fprintf(stderr, "text_create failed.\n"); - return false; + return NULL; } pdfio_array_t *annots = pdfioArrayCreate(pdf); if (!annots_create(pdf, annots, text)) { fprintf(stderr, "annotations_create failed.\n"); - return false; + return NULL; } pdfio_stream_t *page_stream; int p = 0; @@ -1092,7 +1098,7 @@ bool out_pdf_new(const char *cho_filepath, const char *output_folder_or_file, st if (text[t]->lines[tl]->btype == BT_PAGE) { if (!pdfioStreamClose(page_stream)) { fprintf(stderr, "pdfioStreamClose failed.\n"); - return false; + return NULL; } p++; page_stream = out_pdf_page_create(pdf, annots, p); @@ -1104,13 +1110,14 @@ bool out_pdf_new(const char *cho_filepath, const char *output_folder_or_file, st } if (!pdfioStreamClose(page_stream)) { fprintf(stderr, "pdfioStreamClose failed.\n"); - return false; + return NULL; } if (!pdfioFileClose(pdf)) { fprintf(stderr, "pdfioFileClose failed.\n"); - return false; + return NULL; } text_free(text); out_pdf_fnts_free(g_fonts); - return true; + g_fonts = NULL; + return pdf_filename; } diff --git a/out_pdf.h b/out_pdf.h @@ -55,4 +55,4 @@ enum LineLocation { LL_UNDER }; -bool out_pdf_new(const char *cho_filename, const char *output_folder_or_file, struct ChoSong **songs, struct Config *config); +char *out_pdf_new(const char *cho_filename, const char *output_folder_or_file, struct ChoSong **songs, struct Config *config); diff --git a/out_pdf.o b/out_pdf.o Binary files differ.