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