1
0
Fork 0
mirror of https://github.com/LadybirdBrowser/ladybird.git synced 2025-06-10 01:51:03 +09:00

LibPDF+LibGfx: Do not try to read "hmtx" table for PDFs

It is sometimes truncated in fonts embedded in PDFs, and the data
is not needed to render PDFs. 26 of my 1000 test files complained
"Could not load Hmtx: Not enough data" before.

Increases number of PDFs that render without diagnostics from
743 to 764.
This commit is contained in:
Nico Weber 2024-02-20 11:42:59 -05:00 committed by Andreas Kling
parent 5efe80af7f
commit 0dee94ef40
Notes: sideshowbarker 2024-07-17 09:49:33 +09:00
3 changed files with 14 additions and 8 deletions

View file

@ -271,9 +271,12 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_offset(ReadonlyBytes buffer, u3
return Error::from_string_literal("Font is missing Maxp"); return Error::from_string_literal("Font is missing Maxp");
auto maxp = TRY(Maxp::from_slice(opt_maxp_slice.value())); auto maxp = TRY(Maxp::from_slice(opt_maxp_slice.value()));
Optional<Hmtx> hmtx;
if (!(options.skip_tables & Options::SkipTables::Hmtx)) {
if (!opt_hmtx_slice.has_value()) if (!opt_hmtx_slice.has_value())
return Error::from_string_literal("Font is missing Hmtx"); return Error::from_string_literal("Font is missing Hmtx");
auto hmtx = TRY(Hmtx::from_slice(opt_hmtx_slice.value(), maxp.num_glyphs(), hhea.number_of_h_metrics())); hmtx = TRY(Hmtx::from_slice(opt_hmtx_slice.value(), maxp.num_glyphs(), hhea.number_of_h_metrics()));
}
NonnullOwnPtr<CharCodeToGlyphIndex> cmap = options.external_cmap ? options.external_cmap.release_nonnull() : TRY(CmapCharCodeToGlyphIndex::from_slice(opt_cmap_slice.value())); NonnullOwnPtr<CharCodeToGlyphIndex> cmap = options.external_cmap ? options.external_cmap.release_nonnull() : TRY(CmapCharCodeToGlyphIndex::from_slice(opt_cmap_slice.value()));
@ -412,14 +415,14 @@ Gfx::ScaledGlyphMetrics Font::glyph_metrics(u32 glyph_id, float x_scale, float y
return embedded_bitmap_metrics.release_value(); return embedded_bitmap_metrics.release_value();
} }
if (!m_loca.has_value() || !m_glyf.has_value()) { if (!m_loca.has_value() || !m_glyf.has_value() || !m_hmtx.has_value()) {
return Gfx::ScaledGlyphMetrics {}; return Gfx::ScaledGlyphMetrics {};
} }
if (glyph_id >= glyph_count()) { if (glyph_id >= glyph_count()) {
glyph_id = 0; glyph_id = 0;
} }
auto horizontal_metrics = m_hmtx.get_glyph_horizontal_metrics(glyph_id); auto horizontal_metrics = m_hmtx->get_glyph_horizontal_metrics(glyph_id);
auto glyph_offset = m_loca->get_glyph_offset(glyph_id); auto glyph_offset = m_loca->get_glyph_offset(glyph_id);
auto glyph = m_glyf->glyph(glyph_offset); auto glyph = m_glyf->glyph(glyph_offset);
return Gfx::ScaledGlyphMetrics { return Gfx::ScaledGlyphMetrics {

View file

@ -34,6 +34,9 @@ struct FontOptions {
enum SkipTables { enum SkipTables {
// If set, do not try to read the 'name' table. family() and variant() will return empty strings. // If set, do not try to read the 'name' table. family() and variant() will return empty strings.
Name = 1 << 0, Name = 1 << 0,
// If set, do not try to read the 'hmtx' table. This will make glyph_metrics() return 0 for everyting and is_fixed_width() return true.
Hmtx = 1 << 1,
}; };
u32 skip_tables { 0 }; u32 skip_tables { 0 };
}; };
@ -94,7 +97,7 @@ private:
Optional<Name>&& name, Optional<Name>&& name,
Hhea&& hhea, Hhea&& hhea,
Maxp&& maxp, Maxp&& maxp,
Hmtx&& hmtx, Optional<Hmtx>&& hmtx,
NonnullOwnPtr<CharCodeToGlyphIndex> cmap, NonnullOwnPtr<CharCodeToGlyphIndex> cmap,
Optional<Loca>&& loca, Optional<Loca>&& loca,
Optional<Glyf>&& glyf, Optional<Glyf>&& glyf,
@ -130,7 +133,7 @@ private:
Optional<Name> m_name; Optional<Name> m_name;
Hhea m_hhea; Hhea m_hhea;
Maxp m_maxp; Maxp m_maxp;
Hmtx m_hmtx; Optional<Hmtx> m_hmtx;
Optional<Loca> m_loca; Optional<Loca> m_loca;
Optional<Glyf> m_glyf; Optional<Glyf> m_glyf;
NonnullOwnPtr<CharCodeToGlyphIndex> m_cmap; NonnullOwnPtr<CharCodeToGlyphIndex> m_cmap;

View file

@ -19,7 +19,7 @@ class Renderer;
// PDF files don't need most of the data in OpenType fonts, and even contain invalid data for // PDF files don't need most of the data in OpenType fonts, and even contain invalid data for
// these tables in some cases. Skip reading these tables. // these tables in some cases. Skip reading these tables.
constexpr u32 pdf_skipped_opentype_tables = OpenType::FontOptions::SkipTables::Name; constexpr u32 pdf_skipped_opentype_tables = OpenType::FontOptions::SkipTables::Name | OpenType::FontOptions::SkipTables::Hmtx;
class PDFFont : public RefCounted<PDFFont> { class PDFFont : public RefCounted<PDFFont> {
public: public: