Improve name table handling.

Robust reading of name tables.

Internally use sk_sp with LocalizedStrings. After landing, update the
public api as well.

Replace High/Low with Leading/Trailing surrogates in naming. This naming
is far easier to get right.

Change-Id: I542934ea8189ced1c2cbdd1539f9ebba562f0731
Reviewed-on: https://skia-review.googlesource.com/148123
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Ben Wagner <bungeman@google.com>
diff --git a/src/core/SkUtils.h b/src/core/SkUtils.h
index e18934d..cfbdaae 100644
--- a/src/core/SkUtils.h
+++ b/src/core/SkUtils.h
@@ -36,9 +36,9 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-static inline bool SkUTF16_IsHighSurrogate(uint16_t c) { return ((c) & 0xFC00) == 0xD800; }
+static inline bool SkUTF16_IsLeadingSurrogate(uint16_t c) { return ((c) & 0xFC00) == 0xD800; }
 
-static inline bool SkUTF16_IsLowSurrogate (uint16_t c) { return ((c) & 0xFC00) == 0xDC00; }
+static inline bool SkUTF16_IsTrailingSurrogate (uint16_t c) { return ((c) & 0xFC00) == 0xDC00; }
 
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp
index 53dc101..75099f4 100644
--- a/src/ports/SkFontHost_FreeType.cpp
+++ b/src/ports/SkFontHost_FreeType.cpp
@@ -1617,15 +1617,15 @@
 }
 
 SkTypeface::LocalizedStrings* SkTypeface_FreeType::onCreateFamilyNameIterator() const {
-    SkTypeface::LocalizedStrings* nameIter =
-        SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*this);
-    if (nullptr == nameIter) {
+    sk_sp<SkTypeface::LocalizedStrings> nameIter =
+        SkOTUtils::LocalizedStrings_NameTable::MakeForFamilyNames(*this);
+    if (!nameIter) {
         SkString familyName;
         this->getFamilyName(&familyName);
         SkString language("und"); //undetermined
-        nameIter = new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
+        nameIter = sk_make_sp<SkOTUtils::LocalizedStrings_SingleName>(familyName, language);
     }
-    return nameIter;
+    return nameIter.release();
 }
 
 int SkTypeface_FreeType::onGetVariationDesignPosition(
diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp
index 370adc1..85625ea 100644
--- a/src/ports/SkFontHost_mac.cpp
+++ b/src/ports/SkFontHost_mac.cpp
@@ -2166,9 +2166,9 @@
 }
 
 SkTypeface::LocalizedStrings* SkTypeface_Mac::onCreateFamilyNameIterator() const {
-    SkTypeface::LocalizedStrings* nameIter =
-            SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*this);
-    if (nullptr == nameIter) {
+    sk_sp<SkTypeface::LocalizedStrings> nameIter =
+            SkOTUtils::LocalizedStrings_NameTable::MakeForFamilyNames(*this);
+    if (!nameIter) {
         CFStringRef cfLanguageRaw;
         UniqueCFRef<CFStringRef> cfFamilyName(
                 CTFontCopyLocalizedName(fFontRef.get(), kCTFontFamilyNameKey, &cfLanguageRaw));
@@ -2185,9 +2185,9 @@
             CFStringToSkString(cfFamilyName.get(), &skFamilyName);
         }
 
-        nameIter = new SkOTUtils::LocalizedStrings_SingleName(skFamilyName, skLanguage);
+        nameIter = sk_make_sp<SkOTUtils::LocalizedStrings_SingleName>(skFamilyName, skLanguage);
     }
