1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 12:07:45 +00:00

LibGfx: Remove bit casting in OpenType Hmtx table after construction

Store the variable-length data in Spans instead.
This commit is contained in:
Sam Atkins 2023-10-26 17:16:40 +01:00 committed by Andreas Kling
parent cef4d4821b
commit 75376d6834
2 changed files with 23 additions and 17 deletions

View file

@ -145,27 +145,35 @@ u16 Maxp::num_glyphs() const
ErrorOr<Hmtx> Hmtx::from_slice(ReadonlyBytes slice, u32 num_glyphs, u32 number_of_h_metrics) ErrorOr<Hmtx> Hmtx::from_slice(ReadonlyBytes slice, u32 num_glyphs, u32 number_of_h_metrics)
{ {
if (slice.size() < number_of_h_metrics * sizeof(LongHorMetric) + (num_glyphs - number_of_h_metrics) * sizeof(u16)) { if (slice.size() < number_of_h_metrics * sizeof(LongHorMetric) + (num_glyphs - number_of_h_metrics) * sizeof(i16))
return Error::from_string_literal("Could not load Hmtx: Not enough data"); return Error::from_string_literal("Could not load Hmtx: Not enough data");
// The Horizontal Metrics table is LongHorMetric[number_of_h_metrics] followed by i16[num_glyphs - number_of_h_metrics];
ReadonlySpan<LongHorMetric> long_hor_metrics { bit_cast<LongHorMetric*>(slice.data()), number_of_h_metrics };
ReadonlySpan<i16> left_side_bearings {};
auto number_of_left_side_bearings = num_glyphs - number_of_h_metrics;
if (number_of_left_side_bearings > 0) {
left_side_bearings = {
bit_cast<i16*>(slice.offset(number_of_h_metrics * sizeof(LongHorMetric))),
number_of_left_side_bearings
};
} }
return Hmtx(slice, num_glyphs, number_of_h_metrics); return Hmtx(long_hor_metrics, left_side_bearings);
} }
GlyphHorizontalMetrics Hmtx::get_glyph_horizontal_metrics(u32 glyph_id) const GlyphHorizontalMetrics Hmtx::get_glyph_horizontal_metrics(u32 glyph_id) const
{ {
VERIFY(glyph_id < m_num_glyphs); VERIFY(glyph_id < m_long_hor_metrics.size() + m_left_side_bearings.size());
auto const* long_hor_metrics = bit_cast<LongHorMetric const*>(m_slice.data()); if (glyph_id < m_long_hor_metrics.size()) {
if (glyph_id < m_number_of_h_metrics) {
return GlyphHorizontalMetrics { return GlyphHorizontalMetrics {
.advance_width = static_cast<u16>(long_hor_metrics[glyph_id].advance_width), .advance_width = m_long_hor_metrics[glyph_id].advance_width,
.left_side_bearing = static_cast<i16>(long_hor_metrics[glyph_id].lsb), .left_side_bearing = m_long_hor_metrics[glyph_id].lsb,
}; };
} }
auto const* left_side_bearings = bit_cast<BigEndian<u16> const*>(m_slice.offset(m_number_of_h_metrics * sizeof(LongHorMetric)));
return GlyphHorizontalMetrics { return GlyphHorizontalMetrics {
.advance_width = static_cast<u16>(long_hor_metrics[m_number_of_h_metrics - 1].advance_width), .advance_width = m_long_hor_metrics.last().advance_width,
.left_side_bearing = static_cast<i16>(left_side_bearings[glyph_id - m_number_of_h_metrics]), .left_side_bearing = m_left_side_bearings[glyph_id - m_long_hor_metrics.size()],
}; };
} }

View file

@ -260,16 +260,14 @@ private:
}; };
static_assert(AssertSize<LongHorMetric, 4>()); static_assert(AssertSize<LongHorMetric, 4>());
Hmtx(ReadonlyBytes slice, u32 num_glyphs, u32 number_of_h_metrics) Hmtx(ReadonlySpan<LongHorMetric> long_hor_metrics, ReadonlySpan<i16> left_side_bearings)
: m_slice(slice) : m_long_hor_metrics(long_hor_metrics)
, m_num_glyphs(num_glyphs) , m_left_side_bearings(left_side_bearings)
, m_number_of_h_metrics(number_of_h_metrics)
{ {
} }
ReadonlyBytes m_slice; ReadonlySpan<LongHorMetric> m_long_hor_metrics;
u32 m_num_glyphs { 0 }; ReadonlySpan<i16> m_left_side_bearings;
u32 m_number_of_h_metrics { 0 };
}; };
// https://learn.microsoft.com/en-us/typography/opentype/spec/os2 // https://learn.microsoft.com/en-us/typography/opentype/spec/os2