LibGfx/OpenType: Validate we can read the active cmap subtable format

We now reject fonts where the active cmap subtable is in a format
we can't read yet, instead of silently drawing squares for all glyphs.

This doesn't fire at all for my 1000-file PDF test set, but seems
like a good thing to check.

(Instead of duplicating the switch, I first tried making a
glyph_id_for_code_point_or_else() that returns ErrorOr<u32> and then
make both glyph_id_for_code_point() and validate_format_can_be_read()
call that, but I liked less how that worked out -- felt too clever.)
This commit is contained in:
Nico Weber 2024-02-07 20:23:18 -05:00 committed by Sam Atkins
parent be8b5b794f
commit 93ee01041f
Notes: sideshowbarker 2024-07-17 06:46:15 +09:00
3 changed files with 27 additions and 0 deletions

View File

@ -79,9 +79,31 @@ Optional<Cmap::Subtable> Cmap::subtable(u32 index) const
return Subtable(subtable_slice, platform_id, encoding_id);
}
ErrorOr<void> Cmap::validate_active_cmap_format() const
{
auto opt_subtable = subtable(m_active_index);
VERIFY(opt_subtable.has_value());
return opt_subtable.value().validate_format_can_be_read();
}
ErrorOr<void> Cmap::Subtable::validate_format_can_be_read() const
{
// Keep in sync with switch in glyph_id_for_code_point().
switch (format()) {
case Format::ByteEncoding:
case Format::SegmentToDelta:
case Format::TrimmedTable:
case Format::SegmentedCoverage:
return {};
default:
return Error::from_string_view("Unimplemented cmap format"sv);
}
}
// FIXME: Implement the missing formats.
u32 Cmap::Subtable::glyph_id_for_code_point(u32 code_point) const
{
// Keep in sync with switch in validate_format_can_be_read().
switch (format()) {
case Format::ByteEncoding:
return glyph_id_for_code_point_table_0(code_point);

View File

@ -55,6 +55,9 @@ public:
, m_encoding_id(encoding_id)
{
}
ErrorOr<void> validate_format_can_be_read() const;
// Returns 0 if glyph not found. This corresponds to the "missing glyph"
u32 glyph_id_for_code_point(u32 code_point) const;
Optional<Platform> platform_id() const;
@ -107,6 +110,7 @@ public:
u32 num_subtables() const;
Optional<Subtable> subtable(u32 index) const;
void set_active_index(u32 index) { m_active_index = index; }
ErrorOr<void> validate_active_cmap_format() const;
// Returns 0 if glyph not found. This corresponds to the "missing glyph"
u32 glyph_id_for_code_point(u32 code_point) const;

View File

@ -264,6 +264,7 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_offset(ReadonlyBytes buffer, u3
}
if (!active_cmap_index.has_value())
return Error::from_string_literal("No suitable cmap subtable found");
TRY(cmap.subtable(active_cmap_index.value()).value().validate_format_can_be_read());
cmap.set_active_index(active_cmap_index.value());
return adopt_ref(*new Font(