javascriptarraybufferuint8arraypdf-lib.js

why does a Uint8Array() from buffer returns empty?


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()


Solution

  • 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