Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Functions
SkPDFType1Font.cpp File Reference
#include "src/pdf/SkPDFType1Font.h"
#include "include/private/base/SkTemplates.h"
#include "include/private/base/SkTo.h"
#include "src/core/SkStrike.h"
#include "src/core/SkStrikeSpec.h"
#include <ctype.h>

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 222 of file SkPDFType1Font.cpp.

222 {
224}
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 136 of file SkPDFType1Font.cpp.

139 {
140 size_t srcLen = srcStream ? srcStream->getLength() : 0;
141 SkASSERT(srcLen);
142 if (!srcLen) {
143 return nullptr;
144 }
145 // Flatten and Nul-terminate the source stream so that we can use
146 // strstr() to search it.
147 AutoTMalloc<uint8_t> sourceBuffer(SkToInt(srcLen + 1));
148 (void)srcStream->read(sourceBuffer.get(), srcLen);
149 sourceBuffer[SkToInt(srcLen)] = 0;
150 const uint8_t* src = sourceBuffer.get();
151
152 if (parsePFB(src, srcLen, headerLen, dataLen, trailerLen)) {
153 static const int kPFBSectionHeaderLength = 6;
154 const size_t length = *headerLen + *dataLen + *trailerLen;
155 SkASSERT(length > 0);
156 SkASSERT(length + (2 * kPFBSectionHeaderLength) <= srcLen);
157
159
160 const uint8_t* const srcHeader = src + kPFBSectionHeaderLength;
161 // There is a six-byte section header before header and data
162 // (but not trailer) that we're not going to copy.
163 const uint8_t* const srcData = srcHeader + *headerLen + kPFBSectionHeaderLength;
164 const uint8_t* const srcTrailer = srcData + *headerLen;
165
166 uint8_t* const resultHeader = (uint8_t*)data->writable_data();
167 uint8_t* const resultData = resultHeader + *headerLen;
168 uint8_t* const resultTrailer = resultData + *dataLen;
169
170 SkASSERT(resultTrailer + *trailerLen == resultHeader + length);
171
172 memcpy(resultHeader, srcHeader, *headerLen);
173 memcpy(resultData, srcData, *dataLen);
174 memcpy(resultTrailer, srcTrailer, *trailerLen);
175
176 return data;
177 }
178
179 // A PFA has to be converted for PDF.
180 size_t hexDataLen;
181 if (!parsePFA((const char*)src, srcLen, headerLen, &hexDataLen, dataLen,
182 trailerLen)) {
183 return nullptr;
184 }
185 const size_t length = *headerLen + *dataLen + *trailerLen;
186 SkASSERT(length > 0);
188 uint8_t* buffer = (uint8_t*)data->writable_data();
189
190 memcpy(buffer, src, *headerLen);
191 uint8_t* const resultData = &(buffer[*headerLen]);
192
193 const uint8_t* hexData = src + *headerLen;
194 const uint8_t* trailer = hexData + hexDataLen;
195 size_t outputOffset = 0;
196 uint8_t dataByte = 0; // To hush compiler.
197 bool highNibble = true;
198 for (; hexData < trailer; hexData++) {
199 int8_t curNibble = hexToBin(*hexData);
200 if (curNibble < 0) {
201 continue;
202 }
203 if (highNibble) {
204 dataByte = curNibble << 4;
205 highNibble = false;
206 } else {
207 dataByte |= curNibble;
208 highNibble = true;
209 resultData[outputOffset++] = dataByte;
210 }
211 }
212 if (!highNibble) {
213 resultData[outputOffset++] = dataByte;
214 }
215 SkASSERT(outputOffset == *dataLen);
216
217 uint8_t* const resultTrailer = &(buffer[SkToInt(*headerLen + outputOffset)]);
218 memcpy(resultTrailer, src + *headerLen + hexDataLen, *trailerLen);
219 return data;
220}
#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
static const uint8_t buffer[]
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 data
Definition switches.h:41

◆ from_font_units()

static SkScalar from_font_units ( SkScalar  scaled,
uint16_t  emSize 
)
inlinestatic

Definition at line 226 of file SkPDFType1Font.cpp.

226 {
227 return emSize == 1000 ? scaled : scaled * 1000 / emSize;
228}

◆ hexToBin()

static int8_t hexToBin ( uint8_t  c)
static

Definition at line 123 of file SkPDFType1Font.cpp.

123 {
124 if (!isxdigit(c)) {
125 return -1;
126 } else if (c <= '9') {
127 return c - '0';
128 } else if (c <= 'F') {
129 return c - 'A' + 10;
130 } else if (c <= 'f') {
131 return c - 'a' + 10;
132 }
133 return -1;
134}

◆ make_type1_font_descriptor()

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

Definition at line 230 of file SkPDFType1Font.cpp.

