diff --git a/layout/src/main/kotlin/de/pfadfinder/songbook/layout/MeasurementEngine.kt b/layout/src/main/kotlin/de/pfadfinder/songbook/layout/MeasurementEngine.kt index 740d2f0..ced4ad4 100644 --- a/layout/src/main/kotlin/de/pfadfinder/songbook/layout/MeasurementEngine.kt +++ b/layout/src/main/kotlin/de/pfadfinder/songbook/layout/MeasurementEngine.kt @@ -91,11 +91,11 @@ class MeasurementEngine( } } - // Reference book footer: reserve space for abbreviation row + page number row + separator line + // Reference book footer: gap + separator line + abbreviation row + page number row if (config.referenceBooks.isNotEmpty() && song.references.isNotEmpty()) { val metaLineHeight = fontMetrics.measureLineHeight(config.fonts.metadata, config.fonts.metadata.size) + heightMm += 4f * 0.3528f // gap before footer (4pt converted to mm) heightMm += metaLineHeight * 1.4f * 2 // two rows (headers + numbers) - heightMm += metaLineHeight * 0.5f // separator line gap } val pageCount = if (heightMm <= contentHeightMm) 1 else 2 diff --git a/renderer-pdf/src/main/kotlin/de/pfadfinder/songbook/renderer/pdf/PdfBookRenderer.kt b/renderer-pdf/src/main/kotlin/de/pfadfinder/songbook/renderer/pdf/PdfBookRenderer.kt index dc5d51a..198a7c8 100644 --- a/renderer-pdf/src/main/kotlin/de/pfadfinder/songbook/renderer/pdf/PdfBookRenderer.kt +++ b/renderer-pdf/src/main/kotlin/de/pfadfinder/songbook/renderer/pdf/PdfBookRenderer.kt @@ -240,12 +240,11 @@ class PdfBookRenderer : BookRenderer { } } - // Reference footer + // Reference footer: gap + separator line + abbreviation row + page number row if (config.referenceBooks.isNotEmpty() && song.references.isNotEmpty()) { val lineHeight = metaSize * 1.4f + reserved += 4f // gap before footer reserved += lineHeight * 2 // two rows (headers + numbers) - reserved += lineHeight * 1.5f // separator line gap - reserved += lineHeight * 0.5f // bottom gap } return reserved @@ -474,10 +473,10 @@ class PdfBookRenderer : BookRenderer { // Render reference book footer on the last page of the song if (config.referenceBooks.isNotEmpty() && song.references.isNotEmpty() && isLastPage) { + y -= 4f // gap before reference footer renderReferenceFooter( cb, fontMetrics, config, song, - leftMargin, contentWidth, - bottomMargin + leftMargin, y, contentWidth ) } } @@ -512,8 +511,9 @@ class PdfBookRenderer : BookRenderer { } /** - * Renders reference book abbreviations and page numbers as a footer row - * at the bottom of the song page, above the page number. + * Renders reference book abbreviations and page numbers as a footer + * on the song page, positioned below the current content at [topY]. + * Layout (top to bottom): separator line, abbreviation row, page number row. */ private fun renderReferenceFooter( cb: PdfContentByte, @@ -521,40 +521,44 @@ class PdfBookRenderer : BookRenderer { config: BookConfig, song: Song, leftMargin: Float, - contentWidth: Float, - bottomMargin: Float + topY: Float, + contentWidth: Float ) { val metaFont = fontMetrics.getBaseFont(config.fonts.metadata) val metaSize = config.fonts.metadata.size val lineHeight = metaSize * 1.4f - // Position: just above the page number area - val footerY = bottomMargin + lineHeight * 0.5f - - // Map book IDs to abbreviations - val refAbbreviations = config.referenceBooks.associate { it.id to it.abbreviation } val books = config.referenceBooks // Calculate column widths: evenly distribute across content width val colWidth = contentWidth / books.size - // Row 1: Abbreviation headers + // Draw a thin separator line at the top of the footer + val lineY = topY + cb.setLineWidth(0.3f) + cb.setColorStroke(Color.LIGHT_GRAY) + cb.moveTo(leftMargin, lineY) + cb.lineTo(leftMargin + contentWidth, lineY) + cb.stroke() + + // Row 1: Abbreviation headers (below the separator line) + val abbrY = lineY - lineHeight for ((i, book) in books.withIndex()) { val x = leftMargin + i * colWidth val abbr = book.abbreviation val textWidth = metaFont.getWidthPoint(abbr, metaSize) - // Center text in column val textX = x + (colWidth - textWidth) / 2 cb.beginText() cb.setFontAndSize(metaFont, metaSize) cb.setColorFill(Color.DARK_GRAY) - cb.setTextMatrix(textX, footerY + lineHeight) + cb.setTextMatrix(textX, abbrY) cb.showText(abbr) cb.endText() } - // Row 2: Page numbers + // Row 2: Page numbers (below abbreviation headers) + val numY = abbrY - lineHeight for ((i, book) in books.withIndex()) { val x = leftMargin + i * colWidth val pageNum = song.references[book.id] @@ -566,18 +570,11 @@ class PdfBookRenderer : BookRenderer { cb.beginText() cb.setFontAndSize(metaFont, metaSize) cb.setColorFill(Color.DARK_GRAY) - cb.setTextMatrix(textX, footerY) + cb.setTextMatrix(textX, numY) cb.showText(pageText) cb.endText() } } - - // Draw a thin line above the footer - cb.setLineWidth(0.3f) - cb.setColorStroke(Color.LIGHT_GRAY) - cb.moveTo(leftMargin, footerY + lineHeight * 1.5f) - cb.lineTo(leftMargin + contentWidth, footerY + lineHeight * 1.5f) - cb.stroke() } private fun renderForewordPage( diff --git a/songbook.yaml b/songbook.yaml index 1f6f38c..48e58bc 100644 --- a/songbook.yaml +++ b/songbook.yaml @@ -37,6 +37,9 @@ reference_books: name: "Pfadfinderliederbuch" abbreviation: "PfLB" +toc: + highlight_column: "Seite" + output: directory: "./output" filename: "liederbuch.pdf"