Chromium Code Reviews| Index: src/pdf/SkPDFFont.cpp |
| diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp |
| index 05dbdc7e55deabd8ba59c5b388018a1cf97355c2..fea009d31b1d408ff31091fb225ebcb43c2c87c7 100644 |
| --- a/src/pdf/SkPDFFont.cpp |
| +++ b/src/pdf/SkPDFFont.cpp |
| @@ -75,20 +75,6 @@ private: |
| typedef SkPDFDict INHERITED; |
| }; |
| -class SkPDFCIDFont final : public SkPDFFont { |
| -public: |
| - SkPDFCIDFont(const SkAdvancedTypefaceMetrics* info, |
| - SkTypeface* typeface, |
| - const SkPDFGlyphSet* subset); |
| - virtual ~SkPDFCIDFont(); |
| - bool multiByteGlyphs() const override { return true; } |
| - |
| -private: |
| - bool populate(const SkPDFGlyphSet* subset); |
| - bool addFontDescriptor(int16_t defaultWidth, |
| - const SkTDArray<uint32_t>* subset); |
| -}; |
| - |
| class SkPDFType1Font final : public SkPDFFont { |
| public: |
| SkPDFType1Font(const SkAdvancedTypefaceMetrics* info, |
| @@ -180,16 +166,7 @@ static void FinishRange( |
| zeroWildcardsInRange(range); |
| } |
| - |
| -/** Retrieve advance data for glyphs. Used by the PDF backend. |
| - @param num_glyphs Total number of glyphs in the given font. |
| - @param glyphIDs For per-glyph info, specify subset of the |
| - font by giving glyph ids. Each integer |
| - represents a glyph id. Passing nullptr |
| - means all glyphs in the font. |
| - @param glyphIDsCount Number of elements in subsetGlyphIds. |
| - Ignored if glyphIDs is nullptr. |
| -*/ |
| +/** Retrieve advance data for glyphs. Used by the PDF backend. */ |
| // TODO(halcanary): this function is complex enough to need its logic |
| // tested with unit tests. On the other hand, I want to do another |
| // round of re-factoring before figuring out how to mock this. |
| @@ -197,11 +174,17 @@ static void FinishRange( |
| // composeAdvanceData() so that we don't need to produce a linked list |
| // of intermediate values. Or we could make the intermediate value |
| // something other than a linked list. |
| -static void get_glyph_widths(SkSinglyLinkedList<AdvanceMetric>* glyphWidths, |
| - int num_glyphs, |
| - const uint32_t* subsetGlyphIDs, |
| - uint32_t subsetGlyphIDsLength, |
| - SkGlyphCache* glyphCache) { |
| +static void set_glyph_widths(SkTypeface* typeface, |
| + const SkPDFGlyphSet* subset, |
| + SkSinglyLinkedList<AdvanceMetric>* glyphWidths) { |
| + SkPaint tmpPaint; |
| + tmpPaint.setHinting(SkPaint::kNo_Hinting); |
| + tmpPaint.setTypeface(sk_ref_sp(typeface)); |
| + tmpPaint.setTextSize((SkScalar)typeface->getUnitsPerEm()); |
| + const SkSurfaceProps props(0, kUnknown_SkPixelGeometry); |
| + SkAutoGlyphCache glyphCache(tmpPaint, &props, nullptr); |
| + SkASSERT(glyphCache.get()); |
| + |
| // Assuming that on average, the ASCII representation of an advance plus |
| // a space is 8 characters and the ASCII representation of a glyph id is 3 |
| // characters, then the following cut offs for using different range types |
| @@ -217,34 +200,28 @@ static void get_glyph_widths(SkSinglyLinkedList<AdvanceMetric>* glyphWidths, |
| // d. Removing a leading 0/don't cares is a win because it is omitted |
| // e. Removing 2 repeating advances is a win |
| + int num_glyphs = typeface->countGlyphs(); |
| + |
| AdvanceMetric* prevRange = nullptr; |
| int16_t lastAdvance = kInvalidAdvance; |
| int repeatedAdvances = 0; |
| int wildCardsInRun = 0; |
| int trailingWildCards = 0; |
| - uint32_t subsetIndex = 0; |
| // Limit the loop count to glyph id ranges provided. |
| - int firstIndex = 0; |
| int lastIndex = num_glyphs; |
| - if (subsetGlyphIDs) { |
| - firstIndex = static_cast<int>(subsetGlyphIDs[0]); |
| - lastIndex = |
| - static_cast<int>(subsetGlyphIDs[subsetGlyphIDsLength - 1]) + 1; |
| + if (subset) { |
| + while (!subset->has(lastIndex - 1) && lastIndex > 0) { |
| + --lastIndex; |
| + } |
| } |
| - AdvanceMetric curRange(firstIndex); |
| + AdvanceMetric curRange(0); |
| - for (int gId = firstIndex; gId <= lastIndex; gId++) { |
| + for (int gId = 0; gId <= lastIndex; gId++) { |
| int16_t advance = kInvalidAdvance; |
| if (gId < lastIndex) { |
| - // Get glyph id only when subset is nullptr, or the id is in subset. |
| - SkASSERT(!subsetGlyphIDs || (subsetIndex < subsetGlyphIDsLength && |
| - static_cast<uint32_t>(gId) <= subsetGlyphIDs[subsetIndex])); |
| - if (!subsetGlyphIDs || |
| - (subsetIndex < subsetGlyphIDsLength && |
| - static_cast<uint32_t>(gId) == subsetGlyphIDs[subsetIndex])) { |
| + if (!subset || 0 == gId || subset->has(gId)) { |
| advance = (int16_t)glyphCache->getGlyphIDAdvance(gId).fAdvanceX; |
| - ++subsetIndex; |
| } else { |
| advance = kDontCareAdvance; |
| } |
| @@ -322,7 +299,6 @@ static void get_glyph_widths(SkSinglyLinkedList<AdvanceMetric>* glyphWidths, |
| //////////////////////////////////////////////////////////////////////////////// |
| - |
| // scale from em-units to base-1000, returning as a SkScalar |
| SkScalar from_font_units(SkScalar scaled, uint16_t emSize) { |
| if (emSize == 1000) { |
| @@ -669,33 +645,27 @@ void SkPDFFont::setFontDescriptor(SkPDFDict* descriptor) { |
| SkSafeRef(descriptor); |
| } |
| -bool SkPDFFont::addCommonFontDescriptorEntries(int16_t defaultWidth) { |
| - if (fDescriptor.get() == nullptr) { |
| - return false; |
| - } |
| - |
| - const uint16_t emSize = fFontInfo->fEmSize; |
| - |
| - fDescriptor->insertName("FontName", fFontInfo->fFontName); |
| - fDescriptor->insertInt("Flags", fFontInfo->fStyle | kPdfSymbolic); |
| - fDescriptor->insertScalar("Ascent", |
| - scaleFromFontUnits(fFontInfo->fAscent, emSize)); |
| - fDescriptor->insertScalar("Descent", |
| - scaleFromFontUnits(fFontInfo->fDescent, emSize)); |
| - fDescriptor->insertScalar("StemV", |
| - scaleFromFontUnits(fFontInfo->fStemV, emSize)); |
| - |
| - fDescriptor->insertScalar("CapHeight", |
| - scaleFromFontUnits(fFontInfo->fCapHeight, emSize)); |
| - fDescriptor->insertInt("ItalicAngle", fFontInfo->fItalicAngle); |
| - fDescriptor->insertObject( |
| - "FontBBox", makeFontBBox(fFontInfo->fBBox, fFontInfo->fEmSize)); |
| - |
| +static void add_common_font_descriptor_entries(SkPDFDict* descriptor, |
| + const SkAdvancedTypefaceMetrics& metrics, |
| + int16_t defaultWidth) { |
| + const uint16_t emSize = metrics.fEmSize; |
| + descriptor->insertName("FontName", metrics.fFontName); |
| + descriptor->insertInt("Flags", metrics.fStyle | kPdfSymbolic); |
| + descriptor->insertScalar("Ascent", |
| + scaleFromFontUnits(metrics.fAscent, emSize)); |
| + descriptor->insertScalar("Descent", |
| + scaleFromFontUnits(metrics.fDescent, emSize)); |
| + descriptor->insertScalar("StemV", |
| + scaleFromFontUnits(metrics.fStemV, emSize)); |
| + descriptor->insertScalar("CapHeight", |
| + scaleFromFontUnits(metrics.fCapHeight, emSize)); |
| + descriptor->insertInt("ItalicAngle", metrics.fItalicAngle); |
| + descriptor->insertObject( |
| + "FontBBox", makeFontBBox(metrics.fBBox, metrics.fEmSize)); |
| if (defaultWidth > 0) { |
| - fDescriptor->insertScalar("MissingWidth", |
| + descriptor->insertScalar("MissingWidth", |
| scaleFromFontUnits(defaultWidth, emSize)); |
| } |
| - return true; |
| } |
| void SkPDFFont::adjustGlyphRangeForSingleByteEncoding(uint16_t glyphID) { |
| @@ -750,36 +720,6 @@ void SkPDFType0Font::emitObject(SkWStream* stream, |
| } |
| #endif |
| -bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset) { |
| - insertName("Subtype", "Type0"); |
| - insertName("BaseFont", fontInfo()->fFontName); |
| - insertName("Encoding", "Identity-H"); |
| - |
| - sk_sp<SkPDFCIDFont> newCIDFont( |
| - new SkPDFCIDFont(fontInfo(), typeface(), subset)); |
| - auto descendantFonts = sk_make_sp<SkPDFArray>(); |
| - descendantFonts->appendObjRef(std::move(newCIDFont)); |
| - this->insertObject("DescendantFonts", std::move(descendantFonts)); |
| - |
| - this->populateToUnicodeTable(subset); |
| - |
| - SkDEBUGCODE(fPopulated = true); |
| - return true; |
| -} |
| - |
| -/////////////////////////////////////////////////////////////////////////////// |
| -// class SkPDFCIDFont |
| -/////////////////////////////////////////////////////////////////////////////// |
| - |
| -SkPDFCIDFont::SkPDFCIDFont(const SkAdvancedTypefaceMetrics* info, |
| - SkTypeface* typeface, |
| - const SkPDFGlyphSet* subset) |
| - : SkPDFFont(info, typeface, nullptr) { |
| - this->populate(subset); |
| -} |
| - |
| -SkPDFCIDFont::~SkPDFCIDFont() {} |
| - |
| #ifdef SK_SFNTLY_SUBSETTER |
| // if possible, make no copy. |
| static sk_sp<SkData> stream_to_data(std::unique_ptr<SkStreamAsset> stream) { |
| @@ -833,21 +773,21 @@ static sk_sp<SkPDFObject> get_subset_font_stream( |
| } |
| #endif // SK_SFNTLY_SUBSETTER |
| -bool SkPDFCIDFont::addFontDescriptor(int16_t defaultWidth, |
| - const SkTDArray<uint32_t>* subset) { |
| - auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor"); |
| - setFontDescriptor(descriptor.get()); |
| - if (!addCommonFontDescriptorEntries(defaultWidth)) { |
| - this->insertObjRef("FontDescriptor", std::move(descriptor)); |
| - return false; |
| - } |
| +bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset) { |
| SkASSERT(this->canEmbed()); |
| + SkASSERT(this->fontInfo()); |
| + const SkAdvancedTypefaceMetrics& metrics = *(this->fontInfo()); |
| + SkAdvancedTypefaceMetrics::FontType type = this->getType(); |
| + SkTypeface* face = this->typeface(); |
| + SkASSERT(face); |
| + const char* name = metrics.fFontName.c_str(); |
| - switch (getType()) { |
| + auto descriptor = sk_make_sp<SkPDFDict>("FontDescriptor"); |
| + add_common_font_descriptor_entries(descriptor.get(), metrics, 0); |
| + switch (type) { |
| case SkAdvancedTypefaceMetrics::kTrueType_Font: { |
| int ttcIndex; |
| - std::unique_ptr<SkStreamAsset> fontAsset( |
| - this->typeface()->openStream(&ttcIndex)); |
| + std::unique_ptr<SkStreamAsset> fontAsset(face->openStream(&ttcIndex)); |
| SkASSERT(fontAsset); |
| if (!fontAsset) { |
| return false; |
| @@ -860,14 +800,22 @@ bool SkPDFCIDFont::addFontDescriptor(int16_t defaultWidth, |
| #ifdef SK_SFNTLY_SUBSETTER |
| if (this->canSubset() && subset) { |
| + // Generate glyph id array. in format needed by sfntly |
| + SkTDArray<uint32_t> glyphIDs; |
| + if (subset) { |
| + if (!subset->has(0)) { |
| + glyphIDs.push(0); // Always include glyph 0. |
| + } |
| + subset->exportTo(&glyphIDs); |
| + } |
| sk_sp<SkPDFObject> subsetStream = get_subset_font_stream( |
| - std::move(fontAsset), *subset, fontInfo()->fFontName.c_str()); |
| + std::move(fontAsset), glyphIDs, name); |
| if (subsetStream) { |
| descriptor->insertObjRef("FontFile2", std::move(subsetStream)); |
| break; |
| } |
| // If subsetting fails, fall back to original font data. |
| - fontAsset.reset(this->typeface()->openStream(&ttcIndex)); |
| + fontAsset.reset(face->openStream(&ttcIndex)); |
| } |
| #endif // SK_SFNTLY_SUBSETTER |
| auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontAsset)); |
| @@ -875,91 +823,31 @@ bool SkPDFCIDFont::addFontDescriptor(int16_t defaultWidth, |
| descriptor->insertObjRef("FontFile2", std::move(fontStream)); |
| break; |
| } |
| - case SkAdvancedTypefaceMetrics::kCFF_Font: |
| case SkAdvancedTypefaceMetrics::kType1CID_Font: { |
| - std::unique_ptr<SkStreamAsset> fontData( |
| - this->typeface()->openStream(nullptr)); |
| + std::unique_ptr<SkStreamAsset> fontData(face->openStream(nullptr)); |
| SkASSERT(fontData); |
| SkASSERT(fontData->getLength() > 0); |
| if (!fontData || 0 == fontData->getLength()) { |
| return false; |
| } |
| auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontData)); |
| - if (getType() == SkAdvancedTypefaceMetrics::kCFF_Font) { |
| - fontStream->dict()->insertName("Subtype", "Type1C"); |
| - } else { |
| - fontStream->dict()->insertName("Subtype", "CIDFontType0c"); |
| - } |
| + fontStream->dict()->insertName("Subtype", "CIDFontType0c"); |
| descriptor->insertObjRef("FontFile3", std::move(fontStream)); |
| break; |
| } |
| default: |
| SkASSERT(false); |
| } |
| - this->insertObjRef("FontDescriptor", std::move(descriptor)); |
| - return true; |
| -} |
| - |
| -void set_glyph_widths(SkTypeface* tf, |
| - const SkTDArray<uint32_t>* glyphIDs, |
| - SkSinglyLinkedList<AdvanceMetric>* dst) { |
| - SkPaint tmpPaint; |
| - tmpPaint.setHinting(SkPaint::kNo_Hinting); |
| - tmpPaint.setTypeface(sk_ref_sp(tf)); |
| - tmpPaint.setTextSize((SkScalar)tf->getUnitsPerEm()); |
| - const SkSurfaceProps props(0, kUnknown_SkPixelGeometry); |
| - SkAutoGlyphCache autoGlyphCache(tmpPaint, &props, nullptr); |
| - if (!glyphIDs || glyphIDs->isEmpty()) { |
| - get_glyph_widths(dst, tf->countGlyphs(), nullptr, 0, autoGlyphCache.get()); |
| - } else { |
| - get_glyph_widths(dst, tf->countGlyphs(), glyphIDs->begin(), |
| - glyphIDs->count(), autoGlyphCache.get()); |
| - } |
| -} |
| - |
| -sk_sp<const SkAdvancedTypefaceMetrics> SkPDFFont::GetFontMetricsWithGlyphNames( |
| - SkTypeface* typeface, uint32_t* glyphs, uint32_t glyphsCount) { |
| - return sk_sp<const SkAdvancedTypefaceMetrics>( |
| - typeface->getAdvancedTypefaceMetrics( |
| - SkTypeface::kGlyphNames_PerGlyphInfo, glyphs, glyphsCount)); |
| -} |
| - |
| -sk_sp<const SkAdvancedTypefaceMetrics> SkPDFFont::GetFontMetricsWithToUnicode( |
| - SkTypeface* typeface, uint32_t* glyphs, uint32_t glyphsCount) { |
| - return sk_sp<const SkAdvancedTypefaceMetrics>( |
| - typeface->getAdvancedTypefaceMetrics( |
| - SkTypeface::kToUnicode_PerGlyphInfo, glyphs, glyphsCount)); |
| -} |
| - |
| -bool SkPDFCIDFont::populate(const SkPDFGlyphSet* subset) { |
| - // Generate new font metrics with advance info for true type fonts. |
| - // Generate glyph id array. |
| - SkTDArray<uint32_t> glyphIDs; |
| - if (subset) { |
| - if (!subset->has(0)) { |
| - glyphIDs.push(0); // Always include glyph 0. |
| - } |
| - subset->exportTo(&glyphIDs); |
| - } |
| - if (fontInfo()->fType == SkAdvancedTypefaceMetrics::kTrueType_Font) { |
| - uint32_t* glyphs = (glyphIDs.count() == 0) ? nullptr : glyphIDs.begin(); |
| - uint32_t glyphsCount = glyphs ? glyphIDs.count() : 0; |
| - sk_sp<const SkAdvancedTypefaceMetrics> fontMetrics = |
| - SkPDFFont::GetFontMetricsWithGlyphNames(this->typeface(), glyphs, glyphsCount); |
| - this->setFontInfo(fontMetrics.get()); |
| - this->addFontDescriptor(0, &glyphIDs); |
| - } else { |
| - // Other CID fonts |
| - addFontDescriptor(0, nullptr); |
| - } |
| - insertName("BaseFont", fontInfo()->fFontName); |
| + auto newCIDFont = sk_make_sp<SkPDFDict>("Font"); |
| + newCIDFont->insertObjRef("FontDescriptor", std::move(descriptor)); |
| + newCIDFont->insertName("BaseFont", fontInfo()->fFontName); |
| - if (getType() == SkAdvancedTypefaceMetrics::kType1CID_Font) { |
| - insertName("Subtype", "CIDFontType0"); |
| - } else if (getType() == SkAdvancedTypefaceMetrics::kTrueType_Font) { |
| - insertName("Subtype", "CIDFontType2"); |
| - insertName("CIDToGIDMap", "Identity"); |
| + if (type == SkAdvancedTypefaceMetrics::kType1CID_Font) { |
| + newCIDFont->insertName("Subtype", "CIDFontType0"); |
| + } else if (type == SkAdvancedTypefaceMetrics::kTrueType_Font) { |
| + newCIDFont->insertName("Subtype", "CIDFontType2"); |
| + newCIDFont->insertName("CIDToGIDMap", "Identity"); |
| } else { |
| SkASSERT(false); |
| } |
| @@ -968,22 +856,49 @@ bool SkPDFCIDFont::populate(const SkPDFGlyphSet* subset) { |
| sysInfo->insertString("Registry", "Adobe"); |
| sysInfo->insertString("Ordering", "Identity"); |
| sysInfo->insertInt("Supplement", 0); |
| - this->insertObject("CIDSystemInfo", std::move(sysInfo)); |
| + newCIDFont->insertObject("CIDSystemInfo", std::move(sysInfo)); |
| SkSinglyLinkedList<AdvanceMetric> tmpMetrics; |
| - set_glyph_widths(this->typeface(), &glyphIDs, &tmpMetrics); |
| + set_glyph_widths(face, subset, &tmpMetrics); |
| int16_t defaultWidth = 0; |
| uint16_t emSize = (uint16_t)this->fontInfo()->fEmSize; |
| sk_sp<SkPDFArray> widths = composeAdvanceData(tmpMetrics, emSize, &defaultWidth); |
| if (widths->size()) { |
| - this->insertObject("W", std::move(widths)); |
| + newCIDFont->insertObject("W", std::move(widths)); |
| } |
| - this->insertScalar( |
| + newCIDFont->insertScalar( |
| "DW", scaleFromFontUnits(defaultWidth, emSize)); |
| + |
| + |
| + //////////////////////////////////////////////////////////////////////////// |
| + |
| + this->insertName("Subtype", "Type0"); |
| + this->insertName("BaseFont", metrics.fFontName); |
| + this->insertName("Encoding", "Identity-H"); |
| + auto descendantFonts = sk_make_sp<SkPDFArray>(); |
| + descendantFonts->appendObjRef(std::move(newCIDFont)); |
| + this->insertObject("DescendantFonts", std::move(descendantFonts)); |
| + this->populateToUnicodeTable(subset); |
| + SkDEBUGCODE(fPopulated = true); |
| return true; |
| } |
| +sk_sp<const SkAdvancedTypefaceMetrics> SkPDFFont::GetFontMetricsWithGlyphNames( |
|
bungeman-skia
2016/08/16 14:39:30
It doesn't look like this method is used anymore?
hal.canary
2016/08/16 15:07:31
right. removed
|
| + SkTypeface* typeface, uint32_t* glyphs, uint32_t glyphsCount) { |
| + return sk_sp<const SkAdvancedTypefaceMetrics>( |
| + typeface->getAdvancedTypefaceMetrics( |
| + SkTypeface::kGlyphNames_PerGlyphInfo, glyphs, glyphsCount)); |
| +} |
| + |
| +sk_sp<const SkAdvancedTypefaceMetrics> SkPDFFont::GetFontMetricsWithToUnicode( |
|
bungeman-skia
2016/08/16 14:39:30
Neither is this one?
hal.canary
2016/08/16 15:07:30
Called by add_type3_font_info()
|
| + SkTypeface* typeface, uint32_t* glyphs, uint32_t glyphsCount) { |
| + return sk_sp<const SkAdvancedTypefaceMetrics>( |
| + typeface->getAdvancedTypefaceMetrics( |
| + SkTypeface::kToUnicode_PerGlyphInfo, glyphs, glyphsCount)); |
| +} |
| + |
| + |
| /////////////////////////////////////////////////////////////////////////////// |
| // class SkPDFType1Font |
| /////////////////////////////////////////////////////////////////////////////// |
| @@ -1025,9 +940,12 @@ bool SkPDFType1Font::addFontDescriptor(int16_t defaultWidth) { |
| fontStream->dict()->insertInt("Length3", trailer); |
| descriptor->insertObjRef("FontFile", std::move(fontStream)); |
| + SkASSERT(this->fontInfo()); |
| + add_common_font_descriptor_entries(descriptor.get(), |
| + *this->fontInfo(), |
| + defaultWidth); |
| this->insertObjRef("FontDescriptor", std::move(descriptor)); |
| - |
| - return addCommonFontDescriptorEntries(defaultWidth); |
| + return true; |
| } |
| bool SkPDFType1Font::populate(int16_t glyphID) { |