lorid

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

commit 2a79e50c9047656f6b6dd8de5f95f8a77d84a35c
parent 20e97fb27e648467ee57e6c5beec23daeee0147a
Author: nibo <nibo@relim.de>
Date:   Tue,  7 Jan 2025 14:31:54 +0100

Find present song fragments

Later we can then only load fonts for the
actually used song fragments.

Diffstat:
Mchordpro.c | 90+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Mchordpro.h | 39+++++++++++++++++++++++----------------
Mconfig.c | 178++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Mconfig.h | 5+++--
Mlorid.c | 2+-
Mout_pdf.c | 67++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
6 files changed, 263 insertions(+), 118 deletions(-)

diff --git a/chordpro.c b/chordpro.c @@ -212,7 +212,10 @@ static const char *song_fragment_type_enums[] = { "SF_TEXT", "SF_TITLE", "SF_SUBTITLE", - "SF_LABEL" + "SF_LABEL", + "SF_COMMENT", + "SF_COMMENT_ITALIC", + "SF_COMMENT_BOX" }; static const char *style_property_type_enums[] = { @@ -869,35 +872,13 @@ struct ChoStyle * cho_style_new_from_config(enum SongFragmentType ftype) { struct OutputStyle *style; - switch (ftype) { - case SF_CHORD: - style = config_output_style_get(g_config->output->styles, "chord"); - return cho_style_copy(style->style); - case SF_ANNOT: - style = config_output_style_get(g_config->output->styles, "annotation"); - return cho_style_copy(style->style); - case SF_GRID: - style = config_output_style_get(g_config->output->styles, "grid"); - return cho_style_copy(style->style); - case SF_TAB: - style = config_output_style_get(g_config->output->styles, "tab"); - return cho_style_copy(style->style); - case SF_LABEL: - style = config_output_style_get(g_config->output->styles, "label"); - return cho_style_copy(style->style); - case SF_TITLE: - style = config_output_style_get(g_config->output->styles, "title"); - return cho_style_copy(style->style); - case SF_SUBTITLE: - style = config_output_style_get(g_config->output->styles, "subtitle"); - return cho_style_copy(style->style); - case SF_TOC: - style = config_output_style_get(g_config->output->styles, "toc"); - return cho_style_copy(style->style); - default: - style = config_output_style_get(g_config->output->styles, "text"); - return cho_style_copy(style->style); + style = config_output_style_get(g_config->output->styles, ftype); + if (!style) { + printf("fragment type '%d'\n", ftype); + LOG_DEBUG("config_output_style_get failed."); + return NULL; } + return cho_style_copy(style->style); } struct ChoStyle * @@ -3106,6 +3087,7 @@ cho_song_new(void) song->metadata = NULL; song->sections = NULL; song->diagrams = NULL; + memset(song->present_fragments, 0, SF_LENGTH); return song; } @@ -3370,22 +3352,37 @@ cho_directive_parse(const char *name) !strcmp(name, "c") || !strcmp(name, "highlight") ) { - directive->style->background_color = cho_rgbcolor_new(228, 228, 228); directive->dtype = DT_FORMATTING; + g_prev_ftype = g_current_ftype; + g_current_ftype = SF_COMMENT; + cho_style_free(directive->style); + directive->style = cho_style_new_default(); + g_current_ftype = g_prev_ftype; + directive->ftype = SF_COMMENT; goto END; } else if ( !strcmp(name, "comment_italic") || !strcmp(name, "ci") ) { - directive->style->font->style = FS_ITALIC; directive->dtype = DT_FORMATTING; + g_prev_ftype = g_current_ftype; + g_current_ftype = SF_COMMENT_ITALIC; + cho_style_free(directive->style); + directive->style = cho_style_new_default(); + g_current_ftype = g_prev_ftype; + directive->ftype = SF_COMMENT_ITALIC; goto END; } else if ( !strcmp(name, "comment_box") || !strcmp(name, "cb") ) { - directive->style->boxed = true; directive->dtype = DT_FORMATTING; + g_prev_ftype = g_current_ftype; + g_current_ftype = SF_COMMENT_BOX; + cho_style_free(directive->style); + directive->style = cho_style_new_default(); + g_current_ftype = g_prev_ftype; + directive->ftype = SF_COMMENT_BOX; goto END; } if (!strcmp(name, "image")) { @@ -3666,7 +3663,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) char tag_start[6]; char tag_end[6]; char custom_directive[64]; - char *label, *metadata_value; + char *label, *metadata_value, *stripped_directive_value; enum State state = STATE_LYRICS; enum State prev_state = STATE_LYRICS; int dn = 0; @@ -3844,6 +3841,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) (*lines)[li] = cho_line_new(); (*lines)[li]->items = emalloc(sizeof(struct ChoLineItem *)); (*lines)[li]->items[ly] = cho_line_item_new(); + songs[so]->present_fragments[directive->ftype] = true; break; case POS_END: if (directive->stype == songs[so]->sections[se]->type) { @@ -4068,6 +4066,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) if (buf == '}') { directive_value[dv] = 0; dv = 0; + stripped_directive_value = str_remove_leading_whitespace(directive_value); directive = cho_directive_parse(directive_name); /* printf( "directive: '%s'\ndtype: %s, stype: %s, position: %s\n", @@ -4075,6 +4074,9 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) ); */ switch (directive->dtype) { case DT_ENVIRONMENT: + if (strlen(stripped_directive_value) > 0) { + songs[so]->present_fragments[SF_LABEL] = true; + } g_current_ftype = directive->ftype; switch (directive->position) { case POS_START: @@ -4101,7 +4103,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) } songs[so]->sections[se]->label->text = label; } else { - songs[so]->sections[se]->label->text = str_remove_leading_whitespace(directive_value); + songs[so]->sections[se]->label->text = strdup(stripped_directive_value); } songs[so]->sections[se]->label->style = cho_style_new_from_config(SF_LABEL); li = 0; @@ -4110,6 +4112,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) (*lines)[li] = cho_line_new(); (*lines)[li]->items = emalloc(sizeof(struct ChoLineItem *)); (*lines)[li]->items[ly] = cho_line_item_new(); + songs[so]->present_fragments[directive->ftype] = true; break; case POS_END: if (directive->stype == songs[so]->sections[se]->type) { @@ -4131,7 +4134,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) break; case POS_EMPTY: /* INFO: {chorus: ...} */ - label = str_remove_leading_whitespace(directive_value); + label = strdup(stripped_directive_value); chorus = cho_find_previous_chorus(songs[so]->sections, se); if (chorus) { if (config->output->chorus->quote) { @@ -4220,7 +4223,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) } break; case DT_METADATA: - metadata_value = str_remove_leading_whitespace(directive_value); + metadata_value = strdup(stripped_directive_value); if (strlen(metadata_value) == 0) { cho_log(LOG_WARN, "Ignoring metadata directive '%s' because it has no value.", directive_name); free(metadata_value); @@ -4235,6 +4238,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) cho_style_free(songs[so]->metadata[m]->style); songs[so]->metadata[m]->style = cho_style_copy(directive->style); m++; + songs[so]->present_fragments[SF_TITLE] = true; break; case SUBTITLE: songs[so]->metadata = erealloc(songs[so]->metadata, (m+1) * sizeof(struct ChoMetadata *)); @@ -4244,6 +4248,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) cho_style_free(songs[so]->metadata[m]->style); songs[so]->metadata[m]->style = cho_style_copy(directive->style); m++; + songs[so]->present_fragments[SF_SUBTITLE] = true; break; default: if (!strcmp(directive_name, "meta")) { @@ -4281,9 +4286,9 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) (*lines)[li]->items[ly] = cho_line_item_new(); cho_style_free((*lines)[li]->items[ly]->u.text->style); (*lines)[li]->items[ly]->u.text->style = cho_style_copy(directive->style); - char *trimmed_directive_value = str_remove_leading_whitespace(directive_value); - (*lines)[li]->items[ly]->u.text->text = trimmed_directive_value; - te += strlen(trimmed_directive_value); + (*lines)[li]->items[ly]->u.text->text = strdup(stripped_directive_value); + te += strlen(stripped_directive_value); + songs[so]->present_fragments[directive->ftype] = true; break; case DT_IMAGE: if (strstr(directive_value, "=")) { @@ -4294,7 +4299,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) } } else { image = cho_image_new(); - image->src = str_remove_leading_whitespace(directive_value); + image->src = strdup(stripped_directive_value); } if (image->is_asset) { g_image_assets = erealloc(g_image_assets, (g_ia+1) * sizeof(struct ChoImage *)); @@ -4319,7 +4324,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) return NULL; case DT_FONT: sprop.ftype = directive->ftype; - char *dir_value = str_remove_leading_whitespace(directive_value); + char *dir_value = strdup(stripped_directive_value); switch (directive->sprop) { case SPT_FONT: sprop.u.font_name = emalloc((strlen(dir_value)+1) * sizeof(char)); @@ -4395,6 +4400,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) return NULL; } memset(directive_value, 0, strlen(directive_value)); + free(stripped_directive_value); cho_directive_free(directive); directive = NULL; state = STATE_LYRICS; @@ -4442,6 +4448,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) cho_log(LOG_INFO, "Didn't recognize the chord '%s'.", (*lines)[li]->text_above[c]->u.chord->name); } } + songs[so]->present_fragments[SF_CHORD] = true; memset(chord, 0, strlen(chord)); c++; g_current_ftype = g_prev_ftype; @@ -4487,6 +4494,7 @@ cho_songs_parse(FILE *fp, const char *chordpro_filepath, struct Config *config) if (buf == ']') { (*lines)[li]->text_above[c]->u.annot->text = erealloc((*lines)[li]->text_above[c]->u.annot->text, (ann+1) * sizeof(char)); (*lines)[li]->text_above[c]->u.annot->text[ann] = 0; + songs[so]->present_fragments[SF_ANNOT] = true; ann = 0; c++; g_current_ftype = g_prev_ftype; diff --git a/chordpro.h b/chordpro.h @@ -1,9 +1,30 @@ #include <stdint.h> -#include "config.h" #ifndef _CHORDPRO_H_ #define _CHORDPRO_H_ +enum SongFragmentType { + SF_EMPTY, + SF_CHORD, + SF_ANNOT, + SF_CHORUS, + SF_FOOTER, + SF_GRID, + SF_TAB, + SF_TOC, + SF_TEXT, + SF_TITLE, + SF_SUBTITLE, + SF_LABEL, + SF_COMMENT, + SF_COMMENT_ITALIC, + SF_COMMENT_BOX, + SF_LENGTH +}; + +#include "config.h" + + #define ERROR -1.0 #define EMPTY_DOUBLE -1.0 #define EMPTY_INT -1 @@ -136,21 +157,6 @@ enum SectionType { ST_CUSTOM }; -enum SongFragmentType { - SF_EMPTY, - SF_CHORD, - SF_ANNOT, - SF_CHORUS, - SF_FOOTER, - SF_GRID, - SF_TAB, - SF_TOC, - SF_TEXT, - SF_TITLE, - SF_SUBTITLE, - SF_LABEL -}; - enum State { STATE_LYRICS, STATE_DIRECTIVE_NAME, @@ -300,6 +306,7 @@ struct ChoSong { struct ChoMetadata **metadata; struct ChoSection **sections; struct ChordDiagram **diagrams; + bool present_fragments[SF_LENGTH]; }; union StylePropertyValue { diff --git a/config.c b/config.c @@ -30,7 +30,14 @@ static const char *instruments[] = { "unknown" }; -static const char *g_valid_styles[] = { +static const char *song_fragment_types[] = { + "empty", "chord", "annotation", "chorus", + "footer", "grid", "tab", "toc", "text", + "title", "subtitle", "label", "comment", + "comment_italic", "comment_box" +}; + +/* static const char *g_valid_styles[] = { "title", "subtitle", "footer", // TODO @@ -50,7 +57,7 @@ static const char *g_valid_styles[] = { "diagram", // TODO "diagram_base", // TODO "chordfingers" // TODO -}; +}; */ static struct Note notes_common[] = { { .note = "C", .sharp = "C#", .flat = NULL }, @@ -112,11 +119,59 @@ static struct Note notes_nashville[] = { { .note = "7", .sharp = NULL, .flat = "7b" }, }; +static enum SongFragmentType +config_song_fragment_type_parse(const char *str) +{ + // TODO: can g_valid_styles be replaced by the song fragment types? + if (!strcmp(str, song_fragment_types[SF_CHORD])) { + return SF_CHORD; + } else + if (!strcmp(str, song_fragment_types[SF_ANNOT])) { + return SF_ANNOT; + } else + if (!strcmp(str, song_fragment_types[SF_CHORUS])) { + } else + if (!strcmp(str, song_fragment_types[SF_FOOTER])) { + return SF_FOOTER; + } else + if (!strcmp(str, song_fragment_types[SF_GRID])) { + return SF_GRID; + } else + if (!strcmp(str, song_fragment_types[SF_TAB])) { + return SF_TAB; + } else + if (!strcmp(str, song_fragment_types[SF_TOC])) { + return SF_TOC; + } else + if (!strcmp(str, song_fragment_types[SF_TEXT])) { + return SF_TEXT; + } else + if (!strcmp(str, song_fragment_types[SF_TITLE])) { + return SF_TITLE; + } else + if (!strcmp(str, song_fragment_types[SF_SUBTITLE])) { + return SF_SUBTITLE; + } else + if (!strcmp(str, song_fragment_types[SF_LABEL])) { + return SF_LABEL; + } else + if (!strcmp(str, song_fragment_types[SF_COMMENT])) { + return SF_COMMENT; + } else + if (!strcmp(str, song_fragment_types[SF_COMMENT_ITALIC])) { + return SF_COMMENT_ITALIC; + } else + if (!strcmp(str, song_fragment_types[SF_COMMENT_BOX])) { + return SF_COMMENT_BOX; + } + return SF_EMPTY; +} + static struct OutputStyle * -config_output_style_new(const char *name) +config_output_style_new(enum SongFragmentType type) { struct OutputStyle *item = emalloc(sizeof(struct OutputStyle)); - item->name = strdup(name); + item->type = type; item->style = cho_style_new(); return item; } @@ -124,17 +179,16 @@ config_output_style_new(const char *name) static void config_output_style_free(struct OutputStyle *item) { - free(item->name); cho_style_free(item->style); free(item); } struct OutputStyle * -config_output_style_get(struct OutputStyle **styles, const char *name) +config_output_style_get(struct OutputStyle **styles, enum SongFragmentType type) { struct OutputStyle **os; for (os = styles; *os; os++) { - if (!strcmp((*os)->name, name)) { + if ((*os)->type == type) { return *os; } } @@ -373,41 +427,63 @@ config_load_default(void) config->output->diagram->show = true; config->output->diagram->instrument = INS_GUITAR; config->output->system = NS_COMMON; - config->output->styles = emalloc(13 * sizeof(struct OutputStyle *)); - config->output->styles[0] = config_output_style_new("title"); - config->output->styles[0]->style->font->name = strdup("Open Sans"); + config->output->styles = emalloc(14 * sizeof(struct OutputStyle *)); + + config->output->styles[0] = config_output_style_new(SF_CHORD); + config->output->styles[0]->style->font->name = strdup(DEFAULT_FONT_FAMILY); config->output->styles[0]->style->font->weight = FW_BOLD; - config->output->styles[0]->style->font->size = 18.0; - config->output->styles[1] = config_output_style_new("subtitle"); - config->output->styles[1]->style->font->name = strdup("Open Sans"); - config->output->styles[1]->style->font->size = 12.0; - config->output->styles[2] = config_output_style_new("text"); - config->output->styles[2]->style->font->name = strdup("Open Sans"); - config->output->styles[3] = config_output_style_new("chord"); - config->output->styles[3]->style->font->name = strdup("Open Sans"); + + config->output->styles[1] = config_output_style_new(SF_ANNOT); + config->output->styles[1]->style->font->name = strdup(DEFAULT_FONT_FAMILY); + config->output->styles[1]->style->font->style = FS_ITALIC; + + config->output->styles[2] = config_output_style_new(SF_CHORUS); + config->output->styles[2]->style->font->name = strdup(DEFAULT_FONT_FAMILY); + + // Footer + + config->output->styles[3] = config_output_style_new(SF_GRID); + config->output->styles[3]->style->font->name = strdup(DEFAULT_FONT_FAMILY); config->output->styles[3]->style->font->weight = FW_BOLD; - config->output->styles[4] = config_output_style_new("comment"); - config->output->styles[4]->style->font->name = strdup("Open Sans"); - config->output->styles[5] = config_output_style_new("comment_italic"); - config->output->styles[5]->style->font->name = strdup("Open Sans"); - config->output->styles[5]->style->font->style = FS_ITALIC; - config->output->styles[6] = config_output_style_new("comment_box"); - config->output->styles[6]->style->font->name = strdup("Open Sans"); - config->output->styles[7] = config_output_style_new("tab"); - config->output->styles[7]->style->font->name = strdup("Open Sans"); - config->output->styles[8] = config_output_style_new("grid"); - config->output->styles[8]->style->font->name = strdup("Open Sans"); - config->output->styles[8]->style->font->weight = FW_BOLD; - config->output->styles[9] = config_output_style_new("label"); - config->output->styles[9]->style->font->name = strdup("Open Sans"); + + config->output->styles[4] = config_output_style_new(SF_TAB); + config->output->styles[4]->style->font->name = strdup(DEFAULT_FONT_FAMILY); + + config->output->styles[5] = config_output_style_new(SF_TOC); + config->output->styles[5]->style->font->name = strdup(DEFAULT_FONT_FAMILY); + config->output->styles[5]->style->font->size = 12.0; + + config->output->styles[6] = config_output_style_new(SF_TEXT); + config->output->styles[6]->style->font->name = strdup(DEFAULT_FONT_FAMILY); + + config->output->styles[7] = config_output_style_new(SF_TITLE); + config->output->styles[7]->style->font->name = strdup(DEFAULT_FONT_FAMILY); + config->output->styles[7]->style->font->weight = FW_BOLD; + config->output->styles[7]->style->font->size = 18.0; + + config->output->styles[8] = config_output_style_new(SF_SUBTITLE); + config->output->styles[8]->style->font->name = strdup(DEFAULT_FONT_FAMILY); + config->output->styles[8]->style->font->size = 12.0; + + config->output->styles[9] = config_output_style_new(SF_LABEL); + config->output->styles[9]->style->font->name = strdup(DEFAULT_FONT_FAMILY); config->output->styles[9]->style->font->style = FS_ITALIC; - config->output->styles[10] = config_output_style_new("annotation"); - config->output->styles[10]->style->font->name = strdup("Open Sans"); - config->output->styles[10]->style->font->style = FS_ITALIC; - config->output->styles[11] = config_output_style_new("toc"); - config->output->styles[11]->style->font->name = strdup("Open Sans"); - config->output->styles[11]->style->font->size = 12.0; - config->output->styles[12] = NULL; + + config->output->styles[10] = config_output_style_new(SF_COMMENT); + config->output->styles[10]->style->font->name = strdup(DEFAULT_FONT_FAMILY); + config->output->styles[10]->style->background_color->red = 228; + config->output->styles[10]->style->background_color->green = 228; + config->output->styles[10]->style->background_color->blue = 228; + + config->output->styles[11] = config_output_style_new(SF_COMMENT_ITALIC); + config->output->styles[11]->style->font->name = strdup(DEFAULT_FONT_FAMILY); + config->output->styles[11]->style->font->style = FS_ITALIC; + + config->output->styles[12] = config_output_style_new(SF_COMMENT_BOX); + config->output->styles[12]->style->font->name = strdup(DEFAULT_FONT_FAMILY); + config->output->styles[12]->style->boxed = true; + + config->output->styles[13] = NULL; config->output->notes = config_notes_new_default(NS_COMMON); config->parser = emalloc(sizeof(struct ConfigParser)); config->parser->chords = emalloc(sizeof(struct ConfigChords)); @@ -418,10 +494,11 @@ config_load_default(void) } static void -config_output_style_print_as_toml(struct OutputStyle *item) +config_output_style_print_as_toml(struct OutputStyle *style) { - printf("[output.styles.%s]\n", item->name); - cho_style_print_as_toml(item->style, item->name); + const char *name = song_fragment_types[style->type]; + printf("[output.styles.%s]\n", name); + cho_style_print_as_toml(style->style, name); } void @@ -636,17 +713,6 @@ config_load_style(struct ChoStyle *style, toml_table_t *table, const char *key_n return true; } -static bool -config_is_style(const char *str) -{ - const char **s; - for (s = g_valid_styles; *s; s++) { - if (!strcmp(*s, str)) - return true; - } - return false; -} - struct Config * config_load(const char *filepath) { @@ -747,13 +813,15 @@ config_load(const char *filepath) const char *key_name; toml_table_t *key; struct OutputStyle *item; + enum SongFragmentType ftype; int i; for (i = 0; i<toml_table_len(styles); i++) { key_name = toml_table_key(styles, i, &unused); - if (config_is_style(key_name)) { + ftype = config_song_fragment_type_parse(key_name); + if (ftype != SF_EMPTY) { key = toml_table_table(styles, key_name); if (key) { - item = config_output_style_get(config->output->styles, key_name); + item = config_output_style_get(config->output->styles, ftype); if (item) { if (!config_load_style(item->style, key, key_name)) { LOG_DEBUG("config_load_style failed."); diff --git a/config.h b/config.h @@ -6,9 +6,10 @@ #else #define SYMBOLS_FILEPATH PREFIX"/share/lorid/ChordProSymbols.ttf" #endif /* DEBUG */ +#define DEFAULT_FONT_FAMILY "Open Sans" struct OutputStyle { - char *name; + enum SongFragmentType type; struct ChoStyle *style; }; @@ -89,6 +90,6 @@ struct Config { struct Config *config_load(const char *filepath); void config_free(struct Config *config); void config_print_default(void); -struct OutputStyle *config_output_style_get(struct OutputStyle **styles, const char *name); +struct OutputStyle *config_output_style_get(struct OutputStyle **styles, enum SongFragmentType type); #endif /* _CONFIG_H_ */ diff --git a/lorid.c b/lorid.c @@ -3,8 +3,8 @@ #include <stdbool.h> #include <string.h> #include <getopt.h> -#include "config.h" #include "chordpro.h" +#include "config.h" #include "out_pdf.h" #include "util.h" diff --git a/out_pdf.c b/out_pdf.c @@ -191,6 +191,60 @@ fonts_get_all(struct ChoSong **songs, struct Config *config) struct ChoLineItem **it; struct ChoStyle *style; for (so = songs; *so; so++) { + // TODO: Take care of SF_TOC and SF_FOOTER + int i; + const char *name; + for (i = 0; i<SF_LENGTH; i++) { + switch (i) { + case SF_EMPTY: + name = "SF_EMPTY"; + break; + case SF_CHORD: + name = "SF_CHORD"; + break; + case SF_ANNOT: + name = "SF_ANNOT"; + break; + case SF_CHORUS: + name = "SF_CHORUS"; + break; + case SF_FOOTER: + name = "SF_FOOTER"; + break; + case SF_GRID: + name = "SF_GRID"; + break; + case SF_TAB: + name = "SF_TAB"; + break; + case SF_TOC: + name = "SF_TOC"; + break; + case SF_TEXT: + name = "SF_TEXT"; + break; + case SF_TITLE: + name = "SF_TITLE"; + break; + case SF_SUBTITLE: + name = "SF_SUBTITLE"; + break; + case SF_LABEL: + name = "SF_LABEL"; + break; + case SF_COMMENT: + name = "SF_COMMENT"; + break; + case SF_COMMENT_ITALIC: + name = "SF_COMMENT_ITALIC"; + break; + case SF_COMMENT_BOX: + name = "SF_COMMENT_BOX"; + break; + } + printf("%s = %d\n", name, (*so)->present_fragments[i]); + } + printf("\n"); for (se = (*so)->sections; *se; se++) { for (li = (*se)->lines; *li; li++) { for (above = (*li)->text_above; *above; above++) { @@ -235,6 +289,8 @@ fontpath_find(struct Font *font, enum FontType font_type) FcPatternAdd(pattern, FC_FAMILY, family, FcFalse); FcValue font_wrapper = { .type = FcTypeString, .u.s = (FcChar8 *)"SFNT" }; FcPatternAdd(pattern, FC_FONT_WRAPPER, font_wrapper, FcFalse); + FcValue variable = { .type = FcTypeBool, .u.b = FcFalse }; + FcPatternAdd(pattern, FC_VARIABLE, variable, 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 }; @@ -342,14 +398,17 @@ pdf_load_fonts(struct Font **needed_fonts, struct Config *config) struct Obj *fnt; for (f = needed_fonts; *f; f++) { if (font_name_is_path((*f)->name)) { + fontpath = filepath_resolve_tilde((*f)->name); fnt = obj_new(); fnt->name = fnt_name_create(*f); - fnt->value = pdfioFileCreateFontObjFromFile(g_pdf_file, (*f)->name, true); + fnt->value = pdfioFileCreateFontObjFromFile(g_pdf_file, fontpath, true); if (!fnt->value) { LOG_DEBUG("pdfioFileCreateFontObjFromFile failed."); return false; } + free(fontpath); util_log(LOG_INFO, "Loaded font from '%s'.", (*f)->name); + // cho_font_print(*f); objs_add_obj(&g_fonts, fnt); } else if ((name = is_base_font(*f))) { @@ -372,6 +431,7 @@ pdf_load_fonts(struct Font **needed_fonts, struct Config *config) return false; } util_log(LOG_INFO, "Loaded font from '%s'.", fontpath); + // cho_font_print(*f); objs_add_obj(&g_fonts, fnt); free(fontpath); } else { @@ -385,6 +445,7 @@ pdf_load_fonts(struct Font **needed_fonts, struct Config *config) return false; } util_log(LOG_INFO, "Loaded font from '%s'.", fontpath); + // cho_font_print(*f); objs_add_obj(&g_fonts, fnt); free(fontpath); } else { @@ -1840,7 +1901,7 @@ pdf_toc_create( ctx.content->pages = emalloc(sizeof(struct PDFPage *)); ctx.content->pages[ctx.page] = pdf_page_new(); texts = &ctx.content->pages[ctx.page]->texts; - struct OutputStyle *toc_style = config_output_style_get(config->output->styles, "toc"); + struct OutputStyle *toc_style = config_output_style_get(config->output->styles, SF_TOC); struct TocEntry **toc; toc = pdf_content->toc; max_title_width = LINE_WIDTH * 0.85; @@ -1973,7 +2034,7 @@ pdf_content_create( config file */ struct OutputStyle *output_style; - output_style = config_output_style_get(config->output->styles, "subtitle"); + output_style = config_output_style_get(config->output->styles, SF_SUBTITLE); if (!output_style) { LOG_DEBUG("config_output_style_get failed."); return NULL;