This commit was merged in pull request #28.
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
Reference in New Issue
Block a user