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

LibGfx: Use ErrorOr to report failure to load OpenFont tables

This commit is contained in:
Sam Atkins 2023-10-21 17:33:46 +01:00 committed by Andreas Kling
parent 1ab03ff963
commit 72483673d2
7 changed files with 51 additions and 64 deletions

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
#include <AK/Error.h>
#include <AK/Format.h> #include <AK/Format.h>
#include <AK/Optional.h> #include <AK/Optional.h>
#include <LibGfx/Font/OpenType/Cmap.h> #include <LibGfx/Font/OpenType/Cmap.h>
@ -180,10 +181,11 @@ u32 Cmap::glyph_id_for_code_point(u32 code_point) const
return subtable.glyph_id_for_code_point(code_point); return subtable.glyph_id_for_code_point(code_point);
} }
Optional<Cmap> Cmap::from_slice(ReadonlyBytes slice) ErrorOr<Cmap> Cmap::from_slice(ReadonlyBytes slice)
{ {
if (slice.size() < (size_t)Sizes::TableHeader) if (slice.size() < (size_t)Sizes::TableHeader)
return {}; return Error::from_string_literal("Could not load Cmap: Not enough data");
return Cmap(slice); return Cmap(slice);
} }

View file

@ -93,7 +93,7 @@ public:
u16 m_encoding_id { 0 }; u16 m_encoding_id { 0 };
}; };
static Optional<Cmap> from_slice(ReadonlyBytes); static ErrorOr<Cmap> from_slice(ReadonlyBytes);
u32 num_subtables() const; u32 num_subtables() const;
Optional<Subtable> subtable(u32 index) const; Optional<Subtable> subtable(u32 index) const;
void set_active_index(u32 index) { m_active_index = index; } void set_active_index(u32 index) { m_active_index = index; }

View file

