From e6131e45e269f48f09cb993a67e63a00267005ec Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 4 Mar 2023 00:39:54 +0100 Subject: [PATCH] LibGfx/OpenType: Make "glyf" and "loca" tables optional These tables are not guaranteed to be present in all font files. --- .../Libraries/LibGfx/Font/OpenType/Font.cpp | 47 ++++++++++++------- .../Libraries/LibGfx/Font/OpenType/Font.h | 6 +-- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp b/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp index 78983fca08..b8b9730809 100644 --- a/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp +++ b/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp @@ -405,7 +405,6 @@ ErrorOr> Font::try_load_from_offset(ReadonlyBytes buffer, u3 Optional opt_maxp = {}; Optional opt_hmtx = {}; Optional opt_cmap = {}; - Optional opt_loca = {}; Optional opt_os2 = {}; Optional opt_kern = {}; Optional opt_fpgm = {}; @@ -481,13 +480,17 @@ ErrorOr> Font::try_load_from_offset(ReadonlyBytes buffer, u3 return Error::from_string_literal("Could not load Cmap"); auto cmap = opt_cmap.value(); - if (!opt_loca_slice.has_value() || !(opt_loca = Loca::from_slice(opt_loca_slice.value(), maxp.num_glyphs(), head.index_to_loc_format())).has_value()) - return Error::from_string_literal("Could not load Loca"); - auto loca = opt_loca.value(); + Optional loca; + if (opt_loca_slice.has_value()) { + loca = Loca::from_slice(opt_loca_slice.value(), maxp.num_glyphs(), head.index_to_loc_format()); + if (!loca.has_value()) + return Error::from_string_literal("Could not load Loca"); + } - if (!opt_glyf_slice.has_value()) - return Error::from_string_literal("Could not load Glyf"); - auto glyf = Glyf(opt_glyf_slice.value()); + Optional glyf; + if (opt_glyf_slice.has_value()) { + glyf = Glyf(opt_glyf_slice.value()); + } Optional os2; if (opt_os2_slice.has_value()) @@ -560,15 +563,18 @@ Gfx::ScaledFontMetrics Font::metrics([[maybe_unused]] float x_scale, float y_sca }; } -// FIXME: "loca" and "glyf" are not available for CFF fonts. Gfx::ScaledGlyphMetrics Font::glyph_metrics(u32 glyph_id, float x_scale, float y_scale) const { + if (!m_loca.has_value() || !m_glyf.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 glyph_offset = m_loca.get_glyph_offset(glyph_id); - auto glyph = m_glyf.glyph(glyph_offset); + auto glyph_offset = m_loca->get_glyph_offset(glyph_id); + auto glyph = m_glyf->glyph(glyph_offset); return Gfx::ScaledGlyphMetrics { .ascender = static_cast(glyph.ascender()) * y_scale, .descender = static_cast(glyph.descender()) * y_scale, @@ -584,14 +590,17 @@ float Font::glyphs_horizontal_kerning(u32 left_glyph_id, u32 right_glyph_id, flo return m_kern->get_glyph_kerning(left_glyph_id, right_glyph_id) * x_scale; } -// FIXME: "loca" and "glyf" are not available for CFF fonts. RefPtr Font::rasterize_glyph(u32 glyph_id, float x_scale, float y_scale, Gfx::GlyphSubpixelOffset subpixel_offset) const { + if (!m_loca.has_value() || !m_glyf.has_value()) { + return nullptr; + } + if (glyph_id >= glyph_count()) { glyph_id = 0; } - auto glyph_offset = m_loca.get_glyph_offset(glyph_id); - auto glyph = m_glyf.glyph(glyph_offset); + auto glyph_offset = m_loca->get_glyph_offset(glyph_id); + auto glyph = m_glyf->glyph(glyph_offset); i16 ascender = 0; i16 descender = 0; @@ -608,8 +617,8 @@ RefPtr Font::rasterize_glyph(u32 glyph_id, float x_scale, float y_s if (glyph_id >= glyph_count()) { glyph_id = 0; } - auto glyph_offset = m_loca.get_glyph_offset(glyph_id); - return m_glyf.glyph(glyph_offset); + auto glyph_offset = m_loca->get_glyph_offset(glyph_id); + return m_glyf->glyph(glyph_offset); }); } @@ -735,8 +744,12 @@ Optional Font::control_value_program() const Optional Font::glyph_program(u32 glyph_id) const { - auto glyph_offset = m_loca.get_glyph_offset(glyph_id); - auto glyph = m_glyf.glyph(glyph_offset); + if (!m_loca.has_value() || !m_glyf.has_value()) { + return {}; + } + + auto glyph_offset = m_loca->get_glyph_offset(glyph_id); + auto glyph = m_glyf->glyph(glyph_offset); return glyph.program(); } diff --git a/Userland/Libraries/LibGfx/Font/OpenType/Font.h b/Userland/Libraries/LibGfx/Font/OpenType/Font.h index 903cf29abe..86abc00b44 100644 --- a/Userland/Libraries/LibGfx/Font/OpenType/Font.h +++ b/Userland/Libraries/LibGfx/Font/OpenType/Font.h @@ -59,7 +59,7 @@ private: static ErrorOr> try_load_from_offset(ReadonlyBytes, unsigned index = 0); - Font(ReadonlyBytes bytes, Head&& head, Name&& name, Hhea&& hhea, Maxp&& maxp, Hmtx&& hmtx, Cmap&& cmap, Loca&& loca, Glyf&& glyf, Optional os2, Optional&& kern, Optional fpgm, Optional prep) + Font(ReadonlyBytes bytes, Head&& head, Name&& name, Hhea&& hhea, Maxp&& maxp, Hmtx&& hmtx, Cmap&& cmap, Optional&& loca, Optional&& glyf, Optional os2, Optional&& kern, Optional fpgm, Optional prep) : m_buffer(move(bytes)) , m_head(move(head)) , m_name(move(name)) @@ -86,8 +86,8 @@ private: Hhea m_hhea; Maxp m_maxp; Hmtx m_hmtx; - Loca m_loca; - Glyf m_glyf; + Optional m_loca; + Optional m_glyf; Cmap m_cmap; Optional m_os2; Optional m_kern;