xref: /third_party/skia/src/pdf/SkPDFFont.cpp (revision cb93a386)
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
51void SkPDFFont::GetType1GlyphNames(const SkTypeface& face, SkString* dst) {
52    face.getPostScriptGlyphNames(dst);
53}
54
55namespace {
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)
59static const int32_t kPdfSymbolic = 4;
60
61
62// scale from em-units to base-1000, returning as a SkScalar
63inline SkScalar from_font_units(SkScalar scaled, uint16_t emSize) {
64    return emSize == 1000 ? scaled : scaled * 1000 / emSize;
65}
66
67inline SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) {
68    return from_font_units(SkIntToScalar(val), emSize);
69}
70
71void 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
96SkPDFFont::~SkPDFFont() = default;
97
98SkPDFFont::SkPDFFont(SkPDFFont&&) = default;
99
100SkPDFFont& SkPDFFont::operator=(SkPDFFont&&) = default;
101
102static bool can_embed(const SkAdvancedTypefaceMetrics& metrics) {
103    return !SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag);
104}
105
106const 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
156const 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
169SkAdvancedTypefaceMetrics::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
178static SkGlyphID first_nonzero_glyph_for_single_byte_encoding(SkGlyphID gid) {
179    return gid != 0 ? gid - (gid - 1) % 255 : 1;
180}
181
182SkPDFFont* 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
225SkPDFFont::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
239void 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.
270static 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
283static 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
410namespace {
411// returns [0, first, first+1, ... last-1,  last]
412struct SingleByteGlyphIdIterator {
413    SingleByteGlyphIdIterator(SkGlyphID first, SkGlyphID last)
414        : fFirst(first), fLast(last) {
415        SkASSERT(fFirst > 0);
416        SkASSERT(fLast >= first);
417    }
418    struct Iter {
419        void operator++() {
420            fCurrent = (0 == fCurrent) ? fFirst : fCurrent + 1;
421        }
422        // This is an input_iterator
423        SkGlyphID operator*() const { return (SkGlyphID)fCurrent; }
424        bool operator!=(const Iter& rhs) const {
425            return fCurrent != rhs.fCurrent;
426        }
427        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    };
432    Iter begin() const { return Iter(fFirst, 0); }
433    Iter end() const { return Iter(fFirst, (int)fLast + 1); }
434private:
435    const SkGlyphID fFirst;
436    const SkGlyphID fLast;
437};
438}  // namespace
439
440struct ImageAndOffset {
441    sk_sp<SkImage> fImage;
442    SkIPoint fOffset;
443};
444static 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
484static 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
513static constexpr float kBitmapFontSize = SK_PDF_BITMAP_GLYPH_RASTER_SIZE;
514#else
515static constexpr float kBitmapFontSize = 64;
516#endif
517
518SkStrikeSpec 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
529static 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
669void SkPDFFont::emitSubset(SkPDFDocument* doc) const {
670    switch (fFontType) {
671        case SkAdvancedTypefaceMetrics::kType1CID_Font:
672        case SkAdvancedTypefaceMetrics::kTrueType_Font:
673            return emit_subset_type0(*this, doc);
674#ifndef SK_PDF_DO_NOT_SUPPORT_TYPE_1_FONTS
675        case SkAdvancedTypefaceMetrics::kType1_Font:
676            return SkPDFEmitType1Font(*this, doc);
677#endif
678        default:
679            return emit_subset_type3(*this, doc);
680    }
681}
682
683////////////////////////////////////////////////////////////////////////////////
684
685bool SkPDFFont::CanEmbedTypeface(SkTypeface* typeface, SkPDFDocument* doc) {
686    const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, doc);
687    return metrics && can_embed(*metrics);
688}
689
690