Flutter Engine
The Flutter Engine
Functions
SkPDFType1Font.cpp File Reference
#include "src/pdf/SkPDFType1Font.h"
#include "include/core/SkData.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkStream.h"
#include "include/core/SkString.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkMacros.h"
#include "include/private/base/SkSpan_impl.h"
#include "include/private/base/SkTemplates.h"
#include "include/private/base/SkTo.h"
#include "src/base/SkBitmaskEnum.h"
#include "src/core/SkAdvancedTypefaceMetrics.h"
#include "src/core/SkGlyph.h"
#include "src/core/SkStrikeSpec.h"
#include "src/core/SkTHash.h"
#include "src/pdf/SkPDFDocumentPriv.h"
#include "src/pdf/SkPDFFont.h"
#include "src/pdf/SkPDFTypes.h"
#include <ctype.h>
#include <cstdint>
#include <cstring>
#include <memory>
#include <utility>
#include <vector>

Go to the source code of this file.

Functions

static bool parsePFBSection (const uint8_t **src, size_t *len, int sectionType, size_t *size)
 
static bool parsePFB (const uint8_t *src, size_t size, size_t *headerLen, size_t *dataLen, size_t *trailerLen)
 
static bool parsePFA (const char *src, size_t size, size_t *headerLen, size_t *hexDataLen, size_t *dataLen, size_t *trailerLen)
 
static int8_t hexToBin (uint8_t c)
 
static sk_sp< SkDataconvert_type1_font_stream (std::unique_ptr< SkStreamAsset > srcStream, size_t *headerLen, size_t *dataLen, size_t *trailerLen)
 
static bool can_embed (const SkAdvancedTypefaceMetrics &metrics)
 
static SkScalar from_font_units (SkScalar scaled, uint16_t emSize)
 
static SkPDFIndirectReference make_type1_font_descriptor (SkPDFDocument *doc, const SkTypeface *typeface, const SkAdvancedTypefaceMetrics *info)
 
static const std::vector< SkString > & type_1_glyphnames (SkPDFDocument *canon, const SkTypeface *typeface)
 
static SkPDFIndirectReference type1_font_descriptor (SkPDFDocument *doc, const SkTypeface *typeface)
 
void SkPDFEmitType1Font (const SkPDFFont &pdfFont, SkPDFDocument *doc)
 

Function Documentation

◆ can_embed()

static bool can_embed ( const SkAdvancedTypefaceMetrics metrics)
inlinestatic

Definition at line 242 of file SkPDFType1Font.cpp.

242 {
244}
static constexpr bool SkToBool(const T &x)
Definition: SkTo.h:35
@ kNotEmbeddable_FontFlag
May not be embedded.

◆ convert_type1_font_stream()

static sk_sp< SkData > convert_type1_font_stream ( std::unique_ptr< SkStreamAsset srcStream,
size_t *  headerLen,
size_t *  dataLen,
size_t *  trailerLen 
)
static

Definition at line 156 of file SkPDFType1Font.cpp.

