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 "SkData.h"
9#include "SkGlyphCache.h"
10#include "SkMakeUnique.h"
11#include "SkPDFCanon.h"
12#include "SkPDFConvertType1FontStream.h"
13#include "SkPDFDevice.h"
14#include "SkPDFFont.h"
15#include "SkPDFMakeCIDGlyphWidthsArray.h"
16#include "SkPDFMakeToUnicodeCmap.h"
17#include "SkPDFUtils.h"
18#include "SkPaint.h"
19#include "SkRefCnt.h"
20#include "SkScalar.h"
21#include "SkStream.h"
22#include "SkTypes.h"
23#include "SkUtils.h"
24
25#ifdef SK_PDF_USE_SFNTLY
26    #include "sample/chromium/font_subsetter.h"
27#endif
28
29SkAutoGlyphCache SkPDFFont::MakeVectorCache(SkTypeface* face, int* size) {
30    SkPaint tmpPaint;
31    tmpPaint.setHinting(SkPaint::kNo_Hinting);
32    tmpPaint.setTypeface(sk_ref_sp(face));
33    int unitsPerEm = face->getUnitsPerEm();
34    if (unitsPerEm <= 0) {
35        unitsPerEm = 1024;
36    }
37    if (size) {
38        *size = unitsPerEm;
39    }
40    tmpPaint.setTextSize((SkScalar)unitsPerEm);
41    const SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
42    SkAutoGlyphCache glyphCache(tmpPaint, &props, nullptr);
43    SkASSERT(glyphCache.get());
44    return glyphCache;
45}
46
47namespace {
48// PDF's notion of symbolic vs non-symbolic is related to the character set, not
49// symbols vs. characters.  Rarely is a font the right character set to call it
50// non-symbolic, so always call it symbolic.  (PDF 1.4 spec, section 5.7.1)
51static const int32_t kPdfSymbolic = 4;
52
53struct SkPDFType0Font final : public SkPDFFont {
54    SkPDFType0Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&);
55    ~SkPDFType0Font() override;
56    void getFontSubset(SkPDFCanon*) override;
57#ifdef SK_DEBUG
58    void emitObject(SkWStream*, const SkPDFObjNumMap&) const override;
59    bool fPopulated;
60#endif
61    typedef SkPDFDict INHERITED;
62};
63
64struct SkPDFType1Font final : public SkPDFFont {
65    SkPDFType1Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&, SkPDFCanon*);
66    ~SkPDFType1Font() override {}
67    void getFontSubset(SkPDFCanon*) override {} // TODO(halcanary): implement
68};
69
70struct SkPDFType3Font final : public SkPDFFont {
71    SkPDFType3Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&);
72    ~SkPDFType3Font() override {}
73    void getFontSubset(SkPDFCanon*) override;
74};
75
76///////////////////////////////////////////////////////////////////////////////
77// File-Local Functions
78///////////////////////////////////////////////////////////////////////////////
79
80// scale from em-units to base-1000, returning as a SkScalar
81SkScalar from_font_units(SkScalar scaled, uint16_t emSize) {
82    if (emSize == 1000) {
83        return scaled;
84    } else {
85        return scaled * 1000 / emSize;
86    }
87}
88
89SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) {
90    return from_font_units(SkIntToScalar(val), emSize);
91}
92
93
94void setGlyphWidthAndBoundingBox(SkScalar width, SkIRect box,
95                                 SkDynamicMemoryWStream* content) {
96    // Specify width and bounding box for the glyph.
97    SkPDFUtils::AppendScalar(width, content);
98    content->writeText(" 0 ");
99    content->writeDecAsText(box.fLeft);
100    content->writeText(" ");
101    content->writeDecAsText(box.fTop);
102    content->writeText(" ");
103    content->writeDecAsText(box.fRight);
104    content->writeText(" ");
105    content->writeDecAsText(box.fBottom);
106    content->writeText(" d1\n");
107}
108
109static sk_sp<SkPDFArray> makeFontBBox(SkIRect glyphBBox, uint16_t emSize) {
110    auto bbox = sk_make_sp<SkPDFArray>();
111    bbox->reserve(4);
112    bbox->appendScalar(scaleFromFontUnits(glyphBBox.fLeft, emSize));
113    bbox->appendScalar(scaleFromFontUnits(glyphBBox.fBottom, emSize));
114    bbox->appendScalar(scaleFromFontUnits(glyphBBox.fRight, emSize));
115    bbox->appendScalar(scaleFromFontUnits(glyphBBox.fTop, emSize));
116    return bbox;
117}
118}  // namespace
119
120///////////////////////////////////////////////////////////////////////////////
121// class SkPDFFont
122///////////////////////////////////////////////////////////////////////////////
123
124/* Font subset design: It would be nice to be able to subset fonts
125 * (particularly type 3 fonts), but it's a lot of work and not a priority.
126 *
127 * Resources are canonicalized and uniqueified by pointer so there has to be
128 * some additional state indicating which subset of the font is used.  It
129 * must be maintained at the page granularity and then combined at the document
130 * granularity. a) change SkPDFFont to fill in its state on demand, kind of
131 * like SkPDFGraphicState.  b) maintain a per font glyph usage class in each
132 * page/pdf device. c) in the document, retrieve the per font glyph usage
133 * from each page and combine it and ask for a resource with that subset.
134 */
135
136SkPDFFont::~SkPDFFont() {}
137
138static bool can_embed(const SkAdvancedTypefaceMetrics& metrics) {
139    return !SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag);
140}
141
142const SkAdvancedTypefaceMetrics* SkPDFFont::GetMetrics(SkTypeface* typeface,
143                                                       SkPDFCanon* canon) {
144    SkASSERT(typeface);
145    SkFontID id = typeface->uniqueID();
146    if (std::unique_ptr<SkAdvancedTypefaceMetrics>* ptr = canon->fTypefaceMetrics.find(id)) {
147        return ptr->get();  // canon retains ownership.
148    }
149    int count = typeface->countGlyphs();
150    if (count <= 0 || count > 1 + SK_MaxU16) {
151        // Cache nullptr to skip this check.  Use SkSafeUnref().
152        canon->fTypefaceMetrics.set(id, nullptr);
153        return nullptr;
154    }
155    std::unique_ptr<SkAdvancedTypefaceMetrics> metrics = typeface->getAdvancedMetrics();
156    if (!metrics) {
157        metrics = skstd::make_unique<SkAdvancedTypefaceMetrics>();
158    }
159
160    if (0 == metrics->fStemV || 0 == metrics->fCapHeight) {
161        SkPaint tmpPaint;
162        tmpPaint.setHinting(SkPaint::kNo_Hinting);
163        tmpPaint.setTypeface(sk_ref_sp(typeface));
164        tmpPaint.setTextSize(1000);  // glyph coordinate system
165        if (0 == metrics->fStemV) {
166            // Figure out a good guess for StemV - Min width of i, I, !, 1.
167            // This probably isn't very good with an italic font.
168            int16_t stemV = SHRT_MAX;
169            for (char c : {'i', 'I', '!', '1'}) {
170                SkRect bounds;
171                tmpPaint.measureText(&c, 1, &bounds);
172                stemV = SkTMin(stemV, SkToS16(SkScalarRoundToInt(bounds.width())));
173            }
174            metrics->fStemV = stemV;
175        }
176        if (0 == metrics->fCapHeight) {
177            // Figure out a good guess for CapHeight: average the height of M and X.
178            SkScalar capHeight = 0;
179            for (char c : {'M', 'X'}) {
180                SkRect bounds;
181                tmpPaint.measureText(&c, 1, &bounds);
182                capHeight += bounds.height();
183            }
184            metrics->fCapHeight = SkToS16(SkScalarRoundToInt(capHeight / 2));
185        }
186    }
187    return canon->fTypefaceMetrics.set(id, std::move(metrics))->get();
188}
189
190SkAdvancedTypefaceMetrics::FontType SkPDFFont::FontType(const SkAdvancedTypefaceMetrics& metrics) {
191    if (SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag) ||
192        SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag)) {
193        // force Type3 fallback.
194        return SkAdvancedTypefaceMetrics::kOther_Font;
195    }
196    return metrics.fType;
197}
198
199static SkGlyphID first_nonzero_glyph_for_single_byte_encoding(SkGlyphID gid) {
200    return gid != 0 ? gid - (gid - 1) % 255 : 1;
201}
202
203sk_sp<SkPDFFont> SkPDFFont::GetFontResource(SkPDFCanon* canon,
204                                            SkTypeface* face,
205                                            SkGlyphID glyphID) {
206    SkASSERT(canon);
207    SkASSERT(face);  // All SkPDFDevice::internalDrawText ensures this.
208    const SkAdvancedTypefaceMetrics* fontMetrics = SkPDFFont::GetMetrics(face, canon);
209    SkASSERT(fontMetrics);  // SkPDFDevice::internalDrawText ensures the typeface is good.
210                            // GetMetrics only returns null to signify a bad typeface.
211    const SkAdvancedTypefaceMetrics& metrics = *fontMetrics;
212    SkAdvancedTypefaceMetrics::FontType type = SkPDFFont::FontType(metrics);
213    bool multibyte = SkPDFFont::IsMultiByte(type);
214    SkGlyphID subsetCode = multibyte ? 0 : first_nonzero_glyph_for_single_byte_encoding(glyphID);
215    uint64_t fontID = (SkTypeface::UniqueID(face) << 16) | subsetCode;
216
217    if (sk_sp<SkPDFFont>* found = canon->fFontMap.find(fontID)) {
218        SkDEBUGCODE(SkPDFFont* foundFont = found->get());
219        SkASSERT(foundFont && multibyte == foundFont->multiByteGlyphs());
220        return *found;
221    }
222
223    sk_sp<SkTypeface> typeface(sk_ref_sp(face));
224    SkASSERT(typeface);
225
226    SkGlyphID lastGlyph = SkToU16(typeface->countGlyphs() - 1);
227
228    // should be caught by SkPDFDevice::internalDrawText
229    SkASSERT(glyphID <= lastGlyph);
230
231    SkGlyphID firstNonZeroGlyph;
232    if (multibyte) {
233        firstNonZeroGlyph = 1;
234    } else {
235        firstNonZeroGlyph = subsetCode;
236        lastGlyph = SkToU16(SkTMin<int>((int)lastGlyph, 254 + (int)subsetCode));
237    }
238    SkPDFFont::Info info = {std::move(typeface), firstNonZeroGlyph, lastGlyph, type};
239    sk_sp<SkPDFFont> font;
240    switch (type) {
241        case SkAdvancedTypefaceMetrics::kType1CID_Font:
242        case SkAdvancedTypefaceMetrics::kTrueType_Font:
243            SkASSERT(multibyte);
244            font = sk_make_sp<SkPDFType0Font>(std::move(info), metrics);
245            break;
246        case SkAdvancedTypefaceMetrics::kType1_Font:
247            SkASSERT(!multibyte);
248            font = sk_make_sp<SkPDFType1Font>(std::move(info), metrics, canon);
249            break;
250        default:
251            SkASSERT(!multibyte);
252            // Type3 is our fallback font.
253            font = sk_make_sp<SkPDFType3Font>(std::move(info), metrics);
254            break;
255    }
256    canon->fFontMap.set(fontID, font);
257    return font;
258}
259
260SkPDFFont::SkPDFFont(SkPDFFont::Info info)
261    : SkPDFDict("Font")
262    , fTypeface(std::move(info.fTypeface))
263    , fGlyphUsage(info.fLastGlyphID + 1)  // TODO(halcanary): Adjust mapping?
264    , fFirstGlyphID(info.fFirstGlyphID)
265    , fLastGlyphID(info.fLastGlyphID)
266    , fFontType(info.fFontType) {
267    SkASSERT(fTypeface);
268}
269
270static void  add_common_font_descriptor_entries(SkPDFDict* descriptor,
271                                                const SkAdvancedTypefaceMetrics& metrics,
272                                                uint16_t emSize,
273                                                int16_t defaultWidth) {
274    descriptor->insertName("FontName", metrics.fFontName);
275    descriptor->insertInt("Flags", (size_t)(metrics.fStyle | kPdfSymbolic));
276    descriptor->insertScalar("Ascent",
277            scaleFromFontUnits(metrics.fAscent, emSize));
278    descriptor->insertScalar("Descent",
279            scaleFromFontUnits(metrics.fDescent, emSize));
280    descriptor->insertScalar("StemV",
281            scaleFromFontUnits(metrics.fStemV, emSize));
282    descriptor->insertScalar("CapHeight",
283            scaleFromFontUnits(metrics.fCapHeight, emSize));
284    descriptor->insertInt("ItalicAngle", metrics.fItalicAngle);
285    descriptor->insertObject(
286            "FontBBox", makeFontBBox(metrics.fBBox, emSize));
287    if (defaultWidth > 0) {
288        descriptor->insertScalar("MissingWidth",
289                scaleFromFontUnits(defaultWidth, emSize));
290    }
291}
292
293///////////////////////////////////////////////////////////////////////////////
294// class SkPDFType0Font
295///////////////////////////////////////////////////////////////////////////////
296
297SkPDFType0Font::SkPDFType0Font(
298        SkPDFFont::Info info,
299        const SkAdvancedTypefaceMetrics& metrics)
300    : SkPDFFont(std::move(info)) {
301    SkDEBUGCODE(fPopulated = false);
302}
303
304SkPDFType0Font::~SkPDFType0Font() {}
305
306
307#ifdef SK_DEBUG
308void SkPDFType0Font::emitObject(SkWStream* stream,
309                                const SkPDFObjNumMap& objNumMap) const {
310    SkASSERT(fPopulated);
311    return INHERITED::emitObject(stream, objNumMap);
312}
313#endif
314
315#ifdef SK_PDF_USE_SFNTLY
316// if possible, make no copy.
317static sk_sp<SkData> stream_to_data(std::unique_ptr<SkStreamAsset> stream) {
318    SkASSERT(stream);
319    (void)stream->rewind();
320    SkASSERT(stream->hasLength());
321    size_t size = stream->getLength();
322    if (const void* base = stream->getMemoryBase()) {
323        SkData::ReleaseProc proc =
324            [](const void*, void* ctx) { delete (SkStreamAsset*)ctx; };
325        return SkData::MakeWithProc(base, size, proc, stream.release());
326    }
327    return SkData::MakeFromStream(stream.get(), size);
328}
329
330static sk_sp<SkPDFStream> get_subset_font_stream(
331        std::unique_ptr<SkStreamAsset> fontAsset,
332        const SkBitSet& glyphUsage,
333        const char* fontName,
334        int ttcIndex) {
335    // Generate glyph id array in format needed by sfntly.
336    // TODO(halcanary): sfntly should take a more compact format.
337    SkTDArray<unsigned> subset;
338    if (!glyphUsage.has(0)) {
339        subset.push(0);  // Always include glyph 0.
340    }
341    glyphUsage.exportTo(&subset);
342
343    unsigned char* subsetFont{nullptr};
344    sk_sp<SkData> fontData(stream_to_data(std::move(fontAsset)));
345#if defined(SK_BUILD_FOR_GOOGLE3)
346    // TODO(halcanary): update SK_BUILD_FOR_GOOGLE3 to newest version of Sfntly.
347    (void)ttcIndex;
348    int subsetFontSize = SfntlyWrapper::SubsetFont(fontName,
349                                                   fontData->bytes(),
350                                                   fontData->size(),
351                                                   subset.begin(),
352                                                   subset.count(),
353                                                   &subsetFont);
354#else
355    (void)fontName;
356    int subsetFontSize = SfntlyWrapper::SubsetFont(ttcIndex,
357                                                   fontData->bytes(),
358                                                   fontData->size(),
359                                                   subset.begin(),
360                                                   subset.count(),
361                                                   &subsetFont);
362#endif
363    fontData.reset();
364    subset.reset();
365    SkASSERT(subsetFontSize > 0 || subsetFont == nullptr);
366    if (subsetFontSize < 1) {
367        return nullptr;
368    }
369    SkASSERT(subsetFont != nullptr);
370    auto subsetStream = sk_make_sp<SkPDFStream>(
371            SkData::MakeWithProc(
372                    subsetFont, subsetFontSize,
373                    [](const void* p, void*) { delete[] (unsigned char*)p; },
374                    nullptr));
375    subsetStream->dict()->insertInt("Length1", subsetFontSize);
376    return subsetStream;
377}
378#endif  // SK_PDF_USE_SFNTLY
379
380void SkPDFType0Font::getFontSubset(SkPDFCanon* canon) {
381    const SkAdvancedTypefaceMetrics* metricsPtr =
382        SkPDFFont::GetMetrics(this->typeface(), canon);
383    SkASSERT(metricsPtr);
384    if (!metricsPtr) { return; }
385    const SkAdvancedTypefaceMetrics& metrics = *metricsPtr;
386    SkASSERT(can_embed(metrics));
387    SkAdvancedTypefaceMetrics::FontType type = this->getType();
388    SkTypeface* face = this->typeface();
389    SkASSERT(face);
390
391    auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor");
392    uint16_t emSize = SkToU16(this->typeface()->getUnitsPerEm());
393    add_common_font_descriptor_entries(descriptor.get(), metrics, emSize , 0);
394
395    int ttcIndex;
396    std::unique_ptr<SkStreamAsset> fontAsset(face->openStream(&ttcIndex));
397    size_t fontSize = fontAsset ? fontAsset->getLength() : 0;
398    if (0 == fontSize) {
399        SkDebugf("Error: (SkTypeface)(%p)::openStream() returned "
400                 "empty stream (%p) when identified as kType1CID_Font "
401                 "or kTrueType_Font.\n", face, fontAsset.get());
402    } else {
403        switch (type) {
404            case SkAdvancedTypefaceMetrics::kTrueType_Font: {
405                #ifdef SK_PDF_USE_SFNTLY
406                if (!SkToBool(metrics.fFlags &
407                              SkAdvancedTypefaceMetrics::kNotSubsettable_FontFlag)) {
408                    sk_sp<SkPDFStream> subsetStream = get_subset_font_stream(
409                            std::move(fontAsset), this->glyphUsage(),
410                            metrics.fFontName.c_str(), ttcIndex);
411                    if (subsetStream) {
412                        descriptor->insertObjRef("FontFile2", std::move(subsetStream));
413                        break;
414                    }
415                    // If subsetting fails, fall back to original font data.
416                    fontAsset.reset(face->openStream(&ttcIndex));
417                    SkASSERT(fontAsset);
418                    SkASSERT(fontAsset->getLength() == fontSize);
419                    if (!fontAsset || fontAsset->getLength() == 0) { break; }
420                }
421                #endif  // SK_PDF_USE_SFNTLY
422                auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontAsset));
423                fontStream->dict()->insertInt("Length1", fontSize);
424                descriptor->insertObjRef("FontFile2", std::move(fontStream));
425                break;
426            }
427            case SkAdvancedTypefaceMetrics::kType1CID_Font: {
428                auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontAsset));
429                fontStream->dict()->insertName("Subtype", "CIDFontType0C");
430                descriptor->insertObjRef("FontFile3", std::move(fontStream));
431                break;
432            }
433            default:
434                SkASSERT(false);
435        }
436    }
437
438    auto newCIDFont = sk_make_sp<SkPDFDict>("Font");
439    newCIDFont->insertObjRef("FontDescriptor", std::move(descriptor));
440    newCIDFont->insertName("BaseFont", metrics.fFontName);
441
442    switch (type) {
443        case SkAdvancedTypefaceMetrics::kType1CID_Font:
444            newCIDFont->insertName("Subtype", "CIDFontType0");
445            break;
446        case SkAdvancedTypefaceMetrics::kTrueType_Font:
447            newCIDFont->insertName("Subtype", "CIDFontType2");
448            newCIDFont->insertName("CIDToGIDMap", "Identity");
449            break;
450        default:
451            SkASSERT(false);
452    }
453    auto sysInfo = sk_make_sp<SkPDFDict>();
454    sysInfo->insertString("Registry", "Adobe");
455    sysInfo->insertString("Ordering", "Identity");
456    sysInfo->insertInt("Supplement", 0);
457    newCIDFont->insertObject("CIDSystemInfo", std::move(sysInfo));
458
459    int16_t defaultWidth = 0;
460    {
461        int emSize;
462        SkAutoGlyphCache glyphCache = SkPDFFont::MakeVectorCache(face, &emSize);
463        sk_sp<SkPDFArray> widths = SkPDFMakeCIDGlyphWidthsArray(
464                glyphCache.get(), &this->glyphUsage(), SkToS16(emSize), &defaultWidth);
465        if (widths && widths->size() > 0) {
466            newCIDFont->insertObject("W", std::move(widths));
467        }
468        newCIDFont->insertScalar(
469                "DW", scaleFromFontUnits(defaultWidth, SkToS16(emSize)));
470    }
471
472    ////////////////////////////////////////////////////////////////////////////
473
474    this->insertName("Subtype", "Type0");
475    this->insertName("BaseFont", metrics.fFontName);
476    this->insertName("Encoding", "Identity-H");
477    auto descendantFonts = sk_make_sp<SkPDFArray>();
478    descendantFonts->appendObjRef(std::move(newCIDFont));
479    this->insertObject("DescendantFonts", std::move(descendantFonts));
480
481    if (metrics.fGlyphToUnicode.count() > 0) {
482        this->insertObjRef("ToUnicode",
483                           SkPDFMakeToUnicodeCmap(metrics.fGlyphToUnicode,
484                                                  &this->glyphUsage(),
485                                                  multiByteGlyphs(),
486                                                  firstGlyphID(),
487                                                  lastGlyphID()));
488    }
489    SkDEBUGCODE(fPopulated = true);
490    return;
491}
492
493///////////////////////////////////////////////////////////////////////////////
494// class SkPDFType1Font
495///////////////////////////////////////////////////////////////////////////////
496
497static sk_sp<SkPDFDict> make_type1_font_descriptor(
498        SkTypeface* typeface,
499        const SkAdvancedTypefaceMetrics& info) {
500    auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor");
501    uint16_t emSize = SkToU16(typeface->getUnitsPerEm());
502    add_common_font_descriptor_entries(descriptor.get(), info, emSize, 0);
503    if (!can_embed(info)) {
504        return descriptor;
505    }
506    int ttcIndex;
507    size_t header SK_INIT_TO_AVOID_WARNING;
508    size_t data SK_INIT_TO_AVOID_WARNING;
509    size_t trailer SK_INIT_TO_AVOID_WARNING;
510    std::unique_ptr<SkStreamAsset> rawFontData(typeface->openStream(&ttcIndex));
511    sk_sp<SkData> fontData = SkPDFConvertType1FontStream(std::move(rawFontData),
512                                                         &header, &data, &trailer);
513    if (fontData) {
514        auto fontStream = sk_make_sp<SkPDFStream>(std::move(fontData));
515        fontStream->dict()->insertInt("Length1", header);
516        fontStream->dict()->insertInt("Length2", data);
517        fontStream->dict()->insertInt("Length3", trailer);
518        descriptor->insertObjRef("FontFile", std::move(fontStream));
519    }
520    return descriptor;
521}
522
523static void populate_type_1_font(SkPDFDict* font,
524                                 const SkAdvancedTypefaceMetrics& info,
525                                 SkTypeface* typeface,
526                                 SkGlyphID firstGlyphID,
527                                 SkGlyphID lastGlyphID) {
528    font->insertName("Subtype", "Type1");
529    font->insertName("BaseFont", info.fFontName);
530
531    // glyphCount not including glyph 0
532    unsigned glyphCount = 1 + lastGlyphID - firstGlyphID;
533    SkASSERT(glyphCount > 0 && glyphCount <= 255);
534    font->insertInt("FirstChar", (size_t)0);
535    font->insertInt("LastChar", (size_t)glyphCount);
536    {
537        int emSize;
538        SkAutoGlyphCache glyphCache = SkPDFFont::MakeVectorCache(typeface, &emSize);
539        auto widths = sk_make_sp<SkPDFArray>();
540        SkScalar advance = glyphCache->getGlyphIDAdvance(0).fAdvanceX;
541        widths->appendScalar(from_font_units(advance, SkToU16(emSize)));
542        for (unsigned gID = firstGlyphID; gID <= lastGlyphID; gID++) {
543            advance = glyphCache->getGlyphIDAdvance(gID).fAdvanceX;
544            widths->appendScalar(from_font_units(advance, SkToU16(emSize)));
545        }
546        font->insertObject("Widths", std::move(widths));
547    }
548    auto encDiffs = sk_make_sp<SkPDFArray>();
549    encDiffs->reserve(lastGlyphID - firstGlyphID + 3);
550    encDiffs->appendInt(0);
551    const SkTArray<SkString>& glyphNames = info.fGlyphNames;
552    SkASSERT(glyphNames.count() > lastGlyphID);
553    encDiffs->appendName(glyphNames[0].c_str());
554    const SkString unknown("UNKNOWN");
555    for (int gID = firstGlyphID; gID <= lastGlyphID; gID++) {
556        const bool valid = gID < glyphNames.count() && !glyphNames[gID].isEmpty();
557        const SkString& name = valid ? glyphNames[gID] : unknown;
558        encDiffs->appendName(name);
559    }
560
561    auto encoding = sk_make_sp<SkPDFDict>("Encoding");
562    encoding->insertObject("Differences", std::move(encDiffs));
563    font->insertObject("Encoding", std::move(encoding));
564}
565
566SkPDFType1Font::SkPDFType1Font(SkPDFFont::Info info,
567                               const SkAdvancedTypefaceMetrics& metrics,
568                               SkPDFCanon* canon)
569    : SkPDFFont(std::move(info))
570{
571    SkFontID fontID = this->typeface()->uniqueID();
572    sk_sp<SkPDFDict> fontDescriptor;
573    if (sk_sp<SkPDFDict>* ptr = canon->fFontDescriptors.find(fontID)) {
574        fontDescriptor = *ptr;
575    } else {
576        fontDescriptor = make_type1_font_descriptor(this->typeface(), metrics);
577        canon->fFontDescriptors.set(fontID, fontDescriptor);
578    }
579    this->insertObjRef("FontDescriptor", std::move(fontDescriptor));
580    // TODO(halcanary): subset this (advances and names).
581    populate_type_1_font(this, metrics, this->typeface(),
582                         this->firstGlyphID(), this->lastGlyphID());
583}
584
585///////////////////////////////////////////////////////////////////////////////
586// class SkPDFType3Font
587///////////////////////////////////////////////////////////////////////////////
588
589namespace {
590// returns [0, first, first+1, ... last-1,  last]
591struct SingleByteGlyphIdIterator {
592    SingleByteGlyphIdIterator(SkGlyphID first, SkGlyphID last)
593        : fFirst(first), fLast(last) {
594        SkASSERT(fFirst > 0);
595        SkASSERT(fLast >= first);
596    }
597    struct Iter {
598        void operator++() {
599            fCurrent = (0 == fCurrent) ? fFirst : fCurrent + 1;
600        }
601        // This is an input_iterator
602        SkGlyphID operator*() const { return (SkGlyphID)fCurrent; }
603        bool operator!=(const Iter& rhs) const {
604            return fCurrent != rhs.fCurrent;
605        }
606        Iter(SkGlyphID f, int c) : fFirst(f), fCurrent(c) {}
607    private:
608        const SkGlyphID fFirst;
609        int fCurrent; // must be int to make fLast+1 to fit
610    };
611    Iter begin() const { return Iter(fFirst, 0); }
612    Iter end() const { return Iter(fFirst, (int)fLast + 1); }
613private:
614    const SkGlyphID fFirst;
615    const SkGlyphID fLast;
616};
617}
618
619static void add_type3_font_info(SkPDFCanon* canon,
620                                SkPDFDict* font,
621                                SkTypeface* typeface,
622                                const SkBitSet& subset,
623                                SkGlyphID firstGlyphID,
624                                SkGlyphID lastGlyphID) {
625    const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, canon);
626    SkASSERT(lastGlyphID >= firstGlyphID);
627    // Remove unused glyphs at the end of the range.
628    // Keep the lastGlyphID >= firstGlyphID invariant true.
629    while (lastGlyphID > firstGlyphID && !subset.has(lastGlyphID)) {
630        --lastGlyphID;
631    }
632    int unitsPerEm;
633    SkAutoGlyphCache cache = SkPDFFont::MakeVectorCache(typeface, &unitsPerEm);
634    SkScalar emSize = (SkScalar)unitsPerEm;
635    font->insertName("Subtype", "Type3");
636    // Flip about the x-axis and scale by 1/emSize.
637    SkMatrix fontMatrix;
638    fontMatrix.setScale(SkScalarInvert(emSize), -SkScalarInvert(emSize));
639    font->insertObject("FontMatrix", SkPDFUtils::MatrixToArray(fontMatrix));
640
641    auto charProcs = sk_make_sp<SkPDFDict>();
642    auto encoding = sk_make_sp<SkPDFDict>("Encoding");
643
644    auto encDiffs = sk_make_sp<SkPDFArray>();
645    // length(firstGlyphID .. lastGlyphID) ==  lastGlyphID - firstGlyphID + 1
646    // plus 1 for glyph 0;
647    SkASSERT(firstGlyphID > 0);
648    SkASSERT(lastGlyphID >= firstGlyphID);
649    int glyphCount = lastGlyphID - firstGlyphID + 2;
650    // one other entry for the index of first glyph.
651    encDiffs->reserve(glyphCount + 1);
652    encDiffs->appendInt(0);  // index of first glyph
653
654    auto widthArray = sk_make_sp<SkPDFArray>();
655    widthArray->reserve(glyphCount);
656
657    SkIRect bbox = SkIRect::MakeEmpty();
658
659    sk_sp<SkPDFStream> emptyStream;
660    for (SkGlyphID gID : SingleByteGlyphIdIterator(firstGlyphID, lastGlyphID)) {
661        bool skipGlyph = gID != 0 && !subset.has(gID);
662        SkString characterName;
663        SkScalar advance = 0.0f;
664        SkIRect glyphBBox;
665        if (skipGlyph) {
666            characterName.set("g0");
667        } else {
668            characterName.printf("g%X", gID);
669            const SkGlyph& glyph = cache->getGlyphIDMetrics(gID);
670            advance = SkFloatToScalar(glyph.fAdvanceX);
671            glyphBBox = SkIRect::MakeXYWH(glyph.fLeft, glyph.fTop,
672                                          glyph.fWidth, glyph.fHeight);
673            bbox.join(glyphBBox);
674            const SkPath* path = cache->findPath(glyph);
675            if (path && !path->isEmpty()) {
676                SkDynamicMemoryWStream content;
677                setGlyphWidthAndBoundingBox(SkFloatToScalar(glyph.fAdvanceX), glyphBBox,
678                                            &content);
679                SkPDFUtils::EmitPath(*path, SkPaint::kFill_Style, &content);
680                SkPDFUtils::PaintPath(SkPaint::kFill_Style, path->getFillType(),
681                                      &content);
682                charProcs->insertObjRef(
683                    characterName, sk_make_sp<SkPDFStream>(
684                            std::unique_ptr<SkStreamAsset>(content.detachAsStream())));
685            } else {
686                if (!emptyStream) {
687                    emptyStream = sk_make_sp<SkPDFStream>(
688                            std::unique_ptr<SkStreamAsset>(
689                                    new SkMemoryStream((size_t)0)));
690                }
691                charProcs->insertObjRef(characterName, emptyStream);
692            }
693        }
694        encDiffs->appendName(characterName.c_str());
695        widthArray->appendScalar(advance);
696    }
697
698    encoding->insertObject("Differences", std::move(encDiffs));
699    font->insertInt("FirstChar", 0);
700    font->insertInt("LastChar", lastGlyphID - firstGlyphID + 1);
701    /* FontBBox: "A rectangle expressed in the glyph coordinate
702      system, specifying the font bounding box. This is the smallest
703      rectangle enclosing the shape that would result if all of the
704      glyphs of the font were placed with their origins coincident and
705      then filled." */
706    auto fontBBox = sk_make_sp<SkPDFArray>();
707    fontBBox->reserve(4);
708    fontBBox->appendInt(bbox.left());
709    fontBBox->appendInt(bbox.bottom());
710    fontBBox->appendInt(bbox.right());
711    fontBBox->appendInt(bbox.top());
712    font->insertObject("FontBBox", std::move(fontBBox));
713    font->insertName("CIDToGIDMap", "Identity");
714    if (metrics && metrics->fGlyphToUnicode.count() > 0) {
715        font->insertObjRef("ToUnicode",
716                           SkPDFMakeToUnicodeCmap(metrics->fGlyphToUnicode,
717                                                  &subset,
718                                                  false,
719                                                  firstGlyphID,
720                                                  lastGlyphID));
721    }
722    auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor");
723    int32_t fontDescriptorFlags = kPdfSymbolic;
724    if (metrics) {
725        // Type3 FontDescriptor does not require all the same fields.
726        descriptor->insertName("FontName", metrics->fFontName);
727        descriptor->insertInt("ItalicAngle", metrics->fItalicAngle);
728        fontDescriptorFlags |= (int32_t)metrics->fStyle;
729    }
730    descriptor->insertInt("Flags", fontDescriptorFlags);
731    font->insertObjRef("FontDescriptor", std::move(descriptor));
732    font->insertObject("Widths", std::move(widthArray));
733    font->insertObject("Encoding", std::move(encoding));
734    font->insertObject("CharProcs", std::move(charProcs));
735}
736
737SkPDFType3Font::SkPDFType3Font(SkPDFFont::Info info,
738                               const SkAdvancedTypefaceMetrics& metrics)
739    : SkPDFFont(std::move(info)) {}
740
741void SkPDFType3Font::getFontSubset(SkPDFCanon* canon) {
742    add_type3_font_info(canon, this, this->typeface(), this->glyphUsage(),
743                        this->firstGlyphID(), this->lastGlyphID());
744}
745
746////////////////////////////////////////////////////////////////////////////////
747
748bool SkPDFFont::CanEmbedTypeface(SkTypeface* typeface, SkPDFCanon* canon) {
749    const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, canon);
750    return metrics && can_embed(*metrics);
751}
752
753void SkPDFFont::drop() {
754    fTypeface = nullptr;
755    fGlyphUsage.~SkBitSet();
756    new (&fGlyphUsage) SkBitSet(0);
757    this->SkPDFDict::drop();
758}
759