232 {
233 SkPDFDict descriptor("FontDescriptor");
234 uint16_t emSize = SkToU16(typeface->getUnitsPerEm());
235 if (info) {
236 SkPDFFont::PopulateCommonFontDescriptor(&descriptor, *info, emSize, 0);
237 if (can_embed(*info)) {
238 int ttcIndex;
241 size_t trailer SK_INIT_TO_AVOID_WARNING;
242 std::unique_ptr<SkStreamAsset> rawFontData = typeface->openStream(&ttcIndex);
243 sk_sp<SkData> fontData = convert_type1_font_stream(std::move(rawFontData),
244 &header, &data, &trailer);
245 if (fontData) {
246 std::unique_ptr<SkPDFDict> dict = SkPDFMakeDict();
247 dict->insertInt("Length1", header);
248 dict->insertInt("Length2", data);
249 dict->insertInt("Length3", trailer);
250 auto fontStream = SkMemoryStream::Make(std::move(fontData));
251 descriptor.insertRef("FontFile",
252 SkPDFStreamOut(std::move(dict), std::move(fontStream),
254 }
255 }
256 }
257 return doc->emit(descriptor);
258}
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)
static std::unique_ptr< SkPDFDict > SkPDFMakeDict(const char *type=nullptr)
Definition SkPDFTypes.h:195
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)
int getUnitsPerEm() const
std::unique_ptr< SkStreamAsset > openStream(int *ttcIndex) const
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 70 of file SkPDFType1Font.cpp.

71 {
72 const char* end = src + size;
73
74 const char* dataPos = strstr(src, "eexec");
75 if (!dataPos) {
76 return false;
77 }
78 dataPos += strlen("eexec");
79 while ((*dataPos == '\n' || *dataPos == '\r' || *dataPos == ' ') &&
80 dataPos < end) {
81 dataPos++;
82 }
83 *headerLen = dataPos - src;
84
85 const char* trailerPos = strstr(dataPos, "cleartomark");
86 if (!trailerPos) {
87 return false;
88 }
89 int zeroCount = 0;
90 for (trailerPos--; trailerPos > dataPos && zeroCount < 512; trailerPos--) {
91 if (*trailerPos == '\n' || *trailerPos == '\r' || *trailerPos == ' ') {
92 continue;
93 } else if (*trailerPos == '0') {
94 zeroCount++;
95 } else {
96 return false;
97 }
98 }
99 if (zeroCount != 512) {
100 return false;
101 }
102
103 *hexDataLen = trailerPos - src - *headerLen;
104 *trailerLen = size - *headerLen - *hexDataLen;
105
106 // Verify that the data section is hex encoded and count the bytes.
107 int nibbles = 0;
108 for (; dataPos < trailerPos; dataPos++) {
109 if (isspace(*dataPos)) {
110 continue;
111 }
112 // isxdigit() is locale-sensitive https://bugs.skia.org/8285
113 if (nullptr == strchr("0123456789abcdefABCDEF", *dataPos)) {
114 return false;
115 }
116 nibbles++;
117 }
118 *dataLen = (nibbles + 1) / 2;
119
120 return true;
121}
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 51 of file SkPDFType1Font.cpp.

52 {
53 const uint8_t* srcPtr = src;
54 size_t remaining = size;
55
56 return parsePFBSection(&srcPtr, &remaining, 1, headerLen) &&
57 parsePFBSection(&srcPtr, &remaining, 2, dataLen) &&
58 parsePFBSection(&srcPtr, &remaining, 1, trailerLen) &&
59 parsePFBSection(&srcPtr, &remaining, 3, nullptr);
60}
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 25 of file SkPDFType1Font.cpp.

26 {
27 // PFB sections have a two or six bytes header. 0x80 and a one byte
28 // section type followed by a four byte section length. Type one is
29 // an ASCII section (includes a length), type two is a binary section
30 // (includes a length) and type three is an EOF marker with no length.
31 const uint8_t* buf = *src;
32 if (*len < 2 || buf[0] != 0x80 || buf[1] != sectionType) {
33 return false;
34 } else if (buf[1] == 3) {
35 return true;
36 } else if (*len < 6) {
37 return false;
38 }
39
40 *size = (size_t)buf[2] | ((size_t)buf[3] << 8) | ((size_t)buf[4] << 16) |
41 ((size_t)buf[5] << 24);
42 size_t consumed = *size + 6;
43 if (consumed > *len) {
44 return false;
45 }
46 *src = *src + consumed;
47 *len = *len - consumed;
48 return true;
49}

◆ SkPDFEmitType1Font()

void SkPDFEmitType1Font ( const SkPDFFont pdfFont,
SkPDFDocument doc 
)

Definition at line 287 of file SkPDFType1Font.cpp.

287 {
288 SkTypeface* typeface = pdfFont.typeface();
289 const std::vector<SkString>& glyphNames = type_1_glyphnames(doc, typeface);
290 SkGlyphID firstGlyphID = pdfFont.firstGlyphID();
291 SkGlyphID lastGlyphID = pdfFont.lastGlyphID();
292
293 SkPDFDict font("Font");
294 font.insertRef("FontDescriptor", type1_font_descriptor(doc, typeface));
295 font.insertName("Subtype", "Type1");
296 if (const SkAdvancedTypefaceMetrics* info = SkPDFFont::GetMetrics(typeface, doc)) {
297 font.insertName("BaseFont", info->fPostScriptName);
298 }
299
300 // glyphCount not including glyph 0
301 unsigned glyphCount = 1 + lastGlyphID - firstGlyphID;
302 SkASSERT(glyphCount > 0 && glyphCount <= 255);
303 font.insertInt("FirstChar", (size_t)0);
304 font.insertInt("LastChar", (size_t)glyphCount);
305 {
306 int emSize;
307 auto widths = SkPDFMakeArray();
308
309 int glyphRangeSize = lastGlyphID - firstGlyphID + 2;
310 AutoTArray<SkGlyphID> glyphIDs{glyphRangeSize};
311 glyphIDs[0] = 0;
312 for (unsigned gId = firstGlyphID; gId <= lastGlyphID; gId++) {
313 glyphIDs[gId - firstGlyphID + 1] = gId;
314 }
315 SkStrikeSpec strikeSpec = SkStrikeSpec::MakePDFVector(*typeface, &emSize);
316 SkBulkGlyphMetrics metrics{strikeSpec};
317 auto glyphs = metrics.glyphs(SkSpan(glyphIDs.get(), glyphRangeSize));
318 for (int i = 0; i < glyphRangeSize; ++i) {
319 widths->appendScalar(from_font_units(glyphs[i]->advanceX(), SkToU16(emSize)));
320 }
321 font.insertObject("Widths", std::move(widths));
322 }
323 auto encDiffs = SkPDFMakeArray();
324 encDiffs->reserve(lastGlyphID - firstGlyphID + 3);
325 encDiffs->appendInt(0);
326
327 SkASSERT(glyphNames.size() > lastGlyphID);
328 const SkString unknown("UNKNOWN");
329 encDiffs->appendName(glyphNames[0].isEmpty() ? unknown : glyphNames[0]);
330 for (int gID = firstGlyphID; gID <= lastGlyphID; gID++) {
331 encDiffs->appendName(glyphNames[gID].isEmpty() ? unknown : glyphNames[gID]);
332 }
333
334 auto encoding = SkPDFMakeDict("Encoding");
335 encoding->insertObject("Differences", std::move(encDiffs));
336 font.insertObject("Encoding", std::move(encoding));
337
338 doc->emit(font, pdfFont.indirectReference());
339}
uint16_t glyphs[5]
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:135
uint16_t SkGlyphID
Definition SkTypes.h:179
const SkScalar widths[]
static const SkAdvancedTypefaceMetrics * GetMetrics(const SkTypeface *typeface, SkPDFDocument *canon)
SkPDFIndirectReference indirectReference() const
Definition SkPDFFont.h:81
SkGlyphID lastGlyphID() const
Definition SkPDFFont.h:119
SkGlyphID firstGlyphID() const
Definition SkPDFFont.h:118
SkTypeface * typeface() const
Definition SkPDFFont.h:39
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 274 of file SkPDFType1Font.cpp.

275 {
276 SkTypefaceID typefaceID = typeface->uniqueID();
277 if (SkPDFIndirectReference* ptr = doc->fFontDescriptors.find(typefaceID)) {
278 return *ptr;
279 }
281 auto fontDescriptor = make_type1_font_descriptor(doc, typeface, info);
282 doc->fFontDescriptors.set(typefaceID, fontDescriptor);
283 return fontDescriptor;
284}
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:479
V * set(K key, V val)
Definition SkTHash.h:472

◆ type_1_glyphnames()

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

Definition at line 261 of file SkPDFType1Font.cpp.

262 {
263 SkTypefaceID typefaceID = typeface->uniqueID();
264 const std::vector<SkString>* glyphNames = canon->fType1GlyphNames.find(typefaceID);
265 if (!glyphNames) {
266 std::vector<SkString> names(typeface->countGlyphs());
267 SkPDFFont::GetType1GlyphNames(*typeface, names.data());
268 glyphNames = canon->fType1GlyphNames.set(typefaceID, std::move(names));
269 }
270 SkASSERT(glyphNames);
271 return *glyphNames;
272}
skia_private::THashMap< uint32_t, std::vector< SkString > > fType1GlyphNames
static void GetType1GlyphNames(const SkTypeface &, SkString *)
Definition SkPDFFont.cpp:53
int countGlyphs() const