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