feat: support inline images within song pages (Closes #2)
Add {image: path} directive to embed images at any position within a song's
sections. SongLine gains an optional imagePath field; when set, the line
represents an inline image rather than chord/lyric content. The renderer
scales and centers images within the content width. MeasurementEngine
reserves 40mm height per inline image for layout calculations.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit was merged in pull request #13.
This commit is contained in:
@@ -43,15 +43,21 @@ class MeasurementEngine(
|
||||
|
||||
// Lines in section
|
||||
for (line in section.lines) {
|
||||
val hasChords = line.segments.any { it.chord != null }
|
||||
val lyricHeight = fontMetrics.measureLineHeight(config.fonts.lyrics, config.fonts.lyrics.size)
|
||||
if (hasChords) {
|
||||
val chordHeight = fontMetrics.measureLineHeight(config.fonts.chords, config.fonts.chords.size)
|
||||
heightMm += chordHeight + config.layout.chordLineSpacing + lyricHeight
|
||||
if (line.imagePath != null) {
|
||||
// Inline image: estimate height as 40mm (default image block height)
|
||||
heightMm += 40f
|
||||
heightMm += 2f // gap around image
|
||||
} else {
|
||||
heightMm += lyricHeight
|
||||
val hasChords = line.segments.any { it.chord != null }
|
||||
val lyricHeight = fontMetrics.measureLineHeight(config.fonts.lyrics, config.fonts.lyrics.size)
|
||||
if (hasChords) {
|
||||
val chordHeight = fontMetrics.measureLineHeight(config.fonts.chords, config.fonts.chords.size)
|
||||
heightMm += chordHeight + config.layout.chordLineSpacing + lyricHeight
|
||||
} else {
|
||||
heightMm += lyricHeight
|
||||
}
|
||||
heightMm += 0.35f // ~1pt gap between lines
|
||||
}
|
||||
heightMm += 0.35f // ~1pt gap between lines
|
||||
}
|
||||
|
||||
// Verse spacing
|
||||
|
||||
@@ -324,4 +324,40 @@ class MeasurementEngineTest {
|
||||
// Should be the same since no reference books are configured
|
||||
heightWith shouldBe heightWithout
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `inline image adds significant height`() {
|
||||
val songWithImage = Song(
|
||||
title = "With Image",
|
||||
sections = listOf(
|
||||
SongSection(
|
||||
type = SectionType.VERSE,
|
||||
lines = listOf(
|
||||
SongLine(listOf(LineSegment(text = "Line before"))),
|
||||
SongLine(imagePath = "images/test.png"),
|
||||
SongLine(listOf(LineSegment(text = "Line after")))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
val songWithoutImage = Song(
|
||||
title = "No Image",
|
||||
sections = listOf(
|
||||
SongSection(
|
||||
type = SectionType.VERSE,
|
||||
lines = listOf(
|
||||
SongLine(listOf(LineSegment(text = "Line before"))),
|
||||
SongLine(listOf(LineSegment(text = "Line after")))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
val heightWith = engine.measure(songWithImage).totalHeightMm
|
||||
val heightWithout = engine.measure(songWithoutImage).totalHeightMm
|
||||
|
||||
// Inline image adds ~42mm (40mm image + 2mm gap)
|
||||
val diff = heightWith - heightWithout
|
||||
diff shouldBeGreaterThan 30f // should be substantial
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user