lorid

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

commit e69184c0f06e72039dd8a3ca32b0e105479d3019
parent 7df72cd690fff63c07b79ac54852b4b6802c2528
Author: nibo <nibo@relim.de>
Date:   Tue, 24 Dec 2024 18:06:38 +0100

Finish toc

Diffstat:
Mout_pdf.c | 192++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 156 insertions(+), 36 deletions(-)

diff --git a/out_pdf.c b/out_pdf.c @@ -18,6 +18,7 @@ static char g_cho_dirpath[PATH_MAX]; static char g_current_font_name[200]; static double g_current_font_size; static pdfio_obj_t *g_current_font_obj = NULL; +static int g_current_page_index; static pdfio_file_t *g_pdf_file = NULL; pdfio_obj_t * @@ -291,8 +292,13 @@ out_pdf_fnt_name_create(struct Font *font) static bool out_pdf_font_set(pdfio_stream_t *stream, struct Font *font) { + static int page_index = 0; char *name = out_pdf_fnt_name_create(font); - if (!strcmp(name, g_current_font_name) && font->size == g_current_font_size) { + if ( + !strcmp(name, g_current_font_name) && + font->size == g_current_font_size && + g_current_page_index == page_index + ) { free(name); return true; } @@ -308,6 +314,7 @@ out_pdf_font_set(pdfio_stream_t *stream, struct Font *font) strcpy(g_current_font_name, name); g_current_font_obj = font_obj; g_current_font_size = font->size; + page_index = g_current_page_index; free(name); return true; } @@ -514,16 +521,20 @@ static bool annot_page_link_add( struct PDFContext *ctx, struct TocEntry *entry, + int toc_page_count, + int line_count, double font_size ) { + int page_index; pdfio_rect_t rect; pdfio_dict_t *annot; pdfio_array_t *destination; rect.x1 = MARGIN_HORIZONTAL; rect.x2 = MARGIN_HORIZONTAL + LINE_WIDTH; rect.y1 = ctx->y - 2.0; - rect.y2 = ctx->y + font_size * 0.8; + rect.y2 = 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); if (!pdfioDictSetName(annot, "Subtype", "Link")) { LOG_DEBUG("pdfioDictSetName failed."); @@ -534,15 +545,20 @@ annot_page_link_add( return false; } destination = pdfioArrayCreate(g_pdf_file); - printf("page index '%d'\n", entry->page_index); - if (!pdfioArrayAppendNumber(destination, entry->page_index)) { + if (!pdfioArrayAppendNumber(destination, page_index)) { LOG_DEBUG("pdfioArrayAppendNumber failed."); return false; } - if (!pdfioArrayAppendName(destination, "Fit")) { + if (!pdfioArrayAppendName(destination, "FitH")) { LOG_DEBUG("pdfioArrayAppendName failed."); return false; } + // TODO: Is this constant '30.0' correct with different font sizes, etc. ? + // clicking the annotation should show the song including the song title at the top + if (!pdfioArrayAppendNumber(destination, entry->page_y + 30.0)) { + LOG_DEBUG("pdfioArrayAppendNumber failed."); + return false; + } if (!pdfioDictSetArray(annot, "Dest", destination)) { LOG_DEBUG("pdfioDictSetArray failed."); return false; @@ -1339,6 +1355,7 @@ text_above_update_positions(struct ChoLineItemAbove **aboves, size_t consumed_ly } } +// TODO: This function doesn't create a new page if needed static bool pdf_texts_add_lyrics( struct ChoLineItem *item, @@ -1447,6 +1464,7 @@ calc_x(double width, enum Alignment align) return MARGIN_HORIZONTAL; } +// TODO: This function doesn't create a new page if needed static bool pdf_texts_add_text( struct PDFContext *ctx, @@ -1542,17 +1560,78 @@ pdf_texts_add_text( return true; } +// TODO: This function doesn't create a new page if needed +static int +pdf_toc_page_count( + struct TocEntry **entries, + struct ChoStyle *style, + double max_title_width +) +{ + int text = 0; + int page = 0; + double x = MARGIN_HORIZONTAL; + double y = MEDIABOX_HEIGHT - MARGIN_TOP; + double width; + struct TocEntry **toc; + toc = entries; + while (*toc) { + if (y < MARGIN_BOTTOM) { + text = 0; + y = MEDIABOX_HEIGHT - MARGIN_TOP; + page++; + } + int index; + char tmp[strlen((*toc)->title)+1]; + strcpy((char *)&tmp, (*toc)->title); + width = text_width((*toc)->title, style); + if (width == ERROR) { + LOG_DEBUG("text_width failed."); + return -1; + } + width += MARGIN_HORIZONTAL; + 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); + if (index == EMPTY_INT) { + LOG_DEBUG("text_find_fitting failed."); + return -1; + } + t[index] = 0; + y -= 8.0 + style->font->size; + t += index + 1; + width = text_width(t, style); + if (width == ERROR) { + LOG_DEBUG("text_width failed."); + return -1; + } + } + y -= 8.0 + style->font->size; + } else { + y -= 8.0 + style->font->size; + } + toc++; + } + return page + 1; +} + +// TODO: This function doesn't create a new page if needed static bool pdf_texts_add_toc_entry( struct PDFContext *ctx, struct TocEntry *entry, struct ChoStyle *style, - double max_title_width + double max_title_width, + int toc_page_count ) { - double width; - int index; + struct PDFText ***texts; + texts = &ctx->content->pages[ctx->page]->texts; + double width, page_no_x; + int index, line_count; char tmp[strlen(entry->title)+1]; + char page_no[5+1]; strcpy((char *)&tmp, entry->title); width = text_width(entry->title, style); if (width == ERROR) { @@ -1562,6 +1641,7 @@ pdf_texts_add_toc_entry( width += MARGIN_HORIZONTAL; if (width > max_title_width) { char *t = (char *)&tmp; + line_count = 0; while (width > max_title_width) { index = text_find_fitting(t, style, MARGIN_HORIZONTAL, max_title_width); if (index == EMPTY_INT) { @@ -1569,7 +1649,15 @@ pdf_texts_add_toc_entry( return false; } t[index] = 0; - printf("part '%s'\n", t); + *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->text++; + ctx->y -= 8.0 + style->font->size; + line_count++; t += index + 1; width = text_width(t, style); if (width == ERROR) { @@ -1577,9 +1665,54 @@ pdf_texts_add_toc_entry( return false; } } - printf("last part '%s'\n", t); + *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->text++; + sprintf((char *)&page_no, "%d", entry->page_index+1); + width = text_width(page_no, style); + + page_no_x = MEDIABOX_WIDTH - MARGIN_HORIZONTAL - width; + *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; + 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; } else { - printf("title '%s'\n", entry->title); + *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; + ctx->text++; + sprintf((char *)&page_no, "%d", entry->page_index+1); + width = text_width(page_no, style); + + page_no_x = MEDIABOX_WIDTH - MARGIN_HORIZONTAL - width; + *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; + 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; } return true; } @@ -1593,6 +1726,7 @@ pdf_toc_create( ) { double width, space_for_dots, max_title_width; + int toc_page_count; struct PDFContext ctx; struct PDFText ***texts; ctx.text = 0; @@ -1606,10 +1740,14 @@ pdf_toc_create( struct OutputStyle *toc_style = config_output_style_get(config->output->styles, "toc"); struct TocEntry **toc; toc = pdf_content->toc; - max_title_width = LINE_WIDTH * 0.85 + MARGIN_HORIZONTAL; - // TODO: First find out how many pages the toc will have + max_title_width = LINE_WIDTH * 0.85; + toc_page_count = pdf_toc_page_count(toc, toc_style->style, max_title_width); + if (toc_page_count == -1) { + LOG_DEBUG("pdf_toc_page_count failed."); + return false; + } while (*toc) { - if (!pdf_texts_add_toc_entry(&ctx, *toc, toc_style->style, max_title_width)) { + if (!pdf_texts_add_toc_entry(&ctx, *toc, toc_style->style, max_title_width, toc_page_count)) { LOG_DEBUG("pdf_texts_add_toc_entry failed."); return false; } @@ -1623,29 +1761,9 @@ pdf_toc_create( ctx.content->pages[ctx.page] = pdf_page_new(); texts = &ctx.content->pages[ctx.page]->texts; } - // pdf_text_count_vertical_space((*toc)->title, toc_style->style); - /* if (!annot_page_link_add(&ctx, *toc, toc_style->style->font->size)) { - LOG_DEBUG("annot_page_link_add"); - return false; - } */ // TODO: create (multi)line with title, dots and the page number - space_for_dots = LINE_WIDTH; - char page_no[5+1]; - sprintf((char *)&page_no, "%d", (*toc)->page_index+1); - width = text_width(page_no, toc_style->style); - - double most_right_x = MEDIABOX_WIDTH - MARGIN_HORIZONTAL; - double page_no_x = most_right_x - width; - *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(toc_style->style); - (*texts)[ctx.text]->x = page_no_x; - (*texts)[ctx.text]->y = ctx.y; - ctx.text++; - ctx.y -= 8.0 + toc_style->style->font->size; - - /* space_for_dots -= width; + /* space_for_dots = LINE_WIDTH; + space_for_dots -= width; width = text_width((*toc)->title, toc_style->style); space_for_dots -= width; printf("width for dots '%.1f'\n", space_for_dots); @@ -2042,6 +2160,7 @@ 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; texts = pages[p]->texts; stream = out_pdf_page_create(file, NULL, pages[p]->annots); while (*texts) { @@ -2069,6 +2188,7 @@ 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; texts = pages[p]->texts; imgs = pages[p]->images; stream = out_pdf_page_create(file, imgs, pages[p]->annots);