Skip to content

Commit

Permalink
Fix regression in PDF HTML tag handling.
Browse files Browse the repository at this point in the history
pdf-lib differs from jspdf in that one call to drawText does not adjust
the x offset for future text. We need to track the x offset by measuring
text width and keeping an internal record for each drawText call.

See #34
  • Loading branch information
jpd236 committed Aug 13, 2023
1 parent 55cf79c commit b40f39d
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ expect class PdfDocument private constructor() {
suspend fun getTextWidth(text: String, font: PdfFont, size: Float): Float

/** Draw and stroke the given [text]. */
fun drawText(text: String)
suspend fun drawText(text: String)

/** Set the line width. */
fun setLineWidth(width: Float)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ class PdfTest {
)
}

@Test
fun asPdf_html() = runTest {
ImageComparator.assertPdfEquals(
readBinaryResource(ImageComparator::class, "pdf/test-html.pdf"),
JpzFile(readBinaryResource(PdfTest::class, "jpz/test-html.jpz"))
.asPuzzle().asPdf(blackSquareLightnessAdjustment = 0.75f, fontFamily = getNotoSerifFontFamily())
)
}

// Note for splitTextToLines tests: a 100 pt line fits 16 10pt Courier characters.

@Test
Expand Down
119 changes: 119 additions & 0 deletions src/commonTest/resources/jpz/test-html.jpz
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<?xml version="1.0" encoding="UTF-8"?>
<crossword-compiler xmlns="http://crossword.info/xml/crossword-compiler">
<rectangular-puzzle xmlns="http://crossword.info/xml/rectangular-puzzle">
<metadata>
<title>Example Puzzle for Kotwords</title>
<creator>Jeff Davidson</creator>
<copyright>© 2018 Jeff Davidson</copyright>
<description>Notepad text goes here.</description>
</metadata>
<crossword>
<grid width="5" height="5">
<grid-look numbering-scheme="normal" cell-size-in-pixels="26" clue-square-divider-width="0.7"/>
<cell x="1" y="1" solution="A" number="1"/>
<cell x="2" y="1" solution="B" number="2"/>
<cell x="3" y="1" solution="C" number="3"/>
<cell x="4" y="1" solution="D" number="4"/>
<cell x="5" y="1" type="block"/>
<cell x="1" y="2" solution="E" number="5"/>
<cell x="2" y="2" solution="F"/>
<cell x="3" y="2" solution="G"/>
<cell x="4" y="2" solution="H"/>
<cell x="5" y="2" type="block"/>
<cell x="1" y="3" solution="I" number="6" background-shape="circle"/>
<cell x="2" y="3" solution="J"/>
<cell x="3" y="3" solution="XYZ"/>
<cell x="4" y="3" solution="L"/>
<cell x="5" y="3" solution="M" number="7" background-shape="circle"/>
<cell x="1" y="4" type="block"/>
<cell x="2" y="4" solution="N" number="8"/>
<cell x="3" y="4" solution="O"/>
<cell x="4" y="4" solution="P"/>
<cell x="5" y="4" solution="Q"/>
<cell x="1" y="5" type="block"/>
<cell x="2" y="5" solution="1" number="9"/>
<cell x="3" y="5" solution="2"/>
<cell x="4" y="5" solution="$"/>
<cell x="5" y="5" solution="@"/>
</grid>
<word id="1">
<cells x="1" y="1"/>
<cells x="2" y="1"/>
<cells x="3" y="1"/>
<cells x="4" y="1"/>
</word>
<word id="5">
<cells x="1" y="2"/>
<cells x="2" y="2"/>
<cells x="3" y="2"/>
<cells x="4" y="2"/>
</word>
<word id="6">
<cells x="1" y="3"/>
<cells x="2" y="3"/>
<cells x="3" y="3"/>
<cells x="4" y="3"/>
<cells x="5" y="3"/>
</word>
<word id="8">
<cells x="2" y="4"/>
<cells x="3" y="4"/>
<cells x="4" y="4"/>
<cells x="5" y="4"/>
</word>
<word id="9">
<cells x="2" y="5"/>
<cells x="3" y="5"/>
<cells x="4" y="5"/>
<cells x="5" y="5"/>
</word>
<word id="1001">
<cells x="1" y="1"/>
<cells x="1" y="2"/>
<cells x="1" y="3"/>
</word>
<word id="1002">
<cells x="2" y="1"/>
<cells x="2" y="2"/>
<cells x="2" y="3"/>
<cells x="2" y="4"/>
<cells x="2" y="5"/>
</word>
<word id="1003">
<cells x="3" y="1"/>
<cells x="3" y="2"/>
<cells x="3" y="3"/>
<cells x="3" y="4"/>
<cells x="3" y="5"/>
</word>
<word id="1004">
<cells x="4" y="1"/>
<cells x="4" y="2"/>
<cells x="4" y="3"/>
<cells x="4" y="4"/>
<cells x="4" y="5"/>
</word>
<word id="1007">
<cells x="5" y="3"/>
<cells x="5" y="4"/>
<cells x="5" y="5"/>
</word>
<clues ordering="normal">
<title><b>Across</b></title>
<clue word="1" number="1">First across clue with <b>bold</b>, <i>italic</i>, and <b><i>bold italic</i></b> text</clue>
<clue word="5" number="5">Second across clue with <sub>subscript</sub> and <sup>superscript</sup></clue>
<clue word="6" number="6">Third across clue with <sub><i>italic subscript</i></sub> and more</clue>
<clue word="8" number="8">Fourth across clue</clue>
<clue word="9" number="9">Fifth across clue</clue>
</clues>
<clues ordering="normal">
<title><b>Down</b></title>
<clue word="1001" number="1">First down clue</clue>
<clue word="1002" number="2">Second down clue</clue>
<clue word="1003" number="3">Third down clue</clue>
<clue word="1004" number="4">Fourth down clue</clue>
<clue word="1007" number="7">Fifth down clue</clue>
</clues>
</crossword>
</rectangular-puzzle>
</crossword-compiler>
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,15 @@ actual class PdfDocument {
private lateinit var page: PDFPage

private var currentFont: PDFFont? = null
private var fontSize: Float = 0f
private val loadedFonts = mutableMapOf<PdfFont, PDFFont>()

private var lineWidth: Float = 1f
private var strokeColor: RGB = rgb(0f, 0f, 0f)
private var fillColor: RGB = rgb(1f, 1f, 1f)

private var xOffset: Float = 0f

private suspend fun init() {
pdf = PDFDocument.create().await()
pdf.registerFontkit(FontkitModule.default)
Expand All @@ -42,18 +45,21 @@ actual class PdfDocument {
actual val height: Float get() = page.getHeight()

actual fun beginText() {
xOffset = 0f
page.moveTo(0f, 0f)
}

actual fun endText() {}

actual fun newLineAtOffset(offsetX: Float, offsetY: Float) {
page.moveRight(offsetX)
page.moveRight(offsetX - xOffset)
xOffset = 0f
page.moveUp(offsetY)
}

actual suspend fun setFont(font: PdfFont, size: Float) {
setFont(font)
fontSize = size
page.setFontSize(size)
}

Expand Down Expand Up @@ -91,8 +97,11 @@ actual class PdfDocument {
return loadFont(font).widthOfTextAtSize(text, size)
}

actual fun drawText(text: String) {
actual suspend fun drawText(text: String) {
page.drawText(text)
val width = currentFont!!.widthOfTextAtSize(text, fontSize)
xOffset += width
page.moveRight(width)
}

actual fun setLineWidth(width: Float) {
Expand Down
Binary file added src/jsTest/resources/pdf/test-html.pdf
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ actual class PdfDocument {
return font.toPdfFont().getStringWidth(text) * size / 1000
}

actual fun drawText(text: String) {
actual suspend fun drawText(text: String) {
content.showText(text)
}

Expand Down
Binary file added src/jvmTest/resources/pdf/test-html.pdf
Binary file not shown.

0 comments on commit b40f39d

Please sign in to comment.