LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/pdf - SkPDFFont.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 413 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 47 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13