Proposal for font support in Web Workers

Currently, the getFontOffset() function in Engine requires access to the document element and is thus not compatible with web workers. In my own app I use the following code to patch it inside the web worker:

import { Engine } from "@babylonjs/core/Engines/engine";

let canvas: OffscreenCanvas|null = null;
let ctx: OffscreenCanvasRenderingContext2D|null = null;

interface FontOffset {
    ascent: number
    height: number
    descent: number
}

function getFontOffset(font: string): FontOffset {
    if (!canvas || !ctx) {
        canvas = new OffscreenCanvas(64,64);
        ctx = canvas.getContext('2d'); 
        if (!ctx) {
            throw Error('2D context in offscreen not available!')
        }
    }

    ctx.font = font;
    ctx.textBaseline = "alphabetic";
    const descent = ctx.measureText('Hg').actualBoundingBoxDescent;
    ctx.textBaseline = "bottom";
    const ascent = ctx.measureText('Hg').actualBoundingBoxAscent;
    return { ascent: ascent, height: ascent + descent, descent: descent };
}

export function patchEngine(engine: Engine) {
    engine.getFontOffset = getFontOffset;
}

This code works fine for me, but creates different results compared to the original one. E.g. for “18px Arial” on Chrome/Windows the original code produces {ascent: 16, height: 21, descent: 5}, whereas my code {ascent: 17.03125, descent: 4, height: 21.03125}.

Since I don’t know if this would create any problem and have zero experience with pull requests I thought I post the code here instead.

@carolhmj and @RaananW you might find this one interesting for the GUI

Actually would be great to always use offscreenCanvas for gui and the like of it when available ?

1 Like

That’s a good idea :thinking: