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