From e984200206c54ad485c4bdc8a2872edf494b079a Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Tue, 20 Jul 2021 01:31:00 +0200 Subject: [PATCH] LibTTF: Parse OS/2 tables The OS/2 table contains nice typographic ascent/descent information. --- Userland/Libraries/LibTTF/Font.cpp | 25 ++++++++++++++++++++++++- Userland/Libraries/LibTTF/Font.h | 4 +++- Userland/Libraries/LibTTF/Tables.h | 21 +++++++++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/Userland/Libraries/LibTTF/Font.cpp b/Userland/Libraries/LibTTF/Font.cpp index b24050d75c..32867bc70a 100644 --- a/Userland/Libraries/LibTTF/Font.cpp +++ b/Userland/Libraries/LibTTF/Font.cpp @@ -274,6 +274,7 @@ Result, String> Font::try_load_from_offset(ReadonlyBytes buf Optional opt_cmap_slice = {}; Optional opt_loca_slice = {}; Optional opt_glyf_slice = {}; + Optional opt_os2_slice = {}; Optional opt_head = {}; Optional opt_name = {}; @@ -282,6 +283,7 @@ Result, String> Font::try_load_from_offset(ReadonlyBytes buf Optional opt_hmtx = {}; Optional opt_cmap = {}; Optional opt_loca = {}; + Optional opt_os2 = {}; auto num_tables = be_u16(buffer.offset_pointer(offset + (u32)Offsets::NumTables)); if (buffer.size() < offset + (u32)Sizes::OffsetTable + num_tables * (u32)Sizes::TableRecord) @@ -318,6 +320,8 @@ Result, String> Font::try_load_from_offset(ReadonlyBytes buf opt_loca_slice = buffer_here; } else if (tag == tag_from_str("glyf")) { opt_glyf_slice = buffer_here; + } else if (tag == tag_from_str("OS/2")) { + opt_os2_slice = buffer_here; } } @@ -353,6 +357,10 @@ Result, String> Font::try_load_from_offset(ReadonlyBytes buf return String { "Could not load Glyf" }; auto glyf = Glyf(opt_glyf_slice.value()); + if (!opt_os2_slice.has_value()) + return String { "Could not load OS/2" }; + auto os2 = OS2(opt_os2_slice.value()); + // Select cmap table. FIXME: Do this better. Right now, just looks for platform "Windows" // and corresponding encoding "Unicode full repertoire", or failing that, "Unicode BMP" for (u32 i = 0; i < cmap.num_subtables(); i++) { @@ -373,7 +381,7 @@ Result, String> Font::try_load_from_offset(ReadonlyBytes buf } } - return adopt_ref(*new Font(move(buffer), move(head), move(name), move(hhea), move(maxp), move(hmtx), move(cmap), move(loca), move(glyf))); + return adopt_ref(*new Font(move(buffer), move(head), move(name), move(hhea), move(maxp), move(hmtx), move(cmap), move(loca), move(glyf), move(os2))); } ScaledFontMetrics Font::metrics(float x_scale, float y_scale) const @@ -551,4 +559,19 @@ u8 ScaledFont::glyph_fixed_width() const return glyph_metrics(glyph_id_for_code_point(' ')).advance_width; } +i16 OS2::typographic_ascender() const +{ + return be_i16(m_slice.offset_pointer((u32)Offsets::TypographicAscender)); +} + +i16 OS2::typographic_descender() const +{ + return be_i16(m_slice.offset_pointer((u32)Offsets::TypographicDescender)); +} + +i16 OS2::typographic_line_gap() const +{ + return be_i16(m_slice.offset_pointer((u32)Offsets::TypographicLineGap)); +} + } diff --git a/Userland/Libraries/LibTTF/Font.h b/Userland/Libraries/LibTTF/Font.h index 9a565972f6..42d2b948e0 100644 --- a/Userland/Libraries/LibTTF/Font.h +++ b/Userland/Libraries/LibTTF/Font.h @@ -73,7 +73,7 @@ private: static Result, String> 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) + Font(ReadonlyBytes bytes, Head&& head, Name&& name, Hhea&& hhea, Maxp&& maxp, Hmtx&& hmtx, Cmap&& cmap, Loca&& loca, Glyf&& glyf, OS2&& os2) : m_buffer(move(bytes)) , m_head(move(head)) , m_name(move(name)) @@ -83,6 +83,7 @@ private: , m_loca(move(loca)) , m_glyf(move(glyf)) , m_cmap(move(cmap)) + , m_os2(move(os2)) { } @@ -99,6 +100,7 @@ private: Loca m_loca; Glyf m_glyf; Cmap m_cmap; + OS2 m_os2; }; class ScaledFont : public Gfx::Font { diff --git a/Userland/Libraries/LibTTF/Tables.h b/Userland/Libraries/LibTTF/Tables.h index 294f0490a3..2c7a5a7d29 100644 --- a/Userland/Libraries/LibTTF/Tables.h +++ b/Userland/Libraries/LibTTF/Tables.h @@ -126,6 +126,27 @@ private: u32 m_number_of_h_metrics { 0 }; }; +class OS2 { +public: + enum class Offsets { + TypographicAscender = 68, + TypographicDescender = 70, + TypographicLineGap = 72, + }; + + i16 typographic_ascender() const; + i16 typographic_descender() const; + i16 typographic_line_gap() const; + + explicit OS2(ReadonlyBytes const& slice) + : m_slice(slice) + { + } + +private: + ReadonlyBytes m_slice; +}; + class Name { public: enum class Platform {