mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 07:07:34 +00:00
LibTTF: Parse TTF "name" table
This commit is contained in:
parent
f12754ee10
commit
2c4e13f14a
3 changed files with 91 additions and 2 deletions
|
@ -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 };
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue