0

I am trying to load a font for pdf-lib to use. In order to use it, i must provide a Uint8Array for pdfDoc.embedFont(font); For some reason, whenever i create the UInt8Array, it returns empty. The ArrayBuffer is returning something so i am quite confused. I am new to JS so my apologies if this is a dumb question.

var request = new XMLHttpRequest();

request.open("GET", "./resources/skill_positioning.json", false);
request.send(null)
const positionData = JSON.parse(request.responseText);

async function createPdf() {
    var fontkit = window.fontkit;
    var pdflib = window.PDFLib;
    const url = './resources/character_sheet_blank.pdf';
    const existingPdfBytes = await fetch(url).then((res) =>
        res.arrayBuffer(),
    );

    const pdfDoc = await pdflib.PDFDocument.load(existingPdfBytes)

    pdfDoc.registerFontkit(fontkit);

    const customFont = fetch('./resources/fonts/arialnb.ttf').then((response) => {
        const buffer = response.arrayBuffer();
        return new Uint8Array(buffer);
    }).then((buffer) => {
        return fontkit.create(buffer);
    }).then((font) => {
        return pdfDoc.embedFont(font);
    }).then((customFont) => {
        const pages = pdfDoc.getPages()
        const firstPage = pages[0]
        const { width, height } = firstPage.getSize()

        var curRow = 1;
        var curCollumn = 0;
            firstPage.drawText('This text was added with JavaScript!', {
            x: positionData.boxes[0].x,
            y: height - (positionData.boxes[0].y + curRow * positionData.row_height),
            size: 110,
            font: customFont,
            color: pdflib.rgb(0.0, 0.0, 0.0),
        })
        return pdfDoc;
    }).then((pdfDoc) => {
        const pdfBytes = pdfDoc.save();
        download(pdfBytes, "character_sheet.pdf");
    })
}

I have tried to create a new Uint8Array from the array buffer, before and after .then()

1 Answers1

0

arrayBuffer() returns a Promise. Therefore you should write

fetch('./resources/fonts/arialnb.ttf').then((response) => {
    return response.arrayBuffer();
}).then((buffer) => {
    return fontkit.create(buffer);
})

Assigning the result of your fetch call to const customFont is meaningless because your last then block in the chain returns nothing.

Also consider using the async/await syntax which makes promise code more intuitive. In fact you are already using async/await in the first half of the function. Why switch back to then chain?

const response = await fetch('./resources/fonts/arialnb.ttf');
const buffer = await response.arrayBuffer();
const font = await fontkit.create(buffer);
const customFont = await pdfDoc.embedFont(font);
//... continue to work with customFont
Ricky Mo
  • 6,285
  • 1
  • 14
  • 30
  • I have already tried all of those. I genuinly do not know why but neither works. The first way you suggested corrupts the entire pdf somehow, as for the second it gives an error: "ont` must be of type `string` or `Uint8Array` or `ArrayBuffer`, but was actually of type `NaN` " which for some reason using .then() seemed to fix – skelyvelocirap Jun 19 '23 at 02:10
  • Those are other questions related to pdf-lib, but for what you asked in this post (array buffer empty), this is how to fix it (you can `console.log(buffer)` to verify). – Ricky Mo Jun 19 '23 at 02:16
  • I am not familiar with pdf-lib, but with a quick glance at the library, it seems you should pass `buffer` directly to `pdfDoc.embedFont(buffer)`, instead of the `Font` class created by `fontkit`. `fontkit` is only used at `pdfDoc.registerFontkit(fontkit)`. I suggest reading the [documentation](https://github.com/Hopding/pdf-lib#embed-font-and-measure-text) of pdf-lib more carefully. – Ricky Mo Jun 19 '23 at 02:22
  • Ughhhhhhhhhhhhh. I am exasperated with myself at this point. I have spent hours trying to understand why it wasn't working. I had done each of the things you proposed as solutions(thank you anyway as it still helped me recognize my mistake). And the issue was basically the last line, not even font related... `const pdfBytes = pdfDoc.save();` should be `const pdfBytes = await pdfDoc.save();` – skelyvelocirap Jun 19 '23 at 02:42
  • sorry for wasting your time and thank you again. – skelyvelocirap Jun 19 '23 at 02:43