diff --git a/Userland/Libraries/LibGfx/Font/OpenType/Tables.cpp b/Userland/Libraries/LibGfx/Font/OpenType/Tables.cpp index 62a5e5b62d..9a5dd1b365 100644 --- a/Userland/Libraries/LibGfx/Font/OpenType/Tables.cpp +++ b/Userland/Libraries/LibGfx/Font/OpenType/Tables.cpp @@ -179,18 +179,33 @@ GlyphHorizontalMetrics Hmtx::get_glyph_horizontal_metrics(u32 glyph_id) const ErrorOr Name::from_slice(ReadonlyBytes slice) { - return Name(slice); + // FIXME: Support version 1 table too. + + if (slice.size() < sizeof(NamingTableVersion0)) + return Error::from_string_literal("Could not load Name: Not enough data"); + + auto& naming_table = *bit_cast(slice.data()); + + auto name_record_data_size = naming_table.count * sizeof(NameRecord); + if (slice.size() < sizeof(NamingTableVersion0) + name_record_data_size) + return Error::from_string_literal("Could not load Name: Not enough data"); + ReadonlySpan name_records = { bit_cast(slice.offset_pointer(sizeof(NamingTableVersion0))), naming_table.count }; + + if (slice.size() < naming_table.storage_offset) + return Error::from_string_literal("Could not load Name: Not enough data"); + ReadonlyBytes string_data = slice.slice(naming_table.storage_offset); + + return Name(naming_table, name_records, string_data); } String Name::string_for_id(NameId id) const { - auto const count = header().count; - auto const storage_offset = header().storage_offset; + auto const count = m_naming_table.count; Vector valid_ids; for (size_t i = 0; i < count; ++i) { - auto this_id = header().name_record[i].name_id; + auto this_id = m_name_records[i].name_id; if (this_id == to_underlying(id)) valid_ids.append(i); } @@ -200,7 +215,7 @@ String Name::string_for_id(NameId id) const auto it = valid_ids.find_if([this](auto const& i) { // check if font has naming table for en-US language id - auto const& name_record = header().name_record[i]; + auto const& name_record = m_name_records[i]; auto const platform_id = name_record.platform_id; auto const language_id = name_record.language_id; return (platform_id == to_underlying(Platform::Macintosh) && language_id == to_underlying(MacintoshLanguage::English)) @@ -208,7 +223,7 @@ String Name::string_for_id(NameId id) const }); auto i = it != valid_ids.end() ? *it : valid_ids.first(); - auto const& name_record = header().name_record[i]; + auto const& name_record = m_name_records[i]; auto const platform_id = name_record.platform_id; auto const length = name_record.length; @@ -216,10 +231,10 @@ String Name::string_for_id(NameId id) const if (platform_id == to_underlying(Platform::Windows)) { static auto& decoder = *TextCodec::decoder_for("utf-16be"sv); - return decoder.to_utf8(StringView { (char const*)m_slice.offset(storage_offset + offset), length }).release_value_but_fixme_should_propagate_errors(); + return decoder.to_utf8(m_string_data.slice(offset, length)).release_value_but_fixme_should_propagate_errors(); } - return String::from_utf8(m_slice.slice(storage_offset + offset, length)).release_value_but_fixme_should_propagate_errors(); + return String::from_utf8(m_string_data.slice(offset, length)).release_value_but_fixme_should_propagate_errors(); } ErrorOr Kern::from_slice(ReadonlyBytes slice) diff --git a/Userland/Libraries/LibGfx/Font/OpenType/Tables.h b/Userland/Libraries/LibGfx/Font/OpenType/Tables.h index 98a6ef2818..63ce23b769 100644 --- a/Userland/Libraries/LibGfx/Font/OpenType/Tables.h +++ b/Userland/Libraries/LibGfx/Font/OpenType/Tables.h @@ -382,12 +382,11 @@ private: BigEndian version; BigEndian count; Offset16 storage_offset; - NameRecord name_record[0]; + // NameRecords are stored in a separate span. + // NameRecord name_record[0]; }; static_assert(AssertSize()); - NamingTableVersion0 const& header() const { return *bit_cast(m_slice.data()); } - enum class NameId : u16 { Copyright = 0, FamilyName = 1, @@ -404,14 +403,18 @@ private: TypographicSubfamilyName = 17, }; - Name(ReadonlyBytes slice) - : m_slice(slice) + Name(NamingTableVersion0 const& naming_table, ReadonlySpan name_records, ReadonlyBytes string_data) + : m_naming_table(naming_table) + , m_name_records(name_records) + , m_string_data(string_data) { } [[nodiscard]] String string_for_id(NameId) const; - ReadonlyBytes m_slice; + NamingTableVersion0 const& m_naming_table; + ReadonlySpan m_name_records; + ReadonlyBytes m_string_data; }; // https://learn.microsoft.com/en-us/typography/opentype/spec/kern