HeapsIO / heaps

Heaps : Haxe Game Framework
http://heaps.io
MIT License
3.21k stars 338 forks source link

JS: FontBuilder artifacts #936

Open zommerfelds opened 3 years ago

zommerfelds commented 3 years ago

Hi!

I'm trying to use FontBuilder like this:

font = hxd.res.FontBuilder.getFont("garineldo", 30);

I'm loading the font via HTML and CSS like this:

@font-face {
    font-family: garineldo;
    src: url("res/Garineldo.otf") format("opentype");
}

.customfont {
    font-family: "pompiere";
}
<div class="customfont" style="visibility: hidden;">Load font</div>

Unfortunately, I'm getting weird font pieces being drawn wrong, like this:

image

The problem seems to be dependent on the font size. This happens with others fonts as well, like Pompiere-Regular.

It looks like the font bitmap generation code might have a bug? If it helps I can setup a demo app with the issue.

zommerfelds commented 3 years ago

I was just playing around with this newer font metrics API: https://developer.mozilla.org/en-US/docs/Web/API/TextMetrics

See demo in https://codepen.io/christianzom/pen/vYyzBPQ?editors=1010 (pasted code below for the record).

Would it be an option to use those new metrics given the API is pretty new? I think it is hard to draw characters at the right place, since some characters extend backwards in the X coordinate (see demo of a "p" above). It might be best to draw each letter individually to a canvas with a safety margin, then transfer the output using the textmetrics to the main texture. What do you think?

BTW, there is this related past issue here: https://github.com/HeapsIO/heaps/pull/390

var font = '500px Tangerine';

document.fonts.load(font).then(() => {

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.font = font;
ctx.strokeStyle = 'red';

let text = 'p';
ctx.textBaseline = 'bottom';
let textMetrics = ctx.measureText(text);
console.log(textMetrics);
ctx.beginPath();
let x = 50, y = 300;
ctx.fillText(text, x, y);
let l = -textMetrics.actualBoundingBoxLeft;
let r = textMetrics.actualBoundingBoxRight;
let b = -textMetrics.actualBoundingBoxDescent;
let t = -textMetrics.actualBoundingBoxAscent;

ctx.lineWidth = 2;
ctx.rect(x + l, y + t, r - l, b - t)
ctx.stroke();

ctx.beginPath();
ctx.arc(x, y, 3, 0, 2 * Math.PI, false);
ctx.fillStyle = 'red';
ctx.fill();

})

image

zommerfelds commented 3 years ago

Hmm, never mind (yet) about using the new API: Haxe doesn't have those experimental fields available yet (https://github.com/HaxeFoundation/haxe/issues/10166)