How to add custom font into pdf-lib

57 views Asked by At

I am attempting to add a custom font to the pdf-lib library, but I am encountering an error: 'Unknown font format.' I have tried TTF, OTF, WOFF, and WOFF2 fromats, but none of them seem to work. Could someone please help me identify what I might be doing wrong in this process?

  const url = "./Roboto-Italic.ttf";
  const fontBytes = await fetch(url).then((res) => res.arrayBuffer());
  pdfDoc.registerFontkit(fontkit);
  const font = await pdfDoc.embedFont(fontBytes);

error:

    at Object.create (http://localhost:3000/main.86466a5e8eefe1529961.hot-update.js:8806:11)
    at Function.<anonymous> (http://localhost:3000/main.86466a5e8eefe1529961.hot-update.js:47584:42)
    at step (http://localhost:3000/main.86466a5e8eefe1529961.hot-update.js:56459:17)
    at Object.next (http://localhost:3000/main.86466a5e8eefe1529961.hot-update.js:56408:14)
    at http://localhost:3000/main.86466a5e8eefe1529961.hot-update.js:56382:67
    at new Promise (<anonymous>)
    at __awaiter (http://localhost:3000/main.86466a5e8eefe1529961.hot-update.js:56364:10)
    at CustomFontEmbedder.for (http://localhost:3000/main.86466a5e8eefe1529961.hot-update.js:47579:60)
    at PDFDocument.<anonymous> (http://localhost:3000/main.86466a5e8eefe1529961.hot-update.js:35659:91)
    at step (http://localhost:3000/main.86466a5e8eefe1529961.hot-update.js:56459:17)
1

There are 1 answers

0
K J On

Most PDF libraries will use a TTF font for PDF mapping "ToUnicode". but there are security restrictions on imbedding binary fonts from external sources into a text based carrier like a PDF wrapper.

PDF-LIB uses a fontkit which needs to do the necessary embedding of pulling a remote untainted binary.ttf into a clients text based HTML editor. So follow the guides for adding more than the font-less 14 Standard Fonts embedded in PDF Viewers / Reader-editors.

enter image description here enter image description here

Beware as shown above some fonts may not work well without some fettling so for example this Ballet font thinks its Ball et

<html><head><meta charset="utf-8" />
  <script src="https://unpkg.com/[email protected]"></script>
  <script src="https://unpkg.com/@pdf-lib/[email protected]"></script>
  <script src="https://unpkg.com/[email protected]"></script>
    <style>
      body {width: 100vw;height: 100vh;display: flex;justify-content: center;lign-items: center;flex-direction: column;}
      p {font-family: helvetica;font-size: 24px;text-align: center;margin: 25px;}
      .small {font-family: helvetica;font-size: 18px;text-align: center;margin: 25px;}
      button {background-color: #008CBA;border: none;color: white;padding: 15px 32px;text-align: center;font-size: 16px;}
    </style>
</head>
<body>
      <p>Click the button to embed a custom font and measure text drawn in that font with <code>pdf-lib</code></p>
      <button onclick="embedFontAndMeasureText()">Create PDF</button>
      <p class="small">(Your browser will download the resulting file)</p>
</body>

  <script>
    const { PDFDocument, rgb } = PDFLib

    async function embedFontAndMeasureText() {
      const url = 'https://fonts.cdnfonts.com/s/107471/Ballet[opsz].ttf' // Fetch custom font from FULL UNTAINTED URL
      const fontBytes = await fetch(url).then(res => res.arrayBuffer())
      const pdfDoc = await PDFDocument.create() // Create a new PDFDocument
      pdfDoc.registerFontkit(fontkit)  // Register the `fontkit` instance
      const Font15 = await pdfDoc.embedFont(fontBytes)  // Embed custom font in the doc in addition to 14 standard ones

      const page = pdfDoc.addPage()  // Add a blank page to the document

      const text = 'This  is  text  in  remote  embedded  Ballet  font!'  // Create a string of plain text 
      const textSize = 30
      const textWidth = Font15.widthOfTextAtSize(text, textSize) // measure text at size at its custom width and height
      const textHeight = Font15.heightAtSize(textSize)

      // Draw the string of text using Font_15 on the page
      page.drawText(text, {
        x: 40,
        y: 450,
        size: textSize,
        font: Font15,
        color: rgb(0.25, 0.50, 0.75),
      })

      // Draw a box around the string of text
      page.drawRectangle({
        x: 40,
        y: 450,
        width: textWidth,
        height: textHeight,
        borderColor: rgb(1, 0, 0),
        borderWidth: 1.5,
      })

      // Serialize the PDFDocument to bytes (a Uint8Array)
      const pdfBytes = await pdfDoc.save()

            // Trigger the browser to download the PDF document
      download(pdfBytes, "pdf-lib_creation_example.pdf", "application/pdf");
    }
  </script>
</html>