31 const uint8_t* buf = *src;
32 if (*len < 2 || buf[0] != 0x80 || buf[1] != sectionType) {
34 }
else if (buf[1] == 3) {
36 }
else if (*len < 6) {
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) {
46 *src = *src + consumed;
47 *len = *len - consumed;
51static bool parsePFB(
const uint8_t* src,
size_t size,
size_t* headerLen,
52 size_t* dataLen,
size_t* trailerLen) {
53 const uint8_t* srcPtr = src;
54 size_t remaining = size;
70static bool parsePFA(
const char* src,
size_t size,
size_t* headerLen,
71 size_t* hexDataLen,
size_t* dataLen,
size_t* trailerLen) {
72 const char*
end = src + size;
74 const char* dataPos = strstr(src,
"eexec");
78 dataPos += strlen(
"eexec");
79 while ((*dataPos ==
'\n' || *dataPos ==
'\r' || *dataPos ==
' ') &&
83 *headerLen = dataPos - src;
85 const char* trailerPos = strstr(dataPos,
"cleartomark");
90 for (trailerPos--; trailerPos > dataPos && zeroCount < 512; trailerPos--) {
91 if (*trailerPos ==
'\n' || *trailerPos ==
'\r' || *trailerPos ==
' ') {
93 }
else if (*trailerPos ==
'0') {
99 if (zeroCount != 512) {
103 *hexDataLen = trailerPos - src - *headerLen;
104 *trailerLen = size - *headerLen - *hexDataLen;
108 for (; dataPos < trailerPos; dataPos++) {
109 if (isspace(*dataPos)) {
113 if (
nullptr == strchr(
"0123456789abcdefABCDEF", *dataPos)) {
118 *dataLen = (nibbles + 1) / 2;
126 }
else if (c <=
'9') {
128 }
else if (c <=
'F') {
130 }
else if (c <=
'f') {
139 size_t* trailerLen) {
140 size_t srcLen = srcStream ? srcStream->getLength() : 0;
148 (void)srcStream->read(sourceBuffer.
get(), srcLen);
149 sourceBuffer[
SkToInt(srcLen)] = 0;
150 const uint8_t* src = sourceBuffer.
get();
152 if (
parsePFB(src, srcLen, headerLen, dataLen, trailerLen)) {
153 static const int kPFBSectionHeaderLength = 6;
154 const size_t length = *headerLen + *dataLen + *trailerLen;
160 const uint8_t*
const srcHeader = src + kPFBSectionHeaderLength;
163 const uint8_t*
const srcData = srcHeader + *headerLen + kPFBSectionHeaderLength;
164 const uint8_t*
const srcTrailer = srcData + *headerLen;
166 uint8_t*
const resultHeader = (uint8_t*)data->writable_data();
167 uint8_t*
const resultData = resultHeader + *headerLen;
168 uint8_t*
const resultTrailer = resultData + *dataLen;
172 memcpy(resultHeader, srcHeader, *headerLen);
173 memcpy(resultData, srcData, *dataLen);
174 memcpy(resultTrailer, srcTrailer, *trailerLen);
181 if (!
parsePFA((
const char*)src, srcLen, headerLen, &hexDataLen, dataLen,
185 const size_t length = *headerLen + *dataLen + *trailerLen;
188 uint8_t*
buffer = (uint8_t*)data->writable_data();
190 memcpy(
buffer, src, *headerLen);
191 uint8_t*
const resultData = &(
buffer[*headerLen]);
193 const uint8_t* hexData = src + *headerLen;
194 const uint8_t* trailer = hexData + hexDataLen;
195 size_t outputOffset = 0;
196 uint8_t dataByte = 0;
197 bool highNibble =
true;
198 for (; hexData < trailer; hexData++) {
199 int8_t curNibble =
hexToBin(*hexData);
204 dataByte = curNibble << 4;
207 dataByte |= curNibble;
209 resultData[outputOffset++] = dataByte;
213 resultData[outputOffset++] = dataByte;
217 uint8_t*
const resultTrailer = &(
buffer[
SkToInt(*headerLen + outputOffset)]);
218 memcpy(resultTrailer, src + *headerLen + hexDataLen, *trailerLen);
227 return emSize == 1000 ? scaled : scaled * 1000 / emSize;
242 std::unique_ptr<SkStreamAsset> rawFontData = typeface->
openStream(&ttcIndex);
244 &
header, &data, &trailer);
247 dict->insertInt(
"Length1",
header);
248 dict->insertInt(
"Length2", data);
249 dict->insertInt(
"Length3", trailer);
257 return doc->
emit(descriptor);
266 std::vector<SkString> names(typeface->
countGlyphs());
283 return fontDescriptor;
295 font.insertName(
"Subtype",
"Type1");
297 font.insertName(
"BaseFont",
info->fPostScriptName);
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);
309 int glyphRangeSize = lastGlyphID - firstGlyphID + 2;
312 for (
unsigned gId = firstGlyphID; gId <= lastGlyphID; gId++) {
313 glyphIDs[gId - firstGlyphID + 1] = gId;
317 auto glyphs = metrics.glyphs(
SkSpan(glyphIDs.get(), glyphRangeSize));
318 for (
int i = 0; i < glyphRangeSize; ++i) {
321 font.insertObject(
"Widths", std::move(
widths));
324 encDiffs->reserve(lastGlyphID - firstGlyphID + 3);
325 encDiffs->appendInt(0);
327 SkASSERT(glyphNames.size() > lastGlyphID);
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]);
335 encoding->insertObject(
"Differences", std::move(encDiffs));
336 font.insertObject(
"Encoding", std::move(encoding));
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
#define SK_INIT_TO_AVOID_WARNING
static bool parsePFBSection(const uint8_t **src, size_t *len, int sectionType, size_t *size)
static const std::vector< SkString > & type_1_glyphnames(SkPDFDocument *canon, const SkTypeface *typeface)
static sk_sp< SkData > convert_type1_font_stream(std::unique_ptr< SkStreamAsset > srcStream, size_t *headerLen, size_t *dataLen, size_t *trailerLen)
void SkPDFEmitType1Font(const SkPDFFont &pdfFont, SkPDFDocument *doc)
static SkPDFIndirectReference make_type1_font_descriptor(SkPDFDocument *doc, const SkTypeface *typeface, const SkAdvancedTypefaceMetrics *info)
static bool parsePFB(const uint8_t *src, size_t size, size_t *headerLen, size_t *dataLen, size_t *trailerLen)
static SkScalar from_font_units(SkScalar scaled, uint16_t emSize)
static bool parsePFA(const char *src, size_t size, size_t *headerLen, size_t *hexDataLen, size_t *dataLen, size_t *trailerLen)
static bool can_embed(const SkAdvancedTypefaceMetrics &metrics)
static int8_t hexToBin(uint8_t c)
static SkPDFIndirectReference type1_font_descriptor(SkPDFDocument *doc, const SkTypeface *typeface)
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)
static std::unique_ptr< SkPDFArray > SkPDFMakeArray(Args... args)
constexpr uint16_t SkToU16(S x)
constexpr int SkToInt(S x)
static constexpr bool SkToBool(const T &x)
static sk_sp< SkData > MakeUninitialized(size_t length)
static std::unique_ptr< SkMemoryStream > Make(sk_sp< SkData > data)
void insertRef(const char key[], SkPDFIndirectReference)
SkPDFIndirectReference emit(const SkPDFObject &, SkPDFIndirectReference)
skia_private::THashMap< uint32_t, SkPDFIndirectReference > fFontDescriptors
skia_private::THashMap< uint32_t, std::vector< SkString > > fType1GlyphNames
static const SkAdvancedTypefaceMetrics * GetMetrics(const SkTypeface *typeface, SkPDFDocument *canon)
static void PopulateCommonFontDescriptor(SkPDFDict *descriptor, const SkAdvancedTypefaceMetrics &, uint16_t emSize, int16_t defaultWidth)
SkPDFIndirectReference indirectReference() const
SkGlyphID lastGlyphID() const
SkGlyphID firstGlyphID() const
static void GetType1GlyphNames(const SkTypeface &, SkString *)
SkTypeface * typeface() const
static SkStrikeSpec MakePDFVector(const SkTypeface &typeface, int *size)
SkTypefaceID uniqueID() const
int getUnitsPerEm() const
std::unique_ptr< SkStreamAsset > openStream(int *ttcIndex) const
V * find(const K &key) const
static const uint8_t buffer[]
static const char header[]
@ kNotEmbeddable_FontFlag
May not be embedded.