• 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 "src/pdf/SkPDFFont.h"
9 
10 #include "include/core/SkBitmap.h"
11 #include "include/core/SkCanvas.h"
12 #include "include/core/SkData.h"
13 #include "include/core/SkDrawable.h"
14 #include "include/core/SkFont.h"
15 #include "include/core/SkFontMetrics.h"
16 #include "include/core/SkFontStyle.h"
17 #include "include/core/SkFontTypes.h"
18 #include "include/core/SkImage.h"
19 #include "include/core/SkImageInfo.h"
20 #include "include/core/SkMatrix.h"
21 #include "include/core/SkPaint.h"
22 #include "include/core/SkPath.h"
23 #include "include/core/SkPoint.h"
24 #include "include/core/SkRect.h"
25 #include "include/core/SkRefCnt.h"
26 #include "include/core/SkScalar.h"
27 #include "include/core/SkStream.h"
28 #include "include/core/SkString.h"
29 #include "include/core/SkSurfaceProps.h"
30 #include "include/private/base/SkDebug.h"
31 #include "include/private/base/SkTPin.h"
32 #include "include/private/base/SkTo.h"
33 #include "src/base/SkBitmaskEnum.h"
34 #include "src/base/SkUTF.h"
35 #include "src/core/SkDevice.h"
36 #include "src/core/SkGlyph.h"
37 #include "src/core/SkMask.h"
38 #include "src/core/SkScalerContext.h"
39 #include "src/core/SkStrike.h"
40 #include "src/core/SkStrikeSpec.h"
41 #include "src/core/SkTHash.h"
42 #include "src/pdf/SkPDFBitmap.h"
43 #include "src/pdf/SkPDFDevice.h"
44 #include "src/pdf/SkPDFDocumentPriv.h"
45 #include "src/pdf/SkPDFFormXObject.h"
46 #include "src/pdf/SkPDFMakeCIDGlyphWidthsArray.h"
47 #include "src/pdf/SkPDFMakeToUnicodeCmap.h"
48 #include "src/pdf/SkPDFSubsetFont.h"
49 #include "src/pdf/SkPDFType1Font.h"
50 #include "src/pdf/SkPDFUtils.h"
51 
52 #include <limits.h>
53 #include <algorithm>
54 #include <cstddef>
55 #include <initializer_list>
56 #include <memory>
57 #include <utility>
58 
GetType1GlyphNames(const SkTypeface & face,SkString * dst)59 void SkPDFFont::GetType1GlyphNames(const SkTypeface& face, SkString* dst) {
60     face.getPostScriptGlyphNames(dst);
61 }
62 
63 namespace {
64 // PDF's notion of symbolic vs non-symbolic is related to the character set, not
65 // symbols vs. characters.  Rarely is a font the right character set to call it
66 // non-symbolic, so always call it symbolic.  (PDF 1.4 spec, section 5.7.1)
67 static const int32_t kPdfSymbolic = 4;
68 static const SkFontTableTag kCOLRTableTag = SkSetFourByteTag('C', 'O', 'L', 'R');
69 
70 // scale from em-units to base-1000, returning as a SkScalar
from_font_units(SkScalar scaled,uint16_t emSize)71 inline SkScalar from_font_units(SkScalar scaled, uint16_t emSize) {
72     return emSize == 1000 ? scaled : scaled * 1000 / emSize;
73 }
74 
scaleFromFontUnits(int16_t val,uint16_t emSize)75 inline SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) {
76     return from_font_units(SkIntToScalar(val), emSize);
77 }
78 
setGlyphWidthAndBoundingBox(SkScalar width,SkIRect box,SkDynamicMemoryWStream * content)79 void setGlyphWidthAndBoundingBox(SkScalar width, SkIRect box,
80                                  SkDynamicMemoryWStream* content) {
81     // Specify width and bounding box for the glyph.
82     SkPDFUtils::AppendScalar(width, content);
83     content->writeText(" 0 ");
84     content->writeDecAsText(box.fLeft);
85     content->writeText(" ");
86     content->writeDecAsText(box.fTop);
87     content->writeText(" ");
88     content->writeDecAsText(box.fRight);
89     content->writeText(" ");
90     content->writeDecAsText(box.fBottom);
91     content->writeText(" d1\n");
92 }
93 }  // namespace
94 
95 ///////////////////////////////////////////////////////////////////////////////
96 // class SkPDFFont
97 ///////////////////////////////////////////////////////////////////////////////
98 
99 /* Resources are canonicalized and uniqueified by pointer so there has to be
100  * some additional state indicating which subset of the font is used.  It
101  * must be maintained at the document granularity.
102  */
103 
104 SkPDFFont::~SkPDFFont() = default;
105 
106 SkPDFFont::SkPDFFont(SkPDFFont&&) = default;
107 
108 SkPDFFont& SkPDFFont::operator=(SkPDFFont&&) = default;
109 
can_embed(const SkAdvancedTypefaceMetrics & metrics)110 static bool can_embed(const SkAdvancedTypefaceMetrics& metrics) {
111     return !SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag);
112 }
113 
GetMetrics(const SkTypeface * typeface,SkPDFDocument * canon)114 const SkAdvancedTypefaceMetrics* SkPDFFont::GetMetrics(const SkTypeface* typeface,
115                                                        SkPDFDocument* canon) {
116     SkASSERT(typeface);
117     SkTypefaceID id = typeface->uniqueID();
118     if (std::unique_ptr<SkAdvancedTypefaceMetrics>* ptr = canon->fTypefaceMetrics.find(id)) {
119         return ptr->get();  // canon retains ownership.
120     }
121     int count = typeface->countGlyphs();
122     if (count <= 0 || count > 1 + SkTo<int>(UINT16_MAX)) {
123         // Cache nullptr to skip this check.  Use SkSafeUnref().
124         canon->fTypefaceMetrics.set(id, nullptr);
125         return nullptr;
126     }
127     std::unique_ptr<SkAdvancedTypefaceMetrics> metrics = typeface->getAdvancedMetrics();
128     if (!metrics) {
129         metrics = std::make_unique<SkAdvancedTypefaceMetrics>();
130     }
131 
132     if (0 == metrics->fStemV || 0 == metrics->fCapHeight) {
133         SkFont font;
134         font.setHinting(SkFontHinting::kNone);
135         font.setTypeface(sk_ref_sp(typeface));
136         font.setSize(1000);  // glyph coordinate system
137         if (0 == metrics->fStemV) {
138             // Figure out a good guess for StemV - Min width of i, I, !, 1.
139             // This probably isn't very good with an italic font.
140             int16_t stemV = SHRT_MAX;
141             for (char c : {'i', 'I', '!', '1'}) {
142                 uint16_t g = font.unicharToGlyph(c);
143                 SkRect bounds;
144                 font.getBounds(&g, 1, &bounds, nullptr);
145                 stemV = std::min(stemV, SkToS16(SkScalarRoundToInt(bounds.width())));
146             }
147             metrics->fStemV = stemV;
148         }
149         if (0 == metrics->fCapHeight) {
150             // Figure out a good guess for CapHeight: average the height of M and X.
151             SkScalar capHeight = 0;
152             for (char c : {'M', 'X'}) {
153                 uint16_t g = font.unicharToGlyph(c);
154                 SkRect bounds;
155                 font.getBounds(&g, 1, &bounds, nullptr);
156                 capHeight += bounds.height();
157             }
158             metrics->fCapHeight = SkToS16(SkScalarRoundToInt(capHeight / 2));
159         }
160     }
161     // Fonts are always subset, so always prepend the subset tag.
162     metrics->fPostScriptName.prepend(canon->nextFontSubsetTag());
163     return canon->fTypefaceMetrics.set(id, std::move(metrics))->get();
164 }
165 
GetUnicodeMap(const SkTypeface * typeface,SkPDFDocument * canon)166 const std::vector<SkUnichar>& SkPDFFont::GetUnicodeMap(const SkTypeface* typeface,
167                                                        SkPDFDocument* canon) {
168     SkASSERT(typeface);
169     SkASSERT(canon);
170     SkTypefaceID id = typeface->uniqueID();
171     if (std::vector<SkUnichar>* ptr = canon->fToUnicodeMap.find(id)) {
172         return *ptr;
173     }
174     std::vector<SkUnichar> buffer(typeface->countGlyphs());
175     typeface->getGlyphToUnicodeMap(buffer.data());
176     return *canon->fToUnicodeMap.set(id, std::move(buffer));
177 }
178 
FontType(const SkTypeface & typeface,const SkAdvancedTypefaceMetrics & metrics)179 SkAdvancedTypefaceMetrics::FontType SkPDFFont::FontType(const SkTypeface& typeface,
180                                                         const SkAdvancedTypefaceMetrics& metrics) {
181     if (SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kVariable_FontFlag) ||
182         // PDF is actually interested in the encoding of the data, not just the logical format.
183         // If the TrueType is actually wOFF or wOF2 then it should not be directly embedded in PDF.
184         // For now export these as Type3 until the subsetter can handle table based fonts.
185         // See https://github.com/harfbuzz/harfbuzz/issues/3609 and
186         // https://skia-review.googlesource.com/c/skia/+/543485
187         SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kAltDataFormat_FontFlag) ||
188         SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag)) {
189         // force Type3 fallback.
190         return SkAdvancedTypefaceMetrics::kOther_Font;
191     }
192     if (typeface.getTableSize(kCOLRTableTag)) {
193         // https://bugs.chromium.org/p/skia/issues/detail?id=12650
194         // Don't embed COLRv0 / COLRv1 fonts, fall back to bitmaps.
195         return SkAdvancedTypefaceMetrics::kOther_Font;
196     }
197     return metrics.fType;
198 }
199 
first_nonzero_glyph_for_single_byte_encoding(SkGlyphID gid)200 static SkGlyphID first_nonzero_glyph_for_single_byte_encoding(SkGlyphID gid) {
201     return gid != 0 ? gid - (gid - 1) % 255 : 1;
202 }
203 
GetFontResource(SkPDFDocument * doc,const SkGlyph * glyph,SkTypeface * face)204 SkPDFFont* SkPDFFont::GetFontResource(SkPDFDocument* doc,
205                                       const SkGlyph* glyph,
206                                       SkTypeface* face) {
207     SkASSERT(doc);
208     SkASSERT(face);  // All SkPDFDevice::internalDrawText ensures this.
209     const SkAdvancedTypefaceMetrics* fontMetrics = SkPDFFont::GetMetrics(face, doc);
210     SkASSERT(fontMetrics);  // SkPDFDevice::internalDrawText ensures the typeface is good.
211                             // GetMetrics only returns null to signify a bad typeface.
212     const SkAdvancedTypefaceMetrics& metrics = *fontMetrics;
213     SkAdvancedTypefaceMetrics::FontType type = SkPDFFont::FontType(*face, metrics);
214     if (!(glyph->isEmpty() || glyph->path())) {
215         type = SkAdvancedTypefaceMetrics::kOther_Font;
216     }
217     bool multibyte = SkPDFFont::IsMultiByte(type);
218     SkGlyphID subsetCode =
219             multibyte ? 0 : first_nonzero_glyph_for_single_byte_encoding(glyph->getGlyphID());
220     uint64_t typefaceID = (static_cast<uint64_t>(face->uniqueID()) << 16) | subsetCode;
221 
222     if (SkPDFFont* found = doc->fFontMap.find(typefaceID)) {
223         SkASSERT(multibyte == found->multiByteGlyphs());
224         return found;
225     }
226 
227     sk_sp<SkTypeface> typeface(sk_ref_sp(face));
228     SkASSERT(typeface);
229 
230     SkGlyphID lastGlyph = SkToU16(typeface->countGlyphs() - 1);
231 
232     // should be caught by SkPDFDevice::internalDrawText
233     SkASSERT(glyph->getGlyphID() <= lastGlyph);
234 
235     SkGlyphID firstNonZeroGlyph;
236     if (multibyte) {
237         firstNonZeroGlyph = 1;
238     } else {
239         firstNonZeroGlyph = subsetCode;
240         lastGlyph = SkToU16(std::min<int>((int)lastGlyph, 254 + (int)subsetCode));
241     }
242     auto ref = doc->reserveRef();
243     return doc->fFontMap.set(
244             typefaceID, SkPDFFont(std::move(typeface), firstNonZeroGlyph, lastGlyph, type, ref));
245 }
246 
SkPDFFont(sk_sp<SkTypeface> typeface,SkGlyphID firstGlyphID,SkGlyphID lastGlyphID,SkAdvancedTypefaceMetrics::FontType fontType,SkPDFIndirectReference indirectReference)247 SkPDFFont::SkPDFFont(sk_sp<SkTypeface> typeface,
248                      SkGlyphID firstGlyphID,
249                      SkGlyphID lastGlyphID,
250                      SkAdvancedTypefaceMetrics::FontType fontType,
251                      SkPDFIndirectReference indirectReference)
252     : fTypeface(std::move(typeface))
253     , fGlyphUsage(firstGlyphID, lastGlyphID)
254     , fIndirectReference(indirectReference)
255     , fFontType(fontType)
256 {
257     // Always include glyph 0
258     this->noteGlyphUsage(0);
259 }
260 
PopulateCommonFontDescriptor(SkPDFDict * descriptor,const SkAdvancedTypefaceMetrics & metrics,uint16_t emSize,int16_t defaultWidth)261 void SkPDFFont::PopulateCommonFontDescriptor(SkPDFDict* descriptor,
262                                              const SkAdvancedTypefaceMetrics& metrics,
263                                              uint16_t emSize,
264                                              int16_t defaultWidth) {
265     descriptor->insertName("FontName", metrics.fPostScriptName);
266     descriptor->insertInt("Flags", (size_t)(metrics.fStyle | kPdfSymbolic));
267     descriptor->insertScalar("Ascent",
268             scaleFromFontUnits(metrics.fAscent, emSize));
269     descriptor->insertScalar("Descent",
270             scaleFromFontUnits(metrics.fDescent, emSize));
271     descriptor->insertScalar("StemV",
272             scaleFromFontUnits(metrics.fStemV, emSize));
273     descriptor->insertScalar("CapHeight",
274             scaleFromFontUnits(metrics.fCapHeight, emSize));
275     descriptor->insertInt("ItalicAngle", metrics.fItalicAngle);
276     descriptor->insertObject("FontBBox",
277                              SkPDFMakeArray(scaleFromFontUnits(metrics.fBBox.left(), emSize),
278                                             scaleFromFontUnits(metrics.fBBox.bottom(), emSize),
279                                             scaleFromFontUnits(metrics.fBBox.right(), emSize),
280                                             scaleFromFontUnits(metrics.fBBox.top(), emSize)));
281     if (defaultWidth > 0) {
282         descriptor->insertScalar("MissingWidth",
283                 scaleFromFontUnits(defaultWidth, emSize));
284     }
285 }
286 
287 ///////////////////////////////////////////////////////////////////////////////
288 //  Type0Font
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             case SkAdvancedTypefaceMetrics::kCFF_Font: {
317                 if (!SkToBool(metrics.fFlags &
318                               SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag)) {
319                     SkASSERT(font.firstGlyphID() == 1);
320                     sk_sp<SkData> subsetFontData = SkPDFSubsetFont(*face, font.glyphUsage());
321                     if (subsetFontData) {
322                         std::unique_ptr<SkPDFDict> tmp = SkPDFMakeDict();
323                         tmp->insertInt("Length1", SkToInt(subsetFontData->size()));
324                         descriptor->insertRef(
325                                 "FontFile2",
326                                 SkPDFStreamOut(std::move(tmp),
327                                                SkMemoryStream::Make(std::move(subsetFontData)),
328                                                doc, SkPDFSteamCompressionEnabled::Yes));
329                         break;
330                     }
331                     // If subsetting fails, fall back to original font data.
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, SkPDFSteamCompressionEnabled::Yes));
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, SkPDFSteamCompressionEnabled::Yes));
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         case SkAdvancedTypefaceMetrics::kCFF_Font:
363             newCIDFont->insertName("Subtype", "CIDFontType2");
364             newCIDFont->insertName("CIDToGIDMap", "Identity");
365             break;
366         default:
367             SkASSERT(false);
368     }
369     auto sysInfo = SkPDFMakeDict();
370     // These are actually ASCII strings.
371     sysInfo->insertByteString("Registry", "Adobe");
372     sysInfo->insertByteString("Ordering", "Identity");
373     sysInfo->insertInt("Supplement", 0);
374     newCIDFont->insertObject("CIDSystemInfo", std::move(sysInfo));
375 
376     // Unfortunately, poppler enforces DW (default width) must be an integer.
377     int32_t defaultWidth = 0;
378     {
379         std::unique_ptr<SkPDFArray> widths = SkPDFMakeCIDGlyphWidthsArray(
380                 *face, font.glyphUsage(), &defaultWidth);
381         if (widths && widths->size() > 0) {
382             newCIDFont->insertObject("W", std::move(widths));
383         }
384         newCIDFont->insertInt("DW", defaultWidth);
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 // PDFType3Font
413 ///////////////////////////////////////////////////////////////////////////////
414 
415 namespace {
416 // returns [0, first, first+1, ... last-1,  last]
417 struct SingleByteGlyphIdIterator {
SingleByteGlyphIdIterator__anonc0ac3e7c0211::SingleByteGlyphIdIterator418     SingleByteGlyphIdIterator(SkGlyphID first, SkGlyphID last)
419         : fFirst(first), fLast(last) {
420         SkASSERT(fFirst > 0);
421         SkASSERT(fLast >= first);
422     }
423     struct Iter {
operator ++__anonc0ac3e7c0211::SingleByteGlyphIdIterator::Iter424         void operator++() {
425             fCurrent = (0 == fCurrent) ? fFirst : fCurrent + 1;
426         }
427         // This is an input_iterator
operator *__anonc0ac3e7c0211::SingleByteGlyphIdIterator::Iter428         SkGlyphID operator*() const { return (SkGlyphID)fCurrent; }
operator !=__anonc0ac3e7c0211::SingleByteGlyphIdIterator::Iter429         bool operator!=(const Iter& rhs) const {
430             return fCurrent != rhs.fCurrent;
431         }
Iter__anonc0ac3e7c0211::SingleByteGlyphIdIterator::Iter432         Iter(SkGlyphID f, int c) : fFirst(f), fCurrent(c) {}
433     private:
434         const SkGlyphID fFirst;
435         int fCurrent; // must be int to make fLast+1 to fit
436     };
begin__anonc0ac3e7c0211::SingleByteGlyphIdIterator437     Iter begin() const { return Iter(fFirst, 0); }
end__anonc0ac3e7c0211::SingleByteGlyphIdIterator438     Iter end() const { return Iter(fFirst, (int)fLast + 1); }
439 private:
440     const SkGlyphID fFirst;
441     const SkGlyphID fLast;
442 };
443 }  // namespace
444 
445 struct ImageAndOffset {
446     sk_sp<SkImage> fImage;
447     SkIPoint fOffset;
448 };
to_image(SkGlyphID gid,SkBulkGlyphMetricsAndImages * smallGlyphs)449 static ImageAndOffset to_image(SkGlyphID gid, SkBulkGlyphMetricsAndImages* smallGlyphs) {
450     const SkGlyph* glyph = smallGlyphs->glyph(SkPackedGlyphID{gid});
451     SkMask mask = glyph->mask();
452     if (!mask.fImage) {
453         return {nullptr, {0, 0}};
454     }
455     SkIRect bounds = mask.fBounds;
456     SkBitmap bm;
457     switch (mask.fFormat) {
458         case SkMask::kBW_Format:
459             bm.allocPixels(SkImageInfo::MakeA8(bounds.width(), bounds.height()));
460             for (int y = 0; y < bm.height(); ++y) {
461                 for (int x8 = 0; x8 < bm.width(); x8 += 8) {
462                     uint8_t v = *mask.getAddr1(x8 + bounds.x(), y + bounds.y());
463                     int e = std::min(x8 + 8, bm.width());
464                     for (int x = x8; x < e; ++x) {
465                         *bm.getAddr8(x, y) = (v >> (x & 0x7)) & 0x1 ? 0xFF : 0x00;
466                     }
467                 }
468             }
469             bm.setImmutable();
470             return {bm.asImage(), {bounds.x(), bounds.y()}};
471         case SkMask::kA8_Format:
472             return {SkImages::RasterFromData(
473                         SkImageInfo::MakeA8(bounds.width(), bounds.height()),
474                         SkData::MakeWithCopy(mask.fImage, mask.computeTotalImageSize()),
475                         mask.fRowBytes),
476                     {bounds.x(), bounds.y()}};
477         case SkMask::kARGB32_Format:
478             return {SkImages::RasterFromData(
479                         SkImageInfo::MakeN32Premul(bounds.width(), bounds.height()),
480                         SkData::MakeWithCopy(mask.fImage, mask.computeTotalImageSize()),
481                         mask.fRowBytes),
482                     {bounds.x(), bounds.y()}};
483         case SkMask::k3D_Format:
484         case SkMask::kLCD16_Format:
485         default:
486             SkASSERT(false);
487             return {nullptr, {0, 0}};
488     }
489 }
490 
type3_descriptor(SkPDFDocument * doc,const SkTypeface * typeface,SkScalar xHeight)491 static SkPDFIndirectReference type3_descriptor(SkPDFDocument* doc,
492                                                const SkTypeface* typeface,
493                                                SkScalar xHeight) {
494     if (SkPDFIndirectReference* ptr = doc->fType3FontDescriptors.find(typeface->uniqueID())) {
495         return *ptr;
496     }
497 
498     SkPDFDict descriptor("FontDescriptor");
499     int32_t fontDescriptorFlags = kPdfSymbolic;
500 
501     /** PDF32000_2008: FontFamily should be used for Type3 fonts in Tagged PDF documents. */
502     SkString familyName;
503     typeface->getFamilyName(&familyName);
504     if (!familyName.isEmpty()) {
505         descriptor.insertByteString("FontFamily", familyName);
506     }
507 
508     /** PDF32000_2008: FontStretch should be used for Type3 fonts in Tagged PDF documents. */
509     static constexpr const char* stretchNames[9] = {
510         "UltraCondensed",
511         "ExtraCondensed",
512         "Condensed",
513         "SemiCondensed",
514         "Normal",
515         "SemiExpanded",
516         "Expanded",
517         "ExtraExpanded",
518         "UltraExpanded",
519     };
520     const char* stretchName = stretchNames[typeface->fontStyle().width() - 1];
521     descriptor.insertName("FontStretch", stretchName);
522 
523     /** PDF32000_2008: FontWeight should be used for Type3 fonts in Tagged PDF documents. */
524     int weight = (typeface->fontStyle().weight() + 50) / 100;
525     descriptor.insertInt("FontWeight", SkTPin(weight, 1, 9) * 100);
526 
527     if (const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, doc)) {
528         // Type3 FontDescriptor does not require all the same fields.
529         descriptor.insertName("FontName", metrics->fPostScriptName);
530         descriptor.insertInt("ItalicAngle", metrics->fItalicAngle);
531         fontDescriptorFlags |= (int32_t)metrics->fStyle;
532         // Adobe requests CapHeight, XHeight, and StemV be added
533         // to "greatly help our workflow downstream".
534         if (metrics->fCapHeight != 0) { descriptor.insertInt("CapHeight", metrics->fCapHeight); }
535         if (metrics->fStemV     != 0) { descriptor.insertInt("StemV",     metrics->fStemV);     }
536         if (xHeight != 0) {
537             descriptor.insertScalar("XHeight", xHeight);
538         }
539     }
540     descriptor.insertInt("Flags", fontDescriptorFlags);
541     SkPDFIndirectReference ref = doc->emit(descriptor);
542     doc->fType3FontDescriptors.set(typeface->uniqueID(), ref);
543     return ref;
544 }
545 
546 #ifdef SK_PDF_BITMAP_GLYPH_RASTER_SIZE
547 static constexpr float kBitmapFontSize = SK_PDF_BITMAP_GLYPH_RASTER_SIZE;
548 #else
549 static constexpr float kBitmapFontSize = 64;
550 #endif
551 
make_small_strike(const SkTypeface & typeface)552 SkStrikeSpec make_small_strike(const SkTypeface& typeface) {
553     SkFont font(sk_ref_sp(&typeface), kBitmapFontSize);
554     font.setHinting(SkFontHinting::kNone);
555     font.setEdging(SkFont::Edging::kAlias);
556     return SkStrikeSpec::MakeMask(font,
557                                   SkPaint(),
558                                   SkSurfaceProps(),
559                                   SkScalerContextFlags::kFakeGammaAndBoostContrast,
560                                   SkMatrix::I());
561 }
562 
emit_subset_type3(const SkPDFFont & pdfFont,SkPDFDocument * doc)563 static void emit_subset_type3(const SkPDFFont& pdfFont, SkPDFDocument* doc) {
564     SkTypeface* typeface = pdfFont.typeface();
565     SkGlyphID firstGlyphID = pdfFont.firstGlyphID();
566     SkGlyphID lastGlyphID = pdfFont.lastGlyphID();
567     const SkPDFGlyphUse& subset = pdfFont.glyphUsage();
568     SkASSERT(lastGlyphID >= firstGlyphID);
569     // Remove unused glyphs at the end of the range.
570     // Keep the lastGlyphID >= firstGlyphID invariant true.
571     while (lastGlyphID > firstGlyphID && !subset.has(lastGlyphID)) {
572         --lastGlyphID;
573     }
574     int unitsPerEm;
575     SkStrikeSpec strikeSpec = SkStrikeSpec::MakePDFVector(*typeface, &unitsPerEm);
576     auto strike = strikeSpec.findOrCreateStrike();
577     SkASSERT(strike);
578     SkScalar emSize = (SkScalar)unitsPerEm;
579     SkScalar xHeight = strike->getFontMetrics().fXHeight;
580     SkBulkGlyphMetricsAndPaths metricsAndPaths((sk_sp<SkStrike>(strike)));
581     SkBulkGlyphMetricsAndDrawables metricsAndDrawables(std::move(strike));
582 
583     SkStrikeSpec strikeSpecSmall = kBitmapFontSize > 0 ? make_small_strike(*typeface)
584                                                        : strikeSpec;
585 
586     SkBulkGlyphMetricsAndImages smallGlyphs(strikeSpecSmall);
587     float bitmapScale = kBitmapFontSize > 0 ? emSize / kBitmapFontSize : 1.0f;
588 
589     SkPDFDict font("Font");
590     font.insertName("Subtype", "Type3");
591     // Flip about the x-axis and scale by 1/emSize.
592     SkMatrix fontMatrix;
593     fontMatrix.setScale(SkScalarInvert(emSize), -SkScalarInvert(emSize));
594     font.insertObject("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix));
595 
596     auto charProcs = SkPDFMakeDict();
597     auto encoding = SkPDFMakeDict("Encoding");
598 
599     auto encDiffs = SkPDFMakeArray();
600     // length(firstGlyphID .. lastGlyphID) ==  lastGlyphID - firstGlyphID + 1
601     // plus 1 for glyph 0;
602     SkASSERT(firstGlyphID > 0);
603     SkASSERT(lastGlyphID >= firstGlyphID);
604     int glyphCount = lastGlyphID - firstGlyphID + 2;
605     // one other entry for the index of first glyph.
606     encDiffs->reserve(glyphCount + 1);
607     encDiffs->appendInt(0);  // index of first glyph
608 
609     auto widthArray = SkPDFMakeArray();
610     widthArray->reserve(glyphCount);
611 
612     SkIRect bbox = SkIRect::MakeEmpty();
613 
614     std::vector<std::pair<SkGlyphID, SkPDFIndirectReference>> imageGlyphs;
615     for (SkGlyphID gID : SingleByteGlyphIdIterator(firstGlyphID, lastGlyphID)) {
616         bool skipGlyph = gID != 0 && !subset.has(gID);
617         SkString characterName;
618         SkScalar advance = 0.0f;
619         SkIRect glyphBBox;
620         if (skipGlyph) {
621             characterName.set("g0");
622         } else {
623             characterName.printf("g%X", gID);
624             const SkGlyph* pathGlyph = metricsAndPaths.glyph(gID);
625             const SkGlyph* drawableGlyph = metricsAndDrawables.glyph(gID);
626             advance = pathGlyph->advanceX();
627             glyphBBox = pathGlyph->iRect();
628             bbox.join(glyphBBox);
629             const SkPath* path = pathGlyph->path();
630             SkDrawable* drawable = drawableGlyph->drawable();
631             SkDynamicMemoryWStream content;
632             if (drawable && !drawable->getBounds().isEmpty()) {
633                 sk_sp<SkPDFDevice> glyphDevice = sk_make_sp<SkPDFDevice>(glyphBBox.size(), doc);
634                 SkCanvas canvas(glyphDevice);
635                 canvas.translate(-glyphBBox.fLeft, -glyphBBox.fTop);
636                 canvas.drawDrawable(drawable);
637                 SkPDFIndirectReference xobject = SkPDFMakeFormXObject(
638                         doc, glyphDevice->content(),
639                         SkPDFMakeArray(0, 0, glyphBBox.width(), glyphBBox.height()),
640                         glyphDevice->makeResourceDict(),
641                         SkMatrix::Translate(glyphBBox.fLeft, glyphBBox.fTop), nullptr);
642                 imageGlyphs.emplace_back(gID, xobject);
643                 SkPDFUtils::AppendScalar(drawableGlyph->advanceX(), &content);
644                 content.writeText(" 0 d0\n1 0 0 1 0 0 cm\n/X");
645                 content.write(characterName.c_str(), characterName.size());
646                 content.writeText(" Do\n");
647             } else if (path && !path->isEmpty()) {
648                 setGlyphWidthAndBoundingBox(pathGlyph->advanceX(), glyphBBox, &content);
649                 SkPDFUtils::EmitPath(*path, SkPaint::kFill_Style, &content);
650                 SkPDFUtils::PaintPath(SkPaint::kFill_Style, path->getFillType(), &content);
651             } else {
652                 auto pimg = to_image(gID, &smallGlyphs);
653                 if (!pimg.fImage) {
654                     setGlyphWidthAndBoundingBox(pathGlyph->advanceX(), glyphBBox, &content);
655                 } else {
656                     using SkPDFUtils::AppendScalar;
657                     imageGlyphs.emplace_back(gID, SkPDFSerializeImage(pimg.fImage.get(), doc));
658                     AppendScalar(pathGlyph->advanceX(), &content);
659                     content.writeText(" 0 d0\n");
660                     AppendScalar(pimg.fImage->width() * bitmapScale, &content);
661                     content.writeText(" 0 0 ");
662                     AppendScalar(-pimg.fImage->height() * bitmapScale, &content);
663                     content.writeText(" ");
664                     AppendScalar(pimg.fOffset.x() * bitmapScale, &content);
665                     content.writeText(" ");
666                     AppendScalar((pimg.fImage->height() + pimg.fOffset.y()) * bitmapScale,
667                                  &content);
668                     content.writeText(" cm\n/X");
669                     content.write(characterName.c_str(), characterName.size());
670                     content.writeText(" Do\n");
671                 }
672             }
673             charProcs->insertRef(characterName, SkPDFStreamOut(nullptr,
674                                                                content.detachAsStream(), doc));
675         }
676         encDiffs->appendName(std::move(characterName));
677         widthArray->appendScalar(advance);
678     }
679 
680     if (!imageGlyphs.empty()) {
681         auto d0 = SkPDFMakeDict();
682         for (const auto& pair : imageGlyphs) {
683             d0->insertRef(SkStringPrintf("Xg%X", pair.first), pair.second);
684         }
685         auto d1 = SkPDFMakeDict();
686         d1->insertObject("XObject", std::move(d0));
687         font.insertObject("Resources", std::move(d1));
688     }
689 
690     encoding->insertObject("Differences", std::move(encDiffs));
691     font.insertInt("FirstChar", 0);
692     font.insertInt("LastChar", lastGlyphID - firstGlyphID + 1);
693     /* FontBBox: "A rectangle expressed in the glyph coordinate
694       system, specifying the font bounding box. This is the smallest
695       rectangle enclosing the shape that would result if all of the
696       glyphs of the font were placed with their origins coincident and
697       then filled." */
698     font.insertObject("FontBBox", SkPDFMakeArray(bbox.left(),
699                                                   bbox.bottom(),
700                                                   bbox.right(),
701                                                   bbox.top()));
702 
703     font.insertName("CIDToGIDMap", "Identity");
704 
705     const std::vector<SkUnichar>& glyphToUnicode = SkPDFFont::GetUnicodeMap(typeface, doc);
706     SkASSERT(glyphToUnicode.size() == SkToSizeT(typeface->countGlyphs()));
707     auto toUnicodeCmap = SkPDFMakeToUnicodeCmap(glyphToUnicode.data(),
708                                                 &subset,
709                                                 false,
710                                                 firstGlyphID,
711                                                 lastGlyphID);
712     font.insertRef("ToUnicode", SkPDFStreamOut(nullptr, std::move(toUnicodeCmap), doc));
713     font.insertRef("FontDescriptor", type3_descriptor(doc, typeface, xHeight));
714     font.insertObject("Widths", std::move(widthArray));
715     font.insertObject("Encoding", std::move(encoding));
716     font.insertObject("CharProcs", std::move(charProcs));
717 
718     doc->emit(font, pdfFont.indirectReference());
719 }
720 
emitSubset(SkPDFDocument * doc) const721 void SkPDFFont::emitSubset(SkPDFDocument* doc) const {
722     switch (fFontType) {
723         case SkAdvancedTypefaceMetrics::kType1CID_Font:
724         case SkAdvancedTypefaceMetrics::kTrueType_Font:
725         case SkAdvancedTypefaceMetrics::kCFF_Font:
726             return emit_subset_type0(*this, doc);
727 #ifndef SK_PDF_DO_NOT_SUPPORT_TYPE_1_FONTS
728         case SkAdvancedTypefaceMetrics::kType1_Font:
729             return SkPDFEmitType1Font(*this, doc);
730 #endif
731         default:
732             return emit_subset_type3(*this, doc);
733     }
734 }
735 
736 ////////////////////////////////////////////////////////////////////////////////
737 
CanEmbedTypeface(SkTypeface * typeface,SkPDFDocument * doc)738 bool SkPDFFont::CanEmbedTypeface(SkTypeface* typeface, SkPDFDocument* doc) {
739     const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, doc);
740     return metrics && can_embed(*metrics);
741 }
742 
743