fix: position reference footer below content to prevent overlap (Closes #25) (#28)

This commit was merged in pull request #28.
This commit is contained in:
2026-03-17 14:59:48 +01:00
parent a251fac053
commit 032387c02d
3 changed files with 28 additions and 28 deletions

View File

@@ -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()) { if (config.referenceBooks.isNotEmpty() && song.references.isNotEmpty()) {
val metaLineHeight = fontMetrics.measureLineHeight(config.fonts.metadata, config.fonts.metadata.size) 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 * 1.4f * 2 // two rows (headers + numbers)
heightMm += metaLineHeight * 0.5f // separator line gap
} }
val pageCount = if (heightMm <= contentHeightMm) 1 else 2 val pageCount = if (heightMm <= contentHeightMm) 1 else 2

View File

@@ -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()) { if (config.referenceBooks.isNotEmpty() && song.references.isNotEmpty()) {
val lineHeight = metaSize * 1.4f val lineHeight = metaSize * 1.4f
reserved += 4f // gap before footer
reserved += lineHeight * 2 // two rows (headers + numbers) reserved += lineHeight * 2 // two rows (headers + numbers)
reserved += lineHeight * 1.5f // separator line gap
reserved += lineHeight * 0.5f // bottom gap
} }
return reserved return reserved
@@ -474,10 +473,10 @@ class PdfBookRenderer : BookRenderer {
// Render reference book footer on the last page of the song // Render reference book footer on the last page of the song
if (config.referenceBooks.isNotEmpty() && song.references.isNotEmpty() && isLastPage) { if (config.referenceBooks.isNotEmpty() && song.references.isNotEmpty() && isLastPage) {
y -= 4f // gap before reference footer
renderReferenceFooter( renderReferenceFooter(
cb, fontMetrics, config, song, cb, fontMetrics, config, song,
leftMargin, contentWidth, leftMargin, y, contentWidth
bottomMargin
) )
} }
} }
@@ -512,8 +511,9 @@ class PdfBookRenderer : BookRenderer {
} }
/** /**
* Renders reference book abbreviations and page numbers as a footer row * Renders reference book abbreviations and page numbers as a footer
* at the bottom of the song page, above the page number. * 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( private fun renderReferenceFooter(
cb: PdfContentByte, cb: PdfContentByte,
@@ -521,40 +521,44 @@ class PdfBookRenderer : BookRenderer {
config: BookConfig, config: BookConfig,
song: Song, song: Song,
leftMargin: Float, leftMargin: Float,
contentWidth: Float, topY: Float,
bottomMargin: Float contentWidth: Float
) { ) {
val metaFont = fontMetrics.getBaseFont(config.fonts.metadata) val metaFont = fontMetrics.getBaseFont(config.fonts.metadata)
val metaSize = config.fonts.metadata.size val metaSize = config.fonts.metadata.size
val lineHeight = metaSize * 1.4f 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 val books = config.referenceBooks
// Calculate column widths: evenly distribute across content width // Calculate column widths: evenly distribute across content width
val colWidth = contentWidth / books.size 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()) { for ((i, book) in books.withIndex()) {
val x = leftMargin + i * colWidth val x = leftMargin + i * colWidth
val abbr = book.abbreviation val abbr = book.abbreviation
val textWidth = metaFont.getWidthPoint(abbr, metaSize) val textWidth = metaFont.getWidthPoint(abbr, metaSize)
// Center text in column
val textX = x + (colWidth - textWidth) / 2 val textX = x + (colWidth - textWidth) / 2
cb.beginText() cb.beginText()
cb.setFontAndSize(metaFont, metaSize) cb.setFontAndSize(metaFont, metaSize)
cb.setColorFill(Color.DARK_GRAY) cb.setColorFill(Color.DARK_GRAY)
cb.setTextMatrix(textX, footerY + lineHeight) cb.setTextMatrix(textX, abbrY)
cb.showText(abbr) cb.showText(abbr)
cb.endText() cb.endText()
} }
// Row 2: Page numbers // Row 2: Page numbers (below abbreviation headers)
val numY = abbrY - lineHeight
for ((i, book) in books.withIndex()) { for ((i, book) in books.withIndex()) {
val x = leftMargin + i * colWidth val x = leftMargin + i * colWidth
val pageNum = song.references[book.id] val pageNum = song.references[book.id]
@@ -566,18 +570,11 @@ class PdfBookRenderer : BookRenderer {
cb.beginText() cb.beginText()
cb.setFontAndSize(metaFont, metaSize) cb.setFontAndSize(metaFont, metaSize)
cb.setColorFill(Color.DARK_GRAY) cb.setColorFill(Color.DARK_GRAY)
cb.setTextMatrix(textX, footerY) cb.setTextMatrix(textX, numY)
cb.showText(pageText) cb.showText(pageText)
cb.endText() 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( private fun renderForewordPage(

View File

@@ -37,6 +37,9 @@ reference_books:
name: "Pfadfinderliederbuch" name: "Pfadfinderliederbuch"
abbreviation: "PfLB" abbreviation: "PfLB"
toc:
highlight_column: "Seite"
output: output:
directory: "./output" directory: "./output"
filename: "liederbuch.pdf" filename: "liederbuch.pdf"