Przeglądaj źródła

LibGfx: Support computing a font's glyph width with code point iterators

This allows consideration of multi-code point glyphs.
Timothy Flynn 2 lat temu
rodzic
commit
a391ea3da3

+ 26 - 15
Userland/Libraries/LibGfx/Font/BitmapFont.cpp

@@ -314,23 +314,34 @@ float BitmapFont::glyph_width(u32 code_point) const
     return m_fixed_width || !index.has_value() ? m_glyph_width : m_glyph_widths[index.value()];
 }
 
-int BitmapFont::glyph_or_emoji_width_for_variable_width_font(u32 code_point) const
+template<typename CodePointIterator>
+static float glyph_or_emoji_width_impl(BitmapFont const& font, CodePointIterator& it)
 {
-    // FIXME: This is a hack in lieu of proper code point identification.
-    // 0xFFFF is arbitrary but also the end of the Basic Multilingual Plane.
-    if (code_point < 0xFFFF) {
-        auto index = glyph_index(code_point);
-        if (!index.has_value())
-            return glyph_width(0xFFFD);
-        if (m_glyph_widths[index.value()] > 0)
-            return glyph_width(code_point);
-        return glyph_width(0xFFFD);
-    }
+    if (auto const* emoji = Emoji::emoji_for_code_point_iterator(it))
+        return font.pixel_size() * emoji->width() / emoji->height();
+
+    if (font.is_fixed_width())
+        return font.glyph_fixed_width();
+
+    return font.glyph_width(*it);
+}
+
+float BitmapFont::glyph_or_emoji_width(u32 code_point) const
+{
+    Utf32View code_point_view { &code_point, 1 };
+    auto it = code_point_view.begin();
 
-    auto const* emoji = Emoji::emoji_for_code_point(code_point);
-    if (emoji == nullptr)
-        return glyph_width(0xFFFD);
-    return glyph_height() * emoji->width() / emoji->height();
+    return glyph_or_emoji_width_impl(*this, it);
+}
+
+float BitmapFont::glyph_or_emoji_width(Utf8CodePointIterator& it) const
+{
+    return glyph_or_emoji_width_impl(*this, it);
+}
+
+float BitmapFont::glyph_or_emoji_width(Utf32CodePointIterator& it) const
+{
+    return glyph_or_emoji_width_impl(*this, it);
 }
 
 float BitmapFont::width(StringView view) const { return unicode_view_width(Utf8View(view)); }

+ 4 - 7
Userland/Libraries/LibGfx/Font/BitmapFont.h

@@ -61,12 +61,10 @@ public:
     bool contains_glyph(u32 code_point) const override;
     bool contains_raw_glyph(u32 code_point) const { return m_glyph_widths[code_point] > 0; }
 
-    virtual float glyph_or_emoji_width(u32 code_point) const override
-    {
-        if (m_fixed_width)
-            return m_glyph_width;
-        return glyph_or_emoji_width_for_variable_width_font(code_point);
-    }
+    virtual float glyph_or_emoji_width(u32) const override;
+    virtual float glyph_or_emoji_width(Utf8CodePointIterator&) const override;
+    virtual float glyph_or_emoji_width(Utf32CodePointIterator&) const override;
+
     float glyphs_horizontal_kerning(u32, u32) const override { return 0.f; }
     u8 glyph_height() const override { return m_glyph_height; }
     int x_height() const override { return m_x_height; }
@@ -138,7 +136,6 @@ private:
     int unicode_view_width(T const& view) const;
 
     void update_x_height() { m_x_height = m_baseline - m_mean_line; };
-    int glyph_or_emoji_width_for_variable_width_font(u32 code_point) const;
 
     DeprecatedString m_name;
     DeprecatedString m_family;

+ 2 - 0
Userland/Libraries/LibGfx/Font/Font.h

@@ -168,6 +168,8 @@ public:
     virtual float glyph_left_bearing(u32 code_point) const = 0;
     virtual float glyph_width(u32 code_point) const = 0;
     virtual float glyph_or_emoji_width(u32 code_point) const = 0;
+    virtual float glyph_or_emoji_width(Utf8CodePointIterator&) const = 0;
+    virtual float glyph_or_emoji_width(Utf32CodePointIterator&) const = 0;
     virtual float glyphs_horizontal_kerning(u32 left_code_point, u32 right_code_point) const = 0;
     virtual u8 glyph_height() const = 0;
     virtual int x_height() const = 0;

+ 12 - 0
Userland/Libraries/LibGfx/Font/ScaledFont.cpp

@@ -105,6 +105,18 @@ float ScaledFont::glyph_or_emoji_width(u32 code_point) const
     return metrics.advance_width;
 }
 
+float ScaledFont::glyph_or_emoji_width(Utf8CodePointIterator& it) const
+{
+    // FIXME: Support multi-code point emoji with scaled fonts.
+    return glyph_or_emoji_width(*it);
+}
+
+float ScaledFont::glyph_or_emoji_width(Utf32CodePointIterator& it) const
+{
+    // FIXME: Support multi-code point emoji with scaled fonts.
+    return glyph_or_emoji_width(*it);
+}
+
 float ScaledFont::glyphs_horizontal_kerning(u32 left_code_point, u32 right_code_point) const
 {
     if (left_code_point == 0 || right_code_point == 0)

+ 2 - 0
Userland/Libraries/LibGfx/Font/ScaledFont.h

@@ -47,6 +47,8 @@ public:
     virtual bool contains_glyph(u32 code_point) const override { return m_font->glyph_id_for_code_point(code_point) > 0; }
     virtual float glyph_width(u32 code_point) const override;
     virtual float glyph_or_emoji_width(u32 code_point) const override;
+    virtual float glyph_or_emoji_width(Utf8CodePointIterator&) const override;
+    virtual float glyph_or_emoji_width(Utf32CodePointIterator&) const override;
     virtual float glyphs_horizontal_kerning(u32 left_code_point, u32 right_code_point) const override;
     virtual float preferred_line_height() const override { return metrics().height() + metrics().line_gap; }
     virtual u8 glyph_height() const override { return pixel_size(); }