mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 10:57:35 +00:00
LibGfx: Remove bit casting in OpenType OS2 table after construction
This commit is contained in:
parent
d4e1305413
commit
fe2e1a0282
3 changed files with 46 additions and 21 deletions
|
@ -213,7 +213,7 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_offset(ReadonlyBytes buffer, u3
|
||||||
|
|
||||||
Optional<OS2> os2;
|
Optional<OS2> os2;
|
||||||
if (opt_os2_slice.has_value())
|
if (opt_os2_slice.has_value())
|
||||||
os2 = OS2(opt_os2_slice.value());
|
os2 = TRY(OS2::from_slice(opt_os2_slice.value()));
|
||||||
|
|
||||||
Optional<Kern> kern {};
|
Optional<Kern> kern {};
|
||||||
if (opt_kern_slice.has_value())
|
if (opt_kern_slice.has_value())
|
||||||
|
|
|
@ -345,46 +345,76 @@ Optional<i16> Kern::read_glyph_kerning_format0(ReadonlyBytes slice, u16 left_gly
|
||||||
return pair->value;
|
return pair->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorOr<OS2> OS2::from_slice(ReadonlyBytes slice)
|
||||||
|
{
|
||||||
|
// All OS2 tables begin with a version.
|
||||||
|
if (slice.size() < sizeof(BigEndian<u16>))
|
||||||
|
return Error::from_string_literal("Could not load OS2: Not enough data");
|
||||||
|
u16 version = *bit_cast<BigEndian<u16> 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<Version0 const*>(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<Version1 const*>(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<Version2 const*>(slice.data()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
u16 OS2::weight_class() const
|
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
|
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
|
u16 OS2::selection() const
|
||||||
{
|
{
|
||||||
return header().fs_selection;
|
return m_data.visit([](auto* any) { return any->fs_selection; });
|
||||||
}
|
}
|
||||||
|
|
||||||
i16 OS2::typographic_ascender() const
|
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
|
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
|
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
|
bool OS2::use_typographic_metrics() const
|
||||||
{
|
{
|
||||||
return header().fs_selection & 0x80;
|
return m_data.visit([](auto* any) { return any->fs_selection & 0x80; });
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<i16> OS2::x_height() const
|
Optional<i16> OS2::x_height() const
|
||||||
{
|
{
|
||||||
if (header().version < 2)
|
return m_data.visit(
|
||||||
return {};
|
[]<typename T> requires(requires { T::sx_height; })(T * data)->Optional<i16> {
|
||||||
return header_v2().sx_height;
|
return data->sx_height;
|
||||||
|
},
|
||||||
|
[](auto*) { return Optional<i16>(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorOr<CBLC> CBLC::from_slice(ReadonlyBytes slice)
|
ErrorOr<CBLC> CBLC::from_slice(ReadonlyBytes slice)
|
||||||
|
|
|
@ -272,6 +272,8 @@ private:
|
||||||
// OS/2: OS/2 and Windows Metrics Table
|
// OS/2: OS/2 and Windows Metrics Table
|
||||||
class OS2 {
|
class OS2 {
|
||||||
public:
|
public:
|
||||||
|
static ErrorOr<OS2> from_slice(ReadonlyBytes);
|
||||||
|
|
||||||
u16 weight_class() const;
|
u16 weight_class() const;
|
||||||
u16 width_class() const;
|
u16 width_class() const;
|
||||||
u16 selection() const;
|
u16 selection() const;
|
||||||
|
@ -283,11 +285,6 @@ public:
|
||||||
|
|
||||||
[[nodiscard]] Optional<i16> x_height() const;
|
[[nodiscard]] Optional<i16> x_height() const;
|
||||||
|
|
||||||
explicit OS2(ReadonlyBytes slice)
|
|
||||||
: m_slice(slice)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct [[gnu::packed]] Version0 {
|
struct [[gnu::packed]] Version0 {
|
||||||
BigEndian<u16> version;
|
BigEndian<u16> version;
|
||||||
|
@ -338,14 +335,12 @@ private:
|
||||||
};
|
};
|
||||||
static_assert(AssertSize<Version2, 96>());
|
static_assert(AssertSize<Version2, 96>());
|
||||||
|
|
||||||
Version0 const& header() const { return *bit_cast<Version0 const*>(m_slice.data()); }
|
explicit OS2(Variant<Version0 const*, Version1 const*, Version2 const*> data)
|
||||||
Version2 const& header_v2() const
|
: m_data(move(data))
|
||||||
{
|
{
|
||||||
VERIFY(header().version >= 2);
|
|
||||||
return *bit_cast<Version2 const*>(m_slice.data());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ReadonlyBytes m_slice;
|
Variant<Version0 const*, Version1 const*, Version2 const*> m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://learn.microsoft.com/en-us/typography/opentype/spec/name
|
// https://learn.microsoft.com/en-us/typography/opentype/spec/name
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue