Flutter Engine
The Flutter Engine
SkOTUtils.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include <array>
9
10#include "src/sfnt/SkOTUtils.h"
11
12#include "include/core/SkData.h"
15#include "src/base/SkEndian.h"
21
23 uint32_t sum = 0;
24 SK_OT_ULONG *dataEnd = data + ((length + 3) & ~3) / sizeof(SK_OT_ULONG);
25 for (; data < dataEnd; ++data) {
26 sum += SkEndian_SwapBE32(*data);
27 }
28 return sum;
29}
30
31SkData* SkOTUtils::RenameFont(SkStreamAsset* fontData, const char* fontName, int fontNameLen) {
32
33 // Get the sfnt header.
34 SkSFNTHeader sfntHeader;
35 if (fontData->read(&sfntHeader, sizeof(sfntHeader)) < sizeof(sfntHeader)) {
36 return nullptr;
37 }
38
39 // Find the existing 'name' table.
40 int tableIndex;
42 int numTables = SkEndian_SwapBE16(sfntHeader.numTables);
43 for (tableIndex = 0; tableIndex < numTables; ++tableIndex) {
44 if (fontData->read(&tableEntry, sizeof(tableEntry)) < sizeof(tableEntry)) {
45 return nullptr;
46 }
47 if (SkOTTableName::TAG == tableEntry.tag) {
48 break;
49 }
50 }
51 if (tableIndex == numTables) {
52 return nullptr;
53 }
54
55 if (!fontData->rewind()) {
56 return nullptr;
57 }
58
59 // The required 'name' record types: Family, Style, Unique, Full and PostScript.
60 static constexpr std::array<SkOTTableName::Record::NameID::Predefined::Value, 5> names{{
66 }};
67
68 // GDI will not use a Symbol cmap table if there is no Symbol encoded name.
69 static constexpr std::array<SkOTTableName::Record::EncodingID::Windows::Value, 2> encodings{{
72 }};
73
74 // Copy the data, leaving out the old name table.
75 // In theory, we could also remove the DSIG table if it exists.
76 size_t nameTableLogicalSize = sizeof(SkOTTableName)
77 + (encodings.size() * names.size() * sizeof(SkOTTableName::Record))
78 + (fontNameLen * sizeof(SK_OT_USHORT));
79 size_t nameTablePhysicalSize = (nameTableLogicalSize + 3) & ~3; // Rounded up to a multiple of 4.
80
81 size_t oldNameTablePhysicalSize = (SkEndian_SwapBE32(tableEntry.logicalLength) + 3) & ~3; // Rounded up to a multiple of 4.
82 size_t oldNameTableOffset = SkEndian_SwapBE32(tableEntry.offset);
83
84 //originalDataSize is the size of the original data without the name table.
85 size_t originalDataSize = fontData->getLength() - oldNameTablePhysicalSize;
86 size_t newDataSize = originalDataSize + nameTablePhysicalSize;
87
88 auto rewrittenFontData = SkData::MakeUninitialized(newDataSize);
89 SK_OT_BYTE* data = static_cast<SK_OT_BYTE*>(rewrittenFontData->writable_data());
90
91 if (fontData->read(data, oldNameTableOffset) < oldNameTableOffset) {
92 return nullptr;
93 }
94 if (fontData->skip(oldNameTablePhysicalSize) < oldNameTablePhysicalSize) {
95 return nullptr;
96 }
97 if (fontData->read(data + oldNameTableOffset, originalDataSize - oldNameTableOffset) < originalDataSize - oldNameTableOffset) {
98 return nullptr;
99 }
100
101 //Fix up the offsets of the directory entries after the old 'name' table entry.
102 SkSFNTHeader::TableDirectoryEntry* currentEntry = reinterpret_cast<SkSFNTHeader::TableDirectoryEntry*>(data + sizeof(SkSFNTHeader));
103 SkSFNTHeader::TableDirectoryEntry* endEntry = currentEntry + numTables;
104 SkSFNTHeader::TableDirectoryEntry* headTableEntry = nullptr;
105 for (; currentEntry < endEntry; ++currentEntry) {
106 uint32_t oldOffset = SkEndian_SwapBE32(currentEntry->offset);
107 if (oldOffset > oldNameTableOffset) {
108 currentEntry->offset = SkEndian_SwapBE32(SkToU32(oldOffset - oldNameTablePhysicalSize));
109 }
110
111 if (SkOTTableHead::TAG == currentEntry->tag) {
112 headTableEntry = currentEntry;
113 }
114 }
115
116 // Make the table directory entry point to the new 'name' table.
117 SkSFNTHeader::TableDirectoryEntry* nameTableEntry = reinterpret_cast<SkSFNTHeader::TableDirectoryEntry*>(data + sizeof(SkSFNTHeader)) + tableIndex;
118 nameTableEntry->logicalLength = SkEndian_SwapBE32(SkToU32(nameTableLogicalSize));
119 nameTableEntry->offset = SkEndian_SwapBE32(SkToU32(originalDataSize));
120
121 // Write the new 'name' table after the original font data.
122 SkOTTableName* nameTable = reinterpret_cast<SkOTTableName*>(data + originalDataSize);
123 unsigned short stringOffset = sizeof(SkOTTableName) + (encodings.size() * names.size() * sizeof(SkOTTableName::Record));
124 nameTable->format = SkOTTableName::format_0;
125 nameTable->count = SkEndian_SwapBE16(encodings.size() * names.size());
126 nameTable->stringOffset = SkEndian_SwapBE16(stringOffset);
127
128 SkOTTableName::Record* nameRecord = reinterpret_cast<SkOTTableName::Record*>(data + originalDataSize + sizeof(SkOTTableName));
129 for (const auto& encoding : encodings) {
130 for (const auto& name : names) {
132 nameRecord->encodingID.windows.value = encoding;
134 nameRecord->nameID.predefined.value = name;
135 nameRecord->offset = SkEndian_SwapBE16(0);
136 nameRecord->length = SkEndian_SwapBE16(SkToU16(fontNameLen * sizeof(SK_OT_USHORT)));
137 ++nameRecord;
138 }
139 }
140
141 SK_OT_USHORT* nameString = reinterpret_cast<SK_OT_USHORT*>(data + originalDataSize + stringOffset);
142 for (int i = 0; i < fontNameLen; ++i) {
143 nameString[i] = SkEndian_SwapBE16(fontName[i]);
144 }
145
146 unsigned char* logical = data + originalDataSize + nameTableLogicalSize;
147 unsigned char* physical = data + originalDataSize + nameTablePhysicalSize;
148 for (; logical < physical; ++logical) {
149 *logical = 0;
150 }
151
152 // Update the table checksum in the directory entry.
153 nameTableEntry->checksum = SkEndian_SwapBE32(SkOTUtils::CalcTableChecksum(reinterpret_cast<SK_OT_ULONG*>(nameTable), nameTableLogicalSize));
154
155 // Update the checksum adjustment in the head table.
156 if (headTableEntry) {
157 size_t headTableOffset = SkEndian_SwapBE32(headTableEntry->offset);
158 if (headTableOffset + sizeof(SkOTTableHead) < originalDataSize) {
159 SkOTTableHead* headTable = reinterpret_cast<SkOTTableHead*>(data + headTableOffset);
161 uint32_t unadjustedFontChecksum = SkOTUtils::CalcTableChecksum(reinterpret_cast<SK_OT_ULONG*>(data), originalDataSize + nameTablePhysicalSize);
162 headTable->checksumAdjustment = SkEndian_SwapBE32(SkOTTableHead::fontChecksum - unadjustedFontChecksum);
163 }
164 }
165
166 return rewrittenFontData.release();
167}
168
171 SK_OT_USHORT types[],
172 int typesCount)
173{
174 static const SkFontTableTag nameTag = SkSetFourByteTag('n','a','m','e');
175 size_t nameTableSize = typeface.getTableSize(nameTag);
176 if (0 == nameTableSize) {
177 return nullptr;
178 }
179 std::unique_ptr<uint8_t[]> nameTableData(new uint8_t[nameTableSize]);
180 size_t copied = typeface.getTableData(nameTag, 0, nameTableSize, nameTableData.get());
181 if (copied != nameTableSize) {
182 return nullptr;
183 }
184
186 new SkOTUtils::LocalizedStrings_NameTable(std::move(nameTableData), nameTableSize,
187 types, typesCount));
188}
189
192 return Make(typeface,
193 SkOTUtils::LocalizedStrings_NameTable::familyNameTypes,
194 std::size(SkOTUtils::LocalizedStrings_NameTable::familyNameTypes));
195}
196
198 do {
200 if (fFamilyNameIter.next(record)) {
201 localizedString->fString = record.name;
202 localizedString->fLanguage = record.language;
203 return true;
204 }
205 if (fTypesCount == fTypesIndex + 1) {
206 return false;
207 }
208 ++fTypesIndex;
209 fFamilyNameIter.reset(fTypes[fTypesIndex]);
210 } while (true);
211}
212
213SK_OT_USHORT SkOTUtils::LocalizedStrings_NameTable::familyNameTypes[3] = {
217};
218
221 SkASSERT(info);
222 // The logic should be identical to SkTypeface_FreeType::onGetAdvancedMetrics().
223 if (fsType.raw.value != 0) {
224 if (SkToBool(fsType.field.Restricted) || SkToBool(fsType.field.Bitmap)) {
226 }
227 if (SkToBool(fsType.field.NoSubsetting)) {
229 }
230 }
231}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
#define SkASSERT(cond)
Definition: SkAssert.h:116
#define SkEndian_SwapBE32(n)
Definition: SkEndian.h:136
#define SkEndian_SwapBE16(n)
Definition: SkEndian.h:135
uint8_t SK_OT_BYTE
uint16_t SK_OT_USHORT
uint32_t SK_OT_ULONG
constexpr uint16_t SkToU16(S x)
Definition: SkTo.h:24
static constexpr bool SkToBool(const T &x)
Definition: SkTo.h:35
constexpr uint32_t SkToU32(S x)
Definition: SkTo.h:26
uint32_t SkFontTableTag
Definition: SkTypeface.h:41
static constexpr SkFourByteTag SkSetFourByteTag(char a, char b, char c, char d)
Definition: SkTypes.h:167
Definition: SkData.h:25
static sk_sp< SkData > MakeUninitialized(size_t length)
Definition: SkData.cpp:116
bool next(SkTypeface::LocalizedString *localizedString) override
Definition: SkOTUtils.cpp:197
static sk_sp< LocalizedStrings_NameTable > Make(const SkTypeface &typeface, SK_OT_USHORT types[], int typesCount)
Definition: SkOTUtils.cpp:170
static sk_sp< LocalizedStrings_NameTable > MakeForFamilyNames(const SkTypeface &typeface)
Definition: SkOTUtils.cpp:191
size_t getLength() const override=0
bool rewind() override=0
size_t skip(size_t size)
Definition: SkStream.h:51
virtual size_t read(void *buffer, size_t size)=0
void reset()
Definition: SkString.cpp:358
size_t getTableSize(SkFontTableTag) const
Definition: SkTypeface.cpp:309
size_t getTableData(SkFontTableTag tag, size_t offset, size_t length, void *data) const
Definition: SkTypeface.cpp:313
size_t length
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
static const char *const names[]
Definition: symbols.cc:24
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
@ kNotEmbeddable_FontFlag
May not be embedded.
@ kNotSubsettable_FontFlag
May not be subset.
SK_OT_ULONG checksumAdjustment
static const SK_OT_ULONG TAG
static const uint32_t fontChecksum
enum SkOTTableName::Record::EncodingID::Windows::Value value
enum SkOTTableName::Record::LanguageID::Windows::Value value
enum SkOTTableName::Record::NameID::Predefined::Value value
enum SkOTTableName::Record::PlatformID::Value value
struct SkOTTableName::Record::PlatformID platformID
union SkOTTableName::Record::NameID nameID
union SkOTTableName::Record::LanguageID languageID
union SkOTTableName::Record::EncodingID encodingID
static const SK_OT_USHORT format_0
SK_OT_USHORT stringOffset
SK_OT_USHORT format
static const SK_OT_ULONG TAG
SK_OT_USHORT count
static uint32_t CalcTableChecksum(SK_OT_ULONG *data, size_t length)
Definition: SkOTUtils.cpp:22
static SkData * RenameFont(SkStreamAsset *fontData, const char *fontName, int fontNameLen)
Definition: SkOTUtils.cpp:31
static void SetAdvancedTypefaceFlags(SkOTTableOS2_V4::Type fsType, SkAdvancedTypefaceMetrics *info)
Definition: SkOTUtils.cpp:219
SK_SFNT_USHORT numTables
Definition: SkSFNTHeader.h:51
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63
struct SkOTTableName::Record::EncodingID::Windows windows
struct SkOTTableName::Record::LanguageID::Windows windows
struct SkOTTableName::Record::NameID::Predefined predefined
struct SkOTTableOS2_V4::Type::Field field
struct SkOTTableOS2_V4::Type::Raw raw