LibGfx: Don't try to paint glyphs that aren't in a font

Fixes https://github.com/LadybirdBrowser/ladybird/issues/88

(cherry picked from commit fbc42e7d4282053414c7cf85a3ef7a74e07f4d46;
amended to handle bitmap fonts)
This commit is contained in:
Andreas Kling authored and Nico Weber committed 2025-10-24 19:10:49 -04:00
1 parent 8129847375
commit 9e6666237b
7 files changed
+24 -18

No files matched your search

@@ -25,12 +25,12 @@ void GlyphAtlas::update(HashMap<Gfx::Font const*, HashTable<u32>> const& unique_
for (auto const& [font, code_points] : unique_glyphs) {
for (auto const& code_point : code_points) {
auto glyph = font->glyph(code_point);
if (!glyph.has_value())
continue;
auto atlas_key = GlyphsTextureKey { font, code_point };
if (!m_glyphs_texture_map.contains(atlas_key))
need_to_rebuild_texture = true;
if (glyph.bitmap()) {
glyph_bitmaps.set(atlas_key, *glyph.bitmap());
}
glyph_bitmaps.set(atlas_key, *glyph->bitmap());
}
}
@@ -282,11 +282,12 @@ ErrorOr<void> BitmapFont::write_to_file(NonnullOwnPtr<Core::File> file)
return {};
}
Glyph BitmapFont::glyph(u32 code_point) const
Optional<Glyph> BitmapFont::glyph(u32 code_point) const
{
// Note: Until all fonts support the 0xFFFD replacement
// character, fall back to painting '?' if necessary.
auto index = glyph_index(code_point).value_or('?');
auto maybe_index = glyph_index(code_point);
if (!maybe_index.has_value())
return {};
auto index = maybe_index.release_value();
auto width = m_glyph_widths[index];
auto glyph_byte_count = m_glyph_height * GlyphBitmap::bytes_per_row();
return Glyph(
+2 -2
View File
@@ -60,8 +60,8 @@ public:
virtual u8 slope() const override { return m_slope; }
void set_slope(u8 slope) { m_slope = slope; }
Glyph glyph(u32 code_point) const override;
Glyph glyph(u32 code_point, GlyphSubpixelOffset) const override { return glyph(code_point); }
Optional<Glyph> glyph(u32 code_point) const override;
Optional<Glyph> glyph(u32 code_point, GlyphSubpixelOffset) const override { return glyph(code_point); }
Optional<Glyph> glyph_for_postscript_name(StringView, GlyphSubpixelOffset) const override { return {}; }
float glyph_left_bearing(u32) const override { return 0; }
+2 -2
View File
@@ -173,8 +173,8 @@ public:
virtual u16 width() const = 0;
virtual u16 weight() const = 0;
virtual Glyph glyph(u32 code_point) const = 0;
virtual Glyph glyph(u32 code_point, GlyphSubpixelOffset) const = 0;
virtual Optional<Glyph> glyph(u32 code_point) const = 0;
virtual Optional<Glyph> glyph(u32 code_point, GlyphSubpixelOffset) const = 0;
virtual Optional<Glyph> glyph_for_postscript_name(StringView, GlyphSubpixelOffset) const = 0;
virtual bool contains_glyph(u32 code_point) const = 0;
virtual bool contains_glyph_for_postscript_name(StringView name) const = 0;
@@ -99,19 +99,21 @@ bool ScaledFont::append_glyph_path_to(Gfx::Path& path, u32 glyph_id) const
return success;
}
Gfx::Glyph ScaledFont::glyph(u32 code_point) const
Optional<Gfx::Glyph> ScaledFont::glyph(u32 code_point) const
{
return glyph(code_point, GlyphSubpixelOffset { 0, 0 });
}
Glyph ScaledFont::glyph_for_id(u32 id, GlyphSubpixelOffset subpixel_offset) const
Optional<Glyph> ScaledFont::glyph_for_id(u32 id, GlyphSubpixelOffset subpixel_offset) const
{
auto bitmap = rasterize_glyph(id, subpixel_offset);
if (!bitmap)
return {};
auto metrics = glyph_metrics(id);
return Gfx::Glyph(bitmap, metrics.left_side_bearing, metrics.advance_width, metrics.ascender, m_font->has_color_bitmaps());
}
Gfx::Glyph ScaledFont::glyph(u32 code_point, GlyphSubpixelOffset subpixel_offset) const
Optional<Gfx::Glyph> ScaledFont::glyph(u32 code_point, GlyphSubpixelOffset subpixel_offset) const
{
auto id = glyph_id_for_code_point(code_point);
return glyph_for_id(id, subpixel_offset);
+3 -3
View File
@@ -42,10 +42,10 @@ public:
virtual u8 slope() const override { return m_font->slope(); }
virtual u16 width() const override { return m_font->width(); }
virtual u16 weight() const override { return m_font->weight(); }
virtual Gfx::Glyph glyph(u32 code_point) const override;
virtual Optional<Gfx::Glyph> glyph(u32 code_point) const override;
virtual float glyph_left_bearing(u32 code_point) const override;
Optional<float> glyph_left_bearing_for_postscript_name(StringView) const override;
virtual Glyph glyph(u32 code_point, GlyphSubpixelOffset) const override;
virtual Optional<Glyph> glyph(u32 code_point, GlyphSubpixelOffset) const override;
Optional<Glyph> glyph_for_postscript_name(StringView, GlyphSubpixelOffset) const override;
virtual bool contains_glyph(u32 code_point) const override { return m_font->glyph_id_for_code_point(code_point) > 0; }
virtual bool contains_glyph_for_postscript_name(StringView name) const override { return m_font->glyph_id_for_postscript_name(name).has_value(); }
@@ -80,7 +80,7 @@ public:
virtual bool has_color_bitmaps() const override { return m_font->has_color_bitmaps(); }
private:
Glyph glyph_for_id(u32 id, GlyphSubpixelOffset) const;
Optional<Glyph> glyph_for_id(u32 id, GlyphSubpixelOffset) const;
NonnullRefPtr<VectorFont> m_font;
float m_x_scale { 0.0f };
+4 -1
View File
@@ -1364,7 +1364,10 @@ FLATTEN void Painter::draw_glyph(FloatPoint point, u32 code_point, Font const& f
{
auto top_left = point + FloatPoint(font.glyph_left_bearing(code_point), 0);
auto glyph_position = Gfx::GlyphRasterPosition::get_nearest_fit_for(top_left);
auto glyph = font.glyph(code_point, glyph_position.subpixel_offset);
auto maybe_glyph = font.glyph(code_point, glyph_position.subpixel_offset);
if (!maybe_glyph.has_value())
return;
auto glyph = maybe_glyph.release_value();
draw_glyph_internal(point, glyph_position, top_left, glyph, color);
}