From 4c276e07f570ee6a727f88dcc67251823895c671 Mon Sep 17 00:00:00 2001 From: Caleb Hearon Date: Mon, 2 Jan 2023 17:50:32 -0500 Subject: [PATCH] fix incorrect text width with newer (1.43?) Pango Text renders wider or narrower, as if letter-spacing is set, than it should with newer versions of Pango. My best understanding of this problem is that around version 1.43 Pango dropped support for font hinting because it switched to Harbuzz for glyph postions instead of Freetype. For some reason it still rounds the glyph positions by default. There's no need for node-canvas to support font hinting. The maintainers of the Linux font stack (Behdad and Matthias) have stated that they wont, and font hinting is subjective, and browsers have moved to subpixel positioning too. Reading (warning: lots of drama to wade through): - https://gitlab.gnome.org/GNOME/pango/-/issues/404 - https://gitlab.gnome.org/GNOME/pango/-/issues/463 - https://github.com/harfbuzz/harfbuzz/issues/1892 - https://github.com/harfbuzz/harfbuzz/issues/2394 --- CHANGELOG.md | 1 + src/CanvasRenderingContext2d.cc | 7 +++++++ test/public/tests.js | 5 +++++ 3 files changed, 13 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 484dca949..4222c6ffd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ project adheres to [Semantic Versioning](http://semver.org/). ### Added ### Fixed * Add missing property `canvas` to the `CanvasRenderingContext2D` type +* Fixed glyph positions getting rounded, resulting text having a slight `letter-spacing` effect 2.11.0 ================== diff --git a/src/CanvasRenderingContext2d.cc b/src/CanvasRenderingContext2d.cc index 699ec88fc..c40b00fc2 100644 --- a/src/CanvasRenderingContext2d.cc +++ b/src/CanvasRenderingContext2d.cc @@ -171,6 +171,13 @@ Context2d::Context2d(Canvas *canvas) { _canvas = canvas; _context = canvas->createCairoContext(); _layout = pango_cairo_create_layout(_context); + + // As of January 2023, Pango rounds glyph positions which renders text wider + // or narrower than the browser. See #2184 for more information +#if PANGO_VERSION_CHECK(1, 44, 0) + pango_context_set_round_glyph_positions(pango_layout_get_context(_layout), FALSE); +#endif + states.emplace(); state = &states.top(); pango_layout_set_font_description(_layout, state->fontDescription); diff --git a/test/public/tests.js b/test/public/tests.js index 651105e36..d24202602 100644 --- a/test/public/tests.js +++ b/test/public/tests.js @@ -2693,6 +2693,11 @@ tests['measureText()'] = function (ctx) { drawWithBBox('right', 195, 195) } +tests['glyph advances (#2184)'] = function (ctx) { + ctx.font = '8px Arial' + ctx.fillText('A float is a box that is shifted to the left or right on the current line.', 0, 8) +} + tests['image sampling (#1084)'] = function (ctx, done) { let loaded1, loaded2 const img1 = new Image()