diff --git a/index.js b/index.js index 08bd44a..5a56c46 100644 --- a/index.js +++ b/index.js @@ -55,7 +55,7 @@ export default class TinySDF { const glyphLeft = 0; // If the glyph overflows the canvas size, it will be clipped at the bottom/right - const glyphWidth = Math.min(this.size - this.buffer, Math.ceil(actualBoundingBoxRight - actualBoundingBoxLeft)); + const glyphWidth = Math.max(0, Math.min(this.size - this.buffer, Math.ceil(actualBoundingBoxRight - actualBoundingBoxLeft))); const glyphHeight = Math.min(this.size - this.buffer, glyphTop + Math.ceil(actualBoundingBoxDescent)); const width = glyphWidth + 2 * this.buffer; diff --git a/test/test.js b/test/test.js index 2281706..f197483 100644 --- a/test/test.js +++ b/test/test.js @@ -89,3 +89,22 @@ test('does not crash on diacritic marks', (t) => { sdf.draw('G̱'[1]); t.end(); }); + +test('does not return negative-width glylphs', (t) => { + const sdf = new MockTinySDF(); + // stub these because they vary across environments + sdf.ctx.measureText = () => ({ + width: 0, + actualBoundingBoxLeft: 23.3759765625, + actualBoundingBoxRight: -17.6162109375, + actualBoundingBoxAscent: 20.2080078125, + actualBoundingBoxDescent: -14.51953125, + emHeightAscent: 26, + emHeightDescent: 9, + alphabeticBaseline: 7.51953125 + }); + const glyph = sdf.draw('゙'); + t.equal(glyph.glyphWidth, 0); + t.equal(glyph.width, 6); // zero-width glyph with 3px buffer + t.end(); +});