Chromium Code Reviews| Index: src/pdf/SkPDFFont.cpp |
| diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp |
| index 290061a49171440960b59d4994614d61523e79a9..887f95001f406e88f6f4d4d2e3b942d51081f7bd 100644 |
| --- a/src/pdf/SkPDFFont.cpp |
| +++ b/src/pdf/SkPDFFont.cpp |
| @@ -37,50 +37,27 @@ namespace { |
| // non-symbolic, so always call it symbolic. (PDF 1.4 spec, section 5.7.1) |
| static const int kPdfSymbolic = 4; |
| -class SkPDFType0Font final : public SkPDFFont { |
| -public: |
| - SkPDFType0Font(const SkAdvancedTypefaceMetrics& info, |
| - sk_sp<SkTypeface> typeface, |
| - SkAdvancedTypefaceMetrics::FontType type); |
| +struct SkPDFType0Font final : public SkPDFFont { |
| + SkPDFType0Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&); |
| virtual ~SkPDFType0Font(); |
| - sk_sp<SkPDFObject> getFontSubset(SkPDFCanon*, const SkPDFGlyphSet*) override; |
| -#ifdef SK_DEBUG |
| - void emitObject(SkWStream*, |
| - const SkPDFObjNumMap&, |
| - const SkPDFSubstituteMap&) const override; |
| -#endif |
| - |
| -private: |
| + void getFontSubset(SkPDFCanon*) override; |
| #ifdef SK_DEBUG |
| + void emitObject(SkWStream*, const SkPDFObjNumMap&) const override; |
| bool fPopulated; |
| #endif |
| - bool populate(const SkPDFGlyphSet* subset, |
| - const SkAdvancedTypefaceMetrics& metrics); |
| typedef SkPDFDict INHERITED; |
| }; |
| -class SkPDFType1Font final : public SkPDFFont { |
| -public: |
| - SkPDFType1Font(const SkAdvancedTypefaceMetrics& info, |
| - sk_sp<SkTypeface> typeface, |
| - uint16_t glyphID, |
| - SkPDFCanon* canon); |
| +struct SkPDFType1Font final : public SkPDFFont { |
| + SkPDFType1Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&, SkPDFCanon*); |
| virtual ~SkPDFType1Font() {} |
| + void getFontSubset(SkPDFCanon*) override {} // TODO(halcanary): implement |
|
bungeman-skia
2016/08/18 19:37:00
Is this any different from before?
hal.canary
2016/08/18 20:02:32
nope.
|
| }; |
| -class SkPDFType3Font final : public SkPDFFont { |
| -public: |
| - SkPDFType3Font(const SkAdvancedTypefaceMetrics& info, |
| - sk_sp<SkTypeface> typeface, |
| - SkAdvancedTypefaceMetrics::FontType fontType, |
| - uint16_t glyphID); |
| +struct SkPDFType3Font final : public SkPDFFont { |
| + SkPDFType3Font(SkPDFFont::Info, const SkAdvancedTypefaceMetrics&); |
| virtual ~SkPDFType3Font() {} |
| - void emitObject(SkWStream*, |
| - const SkPDFObjNumMap&, |
| - const SkPDFSubstituteMap&) const override { |
| - SkDEBUGFAIL("should call getFontSubset!"); |
| - } |
| - sk_sp<SkPDFObject> getFontSubset(SkPDFCanon*, const SkPDFGlyphSet*) override; |
| + void getFontSubset(SkPDFCanon*) override; |
| }; |
| /////////////////////////////////////////////////////////////////////////////// |
| @@ -143,58 +120,6 @@ static sk_sp<SkPDFArray> makeFontBBox(SkIRect glyphBBox, uint16_t emSize) { |
| } |
| } // namespace |
| - |
| -/////////////////////////////////////////////////////////////////////////////// |
| -// class SkPDFGlyphSet |
| -/////////////////////////////////////////////////////////////////////////////// |
| - |
| -SkPDFGlyphSet::SkPDFGlyphSet() : fBitSet(SK_MaxU16 + 1) { |
| -} |
| - |
| -void SkPDFGlyphSet::set(const uint16_t* glyphIDs, int numGlyphs) { |
| - for (int i = 0; i < numGlyphs; ++i) { |
| - fBitSet.setBit(glyphIDs[i], true); |
| - } |
| -} |
| - |
| -bool SkPDFGlyphSet::has(uint16_t glyphID) const { |
| - return fBitSet.isBitSet(glyphID); |
| -} |
| - |
| -void SkPDFGlyphSet::exportTo(SkTDArray<unsigned int>* glyphIDs) const { |
| - fBitSet.exportTo(glyphIDs); |
| -} |
| - |
| -/////////////////////////////////////////////////////////////////////////////// |
| -// class SkPDFGlyphSetMap |
| -/////////////////////////////////////////////////////////////////////////////// |
| - |
| -SkPDFGlyphSetMap::SkPDFGlyphSetMap() {} |
| - |
| -SkPDFGlyphSetMap::~SkPDFGlyphSetMap() { |
| - fMap.reset(); |
| -} |
| - |
| -void SkPDFGlyphSetMap::noteGlyphUsage(SkPDFFont* font, const uint16_t* glyphIDs, |
| - int numGlyphs) { |
| - SkPDFGlyphSet* subset = getGlyphSetForFont(font); |
| - if (subset) { |
| - subset->set(glyphIDs, numGlyphs); |
| - } |
| -} |
| - |
| -SkPDFGlyphSet* SkPDFGlyphSetMap::getGlyphSetForFont(SkPDFFont* font) { |
| - int index = fMap.count(); |
| - for (int i = 0; i < index; ++i) { |
| - if (fMap[i].fFont == font) { |
| - return &fMap[i].fGlyphSet; |
| - } |
| - } |
| - FontGlyphSetPair& pair = fMap.push_back(); |
| - pair.fFont = font; |
| - return &pair.fGlyphSet; |
| -} |
| - |
| /////////////////////////////////////////////////////////////////////////////// |
| // class SkPDFFont |
| /////////////////////////////////////////////////////////////////////////////// |
| @@ -322,47 +247,46 @@ SkPDFFont* SkPDFFont::GetFontResource(SkPDFCanon* canon, |
| return nullptr; |
| } |
| + SkGlyphID firstNonZeroGlyph; |
| + SkGlyphID lastGlyph; |
| + if (multibyte) { |
| + firstNonZeroGlyph = 1; |
| + lastGlyph = SkToU16(glyphCount - 1); |
| + } else { |
| + firstNonZeroGlyph = firstGlyph; |
| + lastGlyph = SkToU16(SkTMin<int>(glyphCount - 1, |
| + 254 + (int)firstGlyph)); |
| + } |
| + SkPDFFont::Info info = {std::move(typeface), firstNonZeroGlyph, lastGlyph, type}; |
| sk_sp<SkPDFFont> font; |
| switch (type) { |
| case SkAdvancedTypefaceMetrics::kType1CID_Font: |
| case SkAdvancedTypefaceMetrics::kTrueType_Font: |
| SkASSERT(multibyte); |
| - font = sk_make_sp<SkPDFType0Font>(metrics, |
| - std::move(typeface), |
| - type); |
| + font = sk_make_sp<SkPDFType0Font>(std::move(info), metrics); |
| break; |
| case SkAdvancedTypefaceMetrics::kType1_Font: |
| SkASSERT(!multibyte); |
| - font = sk_make_sp<SkPDFType1Font>(metrics, |
| - std::move(typeface), |
| - glyphID, |
| - canon); |
| + font = sk_make_sp<SkPDFType1Font>(std::move(info), metrics, canon); |
| break; |
| default: |
| SkASSERT(!multibyte); |
| // Type3 is our fallback font. |
| - font = sk_make_sp<SkPDFType3Font>(metrics, |
| - std::move(typeface), |
| - type, |
| - glyphID); |
| + font = sk_make_sp<SkPDFType3Font>(std::move(info), metrics); |
| break; |
| } |
| canon->fFontMap.set(fontID, SkRef(font.get())); |
| return font.release(); // TODO(halcanary) return sk_sp<SkPDFFont>. |
| } |
| -sk_sp<SkPDFObject> SkPDFFont::getFontSubset(SkPDFCanon*, const SkPDFGlyphSet*) { |
| - return nullptr; // Default: no support. |
| -} |
| - |
| -SkPDFFont::SkPDFFont(sk_sp<SkTypeface> typeface, |
| - SkAdvancedTypefaceMetrics::FontType fontType) |
| +SkPDFFont::SkPDFFont(SkPDFFont::Info info) |
| : SkPDFDict("Font") |
| - , fTypeface(std::move(typeface)) |
| - , fFirstGlyphID(1) |
| - , fFontType(fontType) { |
| + , fTypeface(std::move(info.fTypeface)) |
| + , fGlyphUsage(info.fLastGlyphID + 1) // TODO(halcanary): Adjust mapping? |
| + , fFirstGlyphID(info.fFirstGlyphID) |
| + , fLastGlyphID(info.fLastGlyphID) |
| + , fFontType(info.fFontType) { |
| SkASSERT(fTypeface); |
| - fLastGlyphID = SkToU16(fTypeface->countGlyphs() - 1); |
| } |
| static void add_common_font_descriptor_entries(SkPDFDict* descriptor, |
| @@ -388,50 +312,25 @@ static void add_common_font_descriptor_entries(SkPDFDict* descriptor, |
| } |
| } |
| -void SkPDFFont::adjustGlyphRangeForSingleByteEncoding(SkGlyphID glyphID) { |
| - // Single byte glyph encoding supports a max of 255 glyphs. |
| - fFirstGlyphID = first_glyph_for_single_byte_encoding(glyphID); |
| - if (fLastGlyphID > fFirstGlyphID + 255 - 1) { |
| - fLastGlyphID = fFirstGlyphID + 255 - 1; |
| - } |
| -} |
| - |
| /////////////////////////////////////////////////////////////////////////////// |
| // class SkPDFType0Font |
| /////////////////////////////////////////////////////////////////////////////// |
| -SkPDFType0Font::SkPDFType0Font(const SkAdvancedTypefaceMetrics& info, |
| - sk_sp<SkTypeface> typeface, |
| - SkAdvancedTypefaceMetrics::FontType fontType) |
| - : SkPDFFont(std::move(typeface), fontType) { |
| +SkPDFType0Font::SkPDFType0Font( |
| + SkPDFFont::Info info, |
| + const SkAdvancedTypefaceMetrics& metrics) |
| + : SkPDFFont(std::move(info)) { |
| SkDEBUGCODE(fPopulated = false); |
| - if (!can_subset(info)) { |
| - this->populate(nullptr, info); |
| - } |
| } |
| SkPDFType0Font::~SkPDFType0Font() {} |
| -sk_sp<SkPDFObject> SkPDFType0Font::getFontSubset(SkPDFCanon* canon, |
| - const SkPDFGlyphSet* subset) { |
| - const SkAdvancedTypefaceMetrics* metrics = |
| - SkPDFFont::GetMetrics(this->typeface(), canon); |
| - SkASSERT(metrics); |
| - if (!metrics || !can_subset(*metrics)) { |
| - return nullptr; |
| - } |
| - auto newSubset = sk_make_sp<SkPDFType0Font>( |
| - *metrics, this->refTypeface(), this->getType()); |
| - newSubset->populate(subset, *metrics); |
| - return newSubset; |
| -} |
| #ifdef SK_DEBUG |
| void SkPDFType0Font::emitObject(SkWStream* stream, |
| - const SkPDFObjNumMap& objNumMap, |
| - const SkPDFSubstituteMap& substitutes) const { |
| + const SkPDFObjNumMap& objNumMap) const { |
| SkASSERT(fPopulated); |
| - return INHERITED::emitObject(stream, objNumMap, substitutes); |
| + return INHERITED::emitObject(stream, objNumMap); |
| } |
| #endif |
| @@ -488,8 +387,12 @@ static sk_sp<SkPDFObject> get_subset_font_stream( |
| } |
| #endif // SK_SFNTLY_SUBSETTER |
| -bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset, |
| - const SkAdvancedTypefaceMetrics& metrics) { |
| +void SkPDFType0Font::getFontSubset(SkPDFCanon* canon) { |
| + const SkAdvancedTypefaceMetrics* metricsPtr = |
| + SkPDFFont::GetMetrics(this->typeface(), canon); |
| + SkASSERT(metricsPtr); |
| + if (!metricsPtr) { return; } |
| + const SkAdvancedTypefaceMetrics& metrics = *metricsPtr; |
| SkASSERT(can_embed(metrics)); |
| SkAdvancedTypefaceMetrics::FontType type = this->getType(); |
| SkTypeface* face = this->typeface(); |
| @@ -504,24 +407,22 @@ bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset, |
| std::unique_ptr<SkStreamAsset> fontAsset(face->openStream(&ttcIndex)); |
| SkASSERT(fontAsset); |
| if (!fontAsset) { |
| - return false; |
| + return; |
| } |
| size_t fontSize = fontAsset->getLength(); |
| SkASSERT(fontSize > 0); |
| if (fontSize == 0) { |
| - return false; |
| + return; |
| } |
| #ifdef SK_SFNTLY_SUBSETTER |
| - if (can_subset(metrics) && subset) { |
| + if (can_subset(metrics)) { |
| // 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); |
| + if (!this->glyphUsage().has(0)) { |
| + glyphIDs.push(0); // Always include glyph 0. |
| } |
| + this->glyphUsage().exportTo(&glyphIDs); |
| sk_sp<SkPDFObject> subsetStream = get_subset_font_stream( |
| std::move(fontAsset), glyphIDs, name.c_str()); |
| if (subsetStream) { |
| @@ -542,7 +443,7 @@ bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset, |
| SkASSERT(fontData); |
| SkASSERT(fontData->getLength() > 0); |
| if (!fontData || 0 == fontData->getLength()) { |
| - return false; |
| + return; |
| } |
| auto fontStream = sk_make_sp<SkPDFSharedStream>(std::move(fontData)); |
| fontStream->dict()->insertName("Subtype", "CIDFontType0c"); |
| @@ -574,11 +475,10 @@ bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset, |
| uint16_t emSize = metrics.fEmSize; |
| int16_t defaultWidth = 0; |
| - const SkBitSet* bitSet = subset ? &subset->bitSet() : nullptr; |
| { |
| SkAutoGlyphCache glyphCache = vector_cache(face); |
| sk_sp<SkPDFArray> widths = SkPDFMakeCIDGlyphWidthsArray( |
| - glyphCache.get(), bitSet, emSize, &defaultWidth); |
| + glyphCache.get(), &this->glyphUsage(), emSize, &defaultWidth); |
| if (widths && widths->size() > 0) { |
| newCIDFont->insertObject("W", std::move(widths)); |
| } |
| @@ -598,13 +498,13 @@ bool SkPDFType0Font::populate(const SkPDFGlyphSet* subset, |
| if (metrics.fGlyphToUnicode.count() > 0) { |
| this->insertObjRef("ToUnicode", |
| SkPDFMakeToUnicodeCmap(metrics.fGlyphToUnicode, |
| - subset, |
| + &this->glyphUsage(), |
| multiByteGlyphs(), |
| firstGlyphID(), |
| lastGlyphID())); |
| } |
| SkDEBUGCODE(fPopulated = true); |
| - return true; |
| + return; |
| } |
| /////////////////////////////////////////////////////////////////////////////// |
| @@ -679,24 +579,22 @@ static void populate_type_1_font(SkPDFDict* font, |
| font->insertObject("Encoding", std::move(encoding)); |
| } |
| -SkPDFType1Font::SkPDFType1Font(const SkAdvancedTypefaceMetrics& info, |
| - sk_sp<SkTypeface> typeface, |
| - uint16_t glyphID, |
| +SkPDFType1Font::SkPDFType1Font(SkPDFFont::Info info, |
| + const SkAdvancedTypefaceMetrics& metrics, |
| SkPDFCanon* canon) |
| - : SkPDFFont(std::move(typeface), SkAdvancedTypefaceMetrics::kType1_Font) |
| + : SkPDFFont(std::move(info)) |
| { |
| SkFontID fontID = this->typeface()->uniqueID(); |
| sk_sp<SkPDFDict> fontDescriptor; |
| if (SkPDFDict** ptr = canon->fFontDescriptors.find(fontID)) { |
| fontDescriptor = sk_ref_sp(*ptr); |
| } else { |
| - fontDescriptor = make_type1_font_descriptor(this->typeface(), info); |
| + fontDescriptor = make_type1_font_descriptor(this->typeface(), metrics); |
| canon->fFontDescriptors.set(fontID, SkRef(fontDescriptor.get())); |
| } |
| this->insertObjRef("FontDescriptor", std::move(fontDescriptor)); |
| - this->adjustGlyphRangeForSingleByteEncoding(glyphID); |
| // TODO(halcanary): subset this (advances and names). |
|
bungeman-skia
2016/08/18 19:37:00
This is logically the same TODO as the one added a
hal.canary
2016/08/18 20:02:32
yes
|
| - populate_type_1_font(this, info, this->typeface(), |
| + populate_type_1_font(this, metrics, this->typeface(), |
| this->firstGlyphID(), this->lastGlyphID()); |
| } |
| @@ -738,7 +636,7 @@ static void add_type3_font_info(SkPDFCanon* canon, |
| SkPDFDict* font, |
| SkTypeface* typeface, |
| SkScalar emSize, |
| - const SkPDFGlyphSet* subset, |
| + const SkBitSet& subset, |
| SkGlyphID firstGlyphID, |
| SkGlyphID lastGlyphID) { |
| SkASSERT(lastGlyphID >= firstGlyphID); |
| @@ -770,7 +668,7 @@ static void add_type3_font_info(SkPDFCanon* canon, |
| sk_sp<SkPDFStream> emptyStream; |
| for (SkGlyphID gID : SingleByteGlyphIdIterator(firstGlyphID, lastGlyphID)) { |
| - bool skipGlyph = subset && gID != 0 && !subset->has(gID); |
| + bool skipGlyph = gID != 0 && !subset.has(gID); |
| SkString characterName; |
| SkScalar advance = 0.0f; |
| SkIRect glyphBBox; |
| @@ -827,7 +725,7 @@ static void add_type3_font_info(SkPDFCanon* canon, |
| if (metrics /* && metrics->fGlyphToUnicode.count() > 0 */) { |
| font->insertObjRef("ToUnicode", |
| SkPDFMakeToUnicodeCmap(metrics->fGlyphToUnicode, |
| - subset, |
| + &subset, |
| false, |
| firstGlyphID, |
| lastGlyphID)); |
| @@ -837,29 +735,20 @@ static void add_type3_font_info(SkPDFCanon* canon, |
| font->insertObject("CharProcs", std::move(charProcs)); |
| } |
| -SkPDFType3Font::SkPDFType3Font(const SkAdvancedTypefaceMetrics& info, |
| - sk_sp<SkTypeface> typeface, |
| - SkAdvancedTypefaceMetrics::FontType fontType, |
| - uint16_t glyphID) |
| - : SkPDFFont(std::move(typeface), fontType) { |
| - this->adjustGlyphRangeForSingleByteEncoding(glyphID); |
| -} |
| +SkPDFType3Font::SkPDFType3Font(SkPDFFont::Info info, |
| + const SkAdvancedTypefaceMetrics& metrics) |
| + : SkPDFFont(std::move(info)) {} |
| -sk_sp<SkPDFObject> SkPDFType3Font::getFontSubset(SkPDFCanon* canon, |
| - const SkPDFGlyphSet* usage) { |
| - // All fonts are subset before serialization. |
| - // TODO(halcanary): all fonts should follow this pattern. |
| +void SkPDFType3Font::getFontSubset(SkPDFCanon* canon) { |
| const SkAdvancedTypefaceMetrics* info = |
| SkPDFFont::GetMetrics(this->typeface(), canon); |
| SkASSERT(info); |
| uint16_t emSize = info->fEmSize > 0 ? info->fEmSize : 1000; |
| - auto font = sk_make_sp<SkPDFDict>("Font"); |
| - add_type3_font_info(canon, font.get(), this->typeface(), (SkScalar)emSize, usage, |
| + add_type3_font_info(canon, this, this->typeface(), (SkScalar)emSize, |
| + this->glyphUsage(), |
| this->firstGlyphID(), this->lastGlyphID()); |
| - return font; |
| } |
| - |
| //////////////////////////////////////////////////////////////////////////////// |
| bool SkPDFFont::CanEmbedTypeface(SkTypeface* typeface, SkPDFCanon* canon) { |