1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 20:17:44 +00:00

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

This allows consideration of multi-code point glyphs.
This commit is contained in:
Timothy Flynn 2023-02-20 14:40:12 -05:00 committed by Andreas Kling
parent 71967bc5de
commit a391ea3da3
5 changed files with 46 additions and 22 deletions

View file

@ -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();
auto const* emoji = Emoji::emoji_for_code_point(code_point);
if (emoji == nullptr)
return glyph_width(0xFFFD);
return glyph_height() * 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();
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)); }

View file

@ -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;

View file

@ -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;

View file

@ -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)

View file

@ -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(); }