pdf-lib icon indicating copy to clipboard operation
pdf-lib copied to clipboard

Drawing a line of thickness Number.MIN_VALUE (slightly) corrupts the pdf file

Open andreaswimmer opened this issue 2 years ago • 1 comments

What were you trying to do?

Drawing a line as thin as possible.

How did you attempt to do it?

    page.drawLine({
            start: {x: 0, y: 0},
            end: {x: page.getWidth(), y: page.getHeight()},
            thickness: Number.MIN_VALUE,
        }
    )

What actually happened?

Results depend heavily on the PDF viewer. Chrome, Firefox and SumatraPDF have no problem reading the file.

Adobe Acrobat Reader, Adobe Acrobat Pro DC and PDF-Xchange editor have varying degrees of problems parsing the file. Either giving up, or skipping the rest of the current page.

What did you expect to happen?

Interestingly, drawing a line with silly values of thickness like 0 or 0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001 does work fine. It is only Number.MIN_VALUE that corrupts the file.

How can we reproduce the issue?

import {PDFDocument} from "pdf-lib";

export async function createCorruptPDF() {
    const jpgUrl = 'https://pdf-lib.js.org/assets/cat_riding_unicorn.jpg'
    const pngUrl = 'https://pdf-lib.js.org/assets/minions_banana_alpha.png'

    const jpgImageBytes = await fetch(jpgUrl).then((res) => res.arrayBuffer())
    const pngImageBytes = await fetch(pngUrl).then((res) => res.arrayBuffer())


    const pdfDoc = await PDFDocument.create()

    const jpgImage = await pdfDoc.embedJpg(jpgImageBytes)
    const pngImage = await pdfDoc.embedPng(pngImageBytes)

    const jpgDims = jpgImage.scale(0.5)
    const pngDims = pngImage.scale(0.5)

    const page = pdfDoc.addPage()

    page.drawImage(jpgImage, {
        x: page.getWidth() / 2 - jpgDims.width / 2,
        y: page.getHeight() / 2 - jpgDims.height / 2 + 250,
        width: jpgDims.width,
        height: jpgDims.height,
    })
    page.drawLine({
            start: {x: 0, y: 0},
            end: {x: page.getWidth(), y: page.getHeight()},
            thickness: Number.MIN_VALUE,
        }
    )
    page.drawImage(pngImage, {
        x: page.getWidth() / 2 - pngDims.width / 2 + 75,
        y: page.getHeight() / 2 - pngDims.height + 250,
        width: pngDims.width,
        height: pngDims.height,
    })

    const pdfBytes = await pdfDoc.save()
    return pdfBytes;
}

Version

1.17.1

What environment are you running pdf-lib in?

Browser

Checklist

  • [X] My report includes a Short, Self Contained, Correct (Compilable) Example.
  • [X] I have attached all PDFs, images, and other files needed to run my SSCCE.

Additional Notes

Here is the resulting file from the code above. semi-corrupted.pdf

andreaswimmer avatar Apr 18 '22 13:04 andreaswimmer

Number.MIN_VALUE is 5-384. Assuming you're using millimeters, this line would become the new smallest observable thing in the universe!?

That said, I would consider this a bug. Looks like numberToString would need to be looked at.

joewestcott avatar Jun 03 '22 09:06 joewestcott