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