Sfoglia il codice sorgente

LibGfx: Use FourCC as OpenType::Tag type

The one deviation from the spec here is to use this in the WOFF
TableDirectoryEntry's tag field. However, *not* making that a Tag made
a lot of things more complicated than they need to be.
Sam Atkins 1 anno fa
parent
commit
54d0aafff0

+ 2 - 1
Userland/Libraries/LibGfx/Font/OpenType/DataTypes.h

@@ -11,6 +11,7 @@
 
 #include <AK/Endian.h>
 #include <AK/Types.h>
+#include <LibGfx/FourCC.h>
 
 // https://learn.microsoft.com/en-us/typography/opentype/spec/otff#data-types
 namespace OpenType {
@@ -39,7 +40,7 @@ struct [[gnu::packed]] LongDateTime {
 };
 static_assert(AssertSize<LongDateTime, 8>());
 
-using Tag = BigEndian<u32>;
+using Tag = Gfx::FourCC;
 
 using Offset16 = BigEndian<u16>;
 // FIXME: Offset24

+ 18 - 24
Userland/Libraries/LibGfx/Font/OpenType/Font.cpp

@@ -48,7 +48,6 @@ u16 be_u16(u8 const*);
 u32 be_u32(u8 const*);
 i16 be_i16(u8 const*);
 float be_fword(u8 const*);
-u32 tag_from_str(char const*);
 
 u16 be_u16(u8 const* ptr)
 {
@@ -70,11 +69,6 @@ float be_fword(u8 const* ptr)
     return (float)be_i16(ptr) / (float)(1 << 14);
 }
 
-u32 tag_from_str(char const* str)
-{
-    return be_u32((u8 const*)str);
-}
-
 ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_resource(Core::Resource const& resource, unsigned index)
 {
     auto font = TRY(try_load_from_externally_owned_memory(resource.data(), index));
@@ -87,7 +81,7 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_externally_owned_memory(Readonl
     FixedMemoryStream stream { buffer };
 
     auto tag = TRY(stream.read_value<Tag>());
-    if (tag == tag_from_str("ttcf")) {
+    if (tag == Tag("ttcf")) {
         // It's a font collection
         TRY(stream.seek(0, SeekMode::SetPosition));
         auto ttc_header_v1 = TRY(stream.read_in_place<TTCHeaderV1>());
@@ -100,10 +94,10 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_externally_owned_memory(Readonl
         auto offset = TRY(stream.read_value<BigEndian<u32>>());
         return try_load_from_offset(buffer, offset);
     }
-    if (tag == tag_from_str("OTTO"))
+    if (tag == Tag("OTTO"))
         return Error::from_string_literal("CFF fonts not supported yet");
 
-    if (tag != 0x00010000 && tag != tag_from_str("true"))
+    if (tag.to_u32() != 0x00010000 && tag != Tag("true"))
         return Error::from_string_literal("Not a valid font");
 
     return try_load_from_offset(buffer, 0);
@@ -145,35 +139,35 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_offset(ReadonlyBytes buffer, u3
         auto buffer_here = buffer.slice(table_record.offset, table_record.length);
 
         // Get the table offsets we need.
-        if (table_record.table_tag == tag_from_str("head")) {
+        if (table_record.table_tag == Tag("head")) {
             opt_head_slice = buffer_here;
-        } else if (table_record.table_tag == tag_from_str("name")) {
+        } else if (table_record.table_tag == Tag("name")) {
             opt_name_slice = buffer_here;
-        } else if (table_record.table_tag == tag_from_str("hhea")) {
+        } else if (table_record.table_tag == Tag("hhea")) {
             opt_hhea_slice = buffer_here;
-        } else if (table_record.table_tag == tag_from_str("maxp")) {
+        } else if (table_record.table_tag == Tag("maxp")) {
             opt_maxp_slice = buffer_here;
-        } else if (table_record.table_tag == tag_from_str("hmtx")) {
+        } else if (table_record.table_tag == Tag("hmtx")) {
             opt_hmtx_slice = buffer_here;
-        } else if (table_record.table_tag == tag_from_str("cmap")) {
+        } else if (table_record.table_tag == Tag("cmap")) {
             opt_cmap_slice = buffer_here;
-        } else if (table_record.table_tag == tag_from_str("loca")) {
+        } else if (table_record.table_tag == Tag("loca")) {
             opt_loca_slice = buffer_here;
-        } else if (table_record.table_tag == tag_from_str("glyf")) {
+        } else if (table_record.table_tag == Tag("glyf")) {
             opt_glyf_slice = buffer_here;
-        } else if (table_record.table_tag == tag_from_str("OS/2")) {
+        } else if (table_record.table_tag == Tag("OS/2")) {
             opt_os2_slice = buffer_here;
-        } else if (table_record.table_tag == tag_from_str("kern")) {
+        } else if (table_record.table_tag == Tag("kern")) {
             opt_kern_slice = buffer_here;
-        } else if (table_record.table_tag == tag_from_str("fpgm")) {
+        } else if (table_record.table_tag == Tag("fpgm")) {
             opt_fpgm_slice = buffer_here;
-        } else if (table_record.table_tag == tag_from_str("prep")) {
+        } else if (table_record.table_tag == Tag("prep")) {
             opt_prep_slice = buffer_here;
-        } else if (table_record.table_tag == tag_from_str("CBLC")) {
+        } else if (table_record.table_tag == Tag("CBLC")) {
             cblc = TRY(CBLC::from_slice(buffer_here));
-        } else if (table_record.table_tag == tag_from_str("CBDT")) {
+        } else if (table_record.table_tag == Tag("CBDT")) {
             cbdt = TRY(CBDT::from_slice(buffer_here));
-        } else if (table_record.table_tag == tag_from_str("GPOS")) {
+        } else if (table_record.table_tag == Tag("GPOS")) {
             gpos = TRY(GPOS::from_slice(buffer_here));
         }
     }

+ 1 - 11
Userland/Libraries/LibGfx/Font/OpenType/Tables.cpp

@@ -16,16 +16,6 @@
 
 namespace OpenType {
 
-static u32 be_u32(u8 const* ptr)
-{
-    return (((u32)ptr[0]) << 24) | (((u32)ptr[1]) << 16) | (((u32)ptr[2]) << 8) | ((u32)ptr[3]);
-}
-
-static u32 tag_from_str(char const* str)
-{
-    return be_u32((u8 const*)str);
-}
-
 ErrorOr<Head> Head::from_slice(ReadonlyBytes slice)
 {
     if (slice.size() < sizeof(FontHeaderTable))
@@ -576,7 +566,7 @@ Optional<i16> GPOS::glyph_kerning(u16 left_glyph_id, u16 right_glyph_id) const
 
     Optional<Offset16> kern_feature_offset;
     for (auto const& feature_record : m_feature_records) {
-        if (feature_record.feature_tag == tag_from_str("kern")) {
+        if (feature_record.feature_tag == Tag("kern")) {
             kern_feature_offset = feature_record.feature_offset;
             break;
         }

+ 1 - 1
Userland/Libraries/LibGfx/Font/WOFF/Font.cpp

@@ -36,7 +36,7 @@ static_assert(AssertSize<Header, 44>());
 
 // https://www.w3.org/TR/WOFF/#TableDirectory
 struct [[gnu::packed]] TableDirectoryEntry {
-    BigEndian<u32> tag;           // 4-byte sfnt table identifier.
+    OpenType::Tag tag;            // 4-byte sfnt table identifier.
     BigEndian<u32> offset;        // Offset to the data, from beginning of WOFF file.
     BigEndian<u32> comp_length;   // Length of the compressed data, excluding padding.
     BigEndian<u32> orig_length;   // Length of the uncompressed table, excluding padding.

+ 75 - 90
Userland/Libraries/LibGfx/Font/WOFF2/Font.cpp

@@ -125,19 +125,10 @@ enum class TransformationVersion {
 
 struct TableDirectoryEntry {
     TransformationVersion transformation_version { TransformationVersion::Version0 };
-    DeprecatedString tag;
+    OpenType::Tag tag;
     u32 original_length { 0 };
     Optional<u32> transform_length;
 
-    u32 tag_to_u32() const
-    {
-        VERIFY(tag.length() == 4);
-        return (static_cast<u8>(tag[0]) << 24)
-            | (static_cast<u8>(tag[1]) << 16)
-            | (static_cast<u8>(tag[2]) << 8)
-            | static_cast<u8>(tag[3]);
-    }
-
     bool has_transformation() const
     {
         return transform_length.has_value();
@@ -145,70 +136,70 @@ struct TableDirectoryEntry {
 };
 
 // NOTE: Any tags less than 4 characters long are padded with spaces at the end.
-static constexpr Array<StringView, 63> known_tag_names = {
-    "cmap"sv,
-    "head"sv,
-    "hhea"sv,
-    "hmtx"sv,
-    "maxp"sv,
-    "name"sv,
-    "OS/2"sv,
-    "post"sv,
-    "cvt "sv,
-    "fpgm"sv,
-    "glyf"sv,
-    "loca"sv,
-    "prep"sv,
-    "CFF "sv,
-    "VORG"sv,
-    "EBDT"sv,
-    "EBLC"sv,
-    "gasp"sv,
-    "hdmx"sv,
-    "kern"sv,
-    "LTSH"sv,
-    "PCLT"sv,
-    "VDMX"sv,
-    "vhea"sv,
-    "vmtx"sv,
-    "BASE"sv,
-    "GDEF"sv,
-    "GPOS"sv,
-    "GSUB"sv,
-    "EBSC"sv,
-    "JSTF"sv,
-    "MATH"sv,
-    "CBDT"sv,
-    "CBLC"sv,
-    "COLR"sv,
-    "CPAL"sv,
-    "SVG "sv,
-    "sbix"sv,
-    "acnt"sv,
-    "avar"sv,
-    "bdat"sv,
-    "bloc"sv,
-    "bsln"sv,
-    "cvar"sv,
-    "fdsc"sv,
-    "feat"sv,
-    "fmtx"sv,
-    "fvar"sv,
-    "gvar"sv,
-    "hsty"sv,
-    "just"sv,
-    "lcar"sv,
-    "mort"sv,
-    "morx"sv,
-    "opbd"sv,
-    "prop"sv,
-    "trak"sv,
-    "Zapf"sv,
-    "Silf"sv,
-    "Glat"sv,
-    "Gloc"sv,
-    "Feat"sv,
-    "Sill"sv,
+static constexpr Array<OpenType::Tag, 63> known_tag_names = {
+    OpenType::Tag("cmap"),
+    OpenType::Tag("head"),
+    OpenType::Tag("hhea"),
+    OpenType::Tag("hmtx"),
+    OpenType::Tag("maxp"),
+    OpenType::Tag("name"),
+    OpenType::Tag("OS/2"),
+    OpenType::Tag("post"),
+    OpenType::Tag("cvt "),
+    OpenType::Tag("fpgm"),
+    OpenType::Tag("glyf"),
+    OpenType::Tag("loca"),
+    OpenType::Tag("prep"),
+    OpenType::Tag("CFF "),
+    OpenType::Tag("VORG"),
+    OpenType::Tag("EBDT"),
+    OpenType::Tag("EBLC"),
+    OpenType::Tag("gasp"),
+    OpenType::Tag("hdmx"),
+    OpenType::Tag("kern"),
+    OpenType::Tag("LTSH"),
+    OpenType::Tag("PCLT"),
+    OpenType::Tag("VDMX"),
+    OpenType::Tag("vhea"),
+    OpenType::Tag("vmtx"),
+    OpenType::Tag("BASE"),
+    OpenType::Tag("GDEF"),
+    OpenType::Tag("GPOS"),
+    OpenType::Tag("GSUB"),
+    OpenType::Tag("EBSC"),
+    OpenType::Tag("JSTF"),
+    OpenType::Tag("MATH"),
+    OpenType::Tag("CBDT"),
+    OpenType::Tag("CBLC"),
+    OpenType::Tag("COLR"),
+    OpenType::Tag("CPAL"),
+    OpenType::Tag("SVG "),
+    OpenType::Tag("sbix"),
+    OpenType::Tag("acnt"),
+    OpenType::Tag("avar"),
+    OpenType::Tag("bdat"),
+    OpenType::Tag("bloc"),
+    OpenType::Tag("bsln"),
+    OpenType::Tag("cvar"),
+    OpenType::Tag("fdsc"),
+    OpenType::Tag("feat"),
+    OpenType::Tag("fmtx"),
+    OpenType::Tag("fvar"),
+    OpenType::Tag("gvar"),
+    OpenType::Tag("hsty"),
+    OpenType::Tag("just"),
+    OpenType::Tag("lcar"),
+    OpenType::Tag("mort"),
+    OpenType::Tag("morx"),
+    OpenType::Tag("opbd"),
+    OpenType::Tag("prop"),
+    OpenType::Tag("trak"),
+    OpenType::Tag("Zapf"),
+    OpenType::Tag("Silf"),
+    OpenType::Tag("Glat"),
+    OpenType::Tag("Gloc"),
+    OpenType::Tag("Feat"),
+    OpenType::Tag("Sill"),
 };
 
 struct CoordinateTripletEncoding {
@@ -916,16 +907,13 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_externally_owned_memory(Seekabl
         if (tag_number != 0x3F) {
             table_directory_entry.tag = known_tag_names[tag_number];
         } else {
-            u8 tag_buffer[5] {};
-            TRY(stream.read_until_filled(Bytes { tag_buffer, 4 }));
-            table_directory_entry.tag = StringView { tag_buffer, 4 };
+            table_directory_entry.tag = TRY(stream.read_value<OpenType::Tag>());
         }
 
-        VERIFY(table_directory_entry.tag.length() == 4);
         table_directory_entry.original_length = TRY(read_uint_base_128(stream));
 
         bool needs_to_read_transform_length = false;
-        if (table_directory_entry.tag.is_one_of("glyf"sv, "loca"sv))
+        if (table_directory_entry.tag == OpenType::Tag("glyf") || table_directory_entry.tag == OpenType::Tag("loca"))
             needs_to_read_transform_length = table_directory_entry.transformation_version == TransformationVersion::Version0;
         else
             needs_to_read_transform_length = table_directory_entry.transformation_version != TransformationVersion::Version0;
@@ -944,11 +932,11 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_externally_owned_memory(Seekabl
     // FIXME: Read in collection header and entries.
 
     auto glyf_table = table_entries.find_if([](TableDirectoryEntry const& entry) {
-        return entry.tag == "glyf"sv;
+        return entry.tag == OpenType::Tag("glyf");
     });
 
     auto loca_table = table_entries.find_if([](TableDirectoryEntry const& entry) {
-        return entry.tag == "loca"sv;
+        return entry.tag == OpenType::Tag("loca");
     });
 
     // "In other words, both glyf and loca tables must either be present in their transformed format or with null transform applied to both tables."
@@ -991,17 +979,15 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_externally_owned_memory(Seekabl
         size_t table_directory_offset = SFNT_HEADER_SIZE + table_entry_index * SFNT_TABLE_SIZE;
 
         if (table_entry.has_transformation()) {
-            if (table_entry.tag == "glyf"sv) {
+            if (table_entry.tag == OpenType::Tag("glyf")) {
                 auto table_stream = FixedMemoryStream(table_bytes);
                 glyf_and_loca_buffer = TRY(create_glyf_and_loca_tables_from_transformed_glyf_table(table_stream));
 
-                constexpr u32 GLYF_TAG = 0x676C7966;
-
                 if (font_buffer.size() < (font_buffer_offset + glyf_and_loca_buffer->glyf_table.size()))
                     TRY(font_buffer.try_resize(font_buffer_offset + glyf_and_loca_buffer->glyf_table.size()));
 
                 OpenType::TableRecord table_record {
-                    .table_tag = GLYF_TAG,
+                    .table_tag = table_entry.tag,
                     .checksum = 0, // FIXME: WOFF2 does not give us the original checksum.
                     .offset = font_buffer_offset,
                     .length = glyf_and_loca_buffer->glyf_table.size(),
@@ -1010,15 +996,14 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_externally_owned_memory(Seekabl
 
                 font_buffer.overwrite(font_buffer_offset, glyf_and_loca_buffer->glyf_table.data(), glyf_and_loca_buffer->glyf_table.size());
                 font_buffer_offset += glyf_and_loca_buffer->glyf_table.size();
-            } else if (table_entry.tag == "loca"sv) {
+            } else if (table_entry.tag == OpenType::Tag("loca")) {
                 // FIXME: Handle loca table coming before glyf table in input?
                 VERIFY(glyf_and_loca_buffer.has_value());
                 if (font_buffer.size() < (font_buffer_offset + glyf_and_loca_buffer->loca_table.size()))
                     TRY(font_buffer.try_resize(font_buffer_offset + glyf_and_loca_buffer->loca_table.size()));
-                constexpr u32 LOCA_TAG = 0x6C6F6361;
 
                 OpenType::TableRecord table_record {
-                    .table_tag = LOCA_TAG,
+                    .table_tag = table_entry.tag,
                     .checksum = 0, // FIXME: WOFF2 does not give us the original checksum.
                     .offset = font_buffer_offset,
                     .length = glyf_and_loca_buffer->loca_table.size(),
@@ -1027,14 +1012,14 @@ ErrorOr<NonnullRefPtr<Font>> Font::try_load_from_externally_owned_memory(Seekabl
 
                 font_buffer.overwrite(font_buffer_offset, glyf_and_loca_buffer->loca_table.data(), glyf_and_loca_buffer->loca_table.size());
                 font_buffer_offset += glyf_and_loca_buffer->loca_table.size();
-            } else if (table_entry.tag == "hmtx"sv) {
+            } else if (table_entry.tag == OpenType::Tag("hmtx")) {
                 return Error::from_string_literal("Decoding transformed hmtx table not yet supported");
             } else {
                 return Error::from_string_literal("Unknown transformation");
             }
         } else {
             OpenType::TableRecord table_record {
-                .table_tag = table_entry.tag_to_u32(),
+                .table_tag = table_entry.tag,
                 .checksum = 0, // FIXME: WOFF2 does not give us the original checksum.
                 .offset = font_buffer_offset,
                 .length = length_to_read,