159 {
160 size_t srcLen = srcStream ? srcStream->getLength() : 0;
161 SkASSERT(srcLen);
162 if (!srcLen) {
163 return nullptr;
164 }
165 // Flatten and Nul-terminate the source stream so that we can use
166 // strstr() to search it.
167 AutoTMalloc<uint8_t> sourceBuffer(SkToInt(srcLen + 1));
168 (void)srcStream->read(sourceBuffer.get(), srcLen);
169 sourceBuffer[SkToInt(srcLen)] = 0;
170 const uint8_t* src = sourceBuffer.get();
171
172 if (parsePFB(src, srcLen, headerLen, dataLen, trailerLen)) {
173 static const int kPFBSectionHeaderLength = 6;
174 const size_t length = *headerLen + *dataLen + *trailerLen;
175 SkASSERT(length > 0);
176 SkASSERT(length + (2 * kPFBSectionHeaderLength) <= srcLen);
177
179
180 const uint8_t* const srcHeader = src + kPFBSectionHeaderLength;
181 // There is a six-byte section header before header and data
182 // (but not trailer) that we're not going to copy.
183 const uint8_t* const srcData = srcHeader + *headerLen + kPFBSectionHeaderLength;
184 const uint8_t* const srcTrailer = srcData + *headerLen;
185
186 uint8_t* const resultHeader = (uint8_t*)data->writable_data();
187 uint8_t* const resultData = resultHeader + *headerLen;
188 uint8_t* const resultTrailer = resultData + *dataLen;
189
190 SkASSERT(resultTrailer + *trailerLen == resultHeader + length);
191
192 memcpy(resultHeader, srcHeader, *headerLen);
193 memcpy(resultData, srcData, *dataLen);
194 memcpy(resultTrailer, srcTrailer, *trailerLen);
195
196 return data;
197 }
198
199 // A PFA has to be converted for PDF.
200 size_t hexDataLen;
201 if (!parsePFA((const char*)src, srcLen, headerLen, &hexDataLen, dataLen,
202 trailerLen)) {
203 return nullptr;
204 }
205 const size_t length = *headerLen + *dataLen + *trailerLen;
206 SkASSERT(length > 0);
208 uint8_t* buffer = (uint8_t*)data->writable_data();
209
210 memcpy(buffer, src, *headerLen);
211 uint8_t* const resultData = &(buffer[*headerLen]);
212
213 const uint8_t* hexData = src + *headerLen;
214 const uint8_t* trailer = hexData + hexDataLen;
215 size_t outputOffset = 0;
216 uint8_t dataByte = 0; // To hush compiler.
217 bool highNibble = true;
218 for (; hexData < trailer; hexData++) {
219 int8_t curNibble = hexToBin(*hexData);
220 if (curNibble < 0) {
221 continue;
222 }
223 if (highNibble) {
224 dataByte = curNibble << 4;
225 highNibble = false;
226 } else {
227 dataByte |= curNibble;
228 highNibble = true;
229 resultData[outputOffset++] = dataByte;
230 }
231 }
232 if (!highNibble) {
233 resultData[outputOffset++] = dataByte;
234 }
235 SkASSERT(outputOffset == *dataLen);
236
237 uint8_t* const resultTrailer = &(buffer[SkToInt(*headerLen + outputOffset)]);
238 memcpy(resultTrailer, src + *headerLen + hexDataLen, *trailerLen);
239 return data;
240}
#define SkASSERT(cond)
Definition: SkAssert.h:116
static bool parsePFB(const uint8_t *src, size_t size, size_t *headerLen, size_t *dataLen, size_t *trailerLen)
static bool parsePFA(const char *src, size_t size, size_t *headerLen, size_t *hexDataLen, size_t *dataLen, size_t *trailerLen)
static int8_t hexToBin(uint8_t c)
constexpr int SkToInt(S x)
Definition: SkTo.h:29
static sk_sp< SkData > MakeUninitialized(size_t length)
Definition: SkData.cpp:116
size_t length
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63

◆ from_font_units()

static SkScalar from_font_units ( SkScalar  scaled,
uint16_t  emSize 
)
inlinestatic

Definition at line 246 of file SkPDFType1Font.cpp.

246 {
247 return emSize == 1000 ? scaled : scaled * 1000 / emSize;
248}

◆ hexToBin()

static int8_t hexToBin ( uint8_t  c)
static

Definition at line 143 of file SkPDFType1Font.cpp.

143 {
144 if (!isxdigit(c)) {
145 return -1;
146 } else if (c <= '9') {
147 return c - '0';
148 } else if (c <= 'F') {
149 return c - 'A' + 10;
150 } else if (c <= 'f') {
151 return c - 'a' + 10;
152 }
153 return -1;
154}

◆ make_type1_font_descriptor()

static SkPDFIndirectReference make_type1_font_descriptor ( SkPDFDocument doc,
const SkTypeface typeface,
const SkAdvancedTypefaceMetrics info 
)
static

Definition at line 250 of file SkPDFType1Font.cpp.

