diff --git a/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp b/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp index 23d89cb498..51c231b5f2 100644 --- a/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp +++ b/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp @@ -271,9 +271,12 @@ ErrorOr> Font::try_load_from_offset(ReadonlyBytes buffer, u3 return Error::from_string_literal("Font is missing Maxp"); 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; + 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 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(); } - 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 {}; } if (glyph_id >= glyph_count()) { 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 = m_glyf->glyph(glyph_offset); return Gfx::ScaledGlyphMetrics { diff --git a/Userland/Libraries/LibGfx/Font/OpenType/Font.h b/Userland/Libraries/LibGfx/Font/OpenType/Font.h index 16b5c61ba5..823d01b342 100644 --- a/Userland/Libraries/LibGfx/Font/OpenType/Font.h +++ b/Userland/Libraries/LibGfx/Font/OpenType/Font.h @@ -34,6 +34,9 @@ struct FontOptions { enum SkipTables { // If set, do not try to read the 'name' table. family() and variant() will return empty strings. 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 }; }; @@ -94,7 +97,7 @@ private: Optional&& name, Hhea&& hhea, Maxp&& maxp, - Hmtx&& hmtx, + Optional&& hmtx, NonnullOwnPtr cmap, Optional&& loca, Optional&& glyf, @@ -130,7 +133,7 @@ private: Optional m_name; Hhea m_hhea; Maxp m_maxp; - Hmtx m_hmtx; + Optional m_hmtx; Optional m_loca; Optional m_glyf; NonnullOwnPtr m_cmap; diff --git a/Userland/Libraries/LibPDF/Fonts/PDFFont.h b/Userland/Libraries/LibPDF/Fonts/PDFFont.h index cc3b33bac0..8688bfdb18 100644 --- a/Userland/Libraries/LibPDF/Fonts/PDFFont.h +++ b/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 // 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 { public: