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

LibGfx: Define and use OpenType data types for struct definitions

A few closely-related changes:
- Move our definitions of the OpenType spec's "data types" into their
  own header file.
- Add definitions for the integer types there too, for completeness.
  (Plus Uint16 matches the spec term, and is less verbose than
  BigEndian<u16>.)
- Include Traits for the non-BigEndian types so that we can read them
  from Streams. (BigEndian<integer-type> already has this.)
- Use the integer types in our struct definitions.

As a bonus, this fixes a bug in Hmtx, which read the left-side bearings
as i16 instead of BigEndian<i16>.
This commit is contained in:
Sam Atkins 2023-11-02 11:36:51 +00:00 committed by Andreas Kling
parent a28f035d76
commit 2a4d7a193e
3 changed files with 254 additions and 203 deletions

View file

@ -0,0 +1,73 @@
/*
* Copyright (c) 2020, Srimanta Barua <srimanta.barua1@gmail.com>
* Copyright (c) 2022, Jelle Raaijmakers <jelle@gmta.nl>
* Copyright (c) 2023, Lukas Affolter <git@lukasach.dev>
* Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Endian.h>
#include <AK/Types.h>
// https://learn.microsoft.com/en-us/typography/opentype/spec/otff#data-types
namespace OpenType {
using Uint8 = u8;
using Int8 = i8;
using Uint16 = BigEndian<u16>;
using Int16 = BigEndian<i16>;
// FIXME: Uint24
using Uint32 = BigEndian<u32>;
using Int32 = BigEndian<i32>;
struct [[gnu::packed]] Fixed {
BigEndian<u16> integer;
BigEndian<u16> fraction;
};
static_assert(AssertSize<Fixed, 4>());
using FWord = BigEndian<i16>;
using UFWord = BigEndian<u16>;
// FIXME: F2Dot14
struct [[gnu::packed]] LongDateTime {
BigEndian<u64> value;
};
static_assert(AssertSize<LongDateTime, 8>());
using Tag = BigEndian<u32>;
using Offset16 = BigEndian<u16>;
// FIXME: Offset24
using Offset32 = BigEndian<u32>;
struct [[gnu::packed]] Version16Dot16 {
BigEndian<u16> major;
BigEndian<u16> minor;
};
static_assert(AssertSize<Version16Dot16, 4>());
}
namespace AK {
template<>
struct Traits<OpenType::Fixed const> : public GenericTraits<OpenType::Fixed const> {
static constexpr bool is_trivially_serializable() { return true; }
};
template<>
struct Traits<OpenType::LongDateTime const> : public GenericTraits<OpenType::LongDateTime const> {
static constexpr bool is_trivially_serializable() { return true; }
};
template<>
struct Traits<OpenType::Tag const> : public GenericTraits<OpenType::Tag const> {
static constexpr bool is_trivially_serializable() { return true; }
};
template<>
struct Traits<OpenType::Version16Dot16 const> : public GenericTraits<OpenType::Version16Dot16 const> {
static constexpr bool is_trivially_serializable() { return true; }
};
}

View file

@ -145,16 +145,16 @@ 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(i16)) if (slice.size() < number_of_h_metrics * sizeof(LongHorMetric) + (num_glyphs - number_of_h_metrics) * sizeof(Int16))
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]; // The Horizontal Metrics table is LongHorMetric[number_of_h_metrics] followed by Int16[num_glyphs - number_of_h_metrics];
ReadonlySpan<LongHorMetric> long_hor_metrics { bit_cast<LongHorMetric*>(slice.data()), number_of_h_metrics }; ReadonlySpan<LongHorMetric> long_hor_metrics { bit_cast<LongHorMetric*>(slice.data()), number_of_h_metrics };
ReadonlySpan<i16> left_side_bearings {}; ReadonlySpan<Int16> left_side_bearings {};
auto number_of_left_side_bearings = num_glyphs - number_of_h_metrics; auto number_of_left_side_bearings = num_glyphs - number_of_h_metrics;
if (number_of_left_side_bearings > 0) { if (number_of_left_side_bearings > 0) {
left_side_bearings = { left_side_bearings = {
bit_cast<i16*>(slice.offset(number_of_h_metrics * sizeof(LongHorMetric))), bit_cast<Int16*>(slice.offset(number_of_h_metrics * sizeof(LongHorMetric))),
number_of_left_side_bearings number_of_left_side_bearings
}; };
} }

View file

@ -16,6 +16,7 @@
#include <AK/Forward.h> #include <AK/Forward.h>
#include <AK/Span.h> #include <AK/Span.h>
#include <AK/String.h> #include <AK/String.h>
#include <LibGfx/Font/OpenType/DataTypes.h>
namespace OpenType { namespace OpenType {
@ -24,46 +25,23 @@ enum class IndexToLocFormat {
Offset32, Offset32,
}; };
struct [[gnu::packed]] Fixed {
BigEndian<u16> integer;
BigEndian<u16> fraction;
};
static_assert(AssertSize<Fixed, 4>());
struct [[gnu::packed]] LongDateTime {
BigEndian<u64> value;
};
static_assert(AssertSize<LongDateTime, 8>());
struct [[gnu::packed]] Version16Dot16 {
BigEndian<u16> major;
BigEndian<u16> minor;
};
static_assert(AssertSize<Version16Dot16, 4>());
using FWord = BigEndian<i16>;
using UFWord = BigEndian<u16>;
using Tag = BigEndian<u32>;
using Offset16 = BigEndian<u16>;
using Offset32 = BigEndian<u32>;
// https://learn.microsoft.com/en-us/typography/opentype/spec/otff#table-directory // https://learn.microsoft.com/en-us/typography/opentype/spec/otff#table-directory
// Table Directory (known as the Offset Table in ISO-IEC 14496-22:2019) // Table Directory (known as the Offset Table in ISO-IEC 14496-22:2019)
struct [[gnu::packed]] TableDirectory { struct [[gnu::packed]] TableDirectory {
BigEndian<u32> sfnt_version; Uint32 sfnt_version;
BigEndian<u16> num_tables; // Number of tables. Uint16 num_tables; // Number of tables.
BigEndian<u16> search_range; // (Maximum power of 2 <= numTables) x 16. Uint16 search_range; // (Maximum power of 2 <= numTables) x 16.
BigEndian<u16> entry_selector; // Log2(maximum power of 2 <= numTables). Uint16 entry_selector; // Log2(maximum power of 2 <= numTables).
BigEndian<u16> range_shift; // NumTables x 16 - searchRange. Uint16 range_shift; // NumTables x 16 - searchRange.
}; };
static_assert(AssertSize<TableDirectory, 12>()); static_assert(AssertSize<TableDirectory, 12>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/otff#table-directory // https://learn.microsoft.com/en-us/typography/opentype/spec/otff#table-directory
struct [[gnu::packed]] TableRecord { struct [[gnu::packed]] TableRecord {
Tag table_tag; // Table identifier. Tag table_tag; // Table identifier.
BigEndian<u32> checksum; // CheckSum for this table. Uint32 checksum; // CheckSum for this table.
Offset32 offset; // Offset from beginning of TrueType font file. Offset32 offset; // Offset from beginning of TrueType font file.
BigEndian<u32> length; // Length of this table. Uint32 length; // Length of this table.
}; };
static_assert(AssertSize<TableRecord, 16>()); static_assert(AssertSize<TableRecord, 16>());
@ -99,24 +77,24 @@ public:
private: private:
struct [[gnu::packed]] FontHeaderTable { struct [[gnu::packed]] FontHeaderTable {
BigEndian<u16> major_version; Uint16 major_version;
BigEndian<u16> minor_version; Uint16 minor_version;
Fixed font_revision; Fixed font_revision;
BigEndian<u32> checksum_adjustment; Uint32 checksum_adjustment;
BigEndian<u32> magic_number; Uint32 magic_number;
BigEndian<u16> flags; Uint16 flags;
BigEndian<u16> units_per_em; Uint16 units_per_em;
LongDateTime created; LongDateTime created;
LongDateTime modified; LongDateTime modified;
BigEndian<i16> x_min; Int16 x_min;
BigEndian<i16> y_min; Int16 y_min;
BigEndian<i16> x_max; Int16 x_max;
BigEndian<i16> y_max; Int16 y_max;
BigEndian<u16> mac_style; Uint16 mac_style;
BigEndian<u16> lowest_rec_ppem; Uint16 lowest_rec_ppem;
BigEndian<i16> font_direction_hint; Int16 font_direction_hint;
BigEndian<i16> index_to_loc_format; Int16 index_to_loc_format;
BigEndian<i16> glyph_data_format; Int16 glyph_data_format;
}; };
static_assert(AssertSize<FontHeaderTable, 54>()); static_assert(AssertSize<FontHeaderTable, 54>());
@ -141,8 +119,8 @@ public:
private: private:
struct [[gnu::packed]] HorizontalHeaderTable { struct [[gnu::packed]] HorizontalHeaderTable {
BigEndian<u16> major_version; Uint16 major_version;
BigEndian<u16> minor_version; Uint16 minor_version;
FWord ascender; FWord ascender;
FWord descender; FWord descender;
FWord line_gap; FWord line_gap;
@ -150,12 +128,12 @@ private:
FWord min_left_side_bearing; FWord min_left_side_bearing;
FWord min_right_side_bearing; FWord min_right_side_bearing;
FWord x_max_extent; FWord x_max_extent;
BigEndian<i16> caret_slope_rise; Int16 caret_slope_rise;
BigEndian<i16> caret_slope_run; Int16 caret_slope_run;
BigEndian<i16> caret_offset; Int16 caret_offset;
BigEndian<i16> reserved[4]; Int16 reserved[4];
BigEndian<i16> metric_data_format; Int16 metric_data_format;
BigEndian<u16> number_of_h_metrics; Uint16 number_of_h_metrics;
}; };
static_assert(AssertSize<HorizontalHeaderTable, 36>()); static_assert(AssertSize<HorizontalHeaderTable, 36>());
@ -178,24 +156,24 @@ public:
private: private:
struct [[gnu::packed]] Version0_5 { struct [[gnu::packed]] Version0_5 {
Version16Dot16 version; Version16Dot16 version;
BigEndian<u16> num_glyphs; Uint16 num_glyphs;
}; };
static_assert(AssertSize<Version0_5, 6>()); static_assert(AssertSize<Version0_5, 6>());
struct [[gnu::packed]] Version1_0 : Version0_5 { struct [[gnu::packed]] Version1_0 : Version0_5 {
BigEndian<u16> max_points; Uint16 max_points;
BigEndian<u16> max_contours; Uint16 max_contours;
BigEndian<u16> max_composite_points; Uint16 max_composite_points;
BigEndian<u16> max_composite_contours; Uint16 max_composite_contours;
BigEndian<u16> max_zones; Uint16 max_zones;
BigEndian<u16> max_twilight_points; Uint16 max_twilight_points;
BigEndian<u16> max_storage; Uint16 max_storage;
BigEndian<u16> max_function_defs; Uint16 max_function_defs;
BigEndian<u16> max_instruction_defs; Uint16 max_instruction_defs;
BigEndian<u16> max_stack_elements; Uint16 max_stack_elements;
BigEndian<u16> max_size_of_instructions; Uint16 max_size_of_instructions;
BigEndian<u16> max_component_elements; Uint16 max_component_elements;
BigEndian<u16> max_component_depths; Uint16 max_component_depths;
}; };
static_assert(AssertSize<Version1_0, 32>()); static_assert(AssertSize<Version1_0, 32>());
@ -253,19 +231,19 @@ public:
private: private:
struct [[gnu::packed]] LongHorMetric { struct [[gnu::packed]] LongHorMetric {
BigEndian<u16> advance_width; Uint16 advance_width;
BigEndian<i16> lsb; Int16 lsb;
}; };
static_assert(AssertSize<LongHorMetric, 4>()); static_assert(AssertSize<LongHorMetric, 4>());
Hmtx(ReadonlySpan<LongHorMetric> long_hor_metrics, ReadonlySpan<i16> left_side_bearings) Hmtx(ReadonlySpan<LongHorMetric> long_hor_metrics, ReadonlySpan<Int16> left_side_bearings)
: m_long_hor_metrics(long_hor_metrics) : m_long_hor_metrics(long_hor_metrics)
, m_left_side_bearings(left_side_bearings) , m_left_side_bearings(left_side_bearings)
{ {
} }
ReadonlySpan<LongHorMetric> m_long_hor_metrics; ReadonlySpan<LongHorMetric> m_long_hor_metrics;
ReadonlySpan<i16> m_left_side_bearings; ReadonlySpan<Int16> m_left_side_bearings;
}; };
// https://learn.microsoft.com/en-us/typography/opentype/spec/os2 // https://learn.microsoft.com/en-us/typography/opentype/spec/os2
@ -287,51 +265,51 @@ public:
private: private:
struct [[gnu::packed]] Version0 { struct [[gnu::packed]] Version0 {
BigEndian<u16> version; Uint16 version;
BigEndian<i16> avg_char_width; Int16 avg_char_width;
BigEndian<u16> us_weight_class; Uint16 us_weight_class;
BigEndian<u16> us_width_class; Uint16 us_width_class;
BigEndian<u16> fs_type; Uint16 fs_type;
BigEndian<i16> y_subscript_x_size; Int16 y_subscript_x_size;
BigEndian<i16> y_subscript_y_size; Int16 y_subscript_y_size;
BigEndian<i16> y_subscript_x_offset; Int16 y_subscript_x_offset;
BigEndian<i16> y_subscript_y_offset; Int16 y_subscript_y_offset;
BigEndian<i16> y_superscript_x_size; Int16 y_superscript_x_size;
BigEndian<i16> y_superscript_y_size; Int16 y_superscript_y_size;
BigEndian<i16> y_superscript_x_offset; Int16 y_superscript_x_offset;
BigEndian<i16> y_superscript_y_offset; Int16 y_superscript_y_offset;
BigEndian<i16> y_strikeout_size; Int16 y_strikeout_size;
BigEndian<i16> y_strikeout_position; Int16 y_strikeout_position;
BigEndian<i16> s_family_class; Int16 s_family_class;
u8 panose[10]; Uint8 panose[10];
BigEndian<u32> ul_unicode_range1; Uint32 ul_unicode_range1;
BigEndian<u32> ul_unicode_range2; Uint32 ul_unicode_range2;
BigEndian<u32> ul_unicode_range3; Uint32 ul_unicode_range3;
BigEndian<u32> ul_unicode_range4; Uint32 ul_unicode_range4;
Tag ach_vend_id; Tag ach_vend_id;
BigEndian<u16> fs_selection; Uint16 fs_selection;
BigEndian<u16> fs_first_char_index; Uint16 fs_first_char_index;
BigEndian<u16> us_last_char_index; Uint16 us_last_char_index;
BigEndian<i16> s_typo_ascender; Int16 s_typo_ascender;
BigEndian<i16> s_typo_descender; Int16 s_typo_descender;
BigEndian<i16> s_typo_line_gap; Int16 s_typo_line_gap;
BigEndian<u16> us_win_ascent; Uint16 us_win_ascent;
BigEndian<u16> us_win_descent; Uint16 us_win_descent;
}; };
static_assert(AssertSize<Version0, 78>()); static_assert(AssertSize<Version0, 78>());
struct [[gnu::packed]] Version1 : Version0 { struct [[gnu::packed]] Version1 : Version0 {
BigEndian<u32> ul_code_page_range1; Uint32 ul_code_page_range1;
BigEndian<u32> ul_code_page_range2; Uint32 ul_code_page_range2;
}; };
static_assert(AssertSize<Version1, 86>()); static_assert(AssertSize<Version1, 86>());
struct [[gnu::packed]] Version2 : Version1 { struct [[gnu::packed]] Version2 : Version1 {
BigEndian<i16> sx_height; Int16 sx_height;
BigEndian<i16> s_cap_height; Int16 s_cap_height;
BigEndian<u16> us_default_char; Uint16 us_default_char;
BigEndian<u16> us_break_char; Uint16 us_break_char;
BigEndian<u16> us_max_context; Uint16 us_max_context;
}; };
static_assert(AssertSize<Version2, 96>()); static_assert(AssertSize<Version2, 96>());
@ -368,19 +346,19 @@ public:
private: private:
// https://learn.microsoft.com/en-us/typography/opentype/spec/name#name-records // https://learn.microsoft.com/en-us/typography/opentype/spec/name#name-records
struct [[gnu::packed]] NameRecord { struct [[gnu::packed]] NameRecord {
BigEndian<u16> platform_id; Uint16 platform_id;
BigEndian<u16> encoding_id; Uint16 encoding_id;
BigEndian<u16> language_id; Uint16 language_id;
BigEndian<u16> name_id; Uint16 name_id;
BigEndian<u16> length; Uint16 length;
Offset16 string_offset; Offset16 string_offset;
}; };
static_assert(AssertSize<NameRecord, 12>()); static_assert(AssertSize<NameRecord, 12>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/name#naming-table-version-0 // https://learn.microsoft.com/en-us/typography/opentype/spec/name#naming-table-version-0
struct [[gnu::packed]] NamingTableVersion0 { struct [[gnu::packed]] NamingTableVersion0 {
BigEndian<u16> version; Uint16 version;
BigEndian<u16> count; Uint16 count;
Offset16 storage_offset; Offset16 storage_offset;
// NameRecords are stored in a separate span. // NameRecords are stored in a separate span.
// NameRecord name_record[0]; // NameRecord name_record[0];
@ -425,30 +403,30 @@ public:
i16 get_glyph_kerning(u16 left_glyph_id, u16 right_glyph_id) const; i16 get_glyph_kerning(u16 left_glyph_id, u16 right_glyph_id) const;
struct [[gnu::packed]] Header { struct [[gnu::packed]] Header {
BigEndian<u16> version; Uint16 version;
BigEndian<u16> n_tables; Uint16 n_tables;
}; };
static_assert(AssertSize<Header, 4>()); static_assert(AssertSize<Header, 4>());
struct [[gnu::packed]] SubtableHeader { struct [[gnu::packed]] SubtableHeader {
BigEndian<u16> version; Uint16 version;
BigEndian<u16> length; Uint16 length;
BigEndian<u16> coverage; Uint16 coverage;
}; };
static_assert(AssertSize<SubtableHeader, 6>()); static_assert(AssertSize<SubtableHeader, 6>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/kern#format-0 // https://learn.microsoft.com/en-us/typography/opentype/spec/kern#format-0
struct [[gnu::packed]] Format0 { struct [[gnu::packed]] Format0 {
BigEndian<u16> n_pairs; Uint16 n_pairs;
BigEndian<u16> search_range; Uint16 search_range;
BigEndian<u16> entry_selector; Uint16 entry_selector;
BigEndian<u16> range_shift; Uint16 range_shift;
}; };
static_assert(AssertSize<Format0, 8>()); static_assert(AssertSize<Format0, 8>());
struct [[gnu::packed]] Format0Pair { struct [[gnu::packed]] Format0Pair {
BigEndian<u16> left; Uint16 left;
BigEndian<u16> right; Uint16 right;
FWord value; FWord value;
}; };
static_assert(AssertSize<Format0Pair, 6>()); static_assert(AssertSize<Format0Pair, 6>());
@ -483,33 +461,33 @@ class EBLC {
public: public:
// https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#sbitlinemetrics-record // https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#sbitlinemetrics-record
struct [[gnu::packed]] SbitLineMetrics { struct [[gnu::packed]] SbitLineMetrics {
i8 ascender {}; Int8 ascender {};
i8 descender {}; Int8 descender {};
u8 width_max {}; Uint8 width_max {};
i8 caret_slope_numerator {}; Int8 caret_slope_numerator {};
i8 caret_slope_denominator {}; Int8 caret_slope_denominator {};
i8 caret_offset {}; Int8 caret_offset {};
i8 min_origin_sb {}; Int8 min_origin_sb {};
i8 min_advance_sb {}; Int8 min_advance_sb {};
i8 max_before_bl {}; Int8 max_before_bl {};
i8 min_after_bl {}; Int8 min_after_bl {};
i8 pad1 {}; Int8 pad1 {};
i8 pad2 {}; Int8 pad2 {};
}; };
static_assert(AssertSize<SbitLineMetrics, 12>()); static_assert(AssertSize<SbitLineMetrics, 12>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtablearray // https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubtablearray
struct [[gnu::packed]] IndexSubTableArray { struct [[gnu::packed]] IndexSubTableArray {
BigEndian<u16> first_glyph_index; Uint16 first_glyph_index;
BigEndian<u16> last_glyph_index; Uint16 last_glyph_index;
Offset32 additional_offset_to_index_subtable; Offset32 additional_offset_to_index_subtable;
}; };
static_assert(AssertSize<IndexSubTableArray, 8>()); static_assert(AssertSize<IndexSubTableArray, 8>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubheader // https://learn.microsoft.com/en-us/typography/opentype/spec/eblc#indexsubheader
struct [[gnu::packed]] IndexSubHeader { struct [[gnu::packed]] IndexSubHeader {
BigEndian<u16> index_format; Uint16 index_format;
BigEndian<u16> image_format; Uint16 image_format;
Offset32 image_data_offset; Offset32 image_data_offset;
}; };
static_assert(AssertSize<IndexSubHeader, 8>()); static_assert(AssertSize<IndexSubHeader, 8>());
@ -530,25 +508,25 @@ public:
// https://learn.microsoft.com/en-us/typography/opentype/spec/cblc#bitmapsize-record // https://learn.microsoft.com/en-us/typography/opentype/spec/cblc#bitmapsize-record
struct [[gnu::packed]] BitmapSize { struct [[gnu::packed]] BitmapSize {
Offset32 index_subtable_array_offset; Offset32 index_subtable_array_offset;
BigEndian<u32> index_tables_size; Uint32 index_tables_size;
BigEndian<u32> number_of_index_subtables; Uint32 number_of_index_subtables;
BigEndian<u32> color_ref; Uint32 color_ref;
EBLC::SbitLineMetrics hori; EBLC::SbitLineMetrics hori;
EBLC::SbitLineMetrics vert; EBLC::SbitLineMetrics vert;
BigEndian<u16> start_glyph_index; Uint16 start_glyph_index;
BigEndian<u16> end_glyph_index; Uint16 end_glyph_index;
u8 ppem_x {}; Uint8 ppem_x {};
u8 ppem_y {}; Uint8 ppem_y {};
u8 bit_depth {}; Uint8 bit_depth {};
i8 flags {}; Int8 flags {};
}; };
static_assert(AssertSize<BitmapSize, 48>()); static_assert(AssertSize<BitmapSize, 48>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/cblc#cblcheader // https://learn.microsoft.com/en-us/typography/opentype/spec/cblc#cblcheader
struct [[gnu::packed]] CblcHeader { struct [[gnu::packed]] CblcHeader {
BigEndian<u16> major_version; Uint16 major_version;
BigEndian<u16> minor_version; Uint16 minor_version;
BigEndian<u32> num_sizes; Uint32 num_sizes;
// Stored in a separate span: // Stored in a separate span:
// BitmapSize bitmap_sizes[]; // BitmapSize bitmap_sizes[];
}; };
@ -577,11 +555,11 @@ class EBDT {
public: public:
// https://learn.microsoft.com/en-us/typography/opentype/spec/ebdt#smallglyphmetrics // https://learn.microsoft.com/en-us/typography/opentype/spec/ebdt#smallglyphmetrics
struct [[gnu::packed]] SmallGlyphMetrics { struct [[gnu::packed]] SmallGlyphMetrics {
u8 height {}; Uint8 height {};
u8 width {}; Uint8 width {};
i8 bearing_x {}; Int8 bearing_x {};
i8 bearing_y {}; Int8 bearing_y {};
u8 advance {}; Uint8 advance {};
}; };
static_assert(AssertSize<SmallGlyphMetrics, 5>()); static_assert(AssertSize<SmallGlyphMetrics, 5>());
}; };
@ -592,16 +570,16 @@ class CBDT {
public: public:
// https://learn.microsoft.com/en-us/typography/opentype/spec/cbdt#table-structure // https://learn.microsoft.com/en-us/typography/opentype/spec/cbdt#table-structure
struct [[gnu::packed]] CbdtHeader { struct [[gnu::packed]] CbdtHeader {
BigEndian<u16> major_version; Uint16 major_version;
BigEndian<u16> minor_version; Uint16 minor_version;
}; };
static_assert(AssertSize<CbdtHeader, 4>()); static_assert(AssertSize<CbdtHeader, 4>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/cbdt#format-17-small-metrics-png-image-data // https://learn.microsoft.com/en-us/typography/opentype/spec/cbdt#format-17-small-metrics-png-image-data
struct [[gnu::packed]] Format17 { struct [[gnu::packed]] Format17 {
EBDT::SmallGlyphMetrics glyph_metrics; EBDT::SmallGlyphMetrics glyph_metrics;
BigEndian<u32> data_len; Uint32 data_len;
u8 data[]; Uint8 data[];
}; };
static_assert(AssertSize<Format17, 9>()); static_assert(AssertSize<Format17, 9>());
@ -628,7 +606,7 @@ static_assert(AssertSize<FeatureRecord, 6>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#feature-list-table // https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#feature-list-table
struct [[gnu::packed]] FeatureList { struct [[gnu::packed]] FeatureList {
BigEndian<u16> feature_count; Uint16 feature_count;
FeatureRecord feature_records[]; FeatureRecord feature_records[];
}; };
static_assert(AssertSize<FeatureList, 2>()); static_assert(AssertSize<FeatureList, 2>());
@ -636,63 +614,63 @@ static_assert(AssertSize<FeatureList, 2>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#feature-table // https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#feature-table
struct [[gnu::packed]] Feature { struct [[gnu::packed]] Feature {
Offset16 feature_params_offset; Offset16 feature_params_offset;
BigEndian<u16> lookup_index_count; Uint16 lookup_index_count;
BigEndian<u16> lookup_list_indices[]; Uint16 lookup_list_indices[];
}; };
static_assert(AssertSize<Feature, 4>()); static_assert(AssertSize<Feature, 4>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#lookup-table // https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#lookup-table
struct [[gnu::packed]] Lookup { struct [[gnu::packed]] Lookup {
BigEndian<u16> lookup_type; Uint16 lookup_type;
BigEndian<u16> lookup_flag; Uint16 lookup_flag;
BigEndian<u16> subtable_count; Uint16 subtable_count;
Offset16 subtable_offsets[]; Offset16 subtable_offsets[];
}; };
static_assert(AssertSize<Lookup, 6>()); static_assert(AssertSize<Lookup, 6>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#lookup-list-table // https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#lookup-list-table
struct [[gnu::packed]] LookupList { struct [[gnu::packed]] LookupList {
BigEndian<u16> lookup_count; Uint16 lookup_count;
Offset16 lookup_offsets[]; Offset16 lookup_offsets[];
}; };
static_assert(AssertSize<LookupList, 2>()); static_assert(AssertSize<LookupList, 2>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#coverage-format-1 // https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#coverage-format-1
struct [[gnu::packed]] CoverageFormat1 { struct [[gnu::packed]] CoverageFormat1 {
BigEndian<u16> coverage_format; Uint16 coverage_format;
BigEndian<u16> glyph_count; Uint16 glyph_count;
BigEndian<u16> glyph_array[]; Uint16 glyph_array[];
}; };
static_assert(AssertSize<CoverageFormat1, 4>()); static_assert(AssertSize<CoverageFormat1, 4>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#coverage-format-2 // https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#coverage-format-2
struct [[gnu::packed]] RangeRecord { struct [[gnu::packed]] RangeRecord {
BigEndian<u16> start_glyph_id; Uint16 start_glyph_id;
BigEndian<u16> end_glyph_id; Uint16 end_glyph_id;
BigEndian<u16> start_coverage_index; Uint16 start_coverage_index;
}; };
static_assert(AssertSize<RangeRecord, 6>()); static_assert(AssertSize<RangeRecord, 6>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#coverage-format-2 // https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#coverage-format-2
struct [[gnu::packed]] CoverageFormat2 { struct [[gnu::packed]] CoverageFormat2 {
BigEndian<u16> coverage_format; Uint16 coverage_format;
BigEndian<u16> range_count; Uint16 range_count;
RangeRecord range_records[]; RangeRecord range_records[];
}; };
static_assert(AssertSize<CoverageFormat2, 4>()); static_assert(AssertSize<CoverageFormat2, 4>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#class-definition-table-format-2 // https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#class-definition-table-format-2
struct [[gnu::packed]] ClassRangeRecord { struct [[gnu::packed]] ClassRangeRecord {
BigEndian<u16> start_glyph_id; Uint16 start_glyph_id;
BigEndian<u16> end_glyph_id; Uint16 end_glyph_id;
BigEndian<u16> class_; Uint16 class_;
}; };
static_assert(AssertSize<ClassRangeRecord, 6>()); static_assert(AssertSize<ClassRangeRecord, 6>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#class-definition-table-format-2 // https://learn.microsoft.com/en-us/typography/opentype/spec/chapter2#class-definition-table-format-2
struct [[gnu::packed]] ClassDefFormat2 { struct [[gnu::packed]] ClassDefFormat2 {
BigEndian<u16> class_format; Uint16 class_format;
BigEndian<u16> class_range_count; Uint16 class_range_count;
ClassRangeRecord class_range_records[]; ClassRangeRecord class_range_records[];
}; };
static_assert(AssertSize<ClassDefFormat2, 4>()); static_assert(AssertSize<ClassDefFormat2, 4>());
@ -702,8 +680,8 @@ class GPOS {
public: public:
// https://learn.microsoft.com/en-us/typography/opentype/spec/gpos#gpos-header // https://learn.microsoft.com/en-us/typography/opentype/spec/gpos#gpos-header
struct [[gnu::packed]] Version1_0 { struct [[gnu::packed]] Version1_0 {
BigEndian<u16> major_version; Uint16 major_version;
BigEndian<u16> minor_version; Uint16 minor_version;
Offset16 script_list_offset; Offset16 script_list_offset;
Offset16 feature_list_offset; Offset16 feature_list_offset;
Offset16 lookup_list_offset; Offset16 lookup_list_offset;
@ -712,21 +690,21 @@ public:
// https://learn.microsoft.com/en-us/typography/opentype/spec/gpos#pair-adjustment-positioning-format-1-adjustments-for-glyph-pairs // https://learn.microsoft.com/en-us/typography/opentype/spec/gpos#pair-adjustment-positioning-format-1-adjustments-for-glyph-pairs
struct [[gnu::packed]] PairPosFormat1 { struct [[gnu::packed]] PairPosFormat1 {
BigEndian<u16> pos_format; Uint16 pos_format;
Offset16 coverage_offset; Offset16 coverage_offset;
BigEndian<u16> value_format1; Uint16 value_format1;
BigEndian<u16> value_format2; Uint16 value_format2;
BigEndian<u16> pair_set_count; Uint16 pair_set_count;
Offset16 pair_set_offsets[]; Offset16 pair_set_offsets[];
}; };
static_assert(AssertSize<PairPosFormat1, 10>()); static_assert(AssertSize<PairPosFormat1, 10>());
// https://learn.microsoft.com/en-us/typography/opentype/spec/gpos#value-record // https://learn.microsoft.com/en-us/typography/opentype/spec/gpos#value-record
struct [[gnu::packed]] ValueRecord { struct [[gnu::packed]] ValueRecord {
BigEndian<i16> x_placement; Int16 x_placement;
BigEndian<i16> y_placement; Int16 y_placement;
BigEndian<i16> x_advance; Int16 x_advance;
BigEndian<i16> y_advance; Int16 y_advance;
Offset16 x_placement_device_offset; Offset16 x_placement_device_offset;
Offset16 y_placement_device_offset; Offset16 y_placement_device_offset;
Offset16 x_advance_device_offset; Offset16 x_advance_device_offset;
@ -736,14 +714,14 @@ public:
// https://learn.microsoft.com/en-us/typography/opentype/spec/gpos#pair-adjustment-positioning-format-2-class-pair-adjustment // https://learn.microsoft.com/en-us/typography/opentype/spec/gpos#pair-adjustment-positioning-format-2-class-pair-adjustment
struct [[gnu::packed]] PairPosFormat2 { struct [[gnu::packed]] PairPosFormat2 {
BigEndian<u16> pos_format; Uint16 pos_format;
Offset16 coverage_offset; Offset16 coverage_offset;
BigEndian<u16> value_format1; Uint16 value_format1;
BigEndian<u16> value_format2; Uint16 value_format2;
Offset16 class_def1_offset; Offset16 class_def1_offset;
Offset16 class_def2_offset; Offset16 class_def2_offset;
BigEndian<u16> class1_count; Uint16 class1_count;
BigEndian<u16> class2_count; Uint16 class2_count;
}; };
static_assert(AssertSize<PairPosFormat2, 16>()); static_assert(AssertSize<PairPosFormat2, 16>());