1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 08:57:34 +00:00

LibGfx/OpenType: Make "glyf" and "loca" tables optional

These tables are not guaranteed to be present in all font files.
This commit is contained in:
Andreas Kling 2023-03-04 00:39:54 +01:00
parent 918a3082d6
commit e6131e45e2
2 changed files with 33 additions and 20 deletions

View file

@ -405,7 +405,6 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_offset(ReadonlyBytes buffer, u3
Optional<Maxp> opt_maxp = {}; Optional<Maxp> opt_maxp = {};
Optional<Hmtx> opt_hmtx = {}; Optional<Hmtx> opt_hmtx = {};
Optional<Cmap> opt_cmap = {}; Optional<Cmap> opt_cmap = {};
Optional<Loca> opt_loca = {};
Optional<OS2> opt_os2 = {}; Optional<OS2> opt_os2 = {};
Optional<Kern> opt_kern = {}; Optional<Kern> opt_kern = {};
Optional<Fpgm> opt_fpgm = {}; Optional<Fpgm> opt_fpgm = {};
@ -481,13 +480,17 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_offset(ReadonlyBytes buffer, u3
return Error::from_string_literal("Could not load Cmap"); return Error::from_string_literal("Could not load Cmap");
auto cmap = opt_cmap.value(); auto cmap = opt_cmap.value();
if (!opt_loca_slice.has_value() || !(opt_loca = Loca::from_slice(opt_loca_slice.value(), maxp.num_glyphs(), head.index_to_loc_format())).has_value()) Optional<Loca> loca;
return Error::from_string_literal("Could not load Loca"); if (opt_loca_slice.has_value()) {
auto loca = opt_loca.value(); loca = 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");
}
if (!opt_glyf_slice.has_value()) Optional<Glyf> glyf;
return Error::from_string_literal("Could not load Glyf"); if (opt_glyf_slice.has_value()) {
auto glyf = Glyf(opt_glyf_slice.value()); glyf = Glyf(opt_glyf_slice.value());
}
Optional<OS2> os2; Optional<OS2> os2;
if (opt_os2_slice.has_value()) if (opt_os2_slice.has_value())
@ -560,15 +563,18 @@ Gfx::ScaledFontMetrics Font::metrics([[maybe_unused]] float x_scale, float y_sca
}; };
} }
// FIXME: "loca" and "glyf" are not available for CFF fonts.
Gfx::ScaledGlyphMetrics Font::glyph_metrics(u32 glyph_id, float x_scale, float y_scale) const Gfx::ScaledGlyphMetrics Font::glyph_metrics(u32 glyph_id, float x_scale, float y_scale) const
{ {
if (!m_loca.has_value() || !m_glyf.has_value()) {
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 {
.ascender = static_cast<float>(glyph.ascender()) * y_scale, .ascender = static_cast<float>(glyph.ascender()) * y_scale,
.descender = static_cast<float>(glyph.descender()) * y_scale, .descender = static_cast<float>(glyph.descender()) * y_scale,
@ -584,14 +590,17 @@ float Font::glyphs_horizontal_kerning(u32 left_glyph_id, u32 right_glyph_id, flo
return m_kern->get_glyph_kerning(left_glyph_id, right_glyph_id) * x_scale; return m_kern->get_glyph_kerning(left_glyph_id, right_glyph_id) * x_scale;
} }
// FIXME: "loca" and "glyf" are not available for CFF fonts.
RefPtr<Gfx::Bitmap> Font::rasterize_glyph(u32 glyph_id, float x_scale, float y_scale, Gfx::GlyphSubpixelOffset subpixel_offset) const RefPtr<Gfx::Bitmap> Font::rasterize_glyph(u32 glyph_id, float x_scale, float y_scale, Gfx::GlyphSubpixelOffset subpixel_offset) const
{ {
if (!m_loca.has_value() || !m_glyf.has_value()) {
return nullptr;
}
if (glyph_id >= glyph_count()) { if (glyph_id >= glyph_count()) {
glyph_id = 0; glyph_id = 0;
} }
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);
i16 ascender = 0; i16 ascender = 0;
i16 descender = 0; i16 descender = 0;
@ -608,8 +617,8 @@ RefPtr<Gfx::Bitmap> Font::rasterize_glyph(u32 glyph_id, float x_scale, float y_s
if (glyph_id >= glyph_count()) { if (glyph_id >= glyph_count()) {
glyph_id = 0; glyph_id = 0;
} }
auto glyph_offset = m_loca.get_glyph_offset(glyph_id); auto glyph_offset = m_loca->get_glyph_offset(glyph_id);
return m_glyf.glyph(glyph_offset); return m_glyf->glyph(glyph_offset);
}); });
} }
@ -735,8 +744,12 @@ Optional<ReadonlyBytes> Font::control_value_program() const
Optional<ReadonlyBytes> Font::glyph_program(u32 glyph_id) const Optional<ReadonlyBytes> Font::glyph_program(u32 glyph_id) const
{ {
auto glyph_offset = m_loca.get_glyph_offset(glyph_id); if (!m_loca.has_value() || !m_glyf.has_value()) {
auto glyph = m_glyf.glyph(glyph_offset); return {};
}
auto glyph_offset = m_loca->get_glyph_offset(glyph_id);
auto glyph = m_glyf->glyph(glyph_offset);
return glyph.program(); return glyph.program();
} }

View file

@ -59,7 +59,7 @@ private:
static ErrorOr<NonnullRefPtr<Font>> try_load_from_offset(ReadonlyBytes, unsigned index = 0); static ErrorOr<NonnullRefPtr<Font>> try_load_from_offset(ReadonlyBytes, unsigned index = 0);
Font(ReadonlyBytes bytes, Head&& head, Name&& name, Hhea&& hhea, Maxp&& maxp, Hmtx&& hmtx, Cmap&& cmap, Loca&& loca, Glyf&& glyf, Optional<OS2> os2, Optional<Kern>&& kern, Optional<Fpgm> fpgm, Optional<Prep> prep) Font(ReadonlyBytes bytes, Head&& head, Name&& name, Hhea&& hhea, Maxp&& maxp, Hmtx&& hmtx, Cmap&& cmap, Optional<Loca>&& loca, Optional<Glyf>&& glyf, Optional<OS2> os2, Optional<Kern>&& kern, Optional<Fpgm> fpgm, Optional<Prep> prep)
: m_buffer(move(bytes)) : m_buffer(move(bytes))
, m_head(move(head)) , m_head(move(head))
, m_name(move(name)) , m_name(move(name))
@ -86,8 +86,8 @@ private:
Hhea m_hhea; Hhea m_hhea;
Maxp m_maxp; Maxp m_maxp;
Hmtx m_hmtx; Hmtx m_hmtx;
Loca m_loca; Optional<Loca> m_loca;
Glyf m_glyf; Optional<Glyf> m_glyf;
Cmap m_cmap; Cmap m_cmap;
Optional<OS2> m_os2; Optional<OS2> m_os2;
Optional<Kern> m_kern; Optional<Kern> m_kern;