xref: /aosp_15_r20/external/skia/src/pdf/SkPDFFont.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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 "src/pdf/SkPDFFont.h"
9 
10 #include "include/core/SkAlphaType.h"
11 #include "include/core/SkBitmap.h"
12 #include "include/core/SkCanvas.h"
13 #include "include/core/SkColorType.h"
14 #include "include/core/SkData.h"
15 #include "include/core/SkDrawable.h"
16 #include "include/core/SkFont.h"
17 #include "include/core/SkFontMetrics.h"
18 #include "include/core/SkFontStyle.h"
19 #include "include/core/SkFontTypes.h"
20 #include "include/core/SkImage.h"
21 #include "include/core/SkImageInfo.h"
22 #include "include/core/SkMaskFilter.h"
23 #include "include/core/SkMatrix.h"
24 #include "include/core/SkPaint.h"
25 #include "include/core/SkPath.h"
26 #include "include/core/SkPathTypes.h"
27 #include "include/core/SkPoint.h"
28 #include "include/core/SkRect.h"
29 #include "include/core/SkRefCnt.h"
30 #include "include/core/SkScalar.h"
31 #include "include/core/SkSize.h"
32 #include "include/core/SkStream.h"
33 #include "include/core/SkString.h"
34 #include "include/core/SkTypeface.h"
35 #include "include/effects/SkDashPathEffect.h"
36 #include "include/encode/SkJpegEncoder.h"
37 #include "include/private/base/SkDebug.h"
38 #include "include/private/base/SkTPin.h"
39 #include "include/private/base/SkTemplates.h"
40 #include "include/private/base/SkTo.h"
41 #include "src/base/SkBitmaskEnum.h"
42 #include "src/core/SkDescriptor.h"
43 #include "src/core/SkDevice.h"
44 #include "src/core/SkGlyph.h"
45 #include "src/core/SkMask.h"
46 #include "src/core/SkMaskFilterBase.h"
47 #include "src/core/SkPathEffectBase.h"
48 #include "src/core/SkStrike.h"
49 #include "src/core/SkStrikeSpec.h"
50 #include "src/core/SkTHash.h"
51 #include "src/pdf/SkPDFBitmap.h"
52 #include "src/pdf/SkPDFDevice.h"
53 #include "src/pdf/SkPDFDocumentPriv.h"
54 #include "src/pdf/SkPDFFormXObject.h"
55 #include "src/pdf/SkPDFGraphicState.h"
56 #include "src/pdf/SkPDFMakeCIDGlyphWidthsArray.h"
57 #include "src/pdf/SkPDFMakeToUnicodeCmap.h"
58 #include "src/pdf/SkPDFSubsetFont.h"
59 #include "src/pdf/SkPDFType1Font.h"
60 #include "src/pdf/SkPDFUtils.h"
61 
62 #include <limits.h>
63 #include <algorithm>
64 #include <cstddef>
65 #include <initializer_list>
66 #include <memory>
67 #include <utility>
68 
69 using namespace skia_private;
70 
GetType1GlyphNames(const SkTypeface & face,SkString * dst)71 void SkPDFFont::GetType1GlyphNames(const SkTypeface& face, SkString* dst) {
72     face.getPostScriptGlyphNames(dst);
73 }
74 
75 namespace {
76 // PDF's notion of symbolic vs non-symbolic is related to the character set, not
77 // symbols vs. characters.  Rarely is a font the right character set to call it
78 // non-symbolic, so always call it symbolic.  (PDF 1.4 spec, section 5.7.1)
79 static const int32_t kPdfSymbolic = 4;
80 
81 // scale from em-units to base-1000, returning as a SkScalar
from_font_units(SkScalar scaled,uint16_t emSize)82 inline SkScalar from_font_units(SkScalar scaled, uint16_t emSize) {
83     return emSize == 1000 ? scaled : scaled * 1000 / emSize;
84 }
85 
scaleFromFontUnits(int16_t val,uint16_t emSize)86 inline SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) {
87     return from_font_units(SkIntToScalar(val), emSize);
88 }
89 
setGlyphWidthAndBoundingBox(SkScalar width,SkIRect box,SkDynamicMemoryWStream * content)90 void setGlyphWidthAndBoundingBox(SkScalar width, SkIRect box,
91                                  SkDynamicMemoryWStream* content) {
92     // Specify width and bounding box for the glyph.
93     SkPDFUtils::AppendScalar(width, content);
94     content->writeText(" 0 ");
95     content->writeDecAsText(box.fLeft);
96     content->writeText(" ");
97     content->writeDecAsText(box.fTop);
98     content->writeText(" ");
99     content->writeDecAsText(box.fRight);
100     content->writeText(" ");
101     content->writeDecAsText(box.fBottom);
102     content->writeText(" d1\n");
103 }
104 
105 }  // namespace
106 
scale_paint(SkPaint & paint,SkScalar fontToEMScale)107 static bool scale_paint(SkPaint& paint, SkScalar fontToEMScale) {
108     // What we really want here is a way ask the path effect or mask filter for a scaled
109     // version of itself (if it is linearly scalable).
110 
111     if (SkMaskFilterBase* mfb = as_MFB(paint.getMaskFilter())) {
112         SkMaskFilterBase::BlurRec blurRec;
113         if (mfb->asABlur(&blurRec)) {
114             // asABlur returns false if ignoring the CTM
115             blurRec.fSigma *= fontToEMScale;
116             paint.setMaskFilter(SkMaskFilter::MakeBlur(blurRec.fStyle, blurRec.fSigma, true));
117         } else {
118             return false;
119         }
120     }
121     if (SkPathEffectBase* peb = as_PEB(paint.getPathEffect())) {
122         AutoSTMalloc<4, SkScalar> intervals;
123         SkPathEffectBase::DashInfo dashInfo(intervals, 4, 0);
124         if (peb->asADash(&dashInfo) == SkPathEffectBase::DashType::kDash) {
125             if (dashInfo.fCount > 4) {
126                 intervals.realloc(dashInfo.fCount);
127                 peb->asADash(&dashInfo);
128             }
129             for (int32_t i = 0; i < dashInfo.fCount; ++i) {
130                 dashInfo.fIntervals[i] *= fontToEMScale;
131             }
132             dashInfo.fPhase *= fontToEMScale;
133             paint.setPathEffect(
134                 SkDashPathEffect::Make(dashInfo.fIntervals, dashInfo.fCount, dashInfo.fPhase));
135         } else {
136             return false;
137         }
138     }
139 
140     if (paint.getStyle() != SkPaint::kFill_Style && paint.getStrokeWidth() > 0) {
141         paint.setStrokeMiter(paint.getStrokeMiter() * fontToEMScale);
142         paint.setStrokeWidth(paint.getStrokeWidth() * fontToEMScale);
143     }
144 
145     return true;
146 }
147 
148 
SkPDFStrikeSpec(SkStrikeSpec strikeSpec,SkScalar em)149 SkPDFStrikeSpec::SkPDFStrikeSpec(SkStrikeSpec strikeSpec, SkScalar em)
150     : fStrikeSpec(std::move(strikeSpec))
151     , fUnitsPerEM(em)
152 {}
153 
Make(SkPDFDocument * doc,const SkFont & font,const SkPaint & paint)154 sk_sp<SkPDFStrike> SkPDFStrike::Make(SkPDFDocument* doc, const SkFont& font, const SkPaint& paint) {
155 #ifdef SK_PDF_BITMAP_GLYPH_RASTER_SIZE
156     static constexpr float kBitmapFontSize = SK_PDF_BITMAP_GLYPH_RASTER_SIZE;
157 #else
158     static constexpr float kBitmapFontSize = 64;
159 #endif
160 
161     SkScalar unitsPerEm = static_cast<SkScalar>(font.getTypeface()->getUnitsPerEm());
162     SkASSERT(0 < unitsPerEm);
163 
164     SkFont canonFont(font);
165     canonFont.setBaselineSnap(false);  // canonicalize
166     canonFont.setEdging(SkFont::Edging::kAntiAlias); // canonicalize
167     canonFont.setEmbeddedBitmaps(false); // canonicalize
168     //canonFont.setEmbolden(); // applied by scaler context, sets glyph path to modified
169     canonFont.setForceAutoHinting(false); // canonicalize
170     canonFont.setHinting(SkFontHinting::kNone); // canonicalize
171     canonFont.setLinearMetrics(true); // canonicalize
172     canonFont.setScaleX(1.0f); // original value applied by SkPDFDevice
173     //canonFont.setSize(unitsPerEm);  // canonicalize below, adjusted by SkPDFDevice
174     canonFont.setSkewX(0.0f); // original value applied by SkPDFDevice
175     canonFont.setSubpixel(false); // canonicalize
176     //canonFont.setTypeface();
177 
178     SkPaint pathPaint(paint);
179     if (scale_paint(pathPaint, unitsPerEm / font.getSize())) {
180         canonFont.setSize(unitsPerEm);
181     } else {
182         canonFont.setSize(font.getSize());
183     }
184     SkScalar pathStrikeEM = canonFont.getSize();
185     SkStrikeSpec pathStrikeSpec = SkStrikeSpec::MakeWithNoDevice(canonFont, &pathPaint);
186 
187     if (sk_sp<SkPDFStrike>* strike = doc->fStrikes.find(pathStrikeSpec.descriptor())) {
188         return *strike;
189     }
190 
191     if (kBitmapFontSize <= 0) {
192         // old code path compatibility
193         sk_sp<SkPDFStrike> strike(new SkPDFStrike(SkPDFStrikeSpec(pathStrikeSpec, pathStrikeEM),
194                                                   SkPDFStrikeSpec(pathStrikeSpec, pathStrikeEM),
195                                                   pathPaint.getMaskFilter(), doc));
196         doc->fStrikes.set(strike);
197         return strike;
198     }
199 
200     SkPaint imagePaint(paint);
201     if (scale_paint(imagePaint, kBitmapFontSize / font.getSize())) {
202         canonFont.setSize(kBitmapFontSize);
203     } else {
204         canonFont.setSize(font.getSize());
205     }
206     SkScalar imageStrikeEM = canonFont.getSize();
207     SkStrikeSpec imageStrikeSpec = SkStrikeSpec::MakeWithNoDevice(canonFont, &imagePaint);
208 
209     sk_sp<SkPDFStrike> strike(new SkPDFStrike(SkPDFStrikeSpec(pathStrikeSpec, pathStrikeEM),
210                                               SkPDFStrikeSpec(imageStrikeSpec, imageStrikeEM),
211                                               pathPaint.getMaskFilter(), doc));
212     doc->fStrikes.set(strike);
213     return strike;
214 
215 }
216 
SkPDFStrike(SkPDFStrikeSpec path,SkPDFStrikeSpec image,bool hasMaskFilter,SkPDFDocument * doc)217 SkPDFStrike::SkPDFStrike(SkPDFStrikeSpec path, SkPDFStrikeSpec image, bool hasMaskFilter,
218                          SkPDFDocument* doc)
219     : fPath(std::move(path))
220     , fImage(std::move(image))
221     , fHasMaskFilter(hasMaskFilter)
222     , fDoc(doc)
223 {
224     SkASSERT(fDoc);
225 }
226 
GetKey(const sk_sp<SkPDFStrike> & strike)227 const SkDescriptor& SkPDFStrike::Traits::GetKey(const sk_sp<SkPDFStrike>& strike) {
228     return strike->fPath.fStrikeSpec.descriptor();
229 }
Hash(const SkDescriptor & descriptor)230 uint32_t SkPDFStrike::Traits::Hash(const SkDescriptor& descriptor) {
231     return descriptor.getChecksum();
232 }
233 
234 ///////////////////////////////////////////////////////////////////////////////
235 // class SkPDFFont
236 ///////////////////////////////////////////////////////////////////////////////
237 
238 /* Resources are canonicalized and uniqueified by pointer so there has to be
239  * some additional state indicating which subset of the font is used.  It
240  * must be maintained at the document granularity.
241  */
242 
243 SkPDFFont::~SkPDFFont() = default;
244 
245 SkPDFFont::SkPDFFont(SkPDFFont&&) = default;
246 
can_embed(const SkAdvancedTypefaceMetrics & metrics)247 static bool can_embed(const SkAdvancedTypefaceMetrics& metrics) {
248     return !SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag);
249 }
250 
can_subset(const SkAdvancedTypefaceMetrics & metrics)251 static bool can_subset(const SkAdvancedTypefaceMetrics& metrics) {
252     return !SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag);
253 }
254 
GetMetrics(const SkTypeface & typeface,SkPDFDocument * canon)255 const SkAdvancedTypefaceMetrics* SkPDFFont::GetMetrics(const SkTypeface& typeface,
256                                                        SkPDFDocument* canon) {
257     SkTypefaceID id = typeface.uniqueID();
258     if (std::unique_ptr<SkAdvancedTypefaceMetrics>* ptr = canon->fTypefaceMetrics.find(id)) {
259         return ptr->get();  // canon retains ownership.
260     }
261 
262     int count = typeface.countGlyphs();
263     if (count <= 0 || count > 1 + SkTo<int>(UINT16_MAX)) {
264         // Cache nullptr to skip this check.  Use SkSafeUnref().
265         canon->fTypefaceMetrics.set(id, nullptr);
266         return nullptr;
267     }
268 
269     std::unique_ptr<SkAdvancedTypefaceMetrics> metrics = typeface.getAdvancedMetrics();
270     if (!metrics) {
271         metrics = std::make_unique<SkAdvancedTypefaceMetrics>();
272     }
273     if (0 == metrics->fStemV || 0 == metrics->fCapHeight) {
274         SkFont font;
275         font.setHinting(SkFontHinting::kNone);
276         font.setTypeface(sk_ref_sp(&typeface));
277         font.setSize(1000);  // glyph coordinate system
278         if (0 == metrics->fStemV) {
279             // Figure out a good guess for StemV - Min width of i, I, !, 1.
280             // This probably isn't very good with an italic font.
281             int16_t stemV = SHRT_MAX;
282             for (char c : {'i', 'I', '!', '1'}) {
283                 uint16_t g = font.unicharToGlyph(c);
284                 SkRect bounds;
285                 font.getBounds(&g, 1, &bounds, nullptr);
286                 stemV = std::min(stemV, SkToS16(SkScalarRoundToInt(bounds.width())));
287             }
288             metrics->fStemV = stemV;
289         }
290         if (0 == metrics->fCapHeight) {
291             // Figure out a good guess for CapHeight: average the height of M and X.
292             SkScalar capHeight = 0;
293             for (char c : {'M', 'X'}) {
294                 uint16_t g = font.unicharToGlyph(c);
295                 SkRect bounds;
296                 font.getBounds(&g, 1, &bounds, nullptr);
297                 capHeight += bounds.height();
298             }
299             metrics->fCapHeight = SkToS16(SkScalarRoundToInt(capHeight / 2));
300         }
301     }
302     // Fonts are always subset, so always prepend the subset tag.
303     metrics->fPostScriptName.prepend(canon->nextFontSubsetTag());
304     return canon->fTypefaceMetrics.set(id, std::move(metrics))->get();
305 }
306 
GetUnicodeMap(const SkTypeface & typeface,SkPDFDocument * canon)307 const std::vector<SkUnichar>& SkPDFFont::GetUnicodeMap(const SkTypeface& typeface,
308                                                        SkPDFDocument* canon) {
309     SkASSERT(canon);
310     SkTypefaceID id = typeface.uniqueID();
311     if (std::vector<SkUnichar>* ptr = canon->fToUnicodeMap.find(id)) {
312         return *ptr;
313     }
314     std::vector<SkUnichar> buffer(typeface.countGlyphs());
315     typeface.getGlyphToUnicodeMap(buffer.data());
316     return *canon->fToUnicodeMap.set(id, std::move(buffer));
317 }
318 
GetUnicodeMapEx(const SkTypeface & typeface,SkPDFDocument * canon)319 THashMap<SkGlyphID, SkString>& SkPDFFont::GetUnicodeMapEx(const SkTypeface& typeface,
320                                                           SkPDFDocument* canon) {
321     SkASSERT(canon);
322     SkTypefaceID id = typeface.uniqueID();
323     if (THashMap<SkGlyphID, SkString>* ptr = canon->fToUnicodeMapEx.find(id)) {
324         return *ptr;
325     }
326     return *canon->fToUnicodeMapEx.set(id, THashMap<SkGlyphID, SkString>());
327 }
328 
FontType(const SkPDFStrike & pdfStrike,const SkAdvancedTypefaceMetrics & metrics)329 SkAdvancedTypefaceMetrics::FontType SkPDFFont::FontType(const SkPDFStrike& pdfStrike,
330                                                         const SkAdvancedTypefaceMetrics& metrics) {
331     if (SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kVariable_FontFlag) ||
332         // PDF is actually interested in the encoding of the data, not just the logical format.
333         // If the TrueType is actually wOFF or wOF2 then it should not be directly embedded in PDF.
334         // For now export these as Type3 until the subsetter can handle table based fonts.
335         // See https://github.com/harfbuzz/harfbuzz/issues/3609 and
336         // https://skia-review.googlesource.com/c/skia/+/543485
337         SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kAltDataFormat_FontFlag) ||
338         SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag) ||
339         // Something like 45eeeddb00741493 and 7c86e7641b348ca7b0 to output OpenType should work,
340         // but requires PDF 1.6 which is still not supported by all printers. One could fix this by
341         // using bare CFF like 31a170226c22244cbd00497b67f6ae181f0f3e76 which is only PDF 1.3,
342         // but this only works when the CFF CIDs == CFF index == GlyphID as PDF bare CFF prefers
343         // CFF CIDs instead of GlyphIDs and Skia doesn't know the CIDs.
344         metrics.fType == SkAdvancedTypefaceMetrics::kCFF_Font ||
345         pdfStrike.fHasMaskFilter)
346     {
347         // force Type3 fallback.
348         return SkAdvancedTypefaceMetrics::kOther_Font;
349     }
350     return metrics.fType;
351 }
352 
first_nonzero_glyph_for_single_byte_encoding(SkGlyphID gid)353 static SkGlyphID first_nonzero_glyph_for_single_byte_encoding(SkGlyphID gid) {
354     return gid != 0 ? gid - (gid - 1) % 255 : 1;
355 }
356 
getFontResource(const SkGlyph * glyph)357 SkPDFFont* SkPDFStrike::getFontResource(const SkGlyph* glyph) {
358     const SkTypeface& typeface = fPath.fStrikeSpec.typeface();
359     const SkAdvancedTypefaceMetrics* fontMetrics = SkPDFFont::GetMetrics(typeface, fDoc);
360     SkASSERT(fontMetrics);  // SkPDFDevice::internalDrawText ensures the typeface is good.
361                             // GetMetrics only returns null to signify a bad typeface.
362     const SkAdvancedTypefaceMetrics& metrics = *fontMetrics;
363 
364     // Determine the FontType.
365     // 1. Can the "original" font data be used directly
366     // (simple OpenType, no non-default variations, not WOFF, etc).
367     // 2. Is the glyph to be drawn unmodified from the font data
368     // (no path effect, stroking, fake bolding, extra matrix, mask filter).
369     // 3. Will PDF viewers draw this glyph the way we want
370     // (at the moment this means an unmodified glyph path).
371     SkAdvancedTypefaceMetrics::FontType type = SkPDFFont::FontType(*this, metrics);
372     // Keep the type (and original data) if the glyph is empty or the glyph has an unmodified path.
373     // Otherwise, fall back to Type3.
374     if (!(glyph->isEmpty() || (glyph->path() && !glyph->pathIsModified()))) {
375         type = SkAdvancedTypefaceMetrics::kOther_Font;
376     }
377 
378     bool multibyte = SkPDFFont::IsMultiByte(type);
379     SkGlyphID subsetCode =
380             multibyte ? 0 : first_nonzero_glyph_for_single_byte_encoding(glyph->getGlyphID());
381     if (SkPDFFont* font = fFontMap.find(subsetCode)) {
382         SkASSERT(multibyte == font->multiByteGlyphs());
383         return font;
384     }
385 
386     SkGlyphID lastGlyph = SkToU16(typeface.countGlyphs() - 1);
387     SkASSERT(glyph->getGlyphID() <= lastGlyph); // should be caught by SkPDFDevice::internalDrawText
388 
389     SkGlyphID firstNonZeroGlyph;
390     if (multibyte) {
391         firstNonZeroGlyph = 1;
392     } else {
393         firstNonZeroGlyph = subsetCode;
394         lastGlyph = SkToU16(std::min<int>((int)lastGlyph, 254 + (int)subsetCode));
395     }
396     auto ref = fDoc->reserveRef();
397     return fFontMap.set(subsetCode, SkPDFFont(this, firstNonZeroGlyph, lastGlyph, type, ref));
398 }
399 
SkPDFFont(const SkPDFStrike * strike,SkGlyphID firstGlyphID,SkGlyphID lastGlyphID,SkAdvancedTypefaceMetrics::FontType fontType,SkPDFIndirectReference indirectReference)400 SkPDFFont::SkPDFFont(const SkPDFStrike* strike,
401                      SkGlyphID firstGlyphID,
402                      SkGlyphID lastGlyphID,
403                      SkAdvancedTypefaceMetrics::FontType fontType,
404                      SkPDFIndirectReference indirectReference)
405     : fStrike(strike)
406     , fGlyphUsage(firstGlyphID, lastGlyphID)
407     , fIndirectReference(indirectReference)
408     , fFontType(fontType)
409 {
410     // Always include glyph 0
411     this->noteGlyphUsage(0);
412 }
413 
PopulateCommonFontDescriptor(SkPDFDict * descriptor,const SkAdvancedTypefaceMetrics & metrics,uint16_t emSize,int16_t defaultWidth)414 void SkPDFFont::PopulateCommonFontDescriptor(SkPDFDict* descriptor,
415                                              const SkAdvancedTypefaceMetrics& metrics,
416                                              uint16_t emSize,
417                                              int16_t defaultWidth) {
418     descriptor->insertName("FontName", metrics.fPostScriptName);
419     descriptor->insertInt("Flags", (size_t)(metrics.fStyle | kPdfSymbolic));
420     descriptor->insertScalar("Ascent",
421             scaleFromFontUnits(metrics.fAscent, emSize));
422     descriptor->insertScalar("Descent",
423             scaleFromFontUnits(metrics.fDescent, emSize));
424     descriptor->insertScalar("StemV",
425             scaleFromFontUnits(metrics.fStemV, emSize));
426     descriptor->insertScalar("CapHeight",
427             scaleFromFontUnits(metrics.fCapHeight, emSize));
428     descriptor->insertInt("ItalicAngle", metrics.fItalicAngle);
429     descriptor->insertObject("FontBBox",
430                              SkPDFMakeArray(scaleFromFontUnits(metrics.fBBox.left(), emSize),
431                                             scaleFromFontUnits(metrics.fBBox.bottom(), emSize),
432                                             scaleFromFontUnits(metrics.fBBox.right(), emSize),
433                                             scaleFromFontUnits(metrics.fBBox.top(), emSize)));
434     if (defaultWidth > 0) {
435         descriptor->insertScalar("MissingWidth",
436                 scaleFromFontUnits(defaultWidth, emSize));
437     }
438 }
439 
440 ///////////////////////////////////////////////////////////////////////////////
441 //  Type0Font
442 ///////////////////////////////////////////////////////////////////////////////
443 
emit_subset_type0(const SkPDFFont & font,SkPDFDocument * doc)444 static void emit_subset_type0(const SkPDFFont& font, SkPDFDocument* doc) {
445     const SkTypeface& typeface = font.strike().fPath.fStrikeSpec.typeface();
446     const SkAdvancedTypefaceMetrics* metricsPtr = SkPDFFont::GetMetrics(typeface, doc);
447     SkASSERT(metricsPtr);
448     if (!metricsPtr) {
449         return;
450     }
451     const SkAdvancedTypefaceMetrics& metrics = *metricsPtr;
452     SkASSERT(can_embed(metrics));
453     SkAdvancedTypefaceMetrics::FontType type = font.getType();
454 
455     auto descriptor = SkPDFMakeDict("FontDescriptor");
456     uint16_t emSize = SkToU16(SkScalarRoundToInt(font.strike().fPath.fUnitsPerEM));
457     SkPDFFont::PopulateCommonFontDescriptor(descriptor.get(), metrics, emSize, 0);
458 
459     int ttcIndex;
460     std::unique_ptr<SkStreamAsset> fontAsset = typeface.openStream(&ttcIndex);
461     size_t fontSize = fontAsset ? fontAsset->getLength() : 0;
462     if (0 == fontSize) {
463         SkDebugf("Error: (SkTypeface)(%p)::openStream() returned "
464                  "empty stream (%p) when identified as kType1CID_Font "
465                  "or kTrueType_Font.\n", &typeface, fontAsset.get());
466     } else if (type == SkAdvancedTypefaceMetrics::kTrueType_Font) {
467         sk_sp<SkData> subsetFontData;
468         if (can_subset(metrics)) {
469             SkASSERT(font.firstGlyphID() == 1);
470             subsetFontData = SkPDFSubsetFont(typeface, font.glyphUsage());
471         }
472         std::unique_ptr<SkStreamAsset> subsetFontAsset;
473         if (subsetFontData) {
474             subsetFontAsset = SkMemoryStream::Make(std::move(subsetFontData));
475         } else {
476             // If subsetting fails, fall back to original font data.
477             subsetFontAsset = std::move(fontAsset);
478         }
479         std::unique_ptr<SkPDFDict> streamDict = SkPDFMakeDict();
480         streamDict->insertInt("Length1", subsetFontAsset->getLength());
481         descriptor->insertRef("FontFile2",
482                               SkPDFStreamOut(std::move(streamDict), std::move(subsetFontAsset),
483                                              doc, SkPDFSteamCompressionEnabled::Yes));
484     } else if (type == SkAdvancedTypefaceMetrics::kType1CID_Font) {
485         std::unique_ptr<SkPDFDict> streamDict = SkPDFMakeDict();
486         streamDict->insertName("Subtype", "CIDFontType0C");
487         descriptor->insertRef("FontFile3",
488                               SkPDFStreamOut(std::move(streamDict), std::move(fontAsset),
489                                              doc, SkPDFSteamCompressionEnabled::Yes));
490     } else {
491         SkASSERT(false);
492     }
493 
494     auto newCIDFont = SkPDFMakeDict("Font");
495     newCIDFont->insertRef("FontDescriptor", doc->emit(*descriptor));
496     newCIDFont->insertName("BaseFont", metrics.fPostScriptName);
497 
498     switch (type) {
499         case SkAdvancedTypefaceMetrics::kType1CID_Font:
500             newCIDFont->insertName("Subtype", "CIDFontType0");
501             break;
502         case SkAdvancedTypefaceMetrics::kTrueType_Font:
503             newCIDFont->insertName("Subtype", "CIDFontType2");
504             newCIDFont->insertName("CIDToGIDMap", "Identity");
505             break;
506         default:
507             SkASSERT(false);
508     }
509     auto sysInfo = SkPDFMakeDict();
510     // These are actually ASCII strings.
511     sysInfo->insertByteString("Registry", "Adobe");
512     sysInfo->insertByteString("Ordering", "Identity");
513     sysInfo->insertInt("Supplement", 0);
514     newCIDFont->insertObject("CIDSystemInfo", std::move(sysInfo));
515 
516     // Unfortunately, poppler enforces DW (default width) must be an integer.
517     int32_t defaultWidth = 0;
518     {
519         std::unique_ptr<SkPDFArray> widths = SkPDFMakeCIDGlyphWidthsArray(
520                 font.strike().fPath, font.glyphUsage(), &defaultWidth);
521         if (widths && widths->size() > 0) {
522             newCIDFont->insertObject("W", std::move(widths));
523         }
524         newCIDFont->insertInt("DW", defaultWidth);
525     }
526 
527     ////////////////////////////////////////////////////////////////////////////
528 
529     SkPDFDict fontDict("Font");
530     fontDict.insertName("Subtype", "Type0");
531     fontDict.insertName("BaseFont", metrics.fPostScriptName);
532     fontDict.insertName("Encoding", "Identity-H");
533     auto descendantFonts = SkPDFMakeArray();
534     descendantFonts->appendRef(doc->emit(*newCIDFont));
535     fontDict.insertObject("DescendantFonts", std::move(descendantFonts));
536 
537     const std::vector<SkUnichar>& glyphToUnicode =
538         SkPDFFont::GetUnicodeMap(typeface, doc);
539     SkASSERT(SkToSizeT(typeface.countGlyphs()) == glyphToUnicode.size());
540     std::unique_ptr<SkStreamAsset> toUnicode =
541             SkPDFMakeToUnicodeCmap(glyphToUnicode.data(),
542                                    SkPDFFont::GetUnicodeMapEx(typeface, doc),
543                                    &font.glyphUsage(),
544                                    font.multiByteGlyphs(),
545                                    font.firstGlyphID(),
546                                    font.lastGlyphID());
547     fontDict.insertRef("ToUnicode", SkPDFStreamOut(nullptr, std::move(toUnicode), doc));
548 
549     doc->emit(fontDict, font.indirectReference());
550 }
551 
552 ///////////////////////////////////////////////////////////////////////////////
553 // PDFType3Font
554 ///////////////////////////////////////////////////////////////////////////////
555 
556 namespace {
557 // returns [0, first, first+1, ... last-1,  last]
558 struct SingleByteGlyphIdIterator {
SingleByteGlyphIdIterator__anon63c3b1de0211::SingleByteGlyphIdIterator559     SingleByteGlyphIdIterator(SkGlyphID first, SkGlyphID last)
560         : fFirst(first), fLast(last) {
561         SkASSERT(fFirst > 0);
562         SkASSERT(fLast >= first);
563     }
564     struct Iter {
operator ++__anon63c3b1de0211::SingleByteGlyphIdIterator::Iter565         void operator++() {
566             fCurrent = (0 == fCurrent) ? fFirst : fCurrent + 1;
567         }
568         // This is an input_iterator
operator *__anon63c3b1de0211::SingleByteGlyphIdIterator::Iter569         SkGlyphID operator*() const { return (SkGlyphID)fCurrent; }
operator !=__anon63c3b1de0211::SingleByteGlyphIdIterator::Iter570         bool operator!=(const Iter& rhs) const {
571             return fCurrent != rhs.fCurrent;
572         }
Iter__anon63c3b1de0211::SingleByteGlyphIdIterator::Iter573         Iter(SkGlyphID f, int c) : fFirst(f), fCurrent(c) {}
574     private:
575         const SkGlyphID fFirst;
576         int fCurrent; // must be int to make fLast+1 to fit
577     };
begin__anon63c3b1de0211::SingleByteGlyphIdIterator578     Iter begin() const { return Iter(fFirst, 0); }
end__anon63c3b1de0211::SingleByteGlyphIdIterator579     Iter end() const { return Iter(fFirst, (int)fLast + 1); }
580 private:
581     const SkGlyphID fFirst;
582     const SkGlyphID fLast;
583 };
584 }  // namespace
585 
586 struct ImageAndOffset {
587     sk_sp<SkImage> fImage;
588     SkIPoint fOffset;
589 };
to_image(SkGlyphID gid,SkBulkGlyphMetricsAndImages * smallGlyphs)590 static ImageAndOffset to_image(SkGlyphID gid, SkBulkGlyphMetricsAndImages* smallGlyphs) {
591     const SkGlyph* glyph = smallGlyphs->glyph(SkPackedGlyphID{gid});
592     SkMask mask = glyph->mask();
593     if (!mask.fImage) {
594         return {nullptr, {0, 0}};
595     }
596     SkIRect bounds = mask.fBounds;
597     SkBitmap bm;
598     switch (mask.fFormat) {
599         case SkMask::kBW_Format: {
600             // Make a gray image, used to smask a rectangle.
601             // TODO: emit as MaskImage?
602             const SkISize size = bounds.size();
603             bm.allocPixels(SkImageInfo::Make(size, kGray_8_SkColorType, kUnknown_SkAlphaType));
604             for (int y = 0; y < bm.height(); ++y) {
605                 for (int x8 = 0; x8 < bm.width(); x8 += 8) {
606                     uint8_t v = *mask.getAddr1(x8 + bounds.x(), y + bounds.y());
607                     int e = std::min(x8 + 8, bm.width());
608                     for (int x = x8; x < e; ++x) {
609                         *bm.getAddr8(x, y) = (v >> (x & 0x7)) & 0x1 ? 0xFF : 0x00;
610                     }
611                 }
612             }
613             bm.setImmutable();
614             return {bm.asImage(), {bounds.x(), bounds.y()}};
615         }
616         case SkMask::kA8_Format:
617         case SkMask::k3D_Format:  // just do the A8 part
618             // Make a gray image, used to smask a rectangle.
619             return {SkImages::RasterFromData(
620                         SkImageInfo::Make(bounds.size(), kGray_8_SkColorType, kUnknown_SkAlphaType),
621                         SkData::MakeWithCopy(mask.fImage, mask.computeImageSize()),
622                         mask.fRowBytes),
623                     {bounds.x(), bounds.y()}};
624         case SkMask::kARGB32_Format:
625             // These will be drawn as images directly.
626             return {SkImages::RasterFromData(
627                         SkImageInfo::MakeN32Premul(bounds.size()),
628                         SkData::MakeWithCopy(mask.fImage, mask.computeTotalImageSize()),
629                         mask.fRowBytes),
630                     {bounds.x(), bounds.y()}};
631         case SkMask::kLCD16_Format:
632         default:
633             SkASSERT(false);
634             return {nullptr, {0, 0}};
635     }
636 }
637 
type3_descriptor(SkPDFDocument * doc,const SkTypeface & typeface,SkScalar xHeight)638 static SkPDFIndirectReference type3_descriptor(SkPDFDocument* doc,
639                                                const SkTypeface& typeface,
640                                                SkScalar xHeight) {
641     if (SkPDFIndirectReference* ptr = doc->fType3FontDescriptors.find(typeface.uniqueID())) {
642         return *ptr;
643     }
644 
645     SkPDFDict descriptor("FontDescriptor");
646     int32_t fontDescriptorFlags = kPdfSymbolic;
647 
648     /** PDF32000_2008: FontFamily should be used for Type3 fonts in Tagged PDF documents. */
649     SkString familyName;
650     typeface.getFamilyName(&familyName);
651     if (!familyName.isEmpty()) {
652         descriptor.insertByteString("FontFamily", familyName);
653     }
654 
655     /** PDF32000_2008: FontStretch should be used for Type3 fonts in Tagged PDF documents. */
656     static constexpr const char* stretchNames[9] = {
657         "UltraCondensed",
658         "ExtraCondensed",
659         "Condensed",
660         "SemiCondensed",
661         "Normal",
662         "SemiExpanded",
663         "Expanded",
664         "ExtraExpanded",
665         "UltraExpanded",
666     };
667     const char* stretchName = stretchNames[typeface.fontStyle().width() - 1];
668     descriptor.insertName("FontStretch", stretchName);
669 
670     /** PDF32000_2008: FontWeight should be used for Type3 fonts in Tagged PDF documents. */
671     int weight = (typeface.fontStyle().weight() + 50) / 100;
672     descriptor.insertInt("FontWeight", SkTPin(weight, 1, 9) * 100);
673 
674     if (const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, doc)) {
675         // Type3 FontDescriptor does not require all the same fields.
676         descriptor.insertName("FontName", metrics->fPostScriptName);
677         descriptor.insertInt("ItalicAngle", metrics->fItalicAngle);
678         fontDescriptorFlags |= (int32_t)metrics->fStyle;
679         // Adobe requests CapHeight, XHeight, and StemV be added
680         // to "greatly help our workflow downstream".
681         if (metrics->fCapHeight != 0) { descriptor.insertInt("CapHeight", metrics->fCapHeight); }
682         if (metrics->fStemV     != 0) { descriptor.insertInt("StemV",     metrics->fStemV);     }
683         if (xHeight != 0) {
684             descriptor.insertScalar("XHeight", xHeight);
685         }
686     }
687     descriptor.insertInt("Flags", fontDescriptorFlags);
688     SkPDFIndirectReference ref = doc->emit(descriptor);
689     doc->fType3FontDescriptors.set(typeface.uniqueID(), ref);
690     return ref;
691 }
692 
emit_subset_type3(const SkPDFFont & pdfFont,SkPDFDocument * doc)693 static void emit_subset_type3(const SkPDFFont& pdfFont, SkPDFDocument* doc) {
694     const SkPDFStrike& pdfStrike = pdfFont.strike();
695     SkGlyphID firstGlyphID = pdfFont.firstGlyphID();
696     SkGlyphID lastGlyphID = pdfFont.lastGlyphID();
697     const SkPDFGlyphUse& subset = pdfFont.glyphUsage();
698     SkASSERT(lastGlyphID >= firstGlyphID);
699     // Remove unused glyphs at the end of the range.
700     // Keep the lastGlyphID >= firstGlyphID invariant true.
701     while (lastGlyphID > firstGlyphID && !subset.has(lastGlyphID)) {
702         --lastGlyphID;
703     }
704     SkScalar emSize = pdfStrike.fPath.fUnitsPerEM;
705     sk_sp<SkStrike> strike = pdfStrike.fPath.fStrikeSpec.findOrCreateStrike();
706     SkASSERT(strike);
707     SkScalar xHeight = strike->getFontMetrics().fXHeight;
708     SkBulkGlyphMetricsAndPaths metricsAndPaths((sk_sp<SkStrike>(strike)));
709     SkBulkGlyphMetricsAndDrawables metricsAndDrawables(std::move(strike));
710 
711     SkBulkGlyphMetricsAndImages smallGlyphs(pdfFont.strike().fImage.fStrikeSpec);
712     float bitmapScale = emSize / pdfStrike.fImage.fUnitsPerEM;
713 
714     SkPDFDict font("Font");
715     font.insertName("Subtype", "Type3");
716     // Flip about the x-axis and scale by 1/emSize.
717     SkMatrix fontMatrix;
718     fontMatrix.setScale(SkScalarInvert(emSize), -SkScalarInvert(emSize));
719     font.insertObject("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix));
720 
721     auto charProcs = SkPDFMakeDict();
722     auto encoding = SkPDFMakeDict("Encoding");
723 
724     auto encDiffs = SkPDFMakeArray();
725     // length(firstGlyphID .. lastGlyphID) ==  lastGlyphID - firstGlyphID + 1
726     // plus 1 for glyph 0;
727     SkASSERT(firstGlyphID > 0);
728     SkASSERT(lastGlyphID >= firstGlyphID);
729     int glyphCount = lastGlyphID - firstGlyphID + 2;
730     // one other entry for the index of first glyph.
731     encDiffs->reserve(glyphCount + 1);
732     encDiffs->appendInt(0);  // index of first glyph
733 
734     auto widthArray = SkPDFMakeArray();
735     widthArray->reserve(glyphCount);
736 
737     SkIRect bbox = SkIRect::MakeEmpty();
738 
739     std::unique_ptr<SkPDFDict> xobjects = SkPDFMakeDict();
740     std::unique_ptr<SkPDFDict> graphicStates = SkPDFMakeDict();
741     for (SkGlyphID gID : SingleByteGlyphIdIterator(firstGlyphID, lastGlyphID)) {
742         SkString characterName;
743         SkScalar advance = 0.0f;
744 
745         if (gID != 0 && !subset.has(gID)) {
746             characterName.set("g0");
747             advance = 0.0f;
748             encDiffs->appendName(std::move(characterName));
749             widthArray->appendScalar(advance);
750             continue;
751         }
752 
753         const SkGlyph* pathGlyph = metricsAndPaths.glyph(gID);
754         const SkGlyph* drawableGlyph = metricsAndDrawables.glyph(gID);
755 
756         characterName.printf("g%X", gID);
757         advance = pathGlyph->advanceX();
758         encDiffs->appendName(characterName);
759         widthArray->appendScalar(advance);
760 
761         SkIRect glyphBBox = pathGlyph->iRect();
762         bbox.join(glyphBBox);
763         const SkPath* path = pathGlyph->path();
764         SkDrawable* drawable = drawableGlyph->drawable();
765         SkDynamicMemoryWStream content;
766         if (drawable && !drawable->getBounds().isEmpty()) {
767             sk_sp<SkPDFDevice> glyphDevice = sk_make_sp<SkPDFDevice>(glyphBBox.size(), doc);
768             SkCanvas canvas(glyphDevice);
769             canvas.translate(-glyphBBox.fLeft, -glyphBBox.fTop);
770             canvas.drawDrawable(drawable);
771             SkPDFIndirectReference xobject = SkPDFMakeFormXObject(
772                     doc, glyphDevice->content(),
773                     SkPDFMakeArray(0, 0, glyphBBox.width(), glyphBBox.height()),
774                     glyphDevice->makeResourceDict(),
775                     SkMatrix::Translate(glyphBBox.fLeft, glyphBBox.fTop), nullptr);
776             xobjects->insertRef(SkStringPrintf("Xg%X", gID), xobject);
777             SkPDFUtils::AppendScalar(drawableGlyph->advanceX(), &content);
778             content.writeText(" 0 d0\n1 0 0 1 0 0 cm\n/X");
779             content.write(characterName.c_str(), characterName.size());
780             content.writeText(" Do\n");
781         } else if (path && !path->isEmpty() && !pdfStrike.fHasMaskFilter) {
782             setGlyphWidthAndBoundingBox(pathGlyph->advanceX(), glyphBBox, &content);
783             SkPaint::Style style = pathGlyph->pathIsHairline() ? SkPaint::kStroke_Style
784                                                                : SkPaint::kFill_Style;
785             SkPDFUtils::EmitPath(*path, style, &content);
786             SkPDFUtils::PaintPath(style, path->getFillType(), &content);
787         } else if (auto pimg = to_image(gID, &smallGlyphs); pimg.fImage) {
788             using SkPDFUtils::AppendScalar;
789             if (pimg.fImage->colorType() != kGray_8_SkColorType) {
790                 AppendScalar(pathGlyph->advanceX(), &content);
791                 content.writeText(" 0 d0\n");
792                 AppendScalar(pimg.fImage->width() * bitmapScale, &content);
793                 content.writeText(" 0 0 ");
794                 AppendScalar(-pimg.fImage->height() * bitmapScale, &content);
795                 content.writeText(" ");
796                 AppendScalar(pimg.fOffset.x() * bitmapScale, &content);
797                 content.writeText(" ");
798                 AppendScalar((pimg.fImage->height() + pimg.fOffset.y()) * bitmapScale,&content);
799                 content.writeText(" cm\n");
800                 content.writeText("/X");
801                 content.write(characterName.c_str(), characterName.size());
802                 content.writeText(" Do\n");
803                 SkPDFIndirectReference image = SkPDFSerializeImage(pimg.fImage.get(), doc);
804                 xobjects->insertRef(SkStringPrintf("Xg%X", gID), image);
805             } else {
806                 // TODO: For A1, put ImageMask on the PDF image and draw the image?
807                 // The A8 mask has been converted to a Gray image
808 
809                 // This is a `d1` glyph (shaded with the current fill)
810                 const SkGlyph* smallGlyph = smallGlyphs.glyph(SkPackedGlyphID{gID});
811                 SkRect smallBBox = smallGlyph->rect();
812                 SkIRect smallIBox;
813                 SkMatrix::Scale(bitmapScale, bitmapScale).mapRect(smallBBox).roundOut(&smallIBox);
814                 bbox.join(smallIBox);
815                 setGlyphWidthAndBoundingBox(pathGlyph->advanceX(), smallIBox, &content);
816 
817                 AppendScalar(bitmapScale, &content);
818                 content.writeText(" 0 0 ");
819                 AppendScalar(bitmapScale, &content);
820                 content.writeText(" ");
821                 AppendScalar(pimg.fOffset.x() * bitmapScale, &content);
822                 content.writeText(" ");
823                 AppendScalar(pimg.fOffset.y() * bitmapScale, &content);
824                 content.writeText(" cm\n");
825 
826                 // Convert Gray image to jpeg if needed
827                 if (pdfStrike.fHasMaskFilter) {
828                     SkJpegEncoder::Options jpegOptions;
829                     jpegOptions.fQuality = 50; // SK_PDF_MASK_QUALITY
830                     SkImage* image = pimg.fImage.get();
831                     sk_sp<SkData> jpegData = SkJpegEncoder::Encode(nullptr, image, jpegOptions);
832                     if (jpegData) {
833                         sk_sp<SkImage> jpegImage = SkImages::DeferredFromEncodedData(jpegData);
834                         SkASSERT(jpegImage);
835                         if (jpegImage) {
836                             pimg.fImage = jpegImage;
837                         }
838                     }
839                 }
840 
841                 // Draw image into a Form XObject
842                 const SkISize imageSize = pimg.fImage->dimensions();
843                 sk_sp<SkPDFDevice> glyphDevice = sk_sp(new SkPDFDevice(imageSize, doc));
844                 SkCanvas canvas(glyphDevice);
845                 canvas.drawImage(pimg.fImage, 0, 0);
846                 SkPDFIndirectReference sMask = SkPDFMakeFormXObject(
847                         doc, glyphDevice->content(),
848                         SkPDFMakeArray(0, 0, pimg.fImage->width(), pimg.fImage->height()),
849                         glyphDevice->makeResourceDict(),
850                         SkMatrix(), "DeviceGray");
851 
852                 // Use Form XObject as SMask (luminosity) on the graphics state
853                 SkPDFIndirectReference smaskGraphicState = SkPDFGraphicState::GetSMaskGraphicState(
854                         sMask, false,
855                         SkPDFGraphicState::kLuminosity_SMaskMode, doc);
856                 SkPDFUtils::ApplyGraphicState(smaskGraphicState.fValue, &content);
857 
858                 // Draw a rectangle the size of the glyph (masked by SMask)
859                 SkPDFUtils::AppendRectangle(SkRect::Make(pimg.fImage->bounds()), &content);
860                 SkPDFUtils::PaintPath(SkPaint::kFill_Style, SkPathFillType::kWinding, &content);
861 
862                 // Add glyph resources to font resource dict
863                 xobjects->insertRef(SkStringPrintf("Xg%X", gID), sMask);
864                 // TODO: name must match ApplyGraphicState
865                 graphicStates->insertRef(SkStringPrintf("G%d", smaskGraphicState.fValue),
866                                          smaskGraphicState);
867             }
868         } else {
869             setGlyphWidthAndBoundingBox(pathGlyph->advanceX(), glyphBBox, &content);
870         }
871         charProcs->insertRef(std::move(characterName),
872                              SkPDFStreamOut(nullptr, content.detachAsStream(), doc));
873     }
874 
875     if (xobjects->size() || graphicStates->size()) {
876         auto resources = SkPDFMakeDict();
877         if (xobjects->size()) {
878             resources->insertObject("XObject", std::move(xobjects));
879         }
880         if (graphicStates->size()) {
881             resources->insertObject("ExtGState", std::move(graphicStates));
882         }
883         font.insertObject("Resources", std::move(resources));
884     }
885 
886     encoding->insertObject("Differences", std::move(encDiffs));
887     font.insertInt("FirstChar", 0);
888     font.insertInt("LastChar", lastGlyphID - firstGlyphID + 1);
889     /* FontBBox: "A rectangle expressed in the glyph coordinate
890       system, specifying the font bounding box. This is the smallest
891       rectangle enclosing the shape that would result if all of the
892       glyphs of the font were placed with their origins coincident and
893       then filled." */
894     font.insertObject("FontBBox", SkPDFMakeArray(bbox.left(),
895                                                   bbox.bottom(),
896                                                   bbox.right(),
897                                                   bbox.top()));
898 
899     font.insertName("CIDToGIDMap", "Identity");
900 
901     const SkTypeface& pathTypeface = pdfStrike.fPath.fStrikeSpec.typeface();
902     const std::vector<SkUnichar>& glyphToUnicode = SkPDFFont::GetUnicodeMap(pathTypeface, doc);
903     SkASSERT(glyphToUnicode.size() == SkToSizeT(pathTypeface.countGlyphs()));
904     auto toUnicodeCmap = SkPDFMakeToUnicodeCmap(glyphToUnicode.data(),
905                                                 SkPDFFont::GetUnicodeMapEx(pathTypeface, doc),
906                                                 &subset,
907                                                 false,
908                                                 firstGlyphID,
909                                                 lastGlyphID);
910     font.insertRef("ToUnicode", SkPDFStreamOut(nullptr, std::move(toUnicodeCmap), doc));
911     font.insertRef("FontDescriptor", type3_descriptor(doc, pathTypeface, xHeight));
912     font.insertObject("Widths", std::move(widthArray));
913     font.insertObject("Encoding", std::move(encoding));
914     font.insertObject("CharProcs", std::move(charProcs));
915 
916     doc->emit(font, pdfFont.indirectReference());
917 }
918 
emitSubset(SkPDFDocument * doc) const919 void SkPDFFont::emitSubset(SkPDFDocument* doc) const {
920     switch (fFontType) {
921         case SkAdvancedTypefaceMetrics::kType1CID_Font:
922         case SkAdvancedTypefaceMetrics::kTrueType_Font:
923             return emit_subset_type0(*this, doc);
924 #ifndef SK_PDF_DO_NOT_SUPPORT_TYPE_1_FONTS
925         case SkAdvancedTypefaceMetrics::kType1_Font:
926             return SkPDFEmitType1Font(*this, doc);
927 #endif
928         default:
929             return emit_subset_type3(*this, doc);
930     }
931 }
932 
933 ////////////////////////////////////////////////////////////////////////////////
934 
CanEmbedTypeface(const SkTypeface & typeface,SkPDFDocument * doc)935 bool SkPDFFont::CanEmbedTypeface(const SkTypeface& typeface, SkPDFDocument* doc) {
936     const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, doc);
937     return metrics && can_embed(*metrics);
938 }
939 
940