@ -129,16 +129,6 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_offset(ReadonlyBytes buffer, u3
Optional<ReadonlyBytes> opt_fpgm_slice = {}; Optional<ReadonlyBytes> opt_fpgm_slice = {};
Optional<ReadonlyBytes> opt_prep_slice = {}; Optional<ReadonlyBytes> opt_prep_slice = {};
Optional<Head> opt_head = {};
Optional<Name> opt_name = {};
Optional<Hhea> opt_hhea = {};
Optional<Maxp> opt_maxp = {};
Optional<Hmtx> opt_hmtx = {};
Optional<Cmap> opt_cmap = {};
Optional<OS2> opt_os2 = {};
Optional<Kern> opt_kern = {};
Optional<Fpgm> opt_fpgm = {};
Optional<Prep> opt_prep = {};
Optional<CBLC> cblc; Optional<CBLC> cblc;
Optional<CBDT> cbdt; Optional<CBDT> cbdt;
Optional<GPOS> gpos; Optional<GPOS> gpos;
@ -188,36 +178,33 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_offset(ReadonlyBytes buffer, u3
} }
} }
if (!opt_head_slice.has_value() || !(opt_head = Head::from_slice(opt_head_slice.value())).has_value()) if (!opt_head_slice.has_value())
return Error::from_string_literal("Could not load Head"); return Error::from_string_literal("Font is missing Head");
auto head = opt_head.value(); auto head = TRY(Head::from_slice(opt_head_slice.value()));
if (!opt_name_slice.has_value() || !(opt_name = Name::from_slice(opt_name_slice.value())).has_value()) if (!opt_name_slice.has_value())
return Error::from_string_literal("Could not load Name"); return Error::from_string_literal("Font is missing Name");
auto name = opt_name.value(); auto name = TRY(Name::from_slice(opt_name_slice.value()));
if (!opt_hhea_slice.has_value() || !(opt_hhea = Hhea::from_slice(opt_hhea_slice.value())).has_value()) if (!opt_hhea_slice.has_value())
return Error::from_string_literal("Could not load Hhea"); return Error::from_string_literal("Font is missing Hhea");
auto hhea = opt_hhea.value(); auto hhea = TRY(Hhea::from_slice(opt_hhea_slice.value()));
if (!opt_maxp_slice.has_value() || !(opt_maxp = Maxp::from_slice(opt_maxp_slice.value())).has_value()) if (!opt_maxp_slice.has_value())
return Error::from_string_literal("Could not load Maxp"); return Error::from_string_literal("Font is missing Maxp");
auto maxp = opt_maxp.value(); auto maxp = TRY(Maxp::from_slice(opt_maxp_slice.value()));
if (!opt_hmtx_slice.has_value() || !(opt_hmtx = Hmtx::from_slice(opt_hmtx_slice.value(), maxp.num_glyphs(), hhea.number_of_h_metrics())).has_value()) if (!opt_hmtx_slice.has_value())
return Error::from_string_literal("Could not load Hmtx"); return Error::from_string_literal("Font is missing Hmtx");
auto hmtx = opt_hmtx.value(); auto hmtx = TRY(Hmtx::from_slice(opt_hmtx_slice.value(), maxp.num_glyphs(), hhea.number_of_h_metrics()));
if (!opt_cmap_slice.has_value() || !(opt_cmap = Cmap::from_slice(opt_cmap_slice.value())).has_value()) if (!opt_cmap_slice.has_value())
return Error::from_string_literal("Could not load Cmap"); return Error::from_string_literal("Font is missing Cmap");
auto cmap = opt_cmap.value(); auto cmap = TRY(Cmap::from_slice(opt_cmap_slice.value()));
Optional<Loca> loca; Optional<Loca> loca;
if (opt_loca_slice.has_value()) { if (opt_loca_slice.has_value())
loca = Loca::from_slice(opt_loca_slice.value(), maxp.num_glyphs(), head.index_to_loc_format()); loca = TRY(Loca::from_slice(opt_loca_slice.value(), maxp.num_glyphs(), head.index_to_loc_format()));
if (!loca.has_value())
return Error::from_string_literal("Could not load Loca");
}
Optional<Glyf> glyf; Optional<Glyf> glyf;
if (opt_glyf_slice.has_value()) { if (opt_glyf_slice.has_value()) {

View file

@ -176,18 +176,16 @@ Optional<Glyf::Glyph::ComponentIterator::Item> Glyf::Glyph::ComponentIterator::n
}; };
} }
Optional<Loca> Loca::from_slice(ReadonlyBytes slice, u32 num_glyphs, IndexToLocFormat index_to_loc_format) ErrorOr<Loca> Loca::from_slice(ReadonlyBytes slice, u32 num_glyphs, IndexToLocFormat index_to_loc_format)
{ {
switch (index_to_loc_format) { switch (index_to_loc_format) {
case IndexToLocFormat::Offset16: case IndexToLocFormat::Offset16:
if (slice.size() < num_glyphs * 2) { if (slice.size() < num_glyphs * 2)
return {}; return Error::from_string_literal("Could not load Loca: Not enough data");
}
break; break;
case IndexToLocFormat::Offset32: case IndexToLocFormat::Offset32:
if (slice.size() < num_glyphs * 4) { if (slice.size() < num_glyphs * 4)
return {}; return Error::from_string_literal("Could not load Loca: Not enough data");
}
break; break;
} }
return Loca(slice, num_glyphs, index_to_loc_format); return Loca(slice, num_glyphs, index_to_loc_format);

View file

@ -23,7 +23,7 @@ namespace OpenType {
// loca: Index to Location // loca: Index to Location
class Loca { class Loca {
public: public:
static Optional<Loca> from_slice(ReadonlyBytes, u32 num_glyphs, IndexToLocFormat); static ErrorOr<Loca> from_slice(ReadonlyBytes, u32 num_glyphs, IndexToLocFormat);
u32 get_glyph_offset(u32 glyph_id) const; u32 get_glyph_offset(u32 glyph_id) const;
private: private:

View file

@ -26,11 +26,11 @@ static u32 tag_from_str(char const* str)
return be_u32((u8 const*)str); return be_u32((u8 const*)str);
} }
Optional<Head> Head::from_slice(ReadonlyBytes slice) ErrorOr<Head> Head::from_slice(ReadonlyBytes slice)
{ {
if (slice.size() < sizeof(FontHeaderTable)) { if (slice.size() < sizeof(FontHeaderTable))
return {}; return Error::from_string_literal("Could not load Head: Not enough data");
}
return Head(slice); return Head(slice);
} }
@ -81,11 +81,11 @@ IndexToLocFormat Head::index_to_loc_format() const
} }
} }
Optional<Hhea> Hhea::from_slice(ReadonlyBytes slice) ErrorOr<Hhea> Hhea::from_slice(ReadonlyBytes slice)
{ {
if (slice.size() < sizeof(HorizontalHeaderTable)) { if (slice.size() < sizeof(HorizontalHeaderTable))
return {}; return Error::from_string_literal("Could not load Hhea: Not enough data");
}
return Hhea(slice); return Hhea(slice);
} }
@ -114,11 +114,11 @@ u16 Hhea::number_of_h_metrics() const
return header().number_of_h_metrics; return header().number_of_h_metrics;
} }
Optional<Maxp> Maxp::from_slice(ReadonlyBytes slice) ErrorOr<Maxp> Maxp::from_slice(ReadonlyBytes slice)
{ {
if (slice.size() < sizeof(MaximumProfileVersion0_5)) { if (slice.size() < sizeof(MaximumProfileVersion0_5))
return {}; return Error::from_string_literal("Could not load Maxp: Not enough data");
}
return Maxp(slice); return Maxp(slice);
} }
@ -127,10 +127,10 @@ u16 Maxp::num_glyphs() const
return header().num_glyphs; return header().num_glyphs;
} }
Optional<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(u16)) {
return {}; return Error::from_string_literal("Could not load Hmtx: Not enough data");
} }
return Hmtx(slice, num_glyphs, number_of_h_metrics); return Hmtx(slice, num_glyphs, number_of_h_metrics);
} }
@ -153,7 +153,7 @@ GlyphHorizontalMetrics Hmtx::get_glyph_horizontal_metrics(u32 glyph_id) const
}; };
} }
Optional<Name> Name::from_slice(ReadonlyBytes slice) ErrorOr<Name> Name::from_slice(ReadonlyBytes slice)
{ {
return Name(slice); return Name(slice);
} }

