Selaa lähdekoodia

LibPDF+LibGfx: Do not try to read "hmtx" table for PDFs

It is sometimes truncated in fonts embedded in PDFs, and the data
is not needed to render PDFs. 26 of my 1000 test files complained
"Could not load Hmtx: Not enough data" before.

Increases number of PDFs that render without diagnostics from
743 to 764.
Nico Weber 1 vuosi sitten
vanhempi
commit
0dee94ef40

+ 8 - 5
Userland/Libraries/LibGfx/Font/OpenType/Font.cpp

@@ -271,9 +271,12 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_offset(ReadonlyBytes buffer, u3
         return Error::from_string_literal("Font is missing Maxp");
         return Error::from_string_literal("Font is missing Maxp");
     auto maxp = TRY(Maxp::from_slice(opt_maxp_slice.value()));
     auto maxp = TRY(Maxp::from_slice(opt_maxp_slice.value()));
 
 
-    if (!opt_hmtx_slice.has_value())
-        return Error::from_string_literal("Font is missing Hmtx");
-    auto hmtx = TRY(Hmtx::from_slice(opt_hmtx_slice.value(), maxp.num_glyphs(), hhea.number_of_h_metrics()));
+    Optional<Hmtx> hmtx;
+    if (!(options.skip_tables & Options::SkipTables::Hmtx)) {
+        if (!opt_hmtx_slice.has_value())
+            return Error::from_string_literal("Font is missing Hmtx");
+        hmtx = TRY(Hmtx::from_slice(opt_hmtx_slice.value(), maxp.num_glyphs(), hhea.number_of_h_metrics()));
+    }
 
 
     NonnullOwnPtr<CharCodeToGlyphIndex> cmap = options.external_cmap ? options.external_cmap.release_nonnull() : TRY(CmapCharCodeToGlyphIndex::from_slice(opt_cmap_slice.value()));
     NonnullOwnPtr<CharCodeToGlyphIndex> cmap = options.external_cmap ? options.external_cmap.release_nonnull() : TRY(CmapCharCodeToGlyphIndex::from_slice(opt_cmap_slice.value()));
 
 
@@ -412,14 +415,14 @@ Gfx::ScaledGlyphMetrics Font::glyph_metrics(u32 glyph_id, float x_scale, float y
         return embedded_bitmap_metrics.release_value();
         return embedded_bitmap_metrics.release_value();
     }
     }
 
 
-    if (!m_loca.has_value() || !m_glyf.has_value()) {
+    if (!m_loca.has_value() || !m_glyf.has_value() || !m_hmtx.has_value()) {
         return Gfx::ScaledGlyphMetrics {};
         return Gfx::ScaledGlyphMetrics {};
     }
     }
 
 
     if (glyph_id >= glyph_count()) {
     if (glyph_id >= glyph_count()) {
         glyph_id = 0;
         glyph_id = 0;
     }
     }
-    auto horizontal_metrics = m_hmtx.get_glyph_horizontal_metrics(glyph_id);
+    auto horizontal_metrics = m_hmtx->get_glyph_horizontal_metrics(glyph_id);
     auto glyph_offset = m_loca->get_glyph_offset(glyph_id);
     auto glyph_offset = m_loca->get_glyph_offset(glyph_id);
     auto glyph = m_glyf->glyph(glyph_offset);
     auto glyph = m_glyf->glyph(glyph_offset);
     return Gfx::ScaledGlyphMetrics {
     return Gfx::ScaledGlyphMetrics {

+ 5 - 2
Userland/Libraries/LibGfx/Font/OpenType/Font.h

@@ -34,6 +34,9 @@ struct FontOptions {
     enum SkipTables {
     enum SkipTables {
         // If set, do not try to read the 'name' table. family() and variant() will return empty strings.
         // If set, do not try to read the 'name' table. family() and variant() will return empty strings.
         Name = 1 << 0,
         Name = 1 << 0,
+
+        // If set, do not try to read the 'hmtx' table. This will make glyph_metrics() return 0 for everyting and is_fixed_width() return true.
+        Hmtx = 1 << 1,
     };
     };
     u32 skip_tables { 0 };
     u32 skip_tables { 0 };
 };
 };
@@ -94,7 +97,7 @@ private:
         Optional<Name>&& name,
         Optional<Name>&& name,
         Hhea&& hhea,
         Hhea&& hhea,
         Maxp&& maxp,
         Maxp&& maxp,
-        Hmtx&& hmtx,
+        Optional<Hmtx>&& hmtx,
         NonnullOwnPtr<CharCodeToGlyphIndex> cmap,
         NonnullOwnPtr<CharCodeToGlyphIndex> cmap,
         Optional<Loca>&& loca,
         Optional<Loca>&& loca,
         Optional<Glyf>&& glyf,
         Optional<Glyf>&& glyf,
@@ -130,7 +133,7 @@ private:
     Optional<Name> m_name;
     Optional<Name> m_name;
     Hhea m_hhea;
     Hhea m_hhea;
     Maxp m_maxp;
     Maxp m_maxp;
-    Hmtx m_hmtx;
+    Optional<Hmtx> m_hmtx;
     Optional<Loca> m_loca;
     Optional<Loca> m_loca;
     Optional<Glyf> m_glyf;
     Optional<Glyf> m_glyf;
     NonnullOwnPtr<CharCodeToGlyphIndex> m_cmap;
     NonnullOwnPtr<CharCodeToGlyphIndex> m_cmap;

+ 1 - 1
Userland/Libraries/LibPDF/Fonts/PDFFont.h

@@ -19,7 +19,7 @@ class Renderer;
 
 
 // PDF files don't need most of the data in OpenType fonts, and even contain invalid data for
 // PDF files don't need most of the data in OpenType fonts, and even contain invalid data for
 // these tables in some cases. Skip reading these tables.
 // these tables in some cases. Skip reading these tables.
-constexpr u32 pdf_skipped_opentype_tables = OpenType::FontOptions::SkipTables::Name;
+constexpr u32 pdf_skipped_opentype_tables = OpenType::FontOptions::SkipTables::Name | OpenType::FontOptions::SkipTables::Hmtx;
 
 
 class PDFFont : public RefCounted<PDFFont> {
 class PDFFont : public RefCounted<PDFFont> {
 public:
 public: