mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 12:47:35 +00:00
LibGfx: Read OpenType TTCHeaderV1 as a struct
Also check that the requested font index actually exists in the font collection.
This commit is contained in:
parent
1a6da4fbf2
commit
984a2c314b
1 changed files with 30 additions and 6 deletions
|
@ -23,6 +23,26 @@
|
||||||
|
|
||||||
namespace OpenType {
|
namespace OpenType {
|
||||||
|
|
||||||
|
// https://learn.microsoft.com/en-us/typography/opentype/spec/otff#ttc-header
|
||||||
|
struct [[gnu::packed]] TTCHeaderV1 {
|
||||||
|
Tag ttc_tag; // Font Collection ID string: 'ttcf' (used for fonts with CFF or CFF2 outlines as well as TrueType outlines)
|
||||||
|
BigEndian<u16> major_version; // Major version of the TTC Header, = 1.
|
||||||
|
BigEndian<u16> minor_version; // Minor version of the TTC Header, = 0.
|
||||||
|
BigEndian<u32> num_fonts; // Number of fonts in TTC
|
||||||
|
Offset32 table_directory_offsets; // Array of offsets to the TableDirectory for each font from the beginning of the file
|
||||||
|
};
|
||||||
|
static_assert(AssertSize<TTCHeaderV1, 16>());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
class AK::Traits<OpenType::TTCHeaderV1> : public GenericTraits<OpenType::TTCHeaderV1> {
|
||||||
|
public:
|
||||||
|
static constexpr bool is_trivially_serializable() { return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace OpenType {
|
||||||
|
|
||||||
u16 be_u16(u8 const*);
|
u16 be_u16(u8 const*);
|
||||||
u32 be_u32(u8 const*);
|
u32 be_u32(u8 const*);
|
||||||
i16 be_i16(u8 const*);
|
i16 be_i16(u8 const*);
|
||||||
|
@ -63,16 +83,20 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_resource(Core::Resource const&
|
||||||
|
|
||||||
ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_externally_owned_memory(ReadonlyBytes buffer, unsigned index)
|
ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_externally_owned_memory(ReadonlyBytes buffer, unsigned index)
|
||||||
{
|
{
|
||||||
if (buffer.size() < 4)
|
FixedMemoryStream stream { buffer };
|
||||||
return Error::from_string_literal("Font file too small");
|
|
||||||
|
|
||||||
u32 tag = be_u32(buffer.data());
|
auto tag = TRY(stream.read_value<Tag>());
|
||||||
if (tag == tag_from_str("ttcf")) {
|
if (tag == tag_from_str("ttcf")) {
|
||||||
// It's a font collection
|
// It's a font collection
|
||||||
if (buffer.size() < (u32)Sizes::TTCHeaderV1 + sizeof(u32) * (index + 1))
|
TRY(stream.seek(0, SeekMode::SetPosition));
|
||||||
return Error::from_string_literal("Font file too small");
|
auto ttc_header_v1 = TRY(stream.read_in_place<TTCHeaderV1>());
|
||||||
|
// FIXME: Check for major_version == 2.
|
||||||
|
|
||||||
u32 offset = be_u32(buffer.offset((u32)Sizes::TTCHeaderV1 + sizeof(u32) * index));
|
if (index >= ttc_header_v1->num_fonts)
|
||||||
|
return Error::from_string_literal("Requested font index is too large");
|
||||||
|
|
||||||
|
TRY(stream.seek(ttc_header_v1->table_directory_offsets + sizeof(u32) * index, SeekMode::SetPosition));
|
||||||
|
auto offset = TRY(stream.read_value<BigEndian<u32>>());
|
||||||
return try_load_from_offset(buffer, offset);
|
return try_load_from_offset(buffer, offset);
|
||||||
}
|
}
|
||||||
if (tag == tag_from_str("OTTO"))
|
if (tag == tag_from_str("OTTO"))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue