1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2012 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include <array> 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "src/sfnt/SkOTUtils.h" 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_ci#include "include/core/SkData.h" 13cb93a386Sopenharmony_ci#include "include/core/SkStream.h" 14cb93a386Sopenharmony_ci#include "include/private/SkTo.h" 15cb93a386Sopenharmony_ci#include "src/core/SkAdvancedTypefaceMetrics.h" 16cb93a386Sopenharmony_ci#include "src/core/SkEndian.h" 17cb93a386Sopenharmony_ci#include "src/sfnt/SkOTTableTypes.h" 18cb93a386Sopenharmony_ci#include "src/sfnt/SkOTTable_head.h" 19cb93a386Sopenharmony_ci#include "src/sfnt/SkOTTable_name.h" 20cb93a386Sopenharmony_ci#include "src/sfnt/SkSFNTHeader.h" 21cb93a386Sopenharmony_ci 22cb93a386Sopenharmony_ciextern const uint8_t SK_OT_GlyphData_NoOutline[] = { 23cb93a386Sopenharmony_ci 0x0,0x0, //SkOTTableGlyphData::numberOfContours 24cb93a386Sopenharmony_ci 0x0,0x0, //SkOTTableGlyphData::xMin 25cb93a386Sopenharmony_ci 0x0,0x0, //SkOTTableGlyphData::yMin 26cb93a386Sopenharmony_ci 0x0,0x0, //SkOTTableGlyphData::xMax 27cb93a386Sopenharmony_ci 0x0,0x0, //SkOTTableGlyphData::yMax 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_ci 0x0,0x0, //SkOTTableGlyphDataInstructions::length 30cb93a386Sopenharmony_ci}; 31cb93a386Sopenharmony_ci 32cb93a386Sopenharmony_ciuint32_t SkOTUtils::CalcTableChecksum(SK_OT_ULONG *data, size_t length) { 33cb93a386Sopenharmony_ci uint32_t sum = 0; 34cb93a386Sopenharmony_ci SK_OT_ULONG *dataEnd = data + ((length + 3) & ~3) / sizeof(SK_OT_ULONG); 35cb93a386Sopenharmony_ci for (; data < dataEnd; ++data) { 36cb93a386Sopenharmony_ci sum += SkEndian_SwapBE32(*data); 37cb93a386Sopenharmony_ci } 38cb93a386Sopenharmony_ci return sum; 39cb93a386Sopenharmony_ci} 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_ciSkData* SkOTUtils::RenameFont(SkStreamAsset* fontData, const char* fontName, int fontNameLen) { 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_ci // Get the sfnt header. 44cb93a386Sopenharmony_ci SkSFNTHeader sfntHeader; 45cb93a386Sopenharmony_ci if (fontData->read(&sfntHeader, sizeof(sfntHeader)) < sizeof(sfntHeader)) { 46cb93a386Sopenharmony_ci return nullptr; 47cb93a386Sopenharmony_ci } 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_ci // Find the existing 'name' table. 50cb93a386Sopenharmony_ci int tableIndex; 51cb93a386Sopenharmony_ci SkSFNTHeader::TableDirectoryEntry tableEntry; 52cb93a386Sopenharmony_ci int numTables = SkEndian_SwapBE16(sfntHeader.numTables); 53cb93a386Sopenharmony_ci for (tableIndex = 0; tableIndex < numTables; ++tableIndex) { 54cb93a386Sopenharmony_ci if (fontData->read(&tableEntry, sizeof(tableEntry)) < sizeof(tableEntry)) { 55cb93a386Sopenharmony_ci return nullptr; 56cb93a386Sopenharmony_ci } 57cb93a386Sopenharmony_ci if (SkOTTableName::TAG == tableEntry.tag) { 58cb93a386Sopenharmony_ci break; 59cb93a386Sopenharmony_ci } 60cb93a386Sopenharmony_ci } 61cb93a386Sopenharmony_ci if (tableIndex == numTables) { 62cb93a386Sopenharmony_ci return nullptr; 63cb93a386Sopenharmony_ci } 64cb93a386Sopenharmony_ci 65cb93a386Sopenharmony_ci if (!fontData->rewind()) { 66cb93a386Sopenharmony_ci return nullptr; 67cb93a386Sopenharmony_ci } 68cb93a386Sopenharmony_ci 69cb93a386Sopenharmony_ci // The required 'name' record types: Family, Style, Unique, Full and PostScript. 70cb93a386Sopenharmony_ci static constexpr std::array<SkOTTableName::Record::NameID::Predefined::Value, 5> names{{ 71cb93a386Sopenharmony_ci SkOTTableName::Record::NameID::Predefined::FontFamilyName, 72cb93a386Sopenharmony_ci SkOTTableName::Record::NameID::Predefined::FontSubfamilyName, 73cb93a386Sopenharmony_ci SkOTTableName::Record::NameID::Predefined::UniqueFontIdentifier, 74cb93a386Sopenharmony_ci SkOTTableName::Record::NameID::Predefined::FullFontName, 75cb93a386Sopenharmony_ci SkOTTableName::Record::NameID::Predefined::PostscriptName, 76cb93a386Sopenharmony_ci }}; 77cb93a386Sopenharmony_ci 78cb93a386Sopenharmony_ci // GDI will not use a Symbol cmap table if there is no Symbol encoded name. 79cb93a386Sopenharmony_ci static constexpr std::array<SkOTTableName::Record::EncodingID::Windows::Value, 2> encodings{{ 80cb93a386Sopenharmony_ci SkOTTableName::Record::EncodingID::Windows::Symbol, 81cb93a386Sopenharmony_ci SkOTTableName::Record::EncodingID::Windows::UnicodeBMPUCS2, 82cb93a386Sopenharmony_ci }}; 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_ci // Copy the data, leaving out the old name table. 85cb93a386Sopenharmony_ci // In theory, we could also remove the DSIG table if it exists. 86cb93a386Sopenharmony_ci size_t nameTableLogicalSize = sizeof(SkOTTableName) 87cb93a386Sopenharmony_ci + (encodings.size() * names.size() * sizeof(SkOTTableName::Record)) 88cb93a386Sopenharmony_ci + (fontNameLen * sizeof(SK_OT_USHORT)); 89cb93a386Sopenharmony_ci size_t nameTablePhysicalSize = (nameTableLogicalSize + 3) & ~3; // Rounded up to a multiple of 4. 90cb93a386Sopenharmony_ci 91cb93a386Sopenharmony_ci size_t oldNameTablePhysicalSize = (SkEndian_SwapBE32(tableEntry.logicalLength) + 3) & ~3; // Rounded up to a multiple of 4. 92cb93a386Sopenharmony_ci size_t oldNameTableOffset = SkEndian_SwapBE32(tableEntry.offset); 93cb93a386Sopenharmony_ci 94cb93a386Sopenharmony_ci //originalDataSize is the size of the original data without the name table. 95cb93a386Sopenharmony_ci size_t originalDataSize = fontData->getLength() - oldNameTablePhysicalSize; 96cb93a386Sopenharmony_ci size_t newDataSize = originalDataSize + nameTablePhysicalSize; 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_ci auto rewrittenFontData = SkData::MakeUninitialized(newDataSize); 99cb93a386Sopenharmony_ci SK_OT_BYTE* data = static_cast<SK_OT_BYTE*>(rewrittenFontData->writable_data()); 100cb93a386Sopenharmony_ci 101cb93a386Sopenharmony_ci if (fontData->read(data, oldNameTableOffset) < oldNameTableOffset) { 102cb93a386Sopenharmony_ci return nullptr; 103cb93a386Sopenharmony_ci } 104cb93a386Sopenharmony_ci if (fontData->skip(oldNameTablePhysicalSize) < oldNameTablePhysicalSize) { 105cb93a386Sopenharmony_ci return nullptr; 106cb93a386Sopenharmony_ci } 107cb93a386Sopenharmony_ci if (fontData->read(data + oldNameTableOffset, originalDataSize - oldNameTableOffset) < originalDataSize - oldNameTableOffset) { 108cb93a386Sopenharmony_ci return nullptr; 109cb93a386Sopenharmony_ci } 110cb93a386Sopenharmony_ci 111cb93a386Sopenharmony_ci //Fix up the offsets of the directory entries after the old 'name' table entry. 112cb93a386Sopenharmony_ci SkSFNTHeader::TableDirectoryEntry* currentEntry = reinterpret_cast<SkSFNTHeader::TableDirectoryEntry*>(data + sizeof(SkSFNTHeader)); 113cb93a386Sopenharmony_ci SkSFNTHeader::TableDirectoryEntry* endEntry = currentEntry + numTables; 114cb93a386Sopenharmony_ci SkSFNTHeader::TableDirectoryEntry* headTableEntry = nullptr; 115cb93a386Sopenharmony_ci for (; currentEntry < endEntry; ++currentEntry) { 116cb93a386Sopenharmony_ci uint32_t oldOffset = SkEndian_SwapBE32(currentEntry->offset); 117cb93a386Sopenharmony_ci if (oldOffset > oldNameTableOffset) { 118cb93a386Sopenharmony_ci currentEntry->offset = SkEndian_SwapBE32(SkToU32(oldOffset - oldNameTablePhysicalSize)); 119cb93a386Sopenharmony_ci } 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_ci if (SkOTTableHead::TAG == currentEntry->tag) { 122cb93a386Sopenharmony_ci headTableEntry = currentEntry; 123cb93a386Sopenharmony_ci } 124cb93a386Sopenharmony_ci } 125cb93a386Sopenharmony_ci 126cb93a386Sopenharmony_ci // Make the table directory entry point to the new 'name' table. 127cb93a386Sopenharmony_ci SkSFNTHeader::TableDirectoryEntry* nameTableEntry = reinterpret_cast<SkSFNTHeader::TableDirectoryEntry*>(data + sizeof(SkSFNTHeader)) + tableIndex; 128cb93a386Sopenharmony_ci nameTableEntry->logicalLength = SkEndian_SwapBE32(SkToU32(nameTableLogicalSize)); 129cb93a386Sopenharmony_ci nameTableEntry->offset = SkEndian_SwapBE32(SkToU32(originalDataSize)); 130cb93a386Sopenharmony_ci 131cb93a386Sopenharmony_ci // Write the new 'name' table after the original font data. 132cb93a386Sopenharmony_ci SkOTTableName* nameTable = reinterpret_cast<SkOTTableName*>(data + originalDataSize); 133cb93a386Sopenharmony_ci unsigned short stringOffset = sizeof(SkOTTableName) + (encodings.size() * names.size() * sizeof(SkOTTableName::Record)); 134cb93a386Sopenharmony_ci nameTable->format = SkOTTableName::format_0; 135cb93a386Sopenharmony_ci nameTable->count = SkEndian_SwapBE16(encodings.size() * names.size()); 136cb93a386Sopenharmony_ci nameTable->stringOffset = SkEndian_SwapBE16(stringOffset); 137cb93a386Sopenharmony_ci 138cb93a386Sopenharmony_ci SkOTTableName::Record* nameRecord = reinterpret_cast<SkOTTableName::Record*>(data + originalDataSize + sizeof(SkOTTableName)); 139cb93a386Sopenharmony_ci for (const auto& encoding : encodings) { 140cb93a386Sopenharmony_ci for (const auto& name : names) { 141cb93a386Sopenharmony_ci nameRecord->platformID.value = SkOTTableName::Record::PlatformID::Windows; 142cb93a386Sopenharmony_ci nameRecord->encodingID.windows.value = encoding; 143cb93a386Sopenharmony_ci nameRecord->languageID.windows.value = SkOTTableName::Record::LanguageID::Windows::English_UnitedStates; 144cb93a386Sopenharmony_ci nameRecord->nameID.predefined.value = name; 145cb93a386Sopenharmony_ci nameRecord->offset = SkEndian_SwapBE16(0); 146cb93a386Sopenharmony_ci nameRecord->length = SkEndian_SwapBE16(SkToU16(fontNameLen * sizeof(SK_OT_USHORT))); 147cb93a386Sopenharmony_ci ++nameRecord; 148cb93a386Sopenharmony_ci } 149cb93a386Sopenharmony_ci } 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_ci SK_OT_USHORT* nameString = reinterpret_cast<SK_OT_USHORT*>(data + originalDataSize + stringOffset); 152cb93a386Sopenharmony_ci for (int i = 0; i < fontNameLen; ++i) { 153cb93a386Sopenharmony_ci nameString[i] = SkEndian_SwapBE16(fontName[i]); 154cb93a386Sopenharmony_ci } 155cb93a386Sopenharmony_ci 156cb93a386Sopenharmony_ci unsigned char* logical = data + originalDataSize + nameTableLogicalSize; 157cb93a386Sopenharmony_ci unsigned char* physical = data + originalDataSize + nameTablePhysicalSize; 158cb93a386Sopenharmony_ci for (; logical < physical; ++logical) { 159cb93a386Sopenharmony_ci *logical = 0; 160cb93a386Sopenharmony_ci } 161cb93a386Sopenharmony_ci 162cb93a386Sopenharmony_ci // Update the table checksum in the directory entry. 163cb93a386Sopenharmony_ci nameTableEntry->checksum = SkEndian_SwapBE32(SkOTUtils::CalcTableChecksum(reinterpret_cast<SK_OT_ULONG*>(nameTable), nameTableLogicalSize)); 164cb93a386Sopenharmony_ci 165cb93a386Sopenharmony_ci // Update the checksum adjustment in the head table. 166cb93a386Sopenharmony_ci if (headTableEntry) { 167cb93a386Sopenharmony_ci size_t headTableOffset = SkEndian_SwapBE32(headTableEntry->offset); 168cb93a386Sopenharmony_ci if (headTableOffset + sizeof(SkOTTableHead) < originalDataSize) { 169cb93a386Sopenharmony_ci SkOTTableHead* headTable = reinterpret_cast<SkOTTableHead*>(data + headTableOffset); 170cb93a386Sopenharmony_ci headTable->checksumAdjustment = SkEndian_SwapBE32(0); 171cb93a386Sopenharmony_ci uint32_t unadjustedFontChecksum = SkOTUtils::CalcTableChecksum(reinterpret_cast<SK_OT_ULONG*>(data), originalDataSize + nameTablePhysicalSize); 172cb93a386Sopenharmony_ci headTable->checksumAdjustment = SkEndian_SwapBE32(SkOTTableHead::fontChecksum - unadjustedFontChecksum); 173cb93a386Sopenharmony_ci } 174cb93a386Sopenharmony_ci } 175cb93a386Sopenharmony_ci 176cb93a386Sopenharmony_ci return rewrittenFontData.release(); 177cb93a386Sopenharmony_ci} 178cb93a386Sopenharmony_ci 179cb93a386Sopenharmony_cisk_sp<SkOTUtils::LocalizedStrings_NameTable> 180cb93a386Sopenharmony_ciSkOTUtils::LocalizedStrings_NameTable::Make(const SkTypeface& typeface, 181cb93a386Sopenharmony_ci SK_OT_USHORT types[], 182cb93a386Sopenharmony_ci int typesCount) 183cb93a386Sopenharmony_ci{ 184cb93a386Sopenharmony_ci static const SkFontTableTag nameTag = SkSetFourByteTag('n','a','m','e'); 185cb93a386Sopenharmony_ci size_t nameTableSize = typeface.getTableSize(nameTag); 186cb93a386Sopenharmony_ci if (0 == nameTableSize) { 187cb93a386Sopenharmony_ci return nullptr; 188cb93a386Sopenharmony_ci } 189cb93a386Sopenharmony_ci std::unique_ptr<uint8_t[]> nameTableData(new uint8_t[nameTableSize]); 190cb93a386Sopenharmony_ci size_t copied = typeface.getTableData(nameTag, 0, nameTableSize, nameTableData.get()); 191cb93a386Sopenharmony_ci if (copied != nameTableSize) { 192cb93a386Sopenharmony_ci return nullptr; 193cb93a386Sopenharmony_ci } 194cb93a386Sopenharmony_ci 195cb93a386Sopenharmony_ci return sk_sp<SkOTUtils::LocalizedStrings_NameTable>( 196cb93a386Sopenharmony_ci new SkOTUtils::LocalizedStrings_NameTable(std::move(nameTableData), nameTableSize, 197cb93a386Sopenharmony_ci types, typesCount)); 198cb93a386Sopenharmony_ci} 199cb93a386Sopenharmony_ci 200cb93a386Sopenharmony_cisk_sp<SkOTUtils::LocalizedStrings_NameTable> 201cb93a386Sopenharmony_ciSkOTUtils::LocalizedStrings_NameTable::MakeForFamilyNames(const SkTypeface& typeface) { 202cb93a386Sopenharmony_ci return Make(typeface, 203cb93a386Sopenharmony_ci SkOTUtils::LocalizedStrings_NameTable::familyNameTypes, 204cb93a386Sopenharmony_ci SK_ARRAY_COUNT(SkOTUtils::LocalizedStrings_NameTable::familyNameTypes)); 205cb93a386Sopenharmony_ci} 206cb93a386Sopenharmony_ci 207cb93a386Sopenharmony_cibool SkOTUtils::LocalizedStrings_NameTable::next(SkTypeface::LocalizedString* localizedString) { 208cb93a386Sopenharmony_ci do { 209cb93a386Sopenharmony_ci SkOTTableName::Iterator::Record record; 210cb93a386Sopenharmony_ci if (fFamilyNameIter.next(record)) { 211cb93a386Sopenharmony_ci localizedString->fString = record.name; 212cb93a386Sopenharmony_ci localizedString->fLanguage = record.language; 213cb93a386Sopenharmony_ci return true; 214cb93a386Sopenharmony_ci } 215cb93a386Sopenharmony_ci if (fTypesCount == fTypesIndex + 1) { 216cb93a386Sopenharmony_ci return false; 217cb93a386Sopenharmony_ci } 218cb93a386Sopenharmony_ci ++fTypesIndex; 219cb93a386Sopenharmony_ci fFamilyNameIter.reset(fTypes[fTypesIndex]); 220cb93a386Sopenharmony_ci } while (true); 221cb93a386Sopenharmony_ci} 222cb93a386Sopenharmony_ci 223cb93a386Sopenharmony_ciSK_OT_USHORT SkOTUtils::LocalizedStrings_NameTable::familyNameTypes[3] = { 224cb93a386Sopenharmony_ci SkOTTableName::Record::NameID::Predefined::FontFamilyName, 225cb93a386Sopenharmony_ci SkOTTableName::Record::NameID::Predefined::PreferredFamily, 226cb93a386Sopenharmony_ci SkOTTableName::Record::NameID::Predefined::WWSFamilyName, 227cb93a386Sopenharmony_ci}; 228cb93a386Sopenharmony_ci 229cb93a386Sopenharmony_civoid SkOTUtils::SetAdvancedTypefaceFlags(SkOTTableOS2_V4::Type fsType, 230cb93a386Sopenharmony_ci SkAdvancedTypefaceMetrics* info) { 231cb93a386Sopenharmony_ci SkASSERT(info); 232cb93a386Sopenharmony_ci // The logic should be identical to SkTypeface_FreeType::onGetAdvancedMetrics(). 233cb93a386Sopenharmony_ci if (fsType.raw.value != 0) { 234cb93a386Sopenharmony_ci if (SkToBool(fsType.field.Restricted) || SkToBool(fsType.field.Bitmap)) { 235cb93a386Sopenharmony_ci info->fFlags |= SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag; 236cb93a386Sopenharmony_ci } 237cb93a386Sopenharmony_ci if (SkToBool(fsType.field.NoSubsetting)) { 238cb93a386Sopenharmony_ci info->fFlags |= SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag; 239cb93a386Sopenharmony_ci } 240cb93a386Sopenharmony_ci } 241cb93a386Sopenharmony_ci} 242