lorid

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

commit fe1d1a07ca7fb9716f59ffd8d3b4899aa6785972
parent 65a09de40a13b048c0a98f3598bfbe3c79b7281d
Author: nibo <nibo@relim.de>
Date:   Fri,  3 Jan 2025 14:37:06 +0100

Abandon fontconfig.c

Diffstat:
MMakefile | 2+-
Mchord_diagram.c | 1-
Mchordpro.c | 1-
Mchordpro.h | 1+
Dfontconfig.c | 116-------------------------------------------------------------------------------
Dfontconfig.h | 9---------
Mlorid.c | 1-
Mout_pdf.c | 120+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Mout_pdf.h | 5+++++
9 files changed, 113 insertions(+), 143 deletions(-)

diff --git a/Makefile b/Makefile @@ -5,7 +5,7 @@ COLOR = 0 VARS = -DVERSION=\"${VERSION}\" -DCOLOR=${COLOR} -DPREFIX=\"${PREFIX}\" CFLAGS = -pedantic -Wall -Wextra LDFLAGS = -lpdfio -ltoml -lfontconfig -SRC = util.c fontconfig.c config.c chordpro.c chord_diagram.c out_pdf.c lorid.c +SRC = util.c config.c chordpro.c chord_diagram.c out_pdf.c lorid.c compile: $(CC) ${CFLAGS} ${VARS} -O2 ${SRC} -o lorid ${LDFLAGS} diff --git a/chord_diagram.c b/chord_diagram.c @@ -1,5 +1,4 @@ #include <string.h> -#include <stdint.h> #include <pdfio.h> #include <pdfio-content.h> #include "out_pdf.h" diff --git a/chordpro.c b/chordpro.c @@ -1,7 +1,6 @@ #include <stdio.h> #include <stdlib.h> #include <stdbool.h> -#include <stdint.h> #include <stdarg.h> #include <unistd.h> #include <string.h> diff --git a/chordpro.h b/chordpro.h @@ -1,3 +1,4 @@ +#include <stdint.h> #include "config.h" #ifndef _CHORDPRO_H_ diff --git a/fontconfig.c b/fontconfig.c @@ -1,116 +0,0 @@ -#include <stdio.h> -#include <stdbool.h> -#include <stdint.h> -#include <string.h> -#include <fontconfig/fontconfig.h> -#include "fontconfig.h" -#include "util.h" - -static bool -file_extension_is_ttc(const char *filepath) -{ - int mark = -1; - int i; - for (i = 0; filepath[i]; i++) { - if (filepath[i] == '.') { - mark = i; - } - } - if (!strcmp(&filepath[mark+1], "ttc")) - return true; - return false; -} - -char * -fontconfig_fontpath_find_regular_font(void) -{ - char *filepath = NULL; - FcChar8 *file; - FcResult result; - FcPattern *match; - FcPattern *pattern = FcPatternCreate(); - FcConfigSubstitute(NULL, pattern, FcMatchPattern); - FcDefaultSubstitute(pattern); - FcValue weight; - weight.type = FcTypeInteger; - weight.u.i = FC_WEIGHT_REGULAR; - FcPatternAdd(pattern, FC_WEIGHT, weight, FcFalse); - match = FcFontMatch(NULL, pattern, &result); - if (match && result == FcResultMatch) { - if (FcPatternGetString(match, FC_FILE, 0, &file) == FcResultMatch) { - filepath = strdup((const char *)file); - } - } - FcPatternDestroy(pattern); - FcPatternDestroy(match); - return filepath; -} - -char * -fontconfig_fontpath_find(struct Font *font, enum FontType font_type) -{ - char *filepath = NULL; - FcObjectSet *obj = FcObjectSetBuild(FC_FAMILY, FC_SLANT, FC_WEIGHT, FC_FONTFORMAT, FC_FONT_WRAPPER, FC_FILE, NULL); - FcPattern *pattern = FcPatternCreate(); - FcValue family = { .type = FcTypeString, .u.s = (FcChar8 *)font->name }; - FcPatternAdd(pattern, FC_FAMILY, family, FcFalse); - FcValue font_wrapper = { .type = FcTypeString, .u.s = (FcChar8 *)"SFNT" }; - FcPatternAdd(pattern, FC_FONT_WRAPPER, font_wrapper, FcFalse); - /* TODO: Also handle FF_NORMAL, FF_SANS and FF_SERIF, but how? */ - if (font->family == FF_MONOSPACE) { - FcValue spacing = { .type = FcTypeInteger, .u.i = FC_MONO }; - FcPatternAdd(pattern, FC_SPACING, spacing, FcFalse); - } - FcValue type; - type.type = FcTypeString; - if (font_type == FT_OTF) - type.u.s = (FcChar8 *)"CFF"; - else - type.u.s = (FcChar8 *)"TrueType"; - FcPatternAdd(pattern, FC_FONTFORMAT, type, FcFalse); - FcValue style; - style.type = FcTypeInteger; - switch (font->style) { - case FS_ROMAN: - style.u.i = FC_SLANT_ROMAN; - break; - case FS_OBLIQUE: - style.u.i = FC_SLANT_OBLIQUE; - break; - case FS_ITALIC: - style.u.i = FC_SLANT_ITALIC; - break; - default: - util_log(LOG_ERR, "Invalid font style value '%d'.", font->style); - return NULL; - } - FcPatternAdd(pattern, FC_SLANT, style, FcFalse); - FcValue weight; - weight.type = FcTypeInteger; - switch (font->weight) { - case FW_REGULAR: - weight.u.i = FC_WEIGHT_REGULAR; - break; - case FW_BOLD: - weight.u.i = FC_WEIGHT_BOLD; - break; - default: - util_log(LOG_ERR, "Invalid font weight value '%d'.", font->weight); - return NULL; - } - FcPatternAdd(pattern, FC_WEIGHT, weight, FcFalse); - FcFontSet *set = FcFontList(NULL, pattern, obj); - FcChar8 *file; - for (int i=0; i<set->nfont; i++) { - if (FcPatternGetString(set->fonts[i], FC_FILE, 0, &file) == FcResultMatch) { - if (!file_extension_is_ttc((const char *)file)) { - filepath = strdup((const char *)file); - break; - } - } - } - FcObjectSetDestroy(obj); - FcPatternDestroy(pattern); - FcFontSetDestroy(set); - return filepath; -} diff --git a/fontconfig.h b/fontconfig.h @@ -1,9 +0,0 @@ -#include "chordpro.h" - -enum FontType { - FT_TTF, - FT_OTF -}; - -char *fontconfig_fontpath_find_regular_font(void); -char *fontconfig_fontpath_find(struct Font *font, enum FontType font_type); diff --git a/lorid.c b/lorid.c @@ -1,7 +1,6 @@ #include <stdio.h> #include <stdlib.h> #include <stdbool.h> -#include <stdint.h> #include <string.h> #include <getopt.h> #include "config.h" diff --git a/out_pdf.c b/out_pdf.c @@ -1,15 +1,14 @@ #include <stdbool.h> -#include <stdint.h> #include <string.h> #include <unistd.h> #include <pdfio.h> #include <pdfio-content.h> #include <sys/stat.h> #include <errno.h> +#include <fontconfig/fontconfig.h> #include "chordpro.h" #include "config.h" #include "out_pdf.h" -#include "fontconfig.h" #include "util.h" #include "chord_diagram.h" @@ -34,7 +33,7 @@ out_pdf_fnt_obj_get_by_name(const char *name) } static bool -out_pdf_font_add_if_not_in(struct Font *font, struct Font ***array) +fonts_add_if_not_in(struct Font ***array, struct Font *font) { if (!*array) { *array = erealloc(*array, 2 * sizeof(struct Font *)); @@ -61,7 +60,7 @@ out_pdf_font_add_if_not_in(struct Font *font, struct Font ***array) } static void -out_pdf_add_fonts(struct Font *font, struct Font ***fonts) +fonts_add(struct Font ***fonts, struct Font *font) { bool added = false; char part[100]; @@ -79,7 +78,7 @@ out_pdf_add_fonts(struct Font *font, struct Font ***fonts) new_font->style = font->style; new_font->weight = font->weight; new_font->size = font->size; - added = out_pdf_font_add_if_not_in(new_font, fonts); + added = fonts_add_if_not_in(fonts, new_font); if (!added) { cho_font_free(new_font); trimmed = NULL; @@ -99,13 +98,13 @@ out_pdf_add_fonts(struct Font *font, struct Font ***fonts) new_font->style = font->style; new_font->weight = font->weight; new_font->size = font->size; - added = out_pdf_font_add_if_not_in(new_font, fonts); + added = fonts_add_if_not_in(fonts, new_font); if (!added) cho_font_free(new_font); } static struct Font ** -out_pdf_font_get_all(struct ChoSong **songs, struct Config *config) +fonts_get_all(struct ChoSong **songs, struct Config *config) { struct Font **fonts = NULL; struct Font *font; @@ -113,7 +112,7 @@ out_pdf_font_get_all(struct ChoSong **songs, struct Config *config) int i; for (i = 0; config->output->styles[i]; i++) { font = cho_font_copy(config->output->styles[i]->style->font); - added = out_pdf_font_add_if_not_in(font, &fonts); + added = fonts_add_if_not_in(&fonts, font); if (!added) { cho_font_free(font); } @@ -134,14 +133,14 @@ out_pdf_font_get_all(struct ChoSong **songs, struct Config *config) style = (*above)->u.annot->style; } if (style->font->name) { - out_pdf_add_fonts(style->font, &fonts); + fonts_add(&fonts, style->font); } } for (it = (*li)->items; *it; it++) { if ((*it)->is_text) { style = (*it)->u.text->style; if (style->font->name) { - out_pdf_add_fonts(style->font, &fonts); + fonts_add(&fonts, style->font); } } } @@ -151,6 +150,89 @@ out_pdf_font_get_all(struct ChoSong **songs, struct Config *config) return fonts; } +static bool +file_extension_is_ttc(const char *filepath) +{ + int mark = -1; + int i; + for (i = 0; filepath[i]; i++) { + if (filepath[i] == '.') { + mark = i; + } + } + if (!strcmp(&filepath[mark+1], "ttc")) + return true; + return false; +} + +static char * +fontpath_find(struct Font *font, enum FontType font_type) +{ + char *filepath = NULL; + FcObjectSet *obj = FcObjectSetBuild(FC_FAMILY, FC_SLANT, FC_WEIGHT, FC_FONTFORMAT, FC_FONT_WRAPPER, FC_FILE, NULL); + FcPattern *pattern = FcPatternCreate(); + FcValue family = { .type = FcTypeString, .u.s = (FcChar8 *)font->name }; + FcPatternAdd(pattern, FC_FAMILY, family, FcFalse); + FcValue font_wrapper = { .type = FcTypeString, .u.s = (FcChar8 *)"SFNT" }; + FcPatternAdd(pattern, FC_FONT_WRAPPER, font_wrapper, FcFalse); + /* TODO: Also handle FF_NORMAL, FF_SANS and FF_SERIF, but how? */ + if (font->family == FF_MONOSPACE) { + FcValue spacing = { .type = FcTypeInteger, .u.i = FC_MONO }; + FcPatternAdd(pattern, FC_SPACING, spacing, FcFalse); + } + FcValue type; + type.type = FcTypeString; + if (font_type == FT_OTF) + type.u.s = (FcChar8 *)"CFF"; + else + type.u.s = (FcChar8 *)"TrueType"; + FcPatternAdd(pattern, FC_FONTFORMAT, type, FcFalse); + FcValue style; + style.type = FcTypeInteger; + switch (font->style) { + case FS_ROMAN: + style.u.i = FC_SLANT_ROMAN; + break; + case FS_OBLIQUE: + style.u.i = FC_SLANT_OBLIQUE; + break; + case FS_ITALIC: + style.u.i = FC_SLANT_ITALIC; + break; + default: + util_log(LOG_ERR, "Invalid font style value '%d'.", font->style); + return NULL; + } + FcPatternAdd(pattern, FC_SLANT, style, FcFalse); + FcValue weight; + weight.type = FcTypeInteger; + switch (font->weight) { + case FW_REGULAR: + weight.u.i = FC_WEIGHT_REGULAR; + break; + case FW_BOLD: + weight.u.i = FC_WEIGHT_BOLD; + break; + default: + util_log(LOG_ERR, "Invalid font weight value '%d'.", font->weight); + return NULL; + } + FcPatternAdd(pattern, FC_WEIGHT, weight, FcFalse); + FcFontSet *set = FcFontList(NULL, pattern, obj); + FcChar8 *file; + for (int i=0; i<set->nfont; i++) { + if (FcPatternGetString(set->fonts[i], FC_FILE, 0, &file) == FcResultMatch) { + if (!file_extension_is_ttc((const char *)file)) { + filepath = strdup((const char *)file); + break; + } + } + } + FcObjectSetDestroy(obj); + FcPatternDestroy(pattern); + FcFontSetDestroy(set); + return filepath; +} static char * out_pdf_filename_generate_from_songs(struct ChoSong **songs) { @@ -1541,7 +1623,6 @@ pdf_toc_page_count( return page + 1; } -// TODO: This function doesn't create a new page if needed static bool pdf_texts_add_toc_entry( struct PDFContext *ctx, @@ -1781,7 +1862,15 @@ pdf_content_create( imgs = &ctx.content->pages[ctx.page]->images; diagrams = &ctx.content->pages[ctx.page]->diagrams; int s; + // int the_page; for (s = 0; songs[s]; s++) { + /* if (the_page == ctx.page) { + counter++; + } else { + counter = 0; + } + the_page = ctx.page; */ + // printf("song '%d' start on page '%d'.\n", s, ctx.page); if (config->output->diagram->show) { struct ChoChord **chords = NULL; if (!out_pdf_get_chords(songs[s], &chords)) { @@ -2099,6 +2188,9 @@ pdf_content_create( } ctx.y -= SECTION_GAP_WIDTH; } + /* if (config->output->max_songs_per_page == 1) { + // create new page + } */ } *texts = erealloc(*texts, (ctx.text+1) * sizeof(struct PDFText *)); (*texts)[ctx.text] = NULL; @@ -2242,9 +2334,9 @@ out_pdf_create( goto CLEAN; } int f; - needed_fonts = out_pdf_font_get_all(songs, config); + needed_fonts = fonts_get_all(songs, config); for (f = 0; needed_fonts[f]; f++) { - fontpath = fontconfig_fontpath_find(needed_fonts[f], FT_TTF); + fontpath = fontpath_find(needed_fonts[f], FT_TTF); if (fontpath) { fnt = obj_new(); fnt->name = out_pdf_fnt_name_create(needed_fonts[f]); @@ -2252,7 +2344,7 @@ out_pdf_create( objs_add_obj(&g_fonts, fnt); free(fontpath); } else { - fontpath = fontconfig_fontpath_find(needed_fonts[f], FT_OTF); + fontpath = fontpath_find(needed_fonts[f], FT_OTF); if (fontpath) { fnt = obj_new(); fnt->name = out_pdf_fnt_name_create(needed_fonts[f]); diff --git a/out_pdf.h b/out_pdf.h @@ -19,6 +19,11 @@ enum LineLocation { LL_UNDER }; +enum FontType { + FT_TTF, + FT_OTF +}; + struct CharPosition { int line_item_index; int text_index;