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 "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 
     29 SkAutoGlyphCache 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 
     47 namespace {
     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)
     51 static const int32_t kPdfSymbolic = 4;
     52 
     53 struct 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 
     64 struct SkPDFType1Font final : public SkPDFFont {
     65     SkPDFType1Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&, SkPDFCanon*);
     66     ~SkPDFType1Font() override {}
     67     void getFontSubset(SkPDFCanon*) override {} // TODO(halcanary): implement
     68 };
     69 
     70 struct 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
     81 SkScalar 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 
     89 SkScalar scaleFromFontUnits(int16_t val, uint16_t emSize) {
     90     return from_font_units(SkIntToScalar(val), emSize);
     91 }
     92 
     93 
     94 void 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 
    109 static 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 
    136 SkPDFFont::~SkPDFFont() {}
    137 
    138 static bool can_embed(const SkAdvancedTypefaceMetrics& metrics) {
    139     return !SkToBool(metrics.fFlags & SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag);
    140 }
    141 
    142 const 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 
    190 SkAdvancedTypefaceMetrics::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 
    199 static SkGlyphID first_nonzero_glyph_for_single_byte_encoding(SkGlyphID gid) {
    200     return gid != 0 ? gid - (gid - 1) % 255 : 1;
    201 }
    202 
    203 sk_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 
    260 SkPDFFont::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 
    270 static 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 
    297 SkPDFType0Font::SkPDFType0Font(
    298         SkPDFFont::Info info,
    299         const SkAdvancedTypefaceMetrics& metrics)
    300     : SkPDFFont(std::move(info)) {
    301     SkDEBUGCODE(fPopulated = false);
    302 }
    303 
    304 SkPDFType0Font::~SkPDFType0Font() {}
    305 
    306 
    307 #ifdef SK_DEBUG
    308 void 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.
    317 static 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 
    330 static 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 
    380 void 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 
    497 static 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 
    523 static 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 
    566 SkPDFType1Font::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 
    589 namespace {
    590 // returns [0, first, first+1, ... last-1,  last]
    591 struct 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); }
    613 private:
    614     const SkGlyphID fFirst;
    615     const SkGlyphID fLast;
    616 };
    617 }
    618 
    619 static 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 
    737 SkPDFType3Font::SkPDFType3Font(SkPDFFont::Info info,
    738                                const SkAdvancedTypefaceMetrics& metrics)
    739     : SkPDFFont(std::move(info)) {}
    740 
    741 void SkPDFType3Font::getFontSubset(SkPDFCanon* canon) {
    742     add_type3_font_info(canon, this, this->typeface(), this->glyphUsage(),
    743                         this->firstGlyphID(), this->lastGlyphID());
    744 }
    745 
    746 ////////////////////////////////////////////////////////////////////////////////
    747 
    748 bool SkPDFFont::CanEmbedTypeface(SkTypeface* typeface, SkPDFCanon* canon) {
    749     const SkAdvancedTypefaceMetrics* metrics = SkPDFFont::GetMetrics(typeface, canon);
    750     return metrics && can_embed(*metrics);
    751 }
    752 
    753 void SkPDFFont::drop() {
    754     fTypeface = nullptr;
    755     fGlyphUsage.~SkBitSet();
    756     new (&fGlyphUsage) SkBitSet(0);
    757     this->SkPDFDict::drop();
    758 }
    759