From 9f601fcbcfa16c38dd8302bf9baeb4365db88c1e Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Tue, 20 Jul 2021 01:43:39 +0200 Subject: [PATCH] LibTTF+LibGfx: Improve vertical alignment of glyphs Before this patch, some glyphs had a weird off-by-1 vertical position which looked really jarring at small font sizes. This was caused by glyph bitmaps having different heights from each other. (Each glyph bitmap was minimally sized to fit only the glyph itself, and then vertically positioned during the paint phase. Since this vertical positioning was integer based, subpixel precision was lost and things ended up looking wonky.) Fix this by making all glyph bitmaps be the same height so we can blit them at the same integer y position. We use the typographic ascent from the OS/2 table to transform the glyph coordinates. The end result is a huge improvement visually. :^) --- Userland/Libraries/LibGfx/Painter.cpp | 2 +- Userland/Libraries/LibTTF/Font.cpp | 2 +- Userland/Libraries/LibTTF/Glyf.cpp | 6 +++--- Userland/Libraries/LibTTF/Glyf.h | 14 +++++++------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Userland/Libraries/LibGfx/Painter.cpp b/Userland/Libraries/LibGfx/Painter.cpp index f9159daa43..8b995250cc 100644 --- a/Userland/Libraries/LibGfx/Painter.cpp +++ b/Userland/Libraries/LibGfx/Painter.cpp @@ -1160,7 +1160,7 @@ FLATTEN void Painter::draw_glyph(const IntPoint& point, u32 code_point, Color co FLATTEN void Painter::draw_glyph(const IntPoint& point, u32 code_point, const Font& font, Color color) { auto glyph = font.glyph(code_point); - auto top_left = point + IntPoint(glyph.left_bearing(), font.glyph_height() - glyph.ascent()); + auto top_left = point + IntPoint(glyph.left_bearing(), 0); if (glyph.is_glyph_bitmap()) { draw_bitmap(top_left, glyph.glyph_bitmap(), color); diff --git a/Userland/Libraries/LibTTF/Font.cpp b/Userland/Libraries/LibTTF/Font.cpp index 32867bc70a..49734e74aa 100644 --- a/Userland/Libraries/LibTTF/Font.cpp +++ b/Userland/Libraries/LibTTF/Font.cpp @@ -425,7 +425,7 @@ RefPtr Font::rasterize_glyph(u32 glyph_id, float x_scale, float y_s } auto glyph_offset = m_loca.get_glyph_offset(glyph_id); auto glyph = m_glyf.glyph(glyph_offset); - return glyph.rasterize(x_scale, y_scale, [&](u16 glyph_id) { + return glyph.rasterize(m_os2.typographic_ascender(), m_os2.typographic_descender(), x_scale, y_scale, [&](u16 glyph_id) { if (glyph_id >= glyph_count()) { glyph_id = 0; } diff --git a/Userland/Libraries/LibTTF/Glyf.cpp b/Userland/Libraries/LibTTF/Glyf.cpp index 8267ae5776..9ec8e6f586 100644 --- a/Userland/Libraries/LibTTF/Glyf.cpp +++ b/Userland/Libraries/LibTTF/Glyf.cpp @@ -478,12 +478,12 @@ void Glyf::Glyph::rasterize_impl(Rasterizer& rasterizer, Gfx::AffineTransform co rasterizer.draw_path(path); } -RefPtr Glyf::Glyph::rasterize_simple(float x_scale, float y_scale) const +RefPtr Glyf::Glyph::rasterize_simple(i16 font_ascender, i16 font_descender, float x_scale, float y_scale) const { u32 width = (u32)(ceilf((m_xmax - m_xmin) * x_scale)) + 2; - u32 height = (u32)(ceilf((m_ymax - m_ymin) * y_scale)) + 2; + u32 height = (u32)(ceilf((font_ascender - font_descender) * y_scale)) + 2; Rasterizer rasterizer(Gfx::IntSize(width, height)); - auto affine = Gfx::AffineTransform().scale(x_scale, -y_scale).translate(-m_xmin, -m_ymax); + auto affine = Gfx::AffineTransform().scale(x_scale, -y_scale).translate(-m_xmin, -font_ascender); rasterize_impl(rasterizer, affine); return rasterizer.accumulate(); } diff --git a/Userland/Libraries/LibTTF/Glyf.h b/Userland/Libraries/LibTTF/Glyf.h index 1cfdf68ed7..bc9135dd7d 100644 --- a/Userland/Libraries/LibTTF/Glyf.h +++ b/Userland/Libraries/LibTTF/Glyf.h @@ -63,13 +63,13 @@ public: } } template - RefPtr rasterize(float x_scale, float y_scale, GlyphCb glyph_callback) const + RefPtr rasterize(i16 font_ascender, i16 font_descender, float x_scale, float y_scale, GlyphCb glyph_callback) const { switch (m_type) { case Type::Simple: - return rasterize_simple(x_scale, y_scale); + return rasterize_simple(font_ascender, font_descender, x_scale, y_scale); case Type::Composite: - return rasterize_composite(x_scale, y_scale, glyph_callback); + return rasterize_composite(font_ascender, font_descender, x_scale, y_scale, glyph_callback); } VERIFY_NOT_REACHED(); } @@ -102,14 +102,14 @@ public: }; void rasterize_impl(Rasterizer&, Gfx::AffineTransform const&) const; - RefPtr rasterize_simple(float x_scale, float y_scale) const; + RefPtr rasterize_simple(i16 ascender, i16 descender, float x_scale, float y_scale) const; template - RefPtr rasterize_composite(float x_scale, float y_scale, GlyphCb glyph_callback) const + RefPtr rasterize_composite(i16 font_ascender, i16 font_descender, float x_scale, float y_scale, GlyphCb glyph_callback) const { u32 width = (u32)(ceilf((m_xmax - m_xmin) * x_scale)) + 1; - u32 height = (u32)(ceilf((m_ymax - m_ymin) * y_scale)) + 1; + u32 height = (u32)(ceilf((font_ascender - font_descender) * y_scale)) + 1; Rasterizer rasterizer(Gfx::IntSize(width, height)); - auto affine = Gfx::AffineTransform().scale(x_scale, -y_scale).translate(-m_xmin, -m_ymax); + auto affine = Gfx::AffineTransform().scale(x_scale, -y_scale).translate(-m_xmin, -font_ascender); ComponentIterator component_iterator(m_slice); while (true) { auto opt_item = component_iterator.next();