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