From 85158dc0ad9c62f470fa1462623e43747c2bf8ac Mon Sep 17 00:00:00 2001 From: Stephan Unverwerth Date: Sat, 2 Jan 2021 18:22:22 +0100 Subject: [PATCH] LibGfx+LibTTF: Allow Painter to draw TTF glyphs --- Userland/Libraries/LibGfx/Font.h | 11 +++++++- Userland/Libraries/LibGfx/Painter.cpp | 11 +++++++- Userland/Libraries/LibTTF/CMakeLists.txt | 2 +- Userland/Libraries/LibTTF/Font.cpp | 32 +++++++++++++++++++++++- Userland/Libraries/LibTTF/Font.h | 24 ++++++++++-------- 5 files changed, 66 insertions(+), 14 deletions(-) diff --git a/Userland/Libraries/LibGfx/Font.h b/Userland/Libraries/LibGfx/Font.h index 678e039cee..2ec7fece4d 100644 --- a/Userland/Libraries/LibGfx/Font.h +++ b/Userland/Libraries/LibGfx/Font.h @@ -75,18 +75,27 @@ public: { } - Glyph(RefPtr bitmap) + Glyph(RefPtr bitmap, int left_bearing, int advance, int ascent) : m_bitmap(bitmap) + , m_left_bearing(left_bearing) + , m_advance(advance) + , m_ascent(ascent) { } bool is_glyph_bitmap() const { return !m_bitmap; } GlyphBitmap glyph_bitmap() const { return m_glyph_bitmap; } RefPtr bitmap() const { return m_bitmap; } + int left_bearing() const { return m_left_bearing; } + int advance() const { return m_advance; } + int ascent() const { return m_ascent; } private: GlyphBitmap m_glyph_bitmap; RefPtr m_bitmap; + int m_left_bearing; + int m_advance; + int m_ascent; }; class Font : public RefCounted { diff --git a/Userland/Libraries/LibGfx/Painter.cpp b/Userland/Libraries/LibGfx/Painter.cpp index bdf40d2fda..3780ea6d6a 100644 --- a/Userland/Libraries/LibGfx/Painter.cpp +++ b/Userland/Libraries/LibGfx/Painter.cpp @@ -900,7 +900,16 @@ 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) { - draw_bitmap(point, font.glyph(code_point).glyph_bitmap(), color); + auto glyph = font.glyph(code_point); + if (glyph.is_glyph_bitmap()) { + draw_bitmap(point, glyph.glyph_bitmap(), color); + } else { + auto top_left = point + IntPoint(glyph.left_bearing(), font.x_height() - glyph.ascent()); + + blit_filtered(top_left, *glyph.bitmap(), glyph.bitmap()->rect(), [color](Color pixel) -> Color { + return pixel.multiply(color); + }); + } } void Painter::draw_emoji(const IntPoint& point, const Gfx::Bitmap& emoji, const Font& font) diff --git a/Userland/Libraries/LibTTF/CMakeLists.txt b/Userland/Libraries/LibTTF/CMakeLists.txt index f4233e2760..2fe3d94647 100644 --- a/Userland/Libraries/LibTTF/CMakeLists.txt +++ b/Userland/Libraries/LibTTF/CMakeLists.txt @@ -5,4 +5,4 @@ set(SOURCES ) serenity_lib(LibTTF ttf) -target_link_libraries(LibGfx LibM LibCore) +target_link_libraries(LibTTF LibM LibCore) diff --git a/Userland/Libraries/LibTTF/Font.cpp b/Userland/Libraries/LibTTF/Font.cpp index cfed406f61..aa7166683b 100644 --- a/Userland/Libraries/LibTTF/Font.cpp +++ b/Userland/Libraries/LibTTF/Font.cpp @@ -481,6 +481,35 @@ String Font::variant() const return m_name.subfamily_name(); } +u16 Font::weight() const +{ + // FIXME: This is pretty naive, read weight from the actual font table(s) + auto variant_name = variant(); + + if (variant_name == "Thin") + return 100; + if (variant_name == "Extra Light") + return 200; + if (variant_name == "Light") + return 300; + if (variant_name == "Regular") + return 400; + if (variant_name == "Medium") + return 500; + if (variant_name == "Semi Bold") + return 600; + if (variant_name == "Bold") + return 700; + if (variant_name == "Extra Bold") + return 800; + if (variant_name == "Black") + return 900; + if (variant_name == "Extra Black") + return 950; + + return 400; +} + int ScaledFont::width(const StringView& string) const { Utf8View utf8 { string }; @@ -524,7 +553,8 @@ Gfx::Glyph ScaledFont::glyph(u32 code_point) const { auto id = glyph_id_for_codepoint(code_point); auto bitmap = raster_glyph(id); - return Gfx::Glyph(bitmap); + auto metrics = glyph_metrics(id); + return Gfx::Glyph(bitmap, metrics.left_side_bearing, metrics.advance_width, metrics.ascender); } u8 ScaledFont::glyph_width(size_t code_point) const diff --git a/Userland/Libraries/LibTTF/Font.h b/Userland/Libraries/LibTTF/Font.h index 3fe3b5be03..c954e2d2dc 100644 --- a/Userland/Libraries/LibTTF/Font.h +++ b/Userland/Libraries/LibTTF/Font.h @@ -123,6 +123,8 @@ class ScaledFont : public Gfx::Font { public: ScaledFont(RefPtr font, float point_width, float point_height, unsigned dpi_x = DEFAULT_DPI, unsigned dpi_y = DEFAULT_DPI) : m_font(font) + , m_point_width(point_width) + , m_point_height(point_height) { float units_per_em = m_font->units_per_em(); m_x_scale = (point_width * dpi_x) / (POINTS_PER_INCH * units_per_em); @@ -135,18 +137,18 @@ public: // Gfx::Font implementation virtual NonnullRefPtr clone() const override { return *this; } /* TODO */ - virtual u8 presentation_size() const override { return (u8)m_y_scale; } - virtual u16 weight() const override { return 400; } /* TODO */ + virtual u8 presentation_size() const override { return m_point_height; } + virtual u16 weight() const override { return m_font->weight(); } virtual Gfx::Glyph glyph(u32 code_point) const override; virtual u8 glyph_width(size_t ch) const override; virtual int glyph_or_emoji_width(u32 code_point) const override; - virtual u8 glyph_height() const override { return m_y_scale; } /* TODO */ - virtual int x_height() const override { return m_y_scale; } /* TODO */ - virtual u8 min_glyph_width() const override { return 1; } /* TODO */ - virtual u8 max_glyph_width() const override { return m_x_scale; } /* TODO */ + virtual u8 glyph_height() const override { return m_point_height; } /* TODO */ + virtual int x_height() const override { return m_point_height; } /* TODO */ + virtual u8 min_glyph_width() const override { return 1; } /* TODO */ + virtual u8 max_glyph_width() const override { return m_point_height; } /* TODO */ virtual u8 glyph_fixed_width() const override; - virtual u8 baseline() const override { return m_y_scale; } /* TODO */ - virtual u8 mean_line() const override { return m_y_scale; } /* TODO */ + virtual u8 baseline() const override { return m_point_height; } /* TODO */ + virtual u8 mean_line() const override { return m_point_height; } /* TODO */ virtual int width(const StringView&) const override; virtual int width(const Utf8View&) const override; virtual int width(const Utf32View&) const override; @@ -161,8 +163,10 @@ public: private: RefPtr m_font; - float m_x_scale { 0.0 }; - float m_y_scale { 0.0 }; + float m_x_scale { 0.0f }; + float m_y_scale { 0.0f }; + float m_point_width { 0.0f }; + float m_point_height { 0.0f }; mutable AK::HashMap> m_cached_glyph_bitmaps; };