1 /*
2 * Copyright 2011 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 "SkPDFFont.h"
9
10 #include "SkData.h"
11 #include "SkFont.h"
12 #include "SkImagePriv.h"
13 #include "SkMacros.h"
14 #include "SkMakeUnique.h"
15 #include "SkPDFBitmap.h"
16 #include "SkPDFDocument.h"
17 #include "SkPDFConvertType1FontStream.h"
18 #include "SkPDFDevice.h"
19 #include "SkPDFDocumentPriv.h"
20 #include "SkPDFMakeCIDGlyphWidthsArray.h"
21 #include "SkPDFMakeToUnicodeCmap.h"
22 #include "SkPDFResourceDict.h"
23 #include "SkPDFSubsetFont.h"
24 #include "SkPDFUtils.h"
25 #include "SkPaint.h"
26 #include "SkRefCnt.h"
27 #include "SkScalar.h"
28 #include "SkStream.h"
29 #include "SkStrike.h"
30 #include "SkTo.h"
31 #include "SkTypes.h"
32 #include "SkUTF.h"
33
MakeVectorCache(SkTypeface * face,int * size)34 SkExclusiveStrikePtr SkPDFFont::MakeVectorCache(SkTypeface* face, int* size) {
35 SkFont font;
36 font.setHinting(kNo_SkFontHinting);
37 font.setEdging(SkFont::Edging::kAlias);
38 font.setTypeface(sk_ref_sp(face));
39 int unitsPerEm = face->getUnitsPerEm();
40 if (unitsPerEm <= 0) {
41 unitsPerEm = 1024;
42 }
43 if (size) {
44 *size = unitsPerEm;
45 }
46 font.setSize((SkScalar)unitsPerEm);
47 const SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
48 return SkStrikeCache::FindOrCreateStrikeExclusive(
49 font, SkPaint(), props, SkScalerContextFlags::kFakeGammaAndBoostContrast, SkMatrix::I());
50 }
51
52 namespace {
53 // PDF's notion of symbolic vs non-symbolic is related to the character set, not
54 // symbols vs. characters. Rarely is a font the right character set to call it
55 // non-symbolic, so always call it symbolic. (PDF 1.4 spec, section 5.7.1)
56 static const int32_t kPdfSymbolic = 4;
57
58
59 // scale from em-units to base-1000, returning as a SkScalar
from_font_units(SkScalar scaled,uint16_t emSize)60 SkScalar from_font_units(SkScalar scaled, uint16_t emSize) {
61 if (emSize == 1000) {
62 return scaled;
63 } else {
64 return scaled * 1000 / emSize;
65 }
66 }
67
scaleFromFontUnits(int16_t val,uint16_t emSize)68 SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) {
69 return from_font_units(SkIntToScalar(val), emSize);
70 }
71
72
setGlyphWidthAndBoundingBox(SkScalar width,SkIRect box,SkDynamicMemoryWStream * content)73 void setGlyphWidthAndBoundingBox(SkScalar width, SkIRect box,
74 SkDynamicMemoryWStream* content) {
75 // Specify width and bounding box for the glyph.
76 SkPDFUtils::AppendScalar(width, content);
77 content->writeText(" 0 ");
78 content->writeDecAsText(box.fLeft);
79 content->writeText(" ");
80 content->writeDecAsText(box.fTop);
81 content->writeText(" ");
82 content->writeDecAsText(box.fRight);
83 content->writeText(" ");
84 content->writeDecAsText(box.fBottom);
85 content->writeText(" d1\n");
86 }
87 } // namespace
88
89 ///////////////////////////////////////////////////////////////////////////////
90 // class SkPDFFont
91 ///////////////////////////////////////////////////////////////////////////////
92
93 /* Resources are canonicalized and uniqueified by pointer so there has to be
94 * some additional state indicating which subset of the font is used. It
95 * must be maintained at the document granularity.
96 */
97
98 SkPDFFont::~SkPDFFont() = default;
99
100 SkPDFFont::SkPDFFont(SkPDFFont&&) = default;
101
102 SkPDFFont& SkPDFFont::operator=(SkPDFFont&&) = default;
103
can_embed(const SkAdvancedTypefaceMetrics & metrics)104 static bool can_embed(const SkAdvancedTypefaceMetrics& metrics) {
105 return !SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag);
106 }
107
GetMetrics(const SkTypeface * typeface,SkPDFDocument * canon)108 const SkAdvancedTypefaceMetrics* SkPDFFont::GetMetrics(const SkTypeface* typeface,
109 SkPDFDocument* canon) {
110 SkASSERT(typeface);
111 SkFontID id = typeface->uniqueID();
112 if (std::unique_ptr<SkAdvancedTypefaceMetrics>* ptr = canon->fTypefaceMetrics.find(id)) {
113 return ptr->get(); // canon retains ownership.
114 }
115 int count = typeface->countGlyphs();
116 if (count <= 0 || count > 1 + SkTo<int>(UINT16_MAX)) {
117 // Cache nullptr to skip this check. Use SkSafeUnref().
118 canon->fTypefaceMetrics.set(id, nullptr);
119 return nullptr;
120 }
121 std::unique_ptr<SkAdvancedTypefaceMetrics> metrics = typeface->getAdvancedMetrics();
122 if (!metrics) {
123 metrics = skstd::make_unique<SkAdvancedTypefaceMetrics>();
124 }
125
126 if (0 == metrics->fStemV || 0 == metrics->fCapHeight) {
127 SkFont font;
128 font.setHinting(kNo_SkFontHinting);
129 font.setTypeface(sk_ref_sp(typeface));
130 font.setSize(1000); // glyph coordinate system
131 if (0 == metrics->fStemV) {
132 // Figure out a good guess for StemV - Min width of i, I, !, 1.
133 // This probably isn't very good with an italic font.
134 int16_t stemV = SHRT_MAX;
135 for (char c : {'i', 'I', '!', '1'}) {
136 uint16_t g = font.unicharToGlyph(c);
137 SkRect bounds;
138 font.getBounds(&g, 1, &bounds, nullptr);
139 stemV = SkTMin(stemV, SkToS16(SkScalarRoundToInt(bounds.width())));
140 }
141 metrics->fStemV = stemV;
142 }
143 if (0 == metrics->fCapHeight) {
144 // Figure out a good guess for CapHeight: average the height of M and X.
145 SkScalar capHeight = 0;
146 for (char c : {'M', 'X'}) {
147 uint16_t g = font.unicharToGlyph(c);
148 SkRect bounds;
149 font.getBounds(&g, 1, &bounds, nullptr);
150 capHeight += bounds.height();
151 }
152 metrics->fCapHeight = SkToS16(SkScalarRoundToInt(capHeight / 2));
153 }
154 }
155 return canon->fTypefaceMetrics.set(id, std::move(metrics))->get();
156 }
157
GetUnicodeMap(const SkTypeface * typeface,SkPDFDocument * canon)158 const std::vector<SkUnichar>& SkPDFFont::GetUnicodeMap(const SkTypeface* typeface,
159 SkPDFDocument* canon) {
160 SkASSERT(typeface);
161 SkASSERT(canon);
162 SkFontID id = typeface->uniqueID();
163 if (std::vector<SkUnichar>* ptr = canon->fToUnicodeMap.find(id)) {
164 return *ptr;
165 }
166 std::vector<SkUnichar> buffer(typeface->countGlyphs());
167 typeface->getGlyphToUnicodeMap(buffer.data());
168 return *canon->fToUnicodeMap.set(id, std::move(buffer));
169 }
170
FontType(const SkAdvancedTypefaceMetrics & metrics)171 SkAdvancedTypefaceMetrics::FontType SkPDFFont::FontType(const SkAdvancedTypefaceMetrics& metrics) {
172 if (SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag) ||
173 SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag)) {
174 // force Type3 fallback.
175 return SkAdvancedTypefaceMetrics::kOther_Font;
176 }
177 return metrics.fType;
178 }
179
first_nonzero_glyph_for_single_byte_encoding(SkGlyphID gid)180 static SkGlyphID first_nonzero_glyph_for_single_byte_encoding(SkGlyphID gid) {
181 return gid != 0 ? gid - (gid - 1) % 255 : 1;
182 }
183
has_outline_glyph(SkGlyphID gid,SkStrike * cache)184 static bool has_outline_glyph(SkGlyphID gid, SkStrike* cache) {
185 const SkGlyph& glyph = cache->getGlyphIDMetrics(gid);
186 return glyph.isEmpty() || cache->findPath(glyph);
187 }
188
GetFontResource(SkPDFDocument * doc,SkStrike * cache,SkTypeface * face,SkGlyphID glyphID)189 SkPDFFont* SkPDFFont::GetFontResource(SkPDFDocument* doc,
190 SkStrike* cache,
191 SkTypeface* face,
192 SkGlyphID glyphID) {
193 SkASSERT(doc);
194 SkASSERT(face); // All SkPDFDevice::internalDrawText ensures this.
195 const SkAdvancedTypefaceMetrics* fontMetrics = SkPDFFont::GetMetrics(face, doc);
196 SkASSERT(fontMetrics); // SkPDFDevice::internalDrawText ensures the typeface is good.
197 // GetMetrics only returns null to signify a bad typeface.
198 const SkAdvancedTypefaceMetrics& metrics = *fontMetrics;
199 SkAdvancedTypefaceMetrics::FontType type = SkPDFFont::FontType(metrics);
200 if (!has_outline_glyph(glyphID, cache)) {
201 type = SkAdvancedTypefaceMetrics::kOther_Font;
202 }
203 bool multibyte = SkPDFFont::IsMultiByte(type);
204 SkGlyphID subsetCode = multibyte ? 0 : first_nonzero_glyph_for_single_byte_encoding(glyphID);
205 uint64_t fontID = (static_cast<uint64_t>(SkTypeface::UniqueID(face)) << 16) | subsetCode;
206
207 if (SkPDFFont* found = doc->fFontMap.find(fontID)) {
208 SkASSERT(multibyte == found->multiByteGlyphs());
209 return found;
210 }
211
212 sk_sp<SkTypeface> typeface(sk_ref_sp(face));
213 SkASSERT(typeface);
214
215 SkGlyphID lastGlyph = SkToU16(typeface->countGlyphs() - 1);
216
217 // should be caught by SkPDFDevice::internalDrawText
218 SkASSERT(glyphID <= lastGlyph);
219
220 SkGlyphID firstNonZeroGlyph;
221 if (multibyte) {
222 firstNonZeroGlyph = 1;
223 } else {
224 firstNonZeroGlyph = subsetCode;
225 lastGlyph = SkToU16(SkTMin<int>((int)lastGlyph, 254 + (int)subsetCode));
226 }
227 auto ref = doc->reserveRef();
228 return doc->fFontMap.set(
229 fontID, SkPDFFont(std::move(typeface), firstNonZeroGlyph, lastGlyph, type, ref));
230 }
231
SkPDFFont(sk_sp<SkTypeface> typeface,SkGlyphID firstGlyphID,SkGlyphID lastGlyphID,SkAdvancedTypefaceMetrics::FontType fontType,SkPDFIndirectReference indirectReference)232 SkPDFFont::SkPDFFont(sk_sp<SkTypeface> typeface,
233 SkGlyphID firstGlyphID,
234 SkGlyphID lastGlyphID,
235 SkAdvancedTypefaceMetrics::FontType fontType,
236 SkPDFIndirectReference indirectReference)
237 : fTypeface(std::move(typeface))
238 , fGlyphUsage(firstGlyphID, lastGlyphID)
239 , fIndirectReference(indirectReference)
240 , fFontType(fontType) {}
241
add_common_font_descriptor_entries(SkPDFDict * descriptor,const SkAdvancedTypefaceMetrics & metrics,uint16_t emSize,int16_t defaultWidth)242 static void add_common_font_descriptor_entries(SkPDFDict* descriptor,
243 const SkAdvancedTypefaceMetrics& metrics,
244 uint16_t emSize,
245 int16_t defaultWidth) {
246 descriptor->insertName("FontName", metrics.fPostScriptName);
247 descriptor->insertInt("Flags", (size_t)(metrics.fStyle | kPdfSymbolic));
248 descriptor->insertScalar("Ascent",
249 scaleFromFontUnits(metrics.fAscent, emSize));
250 descriptor->insertScalar("Descent",
251 scaleFromFontUnits(metrics.fDescent, emSize));
252 descriptor->insertScalar("StemV",
253 scaleFromFontUnits(metrics.fStemV, emSize));
254 descriptor->insertScalar("CapHeight",
255 scaleFromFontUnits(metrics.fCapHeight, emSize));
256 descriptor->insertInt("ItalicAngle", metrics.fItalicAngle);
257 descriptor->insertObject("FontBBox",
258 SkPDFMakeArray(scaleFromFontUnits(metrics.fBBox.left(), emSize),
259 scaleFromFontUnits(metrics.fBBox.bottom(), emSize),
260 scaleFromFontUnits(metrics.fBBox.right(), emSize),
261 scaleFromFontUnits(metrics.fBBox.top(), emSize)));
262 if (defaultWidth > 0) {
263 descriptor->insertScalar("MissingWidth",
264 scaleFromFontUnits(defaultWidth, emSize));
265 }
266 }
267
268 ///////////////////////////////////////////////////////////////////////////////
269 // Type0Font
270 ///////////////////////////////////////////////////////////////////////////////
271
272 // if possible, make no copy.
stream_to_data(std::unique_ptr<SkStreamAsset> stream)273 static sk_sp<SkData> stream_to_data(std::unique_ptr<SkStreamAsset> stream) {
274 SkASSERT(stream);
275 (void)stream->rewind();
276 SkASSERT(stream->hasLength());
277 size_t size = stream->getLength();
278 if (const void* base = stream->getMemoryBase()) {
279 SkData::ReleaseProc proc =
280 [](const void*, void* ctx) { delete (SkStreamAsset*)ctx; };
281 return SkData::MakeWithProc(base, size, proc, stream.release());
282 }
283 return SkData::MakeFromStream(stream.get(), size);
284 }
285
emit_subset_type0(const SkPDFFont & font,SkPDFDocument * doc)286 static void emit_subset_type0(const SkPDFFont& font, SkPDFDocument* doc) {
287 const SkAdvancedTypefaceMetrics* metricsPtr =
288 SkPDFFont::GetMetrics(font.typeface(), doc);
289 SkASSERT(metricsPtr);
290 if (!metricsPtr) { return; }
291 const SkAdvancedTypefaceMetrics& metrics = *metricsPtr;
292 SkASSERT(can_embed(metrics));
293 SkAdvancedTypefaceMetrics::FontType type = font.getType();
294 SkTypeface* face = font.typeface();
295 SkASSERT(face);
296
297 auto descriptor = SkPDFMakeDict("FontDescriptor");
298 uint16_t emSize = SkToU16(font.typeface()->getUnitsPerEm());
299 add_common_font_descriptor_entries(descriptor.get(), metrics, emSize , 0);
300
301 int ttcIndex;
302 std::unique_ptr<SkStreamAsset> fontAsset = face->openStream(&ttcIndex);
303 size_t fontSize = fontAsset ? fontAsset->getLength() : 0;
304 if (0 == fontSize) {
305 SkDebugf("Error: (SkTypeface)(%p)::openStream() returned "
306 "empty stream (%p) when identified as kType1CID_Font "
307 "or kTrueType_Font.\n", face, fontAsset.get());
308 } else {
309 switch (type) {
310 case SkAdvancedTypefaceMetrics::kTrueType_Font: {
311 if (!SkToBool(metrics.fFlags &
312 SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag)) {
313 SkASSERT(font.firstGlyphID() == 1);
314 sk_sp<SkData> subsetFontData = SkPDFSubsetFont(
315 stream_to_data(std::move(fontAsset)), font.glyphUsage(),
316 metrics.fFontName.c_str(), ttcIndex);
317 if (subsetFontData) {
318 std::unique_ptr<SkPDFDict> tmp = SkPDFMakeDict();
319 tmp->insertInt("Length1", SkToInt(subsetFontData->size()));
320 descriptor->insertRef(
321 "FontFile2",
322 SkPDFStreamOut(std::move(tmp),
323 SkMemoryStream::Make(std::move(subsetFontData)),
324 doc, true));
325 break;
326 }
327 // If subsetting fails, fall back to original font data.
328 fontAsset = face->openStream(&ttcIndex);
329 SkASSERT(fontAsset);
330 SkASSERT(fontAsset->getLength() == fontSize);
331 if (!fontAsset || fontAsset->getLength() == 0) { break; }
332 }
333 std::unique_ptr<SkPDFDict> tmp = SkPDFMakeDict();
334 tmp->insertInt("Length1", fontSize);
335 descriptor->insertRef("FontFile2",
336 SkPDFStreamOut(std::move(tmp), std::move(fontAsset),
337 doc, true));
338 break;
339 }
340 case SkAdvancedTypefaceMetrics::kType1CID_Font: {
341 std::unique_ptr<SkPDFDict> tmp = SkPDFMakeDict();
342 tmp->insertName("Subtype", "CIDFontType0C");
343 descriptor->insertRef("FontFile3",
344 SkPDFStreamOut(std::move(tmp), std::move(fontAsset),
345 doc, true));
346 break;
347 }
348 default:
349 SkASSERT(false);
350 }
351 }
352
353 auto newCIDFont = SkPDFMakeDict("Font");
354 newCIDFont->insertRef("FontDescriptor", doc->emit(*descriptor));
355 newCIDFont->insertName("BaseFont", metrics.fPostScriptName);
356
357 switch (type) {
358 case SkAdvancedTypefaceMetrics::kType1CID_Font:
359 newCIDFont->insertName("Subtype", "CIDFontType0");
360 break;
361 case SkAdvancedTypefaceMetrics::kTrueType_Font:
362 newCIDFont->insertName("Subtype", "CIDFontType2");
363 newCIDFont->insertName("CIDToGIDMap", "Identity");
364 break;
365 default:
366 SkASSERT(false);
367 }
368 auto sysInfo = SkPDFMakeDict();
369 sysInfo->insertString("Registry", "Adobe");
370 sysInfo->insertString("Ordering", "Identity");
371 sysInfo->insertInt("Supplement", 0);
372 newCIDFont->insertObject("CIDSystemInfo", std::move(sysInfo));
373
374 int16_t defaultWidth = 0;
375 {
376 int emSize;
377 auto glyphCache = SkPDFFont::MakeVectorCache(face, &emSize);
378 std::unique_ptr<SkPDFArray> widths = SkPDFMakeCIDGlyphWidthsArray(
379 glyphCache.get(), &font.glyphUsage(), SkToS16(emSize), &defaultWidth);
380 if (widths && widths->size() > 0) {
381 newCIDFont->insertObject("W", std::move(widths));
382 }
383 newCIDFont->insertScalar(
384 "DW", scaleFromFontUnits(defaultWidth, SkToS16(emSize)));
385 }
386
387 ////////////////////////////////////////////////////////////////////////////
388
389 SkPDFDict fontDict("Font");
390 fontDict.insertName("Subtype", "Type0");
391 fontDict.insertName("BaseFont", metrics.fPostScriptName);
392 fontDict.insertName("Encoding", "Identity-H");
393 auto descendantFonts = SkPDFMakeArray();
394 descendantFonts->appendRef(doc->emit(*newCIDFont));
395 fontDict.insertObject("DescendantFonts", std::move(descendantFonts));
396
397 const std::vector<SkUnichar>& glyphToUnicode =
398 SkPDFFont::GetUnicodeMap(font.typeface(), doc);
399 SkASSERT(SkToSizeT(font.typeface()->countGlyphs()) == glyphToUnicode.size());
400 std::unique_ptr<SkStreamAsset> toUnicode =
401 SkPDFMakeToUnicodeCmap(glyphToUnicode.data(),
402 &font.glyphUsage(),
403 font.multiByteGlyphs(),
404 font.firstGlyphID(),
405 font.lastGlyphID());
406 fontDict.insertRef("ToUnicode", SkPDFStreamOut(nullptr, std::move(toUnicode), doc));
407
408 doc->emit(fontDict, font.indirectReference());
409 }
410
411 ///////////////////////////////////////////////////////////////////////////////
412 // Type1Font
413 ///////////////////////////////////////////////////////////////////////////////
414
make_type1_font_descriptor(SkPDFDocument * doc,const SkTypeface * typeface,const SkAdvancedTypefaceMetrics * info)415 static SkPDFIndirectReference make_type1_font_descriptor(SkPDFDocument* doc,
416 const SkTypeface* typeface,
417 const SkAdvancedTypefaceMetrics* info) {
418 SkPDFDict descriptor("FontDescriptor");
419 uint16_t emSize = SkToU16(typeface->getUnitsPerEm());
420 if (info) {
421 add_common_font_descriptor_entries(&descriptor, *info, emSize, 0);
422 if (can_embed(*info)) {
423 int ttcIndex;
424 size_t header SK_INIT_TO_AVOID_WARNING;
425 size_t data SK_INIT_TO_AVOID_WARNING;
426 size_t trailer SK_INIT_TO_AVOID_WARNING;
427 std::unique_ptr<SkStreamAsset> rawFontData = typeface->openStream(&ttcIndex);
428 sk_sp<SkData> fontData = SkPDFConvertType1FontStream(std::move(rawFontData),
429 &header, &data, &trailer);
430 if (fontData) {
431 std::unique_ptr<SkPDFDict> dict = SkPDFMakeDict();
432 dict->insertInt("Length1", header);
433 dict->insertInt("Length2", data);
434 dict->insertInt("Length3", trailer);
435 auto fontStream = SkMemoryStream::Make(std::move(fontData));
436 descriptor.insertRef("FontFile", SkPDFStreamOut(std::move(dict),
437 std::move(fontStream), doc, true));
438 }
439 }
440 }
441 return doc->emit(descriptor);
442 }
443
444
type_1_glyphnames(SkPDFDocument * canon,const SkTypeface * typeface)445 static const std::vector<SkString>& type_1_glyphnames(SkPDFDocument* canon,
446 const SkTypeface* typeface) {
447 SkFontID fontID = typeface->uniqueID();
448 const std::vector<SkString>* glyphNames = canon->fType1GlyphNames.find(fontID);
449 if (!glyphNames) {
450 std::vector<SkString> names(typeface->countGlyphs());
451 SkPDFFont::GetType1GlyphNames(*typeface, names.data());
452 glyphNames = canon->fType1GlyphNames.set(fontID, std::move(names));
453 }
454 SkASSERT(glyphNames);
455 return *glyphNames;
456 }
457
type1_font_descriptor(SkPDFDocument * doc,const SkTypeface * typeface)458 static SkPDFIndirectReference type1_font_descriptor(SkPDFDocument* doc,
459 const SkTypeface* typeface) {
460 SkFontID fontID = typeface->uniqueID();
461 if (SkPDFIndirectReference* ptr = doc->fFontDescriptors.find(fontID)) {
462 return *ptr;
463 }
464 const SkAdvancedTypefaceMetrics* info = SkPDFFont::GetMetrics(typeface, doc);
465 auto fontDescriptor = make_type1_font_descriptor(doc, typeface, info);
466 doc->fFontDescriptors.set(fontID, fontDescriptor);
467 return fontDescriptor;
468 }
469
emit_subset_type1(const SkPDFFont & pdfFont,SkPDFDocument * doc)470 static void emit_subset_type1(const SkPDFFont& pdfFont, SkPDFDocument* doc) {
471 SkTypeface* typeface = pdfFont.typeface();
472 const std::vector<SkString> glyphNames = type_1_glyphnames(doc, typeface);
473 SkGlyphID firstGlyphID = pdfFont.firstGlyphID();
474 SkGlyphID lastGlyphID = pdfFont.lastGlyphID();
475
476 SkPDFDict font("Font");
477 font.insertRef("FontDescriptor", type1_font_descriptor(doc, typeface));
478 font.insertName("Subtype", "Type1");
479 if (const SkAdvancedTypefaceMetrics* info = SkPDFFont::GetMetrics(typeface, doc)) {
480 font.insertName("BaseFont", info->fPostScriptName);
481 }
482
483 // glyphCount not including glyph 0
484 unsigned glyphCount = 1 + lastGlyphID - firstGlyphID;
485 SkASSERT(glyphCount > 0 && glyphCount <= 255);
486 font.insertInt("FirstChar", (size_t)0);
487 font.insertInt("LastChar", (size_t)glyphCount);
488 {
489 int emSize;
490 auto glyphCache = SkPDFFont::MakeVectorCache(typeface, &emSize);
491 auto widths = SkPDFMakeArray();
492 SkScalar advance = glyphCache->getGlyphIDAdvance(0).fAdvanceX;
493 widths->appendScalar(from_font_units(advance, SkToU16(emSize)));
494 for (unsigned gID = firstGlyphID; gID <= lastGlyphID; gID++) {
495 advance = glyphCache->getGlyphIDAdvance(gID).fAdvanceX;
496 widths->appendScalar(from_font_units(advance, SkToU16(emSize)));
497 }
498 font.insertObject("Widths", std::move(widths));
499 }
500 auto encDiffs = SkPDFMakeArray();
501 encDiffs->reserve(lastGlyphID - firstGlyphID + 3);
502 encDiffs->appendInt(0);
503
504 SkASSERT(glyphNames.size() > lastGlyphID);
505 const SkString unknown("UNKNOWN");
506 encDiffs->appendName(glyphNames[0].isEmpty() ? unknown : glyphNames[0]);
507 for (int gID = firstGlyphID; gID <= lastGlyphID; gID++) {
508 encDiffs->appendName(glyphNames[gID].isEmpty() ? unknown : glyphNames[gID]);
509 }
510
511 auto encoding = SkPDFMakeDict("Encoding");
512 encoding->insertObject("Differences", std::move(encDiffs));
513 font.insertObject("Encoding", std::move(encoding));
514
515 doc->emit(font, pdfFont.indirectReference());
516 }
517
GetType1GlyphNames(const SkTypeface & face,SkString * dst)518 void SkPDFFont::GetType1GlyphNames(const SkTypeface& face, SkString* dst) {
519 face.getPostScriptGlyphNames(dst);
520 }
521
522 ///////////////////////////////////////////////////////////////////////////////
523 // PDFType3Font
524 ///////////////////////////////////////////////////////////////////////////////
525
526 namespace {
527 // returns [0, first, first+1, ... last-1, last]
528 struct SingleByteGlyphIdIterator {
SingleByteGlyphIdIterator__anon2206e5110311::SingleByteGlyphIdIterator529 SingleByteGlyphIdIterator(SkGlyphID first, SkGlyphID last)
530 : fFirst(first), fLast(last) {
531 SkASSERT(fFirst > 0);
532 SkASSERT(fLast >= first);
533 }
534 struct Iter {
operator ++__anon2206e5110311::SingleByteGlyphIdIterator::Iter535 void operator++() {
536 fCurrent = (0 == fCurrent) ? fFirst : fCurrent + 1;
537 }
538 // This is an input_iterator
operator *__anon2206e5110311::SingleByteGlyphIdIterator::Iter539 SkGlyphID operator*() const { return (SkGlyphID)fCurrent; }
operator !=__anon2206e5110311::SingleByteGlyphIdIterator::Iter540 bool operator!=(const Iter& rhs) const {
541 return fCurrent != rhs.fCurrent;
542 }
Iter__anon2206e5110311::SingleByteGlyphIdIterator::Iter543 Iter(SkGlyphID f, int c) : fFirst(f), fCurrent(c) {}
544 private:
545 const SkGlyphID fFirst;
546 int fCurrent; // must be int to make fLast+1 to fit
547 };
begin__anon2206e5110311::SingleByteGlyphIdIterator548 Iter begin() const { return Iter(fFirst, 0); }
end__anon2206e5110311::SingleByteGlyphIdIterator549 Iter end() const { return Iter(fFirst, (int)fLast + 1); }
550 private:
551 const SkGlyphID fFirst;
552 const SkGlyphID fLast;
553 };
554 }
555
556 struct ImageAndOffset {
557 sk_sp<SkImage> fImage;
558 SkIPoint fOffset;
559 };
to_image(SkGlyphID gid,SkStrike * cache)560 static ImageAndOffset to_image(SkGlyphID gid, SkStrike* cache) {
561 (void)cache->findImage(cache->getGlyphIDMetrics(gid));
562 SkMask mask;
563 cache->getGlyphIDMetrics(gid).toMask(&mask);
564 if (!mask.fImage) {
565 return {nullptr, {0, 0}};
566 }
567 SkIRect bounds = mask.fBounds;
568 SkBitmap bm;
569 switch (mask.fFormat) {
570 case SkMask::kBW_Format:
571 bm.allocPixels(SkImageInfo::MakeA8(bounds.width(), bounds.height()));
572 for (int y = 0; y < bm.height(); ++y) {
573 for (int x8 = 0; x8 < bm.width(); x8 += 8) {
574 uint8_t v = *mask.getAddr1(x8 + bounds.x(), y + bounds.y());
575 int e = SkTMin(x8 + 8, bm.width());
576 for (int x = x8; x < e; ++x) {
577 *bm.getAddr8(x, y) = (v >> (x & 0x7)) & 0x1 ? 0xFF : 0x00;
578 }
579 }
580 }
581 bm.setImmutable();
582 return {SkImage::MakeFromBitmap(bm), {bounds.x(), bounds.y()}};
583 case SkMask::kA8_Format:
584 bm.installPixels(SkImageInfo::MakeA8(bounds.width(), bounds.height()),
585 mask.fImage, mask.fRowBytes);
586 return {SkMakeImageFromRasterBitmap(bm, kAlways_SkCopyPixelsMode),
587 {bounds.x(), bounds.y()}};
588 case SkMask::kARGB32_Format:
589 bm.installPixels(SkImageInfo::MakeN32Premul(bounds.width(), bounds.height()),
590 mask.fImage, mask.fRowBytes);
591 return {SkMakeImageFromRasterBitmap(bm, kAlways_SkCopyPixelsMode),
592 {bounds.x(), bounds.y()}};
593 case SkMask::k3D_Format:
594 case SkMask::kLCD16_Format:
595 default:
596 SkASSERT(false);
597 return {nullptr, {0, 0}};
598 }
599 }
600
type3_descriptor(SkPDFDocument * doc,const SkTypeface * typeface,SkStrike * cache)601 static SkPDFIndirectReference type3_descriptor(SkPDFDocument* doc,
602 const SkTypeface* typeface,
603 SkStrike* cache) {
604 if (SkPDFIndirectReference* ptr = doc->fType3FontDescriptors.find(typeface->uniqueID())) {
605 return *ptr;
606 }
607
608 SkPDFDict descriptor("FontDescriptor");
609 int32_t fontDescriptorFlags = kPdfSymbolic;
610 if (const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, doc)) {
611 // Type3 FontDescriptor does not require all the same fields.
612 descriptor.insertName("FontName", metrics->fPostScriptName);
613 descriptor.insertInt("ItalicAngle", metrics->fItalicAngle);
614 fontDescriptorFlags |= (int32_t)metrics->fStyle;
615 // Adobe requests CapHeight, XHeight, and StemV be added
616 // to "greatly help our workflow downstream".
617 if (metrics->fCapHeight != 0) { descriptor.insertInt("CapHeight", metrics->fCapHeight); }
618 if (metrics->fStemV != 0) { descriptor.insertInt("StemV", metrics->fStemV); }
619 SkScalar xHeight = cache->getFontMetrics().fXHeight;
620 if (xHeight != 0) {
621 descriptor.insertScalar("XHeight", xHeight);
622 }
623 }
624 descriptor.insertInt("Flags", fontDescriptorFlags);
625 SkPDFIndirectReference ref = doc->emit(descriptor);
626 doc->fType3FontDescriptors.set(typeface->uniqueID(), ref);
627 return ref;
628 }
629
630
emit_subset_type3(const SkPDFFont & pdfFont,SkPDFDocument * doc)631 static void emit_subset_type3(const SkPDFFont& pdfFont, SkPDFDocument* doc) {
632 SkTypeface* typeface = pdfFont.typeface();
633 SkGlyphID firstGlyphID = pdfFont.firstGlyphID();
634 SkGlyphID lastGlyphID = pdfFont.lastGlyphID();
635 const SkPDFGlyphUse& subset = pdfFont.glyphUsage();
636 SkASSERT(lastGlyphID >= firstGlyphID);
637 // Remove unused glyphs at the end of the range.
638 // Keep the lastGlyphID >= firstGlyphID invariant true.
639 while (lastGlyphID > firstGlyphID && !subset.has(lastGlyphID)) {
640 --lastGlyphID;
641 }
642 int unitsPerEm;
643 auto cache = SkPDFFont::MakeVectorCache(typeface, &unitsPerEm);
644 SkASSERT(cache);
645 SkScalar emSize = (SkScalar)unitsPerEm;
646
647 SkPDFDict font("Font");
648 font.insertName("Subtype", "Type3");
649 // Flip about the x-axis and scale by 1/emSize.
650 SkMatrix fontMatrix;
651 fontMatrix.setScale(SkScalarInvert(emSize), -SkScalarInvert(emSize));
652 font.insertObject("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix));
653
654 auto charProcs = SkPDFMakeDict();
655 auto encoding = SkPDFMakeDict("Encoding");
656
657 auto encDiffs = SkPDFMakeArray();
658 // length(firstGlyphID .. lastGlyphID) == lastGlyphID - firstGlyphID + 1
659 // plus 1 for glyph 0;
660 SkASSERT(firstGlyphID > 0);
661 SkASSERT(lastGlyphID >= firstGlyphID);
662 int glyphCount = lastGlyphID - firstGlyphID + 2;
663 // one other entry for the index of first glyph.
664 encDiffs->reserve(glyphCount + 1);
665 encDiffs->appendInt(0); // index of first glyph
666
667 auto widthArray = SkPDFMakeArray();
668 widthArray->reserve(glyphCount);
669
670 SkIRect bbox = SkIRect::MakeEmpty();
671
672 std::vector<std::pair<SkGlyphID, SkPDFIndirectReference>> imageGlyphs;
673 for (SkGlyphID gID : SingleByteGlyphIdIterator(firstGlyphID, lastGlyphID)) {
674 bool skipGlyph = gID != 0 && !subset.has(gID);
675 SkString characterName;
676 SkScalar advance = 0.0f;
677 SkIRect glyphBBox;
678 if (skipGlyph) {
679 characterName.set("g0");
680 } else {
681 characterName.printf("g%X", gID);
682 const SkGlyph& glyph = cache->getGlyphIDMetrics(gID);
683 advance = SkFloatToScalar(glyph.fAdvanceX);
684 glyphBBox = SkIRect::MakeXYWH(glyph.fLeft, glyph.fTop,
685 glyph.fWidth, glyph.fHeight);
686 bbox.join(glyphBBox);
687 const SkPath* path = cache->findPath(glyph);
688 SkDynamicMemoryWStream content;
689 if (path && !path->isEmpty()) {
690 setGlyphWidthAndBoundingBox(SkFloatToScalar(glyph.fAdvanceX), glyphBBox, &content);
691 SkPDFUtils::EmitPath(*path, SkPaint::kFill_Style, &content);
692 SkPDFUtils::PaintPath(SkPaint::kFill_Style, path->getFillType(), &content);
693 } else {
694 auto pimg = to_image(gID, cache.get());
695 if (!pimg.fImage) {
696 setGlyphWidthAndBoundingBox(SkFloatToScalar(glyph.fAdvanceX), glyphBBox,
697 &content);
698 } else {
699 imageGlyphs.emplace_back(gID, SkPDFSerializeImage(pimg.fImage.get(), doc));
700 SkPDFUtils::AppendScalar(SkFloatToScalar(glyph.fAdvanceX), &content);
701 content.writeText(" 0 d0\n");
702 content.writeDecAsText(pimg.fImage->width());
703 content.writeText(" 0 0 ");
704 content.writeDecAsText(-pimg.fImage->height());
705 content.writeText(" ");
706 content.writeDecAsText(pimg.fOffset.x());
707 content.writeText(" ");
708 content.writeDecAsText(pimg.fImage->height() + pimg.fOffset.y());
709 content.writeText(" cm\n/X");
710 content.write(characterName.c_str(), characterName.size());
711 content.writeText(" Do\n");
712 }
713 }
714 charProcs->insertRef(characterName, SkPDFStreamOut(nullptr,
715 content.detachAsStream(), doc));
716 }
717 encDiffs->appendName(std::move(characterName));
718 widthArray->appendScalar(advance);
719 }
720
721 if (!imageGlyphs.empty()) {
722 auto d0 = SkPDFMakeDict();
723 for (const auto& pair : imageGlyphs) {
724 d0->insertRef(SkStringPrintf("Xg%X", pair.first), pair.second);
725 }
726 auto d1 = SkPDFMakeDict();
727 d1->insertObject("XObject", std::move(d0));
728 font.insertObject("Resources", std::move(d1));
729 }
730
731 encoding->insertObject("Differences", std::move(encDiffs));
732 font.insertInt("FirstChar", 0);
733 font.insertInt("LastChar", lastGlyphID - firstGlyphID + 1);
734 /* FontBBox: "A rectangle expressed in the glyph coordinate
735 system, specifying the font bounding box. This is the smallest
736 rectangle enclosing the shape that would result if all of the
737 glyphs of the font were placed with their origins coincident and
738 then filled." */
739 font.insertObject("FontBBox", SkPDFMakeArray(bbox.left(),
740 bbox.bottom(),
741 bbox.right(),
742 bbox.top()));
743
744 font.insertName("CIDToGIDMap", "Identity");
745
746 const std::vector<SkUnichar>& glyphToUnicode = SkPDFFont::GetUnicodeMap(typeface, doc);
747 SkASSERT(glyphToUnicode.size() == SkToSizeT(typeface->countGlyphs()));
748 auto toUnicodeCmap = SkPDFMakeToUnicodeCmap(glyphToUnicode.data(),
749 &subset,
750 false,
751 firstGlyphID,
752 lastGlyphID);
753 font.insertRef("ToUnicode", SkPDFStreamOut(nullptr, std::move(toUnicodeCmap), doc));
754 font.insertRef("FontDescriptor", type3_descriptor(doc, typeface, cache.get()));
755 font.insertObject("Widths", std::move(widthArray));
756 font.insertObject("Encoding", std::move(encoding));
757 font.insertObject("CharProcs", std::move(charProcs));
758
759 doc->emit(font, pdfFont.indirectReference());
760 }
761
762
emitSubset(SkPDFDocument * doc) const763 void SkPDFFont::emitSubset(SkPDFDocument* doc) const {
764 SkASSERT(fFontType != SkPDFFont().fFontType); // not default value
765 switch (fFontType) {
766 case SkAdvancedTypefaceMetrics::kType1CID_Font:
767 case SkAdvancedTypefaceMetrics::kTrueType_Font:
768 return emit_subset_type0(*this, doc);
769 case SkAdvancedTypefaceMetrics::kType1_Font:
770 return emit_subset_type1(*this, doc);
771 default:
772 return emit_subset_type3(*this, doc);
773 }
774 }
775
776 ////////////////////////////////////////////////////////////////////////////////
777
CanEmbedTypeface(SkTypeface * typeface,SkPDFDocument * doc)778 bool SkPDFFont::CanEmbedTypeface(SkTypeface* typeface, SkPDFDocument* doc) {
779 const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, doc);
780 return metrics && can_embed(*metrics);
781 }
782
783