252 {
253 SkPDFDict descriptor("FontDescriptor");
254 uint16_t emSize = SkToU16(typeface->getUnitsPerEm());
255 if (info) {
256 SkPDFFont::PopulateCommonFontDescriptor(&descriptor, *info, emSize, 0);
257 if (can_embed(*info)) {
258 int ttcIndex;
261 size_t trailer SK_INIT_TO_AVOID_WARNING;
262 std::unique_ptr<SkStreamAsset> rawFontData = typeface->openStream(&ttcIndex);
263 sk_sp<SkData> fontData = convert_type1_font_stream(std::move(rawFontData),
264 &header, &data, &trailer);
265 if (fontData) {
266 std::unique_ptr<SkPDFDict> dict = SkPDFMakeDict();
267 dict->insertInt("Length1", header);
268 dict->insertInt("Length2", data);
269 dict->insertInt("Length3", trailer);
270 auto fontStream = SkMemoryStream::Make(std::move(fontData));
271 descriptor.insertRef("FontFile",
272 SkPDFStreamOut(std::move(dict), std::move(fontStream),
274 }
275 }
276 }
277 return doc->emit(descriptor);
278}
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
#define SK_INIT_TO_AVOID_WARNING
Definition: SkMacros.h:58
static sk_sp< SkData > convert_type1_font_stream(std::unique_ptr< SkStreamAsset > srcStream, size_t *headerLen, size_t *dataLen, size_t *trailerLen)
static bool can_embed(const SkAdvancedTypefaceMetrics &metrics)
SkPDFIndirectReference SkPDFStreamOut(std::unique_ptr< SkPDFDict > dict, std::unique_ptr< SkStreamAsset > content, SkPDFDocument *doc, SkPDFSteamCompressionEnabled compress)
Definition: SkPDFTypes.cpp:591
static std::unique_ptr< SkPDFDict > SkPDFMakeDict(const char *type=nullptr)
Definition: SkPDFTypes.h:185
constexpr uint16_t SkToU16(S x)
Definition: SkTo.h:24
static std::unique_ptr< SkMemoryStream > Make(sk_sp< SkData > data)
Definition: SkStream.cpp:314
SkPDFIndirectReference emit(const SkPDFObject &, SkPDFIndirectReference)
static void PopulateCommonFontDescriptor(SkPDFDict *descriptor, const SkAdvancedTypefaceMetrics &, uint16_t emSize, int16_t defaultWidth)
Definition: SkPDFFont.cpp:265
int getUnitsPerEm() const
Definition: SkTypeface.cpp:436
std::unique_ptr< SkStreamAsset > openStream(int *ttcIndex) const
Definition: SkTypeface.cpp:332
static const char header[]
Definition: skpbench.cpp:88

◆ parsePFA()

static bool parsePFA ( const char *  src,
size_t  size,
size_t *  headerLen,
size_t *  hexDataLen,
size_t *  dataLen,
size_t *  trailerLen 
)
static

Definition at line 90 of file SkPDFType1Font.cpp.

91 {
92 const char* end = src + size;
93
94 const char* dataPos = strstr(src, "eexec");
95 if (!dataPos) {
96 return false;
97 }
98 dataPos += strlen("eexec");
99 while ((*dataPos == '\n' || *dataPos == '\r' || *dataPos == ' ') &&
100 dataPos < end) {
101 dataPos++;
102 }
103 *headerLen = dataPos - src;
104
105 const char* trailerPos = strstr(dataPos, "cleartomark");
106 if (!trailerPos) {
107 return false;
108 }
109 int zeroCount = 0;
110 for (trailerPos--; trailerPos > dataPos && zeroCount < 512; trailerPos--) {
111 if (*trailerPos == '\n' || *trailerPos == '\r' || *trailerPos == ' ') {
112 continue;
113 } else if (*trailerPos == '0') {
114 zeroCount++;
115 } else {
116 return false;
117 }
118 }
119 if (zeroCount != 512) {
120 return false;
121 }
122
123 *hexDataLen = trailerPos - src - *headerLen;
124 *trailerLen = size - *headerLen - *hexDataLen;
125
126 // Verify that the data section is hex encoded and count the bytes.
127 int nibbles = 0;
128 for (; dataPos < trailerPos; dataPos++) {
129 if (isspace(*dataPos)) {
130 continue;
131 }
132 // isxdigit() is locale-sensitive https://bugs.skia.org/8285
133 if (nullptr == strchr("0123456789abcdefABCDEF", *dataPos)) {
134 return false;
135 }
136 nibbles++;
137 }
138 *dataLen = (nibbles + 1) / 2;
139
140 return true;
141}
glong glong end
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

◆ parsePFB()

static bool parsePFB ( const uint8_t *  src,
size_t  size,
size_t *  headerLen,
size_t *  dataLen,
size_t *  trailerLen 
)
static

Definition at line 71 of file SkPDFType1Font.cpp.

72 {
73 const uint8_t* srcPtr = src;
74 size_t remaining = size;
75
76 return parsePFBSection(&srcPtr, &remaining, 1, headerLen) &&
77 parsePFBSection(&srcPtr, &remaining, 2, dataLen) &&
78 parsePFBSection(&srcPtr, &remaining, 1, trailerLen) &&
79 parsePFBSection(&srcPtr, &remaining, 3, nullptr);
80}
static bool parsePFBSection(const uint8_t **src, size_t *len, int sectionType, size_t *size)

◆ parsePFBSection()

static bool parsePFBSection ( const uint8_t **  src,
size_t *  len,
int  sectionType,
size_t *  size 
)
static

Definition at line 45 of file SkPDFType1Font.cpp.

46 {
47 // PFB sections have a two or six bytes header. 0x80 and a one byte
48 // section type followed by a four byte section length. Type one is
49 // an ASCII section (includes a length), type two is a binary section
50 // (includes a length) and type three is an EOF marker with no length.
51 const uint8_t* buf = *src;
52 if (*len < 2 || buf[0] != 0x80 || buf[1] != sectionType) {
53 return false;
54 } else if (buf[1] == 3) {
55 return true;
56 } else if (*len < 6) {
57 return false;
58 }
59
60 *size = (size_t)buf[2] | ((size_t)buf[3] << 8) | ((size_t)buf[4] << 16) |
61 ((size_t)buf[5] << 24);
62 size_t consumed = *size + 6;
63 if (consumed > *len) {
64 return false;
65 }
66 *src = *src + consumed;
67 *len = *len - consumed;
68 return true;
69}

◆ SkPDFEmitType1Font()

void SkPDFEmitType1Font ( const SkPDFFont pdfFont,
SkPDFDocument doc 
)

Definition at line 307 of file SkPDFType1Font.cpp.

307 {
308 SkTypeface* typeface = pdfFont.typeface();
309 const std::vector<SkString>& glyphNames = type_1_glyphnames(doc, typeface);
310 SkGlyphID firstGlyphID = pdfFont.firstGlyphID();
311 SkGlyphID lastGlyphID = pdfFont.lastGlyphID();
312
313 SkPDFDict font("Font");
314 font.insertRef("FontDescriptor", type1_font_descriptor(doc, typeface));
315 font.insertName("Subtype", "Type1");
316 if (const SkAdvancedTypefaceMetrics* info = SkPDFFont::GetMetrics(typeface, doc)) {
317 font.insertName("BaseFont", info->fPostScriptName);
318 }
319
320 // glyphCount not including glyph 0
321 unsigned glyphCount = 1 + lastGlyphID - firstGlyphID;
322 SkASSERT(glyphCount > 0 && glyphCount <= 255);
323 font.insertInt("FirstChar", (size_t)0);
324 font.insertInt("LastChar", (size_t)glyphCount);
325 {
326 int emSize;
327 auto widths = SkPDFMakeArray();
328
329 int glyphRangeSize = lastGlyphID - firstGlyphID + 2;
330 AutoTArray<SkGlyphID> glyphIDs{glyphRangeSize};
331 glyphIDs[0] = 0;
332 for (unsigned gId = firstGlyphID; gId <= lastGlyphID; gId++) {
333 glyphIDs[gId - firstGlyphID + 1] = gId;
334 }
335 SkStrikeSpec strikeSpec = SkStrikeSpec::MakePDFVector(*typeface, &emSize);
336 SkBulkGlyphMetrics metrics{strikeSpec};
337 auto glyphs = metrics.glyphs(SkSpan(glyphIDs.get(), glyphRangeSize));
338 for (int i = 0; i < glyphRangeSize; ++i) {
339 widths->appendScalar(from_font_units(glyphs[i]->advanceX(), SkToU16(emSize)));
340 }
341 font.insertObject("Widths", std::move(widths));
342 }
343 auto encDiffs = SkPDFMakeArray();
344 encDiffs->reserve(lastGlyphID - firstGlyphID + 3);
345 encDiffs->appendInt(0);
346
347 SkASSERT(glyphNames.size() > lastGlyphID);
348 const SkString unknown("UNKNOWN");
349 encDiffs->appendName(glyphNames[0].isEmpty() ? unknown : glyphNames[0]);
350 for (int gID = firstGlyphID; gID <= lastGlyphID; gID++) {
351 encDiffs->appendName(glyphNames[gID].isEmpty() ? unknown : glyphNames[gID]);
352 }
353
354 auto encoding = SkPDFMakeDict("Encoding");
355 encoding->insertObject("Differences", std::move(encDiffs));
356 font.insertObject("Encoding", std::move(encoding));
357
358 doc->emit(font, pdfFont.indirectReference());
359}
uint16_t glyphs[5]
Definition: FontMgrTest.cpp:46
static const std::vector< SkString > & type_1_glyphnames(SkPDFDocument *canon, const SkTypeface *typeface)
static SkScalar from_font_units(SkScalar scaled, uint16_t emSize)
static SkPDFIndirectReference type1_font_descriptor(SkPDFDocument *doc, const SkTypeface *typeface)
static std::unique_ptr< SkPDFArray > SkPDFMakeArray(Args... args)
Definition: SkPDFTypes.h:125
SkSpan(Container &&) -> SkSpan< std::remove_pointer_t< decltype(std::data(std::declval< Container >()))> >
uint16_t SkGlyphID
Definition: SkTypes.h:179
const SkScalar widths[]
Definition: StrokerTest.cpp:39
static const SkAdvancedTypefaceMetrics * GetMetrics(const SkTypeface *typeface, SkPDFDocument *canon)
Definition: SkPDFFont.cpp:118
SkPDFIndirectReference indirectReference() const
Definition: SkPDFFont.h:83
SkGlyphID lastGlyphID() const
Definition: SkPDFFont.h:121
SkGlyphID firstGlyphID() const
Definition: SkPDFFont.h:120
SkTypeface * typeface() const
Definition: SkPDFFont.h:41
static SkStrikeSpec MakePDFVector(const SkTypeface &typeface, int *size)
font
Font Metadata and Metrics.

◆ type1_font_descriptor()

static SkPDFIndirectReference type1_font_descriptor ( SkPDFDocument doc,
const SkTypeface typeface 
)
static

Definition at line 294 of file SkPDFType1Font.cpp.

295 {
296 SkTypefaceID typefaceID = typeface->uniqueID();
297 if (SkPDFIndirectReference* ptr = doc->fFontDescriptors.find(typefaceID)) {
298 return *ptr;
299 }
301 auto fontDescriptor = make_type1_font_descriptor(doc, typeface, info);
302 doc->fFontDescriptors.set(typefaceID, fontDescriptor);
303 return fontDescriptor;
304}
static SkPDFIndirectReference make_type1_font_descriptor(SkPDFDocument *doc, const SkTypeface *typeface, const SkAdvancedTypefaceMetrics *info)
uint32_t SkTypefaceID
Definition: SkTypeface.h:38
skia_private::THashMap< uint32_t, SkPDFIndirectReference > fFontDescriptors
SkTypefaceID uniqueID() const
Definition: SkTypeface.h:101
V * find(const K &key) const
Definition: SkTHash.h:494
V * set(K key, V val)
Definition: SkTHash.h:487

◆ type_1_glyphnames()

static const std::vector< SkString > & type_1_glyphnames ( SkPDFDocument canon,
const SkTypeface typeface 
)
static

Definition at line 281 of file SkPDFType1Font.cpp.

282 {
283 SkTypefaceID typefaceID = typeface->uniqueID();
284 const std::vector<SkString>* glyphNames = canon->fType1GlyphNames.find(typefaceID);
285 if (!glyphNames) {
286 std::vector<SkString> names(typeface->countGlyphs());
287 SkPDFFont::GetType1GlyphNames(*typeface, names.data());
288 glyphNames = canon->fType1GlyphNames.set(typefaceID, std::move(names));
289 }
290 SkASSERT(glyphNames);
291 return *glyphNames;
292}
skia_private::THashMap< uint32_t, std::vector< SkString > > fType1GlyphNames
static void GetType1GlyphNames(const SkTypeface &, SkString *)
Definition: SkPDFFont.cpp:59
int countGlyphs() const
Definition: SkTypeface.cpp:432
static const char *const names[]
Definition: symbols.cc:24