1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 22:37:35 +00:00

LibGfx: Tweak semantics of some SkipTables enum values

It turns out that hmtx and OS/2 table values _are_ used when
rendering OpenType for PDFs: hmtx is used for the left-side bearing
value (which is read in `Painter::draw_glyph()`), and OS/2 is used
for the ascender, which Type0's CIDFontType2::draw_glyph()
and TrueTypeFont::draw_glyph() read.

So instead of not trying to read these tables, instead try to read
them but tolerate them failing to read and ignore them then.

Follow-up to #23276.

(I've seen weird glyph positioning from not reading the hmtx table.
I haven't seen any problems caused by not reading the OS/2 table yet,
but since the PDF code does use the ascender value, let's read that
too.)
This commit is contained in:
Nico Weber 2024-02-21 11:09:22 -05:00 committed by Andreas Kling
parent 1560bfc6c9
commit 78b3c552c2
2 changed files with 17 additions and 9 deletions

View file

@ -271,11 +271,16 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_offset(ReadonlyBytes buffer, u3
return Error::from_string_literal("Font is missing Maxp");
auto maxp = TRY(Maxp::from_slice(opt_maxp_slice.value()));
bool can_omit_hmtx = (options.skip_tables & Options::SkipTables::Hmtx);
Optional<Hmtx> hmtx;
if (!(options.skip_tables & Options::SkipTables::Hmtx)) {
if (!opt_hmtx_slice.has_value())
return Error::from_string_literal("Font is missing Hmtx");
hmtx = TRY(Hmtx::from_slice(opt_hmtx_slice.value(), maxp.num_glyphs(), hhea.number_of_h_metrics()));
if (opt_hmtx_slice.has_value()) {
auto hmtx_or_error = Hmtx::from_slice(opt_hmtx_slice.value(), maxp.num_glyphs(), hhea.number_of_h_metrics());
if (!hmtx_or_error.is_error())
hmtx = hmtx_or_error.release_value();
else if (!can_omit_hmtx)
return hmtx_or_error.release_error();
} else if (!can_omit_hmtx) {
return Error::from_string_literal("Font is missing Hmtx");
}
if (!options.external_cmap && !opt_cmap_slice.has_value())
@ -292,9 +297,12 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_offset(ReadonlyBytes buffer, u3
}
Optional<OS2> os2;
if (!(options.skip_tables & Options::SkipTables::OS2)) {
if (opt_os2_slice.has_value())
os2 = TRY(OS2::from_slice(opt_os2_slice.value()));
if (opt_os2_slice.has_value()) {
auto os2_or_error = OS2::from_slice(opt_os2_slice.value());
if (!os2_or_error.is_error())
os2 = os2_or_error.release_value();
else if (!(options.skip_tables & Options::SkipTables::OS2))
return os2_or_error.release_error();
}
Optional<Kern> kern {};

View file

@ -35,10 +35,10 @@ struct FontOptions {
// If set, do not try to read the 'name' table. family() and variant() will return empty strings.
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.
// If set, tolerate a missing or broken 'hmtx' table. This will make glyph_metrics() return 0 for everyting and is_fixed_width() return true.
Hmtx = 1 << 1,
// If set, do not try to read the 'OS/2' table. metrics(), resolve_ascender_and_descender(), weight(), width(), and slope() will return different values.
// If set, tolerate a missing or broken 'OS/2' table. metrics(), resolve_ascender_and_descender(), weight(), width(), and slope() will return different values.
OS2 = 1 << 2,
};
u32 skip_tables { 0 };