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