lorid

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

commit 788651768a878f9ecf4c3168e4b3790d74cb3c63
parent 4c0fb05f7b569b0dbbfe31a6fb2553c39e76b888
Author: nibo <nibo@relim.de>
Date:   Wed, 26 Mar 2025 18:13:32 +0100

Remove global vars by creating a pdf context

The goal here is to be able to generate a pdf
files concurrently from multiple threads. When
using global variables the threads overwrite
each others values but with a context variable
that holds the state this shouldn't happen.

Diffstat:
Msrc/chord_diagram.c | 6++++--
Msrc/chord_diagram.h | 2+-
Msrc/chordpro.c | 10++--------
Msrc/core.h | 1+
Msrc/out_pdf.c | 1357++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/out_pdf.h | 17+++++++++++++++--
6 files changed, 718 insertions(+), 675 deletions(-)

diff --git a/src/chord_diagram.c b/src/chord_diagram.c @@ -413,6 +413,7 @@ finger_to_char(int8_t finger) static bool string_diagram_draw( + struct PDFContext *ctx, pdfio_stream_t *stream, struct StringDiagram *diagram, double x, @@ -506,7 +507,7 @@ string_diagram_draw( } pdfio_obj_t *font_obj; double name_width, centered_x; - font_obj = out_pdf_fnt_obj_get_by_name("chord-diagram-regular-font"); + font_obj = out_pdf_fnt_obj_get_by_name(ctx, "chord-diagram-regular-font"); if (!font_obj) { LOG_DEBUG("out_pdf_fnt_obj_get_by_name failed."); return false; @@ -808,6 +809,7 @@ chord_diagrams_create( bool chord_diagram_draw( + struct PDFContext *ctx, pdfio_stream_t *stream, struct ChordDiagram *diagram, double x, @@ -817,7 +819,7 @@ chord_diagram_draw( { switch (diagram->type) { case CDC_STRING: - if (!string_diagram_draw(stream, diagram->u.sd, x, y, width)) { + if (!string_diagram_draw(ctx, stream, diagram->u.sd, x, y, width)) { LOG_DEBUG("draw_string_chord_diagram failed."); return false; } diff --git a/src/chord_diagram.h b/src/chord_diagram.h @@ -14,7 +14,7 @@ enum Direction { void chord_diagram_set_base_font(bool is_base_font); struct ChordDiagram *chord_diagram_new(); void chord_diagram_free(struct ChordDiagram *d); -bool chord_diagram_draw(pdfio_stream_t *stream, struct ChordDiagram *diagram, double x, double y, double width); +bool chord_diagram_draw(struct PDFContext *ctx, pdfio_stream_t *stream, struct ChordDiagram *diagram, double x, double y, double width); enum ChordDiagramContent chord_diagram_duplicate(struct ChordDiagram *diagram, struct ChordDiagram **custom_diagrams, int custom_diagrams_len, const char *name, const char *chord_to_copy, enum Instrument instrument); struct ChordMap *chord_map_new(void); diff --git a/src/chordpro.c b/src/chordpro.c @@ -185,6 +185,7 @@ static const char *directive_type_enums[] = { }; static const char *section_type_enums[] = { + "ST_UNINITIALIZED", "ST_NEWSONG", "ST_CHORUS", "ST_VERSE", @@ -4098,14 +4099,7 @@ static struct ChoDirective * cho_directive_new(struct ChoContext *ctx) { struct ChoDirective *directive = emalloc(sizeof(struct ChoDirective)); - /*directive->dtype = -1;*/ - /*directive->stype = -1;*/ - /*directive->position = -1;*/ - /*directive->sprop = -1;*/ - /*directive->ttype = -1;*/ - /*directive->btype = -1;*/ - /*directive->meta = -1;*/ - /*directive->ctype = -1;*/ + directive->stype = ST_UNINITIALIZED; directive->style = cho_style_new_default(ctx); return directive; } diff --git a/src/core.h b/src/core.h @@ -72,6 +72,7 @@ enum ChordQualifier { }; enum SectionType { + ST_UNINITIALIZED, ST_NEWSONG, ST_CHORUS, ST_VERSE, diff --git a/src/out_pdf.c b/src/out_pdf.c @@ -8,21 +8,12 @@ #include <fontconfig/fontconfig.h> #include <grapheme.h> #include <math.h> -#include <linux/limits.h> #include "core.h" #include "out_pdf.h" #include "chordpro.h" #include "config.h" #include "chord_diagram.h" -static struct Obj **g_fonts = NULL; -static char g_cho_dirpath[PATH_MAX]; -static char g_current_font_name[200]; -static double g_current_font_size; -static int g_current_page_index; -static pdfio_file_t *g_pdf_file = NULL; -static struct Config *g_config = NULL; - static struct Obj * obj_new(void) { @@ -84,12 +75,12 @@ objs_add_obj(struct Obj ***array, struct Obj *obj) } pdfio_obj_t * -out_pdf_fnt_obj_get_by_name(const char *name) +out_pdf_fnt_obj_get_by_name(struct PDFContext *ctx, const char *name) { int i; - for (i = 0; g_fonts[i]; i++) { - if (!strcmp(g_fonts[i]->name, name)) { - return g_fonts[i]->value; + for (i = 0; ctx->fonts[i]; i++) { + if (!strcmp(ctx->fonts[i]->name, name)) { + return ctx->fonts[i]->value; } } printf("name '%s'\n", name); @@ -325,7 +316,7 @@ fontpath_find(struct Font *font, enum FontType font_type) } static bool -pdf_load_chord_diagram_fonts(void) +pdf_load_chord_diagram_fonts(struct PDFContext *ctx) { struct Obj *fnt; char *fontpath; @@ -339,7 +330,7 @@ pdf_load_chord_diagram_fonts(void) fnt = obj_new(); fnt->name = strdup("chord-diagram-regular-font"); if ((font_name = is_base_font(&font))) { - fnt->value = pdfioFileCreateFontObjFromBase(g_pdf_file, font_name); + fnt->value = pdfioFileCreateFontObjFromBase(ctx->pdf_file, font_name); chord_diagram_set_base_font(true); } else { fontpath = fontpath_find(&font, FT_TTF); @@ -350,14 +341,14 @@ pdf_load_chord_diagram_fonts(void) return false; } } - fnt->value = pdfioFileCreateFontObjFromFile(g_pdf_file, fontpath, true); + fnt->value = pdfioFileCreateFontObjFromFile(ctx->pdf_file, fontpath, true); free(fontpath); } - objs_add_obj(&g_fonts, fnt); + objs_add_obj(&ctx->fonts, fnt); fnt = obj_new(); fnt->name = strdup("chord-diagram-symbols"); - fnt->value = pdfioFileCreateFontObjFromFile(g_pdf_file, SYMBOLS_FILEPATH, true); - objs_add_obj(&g_fonts, fnt); + fnt->value = pdfioFileCreateFontObjFromFile(ctx->pdf_file, SYMBOLS_FILEPATH, true); + objs_add_obj(&ctx->fonts, fnt); return true; } @@ -374,7 +365,7 @@ font_name_is_path(const char *name) } static bool -pdf_load_fonts(struct Font **needed_fonts, struct Config *config) +pdf_load_fonts(struct PDFContext *ctx, struct Font **needed_fonts) { char *fontpath; char **fontpaths = NULL; @@ -389,7 +380,7 @@ pdf_load_fonts(struct Font **needed_fonts, struct Config *config) fnt->name = fnt_name_create(*f); index = strs_get_index_if_in(fontpaths, fontpath); if (index == -1) { - fnt->value = pdfioFileCreateFontObjFromFile(g_pdf_file, fontpath, true); + fnt->value = pdfioFileCreateFontObjFromFile(ctx->pdf_file, fontpath, true); if (!fnt->value) { LOG_DEBUG("pdfioFileCreateFontObjFromFile failed."); return false; @@ -397,21 +388,21 @@ pdf_load_fonts(struct Font **needed_fonts, struct Config *config) strs_add(&fontpaths, fontpath); util_log(NULL, 0, LOG_INFO, "Loaded font from '%s'.", (*f)->name); } else { - fnt->value = g_fonts[index]->value; + fnt->value = ctx->fonts[index]->value; } free(fontpath); // cho_font_print(*f); - objs_add_obj(&g_fonts, fnt); + objs_add_obj(&ctx->fonts, fnt); } else if ((name = is_base_font(*f))) { fnt = obj_new(); fnt->name = fnt_name_create(*f); - fnt->value = pdfioFileCreateFontObjFromBase(g_pdf_file, name); + fnt->value = pdfioFileCreateFontObjFromBase(ctx->pdf_file, name); if (!fnt->value) { LOG_DEBUG("pdfioFileCreateFontObjFromBase failed."); return false; } - objs_add_obj(&g_fonts, fnt); + objs_add_obj(&ctx->fonts, fnt); } else { fontpath = fontpath_find(*f, FT_TTF); if (fontpath) { @@ -419,7 +410,7 @@ pdf_load_fonts(struct Font **needed_fonts, struct Config *config) fnt->name = fnt_name_create(*f); index = strs_get_index_if_in(fontpaths, fontpath); if (index == -1) { - fnt->value = pdfioFileCreateFontObjFromFile(g_pdf_file, fontpath, true); + fnt->value = pdfioFileCreateFontObjFromFile(ctx->pdf_file, fontpath, true); if (!fnt->value) { LOG_DEBUG("pdfioFileCreateFontObjFromFile failed."); return false; @@ -427,10 +418,10 @@ pdf_load_fonts(struct Font **needed_fonts, struct Config *config) strs_add(&fontpaths, fontpath); util_log(NULL, 0, LOG_INFO, "Loaded font from '%s'.", fontpath); } else { - fnt->value = g_fonts[index]->value; + fnt->value = ctx->fonts[index]->value; } // cho_font_print(*f); - objs_add_obj(&g_fonts, fnt); + objs_add_obj(&ctx->fonts, fnt); free(fontpath); } else { fontpath = fontpath_find(*f, FT_OTF); @@ -439,7 +430,7 @@ pdf_load_fonts(struct Font **needed_fonts, struct Config *config) fnt->name = fnt_name_create(*f); index = strs_get_index_if_in(fontpaths, fontpath); if (index == -1) { - fnt->value = pdfioFileCreateFontObjFromFile(g_pdf_file, fontpath, true); + fnt->value = pdfioFileCreateFontObjFromFile(ctx->pdf_file, fontpath, true); if (!fnt->value) { LOG_DEBUG("pdfioFileCreateFontObjFromFile failed."); return false; @@ -447,10 +438,10 @@ pdf_load_fonts(struct Font **needed_fonts, struct Config *config) strs_add(&fontpaths, fontpath); util_log(NULL, 0, LOG_INFO, "Loaded font from '%s'.", fontpath); } else { - fnt->value = g_fonts[index]->value; + fnt->value = ctx->fonts[index]->value; } // cho_font_print(*f); - objs_add_obj(&g_fonts, fnt); + objs_add_obj(&ctx->fonts, fnt); free(fontpath); } else { util_log(NULL, 0, LOG_ERR, "Didn't find font file for following font:"); @@ -460,8 +451,8 @@ pdf_load_fonts(struct Font **needed_fonts, struct Config *config) } } } - if (config->output->diagram->show) { - if (!pdf_load_chord_diagram_fonts()) { + if (ctx->config->output->diagram->show) { + if (!pdf_load_chord_diagram_fonts(ctx)) { LOG_DEBUG("pdf_load_chord_diagram_fonts failed."); return false; } @@ -471,7 +462,7 @@ pdf_load_fonts(struct Font **needed_fonts, struct Config *config) } static char * -pdf_filename_generate_from_songs(struct ChoSong **songs) +pdf_filename_generate_from_songs(struct PDFContext *ctx, struct ChoSong **songs) { char *filename; char *normalized_title; @@ -481,7 +472,7 @@ pdf_filename_generate_from_songs(struct ChoSong **songs) if (len == 0) return NULL; if (len == 1) { - if (!cho_metadata_value(songs[0]->metadata, "title", g_config->metadata_separator, &title, &unused)) { + if (!cho_metadata_value(songs[0]->metadata, "title", ctx->config->metadata_separator, &title, &unused)) { LOG_DEBUG("cho_metadata_value failed."); return NULL; } @@ -500,7 +491,12 @@ pdf_filename_generate_from_songs(struct ChoSong **songs) } static char * -pdf_filepath_create(struct ChoSong **songs, const char *cho_filepath, const char *out) +pdf_filepath_create( + struct PDFContext *ctx, + struct ChoSong **songs, + const char *cho_filepath, + const char *out +) { char *pdf_filepath = NULL; char *pdf_filename, *tmp; @@ -509,7 +505,7 @@ pdf_filepath_create(struct ChoSong **songs, const char *cho_filepath, const char pdf_filepath = file_extension_replace_or_add(cho_filepath, "pdf"); pdf_filename = filepath_basename(pdf_filepath); } else { - pdf_filename = pdf_filename_generate_from_songs(songs); + pdf_filename = pdf_filename_generate_from_songs(ctx, songs); if (!pdf_filename) { LOG_DEBUG("pdf_filename_generate_from_songs failed."); return NULL; @@ -561,14 +557,14 @@ pdf_filepath_create(struct ChoSong **songs, const char *cho_filepath, const char } static bool -pdf_font_set(pdfio_stream_t *stream, struct Font *font) +pdf_font_set(struct PDFContext *ctx, pdfio_stream_t *stream, struct Font *font) { static int page_index = 0; char *name = fnt_name_create(font); if ( - !strcmp(name, g_current_font_name) && - font->size == g_current_font_size && - g_current_page_index == page_index + !strcmp(name, ctx->current_font_name) && + font->size == ctx->current_font_size && + ctx->current_page_index == page_index ) { free(name); return true; @@ -577,18 +573,18 @@ pdf_font_set(pdfio_stream_t *stream, struct Font *font) LOG_DEBUG("pdfioContentSetTextFont failed."); return false; } - strcpy(g_current_font_name, name); - g_current_font_size = font->size; - page_index = g_current_page_index; + strcpy(ctx->current_font_name, name); + ctx->current_font_size = font->size; + page_index = ctx->current_page_index; free(name); return true; } static double -text_width(const char *text, struct ChoStyle *style) +text_width(struct PDFContext *ctx, const char *text, struct ChoStyle *style) { char *name = fnt_name_create(style->font); - pdfio_obj_t *font_obj = out_pdf_fnt_obj_get_by_name(name); + pdfio_obj_t *font_obj = out_pdf_fnt_obj_get_by_name(ctx, name); if (!font_obj) { LOG_DEBUG("out_pdf_fnt_obj_get_by_name failed."); return -1.0; @@ -598,20 +594,20 @@ text_width(const char *text, struct ChoStyle *style) } static double -text_above_width(struct ChoLineItemAbove *above) +text_above_width(struct PDFContext *ctx, struct ChoLineItemAbove *above) { double width; if (above->is_chord) { char *name; name = cho_chord_name_generate(above->u.chord); - width = text_width(name, above->u.chord->style); + width = text_width(ctx, name, above->u.chord->style); if (width == ERROR) { LOG_DEBUG("text_width failed."); return ERROR; } free(name); } else { - width = text_width(above->u.annot->text, above->u.annot->style); + width = text_width(ctx, above->u.annot->text, above->u.annot->style); if (width == ERROR) { LOG_DEBUG("text_width failed."); return ERROR; @@ -634,6 +630,7 @@ find_whitespace(const char *str, size_t start) static int text_find_fitting( + struct PDFContext *ctx, const char *str, struct ChoStyle *style, double x, @@ -653,7 +650,7 @@ text_find_fitting( return -1; } tmp[i] = 0; - width = text_width((const char *)&tmp, style); + width = text_width(ctx, (const char *)&tmp, style); if (width == ERROR) { LOG_DEBUG("text_width failed."); return -1; @@ -749,11 +746,11 @@ is_purest_white(struct RGBColor *color) } static bool -pdf_text_show(pdfio_stream_t *stream, struct PDFText *text) +pdf_text_show(struct PDFContext *ctx, pdfio_stream_t *stream, struct PDFText *text) { double red, green, blue; bool unicode; - if (!pdf_font_set(stream, text->style->font)) { + if (!pdf_font_set(ctx, stream, text->style->font)) { LOG_DEBUG("pdf_font_set failed."); return false; } @@ -814,7 +811,13 @@ pdf_text_show(pdfio_stream_t *stream, struct PDFText *text) LOG_DEBUG("pdfioContentSetFillColorRGB failed."); return false; } - if (!pdfioContentPathRect(stream, text->x - 2.0, text->y - 2.0, text->width + 4.0, text->style->font->size * 0.8 + 4.0)) { + if (!pdfioContentPathRect( + stream, + text->x - 2.0, + text->y - 2.0, + text->width + 4.0, + text->style->font->size * 0.8 + 4.0 + )) { LOG_DEBUG("pdfioContentPathRect failed."); return false; } @@ -841,10 +844,10 @@ annot_page_link_add( pdfio_array_t *destination; rect.x1 = MARGIN_HORIZONTAL; rect.x2 = MARGIN_HORIZONTAL + LINE_WIDTH; - rect.y1 = ctx->y - 2.0; - rect.y2 = ctx->y + (8.0 + font_size) * line_count - font_size * 0.8; + rect.y1 = ctx->t_ctx.y - 2.0; + rect.y2 = ctx->t_ctx.y + (8.0 + font_size) * line_count - font_size * 0.8; page_index = entry->page_index + toc_page_count; - annot = pdfioDictCreate(g_pdf_file); + annot = pdfioDictCreate(ctx->pdf_file); if (!pdfioDictSetName(annot, "Subtype", "Link")) { LOG_DEBUG("pdfioDictSetName failed."); return false; @@ -853,7 +856,7 @@ annot_page_link_add( LOG_DEBUG("pdfioDictSetRect failed."); return false; } - destination = pdfioArrayCreate(g_pdf_file); + destination = pdfioArrayCreate(ctx->pdf_file); if (!pdfioArrayAppendNumber(destination, page_index)) { LOG_DEBUG("pdfioArrayAppendNumber failed."); return false; @@ -872,7 +875,7 @@ annot_page_link_add( LOG_DEBUG("pdfioDictSetArray failed."); return false; } - if (!pdfioArrayAppendDict(ctx->content->pages[ctx->page]->annots, annot)) { + if (!pdfioArrayAppendDict(ctx->t_ctx.content->pages[ctx->t_ctx.page]->annots, annot)) { LOG_DEBUG("pdfioArrayAppendDict failed."); return false; } @@ -880,15 +883,20 @@ annot_page_link_add( } static bool -annot_url_link_add(struct PDFContext *ctx, struct ChoStyle *style, double width) +annot_url_link_add( + struct PDFContext *ctx, + struct PDFContentContext *c_ctx, + struct ChoStyle *style, + double width +) { pdfio_rect_t rect; pdfio_dict_t *annot, *action; - rect.x1 = ctx->x; - rect.x2 = ctx->x + width; - rect.y1 = ctx->y - 2.0; - rect.y2 = ctx->y + style->font->size * 0.8; - annot = pdfioDictCreate(g_pdf_file); + rect.x1 = c_ctx->x; + rect.x2 = c_ctx->x + width; + rect.y1 = c_ctx->y - 2.0; + rect.y2 = c_ctx->y + style->font->size * 0.8; + annot = pdfioDictCreate(ctx->pdf_file); if (!pdfioDictSetName(annot, "Subtype", "Link")) { LOG_DEBUG("pdfioDictSetName failed."); return false; @@ -897,7 +905,7 @@ annot_url_link_add(struct PDFContext *ctx, struct ChoStyle *style, double width) LOG_DEBUG("pdfioDictSetRect failed."); return false; } - action = pdfioDictCreate(g_pdf_file); + action = pdfioDictCreate(ctx->pdf_file); if (!pdfioDictSetName(action, "S", "URI")) { LOG_DEBUG("pdfioDictSetName failed."); return false; @@ -910,7 +918,7 @@ annot_url_link_add(struct PDFContext *ctx, struct ChoStyle *style, double width) LOG_DEBUG("pdfioDictSetDict failed."); return false; } - if (!pdfioArrayAppendDict(ctx->content->pages[ctx->page]->annots, annot)) { + if (!pdfioArrayAppendDict(c_ctx->content->pages[c_ctx->page]->annots, annot)) { LOG_DEBUG("pdfioArrayAppendDict failed."); return false; } @@ -918,18 +926,18 @@ annot_url_link_add(struct PDFContext *ctx, struct ChoStyle *style, double width) } static bool -pdf_set_title(pdfio_file_t *pdf, struct ChoSong **songs) +pdf_set_title(struct PDFContext *ctx, struct ChoSong **songs) { // INFO: Set pdf title only if a single song exist if (songs[0] && !songs[1]) { char *title; struct ChoStyle *unused; - if (!cho_metadata_value(songs[0]->metadata, "title", g_config->metadata_separator, &title, &unused)) { + if (!cho_metadata_value(songs[0]->metadata, "title", ctx->config->metadata_separator, &title, &unused)) { LOG_DEBUG("cho_metadata_value failed."); return false; } if (title) { - pdfioFileSetTitle(pdf, title); + pdfioFileSetTitle(ctx->pdf_file, title); free(title); return true; } @@ -940,17 +948,17 @@ pdf_set_title(pdfio_file_t *pdf, struct ChoSong **songs) static pdfio_stream_t * pdf_page_create( - pdfio_file_t *pdf, + struct PDFContext *ctx, struct PDFImage **imgs, pdfio_array_t *annots ) { pdfio_dict_t *page_dict; pdfio_stream_t *page_stream; - pdfio_array_t *color_array = pdfioArrayCreateColorFromStandard(pdf, 3, PDFIO_CS_ADOBE); + pdfio_array_t *color_array = pdfioArrayCreateColorFromStandard(ctx->pdf_file, 3, PDFIO_CS_ADOBE); struct Obj **f; struct PDFImage **i; - page_dict = pdfioDictCreate(pdf); + page_dict = pdfioDictCreate(ctx->pdf_file); if (!pdfioPageDictAddColorSpace(page_dict, "rgbcolorspace", color_array)) { LOG_DEBUG("pdfioPageDictAddColorSpace failed."); return NULL; @@ -967,13 +975,13 @@ pdf_page_create( } } } - for (f = g_fonts; *f; f++) { + for (f = ctx->fonts; *f; f++) { if (!pdfioPageDictAddFont(page_dict, (*f)->name, (*f)->value)) { LOG_DEBUG("pdfioPageDictAddFont failed."); return NULL; } } - page_stream = pdfioFileCreatePage(pdf, page_dict); + page_stream = pdfioFileCreatePage(ctx->pdf_file, page_dict); if (!pdfioContentSetFillColorSpace(page_stream, "rgbcolorspace")) { LOG_DEBUG("pdfioContentSetFillColorSpace failed."); return NULL; @@ -1026,7 +1034,7 @@ image_height(struct ChoImage *image, pdfio_obj_t *obj) } static char * -image_name(struct ChoImage *image) +image_name(struct PDFContext *ctx, struct ChoImage *image) { char tmp[PATH_MAX]; char *image_path; @@ -1034,7 +1042,7 @@ image_name(struct ChoImage *image) if (strchr(image->src, '/')) { image_path = image->src; } else { - strcpy((char *)&tmp, g_cho_dirpath); + strcpy((char *)&tmp, ctx->cho_dirpath); strcat((char *)&tmp, "/"); strcat((char *)&tmp, image->src); image_path = (char *)&tmp; @@ -1050,7 +1058,7 @@ image_name(struct ChoImage *image) } static bool -pdf_load_images(struct Obj ***images, pdfio_file_t *file, struct ChoSong **songs) +pdf_load_images(struct PDFContext *ctx, struct Obj ***images, struct ChoSong **songs) { struct ChoSong **s; struct ChoSection **se; @@ -1066,10 +1074,10 @@ pdf_load_images(struct Obj ***images, pdfio_file_t *file, struct ChoSong **songs for (it = (*li)->items; *it; it++) { if (!(*it)->is_text) { memset(filepath, 0, PATH_MAX); - strcpy((char *)&filepath, g_cho_dirpath); + strcpy((char *)&filepath, ctx->cho_dirpath); strcat((char *)&filepath, "/"); strcat((char *)&filepath, (*it)->u.image->src); - name = image_name((*it)->u.image); + name = image_name(ctx, (*it)->u.image); if (!name) { LOG_DEBUG("image_name failed."); return false; @@ -1083,7 +1091,7 @@ pdf_load_images(struct Obj ***images, pdfio_file_t *file, struct ChoSong **songs } else { image_filepath = (char *)&filepath; } - (*images)[i]->value = pdfioFileCreateImageObjFromFile(file, image_filepath, true); + (*images)[i]->value = pdfioFileCreateImageObjFromFile(ctx->pdf_file, image_filepath, true); if (!(*images)[i]->value) { LOG_DEBUG("pdfioFileCreateImageObjFromFile failed."); return false; @@ -1123,6 +1131,7 @@ pdf_get_chords(struct ChoSong *song, struct ChoChord ***chords) static double line_width_until_text_above( + struct PDFContext *ctx, struct ChoLineItem **items, struct ChoLineItemAbove *above, struct Obj **img_objs, @@ -1161,7 +1170,7 @@ line_width_until_text_above( if (items[i]->is_text) { text = items[i]->u.text; name = fnt_name_create(text->style->font); - font_obj = out_pdf_fnt_obj_get_by_name(name); + font_obj = out_pdf_fnt_obj_get_by_name(ctx, name); if (!font_obj) { LOG_DEBUG("out_pdf_fnt_obj_get_by_name failed."); return ERROR; @@ -1176,7 +1185,7 @@ line_width_until_text_above( } free(name); } else { - name = image_name(items[i]->u.image); + name = image_name(ctx, items[i]->u.image); if (!name) { LOG_DEBUG("image_name failed."); return ERROR; @@ -1247,13 +1256,13 @@ toc_entry_free(struct TocEntry *entry) } static struct PDFPage * -pdf_page_new(void) +pdf_page_new(struct PDFContext *ctx) { struct PDFPage *page = emalloc(sizeof(struct PDFPage)); page->texts = NULL; page->images = NULL; page->diagrams = NULL; - page->annots = pdfioArrayCreate(g_pdf_file); + page->annots = pdfioArrayCreate(ctx->pdf_file); return page; } @@ -1288,21 +1297,21 @@ pdf_page_free(struct PDFPage *page) } static void -pdf_context_init(struct PDFContext *ctx) -{ - ctx->content = NULL; - ctx->x = MARGIN_HORIZONTAL; - ctx->y = MEDIABOX_HEIGHT - MARGIN_TOP; - ctx->text = 0; - ctx->image = 0; - ctx->diagram = 0; - ctx->page = 0; - ctx->toc_entry = 0; - ctx->spaces = NULL; - ctx->biggest_font_size = 0.0; - ctx->consumed_lyrics = 0; - ctx->prev_added_space = 0.0; - ctx->margin_bottom = MARGIN_BOTTOM; +pdf_content_context_init(struct PDFContentContext *c_ctx) +{ + c_ctx->content = NULL; + c_ctx->x = MARGIN_HORIZONTAL; + c_ctx->y = MEDIABOX_HEIGHT - MARGIN_TOP; + c_ctx->text = 0; + c_ctx->image = 0; + c_ctx->diagram = 0; + c_ctx->page = 0; + c_ctx->toc_entry = 0; + c_ctx->spaces = NULL; + c_ctx->biggest_font_size = 0.0; + c_ctx->consumed_lyrics = 0; + c_ctx->prev_added_space = 0.0; + c_ctx->margin_bottom = MARGIN_BOTTOM; } static struct PDFContent * @@ -1350,6 +1359,7 @@ spaces_free(struct SpaceNeeded **spaces) static bool calc_space_between_text_above( + struct PDFContext *ctx, struct ChoLineItem **items, struct ChoLineItemAbove **text_above, struct Obj **img_objs, @@ -1372,18 +1382,18 @@ calc_space_between_text_above( double width_until_cur; double width_until_prev; double prev_width; - width_until_cur = line_width_until_text_above(items, text_above[i], img_objs, NULL); + width_until_cur = line_width_until_text_above(ctx, items, text_above[i], img_objs, NULL); if (width_until_cur == ERROR) { LOG_DEBUG("line_width_until_text_above failed."); return false; } i--; - width_until_prev = line_width_until_text_above(items, text_above[i], img_objs, &space); + width_until_prev = line_width_until_text_above(ctx, items, text_above[i], img_objs, &space); if (width_until_prev == ERROR) { LOG_DEBUG("line_width_until_text_above failed."); return false; } - prev_width = text_above_width(text_above[i]); + prev_width = text_above_width(ctx, text_above[i]); if (prev_width == ERROR) { LOG_DEBUG("text_above_width failed."); return false; @@ -1406,11 +1416,17 @@ calc_space_between_text_above( } static double -item_width(struct ChoLineItem *item, int i, struct SpaceNeeded **spaces, struct Obj **img_objs) +item_width( + struct PDFContext *ctx, + struct ChoLineItem *item, + int i, + struct SpaceNeeded **spaces, + struct Obj **img_objs +) { double width; if (item->is_text) { - width = text_width(item->u.text->text, item->u.text->style); + width = text_width(ctx, item->u.text->text, item->u.text->style); if (width == ERROR) { LOG_DEBUG("text_width failed."); return ERROR; @@ -1426,7 +1442,7 @@ item_width(struct ChoLineItem *item, int i, struct SpaceNeeded **spaces, struct } else { char *name; pdfio_obj_t *obj; - name = image_name(item->u.image); + name = image_name(ctx, item->u.image); if (!name) { LOG_DEBUG("image_name failed."); return ERROR; @@ -1444,6 +1460,7 @@ item_width(struct ChoLineItem *item, int i, struct SpaceNeeded **spaces, struct static struct CharPosition * items_find_position_to_break_line( + struct PDFContext *ctx, struct ChoLineItem **items, struct SpaceNeeded **spaces, struct Obj **img_objs @@ -1457,7 +1474,7 @@ items_find_position_to_break_line( struct ChoLineItem **it = items; int i; for (i = 0; it[i]; i++) { - d = item_width(it[i], i, spaces, img_objs); + d = item_width(ctx, it[i], i, spaces, img_objs); if (d == ERROR) { LOG_DEBUG("item_width failed."); return NULL; @@ -1466,6 +1483,7 @@ items_find_position_to_break_line( if (it[i]->is_text) { pos->line_item_index = i; pos->text_index = text_find_fitting( + ctx, it[i]->u.text->text, it[i]->u.text->style, width, @@ -1488,7 +1506,12 @@ items_find_position_to_break_line( } static double -images_find_biggest_height(struct ChoLineItem **left_items, int line_item_index, struct Obj **img_objs) +images_find_biggest_height( + struct PDFContext *ctx, + struct ChoLineItem **left_items, + int line_item_index, + struct Obj **img_objs +) { struct ChoLineItem **it; char *name; @@ -1502,7 +1525,7 @@ images_find_biggest_height(struct ChoLineItem **left_items, int line_item_index, } for (it = left_items; *it && i <= end; it++, i++) { if (!(*it)->is_text) { - name = image_name((*it)->u.image); + name = image_name(ctx, (*it)->u.image); if (!name) { LOG_DEBUG("image_name failed."); return ERROR; @@ -1523,7 +1546,11 @@ images_find_biggest_height(struct ChoLineItem **left_items, int line_item_index, } static int -text_above_find_index_to_break_line(struct ChoLineItem **items, struct ChoLineItemAbove **text_above, struct CharPosition *pos) +text_above_find_index_to_break_line( + struct ChoLineItem **items, + struct ChoLineItemAbove **text_above, + struct CharPosition *pos +) { int position = 0; int i, k; @@ -1569,112 +1596,6 @@ text_above_update_positions(struct ChoLineItemAbove **aboves, size_t consumed_ly } } -static bool -pdf_texts_add_lyrics( - struct ChoLineItem *item, - struct PDFContext *ctx, - int i -) -{ - struct PDFText ***texts; - struct SpaceNeeded **sp; - double width; - int t = 0; - int c; - texts = &ctx->content->pages[ctx->page]->texts; - *texts = erealloc(*texts, (ctx->text+1) * sizeof(struct PDFText *)); - (*texts)[ctx->text] = pdf_text_new(); - if (!ctx->spaces) { - (*texts)[ctx->text]->text = strdup(item->u.text->text); - (*texts)[ctx->text]->style = cho_style_copy(item->u.text->style); - (*texts)[ctx->text]->x = ctx->x; - (*texts)[ctx->text]->y = ctx->y; - width = text_width(item->u.text->text, item->u.text->style); - if (width == ERROR) { - LOG_DEBUG("text_width failed."); - return false; - } - (*texts)[ctx->text]->width = width; - if (item->u.text->style->href) { - if (!annot_url_link_add(ctx, item->u.text->style, width)) { - LOG_DEBUG("annot_url_link_add failed."); - return false; - } - } - ctx->x += width; - if ((*texts)[ctx->text]->style->font->size > ctx->biggest_font_size) { - ctx->biggest_font_size = (*texts)[ctx->text]->style->font->size; - } - ctx->consumed_lyrics += strlen((*texts)[ctx->text]->text); - ctx->text++; - return true; - } - for (c = 0; item->u.text->text[c]; c++) { - (*texts)[ctx->text]->text = erealloc((*texts)[ctx->text]->text, (t+1) * sizeof(char)); - (*texts)[ctx->text]->text[t] = item->u.text->text[c]; - t++; - for (sp = ctx->spaces; *sp; sp++) { - if ((*sp)->line_item_index == i && (*sp)->text_index == c) { - size_t len = grapheme_next_character_break_utf8(&item->u.text->text[c], 10); - size_t i; - for (i = 0; i<len-1; i++, t++) { - c++; - (*texts)[ctx->text]->text = erealloc((*texts)[ctx->text]->text, (t+1) * sizeof(char)); - (*texts)[ctx->text]->text[t] = item->u.text->text[c]; - } - (*texts)[ctx->text]->text = erealloc((*texts)[ctx->text]->text, (t+1) * sizeof(char)); - (*texts)[ctx->text]->text[t] = 0; - (*texts)[ctx->text]->style = cho_style_copy(item->u.text->style); - (*texts)[ctx->text]->x = ctx->x; - (*texts)[ctx->text]->y = ctx->y; - width = text_width((*texts)[ctx->text]->text, item->u.text->style); - if (width == ERROR) { - LOG_DEBUG("text_width failed."); - return false; - } - (*texts)[ctx->text]->width = width; - if (item->u.text->style->href) { - if (!annot_url_link_add(ctx, item->u.text->style, width)) { - LOG_DEBUG("annot_url_link_add failed."); - return false; - } - } - ctx->x += width; - ctx->x += (*sp)->amount; - t = 0; - ctx->consumed_lyrics += strlen((*texts)[ctx->text]->text); - ctx->text++; - *texts = erealloc(*texts, (ctx->text+1) * sizeof(struct PDFText *)); - (*texts)[ctx->text] = pdf_text_new(); - } - } - } - (*texts)[ctx->text]->text = erealloc((*texts)[ctx->text]->text, (t+1) * sizeof(char)); - (*texts)[ctx->text]->text[t] = 0; - (*texts)[ctx->text]->style = cho_style_copy(item->u.text->style); - (*texts)[ctx->text]->x = ctx->x; - (*texts)[ctx->text]->y = ctx->y; - width = text_width((*texts)[ctx->text]->text, item->u.text->style); - if (width == ERROR) { - LOG_DEBUG("text_width failed."); - return false; - } - (*texts)[ctx->text]->width = width; - if (item->u.text->style->href) { - if (!annot_url_link_add(ctx, item->u.text->style, width)) { - LOG_DEBUG("annot_url_link_add failed."); - return false; - } - } - ctx->x += width; - if ((*texts)[ctx->text]->style->font->size > ctx->biggest_font_size) { - ctx->biggest_font_size = (*texts)[ctx->text]->style->font->size; - } - ctx->consumed_lyrics += strlen((*texts)[ctx->text]->text); - ctx->text++; - return true; -} - static double calc_x(double width, enum Alignment align) { @@ -1795,7 +1716,11 @@ numeral_system_number_to_str(enum NumeralSystem system, int n) } static bool -pdf_page_add_page_no(struct PDFContext *ctx, enum NumeralSystem numeral_system) +pdf_page_add_page_no( + struct PDFContext *ctx, + struct PDFContentContext *c_ctx, + enum NumeralSystem numeral_system +) { struct PDFText ***texts; struct ChoStyle *style; @@ -1804,25 +1729,25 @@ pdf_page_add_page_no(struct PDFContext *ctx, enum NumeralSystem numeral_system) style = cho_style_new(); style->font->name = strdup(DEFAULT_FONT); - texts = &ctx->content->pages[ctx->page]->texts; - page_no = numeral_system_number_to_str(numeral_system, ctx->page+1); + texts = &c_ctx->content->pages[c_ctx->page]->texts; + page_no = numeral_system_number_to_str(numeral_system, c_ctx->page+1); if (!page_no) { LOG_DEBUG("numeral_system_number_to_str failed."); return false; } - width = text_width(page_no, style); + width = text_width(ctx, page_no, style); if (width == ERROR) { LOG_DEBUG("text_width failed."); return false; } - *texts = erealloc(*texts, (ctx->text+1) * sizeof(struct PDFText *)); - (*texts)[ctx->text] = pdf_text_new(); - (*texts)[ctx->text]->text = strdup(page_no); - (*texts)[ctx->text]->style = style; - (*texts)[ctx->text]->x = MEDIABOX_WIDTH - MARGIN_HORIZONTAL / 2 - width; - (*texts)[ctx->text]->y = MARGIN_BOTTOM / 2; - (*texts)[ctx->text]->width = width; - switch (g_config->output->page_no->align) { + *texts = erealloc(*texts, (c_ctx->text+1) * sizeof(struct PDFText *)); + (*texts)[c_ctx->text] = pdf_text_new(); + (*texts)[c_ctx->text]->text = strdup(page_no); + (*texts)[c_ctx->text]->style = style; + (*texts)[c_ctx->text]->x = MEDIABOX_WIDTH - MARGIN_HORIZONTAL / 2 - width; + (*texts)[c_ctx->text]->y = MARGIN_BOTTOM / 2; + (*texts)[c_ctx->text]->width = width; + switch (ctx->config->output->page_no->align) { case A_LEFT: x = MARGIN_HORIZONTAL / 2; break; @@ -1833,41 +1758,45 @@ pdf_page_add_page_no(struct PDFContext *ctx, enum NumeralSystem numeral_system) x = MEDIABOX_WIDTH - MARGIN_HORIZONTAL / 2 - width; break; default: - util_log(NULL, 0, LOG_ERR, "Invalid Alignment enum value '%d'.", g_config->output->page_no->align); + util_log(NULL, 0, LOG_ERR, "Invalid Alignment enum value '%d'.", ctx->config->output->page_no->align); return false; } - (*texts)[ctx->text]->x = x; - ctx->text++; + (*texts)[c_ctx->text]->x = x; + c_ctx->text++; return true; } static bool -pdf_page_close_then_add(struct PDFContext *ctx, enum NumeralSystem numeral_system) +pdf_page_close_then_add( + struct PDFContext *ctx, + struct PDFContentContext *c_ctx, + enum NumeralSystem numeral_system +) { - ctx->content->pages[ctx->page]->texts = erealloc( - ctx->content->pages[ctx->page]->texts, - (ctx->text+1) * sizeof(struct PDFText *) + c_ctx->content->pages[c_ctx->page]->texts = erealloc( + c_ctx->content->pages[c_ctx->page]->texts, + (c_ctx->text+1) * sizeof(struct PDFText *) ); - ctx->content->pages[ctx->page]->texts[ctx->text] = NULL; - ctx->content->pages[ctx->page]->images = erealloc( - ctx->content->pages[ctx->page]->images, - (ctx->image+1) * sizeof(struct PDFImage *) + c_ctx->content->pages[c_ctx->page]->texts[c_ctx->text] = NULL; + c_ctx->content->pages[c_ctx->page]->images = erealloc( + c_ctx->content->pages[c_ctx->page]->images, + (c_ctx->image+1) * sizeof(struct PDFImage *) ); - ctx->content->pages[ctx->page]->images[ctx->image] = NULL; - ctx->content->pages[ctx->page]->diagrams = erealloc( - ctx->content->pages[ctx->page]->diagrams, - (ctx->diagram+1) * sizeof(struct ChordDiagram *) + c_ctx->content->pages[c_ctx->page]->images[c_ctx->image] = NULL; + c_ctx->content->pages[c_ctx->page]->diagrams = erealloc( + c_ctx->content->pages[c_ctx->page]->diagrams, + (c_ctx->diagram+1) * sizeof(struct ChordDiagram *) ); - ctx->content->pages[ctx->page]->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(); - ctx->y = MEDIABOX_HEIGHT - MARGIN_TOP; - if (g_config->output->page_no->show) { - if (!pdf_page_add_page_no(ctx, numeral_system)) { + c_ctx->content->pages[c_ctx->page]->diagrams[c_ctx->diagram] = NULL; + c_ctx->text = 0; + c_ctx->image = 0; + c_ctx->diagram = 0; + c_ctx->page++; + c_ctx->content->pages = erealloc(c_ctx->content->pages, (c_ctx->page+1) * sizeof(struct PDFPage *)); + c_ctx->content->pages[c_ctx->page] = pdf_page_new(ctx); + c_ctx->y = MEDIABOX_HEIGHT - MARGIN_TOP; + if (ctx->config->output->page_no->show) { + if (!pdf_page_add_page_no(ctx, c_ctx, numeral_system)) { LOG_DEBUG("pdf_page_add_page_no failed."); return false; } @@ -1875,121 +1804,9 @@ pdf_page_close_then_add(struct PDFContext *ctx, enum NumeralSystem numeral_syste return true; } -static bool -pdf_texts_add_text( - struct PDFContext *ctx, - const char *text, - struct ChoStyle *style, - enum Alignment align, - enum NumeralSystem numeral_system -) -{ - struct PDFText ***texts; - char str[strlen(text)+1]; - double width; - int index; - strcpy((char *)&str, text); - texts = &ctx->content->pages[ctx->page]->texts; - width = text_width(text, style); - if (width == ERROR) { - LOG_DEBUG("text_width failed."); - return false; - } - if (width > LINE_WIDTH) { - char *t = (char *)&str; - while (width > LINE_WIDTH) { - if (ctx->y < ctx->margin_bottom) { - if (!pdf_page_close_then_add(ctx, numeral_system)) { - LOG_DEBUG("pdf_page_close_then_add failed."); - return false; - } - texts = &ctx->content->pages[ctx->page]->texts; - } - index = text_find_fitting(t, style, 0.0, LINE_WIDTH); - if (index == EMPTY_INT) { - LOG_DEBUG("text_find_fitting failed."); - return false; - } - t[index] = 0; - width = text_width(t, style); - if (width == ERROR) { - LOG_DEBUG("text_width failed."); - return false; - } - ctx->x = calc_x(width, align); - *texts = erealloc(*texts, (ctx->text+1) * sizeof(struct PDFText *)); - (*texts)[ctx->text] = pdf_text_new(); - (*texts)[ctx->text]->text = strdup(t); - (*texts)[ctx->text]->style = cho_style_copy(style); - (*texts)[ctx->text]->x = ctx->x; - (*texts)[ctx->text]->y = ctx->y; - (*texts)[ctx->text]->width = width; - if (style->href) { - if (!annot_url_link_add(ctx, style, width)) { - LOG_DEBUG("annot_url_link_add failed."); - return false; - } - } - ctx->text++; - ctx->y -= 8.0 + style->font->size; - t += index+1; - width = text_width(t, style); - if (width == ERROR) { - LOG_DEBUG("text_width failed."); - return false; - } - } - width = text_width(t, style); - if (width == ERROR) { - LOG_DEBUG("text_width failed."); - return false; - } - ctx->x = calc_x(width, align); - *texts = erealloc(*texts, (ctx->text+1) * sizeof(struct PDFText *)); - (*texts)[ctx->text] = pdf_text_new(); - (*texts)[ctx->text]->text = strdup(t); - (*texts)[ctx->text]->style = cho_style_copy(style); - (*texts)[ctx->text]->x = ctx->x; - (*texts)[ctx->text]->y = ctx->y; - (*texts)[ctx->text]->width = width; - if (style->href) { - if (!annot_url_link_add(ctx, style, width)) { - LOG_DEBUG("annot_url_link_add failed."); - return false; - } - } - ctx->text++; - ctx->y -= 8.0 + style->font->size; - } else { - if (ctx->y < ctx->margin_bottom) { - if (!pdf_page_close_then_add(ctx, numeral_system)) { - LOG_DEBUG("pdf_page_close_then_add failed."); - return false; - } - texts = &ctx->content->pages[ctx->page]->texts; - } - ctx->x = calc_x(width, align); - *texts = erealloc(*texts, (ctx->text+1) * sizeof(struct PDFText *)); - (*texts)[ctx->text] = pdf_text_new(); - (*texts)[ctx->text]->text = strdup(text); - (*texts)[ctx->text]->style = cho_style_copy(style); - (*texts)[ctx->text]->x = ctx->x; - (*texts)[ctx->text]->y = ctx->y; - (*texts)[ctx->text]->width = width; - if (style->href) { - if (!annot_url_link_add(ctx, style, width)) { - LOG_DEBUG("annot_url_link_add failed."); - return false; - } - } - ctx->text++; - ctx->y -= 8.0 + style->font->size; - } - return true; -} - static int pdf_toc_page_count( + struct PDFContext *ctx, struct TocEntry **entries, struct ChoStyle *style, double max_title_width @@ -2007,7 +1824,7 @@ pdf_toc_page_count( int index; char tmp[strlen((*toc)->title)+1]; strcpy((char *)&tmp, (*toc)->title); - width = text_width((*toc)->title, style); + width = text_width(ctx, (*toc)->title, style); if (width == ERROR) { LOG_DEBUG("text_width failed."); return -1; @@ -2016,7 +1833,7 @@ pdf_toc_page_count( if (width > max_title_width) { char *t = (char *)&tmp; while (width > max_title_width) { - index = text_find_fitting(t, style, MARGIN_HORIZONTAL, max_title_width); + index = text_find_fitting(ctx, t, style, MARGIN_HORIZONTAL, max_title_width); if (index == EMPTY_INT) { LOG_DEBUG("text_find_fitting failed."); return -1; @@ -2024,7 +1841,7 @@ pdf_toc_page_count( t[index] = 0; y -= 8.0 + style->font->size; t += index + 1; - width = text_width(t, style); + width = text_width(ctx, t, style); if (width == ERROR) { LOG_DEBUG("text_width failed."); return -1; @@ -2065,14 +1882,14 @@ pdf_texts_add_toc_entry( ) { struct PDFText ***texts; - texts = &ctx->content->pages[ctx->page]->texts; + texts = &ctx->t_ctx.content->pages[ctx->t_ctx.page]->texts; double width, page_no_x, end_of_title_x, width_between_title_and_page_no, available_dots_width; double page_no_width, dots_width; int index, line_count; char tmp[strlen(entry->title)+1]; char page_no[11+1]; strcpy((char *)&tmp, entry->title); - width = text_width(entry->title, style); + width = text_width(ctx, entry->title, style); if (width == ERROR) { LOG_DEBUG("text_width failed."); return false; @@ -2081,59 +1898,59 @@ pdf_texts_add_toc_entry( char *t = (char *)&tmp; line_count = 0; while (width+MARGIN_HORIZONTAL > max_song_title_width) { - if (ctx->y < MARGIN_BOTTOM) { - if (!pdf_page_close_then_add(ctx, NUS_ROMAN)) { + if (ctx->t_ctx.y < MARGIN_BOTTOM) { + if (!pdf_page_close_then_add(ctx, &ctx->t_ctx, NUS_ROMAN)) { LOG_DEBUG("pdf_page_close_then_add failed."); return false; } - texts = &ctx->content->pages[ctx->page]->texts; + texts = &ctx->t_ctx.content->pages[ctx->t_ctx.page]->texts; } - index = text_find_fitting(t, style, MARGIN_HORIZONTAL, max_song_title_width); + index = text_find_fitting(ctx, t, style, MARGIN_HORIZONTAL, max_song_title_width); if (index == EMPTY_INT) { LOG_DEBUG("text_find_fitting failed."); return false; } t[index] = 0; - *texts = erealloc(*texts, (ctx->text+1) * sizeof(struct PDFText *)); - (*texts)[ctx->text] = pdf_text_new(); - (*texts)[ctx->text]->text = strdup(t); - (*texts)[ctx->text]->style = cho_style_copy(style); - (*texts)[ctx->text]->x = MARGIN_HORIZONTAL; - (*texts)[ctx->text]->y = ctx->y; - ctx->y -= 8.0 + style->font->size; + *texts = erealloc(*texts, (ctx->t_ctx.text+1) * sizeof(struct PDFText *)); + (*texts)[ctx->t_ctx.text] = pdf_text_new(); + (*texts)[ctx->t_ctx.text]->text = strdup(t); + (*texts)[ctx->t_ctx.text]->style = cho_style_copy(style); + (*texts)[ctx->t_ctx.text]->x = MARGIN_HORIZONTAL; + (*texts)[ctx->t_ctx.text]->y = ctx->t_ctx.y; + ctx->t_ctx.y -= 8.0 + style->font->size; line_count++; - width = text_width(t, style); + width = text_width(ctx, t, style); if (width == ERROR) { LOG_DEBUG("text_width failed."); return false; } - (*texts)[ctx->text]->width = width; + (*texts)[ctx->t_ctx.text]->width = width; t += index + 1; - width = text_width(t, style); + width = text_width(ctx, t, style); if (width == ERROR) { LOG_DEBUG("text_width failed."); return false; } - ctx->text++; + ctx->t_ctx.text++; } - if (ctx->y < MARGIN_BOTTOM) { - if (!pdf_page_close_then_add(ctx, NUS_ROMAN)) { + if (ctx->t_ctx.y < MARGIN_BOTTOM) { + if (!pdf_page_close_then_add(ctx, &ctx->t_ctx, NUS_ROMAN)) { LOG_DEBUG("pdf_page_close_then_add failed."); return false; } - texts = &ctx->content->pages[ctx->page]->texts; + texts = &ctx->t_ctx.content->pages[ctx->t_ctx.page]->texts; } end_of_title_x = width; - *texts = erealloc(*texts, (ctx->text+1) * sizeof(struct PDFText *)); - (*texts)[ctx->text] = pdf_text_new(); - (*texts)[ctx->text]->text = strdup(t); - (*texts)[ctx->text]->style = cho_style_copy(style); - (*texts)[ctx->text]->x = MARGIN_HORIZONTAL; - (*texts)[ctx->text]->y = ctx->y; - (*texts)[ctx->text]->width = width; - ctx->text++; + *texts = erealloc(*texts, (ctx->t_ctx.text+1) * sizeof(struct PDFText *)); + (*texts)[ctx->t_ctx.text] = pdf_text_new(); + (*texts)[ctx->t_ctx.text]->text = strdup(t); + (*texts)[ctx->t_ctx.text]->style = cho_style_copy(style); + (*texts)[ctx->t_ctx.text]->x = MARGIN_HORIZONTAL; + (*texts)[ctx->t_ctx.text]->y = ctx->t_ctx.y; + (*texts)[ctx->t_ctx.text]->width = width; + ctx->t_ctx.text++; sprintf((char *)&page_no, "%d", entry->page_index+1); - width = text_width(page_no, style); + width = text_width(ctx, page_no, style); if (width == ERROR) { LOG_DEBUG("text_width failed."); return false; @@ -2148,52 +1965,52 @@ pdf_texts_add_toc_entry( return false; } - *texts = erealloc(*texts, (ctx->text+1) * sizeof(struct PDFText *)); - (*texts)[ctx->text] = pdf_text_new(); - (*texts)[ctx->text]->text = strdup(dots); - (*texts)[ctx->text]->style = cho_style_copy(style); - (*texts)[ctx->text]->x = MARGIN_HORIZONTAL + end_of_title_x + TOC_DOTS_GAP_WIDTH; - (*texts)[ctx->text]->y = ctx->y; - ctx->text++; - - *texts = erealloc(*texts, (ctx->text+1) * sizeof(struct PDFText *)); - (*texts)[ctx->text] = pdf_text_new(); - (*texts)[ctx->text]->text = strdup(page_no); - (*texts)[ctx->text]->style = cho_style_copy(style); - (*texts)[ctx->text]->x = page_no_x; - (*texts)[ctx->text]->y = ctx->y; - (*texts)[ctx->text]->width = width; + *texts = erealloc(*texts, (ctx->t_ctx.text+1) * sizeof(struct PDFText *)); + (*texts)[ctx->t_ctx.text] = pdf_text_new(); + (*texts)[ctx->t_ctx.text]->text = strdup(dots); + (*texts)[ctx->t_ctx.text]->style = cho_style_copy(style); + (*texts)[ctx->t_ctx.text]->x = MARGIN_HORIZONTAL + end_of_title_x + TOC_DOTS_GAP_WIDTH; + (*texts)[ctx->t_ctx.text]->y = ctx->t_ctx.y; + ctx->t_ctx.text++; + + *texts = erealloc(*texts, (ctx->t_ctx.text+1) * sizeof(struct PDFText *)); + (*texts)[ctx->t_ctx.text] = pdf_text_new(); + (*texts)[ctx->t_ctx.text]->text = strdup(page_no); + (*texts)[ctx->t_ctx.text]->style = cho_style_copy(style); + (*texts)[ctx->t_ctx.text]->x = page_no_x; + (*texts)[ctx->t_ctx.text]->y = ctx->t_ctx.y; + (*texts)[ctx->t_ctx.text]->width = width; line_count++; if (!annot_page_link_add(ctx, entry, toc_page_count, line_count, style->font->size)) { LOG_DEBUG("annot_page_link_add"); return false; } - ctx->text++; - ctx->y -= 8.0 + style->font->size; + ctx->t_ctx.text++; + ctx->t_ctx.y -= 8.0 + style->font->size; } else { - if (ctx->y < MARGIN_BOTTOM) { - if (!pdf_page_close_then_add(ctx, NUS_ROMAN)) { + if (ctx->t_ctx.y < MARGIN_BOTTOM) { + if (!pdf_page_close_then_add(ctx, &ctx->t_ctx, NUS_ROMAN)) { LOG_DEBUG("pdf_page_close_then_add failed."); return false; } - texts = &ctx->content->pages[ctx->page]->texts; + texts = &ctx->t_ctx.content->pages[ctx->t_ctx.page]->texts; } end_of_title_x = width; - *texts = erealloc(*texts, (ctx->text+1) * sizeof(struct PDFText *)); - (*texts)[ctx->text] = pdf_text_new(); - (*texts)[ctx->text]->text = strdup(entry->title); - (*texts)[ctx->text]->style = cho_style_copy(style); - (*texts)[ctx->text]->x = MARGIN_HORIZONTAL; - (*texts)[ctx->text]->y = ctx->y; - width = text_width(entry->title, style); + *texts = erealloc(*texts, (ctx->t_ctx.text+1) * sizeof(struct PDFText *)); + (*texts)[ctx->t_ctx.text] = pdf_text_new(); + (*texts)[ctx->t_ctx.text]->text = strdup(entry->title); + (*texts)[ctx->t_ctx.text]->style = cho_style_copy(style); + (*texts)[ctx->t_ctx.text]->x = MARGIN_HORIZONTAL; + (*texts)[ctx->t_ctx.text]->y = ctx->t_ctx.y; + width = text_width(ctx, entry->title, style); if (width == ERROR) { LOG_DEBUG("text_width failed."); return false; } - (*texts)[ctx->text]->width = width; - ctx->text++; + (*texts)[ctx->t_ctx.text]->width = width; + ctx->t_ctx.text++; sprintf((char *)&page_no, "%d", entry->page_index+1); - page_no_width = text_width(page_no, style); + page_no_width = text_width(ctx, page_no, style); if (page_no_width == ERROR) { LOG_DEBUG("text_width failed."); return false; @@ -2207,130 +2024,348 @@ pdf_texts_add_toc_entry( LOG_DEBUG("toc_dots_create failed."); return false; } - dots_width = text_width(dots, style); + dots_width = text_width(ctx, dots, style); if (dots_width == ERROR) { LOG_DEBUG("text_width failed."); return false; } - *texts = erealloc(*texts, (ctx->text+1) * sizeof(struct PDFText *)); - (*texts)[ctx->text] = pdf_text_new(); - (*texts)[ctx->text]->text = strdup(dots); - (*texts)[ctx->text]->style = cho_style_copy(style); - (*texts)[ctx->text]->x = MARGIN_HORIZONTAL + end_of_title_x + TOC_DOTS_GAP_WIDTH; - (*texts)[ctx->text]->y = ctx->y; - (*texts)[ctx->text]->width = dots_width; - ctx->text++; - - *texts = erealloc(*texts, (ctx->text+1) * sizeof(struct PDFText *)); - (*texts)[ctx->text] = pdf_text_new(); - (*texts)[ctx->text]->text = strdup(page_no); - (*texts)[ctx->text]->style = cho_style_copy(style); - (*texts)[ctx->text]->x = page_no_x; - (*texts)[ctx->text]->y = ctx->y; - (*texts)[ctx->text]->width = page_no_width; + *texts = erealloc(*texts, (ctx->t_ctx.text+1) * sizeof(struct PDFText *)); + (*texts)[ctx->t_ctx.text] = pdf_text_new(); + (*texts)[ctx->t_ctx.text]->text = strdup(dots); + (*texts)[ctx->t_ctx.text]->style = cho_style_copy(style); + (*texts)[ctx->t_ctx.text]->x = MARGIN_HORIZONTAL + end_of_title_x + TOC_DOTS_GAP_WIDTH; + (*texts)[ctx->t_ctx.text]->y = ctx->t_ctx.y; + (*texts)[ctx->t_ctx.text]->width = dots_width; + ctx->t_ctx.text++; + + *texts = erealloc(*texts, (ctx->t_ctx.text+1) * sizeof(struct PDFText *)); + (*texts)[ctx->t_ctx.text] = pdf_text_new(); + (*texts)[ctx->t_ctx.text]->text = strdup(page_no); + (*texts)[ctx->t_ctx.text]->style = cho_style_copy(style); + (*texts)[ctx->t_ctx.text]->x = page_no_x; + (*texts)[ctx->t_ctx.text]->y = ctx->t_ctx.y; + (*texts)[ctx->t_ctx.text]->width = page_no_width; if (!annot_page_link_add(ctx, entry, toc_page_count, 1, style->font->size)) { LOG_DEBUG("annot_page_link_add"); return false; } - ctx->text++; - ctx->y -= 8.0 + style->font->size; + ctx->t_ctx.text++; + ctx->t_ctx.y -= 8.0 + style->font->size; + } + return true; +} + +static bool +pdf_texts_add_lyrics( + struct PDFContext *ctx, + struct ChoLineItem *item, + int i +) +{ + struct PDFText ***texts; + struct SpaceNeeded **sp; + double width; + int t = 0; + int c; + texts = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->texts; + *texts = erealloc(*texts, (ctx->b_ctx.text+1) * sizeof(struct PDFText *)); + (*texts)[ctx->b_ctx.text] = pdf_text_new(); + if (!ctx->b_ctx.spaces) { + (*texts)[ctx->b_ctx.text]->text = strdup(item->u.text->text); + (*texts)[ctx->b_ctx.text]->style = cho_style_copy(item->u.text->style); + (*texts)[ctx->b_ctx.text]->x = ctx->b_ctx.x; + (*texts)[ctx->b_ctx.text]->y = ctx->b_ctx.y; + width = text_width(ctx, item->u.text->text, item->u.text->style); + if (width == ERROR) { + LOG_DEBUG("text_width failed."); + return false; + } + (*texts)[ctx->b_ctx.text]->width = width; + if (item->u.text->style->href) { + if (!annot_url_link_add(ctx, &ctx->b_ctx, item->u.text->style, width)) { + LOG_DEBUG("annot_url_link_add failed."); + return false; + } + } + ctx->b_ctx.x += width; + if ((*texts)[ctx->b_ctx.text]->style->font->size > ctx->b_ctx.biggest_font_size) { + ctx->b_ctx.biggest_font_size = (*texts)[ctx->b_ctx.text]->style->font->size; + } + ctx->b_ctx.consumed_lyrics += strlen((*texts)[ctx->b_ctx.text]->text); + ctx->b_ctx.text++; + return true; + } + for (c = 0; item->u.text->text[c]; c++) { + (*texts)[ctx->b_ctx.text]->text = erealloc((*texts)[ctx->b_ctx.text]->text, (t+1) * sizeof(char)); + (*texts)[ctx->b_ctx.text]->text[t] = item->u.text->text[c]; + t++; + for (sp = ctx->b_ctx.spaces; *sp; sp++) { + if ((*sp)->line_item_index == i && (*sp)->text_index == c) { + size_t len = grapheme_next_character_break_utf8(&item->u.text->text[c], 10); + size_t i; + for (i = 0; i<len-1; i++, t++) { + c++; + (*texts)[ctx->b_ctx.text]->text = erealloc((*texts)[ctx->b_ctx.text]->text, (t+1) * sizeof(char)); + (*texts)[ctx->b_ctx.text]->text[t] = item->u.text->text[c]; + } + (*texts)[ctx->b_ctx.text]->text = erealloc((*texts)[ctx->b_ctx.text]->text, (t+1) * sizeof(char)); + (*texts)[ctx->b_ctx.text]->text[t] = 0; + (*texts)[ctx->b_ctx.text]->style = cho_style_copy(item->u.text->style); + (*texts)[ctx->b_ctx.text]->x = ctx->b_ctx.x; + (*texts)[ctx->b_ctx.text]->y = ctx->b_ctx.y; + width = text_width(ctx, (*texts)[ctx->b_ctx.text]->text, item->u.text->style); + if (width == ERROR) { + LOG_DEBUG("text_width failed."); + return false; + } + (*texts)[ctx->b_ctx.text]->width = width; + if (item->u.text->style->href) { + if (!annot_url_link_add(ctx, &ctx->b_ctx, item->u.text->style, width)) { + LOG_DEBUG("annot_url_link_add failed."); + return false; + } + } + ctx->b_ctx.x += width; + ctx->b_ctx.x += (*sp)->amount; + t = 0; + ctx->b_ctx.consumed_lyrics += strlen((*texts)[ctx->b_ctx.text]->text); + ctx->b_ctx.text++; + *texts = erealloc(*texts, (ctx->b_ctx.text+1) * sizeof(struct PDFText *)); + (*texts)[ctx->b_ctx.text] = pdf_text_new(); + } + } + } + (*texts)[ctx->b_ctx.text]->text = erealloc((*texts)[ctx->b_ctx.text]->text, (t+1) * sizeof(char)); + (*texts)[ctx->b_ctx.text]->text[t] = 0; + (*texts)[ctx->b_ctx.text]->style = cho_style_copy(item->u.text->style); + (*texts)[ctx->b_ctx.text]->x = ctx->b_ctx.x; + (*texts)[ctx->b_ctx.text]->y = ctx->b_ctx.y; + width = text_width(ctx, (*texts)[ctx->b_ctx.text]->text, item->u.text->style); + if (width == ERROR) { + LOG_DEBUG("text_width failed."); + return false; + } + (*texts)[ctx->b_ctx.text]->width = width; + if (item->u.text->style->href) { + if (!annot_url_link_add(ctx, &ctx->b_ctx, item->u.text->style, width)) { + LOG_DEBUG("annot_url_link_add failed."); + return false; + } + } + ctx->b_ctx.x += width; + if ((*texts)[ctx->b_ctx.text]->style->font->size > ctx->b_ctx.biggest_font_size) { + ctx->b_ctx.biggest_font_size = (*texts)[ctx->b_ctx.text]->style->font->size; + } + ctx->b_ctx.consumed_lyrics += strlen((*texts)[ctx->b_ctx.text]->text); + ctx->b_ctx.text++; + return true; +} + +static bool +pdf_texts_add_text( + struct PDFContext *ctx, + struct PDFContentContext *c_ctx, + const char *text, + struct ChoStyle *style, + enum Alignment align, + enum NumeralSystem numeral_system +) +{ + struct PDFText ***texts; + char str[strlen(text)+1]; + double width; + int index; + strcpy((char *)&str, text); + texts = &c_ctx->content->pages[c_ctx->page]->texts; + width = text_width(ctx, text, style); + if (width == ERROR) { + LOG_DEBUG("text_width failed."); + return false; + } + if (width > LINE_WIDTH) { + char *t = (char *)&str; + while (width > LINE_WIDTH) { + if (c_ctx->y < c_ctx->margin_bottom) { + if (!pdf_page_close_then_add(ctx, c_ctx, numeral_system)) { + LOG_DEBUG("pdf_page_close_then_add failed."); + return false; + } + texts = &c_ctx->content->pages[c_ctx->page]->texts; + } + index = text_find_fitting(ctx, t, style, 0.0, LINE_WIDTH); + if (index == EMPTY_INT) { + LOG_DEBUG("text_find_fitting failed."); + return false; + } + t[index] = 0; + width = text_width(ctx, t, style); + if (width == ERROR) { + LOG_DEBUG("text_width failed."); + return false; + } + c_ctx->x = calc_x(width, align); + *texts = erealloc(*texts, (c_ctx->text+1) * sizeof(struct PDFText *)); + (*texts)[c_ctx->text] = pdf_text_new(); + (*texts)[c_ctx->text]->text = strdup(t); + (*texts)[c_ctx->text]->style = cho_style_copy(style); + (*texts)[c_ctx->text]->x = c_ctx->x; + (*texts)[c_ctx->text]->y = c_ctx->y; + (*texts)[c_ctx->text]->width = width; + if (style->href) { + if (!annot_url_link_add(ctx, c_ctx, style, width)) { + LOG_DEBUG("annot_url_link_add failed."); + return false; + } + } + c_ctx->text++; + c_ctx->y -= 8.0 + style->font->size; + t += index+1; + width = text_width(ctx, t, style); + if (width == ERROR) { + LOG_DEBUG("text_width failed."); + return false; + } + } + width = text_width(ctx, t, style); + if (width == ERROR) { + LOG_DEBUG("text_width failed."); + return false; + } + c_ctx->x = calc_x(width, align); + *texts = erealloc(*texts, (c_ctx->text+1) * sizeof(struct PDFText *)); + (*texts)[c_ctx->text] = pdf_text_new(); + (*texts)[c_ctx->text]->text = strdup(t); + (*texts)[c_ctx->text]->style = cho_style_copy(style); + (*texts)[c_ctx->text]->x = c_ctx->x; + (*texts)[c_ctx->text]->y = c_ctx->y; + (*texts)[c_ctx->text]->width = width; + if (style->href) { + if (!annot_url_link_add(ctx, c_ctx, style, width)) { + LOG_DEBUG("annot_url_link_add failed."); + return false; + } + } + c_ctx->text++; + c_ctx->y -= 8.0 + style->font->size; + } else { + if (c_ctx->y < c_ctx->margin_bottom) { + if (!pdf_page_close_then_add(ctx, c_ctx, numeral_system)) { + LOG_DEBUG("pdf_page_close_then_add failed."); + return false; + } + texts = &c_ctx->content->pages[c_ctx->page]->texts; + } + c_ctx->x = calc_x(width, align); + *texts = erealloc(*texts, (c_ctx->text+1) * sizeof(struct PDFText *)); + (*texts)[c_ctx->text] = pdf_text_new(); + (*texts)[c_ctx->text]->text = strdup(text); + (*texts)[c_ctx->text]->style = cho_style_copy(style); + (*texts)[c_ctx->text]->x = c_ctx->x; + (*texts)[c_ctx->text]->y = c_ctx->y; + (*texts)[c_ctx->text]->width = width; + if (style->href) { + if (!annot_url_link_add(ctx, c_ctx, style, width)) { + LOG_DEBUG("annot_url_link_add failed."); + return false; + } + } + c_ctx->text++; + c_ctx->y -= 8.0 + style->font->size; } return true; } static bool pdf_toc_create( - struct PDFContent **toc_content, - struct PDFContent *pdf_content, - struct Config *config + struct PDFContext *ctx, + struct PDFContent *pdf_body, + struct PDFContent **out ) { double max_song_title_width, dot_width; int toc_page_count; - struct PDFContext ctx; struct PDFText ***texts; struct ChoStyle *toc_style, *title_style; struct TocEntry **toc; - pdf_context_init(&ctx); - ctx.content = pdf_content_new(); - ctx.content->pages = emalloc(sizeof(struct PDFPage *)); - ctx.content->pages[ctx.page] = pdf_page_new(); - texts = &ctx.content->pages[ctx.page]->texts; - if (config->output->page_no->show) { - if (!pdf_page_add_page_no(&ctx, NUS_ROMAN)) { + pdf_content_context_init(&ctx->t_ctx); + ctx->t_ctx.content = pdf_content_new(); + ctx->t_ctx.content->pages = emalloc(sizeof(struct PDFPage *)); + ctx->t_ctx.content->pages[ctx->t_ctx.page] = pdf_page_new(ctx); + texts = &ctx->t_ctx.content->pages[ctx->t_ctx.page]->texts; + if (ctx->config->output->page_no->show) { + if (!pdf_page_add_page_no(ctx, &ctx->t_ctx, NUS_ROMAN)) { LOG_DEBUG("pdf_page_add_page_no failed."); return false; } } - toc_style = config->output->styles[TT_TOC]; - toc = pdf_content->toc; + toc_style = ctx->config->output->styles[TT_TOC]; + toc = pdf_body->toc; max_song_title_width = LINE_WIDTH * 0.85; - toc_page_count = pdf_toc_page_count(toc, toc_style, max_song_title_width); + toc_page_count = pdf_toc_page_count(ctx, toc, toc_style, max_song_title_width); if (toc_page_count == -1) { LOG_DEBUG("pdf_toc_page_count failed."); return false; } - title_style = config->output->styles[TT_TOC_TITLE]; - if (!pdf_texts_add_text(&ctx, config->output->toc->title, title_style, A_CENTER, NUS_ROMAN)) { + title_style = ctx->config->output->styles[TT_TOC_TITLE]; + if (!pdf_texts_add_text(ctx, &ctx->t_ctx, ctx->config->output->toc->title, title_style, A_CENTER, NUS_ROMAN)) { LOG_DEBUG("pdf_texts_add_text(toctitle) failed."); return false; } - ctx.y -= 30.0; - dot_width = text_width(".", toc_style); + ctx->t_ctx.y -= 30.0; + dot_width = text_width(ctx, ".", toc_style); if (dot_width == ERROR) { LOG_DEBUG("text_width failed."); return false; } for (; *toc; toc++) { - if (!pdf_texts_add_toc_entry(&ctx, *toc, toc_style, max_song_title_width, toc_page_count, dot_width)) { + if (!pdf_texts_add_toc_entry(ctx, *toc, toc_style, max_song_title_width, toc_page_count, dot_width)) { LOG_DEBUG("pdf_texts_add_toc_entry failed."); return false; } } - texts = &ctx.content->pages[ctx.page]->texts; - *texts = erealloc(*texts, (ctx.text+1) * sizeof(struct PDFText *)); - (*texts)[ctx.text] = NULL; - ctx.page++; - ctx.content->pages = erealloc(ctx.content->pages, (ctx.page+1) * sizeof(struct PDFPage *)); - ctx.content->pages[ctx.page] = NULL; - *toc_content = ctx.content; + texts = &ctx->t_ctx.content->pages[ctx->t_ctx.page]->texts; + *texts = erealloc(*texts, (ctx->t_ctx.text+1) * sizeof(struct PDFText *)); + (*texts)[ctx->t_ctx.text] = NULL; + ctx->t_ctx.page++; + ctx->t_ctx.content->pages = erealloc(ctx->t_ctx.content->pages, (ctx->t_ctx.page+1) * sizeof(struct PDFPage *)); + ctx->t_ctx.content->pages[ctx->t_ctx.page] = NULL; + *out = ctx->t_ctx.content; return true; } static bool -pdf_content_create( - struct PDFContent **out, +pdf_body_create( + struct PDFContext *ctx, struct ChoSong **songs, - struct Config *config, - struct Obj **img_objs + struct Obj **img_objs, + struct PDFContent **out ) { struct ChoSection **se; struct ChoLine **li; struct PDFText ***texts; struct PDFImage ***imgs; - struct PDFContext ctx; struct ChordDiagram ***diagrams, **dgrams, **d; - char *metadata; struct ChoStyle *metadata_style; - bool show_diagram = config->output->diagram->show; - bool start_song_on_new_page = config->output->start_song_on_new_page; + char *metadata; + bool show_diagram = ctx->config->output->diagram->show; + bool start_song_on_new_page = ctx->config->output->start_song_on_new_page; double width, height; - pdf_context_init(&ctx); + pdf_content_context_init(&ctx->b_ctx); if (show_diagram) { - ctx.margin_bottom = 150.0; - } - ctx.content = pdf_content_new(); - ctx.content->pages = emalloc(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; - if (config->output->page_no->show) { - if (!pdf_page_add_page_no(&ctx, NUS_WESTERN_ARABIC)) { + ctx->b_ctx.margin_bottom = 150.0; + } + ctx->b_ctx.content = pdf_content_new(); + ctx->b_ctx.content->pages = emalloc(sizeof(struct PDFPage *)); + ctx->b_ctx.content->pages[ctx->b_ctx.page] = pdf_page_new(ctx); + texts = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->texts; + imgs = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->images; + diagrams = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->diagrams; + if (ctx->config->output->page_no->show) { + if (!pdf_page_add_page_no(ctx, &ctx->b_ctx, NUS_WESTERN_ARABIC)) { LOG_DEBUG("pdf_page_add_page_no failed."); return false; } @@ -2345,51 +2380,51 @@ pdf_content_create( } if (chords) { qsort(chords, cho_chord_count(chords), sizeof(struct ChoChord *), cho_chord_compare); - dgrams = chord_diagrams_create(config, &chords, songs[s]->diagrams); + dgrams = chord_diagrams_create(ctx->config, &chords, songs[s]->diagrams); for (d = dgrams; *d; d++) { - *diagrams = erealloc(*diagrams, (ctx.diagram+1) * sizeof(struct ChordDiagram *)); - (*diagrams)[ctx.diagram] = *d; - ctx.diagram++; + *diagrams = erealloc(*diagrams, (ctx->b_ctx.diagram+1) * sizeof(struct ChordDiagram *)); + (*diagrams)[ctx->b_ctx.diagram] = *d; + ctx->b_ctx.diagram++; } free(dgrams); } cho_chords_free(chords); } - if (!cho_metadata_value(songs[s]->metadata, "title", config->metadata_separator, &metadata, &metadata_style)) { + if (!cho_metadata_value(songs[s]->metadata, "title", ctx->config->metadata_separator, &metadata, &metadata_style)) { LOG_DEBUG("cho_metadata_value failed."); return false; } - ctx.content->toc = erealloc(ctx.content->toc, (ctx.toc_entry+1) * sizeof(struct TocEntry *)); - ctx.content->toc[ctx.toc_entry] = emalloc(sizeof(struct TocEntry)); - ctx.content->toc[ctx.toc_entry]->title = strdup(metadata); - ctx.content->toc[ctx.toc_entry]->page_index = ctx.page; - ctx.content->toc[ctx.toc_entry]->page_y = ctx.y; - ctx.toc_entry++; - if (!pdf_texts_add_text(&ctx, metadata, metadata_style, A_CENTER, NUS_WESTERN_ARABIC)) { + ctx->b_ctx.content->toc = erealloc(ctx->b_ctx.content->toc, (ctx->b_ctx.toc_entry+1) * sizeof(struct TocEntry *)); + ctx->b_ctx.content->toc[ctx->b_ctx.toc_entry] = emalloc(sizeof(struct TocEntry)); + ctx->b_ctx.content->toc[ctx->b_ctx.toc_entry]->title = strdup(metadata); + ctx->b_ctx.content->toc[ctx->b_ctx.toc_entry]->page_index = ctx->b_ctx.page; + ctx->b_ctx.content->toc[ctx->b_ctx.toc_entry]->page_y = ctx->b_ctx.y; + ctx->b_ctx.toc_entry++; + if (!pdf_texts_add_text(ctx, &ctx->b_ctx, metadata, metadata_style, A_CENTER, NUS_WESTERN_ARABIC)) { LOG_DEBUG("pdf_texts_add_text(title) failed."); return false; } free(metadata); - if (cho_metadata_value(songs[s]->metadata, "subtitle", config->metadata_separator, &metadata, &metadata_style)) { - if (!pdf_texts_add_text(&ctx, metadata, metadata_style, A_CENTER, NUS_WESTERN_ARABIC)) { + if (cho_metadata_value(songs[s]->metadata, "subtitle", ctx->config->metadata_separator, &metadata, &metadata_style)) { + if (!pdf_texts_add_text(ctx, &ctx->b_ctx, metadata, metadata_style, A_CENTER, NUS_WESTERN_ARABIC)) { LOG_DEBUG("pdf_texts_add_text(subtitle) failed."); return false; } free(metadata); } - texts = &ctx.content->pages[ctx.page]->texts; - imgs = &ctx.content->pages[ctx.page]->images; - diagrams = &ctx.content->pages[ctx.page]->diagrams; - ctx.y -= 30.0; + texts = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->texts; + imgs = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->images; + diagrams = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->diagrams; + ctx->b_ctx.y -= 30.0; for (se = songs[s]->sections; *se; se++) { if ((*se)->label) { - if (!pdf_texts_add_text(&ctx, (*se)->label->text, (*se)->label->style, A_LEFT, NUS_WESTERN_ARABIC)) { + if (!pdf_texts_add_text(ctx, &ctx->b_ctx, (*se)->label->text, (*se)->label->style, A_LEFT, NUS_WESTERN_ARABIC)) { LOG_DEBUG("pdf_texts_add_text(label) failed."); return false; } - texts = &ctx.content->pages[ctx.page]->texts; - imgs = &ctx.content->pages[ctx.page]->images; - diagrams = &ctx.content->pages[ctx.page]->diagrams; + texts = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->texts; + imgs = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->images; + diagrams = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->diagrams; } for (li = (*se)->lines; *li; li++) { int item_index; @@ -2398,16 +2433,16 @@ pdf_content_create( struct ChoLineItemAbove **left_aboves = (*li)->text_above; struct ChoLineItem **left_items = (*li)->items; while (*left_aboves || *left_items) { - ctx.consumed_lyrics = 0; - ctx.biggest_font_size = 0.0; - ctx.prev_added_space = 0.0; + ctx->b_ctx.consumed_lyrics = 0; + ctx->b_ctx.biggest_font_size = 0.0; + ctx->b_ctx.prev_added_space = 0.0; char *string; struct ChoStyle *style; - if (!calc_space_between_text_above(left_items, left_aboves, img_objs, &ctx.spaces)) { + if (!calc_space_between_text_above(ctx, left_items, left_aboves, img_objs, &ctx->b_ctx.spaces)) { LOG_DEBUG("calc_space_between_text_above failed."); return false; } - pos = items_find_position_to_break_line(left_items, ctx.spaces, img_objs); + pos = items_find_position_to_break_line(ctx, left_items, ctx->b_ctx.spaces, img_objs); if (pos->line_item_index == -1) { item_index = 10000; text_above_index = 10000; @@ -2425,23 +2460,23 @@ pdf_content_create( bool text_above_exist; int i; for (i = 0; left_aboves[i] && i<text_above_index; i++) { - width = line_width_until_text_above(left_items, left_aboves[i], img_objs, NULL); + width = line_width_until_text_above(ctx, left_items, left_aboves[i], img_objs, NULL); if (width == ERROR) { - LOG_DEBUG("line_width_until_text_aboave failed."); + LOG_DEBUG("line_width_until_text_above failed."); return false; } - ctx.x = MARGIN_HORIZONTAL + width + ctx.prev_added_space; + ctx->b_ctx.x = MARGIN_HORIZONTAL + width + ctx->b_ctx.prev_added_space; struct SpaceNeeded **sp; - for (sp = ctx.spaces; *sp; sp++) { + for (sp = ctx->b_ctx.spaces; *sp; sp++) { if ((*sp)->text_above_index == i) { - ctx.x += (*sp)->amount; - ctx.prev_added_space += (*sp)->amount; + ctx->b_ctx.x += (*sp)->amount; + ctx->b_ctx.prev_added_space += (*sp)->amount; } } - *texts = erealloc(*texts, (ctx.text+1) * sizeof(struct PDFText *)); - (*texts)[ctx.text] = pdf_text_new(); - (*texts)[ctx.text]->x = ctx.x; - (*texts)[ctx.text]->y = ctx.y; + *texts = erealloc(*texts, (ctx->b_ctx.text+1) * sizeof(struct PDFText *)); + (*texts)[ctx->b_ctx.text] = pdf_text_new(); + (*texts)[ctx->b_ctx.text]->x = ctx->b_ctx.x; + (*texts)[ctx->b_ctx.text]->y = ctx->b_ctx.y; if (left_aboves[i]->is_chord) { string = cho_chord_name_generate(left_aboves[i]->u.chord); style = cho_style_copy(left_aboves[i]->u.chord->style); @@ -2449,25 +2484,25 @@ pdf_content_create( string = strdup(left_aboves[i]->u.annot->text); style = cho_style_copy(left_aboves[i]->u.annot->style); } - (*texts)[ctx.text]->text = string; - (*texts)[ctx.text]->style = style; - (*texts)[ctx.text]->width = text_width(string, style); - if ((*texts)[ctx.text]->width == ERROR) { + (*texts)[ctx->b_ctx.text]->text = string; + (*texts)[ctx->b_ctx.text]->style = style; + (*texts)[ctx->b_ctx.text]->width = text_width(ctx, string, style); + if ((*texts)[ctx->b_ctx.text]->width == ERROR) { LOG_DEBUG("text_width failed."); return false; } if (style->href) { - if (!annot_url_link_add(&ctx, style, (*texts)[ctx.text]->width)) { + if (!annot_url_link_add(ctx, &ctx->b_ctx, style, (*texts)[ctx->b_ctx.text]->width)) { LOG_DEBUG("annot_url_link_add failed."); return false; } } - if (style->font->size > ctx.biggest_font_size) { - ctx.biggest_font_size = style->font->size; + if (style->font->size > ctx->b_ctx.biggest_font_size) { + ctx->b_ctx.biggest_font_size = style->font->size; } - ctx.text++; + ctx->b_ctx.text++; } - height = images_find_biggest_height(left_items, pos->line_item_index, img_objs); + height = images_find_biggest_height(ctx, left_items, pos->line_item_index, img_objs); if (height == ERROR) { LOG_DEBUG("images_find_biggest_height failed."); return false; @@ -2475,88 +2510,88 @@ pdf_content_create( text_above_exist = i > 0; if (text_above_exist) { left_aboves += i; - if (height > 2.0 + ctx.biggest_font_size) { - ctx.y -= height; + if (height > 2.0 + ctx->b_ctx.biggest_font_size) { + ctx->b_ctx.y -= height; } else { - ctx.y -= 2.0 + ctx.biggest_font_size; + ctx->b_ctx.y -= 2.0 + ctx->b_ctx.biggest_font_size; } } else { if (height > 0.0) { - ctx.y -= height; + ctx->b_ctx.y -= height; } } - if (ctx.y < ctx.margin_bottom) { + if (ctx->b_ctx.y < ctx->b_ctx.margin_bottom) { struct PDFText **tmp = NULL; int tm = 0; - ctx.y = MEDIABOX_HEIGHT - MARGIN_TOP; + ctx->b_ctx.y = MEDIABOX_HEIGHT - MARGIN_TOP; if (text_above_exist) { /* INFO: chords/annotations and their corresponding lyrics won't be splitted */ int p; - double prev_y = (*texts)[ctx.text-1]->y; - for (p = ctx.text-1; prev_y == (*texts)[p]->y; p--) { - (*texts)[p]->y = ctx.y; + double prev_y = (*texts)[ctx->b_ctx.text-1]->y; + for (p = ctx->b_ctx.text-1; prev_y == (*texts)[p]->y; p--) { + (*texts)[p]->y = ctx->b_ctx.y; tmp = erealloc(tmp, (tm+1) * sizeof(struct PDFText *)); tmp[tm] = (*texts)[p]; tm++; - *texts = erealloc(*texts, (--ctx.text) * sizeof(struct PDFText *)); + *texts = erealloc(*texts, (--ctx->b_ctx.text) * sizeof(struct PDFText *)); } } - if (!pdf_page_close_then_add(&ctx, NUS_WESTERN_ARABIC)) { + if (!pdf_page_close_then_add(ctx, &ctx->b_ctx, NUS_WESTERN_ARABIC)) { LOG_DEBUG("pdf_page_close_then_add failed."); return false; } - texts = &ctx.content->pages[ctx.page]->texts; - imgs = &ctx.content->pages[ctx.page]->images; - diagrams = &ctx.content->pages[ctx.page]->diagrams; + texts = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->texts; + imgs = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->images; + diagrams = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->diagrams; if (text_above_exist) { for (int i=0; i<tm; i++) { - *texts = erealloc(*texts, (ctx.text+1) * sizeof(struct PDFText *)); - (*texts)[ctx.text] = tmp[i]; - ctx.text++; + *texts = erealloc(*texts, (ctx->b_ctx.text+1) * sizeof(struct PDFText *)); + (*texts)[ctx->b_ctx.text] = tmp[i]; + ctx->b_ctx.text++; } free(tmp); } if (text_above_exist) { - if (height > 2.0 + ctx.biggest_font_size) { - ctx.y -= height; + if (height > 2.0 + ctx->b_ctx.biggest_font_size) { + ctx->b_ctx.y -= height; } else { - ctx.y -= 2.0 + ctx.biggest_font_size; + ctx->b_ctx.y -= 2.0 + ctx->b_ctx.biggest_font_size; } } else { - ctx.y -= height; + ctx->b_ctx.y -= height; } } - ctx.biggest_font_size = 0.0; - ctx.x = MARGIN_HORIZONTAL; + ctx->b_ctx.biggest_font_size = 0.0; + ctx->b_ctx.x = MARGIN_HORIZONTAL; i = 0; while (*left_items && i < item_index) { if ((*left_items)->is_text) { - if (!pdf_texts_add_lyrics(*left_items, &ctx, i)) { + if (!pdf_texts_add_lyrics(ctx, *left_items, i)) { LOG_DEBUG("pdf_texts_add_lyrics failed."); return false; } - texts = &ctx.content->pages[ctx.page]->texts; - imgs = &ctx.content->pages[ctx.page]->images; - diagrams = &ctx.content->pages[ctx.page]->diagrams; + texts = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->texts; + imgs = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->images; + diagrams = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->diagrams; } else { - *imgs = erealloc(*imgs, (ctx.image+1) * sizeof(struct PDFImage *)); - (*imgs)[ctx.image] = pdf_image_new(); - (*imgs)[ctx.image]->name = image_name((*left_items)->u.image); - if (!(*imgs)[ctx.image]->name) { + *imgs = erealloc(*imgs, (ctx->b_ctx.image+1) * sizeof(struct PDFImage *)); + (*imgs)[ctx->b_ctx.image] = pdf_image_new(); + (*imgs)[ctx->b_ctx.image]->name = image_name(ctx, (*left_items)->u.image); + if (!(*imgs)[ctx->b_ctx.image]->name) { LOG_DEBUG("image_name failed."); return false; } - (*imgs)[ctx.image]->obj = objs_get_obj(img_objs, (*imgs)[ctx.image]->name); - if (!(*imgs)[ctx.image]->obj) { + (*imgs)[ctx->b_ctx.image]->obj = objs_get_obj(img_objs, (*imgs)[ctx->b_ctx.image]->name); + if (!(*imgs)[ctx->b_ctx.image]->obj) { LOG_DEBUG("objs_get_obj failed."); return false; } - (*imgs)[ctx.image]->width = image_width((*left_items)->u.image, (*imgs)[ctx.image]->obj); - (*imgs)[ctx.image]->height = image_height((*left_items)->u.image, (*imgs)[ctx.image]->obj); - (*imgs)[ctx.image]->x = ctx.x; - (*imgs)[ctx.image]->y = ctx.y; - ctx.x += (*imgs)[ctx.image]->width; - ctx.image++; + (*imgs)[ctx->b_ctx.image]->width = image_width((*left_items)->u.image, (*imgs)[ctx->b_ctx.image]->obj); + (*imgs)[ctx->b_ctx.image]->height = image_height((*left_items)->u.image, (*imgs)[ctx->b_ctx.image]->obj); + (*imgs)[ctx->b_ctx.image]->x = ctx->b_ctx.x; + (*imgs)[ctx->b_ctx.image]->y = ctx->b_ctx.y; + ctx->b_ctx.x += (*imgs)[ctx->b_ctx.image]->width; + ctx->b_ctx.image++; } i++; left_items++; @@ -2566,99 +2601,99 @@ pdf_content_create( char *tmp; (*left_items)->u.text->text[pos->text_index] = 0; tmp = strdup(&(*left_items)->u.text->text[pos->text_index+1]); - if (!pdf_texts_add_lyrics(*left_items, &ctx, i)) { + if (!pdf_texts_add_lyrics(ctx, *left_items, i)) { LOG_DEBUG("pdf_texts_add_lyrics failed."); return false; } free((*left_items)->u.text->text); (*left_items)->u.text->text = tmp; - texts = &ctx.content->pages[ctx.page]->texts; - imgs = &ctx.content->pages[ctx.page]->images; - diagrams = &ctx.content->pages[ctx.page]->diagrams; + texts = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->texts; + imgs = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->images; + diagrams = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->diagrams; } } else if (pos->line_item_index != -1 && pos->text_index == -1) { if (!(*left_items)->is_text) { - *imgs = erealloc(*imgs, (ctx.image+1) * sizeof(struct PDFImage *)); - (*imgs)[ctx.image] = pdf_image_new(); - (*imgs)[ctx.image]->name = image_name((*left_items)->u.image); - if (!(*imgs)[ctx.image]->name) { + *imgs = erealloc(*imgs, (ctx->b_ctx.image+1) * sizeof(struct PDFImage *)); + (*imgs)[ctx->b_ctx.image] = pdf_image_new(); + (*imgs)[ctx->b_ctx.image]->name = image_name(ctx, (*left_items)->u.image); + if (!(*imgs)[ctx->b_ctx.image]->name) { LOG_DEBUG("image_name failed."); return false; } - (*imgs)[ctx.image]->obj = objs_get_obj(img_objs, (*imgs)[ctx.image]->name); - if (!(*imgs)[ctx.image]->obj) { + (*imgs)[ctx->b_ctx.image]->obj = objs_get_obj(img_objs, (*imgs)[ctx->b_ctx.image]->name); + if (!(*imgs)[ctx->b_ctx.image]->obj) { LOG_DEBUG("objs_get_obj failed."); return false; } - (*imgs)[ctx.image]->width = image_width((*left_items)->u.image, (*imgs)[ctx.image]->obj); - (*imgs)[ctx.image]->height = image_height((*left_items)->u.image, (*imgs)[ctx.image]->obj); - (*imgs)[ctx.image]->x = ctx.x; - (*imgs)[ctx.image]->y = ctx.y; - ctx.image++; + (*imgs)[ctx->b_ctx.image]->width = image_width((*left_items)->u.image, (*imgs)[ctx->b_ctx.image]->obj); + (*imgs)[ctx->b_ctx.image]->height = image_height((*left_items)->u.image, (*imgs)[ctx->b_ctx.image]->obj); + (*imgs)[ctx->b_ctx.image]->x = ctx->b_ctx.x; + (*imgs)[ctx->b_ctx.image]->y = ctx->b_ctx.y; + ctx->b_ctx.image++; } left_items++; } - ctx.y -= 8.0 + ctx.biggest_font_size; - if (ctx.y < ctx.margin_bottom) { - if (!pdf_page_close_then_add(&ctx, NUS_WESTERN_ARABIC)) { + ctx->b_ctx.y -= 8.0 + ctx->b_ctx.biggest_font_size; + if (ctx->b_ctx.y < ctx->b_ctx.margin_bottom) { + if (!pdf_page_close_then_add(ctx, &ctx->b_ctx, NUS_WESTERN_ARABIC)) { LOG_DEBUG("pdf_page_close_then_add failed."); return false; } - texts = &ctx.content->pages[ctx.page]->texts; - imgs = &ctx.content->pages[ctx.page]->images; - diagrams = &ctx.content->pages[ctx.page]->diagrams; + texts = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->texts; + imgs = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->images; + diagrams = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->diagrams; } - spaces_free(ctx.spaces); - ctx.spaces = NULL; + spaces_free(ctx->b_ctx.spaces); + ctx->b_ctx.spaces = NULL; free(pos); pos = NULL; - text_above_update_positions(left_aboves, ctx.consumed_lyrics); + text_above_update_positions(left_aboves, ctx->b_ctx.consumed_lyrics); } if ((*li)->btype == BT_PAGE) { - if (!pdf_page_close_then_add(&ctx, NUS_WESTERN_ARABIC)) { + if (!pdf_page_close_then_add(ctx, &ctx->b_ctx, NUS_WESTERN_ARABIC)) { LOG_DEBUG("pdf_page_close_then_add failed."); return false; } - texts = &ctx.content->pages[ctx.page]->texts; - imgs = &ctx.content->pages[ctx.page]->images; - diagrams = &ctx.content->pages[ctx.page]->diagrams; + texts = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->texts; + imgs = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->images; + diagrams = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->diagrams; } } - ctx.y -= SECTION_GAP_WIDTH; + ctx->b_ctx.y -= SECTION_GAP_WIDTH; } if (start_song_on_new_page) { - if (!pdf_page_close_then_add(&ctx, NUS_WESTERN_ARABIC)) { + if (!pdf_page_close_then_add(ctx, &ctx->b_ctx, NUS_WESTERN_ARABIC)) { LOG_DEBUG("pdf_page_close_then_add failed."); return false; } - texts = &ctx.content->pages[ctx.page]->texts; - imgs = &ctx.content->pages[ctx.page]->images; - diagrams = &ctx.content->pages[ctx.page]->diagrams; + texts = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->texts; + imgs = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->images; + diagrams = &ctx->b_ctx.content->pages[ctx->b_ctx.page]->diagrams; } } - *texts = erealloc(*texts, (ctx.text+1) * sizeof(struct PDFText *)); - (*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; + *texts = erealloc(*texts, (ctx->b_ctx.text+1) * sizeof(struct PDFText *)); + (*texts)[ctx->b_ctx.text] = NULL; + *imgs = erealloc(*imgs, (ctx->b_ctx.image+1) * sizeof(struct PDFImage *)); + (*imgs)[ctx->b_ctx.image] = NULL; + *diagrams = erealloc(*diagrams, (ctx->b_ctx.diagram+1) * sizeof(struct ChordDiagram *)); + (*diagrams)[ctx->b_ctx.diagram] = NULL; if (start_song_on_new_page) { - pdf_page_free(ctx.content->pages[ctx.page]); - ctx.content->pages[ctx.page] = NULL; + pdf_page_free(ctx->b_ctx.content->pages[ctx->b_ctx.page]); + ctx->b_ctx.content->pages[ctx->b_ctx.page] = NULL; } else { - ctx.page++; - ctx.content->pages = erealloc(ctx.content->pages, (ctx.page+1) * sizeof(struct PDFPage *)); - ctx.content->pages[ctx.page] = NULL; + ctx->b_ctx.page++; + ctx->b_ctx.content->pages = erealloc(ctx->b_ctx.content->pages, (ctx->b_ctx.page+1) * sizeof(struct PDFPage *)); + ctx->b_ctx.content->pages[ctx->b_ctx.page] = NULL; } - ctx.content->toc = erealloc(ctx.content->toc, (ctx.toc_entry+1) * sizeof(struct TocEntry *)); - ctx.content->toc[ctx.toc_entry] = NULL; - *out = ctx.content; + ctx->b_ctx.content->toc = erealloc(ctx->b_ctx.content->toc, (ctx->b_ctx.toc_entry+1) * sizeof(struct TocEntry *)); + ctx->b_ctx.content->toc[ctx->b_ctx.toc_entry] = NULL; + *out = ctx->b_ctx.content; return true; } static bool -pdf_toc_render(struct PDFContent *content, pdfio_file_t *file) +pdf_toc_render(struct PDFContext *ctx, struct PDFContent *content) { struct PDFPage **pages; struct PDFText **texts; @@ -2666,14 +2701,14 @@ pdf_toc_render(struct PDFContent *content, pdfio_file_t *file) pages = content->pages; int p; for (p = 0; pages[p]; p++) { - g_current_page_index = p; - stream = pdf_page_create(file, NULL, pages[p]->annots); + ctx->current_page_index = p; + stream = pdf_page_create(ctx, NULL, pages[p]->annots); if (!stream) { LOG_DEBUG("pdf_page_create failed."); return false; } for (texts = pages[p]->texts; *texts; texts++) { - if (!pdf_text_show(stream, *texts)) { + if (!pdf_text_show(ctx, stream, *texts)) { LOG_DEBUG("pdf_text_show failed."); return false; } @@ -2687,7 +2722,7 @@ pdf_toc_render(struct PDFContent *content, pdfio_file_t *file) } static bool -pdf_content_render(struct PDFContent *content, pdfio_file_t *file) +pdf_body_render(struct PDFContext *ctx, struct PDFContent *content) { int p; struct PDFPage **pages; @@ -2696,14 +2731,14 @@ pdf_content_render(struct PDFContent *content, pdfio_file_t *file) pdfio_stream_t *stream; pages = content->pages; for (p = 0; pages[p]; p++) { - g_current_page_index = p; - stream = pdf_page_create(file, pages[p]->images, pages[p]->annots); + ctx->current_page_index = p; + stream = pdf_page_create(ctx, pages[p]->images, pages[p]->annots); if (!stream) { LOG_DEBUG("pdf_page_create failed."); return false; } for (texts = pages[p]->texts; *texts; texts++) { - if (!pdf_text_show(stream, *texts)) { + if (!pdf_text_show(ctx, stream, *texts)) { LOG_DEBUG("pdf_text_show failed."); return false; } @@ -2732,7 +2767,7 @@ pdf_content_render(struct PDFContent *content, pdfio_file_t *file) /* TODO: Handle line break when too long */ for (d = pages[p]->diagrams; *d; d++) { if ((*d)->show) { - if (!chord_diagram_draw(stream, *d, x, y, size)) { + if (!chord_diagram_draw(ctx, stream, *d, x, y, size)) { LOG_DEBUG("chord_diagram_draw failed."); return false; } @@ -2758,79 +2793,77 @@ out_pdf_create( { struct Font **needed_fonts; struct Obj **img_objs = NULL; - struct PDFContent *pdf_content = NULL; - struct PDFContent *toc_content = NULL; + struct PDFContent *pdf_body = NULL; + struct PDFContent *pdf_toc = NULL; + struct PDFContext ctx; pdfio_rect_t media_box_a4 = { 0.0, 0.0, MEDIABOX_WIDTH, MEDIABOX_HEIGHT }; pdfio_rect_t crop_box = { 0.0, 0.0, MEDIABOX_WIDTH, MEDIABOX_HEIGHT }; char *dirpath, *pdf_filepath; - g_config = config; - - memset(&g_current_font_name, 0, sizeof(g_current_font_name)); - memset(&g_cho_dirpath, 0, PATH_MAX); + ctx.fonts = NULL; + ctx.config = config; + ctx.current_page_index = 0; + ctx.current_font_size = 0.0; + memset(&ctx.cho_dirpath, 0, PATH_MAX); + memset(&ctx.current_font_name, 0, 200); if (cho_filepath) { dirpath = filepath_dirname(cho_filepath); } else { dirpath = getcwd(NULL, 0); } - strcpy((char *)&g_cho_dirpath, dirpath); + strcpy((char *)&ctx.cho_dirpath, dirpath); free(dirpath); - pdf_filepath = pdf_filepath_create(songs, cho_filepath, output_folder_or_file); + pdf_filepath = pdf_filepath_create(&ctx, songs, cho_filepath, output_folder_or_file); if (!pdf_filepath) { LOG_DEBUG("pdf_filepath_create failed."); return NULL; } - g_pdf_file = pdfioFileCreate(pdf_filepath, "2.0", &media_box_a4, &crop_box, NULL, NULL); - if (!g_pdf_file) { + ctx.pdf_file = pdfioFileCreate(pdf_filepath, "2.0", &media_box_a4, &crop_box, NULL, NULL); + if (!ctx.pdf_file) { LOG_DEBUG("pdfioFileCreate failed."); return NULL; } - if (!pdf_set_title(g_pdf_file, songs)) { + if (!pdf_set_title(&ctx, songs)) { LOG_DEBUG("pdf_set_title failed."); goto CLEAN; } - needed_fonts = fonts_get_all(songs, config); - if (!pdf_load_fonts(needed_fonts, config)) { + needed_fonts = fonts_get_all(songs, ctx.config); + if (!pdf_load_fonts(&ctx, needed_fonts)) { LOG_DEBUG("pdf_load_fonts failed."); goto CLEAN; } cho_fonts_free(needed_fonts); - if (!pdf_load_images(&img_objs, g_pdf_file, songs)) { + if (!pdf_load_images(&ctx, &img_objs, songs)) { LOG_DEBUG("pdf_load_images failed."); goto CLEAN; } - if (!pdf_content_create(&pdf_content, songs, config, img_objs)) { - LOG_DEBUG("pdf_content_create failed."); + if (!pdf_body_create(&ctx, songs, img_objs, &pdf_body)) { + LOG_DEBUG("pdf_body_create failed."); goto CLEAN; } - if (config->output->toc->show) { - if (!pdf_toc_create(&toc_content, pdf_content, config)) { + if (ctx.config->output->toc->show) { + if (!pdf_toc_create(&ctx, pdf_body, &pdf_toc)) { LOG_DEBUG("pdf_toc_create failed."); goto CLEAN; } - if (!pdf_toc_render(toc_content, g_pdf_file)) { + if (!pdf_toc_render(&ctx, pdf_toc)) { LOG_DEBUG("pdf_toc_render failed."); goto CLEAN; } } - if (!pdf_content_render(pdf_content, g_pdf_file)) { - LOG_DEBUG("pdf_content_render failed."); + if (!pdf_body_render(&ctx, pdf_body)) { + LOG_DEBUG("pdf_body_render failed."); goto CLEAN; } objs_free(img_objs); - pdf_content_free(toc_content); - pdf_content_free(pdf_content); - if (!pdfioFileClose(g_pdf_file)) { + pdf_content_free(pdf_toc); + pdf_content_free(pdf_body); + if (!pdfioFileClose(ctx.pdf_file)) { LOG_DEBUG("pdfioFileClose failed."); goto CLEAN; } - g_pdf_file = NULL; - objs_free(g_fonts); - g_fonts = NULL; - g_current_font_size = 0.0; - g_current_page_index = 0; - g_config = NULL; + objs_free(ctx.fonts); return pdf_filepath; CLEAN: if (unlink(pdf_filepath)) { diff --git a/src/out_pdf.h b/src/out_pdf.h @@ -1,4 +1,5 @@ #include <pdfio.h> +#include <linux/limits.h> #include "core.h" #include "chordpro.h" @@ -81,7 +82,7 @@ struct SpaceNeeded { double amount; }; -struct PDFContext { +struct PDFContentContext { struct PDFContent *content; double x; double y; @@ -97,5 +98,17 @@ struct PDFContext { double margin_bottom; }; +struct PDFContext { + struct Obj **fonts; + struct Config *config; + pdfio_file_t *pdf_file; + double current_font_size; + int current_page_index; + char cho_dirpath[PATH_MAX]; + char current_font_name[200]; + struct PDFContentContext t_ctx; // INFO: context for pdf_toc_create() + struct PDFContentContext b_ctx; // INFO: context for pdf_body_create() +}; + char *out_pdf_create(const char *cho_filename, const char *output_folder_or_file, struct ChoSong **songs, struct Config *config); -pdfio_obj_t *out_pdf_fnt_obj_get_by_name(const char *name); +pdfio_obj_t *out_pdf_fnt_obj_get_by_name(struct PDFContext *ctx, const char *name);