diff options
author | Stephan Unverwerth <s.unverwerth@gmx.de> | 2021-01-01 00:16:18 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-02-15 08:50:48 +0100 |
commit | 2c4e13f14af5762b568f72ba4688979c096f03d2 (patch) | |
tree | 6b1fc0078b9e6af0ccba58d306cb3229a9194a8d /Userland/Libraries/LibTTF | |
parent | f12754ee10ae1a1fcf4b5cf8b18fd06b5f4c13d2 (diff) | |
download | serenity-2c4e13f14af5762b568f72ba4688979c096f03d2.zip |
LibTTF: Parse TTF "name" table
Diffstat (limited to 'Userland/Libraries/LibTTF')
-rw-r--r-- | Userland/Libraries/LibTTF/Font.cpp | 51 | ||||
-rw-r--r-- | Userland/Libraries/LibTTF/Font.h | 6 | ||||
-rw-r--r-- | Userland/Libraries/LibTTF/Tables.h | 36 |
3 files changed, 91 insertions, 2 deletions
diff --git a/Userland/Libraries/LibTTF/Font.cpp b/Userland/Libraries/LibTTF/Font.cpp index 39ef6754a2..083d9db405 100644 --- a/Userland/Libraries/LibTTF/Font.cpp +++ b/Userland/Libraries/LibTTF/Font.cpp @@ -174,6 +174,29 @@ Optional<Hmtx> Hmtx::from_slice(const ReadonlyBytes& slice, u32 num_glyphs, u32 return Hmtx(slice, num_glyphs, number_of_h_metrics); } +Optional<Name> Name::from_slice(const ReadonlyBytes& slice) +{ + return Name(slice); +} + +String Name::string_for_id(NameId id) const +{ + auto num_entries = be_u16(m_slice.offset_pointer(2)); + auto string_offset = be_u16(m_slice.offset_pointer(4)); + + for (int i = 0; i < num_entries; ++i) { + auto this_id = be_u16(m_slice.offset_pointer(6 + i * 12 + 6)); + if (this_id != (u16)id) + continue; + + auto length = be_u16(m_slice.offset_pointer(6 + i * 12 + 8)); + auto offset = be_u16(m_slice.offset_pointer(6 + i * 12 + 10)); + return String((const char*)m_slice.offset_pointer(string_offset + offset), length); + } + + return String::empty(); +} + GlyphHorizontalMetrics Hmtx::get_glyph_horizontal_metrics(u32 glyph_id) const { ASSERT(glyph_id < m_num_glyphs); @@ -252,6 +275,7 @@ RefPtr<Font> Font::load_from_offset(ByteBuffer&& buffer, u32 offset) } Optional<ReadonlyBytes> opt_head_slice = {}; + Optional<ReadonlyBytes> opt_name_slice = {}; Optional<ReadonlyBytes> opt_hhea_slice = {}; Optional<ReadonlyBytes> opt_maxp_slice = {}; Optional<ReadonlyBytes> opt_hmtx_slice = {}; @@ -260,6 +284,7 @@ RefPtr<Font> Font::load_from_offset(ByteBuffer&& buffer, u32 offset) Optional<ReadonlyBytes> opt_glyf_slice = {}; Optional<Head> opt_head = {}; + Optional<Name> opt_name = {}; Optional<Hhea> opt_hhea = {}; Optional<Maxp> opt_maxp = {}; Optional<Hmtx> opt_hmtx = {}; @@ -292,6 +317,8 @@ RefPtr<Font> Font::load_from_offset(ByteBuffer&& buffer, u32 offset) // Get the table offsets we need. if (tag == tag_from_str("head")) { opt_head_slice = buffer_here; + } else if (tag == tag_from_str("name")) { + opt_name_slice = buffer_here; } else if (tag == tag_from_str("hhea")) { opt_hhea_slice = buffer_here; } else if (tag == tag_from_str("maxp")) { @@ -313,6 +340,12 @@ RefPtr<Font> Font::load_from_offset(ByteBuffer&& buffer, u32 offset) } auto head = opt_head.value(); + if (!opt_name_slice.has_value() || !(opt_name = Name::from_slice(opt_name_slice.value())).has_value()) { + dbg() << "Could not load Name"; + return nullptr; + } + auto name = opt_name.value(); + if (!opt_hhea_slice.has_value() || !(opt_hhea = Hhea::from_slice(opt_hhea_slice.value())).has_value()) { dbgln("Could not load Hhea"); return nullptr; @@ -369,7 +402,7 @@ RefPtr<Font> Font::load_from_offset(ByteBuffer&& buffer, u32 offset) } } - return adopt(*new Font(move(buffer), move(head), move(hhea), move(maxp), move(hmtx), move(cmap), move(loca), move(glyf))); + return adopt(*new Font(move(buffer), move(head), move(name), move(hhea), move(maxp), move(hmtx), move(cmap), move(loca), move(glyf))); } ScaledFontMetrics Font::metrics(float x_scale, float y_scale) const @@ -432,6 +465,22 @@ u16 Font::units_per_em() const return m_head.units_per_em(); } +String Font::family() const +{ + auto string = m_name.typographic_family_name(); + if (!string.is_empty()) + return string; + return m_name.family_name(); +} + +String Font::subfamily() const +{ + auto string = m_name.typographic_subfamily_name(); + if (!string.is_empty()) + return string; + return m_name.subfamily_name(); +} + int ScaledFont::width(const StringView& string) const { Utf8View utf8 { string }; diff --git a/Userland/Libraries/LibTTF/Font.h b/Userland/Libraries/LibTTF/Font.h index 79185411c0..939f1944e4 100644 --- a/Userland/Libraries/LibTTF/Font.h +++ b/Userland/Libraries/LibTTF/Font.h @@ -74,6 +74,8 @@ public: u32 glyph_count() const; u16 units_per_em() const; u32 glyph_id_for_codepoint(u32 codepoint) const { return m_cmap.glyph_id_for_codepoint(codepoint); } + String family() const; + String subfamily() const; private: enum class Offsets { @@ -88,9 +90,10 @@ private: }; static RefPtr<Font> load_from_offset(ByteBuffer&&, unsigned index = 0); - Font(ByteBuffer&& buffer, Head&& head, Hhea&& hhea, Maxp&& maxp, Hmtx&& hmtx, Cmap&& cmap, Loca&& loca, Glyf&& glyf) + Font(ByteBuffer&& buffer, Head&& head, Name&& name, Hhea&& hhea, Maxp&& maxp, Hmtx&& hmtx, Cmap&& cmap, Loca&& loca, Glyf&& glyf) : m_buffer(move(buffer)) , m_head(move(head)) + , m_name(move(name)) , m_hhea(move(hhea)) , m_maxp(move(maxp)) , m_hmtx(move(hmtx)) @@ -104,6 +107,7 @@ private: ByteBuffer m_buffer; // These are stateful wrappers around non-owning slices Head m_head; + Name m_name; Hhea m_hhea; Maxp m_maxp; Hmtx m_hmtx; diff --git a/Userland/Libraries/LibTTF/Tables.h b/Userland/Libraries/LibTTF/Tables.h index 5264911ad9..d5f5014bd4 100644 --- a/Userland/Libraries/LibTTF/Tables.h +++ b/Userland/Libraries/LibTTF/Tables.h @@ -146,4 +146,40 @@ private: u32 m_number_of_h_metrics { 0 }; }; +class Name { +public: + static Optional<Name> from_slice(const ReadonlyBytes&); + + String family_name() const { return string_for_id(NameId::FamilyName); } + String subfamily_name() const { return string_for_id(NameId::SubfamilyName); } + String typographic_family_name() const { return string_for_id(NameId::TypographicFamilyName); } + String typographic_subfamily_name() const { return string_for_id(NameId::TypographicSubfamilyName); } + +private: + enum class NameId { + Copyright = 0, + FamilyName = 1, + SubfamilyName = 2, + UniqueIdentifier = 3, + FullName = 4, + VersionString = 5, + PostscriptName = 6, + Trademark = 7, + Manufacturer = 8, + Designer = 9, + Description = 10, + TypographicFamilyName = 16, + TypographicSubfamilyName = 17, + }; + + Name(const ReadonlyBytes& slice) + : m_slice(slice) + { + } + + String string_for_id(NameId id) const; + + ReadonlyBytes m_slice; +}; + } |