1
0
mirror of https://github.com/SerenityOS/serenity synced 2024-07-09 13:30:45 +00:00

LibGfx: Remove bit casting in OpenType Name table after construction

Store the name records as a span, and a separate bytes span for the
string data.
This commit is contained in:
Sam Atkins 2023-10-30 16:46:11 +00:00 committed by Andreas Kling
parent fe2e1a0282
commit 89b35c6dc8
2 changed files with 32 additions and 14 deletions

View File

@ -179,18 +179,33 @@ GlyphHorizontalMetrics Hmtx::get_glyph_horizontal_metrics(u32 glyph_id) const
ErrorOr<Name> 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<NamingTableVersion0 const*>(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<NameRecord> name_records = { bit_cast<NameRecord const*>(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<int> 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> Kern::from_slice(ReadonlyBytes slice)

View File

@ -382,12 +382,11 @@ private:
BigEndian<u16> version;
BigEndian<u16> count;
Offset16 storage_offset;
NameRecord name_record[0];
// NameRecords are stored in a separate span.
// NameRecord name_record[0];
};
static_assert(AssertSize<NamingTableVersion0, 6>());
NamingTableVersion0 const& header() const { return *bit_cast<NamingTableVersion0 const*>(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<NameRecord> 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<NameRecord> m_name_records;
ReadonlyBytes m_string_data;
};
// https://learn.microsoft.com/en-us/typography/opentype/spec/kern