View file

@ -87,7 +87,7 @@ namespace OpenType {
// head: Font Header Table // head: Font Header Table
class Head { class Head {
public: public:
static Optional<Head> from_slice(ReadonlyBytes); static ErrorOr<Head> from_slice(ReadonlyBytes);
u16 units_per_em() const; u16 units_per_em() const;
i16 xmin() const; i16 xmin() const;
i16 ymin() const; i16 ymin() const;
@ -134,7 +134,7 @@ private:
// hhea - Horizontal Header Table // hhea - Horizontal Header Table
class Hhea { class Hhea {
public: public:
static Optional<Hhea> from_slice(ReadonlyBytes); static ErrorOr<Hhea> from_slice(ReadonlyBytes);
i16 ascender() const; i16 ascender() const;
i16 descender() const; i16 descender() const;
i16 line_gap() const; i16 line_gap() const;
@ -175,7 +175,7 @@ private:
// Maxp: Maximum Profile // Maxp: Maximum Profile
class Maxp { class Maxp {
public: public:
static Optional<Maxp> from_slice(ReadonlyBytes); static ErrorOr<Maxp> from_slice(ReadonlyBytes);
u16 num_glyphs() const; u16 num_glyphs() const;
@ -254,7 +254,7 @@ private:
// hmtx: Horizontal Metrics Table // hmtx: Horizontal Metrics Table
class Hmtx { class Hmtx {
public: public:
static Optional<Hmtx> from_slice(ReadonlyBytes, u32 num_glyphs, u32 number_of_h_metrics); static ErrorOr<Hmtx> from_slice(ReadonlyBytes, u32 num_glyphs, u32 number_of_h_metrics);
GlyphHorizontalMetrics get_glyph_horizontal_metrics(u32 glyph_id) const; GlyphHorizontalMetrics get_glyph_horizontal_metrics(u32 glyph_id) const;
private: private:
@ -373,7 +373,7 @@ public:
enum class WindowsLanguage : u16 { enum class WindowsLanguage : u16 {
EnglishUnitedStates = 0x0409, EnglishUnitedStates = 0x0409,
}; };
static Optional<Name> from_slice(ReadonlyBytes); static ErrorOr<Name> from_slice(ReadonlyBytes);
String family_name() const { return string_for_id(NameId::FamilyName); } String family_name() const { return string_for_id(NameId::FamilyName); }
String subfamily_name() const { return string_for_id(NameId::SubfamilyName); } String subfamily_name() const { return string_for_id(NameId::SubfamilyName); }