-    return nameIter;
+    return nameIter.release();
 }
 
 int SkTypeface_Mac::onGetTableTags(SkFontTableTag tags[]) const {
@@ -2377,7 +2377,7 @@
             src = reinterpret_cast<const UniChar*>(chars);
             int extra = 0;
             for (int i = 0; i < glyphCount; ++i) {
-                if (SkUTF16_IsHighSurrogate(src[i + extra])) {
+                if (SkUTF16_IsLeadingSurrogate(src[i + extra])) {
                     ++extra;
                 }
             }
@@ -2418,7 +2418,7 @@
         int extra = 0;
         for (int i = 0; i < glyphCount; ++i) {
             compactedGlyphs[i] = macGlyphs[i + extra];
-            if (SkUTF16_IsHighSurrogate(src[i + extra])) {
+            if (SkUTF16_IsLeadingSurrogate(src[i + extra])) {
                 ++extra;
             }
         }
diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp
index 380396b..3e18773 100644
--- a/src/ports/SkFontHost_win.cpp
+++ b/src/ports/SkFontHost_win.cpp
@@ -2122,7 +2122,7 @@
             // Try a run of bmp.
             int glyphsLeft = glyphCount - glyphIndex;
             int runLength = 0;
-            while (runLength < glyphsLeft && !SkUTF16_IsHighSurrogate(currentUtf16[runLength])) {
+            while (runLength < glyphsLeft && !SkUTF16_IsLeadingSurrogate(currentUtf16[runLength])) {
                 ++runLength;
             }
             if (runLength) {
@@ -2132,7 +2132,7 @@
             }
 
             // Try a run of non-bmp.
-            while (glyphIndex < glyphCount && SkUTF16_IsHighSurrogate(*currentUtf16)) {
+            while (glyphIndex < glyphCount && SkUTF16_IsLeadingSurrogate(*currentUtf16)) {
                 glyphs[glyphIndex] = nonBmpCharToGlyph(hdc, &sc, currentUtf16);
                 ++glyphIndex;
                 currentUtf16 += 2;
@@ -2212,15 +2212,15 @@
 }
 
 SkTypeface::LocalizedStrings* LogFontTypeface::onCreateFamilyNameIterator() const {
-    SkTypeface::LocalizedStrings* nameIter =
-        SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*this);
-    if (nullptr == nameIter) {
+    sk_sp<SkTypeface::LocalizedStrings> nameIter =
+        SkOTUtils::LocalizedStrings_NameTable::MakeForFamilyNames(*this);
+    if (!nameIter) {
         SkString familyName;
         this->getFamilyName(&familyName);
         SkString language("und"); //undetermined
-        nameIter = new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
+        nameIter = sk_make_sp<SkOTUtils::LocalizedStrings_SingleName>(familyName, language);
     }
-    return nameIter;
+    return nameIter.release();
 }
 
 int LogFontTypeface::onGetTableTags(SkFontTableTag tags[]) const {
diff --git a/src/ports/SkTypeface_win_dw.cpp b/src/ports/SkTypeface_win_dw.cpp
index e6a812f..dc2fc26 100644
--- a/src/ports/SkTypeface_win_dw.cpp
+++ b/src/ports/SkTypeface_win_dw.cpp
@@ -176,14 +176,14 @@
 };
 
 SkTypeface::LocalizedStrings* DWriteFontTypeface::onCreateFamilyNameIterator() const {
-    SkTypeface::LocalizedStrings* nameIter =
-        SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*this);
-    if (nullptr == nameIter) {
+    sk_sp<SkTypeface::LocalizedStrings> nameIter =
+        SkOTUtils::LocalizedStrings_NameTable::MakeForFamilyNames(*this);
+    if (!nameIter) {
         SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
         HRNM(fDWriteFontFamily->GetFamilyNames(&familyNames), "Could not obtain family names.");
-        nameIter = new LocalizedStrings_IDWriteLocalizedStrings(familyNames.release());
+        nameIter = sk_make_sp<LocalizedStrings_IDWriteLocalizedStrings>(familyNames.release());
     }
-    return nameIter;
+    return nameIter.release();
 }
 
 int DWriteFontTypeface::onGetVariationDesignPosition(
diff --git a/src/sfnt/SkOTTable_name.cpp b/src/sfnt/SkOTTable_name.cpp
index 05230f4..0a2f47b 100644
--- a/src/sfnt/SkOTTable_name.cpp
+++ b/src/sfnt/SkOTTable_name.cpp
@@ -13,39 +13,49 @@
 #include "SkTemplates.h"
 #include "SkUtils.h"
 
-static SkUnichar next_unichar_UTF16BE(const char** srcPtr) {
-    SkASSERT(srcPtr && *srcPtr);
+static SkUnichar next_unichar_UTF16BE(const uint8_t** srcPtr, size_t* length) {
+    SkASSERT(srcPtr && *srcPtr && length);
+    SkASSERT(*length > 0);
 
-    const char* src = *srcPtr;
-    uint16_t lo;
-    memcpy(&lo, src, 2);
-    src += 2;
+    uint16_t leading;
+    if (*length < sizeof(leading)) {
+        *length = 0;
+        return 0xFFFD;
+    }
+    memcpy(&leading, *srcPtr, sizeof(leading));
+    *srcPtr += sizeof(leading);
+    *length -= sizeof(leading);
+    SkUnichar c = SkEndian_SwapBE16(leading);
 
-    SkUnichar c = SkEndian_SwapBE16(lo);
-
-    SkASSERT(!SkUTF16_IsLowSurrogate(c));
-    if (SkUTF16_IsHighSurrogate(c)) {
-        uint16_t hi;
-        memcpy(&hi, src, 2);
-        src += 2;
-        unsigned c2 = SkEndian_SwapBE16(hi);
-        SkASSERT(SkUTF16_IsLowSurrogate(c2));
+    if (SkUTF16_IsTrailingSurrogate(c)) {
+        return 0xFFFD;
+    }
+    if (SkUTF16_IsLeadingSurrogate(c)) {
+        uint16_t trailing;
+        if (*length < sizeof(trailing)) {
+            *length = 0;
+            return 0xFFFD;
+        }
+        memcpy(&trailing, *srcPtr, sizeof(trailing));
+        SkUnichar c2 = SkEndian_SwapBE16(trailing);
+        if (!SkUTF16_IsTrailingSurrogate(c2)) {
+            return 0xFFFD;
+        }
+        *srcPtr += sizeof(trailing);
+        *length -= sizeof(trailing);
 
         c = (c << 10) + c2 + (0x10000 - (0xD800 << 10) - 0xDC00);
     }
-    *srcPtr = src;
     return c;
 }
 
-static void SkString_from_UTF16BE(const char* utf16be, size_t length, SkString& utf8) {
+static void SkString_from_UTF16BE(const uint8_t* utf16be, size_t length, SkString& utf8) {
     // Note that utf16be may not be 2-byte aligned.
     SkASSERT(utf16be != nullptr);
 
     utf8.reset();
-    size_t numberOf16BitValues = length / 2;
-    const char* end = utf16be + numberOf16BitValues*2;
-    while (utf16be < end) {
-        utf8.appendUnichar(next_unichar_UTF16BE(&utf16be));
+    while (length) {
+        utf8.appendUnichar(next_unichar_UTF16BE(&utf16be, &length));
     }
 }
 
@@ -446,40 +456,55 @@
 }
 
 bool SkOTTableName::Iterator::next(SkOTTableName::Iterator::Record& record) {
-    const size_t nameRecordsCount = SkEndian_SwapBE16(fName.count);
-    const SkOTTableName::Record* nameRecords = SkTAfter<const SkOTTableName::Record>(&fName);
-    const SkOTTableName::Record* nameRecord;
+    SkOTTableName nameTable;
+    if (fNameTableSize < sizeof(nameTable)) {
+        return false;
+    }
+    memcpy(&nameTable, fNameTable, sizeof(nameTable));
+
+    const uint8_t* nameRecords = fNameTable + sizeof(nameTable);
+    const size_t nameRecordsSize = fNameTableSize - sizeof(nameTable);
+
+    const size_t stringTableOffset = SkEndian_SwapBE16(nameTable.stringOffset);
+    if (fNameTableSize < stringTableOffset) {
+        return false;
+    }
+    const uint8_t* stringTable = fNameTable + stringTableOffset;
+    const size_t stringTableSize = fNameTableSize - stringTableOffset;
 
     // Find the next record which matches the requested type.
+    SkOTTableName::Record nameRecord;
+    const size_t nameRecordsCount = SkEndian_SwapBE16(nameTable.count);
+    const size_t nameRecordsMax = SkTMin(nameRecordsCount, nameRecordsSize / sizeof(nameRecord));
     do {
-        if (fIndex >= nameRecordsCount) {
+        if (fIndex >= nameRecordsMax) {
             return false;
         }
 
-        nameRecord = &nameRecords[fIndex];
+        memcpy(&nameRecord, nameRecords + sizeof(nameRecord)*fIndex, sizeof(nameRecord));
         ++fIndex;
-    } while (fType != -1 && nameRecord->nameID.fontSpecific != fType);
+    } while (fType != -1 && nameRecord.nameID.fontSpecific != fType);
 
-    record.type = nameRecord->nameID.fontSpecific;
-
-    const uint16_t stringTableOffset = SkEndian_SwapBE16(fName.stringOffset);
-    const char* stringTable = SkTAddOffset<const char>(&fName, stringTableOffset);
+    record.type = nameRecord.nameID.fontSpecific;
 
     // Decode the name into UTF-8.
-    const uint16_t nameOffset = SkEndian_SwapBE16(nameRecord->offset);
-    const uint16_t nameLength = SkEndian_SwapBE16(nameRecord->length);
-    const char* nameString = SkTAddOffset<const char>(stringTable, nameOffset);
-    switch (nameRecord->platformID.value) {
+    const size_t nameOffset = SkEndian_SwapBE16(nameRecord.offset);
+    const size_t nameLength = SkEndian_SwapBE16(nameRecord.length);
+    if (stringTableSize < nameOffset + nameLength) {
+        return false; // continue?
+    }
+    const uint8_t* nameString = stringTable + nameOffset;
+    switch (nameRecord.platformID.value) {
         case SkOTTableName::Record::PlatformID::Windows:
             if (SkOTTableName::Record::EncodingID::Windows::UnicodeBMPUCS2
-                   != nameRecord->encodingID.windows.value
+                   != nameRecord.encodingID.windows.value
                 && SkOTTableName::Record::EncodingID::Windows::UnicodeUCS4
-                   != nameRecord->encodingID.windows.value
+                   != nameRecord.encodingID.windows.value
                 && SkOTTableName::Record::EncodingID::Windows::Symbol
-                   != nameRecord->encodingID.windows.value)
+                   != nameRecord.encodingID.windows.value)
             {
                 record.name.reset();
-                break;
+                break; // continue?
             }
         case SkOTTableName::Record::PlatformID::Unicode:
         case SkOTTableName::Record::PlatformID::ISO:
@@ -489,12 +514,12 @@
         case SkOTTableName::Record::PlatformID::Macintosh:
             // TODO: need better decoding, especially on Mac.
             if (SkOTTableName::Record::EncodingID::Macintosh::Roman
-                != nameRecord->encodingID.macintosh.value)
+                != nameRecord.encodingID.macintosh.value)
             {
                 record.name.reset();
-                break;
+                break;  // continue?
             }
-            SkStringFromMacRoman((const uint8_t*)nameString, nameLength, record.name);
+            SkStringFromMacRoman(nameString, nameLength, record.name);
             break;
 
         case SkOTTableName::Record::PlatformID::Custom:
@@ -502,27 +527,46 @@
         default:
             SkASSERT(false);
             record.name.reset();
-            break;
+            break;  // continue?
     }
 
     // Determine the language.
-    const uint16_t languageID = SkEndian_SwapBE16(nameRecord->languageID.languageTagID);
+    const uint16_t languageID = SkEndian_SwapBE16(nameRecord.languageID.languageTagID);
 
     // Handle format 1 languages.
-    if (SkOTTableName::format_1 == fName.format && languageID >= 0x8000) {
+    if (SkOTTableName::format_1 == nameTable.format && languageID >= 0x8000) {
         const uint16_t languageTagRecordIndex = languageID - 0x8000;
 
-        const SkOTTableName::Format1Ext* format1ext =
-            SkTAfter<const SkOTTableName::Format1Ext>(nameRecords, nameRecordsCount);
+        if (nameRecordsSize < sizeof(nameRecord)*nameRecordsCount) {
+            return false; //"und" or break?
+        }
+        const uint8_t* format1extData = nameRecords + sizeof(nameRecord)*nameRecordsCount;
+        size_t format1extSize = nameRecordsSize - sizeof(nameRecord)*nameRecordsCount;
+        SkOTTableName::Format1Ext format1ext;
+        if (format1extSize < sizeof(format1ext)) {
+            return false; // "und" or break?
+        }
+        memcpy(&format1ext, format1extData, sizeof(format1ext));
 
-        if (languageTagRecordIndex < SkEndian_SwapBE16(format1ext->langTagCount)) {
-            const SkOTTableName::Format1Ext::LangTagRecord* languageTagRecord =
-                SkTAfter<const SkOTTableName::Format1Ext::LangTagRecord>(format1ext);
+        const uint8_t* languageTagRecords = format1extData + sizeof(format1ext);
+        size_t languageTagRecordsSize = format1extSize - sizeof(format1ext);
+        if (languageTagRecordIndex < SkEndian_SwapBE16(format1ext.langTagCount)) {
+            SkOTTableName::Format1Ext::LangTagRecord languageTagRecord;
+            if (languageTagRecordsSize < sizeof(languageTagRecord)*(languageTagRecordIndex+1)) {
+                return false; // "und"?
+            }
+            const uint8_t* languageTagData = languageTagRecords
+                                           + sizeof(languageTagRecord)*languageTagRecordIndex;
+            memcpy(&languageTagRecord, languageTagData, sizeof(languageTagRecord));
 
-            uint16_t offset = SkEndian_SwapBE16(languageTagRecord[languageTagRecordIndex].offset);
-            uint16_t length = SkEndian_SwapBE16(languageTagRecord[languageTagRecordIndex].length);
-            const char* string = SkTAddOffset<const char>(stringTable, offset);
-            SkString_from_UTF16BE(string, length, record.language);
+            uint16_t languageOffset = SkEndian_SwapBE16(languageTagRecord.offset);
+            uint16_t languageLength = SkEndian_SwapBE16(languageTagRecord.length);
+
+            if (fNameTableSize < stringTableOffset + languageOffset + languageLength) {
+                return false; // "und"?
+            }
+            const uint8_t* languageString = stringTable + languageOffset;
+            SkString_from_UTF16BE(languageString, languageLength, record.language);
             return true;
         }
     }
diff --git a/src/sfnt/SkOTTable_name.h b/src/sfnt/SkOTTable_name.h
index 4c1ce5b..6539d75 100644
--- a/src/sfnt/SkOTTable_name.h
+++ b/src/sfnt/SkOTTable_name.h
@@ -540,12 +540,13 @@
 
     class Iterator {
     public:
-        Iterator(const SkOTTableName& name) : fName(name), fIndex(0), fType(-1) { }
-        Iterator(const SkOTTableName& name, SkOTTableName::Record::NameID::Predefined::Value type)
-            : fName(name), fIndex(0), fType(type)
+        Iterator(const uint8_t* nameTable, size_t size)
+            : fNameTable(nameTable), fNameTableSize(size), fIndex(0), fType(-1) { }
+        Iterator(const uint8_t* nameTable, size_t size, SK_OT_USHORT type)
+            : fNameTable(nameTable), fNameTableSize(size), fIndex(0), fType(type)
         { }
 
-        void reset(SkOTTableName::Record::NameID::Predefined::Value type) {
+        void reset(SK_OT_USHORT type) {
             fIndex = 0;
             fType = type;
         }
@@ -558,7 +559,8 @@
         bool next(Record&);
 
     private:
-        const SkOTTableName& fName;
+        const uint8_t* fNameTable;
+        const size_t fNameTableSize;
         size_t fIndex;
         int fType;
     };
diff --git a/src/sfnt/SkOTUtils.cpp b/src/sfnt/SkOTUtils.cpp
index 1bd051c..1631a4d 100644
--- a/src/sfnt/SkOTUtils.cpp
+++ b/src/sfnt/SkOTUtils.cpp
@@ -163,9 +163,11 @@
     return rewrittenFontData.release();
 }
 
-
-SkOTUtils::LocalizedStrings_NameTable*
-SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(const SkTypeface& typeface) {
+sk_sp<SkOTUtils::LocalizedStrings_NameTable>
+SkOTUtils::LocalizedStrings_NameTable::Make(const SkTypeface& typeface,
+                                            SK_OT_USHORT types[],
+                                            int typesCount)
+{
     static const SkFontTableTag nameTag = SkSetFourByteTag('n','a','m','e');
     size_t nameTableSize = typeface.getTableSize(nameTag);
     if (0 == nameTableSize) {
@@ -177,9 +179,16 @@
         return nullptr;
     }
 
-    return new SkOTUtils::LocalizedStrings_NameTable((SkOTTableName*)nameTableData.release(),
-        SkOTUtils::LocalizedStrings_NameTable::familyNameTypes,
-        SK_ARRAY_COUNT(SkOTUtils::LocalizedStrings_NameTable::familyNameTypes));
+    return sk_sp<SkOTUtils::LocalizedStrings_NameTable>(
+        new SkOTUtils::LocalizedStrings_NameTable(std::move(nameTableData), nameTableSize,
+                                                  types, typesCount));
+}
+
+sk_sp<SkOTUtils::LocalizedStrings_NameTable>
+SkOTUtils::LocalizedStrings_NameTable::MakeForFamilyNames(const SkTypeface& typeface) {
+    return Make(typeface,
+                SkOTUtils::LocalizedStrings_NameTable::familyNameTypes,
+                SK_ARRAY_COUNT(SkOTUtils::LocalizedStrings_NameTable::familyNameTypes));
 }
 
 bool SkOTUtils::LocalizedStrings_NameTable::next(SkTypeface::LocalizedString* localizedString) {
@@ -198,8 +207,7 @@
     } while (true);
 }
 
-SkOTTableName::Record::NameID::Predefined::Value
-SkOTUtils::LocalizedStrings_NameTable::familyNameTypes[3] = {
+SK_OT_USHORT SkOTUtils::LocalizedStrings_NameTable::familyNameTypes[3] = {
     SkOTTableName::Record::NameID::Predefined::FontFamilyName,
     SkOTTableName::Record::NameID::Predefined::PreferredFamily,
     SkOTTableName::Record::NameID::Predefined::WWSFamilyName,
diff --git a/src/sfnt/SkOTUtils.h b/src/sfnt/SkOTUtils.h
index 64d3ae2..2f8fe0b 100644
--- a/src/sfnt/SkOTUtils.h
+++ b/src/sfnt/SkOTUtils.h
@@ -44,26 +44,35 @@
     class LocalizedStrings_NameTable : public SkTypeface::LocalizedStrings {
     public:
         /** Takes ownership of the nameTableData and will free it with SK_DELETE. */
-        LocalizedStrings_NameTable(SkOTTableName* nameTableData,
-                                   SkOTTableName::Record::NameID::Predefined::Value types[],
+        LocalizedStrings_NameTable(std::unique_ptr<uint8_t[]> nameTableData, size_t size,
+                                   SK_OT_USHORT types[],
                                    int typesCount)
             : fTypes(types), fTypesCount(typesCount), fTypesIndex(0)
-            , fNameTableData(nameTableData), fFamilyNameIter(*nameTableData, fTypes[fTypesIndex])
+            , fNameTableData(std::move(nameTableData))
+            , fFamilyNameIter(fNameTableData.get(), size, fTypes[fTypesIndex])
         { }
 
+        /** Creates an iterator over all data in the 'name' table of a typeface.
+         *  If no valid 'name' table can be found, returns nullptr.
+         */
+        static sk_sp<LocalizedStrings_NameTable> Make(
+            const SkTypeface& typeface,
+            SK_OT_USHORT types[],
+            int typesCount);
+
         /** Creates an iterator over all the family names in the 'name' table of a typeface.
          *  If no valid 'name' table can be found, returns nullptr.
          */
-        static LocalizedStrings_NameTable* CreateForFamilyNames(const SkTypeface& typeface);
+        static sk_sp<LocalizedStrings_NameTable> MakeForFamilyNames(const SkTypeface& typeface);
 
         bool next(SkTypeface::LocalizedString* localizedString) override;
     private:
-        static SkOTTableName::Record::NameID::Predefined::Value familyNameTypes[3];
+        static SK_OT_USHORT familyNameTypes[3];
 
-        SkOTTableName::Record::NameID::Predefined::Value* fTypes;
+        SK_OT_USHORT* fTypes;
         int fTypesCount;
         int fTypesIndex;
-        std::unique_ptr<SkOTTableName[]> fNameTableData;
+        std::unique_ptr<uint8_t[]> fNameTableData;
         SkOTTableName::Iterator fFamilyNameIter;
     };
 
diff --git a/src/utils/SkWhitelistTypefaces.cpp b/src/utils/SkWhitelistTypefaces.cpp
index f51a3b3..e02fd6b 100644
--- a/src/utils/SkWhitelistTypefaces.cpp
+++ b/src/utils/SkWhitelistTypefaces.cpp
@@ -40,8 +40,8 @@
 static int whitelist_name_index(const SkTypeface* tf) {
 
     SkString fontNameStr;
-    sk_sp<SkTypeface::LocalizedStrings> nameIter(
-        SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*tf));
+    sk_sp<SkTypeface::LocalizedStrings> nameIter =
+        SkOTUtils::LocalizedStrings_NameTable::MakeForFamilyNames(*tf);
     SkTypeface::LocalizedString familyNameLocalized;
     while (nameIter->next(&familyNameLocalized)) {
         fontNameStr = familyNameLocalized.fString;
@@ -53,8 +53,8 @@
         }
     }
 #if WHITELIST_DEBUG
-    sk_sp<SkTypeface::LocalizedStrings> debugIter(
-        SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*tf));
+    sk_sp<SkTypeface::LocalizedStrings> debugIter =
+        SkOTUtils::LocalizedStrings_NameTable::MakeForFamilyNames(*tf);
     while (debugIter->next(&familyNameLocalized)) {
         SkDebugf("no match fontName=\"%s\"\n", familyNameLocalized.fString.c_str());
     }
diff --git a/tests/FontNamesTest.cpp b/tests/FontNamesTest.cpp
index 3218b29..e3538dc 100644
--- a/tests/FontNamesTest.cpp
+++ b/tests/FontNamesTest.cpp
@@ -13,6 +13,8 @@
 
 #include <stddef.h>
 
+namespace {
+
 template <size_t R, size_t D> struct Format0NameTable {
     SkOTTableName header;
     SkOTTableName::Record nameRecord[R];
@@ -30,7 +32,7 @@
 };
 
 typedef Format0NameTable<1, 9> SimpleFormat0NameTable;
-SimpleFormat0NameTable simpleFormat0NameTable = {
+constexpr SimpleFormat0NameTable simpleFormat0NameTable = {
     /*header*/ {
         /*format*/ SkOTTableName::format_0,
         /*count*/ SkTEndianSwap16<1>::value,
@@ -50,7 +52,7 @@
 };
 
 typedef Format1NameTable<1, 1, 19> SimpleFormat1NameTable;
-SimpleFormat1NameTable simpleFormat1NameTable = {
+constexpr SimpleFormat1NameTable simpleFormat1NameTable = {
     /*header*/ {
         /*format*/ SkOTTableName::format_1,
         /*count*/ SkTEndianSwap16<1>::value,
@@ -82,7 +84,8 @@
 };
 
 struct FontNamesTest {
-    SkOTTableName* data;
+    const uint8_t* data;
+    size_t size;
     SkOTTableName::Record::NameID nameID;
     size_t nameCount;
     struct {
@@ -90,9 +93,10 @@
         const char* language;
     } names[10];
 
-} test[] = {
+} tests[] = {
     {
-        (SkOTTableName*)&simpleFormat0NameTable,
+        reinterpret_cast<const uint8_t*>(&simpleFormat0NameTable),
+        sizeof(simpleFormat0NameTable),
         { SkOTTableName::Record::NameID::Predefined::FontFamilyName },
         1,
         {
@@ -100,7 +104,8 @@
         },
     },
     {
-        (SkOTTableName*)&simpleFormat1NameTable,
+        reinterpret_cast<const uint8_t*>(&simpleFormat1NameTable),
+        sizeof(simpleFormat1NameTable),
         { SkOTTableName::Record::NameID::Predefined::FontFamilyName },
         1,
         {
@@ -110,25 +115,27 @@
 };
 
 static void test_synthetic(skiatest::Reporter* reporter, bool verbose) {
-    for (size_t i = 0; i < SK_ARRAY_COUNT(test); ++i) {
-        SkOTTableName::Iterator iter(*test[i].data, test[i].nameID.predefined.value);
+    for (const auto& test : tests) {
+        SkOTTableName::Iterator iter(test.data, test.size, test.nameID.predefined.value);
         SkOTTableName::Iterator::Record record;
         size_t nameIndex = 0;
-        while (nameIndex < test[i].nameCount && iter.next(record)) {
+        while (nameIndex < test.nameCount && iter.next(record)) {
             REPORTER_ASSERT(reporter,
-                            strcmp(test[i].names[nameIndex].name, record.name.c_str()) == 0,
+                            strcmp(test.names[nameIndex].name, record.name.c_str()) == 0,
                             "Name did not match.");
 
             REPORTER_ASSERT(reporter,
-                            strcmp(test[i].names[nameIndex].language, record.language.c_str()) == 0,
+                            strcmp(test.names[nameIndex].language, record.language.c_str()) == 0,
                             "Language did not match.");
 
-            //printf("%s <%s>\n", record.name.c_str(), record.language.c_str());
+            if (verbose) {
+                SkDebugf("%s <%s>\n", record.name.c_str(), record.language.c_str());
+            }
 
             ++nameIndex;
         }
 
-        REPORTER_ASSERT(reporter, nameIndex == test[i].nameCount, "Fewer names than expected.");
+        REPORTER_ASSERT(reporter, nameIndex == test.nameCount, "Fewer names than expected.");
 
         REPORTER_ASSERT(reporter, !iter.next(record), "More names than expected.");
     }
@@ -176,7 +183,7 @@
             }
 
             SkOTTableName::Iterator::Record record;
-            SkOTTableName::Iterator familyNameIter(*((SkOTTableName*)nameTableData.get()),
+            SkOTTableName::Iterator familyNameIter(nameTableData.get(), nameTableSize,
                 SkOTTableName::Record::NameID::Predefined::FontFamilyName);
             while (familyNameIter.next(record)) {
                 REPORTER_ASSERT(
@@ -188,7 +195,7 @@
                 }
             }
 
-            SkOTTableName::Iterator styleNameIter(*((SkOTTableName*)nameTableData.get()),
+            SkOTTableName::Iterator styleNameIter(nameTableData.get(), nameTableSize,
                 SkOTTableName::Record::NameID::Predefined::FontSubfamilyName);
             while (styleNameIter.next(record)) {
                 REPORTER_ASSERT(
@@ -207,6 +214,8 @@
     }
 }
 
+} // namespace
+
 DEFINE_bool(verboseFontNames, false, "verbose FontNames test.");
 
 DEF_TEST(FontNames, reporter) {