diff --git a/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp b/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp index adb4b00682..6194b7547b 100644 --- a/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp +++ b/Userland/Libraries/LibGfx/Font/OpenType/Font.cpp @@ -213,7 +213,7 @@ ErrorOr> Font::try_load_from_offset(ReadonlyBytes buffer, u3 Optional os2; if (opt_os2_slice.has_value()) - os2 = OS2(opt_os2_slice.value()); + os2 = TRY(OS2::from_slice(opt_os2_slice.value())); Optional kern {}; if (opt_kern_slice.has_value()) diff --git a/Userland/Libraries/LibGfx/Font/OpenType/Tables.cpp b/Userland/Libraries/LibGfx/Font/OpenType/Tables.cpp index 2b2b4c471c..62a5e5b62d 100644 --- a/Userland/Libraries/LibGfx/Font/OpenType/Tables.cpp +++ b/Userland/Libraries/LibGfx/Font/OpenType/Tables.cpp @@ -345,46 +345,76 @@ Optional Kern::read_glyph_kerning_format0(ReadonlyBytes slice, u16 left_gly return pair->value; } +ErrorOr OS2::from_slice(ReadonlyBytes slice) +{ + // All OS2 tables begin with a version. + if (slice.size() < sizeof(BigEndian)) + return Error::from_string_literal("Could not load OS2: Not enough data"); + u16 version = *bit_cast const*>(slice.data()); + + // NOTE: We assume that this table only ever has new fields added to the end in future versions. + switch (version) { + case 0: { + if (slice.size() < sizeof(Version0)) + return Error::from_string_literal("Could not load OS2 v0: Not enough data"); + return OS2(bit_cast(slice.data())); + } + case 1: { + if (slice.size() < sizeof(Version1)) + return Error::from_string_literal("Could not load OS2 v1: Not enough data"); + return OS2(bit_cast(slice.data())); + } + case 2: + default: { + if (slice.size() < sizeof(Version2)) + return Error::from_string_literal("Could not load OS2 v2: Not enough data"); + return OS2(bit_cast(slice.data())); + } + } +} + u16 OS2::weight_class() const { - return header().us_weight_class; + return m_data.visit([](auto* any) { return any->us_weight_class; }); } u16 OS2::width_class() const { - return header().us_width_class; + return m_data.visit([](auto* any) { return any->us_width_class; }); } u16 OS2::selection() const { - return header().fs_selection; + return m_data.visit([](auto* any) { return any->fs_selection; }); } i16 OS2::typographic_ascender() const { - return header().s_typo_ascender; + return m_data.visit([](auto* any) { return any->s_typo_ascender; }); } i16 OS2::typographic_descender() const { - return header().s_typo_descender; + return m_data.visit([](auto* any) { return any->s_typo_descender; }); } i16 OS2::typographic_line_gap() const { - return header().s_typo_line_gap; + return m_data.visit([](auto* any) { return any->s_typo_line_gap; }); } bool OS2::use_typographic_metrics() const { - return header().fs_selection & 0x80; + return m_data.visit([](auto* any) { return any->fs_selection & 0x80; }); } Optional OS2::x_height() const { - if (header().version < 2) - return {}; - return header_v2().sx_height; + return m_data.visit( + [] requires(requires { T::sx_height; })(T * data)->Optional { + return data->sx_height; + }, + [](auto*) { return Optional(); }); } ErrorOr CBLC::from_slice(ReadonlyBytes slice) diff --git a/Userland/Libraries/LibGfx/Font/OpenType/Tables.h b/Userland/Libraries/LibGfx/Font/OpenType/Tables.h index 535f6047c1..98a6ef2818 100644 --- a/Userland/Libraries/LibGfx/Font/OpenType/Tables.h +++ b/Userland/Libraries/LibGfx/Font/OpenType/Tables.h @@ -272,6 +272,8 @@ private: // OS/2: OS/2 and Windows Metrics Table class OS2 { public: + static ErrorOr from_slice(ReadonlyBytes); + u16 weight_class() const; u16 width_class() const; u16 selection() const; @@ -283,11 +285,6 @@ public: [[nodiscard]] Optional x_height() const; - explicit OS2(ReadonlyBytes slice) - : m_slice(slice) - { - } - private: struct [[gnu::packed]] Version0 { BigEndian version; @@ -338,14 +335,12 @@ private: }; static_assert(AssertSize()); - Version0 const& header() const { return *bit_cast(m_slice.data()); } - Version2 const& header_v2() const + explicit OS2(Variant data) + : m_data(move(data)) { - VERIFY(header().version >= 2); - return *bit_cast(m_slice.data()); } - ReadonlyBytes m_slice; + Variant m_data; }; // https://learn.microsoft.com/en-us/typography/opentype/spec/name