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