LibGfx: Mark OpenType file data structs as packed, and assert sizes

Some of these are odd sizes. We managed not to insert padding because
BigEndian is itself marked as packed, but let's be explicit instead of
relying on that. :^)
This commit is contained in:
Sam Atkins 2023-11-01 16:13:06 +00:00 committed by Andreas Kling
parent dfa79ba6d8
commit 1a6da4fbf2
2 changed files with 82 additions and 41 deletions

View file

@ -174,13 +174,14 @@ public:
private:
// https://learn.microsoft.com/en-us/typography/opentype/spec/glyf#glyph-headers
struct GlyphHeader {
struct [[gnu::packed]] GlyphHeader {
BigEndian<i16> number_of_contours;
BigEndian<i16> x_min;
BigEndian<i16> y_min;
BigEndian<i16> x_max;
BigEndian<i16> y_max;
};
static_assert(AssertSize<GlyphHeader, 10>());
ReadonlyBytes m_slice;
};

View file

@ -24,19 +24,22 @@ enum class IndexToLocFormat {
Offset32,
};
struct Fixed {
struct [[gnu::packed]] Fixed {
BigEndian<u16> integer;
BigEndian<u16> fraction;
};
static_assert(AssertSize<Fixed, 4>());
struct LongDateTime {
struct [[gnu::packed]] LongDateTime {
BigEndian<u64> value;
};
static_assert(AssertSize<LongDateTime, 8>());
struct Version16Dot16 {
struct [[gnu::packed]] Version16Dot16 {
BigEndian<u16> major;
BigEndian<u16> minor;
};
static_assert(AssertSize<Version16Dot16, 4>());
using FWord = BigEndian<i16>;
using UFWord = BigEndian<u16>;
@ -79,7 +82,7 @@ public:
IndexToLocFormat index_to_loc_format() const;
private:
struct FontHeaderTable {
struct [[gnu::packed]] FontHeaderTable {
BigEndian<u16> major_version;
BigEndian<u16> minor_version;
Fixed font_revision;
@ -99,6 +102,7 @@ private:
BigEndian<i16> index_to_loc_format;
BigEndian<i16> glyph_data_format;
};
static_assert(AssertSize<FontHeaderTable, 54>());
FontHeaderTable const& header() const { return *bit_cast<FontHeaderTable const*>(m_slice.data()); }
@ -122,7 +126,7 @@ public:
u16 number_of_h_metrics() const;
private:
struct HorizontalHeaderTable {
struct [[gnu::packed]] HorizontalHeaderTable {
BigEndian<u16> major_version;
BigEndian<u16> minor_version;
FWord ascender;
@ -139,6 +143,7 @@ private:
BigEndian<i16> metric_data_format;
BigEndian<u16> number_of_h_metrics;
};
static_assert(AssertSize<HorizontalHeaderTable, 36>());
HorizontalHeaderTable const& header() const { return *bit_cast<HorizontalHeaderTable const*>(m_slice.data()); }
@ -159,12 +164,13 @@ public:
u16 num_glyphs() const;
private:
struct MaximumProfileVersion0_5 {
struct [[gnu::packed]] MaximumProfileVersion0_5 {
Version16Dot16 version;
BigEndian<u16> num_glyphs;
};
static_assert(AssertSize<MaximumProfileVersion0_5, 6>());
struct MaximumProfileVersion1_0 {
struct [[gnu::packed]] MaximumProfileVersion1_0 {
Version16Dot16 version;
BigEndian<u16> num_glyphs;
BigEndian<u16> max_points;
@ -181,6 +187,7 @@ private:
BigEndian<u16> max_component_elements;
BigEndian<u16> max_component_depths;
};
static_assert(AssertSize<MaximumProfileVersion1_0, 32>());
MaximumProfileVersion0_5 const& header() const { return *bit_cast<MaximumProfileVersion0_5 const*>(m_slice.data()); }
@ -235,10 +242,11 @@ public:
GlyphHorizontalMetrics get_glyph_horizontal_metrics(u32 glyph_id) const;
private:
struct LongHorMetric {
struct [[gnu::packed]] LongHorMetric {
BigEndian<u16> advance_width;
BigEndian<i16> lsb;
};
static_assert(AssertSize<LongHorMetric, 4>());
Hmtx(ReadonlyBytes slice, u32 num_glyphs, u32 number_of_h_metrics)
: m_slice(slice)
@ -273,7 +281,7 @@ public:
}
private:
struct Version0 {
struct [[gnu::packed]] Version0 {
BigEndian<u16> version;
BigEndian<i16> avg_char_width;
BigEndian<u16> us_weight_class;
@ -305,14 +313,16 @@ private:
BigEndian<u16> us_win_ascent;
BigEndian<u16> us_win_descent;
};
static_assert(AssertSize<Version0, 78>());
struct Version1 {
struct [[gnu::packed]] Version1 {
Version0 version0;
BigEndian<u32> ul_code_page_range1;
BigEndian<u32> ul_code_page_range2;
};
static_assert(AssertSize<Version1, 86>());
struct Version2 {
struct [[gnu::packed]] Version2 {
Version1 version1;
BigEndian<i16> sx_height;
BigEndian<i16> s_cap_height;
@ -320,6 +330,7 @@ private:
BigEndian<u16> us_break_char;
BigEndian<u16> us_max_context;
};
static_assert(AssertSize<Version2, 96>());
Version0 const& header() const { return *bit_cast<Version0 const*>(m_slice.data()); }
Version2 const& header_v2() const
@ -355,7 +366,7 @@ public:
private:
// https://learn.microsoft.com/en-us/typography/opentype/spec/name#name-records
struct NameRecord {
struct [[gnu::packed]] NameRecord {
BigEndian<u16> platform_id;
BigEndian<u16> encoding_id;
BigEndian<u16> language_id;
@ -363,14 +374,16 @@ private:
BigEndian<u16> length;
Offset16 string_offset;
};
static_assert(AssertSize<NameRecord, 12>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/name#naming-table-version-0
struct NamingTableVersion0 {
struct [[gnu::packed]] NamingTableVersion0 {
BigEndian<u16> version;
BigEndian<u16> count;
Offset16 storage_offset;
NameRecord name_record[0];
};
static_assert(AssertSize<NamingTableVersion0, 6>());
NamingTableVersion0 const& header() const { return *bit_cast<NamingTableVersion0 const*>(m_slice.data()); }
@ -408,30 +421,34 @@ public:
i16 get_glyph_kerning(u16 left_glyph_id, u16 right_glyph_id) const;
private:
struct Header {
struct [[gnu::packed]] Header {
BigEndian<u16> version;
BigEndian<u16> n_tables;
};
static_assert(AssertSize<Header, 4>());
struct SubtableHeader {
struct [[gnu::packed]] SubtableHeader {
BigEndian<u16> version;
BigEndian<u16> length;
BigEndian<u16> coverage;
};
static_assert(AssertSize<SubtableHeader, 6>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/kern#format-0
struct Format0 {
struct [[gnu::packed]] Format0 {
BigEndian<u16> n_pairs;
BigEndian<u16> search_range;
BigEndian<u16> entry_selector;
BigEndian<u16> range_shift;
};
static_assert(AssertSize<Format0, 8>());
struct Format0Pair {
struct [[gnu::packed]] Format0Pair {
BigEndian<u16> left;
BigEndian<u16> right;
FWord value;
};
static_assert(AssertSize<Format0Pair, 6>());
Header const& header() const { return *bit_cast<Header const*>(m_slice.data()); }
@ -452,7 +469,7 @@ private:
class EBLC {
public:
// https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#sbitlinemetrics-record
struct SbitLineMetrics {
struct [[gnu::packed]] SbitLineMetrics {
i8 ascender {};
i8 descender {};
u8 width_max {};
@ -466,27 +483,31 @@ public:
i8 pad1 {};
i8 pad2 {};
};
static_assert(AssertSize<SbitLineMetrics, 12>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtablearray
struct IndexSubTableArray {
struct [[gnu::packed]] IndexSubTableArray {
BigEndian<u16> first_glyph_index;
BigEndian<u16> last_glyph_index;
Offset32 additional_offset_to_index_subtable;
};
static_assert(AssertSize<IndexSubTableArray, 8>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubheader
struct IndexSubHeader {
struct [[gnu::packed]] IndexSubHeader {
BigEndian<u16> index_format;
BigEndian<u16> image_format;
Offset32 image_data_offset;
};
static_assert(AssertSize<IndexSubHeader, 8>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtable1-variable-metrics-glyphs-with-4-byte-offsets
// IndexSubTable1: variable-metrics glyphs with 4-byte offsets
struct IndexSubTable1 {
struct [[gnu::packed]] IndexSubTable1 {
IndexSubHeader header;
Offset32 sbit_offsets[];
};
static_assert(AssertSize<IndexSubTable1, 8>());
};
// https://learn.microsoft.com/en-us/typography/opentype/spec/cblc
@ -494,7 +515,7 @@ public:
class CBLC {
public:
// https://learn.microsoft.com/en-us/typography/opentype/spec/cblc#bitmapsize-record
struct BitmapSize {
struct [[gnu::packed]] BitmapSize {
Offset32 index_subtable_array_offset;
BigEndian<u32> index_tables_size;
BigEndian<u32> number_of_index_subtables;
@ -508,14 +529,16 @@ public:
u8 bit_depth {};
i8 flags {};
};
static_assert(AssertSize<BitmapSize, 48>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/cblc#cblcheader
struct CblcHeader {
struct [[gnu::packed]] CblcHeader {
BigEndian<u16> major_version;
BigEndian<u16> minor_version;
BigEndian<u32> num_sizes;
BitmapSize bitmap_sizes[];
};
static_assert(AssertSize<CblcHeader, 8>());
CblcHeader const& header() const { return *bit_cast<CblcHeader const*>(m_slice.data()); }
ReadonlySpan<BitmapSize> bitmap_sizes() const { return { header().bitmap_sizes, header().num_sizes }; }
@ -540,13 +563,14 @@ private:
class EBDT {
public:
// https://learn.microsoft.com/en-us/typography/opentype/spec/ebdt#smallglyphmetrics
struct SmallGlyphMetrics {
struct [[gnu::packed]] SmallGlyphMetrics {
u8 height {};
u8 width {};
i8 bearing_x {};
i8 bearing_y {};
u8 advance {};
};
static_assert(AssertSize<SmallGlyphMetrics, 5>());
};
// https://learn.microsoft.com/en-us/typography/opentype/spec/cbdt
@ -554,17 +578,19 @@ public:
class CBDT {
public:
// https://learn.microsoft.com/en-us/typography/opentype/spec/cbdt#table-structure
struct CbdtHeader {
struct [[gnu::packed]] CbdtHeader {
BigEndian<u16> major_version;
BigEndian<u16> minor_version;
};
static_assert(AssertSize<CbdtHeader, 4>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/cbdt#format-17-small-metrics-png-image-data
struct Format17 {
struct [[gnu::packed]] Format17 {
EBDT::SmallGlyphMetrics glyph_metrics;
BigEndian<u32> data_len;
u8 data[];
};
static_assert(AssertSize<Format17, 9>());
static ErrorOr<CBDT> from_slice(ReadonlyBytes);
ReadonlyBytes bytes() const { return m_slice; }
@ -581,87 +607,98 @@ private:
};
// https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#feature-list-table
struct FeatureRecord {
struct [[gnu::packed]] FeatureRecord {
Tag feature_tag;
Offset16 feature_offset;
};
static_assert(AssertSize<FeatureRecord, 6>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#feature-list-table
struct FeatureList {
struct [[gnu::packed]] FeatureList {
BigEndian<u16> feature_count;
FeatureRecord feature_records[];
};
static_assert(AssertSize<FeatureList, 2>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#feature-table
struct Feature {
struct [[gnu::packed]] Feature {
Offset16 feature_params_offset;
BigEndian<u16> lookup_index_count;
BigEndian<u16> lookup_list_indices[];
};
static_assert(AssertSize<Feature, 4>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#lookup-table
struct Lookup {
struct [[gnu::packed]] Lookup {
BigEndian<u16> lookup_type;
BigEndian<u16> lookup_flag;
BigEndian<u16> subtable_count;
Offset16 subtable_offsets[];
};
static_assert(AssertSize<Lookup, 6>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#lookup-list-table
struct LookupList {
struct [[gnu::packed]] LookupList {
BigEndian<u16> lookup_count;
Offset16 lookup_offsets[];
};
static_assert(AssertSize<LookupList, 2>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#coverage-format-1
struct CoverageFormat1 {
struct [[gnu::packed]] CoverageFormat1 {
BigEndian<u16> coverage_format;
BigEndian<u16> glyph_count;
BigEndian<u16> glyph_array[];
};
static_assert(AssertSize<CoverageFormat1, 4>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#coverage-format-2
struct RangeRecord {
struct [[gnu::packed]] RangeRecord {
BigEndian<u16> start_glyph_id;
BigEndian<u16> end_glyph_id;
BigEndian<u16> start_coverage_index;
};
static_assert(AssertSize<RangeRecord, 6>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#coverage-format-2
struct CoverageFormat2 {
struct [[gnu::packed]] CoverageFormat2 {
BigEndian<u16> coverage_format;
BigEndian<u16> range_count;
RangeRecord range_records[];
};
static_assert(AssertSize<CoverageFormat2, 4>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#class-definition-table-format-2
struct ClassRangeRecord {
struct [[gnu::packed]] ClassRangeRecord {
BigEndian<u16> start_glyph_id;
BigEndian<u16> end_glyph_id;
BigEndian<u16> class_;
};
static_assert(AssertSize<ClassRangeRecord, 6>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#class-definition-table-format-2
struct ClassDefFormat2 {
struct [[gnu::packed]] ClassDefFormat2 {
BigEndian<u16> class_format;
BigEndian<u16> class_range_count;
ClassRangeRecord class_range_records[];
};
static_assert(AssertSize<ClassDefFormat2, 4>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/gpos#gpos-header
class GPOS {
public:
// https://learn.microsoft.com/en-us/typography/opentype/spec/gpos#gpos-header
struct GPOSHeader {
struct [[gnu::packed]] GPOSHeader {
BigEndian<u16> major_version;
BigEndian<u16> minor_version;
Offset16 script_list_offset;
Offset16 feature_list_offset;
Offset16 lookup_list_offset;
};
static_assert(AssertSize<GPOSHeader, 10>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/gpos#pair-adjustment-positioning-format-1-adjustments-for-glyph-pairs
struct PairPosFormat1 {
struct [[gnu::packed]] PairPosFormat1 {
BigEndian<u16> pos_format;
Offset16 coverage_offset;
BigEndian<u16> value_format1;
@ -669,9 +706,10 @@ public:
BigEndian<u16> pair_set_count;
Offset16 pair_set_offsets[];
};
static_assert(AssertSize<PairPosFormat1, 10>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/gpos#value-record
struct ValueRecord {
struct [[gnu::packed]] ValueRecord {
BigEndian<i16> x_placement;
BigEndian<i16> y_placement;
BigEndian<i16> x_advance;
@ -681,9 +719,10 @@ public:
Offset16 x_advance_device_offset;
Offset16 y_advance_device_offset;
};
static_assert(AssertSize<ValueRecord, 16>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/gpos#pair-adjustment-positioning-format-2-class-pair-adjustment
struct PairPosFormat2 {
struct [[gnu::packed]] PairPosFormat2 {
BigEndian<u16> pos_format;
Offset16 coverage_offset;
BigEndian<u16> value_format1;
@ -693,6 +732,7 @@ public:
BigEndian<u16> class1_count;
BigEndian<u16> class2_count;
};
static_assert(AssertSize<PairPosFormat2, 16>());
enum class ValueFormat : u16 {
X_PLACEMENT = 0x0001,