180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2012 Google Inc.
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkData.h"
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkEndian.h"
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkSFNTHeader.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkStream.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkOTTable_head.h"
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkOTTable_name.h"
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkOTTableTypes.h"
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkOTUtils.h"
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenbergerextern const uint8_t SK_OT_GlyphData_NoOutline[] = {
18363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    0x0,0x0, //SkOTTableGlyphData::numberOfContours
19363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    0x0,0x0, //SkOTTableGlyphData::xMin
20363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    0x0,0x0, //SkOTTableGlyphData::yMin
21363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    0x0,0x0, //SkOTTableGlyphData::xMax
22363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    0x0,0x0, //SkOTTableGlyphData::yMax
23363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
24363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    0x0,0x0, //SkOTTableGlyphDataInstructions::length
25363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger};
26363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruuint32_t SkOTUtils::CalcTableChecksum(SK_OT_ULONG *data, size_t length) {
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    uint32_t sum = 0;
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_OT_ULONG *dataEnd = data + ((length + 3) & ~3) / sizeof(SK_OT_ULONG);
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (; data < dataEnd; ++data) {
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        sum += SkEndian_SwapBE32(*data);
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return sum;
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
36363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek SollenbergerSkData* SkOTUtils::RenameFont(SkStream* fontData, const char* fontName, int fontNameLen) {
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Get the sfnt header.
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkSFNTHeader sfntHeader;
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fontData->read(&sfntHeader, sizeof(sfntHeader)) < sizeof(sfntHeader)) {
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return NULL;
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Find the existing 'name' table.
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int tableIndex;
46363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkSFNTHeader::TableDirectoryEntry tableEntry;
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int numTables = SkEndian_SwapBE16(sfntHeader.numTables);
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (tableIndex = 0; tableIndex < numTables; ++tableIndex) {
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (fontData->read(&tableEntry, sizeof(tableEntry)) < sizeof(tableEntry)) {
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return NULL;
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (SkOTTableName::TAG == tableEntry.tag) {
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            break;
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (tableIndex == numTables) {
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return NULL;
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (!fontData->rewind()) {
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return NULL;
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // The required 'name' record types: Family, Style, Unique, Full and PostScript.
657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    const SkOTTableName::Record::NameID::Predefined::Value namesToCreate[] = {
667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        SkOTTableName::Record::NameID::Predefined::FontFamilyName,
677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        SkOTTableName::Record::NameID::Predefined::FontSubfamilyName,
687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        SkOTTableName::Record::NameID::Predefined::UniqueFontIdentifier,
697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        SkOTTableName::Record::NameID::Predefined::FullFontName,
707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        SkOTTableName::Record::NameID::Predefined::PostscriptName,
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    };
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const int namesCount = SK_ARRAY_COUNT(namesToCreate);
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Copy the data, leaving out the old name table.
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // In theory, we could also remove the DSIG table if it exists.
767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    size_t nameTableLogicalSize = sizeof(SkOTTableName) + (namesCount * sizeof(SkOTTableName::Record)) + (fontNameLen * sizeof(wchar_t));
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t nameTablePhysicalSize = (nameTableLogicalSize + 3) & ~3; // Rounded up to a multiple of 4.
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t oldNameTablePhysicalSize = (SkEndian_SwapBE32(tableEntry.logicalLength) + 3) & ~3; // Rounded up to a multiple of 4.
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t oldNameTableOffset = SkEndian_SwapBE32(tableEntry.offset);
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //originalDataSize is the size of the original data without the name table.
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t originalDataSize = fontData->getLength() - oldNameTablePhysicalSize;
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    size_t newDataSize = originalDataSize + nameTablePhysicalSize;
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_OT_BYTE* data = static_cast<SK_OT_BYTE*>(sk_malloc_throw(newDataSize));
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkAutoTUnref<SkData> rewrittenFontData(SkData::NewFromMalloc(data, newDataSize));
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fontData->read(data, oldNameTableOffset) < oldNameTableOffset) {
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return NULL;
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fontData->skip(oldNameTablePhysicalSize) < oldNameTablePhysicalSize) {
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return NULL;
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (fontData->read(data + oldNameTableOffset, originalDataSize - oldNameTableOffset) < originalDataSize - oldNameTableOffset) {
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return NULL;
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    //Fix up the offsets of the directory entries after the old 'name' table entry.
100363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkSFNTHeader::TableDirectoryEntry* currentEntry = reinterpret_cast<SkSFNTHeader::TableDirectoryEntry*>(data + sizeof(SkSFNTHeader));
101363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkSFNTHeader::TableDirectoryEntry* endEntry = currentEntry + numTables;
102363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkSFNTHeader::TableDirectoryEntry* headTableEntry = NULL;
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (; currentEntry < endEntry; ++currentEntry) {
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        uint32_t oldOffset = SkEndian_SwapBE32(currentEntry->offset);
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (oldOffset > oldNameTableOffset) {
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            currentEntry->offset = SkEndian_SwapBE32(oldOffset - oldNameTablePhysicalSize);
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
108363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger        if (SkOTTableHead::TAG == currentEntry->tag) {
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            headTableEntry = currentEntry;
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Make the table directory entry point to the new 'name' table.
114363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger    SkSFNTHeader::TableDirectoryEntry* nameTableEntry = reinterpret_cast<SkSFNTHeader::TableDirectoryEntry*>(data + sizeof(SkSFNTHeader)) + tableIndex;
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    nameTableEntry->logicalLength = SkEndian_SwapBE32(nameTableLogicalSize);
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    nameTableEntry->offset = SkEndian_SwapBE32(originalDataSize);
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Write the new 'name' table after the original font data.
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkOTTableName* nameTable = reinterpret_cast<SkOTTableName*>(data + originalDataSize);
1207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    unsigned short stringOffset = sizeof(SkOTTableName) + (namesCount * sizeof(SkOTTableName::Record));
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    nameTable->format = SkOTTableName::format_0;
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    nameTable->count = SkEndian_SwapBE16(namesCount);
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    nameTable->stringOffset = SkEndian_SwapBE16(stringOffset);
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkOTTableName::Record* nameRecords = reinterpret_cast<SkOTTableName::Record*>(data + originalDataSize + sizeof(SkOTTableName));
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < namesCount; ++i) {
1277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        nameRecords[i].platformID.value = SkOTTableName::Record::PlatformID::Windows;
1287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        nameRecords[i].encodingID.windows.value = SkOTTableName::Record::EncodingID::Windows::UnicodeBMPUCS2;
1297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        nameRecords[i].languageID.windows.value = SkOTTableName::Record::LanguageID::Windows::English_UnitedStates;
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        nameRecords[i].nameID.predefined.value = namesToCreate[i];
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        nameRecords[i].offset = SkEndian_SwapBE16(0);
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        nameRecords[i].length = SkEndian_SwapBE16(fontNameLen * sizeof(wchar_t));
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_OT_USHORT* nameString = reinterpret_cast<SK_OT_USHORT*>(data + originalDataSize + stringOffset);
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (int i = 0; i < fontNameLen; ++i) {
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        nameString[i] = SkEndian_SwapBE16(fontName[i]);
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned char* logical = data + originalDataSize + nameTableLogicalSize;
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned char* physical = data + originalDataSize + nameTablePhysicalSize;
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    for (; logical < physical; ++logical) {
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        *logical = 0;
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Update the table checksum in the directory entry.
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    nameTableEntry->checksum = SkEndian_SwapBE32(SkOTUtils::CalcTableChecksum(reinterpret_cast<SK_OT_ULONG*>(nameTable), nameTableLogicalSize));
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Update the checksum adjustment in the head table.
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (headTableEntry) {
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        size_t headTableOffset = SkEndian_SwapBE32(headTableEntry->offset);
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (headTableOffset + sizeof(SkOTTableHead) < originalDataSize) {
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkOTTableHead* headTable = reinterpret_cast<SkOTTableHead*>(data + headTableOffset);
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            headTable->checksumAdjustment = SkEndian_SwapBE32(0);
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            uint32_t unadjustedFontChecksum = SkOTUtils::CalcTableChecksum(reinterpret_cast<SK_OT_ULONG*>(data), originalDataSize + nameTablePhysicalSize);
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            headTable->checksumAdjustment = SkEndian_SwapBE32(SkOTTableHead::fontChecksum - unadjustedFontChecksum);
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return rewrittenFontData.detach();
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
162e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
163e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
164e27eefc4844477cee5d32f51ab45ff62020cdb36Derek SollenbergerSkOTUtils::LocalizedStrings_NameTable*
165e27eefc4844477cee5d32f51ab45ff62020cdb36Derek SollenbergerSkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(const SkTypeface& typeface) {
166e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    static const SkFontTableTag nameTag = SkSetFourByteTag('n','a','m','e');
167e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    size_t nameTableSize = typeface.getTableSize(nameTag);
168e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    if (0 == nameTableSize) {
169e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        return NULL;
170e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
171e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkAutoTDeleteArray<uint8_t> nameTableData(new uint8_t[nameTableSize]);
172e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    size_t copied = typeface.getTableData(nameTag, 0, nameTableSize, nameTableData.get());
173e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    if (copied != nameTableSize) {
174e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        return NULL;
175e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    }
176e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
177e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    return new SkOTUtils::LocalizedStrings_NameTable((SkOTTableName*)nameTableData.detach(),
178e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        SkOTUtils::LocalizedStrings_NameTable::familyNameTypes,
179e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        SK_ARRAY_COUNT(SkOTUtils::LocalizedStrings_NameTable::familyNameTypes));
180e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger}
181e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
182e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenbergerbool SkOTUtils::LocalizedStrings_NameTable::next(SkTypeface::LocalizedString* localizedString) {
183e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    do {
184e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        SkOTTableName::Iterator::Record record;
185e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        if (fFamilyNameIter.next(record)) {
186e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            localizedString->fString = record.name;
187e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            localizedString->fLanguage = record.language;
188e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            return true;
189e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        }
190e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        if (fTypesCount == fTypesIndex + 1) {
191e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger            return false;
192e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        }
193e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        ++fTypesIndex;
194e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        fFamilyNameIter.reset(fTypes[fTypesIndex]);
195e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    } while (true);
196e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger}
197e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger
198e27eefc4844477cee5d32f51ab45ff62020cdb36Derek SollenbergerSkOTTableName::Record::NameID::Predefined::Value
199e27eefc4844477cee5d32f51ab45ff62020cdb36Derek SollenbergerSkOTUtils::LocalizedStrings_NameTable::familyNameTypes[3] = {
200e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkOTTableName::Record::NameID::Predefined::FontFamilyName,
201e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkOTTableName::Record::NameID::Predefined::PreferredFamily,
202e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger    SkOTTableName::Record::NameID::Predefined::WWSFamilyName,
203e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger};
204