• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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