Переглянути джерело

LibGfx/OpenType: Ignore glyphs with bogus offsets

Some fonts (like the Bootstrap Icons webfont) have bogus glyph offsets
in the `loca` table that point past the end of the `glyf` table.

AFAICT other rasterizers simply ignore these glyphs and treat them as if
they were missing. So let's do the same.

This makes https://changelog.serenityos.org/ actually work! :^)
Andreas Kling 2 роки тому
батько
коміт
264b9b73ac

+ 10 - 4
Userland/Libraries/LibGfx/Font/OpenType/Font.cpp

@@ -664,9 +664,11 @@ Gfx::ScaledGlyphMetrics Font::glyph_metrics(u32 glyph_id, float x_scale, float y
     auto horizontal_metrics = m_hmtx.get_glyph_horizontal_metrics(glyph_id);
     auto glyph_offset = m_loca->get_glyph_offset(glyph_id);
     auto glyph = m_glyf->glyph(glyph_offset);
+    if (!glyph.has_value())
+        return {};
     return Gfx::ScaledGlyphMetrics {
-        .ascender = static_cast<float>(glyph.ascender()) * y_scale,
-        .descender = static_cast<float>(glyph.descender()) * y_scale,
+        .ascender = static_cast<float>(glyph->ascender()) * y_scale,
+        .descender = static_cast<float>(glyph->descender()) * y_scale,
         .advance_width = static_cast<float>(horizontal_metrics.advance_width) * x_scale,
         .left_side_bearing = static_cast<float>(horizontal_metrics.left_side_bearing) * x_scale,
     };
@@ -708,6 +710,8 @@ RefPtr<Gfx::Bitmap> Font::rasterize_glyph(u32 glyph_id, float x_scale, float y_s
         return nullptr;
 
     auto glyph = m_glyf->glyph(glyph_offset0);
+    if (!glyph.has_value())
+        return nullptr;
 
     i16 ascender = 0;
     i16 descender = 0;
@@ -720,7 +724,7 @@ RefPtr<Gfx::Bitmap> Font::rasterize_glyph(u32 glyph_id, float x_scale, float y_s
         descender = m_hhea.descender();
     }
 
-    return glyph.rasterize(ascender, descender, x_scale, y_scale, subpixel_offset, [&](u16 glyph_id) {
+    return glyph->rasterize(ascender, descender, x_scale, y_scale, subpixel_offset, [&](u16 glyph_id) {
         if (glyph_id >= glyph_count()) {
             glyph_id = 0;
         }
@@ -857,7 +861,9 @@ Optional<ReadonlyBytes> Font::glyph_program(u32 glyph_id) const
 
     auto glyph_offset = m_loca->get_glyph_offset(glyph_id);
     auto glyph = m_glyf->glyph(glyph_offset);
-    return glyph.program();
+    if (!glyph.has_value())
+        return {};
+    return glyph->program();
 }
 
 u32 Font::glyph_id_for_code_point(u32 code_point) const

+ 3 - 1
Userland/Libraries/LibGfx/Font/OpenType/Glyf.cpp

@@ -367,8 +367,10 @@ RefPtr<Gfx::Bitmap> Glyf::Glyph::rasterize_simple(i16 font_ascender, i16 font_de
     return rasterizer.accumulate();
 }
 
-Glyf::Glyph Glyf::glyph(u32 offset) const
+Optional<Glyf::Glyph> Glyf::glyph(u32 offset) const
 {
+    if (offset + sizeof(GlyphHeader) > m_slice.size())
+        return {};
     VERIFY(m_slice.size() >= offset + sizeof(GlyphHeader));
     auto const& glyph_header = *bit_cast<GlyphHeader const*>(m_slice.offset_pointer(offset));
     i16 num_contours = glyph_header.number_of_contours;

+ 7 - 5
Userland/Libraries/LibGfx/Font/OpenType/Glyf.h

@@ -113,12 +113,14 @@ public:
                 auto item = opt_item.value();
                 Gfx::AffineTransform affine_here { transform };
                 affine_here.multiply(item.affine);
-                Glyph glyph = glyph_callback(item.glyph_id);
+                auto glyph = glyph_callback(item.glyph_id);
+                if (!glyph.has_value())
+                    continue;
 
-                if (glyph.m_type == Type::Simple) {
-                    glyph.rasterize_impl(rasterizer, affine_here);
+                if (glyph->m_type == Type::Simple) {
+                    glyph->rasterize_impl(rasterizer, affine_here);
                 } else {
-                    glyph.rasterize_composite_loop(rasterizer, transform, glyph_callback);
+                    glyph->rasterize_composite_loop(rasterizer, transform, glyph_callback);
                 }
             }
         }
@@ -152,7 +154,7 @@ public:
         : m_slice(slice)
     {
     }
-    Glyph glyph(u32 offset) const;
+    Optional<Glyph> glyph(u32 offset) const;
 
 private:
     // https://learn.microsoft.com/en-us/typography/opentype/spec/glyf#glyph-headers