diff options
Diffstat (limited to 'src/pdf')
-rw-r--r-- | src/pdf/SkPDFBitmap.cpp | 34 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.cpp | 11 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.h | 4 | ||||
-rw-r--r-- | src/pdf/SkPDFDocument.cpp | 33 | ||||
-rw-r--r-- | src/pdf/SkPDFDocument.h | 9 | ||||
-rw-r--r-- | src/pdf/SkPDFFont.cpp | 243 | ||||
-rw-r--r-- | src/pdf/SkPDFFont.h | 73 | ||||
-rw-r--r-- | src/pdf/SkPDFGraphicState.cpp | 5 | ||||
-rw-r--r-- | src/pdf/SkPDFGraphicState.h | 3 | ||||
-rw-r--r-- | src/pdf/SkPDFMakeToUnicodeCmap.cpp | 4 | ||||
-rw-r--r-- | src/pdf/SkPDFMakeToUnicodeCmap.h | 4 | ||||
-rw-r--r-- | src/pdf/SkPDFMetadata.cpp | 5 | ||||
-rw-r--r-- | src/pdf/SkPDFTypes.cpp | 120 | ||||
-rw-r--r-- | src/pdf/SkPDFTypes.h | 73 |
14 files changed, 178 insertions, 443 deletions
diff --git a/src/pdf/SkPDFBitmap.cpp b/src/pdf/SkPDFBitmap.cpp index 772745ca50..2d789d04d8 100644 --- a/src/pdf/SkPDFBitmap.cpp +++ b/src/pdf/SkPDFBitmap.cpp @@ -346,8 +346,7 @@ static void emit_image_xobject(SkWStream* stream, const SkImage* image, bool alpha, const sk_sp<SkPDFObject>& smask, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) { + const SkPDFObjNumMap& objNumMap) { SkBitmap bitmap; image_get_ro_pixels(image, &bitmap); // TODO(halcanary): test SkAutoLockPixels autoLockPixels(bitmap); // with malformed images. @@ -385,7 +384,7 @@ static void emit_image_xobject(SkWStream* stream, pdfDict.insertInt("BitsPerComponent", 8); pdfDict.insertName("Filter", "FlateDecode"); pdfDict.insertInt("Length", asset->getLength()); - pdfDict.emitObject(stream, objNumMap, substitutes); + pdfDict.emitObject(stream, objNumMap); pdf_stream_begin(stream); stream->writeStream(asset.get(), asset->getLength()); @@ -400,10 +399,9 @@ class PDFAlphaBitmap final : public SkPDFObject { public: PDFAlphaBitmap(sk_sp<SkImage> image) : fImage(std::move(image)) { SkASSERT(fImage); } void emitObject(SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& subs) const override { + const SkPDFObjNumMap& objNumMap) const override { SkASSERT(fImage); - emit_image_xobject(stream, fImage.get(), true, nullptr, objNumMap, subs); + emit_image_xobject(stream, fImage.get(), true, nullptr, objNumMap); } void drop() override { fImage = nullptr; } @@ -419,19 +417,12 @@ namespace { class PDFDefaultBitmap final : public SkPDFObject { public: void emitObject(SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& subs) const override { + const SkPDFObjNumMap& objNumMap) const override { SkASSERT(fImage); - emit_image_xobject(stream, fImage.get(), false, fSMask, objNumMap, subs); + emit_image_xobject(stream, fImage.get(), false, fSMask, objNumMap); } - void addResources(SkPDFObjNumMap* catalog, - const SkPDFSubstituteMap& subs) const override { - SkASSERT(fImage); - if (fSMask.get()) { - SkPDFObject* obj = subs.getSubstitute(fSMask.get()); - SkASSERT(obj); - catalog->addObjectRecursively(obj, subs); - } + void addResources(SkPDFObjNumMap* catalog) const override { + catalog->addObjectRecursively(fSMask.get()); } void drop() override { fImage = nullptr; fSMask = nullptr; } PDFDefaultBitmap(sk_sp<SkImage> image, sk_sp<SkPDFObject> smask) @@ -458,15 +449,12 @@ public: bool fIsYUV; PDFJpegBitmap(SkISize size, SkData* data, bool isYUV) : fSize(size), fData(SkRef(data)), fIsYUV(isYUV) { SkASSERT(data); } - void emitObject(SkWStream*, - const SkPDFObjNumMap&, - const SkPDFSubstituteMap&) const override; + void emitObject(SkWStream*, const SkPDFObjNumMap&) const override; void drop() override { fData = nullptr; } }; void PDFJpegBitmap::emitObject(SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substituteMap) const { + const SkPDFObjNumMap& objNumMap) const { SkASSERT(fData); SkPDFDict pdfDict("XObject"); pdfDict.insertName("Subtype", "Image"); @@ -481,7 +469,7 @@ void PDFJpegBitmap::emitObject(SkWStream* stream, pdfDict.insertName("Filter", "DCTDecode"); pdfDict.insertInt("ColorTransform", 0); pdfDict.insertInt("Length", SkToInt(fData->size())); - pdfDict.emitObject(stream, objNumMap, substituteMap); + pdfDict.emitObject(stream, objNumMap); pdf_stream_begin(stream); stream->write(fData->data(), fData->size()); pdf_stream_end(stream); diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index 290c1c4f56..edf17280ef 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -1153,7 +1153,6 @@ void SkPDFDevice::internalDrawText( font->multiByteGlyphs(), defaultPositioning, offset); - SkPDFGlyphSetMap* fontGlyphUsage = fDocument->getGlyphUsage(); const SkGlyphID* const glyphsEnd = glyphs + glyphCount; while (glyphs < glyphsEnd) { @@ -1184,7 +1183,7 @@ void SkPDFDevice::internalDrawText( return; } } - fontGlyphUsage->noteGlyphUsage(font, glyphs, stretch); + font->noteGlyphUsage(glyphs, stretch); if (defaultPositioning) { (void)font->glyphsToPDFFontEncoding(glyphs, SkToInt(glyphsEnd - glyphs)); while (stretch-- > 0) { @@ -1318,10 +1317,6 @@ sk_sp<SkPDFDict> SkPDFDevice::makeResourceDict() const { &fonts); } -const SkTDArray<SkPDFFont*>& SkPDFDevice::getFontResources() const { - return fFontResources; -} - sk_sp<SkPDFArray> SkPDFDevice::copyMediaBox() const { auto mediaBox = sk_make_sp<SkPDFArray>(); mediaBox->reserve(4); @@ -1948,9 +1943,9 @@ int SkPDFDevice::getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID) { } int resourceIndex = fFontResources.find(newFont.get()); if (resourceIndex < 0) { + fDocument->registerFont(newFont.get()); resourceIndex = fFontResources.count(); - fFontResources.push(newFont.get()); - newFont.get()->ref(); + fFontResources.push(newFont.release()); } return resourceIndex; } diff --git a/src/pdf/SkPDFDevice.h b/src/pdf/SkPDFDevice.h index 364cc61688..4a860281e3 100644 --- a/src/pdf/SkPDFDevice.h +++ b/src/pdf/SkPDFDevice.h @@ -126,10 +126,6 @@ public: /** Create the resource dictionary for this device. */ sk_sp<SkPDFDict> makeResourceDict() const; - /** Get the fonts used on this device. - */ - const SkTDArray<SkPDFFont*>& getFontResources() const; - /** Add our annotations (link to urls and destinations) to the supplied * array. * @param array Array to add annotations to. diff --git a/src/pdf/SkPDFDocument.cpp b/src/pdf/SkPDFDocument.cpp index 4f044c8771..75c5de91e3 100644 --- a/src/pdf/SkPDFDocument.cpp +++ b/src/pdf/SkPDFDocument.cpp @@ -23,7 +23,7 @@ SkPDFObjectSerializer::~SkPDFObjectSerializer() { } void SkPDFObjectSerializer::addObjectRecursively(const sk_sp<SkPDFObject>& object) { - fObjNumMap.addObjectRecursively(object.get(), fSubstituteMap); + fObjNumMap.addObjectRecursively(object.get()); } #define SKPDF_MAGIC "\xD3\xEB\xE9\xE1" @@ -58,10 +58,9 @@ void SkPDFObjectSerializer::serializeObjects(SkWStream* wStream) { // the head of the linked list of free objects." SkASSERT(fOffsets.count() == fNextToBeSerialized); fOffsets.push(this->offset(wStream)); - SkASSERT(object == fSubstituteMap.getSubstitute(object)); wStream->writeDecAsText(index); wStream->writeText(" 0 obj\n"); // Generation number is always 0. - object->emitObject(wStream, fObjNumMap, fSubstituteMap); + object->emitObject(wStream, fObjNumMap); wStream->writeText("\nendobj\n"); object->drop(); ++fNextToBeSerialized; @@ -93,7 +92,7 @@ void SkPDFObjectSerializer::serializeFooter(SkWStream* wStream, trailerDict.insertObject("ID", std::move(id)); } wStream->writeText("trailer\n"); - trailerDict.emitObject(wStream, fObjNumMap, fSubstituteMap); + trailerDict.emitObject(wStream, fObjNumMap); wStream->writeText("\nstartxref\n"); wStream->writeBigDecAsText(xRefFileOffset); wStream->writeText("\n%%EOF"); @@ -246,11 +245,15 @@ void SkPDFDocument::onEndPage() { } void SkPDFDocument::onAbort() { + this->reset(); +} + +void SkPDFDocument::reset() { fCanvas.reset(nullptr); fPages.reset(); fCanon.reset(); renew(&fObjectSerializer); - renew(&fGlyphUsage); + fFonts.reset(); } #ifdef SK_SUPPORT_LEGACY_DOCUMENT_API @@ -419,10 +422,7 @@ static sk_sp<SkPDFArray> make_srgb_output_intents() { bool SkPDFDocument::onClose(SkWStream* stream) { SkASSERT(!fCanvas.get()); if (fPages.empty()) { - fPages.reset(); - fCanon.reset(); - renew(&fObjectSerializer); - renew(&fGlyphUsage); + this->reset(); return false; } auto docCatalog = sk_make_sp<SkPDFDict>("Catalog"); @@ -442,21 +442,12 @@ bool SkPDFDocument::onClose(SkWStream* stream) { } // Build font subsetting info before calling addObjectRecursively(). - for (const auto& entry : fGlyphUsage) { - sk_sp<SkPDFObject> subsetFont = - entry.fFont->getFontSubset(&fCanon, &entry.fGlyphSet); - if (subsetFont) { - fObjectSerializer.fSubstituteMap.setSubstitute( - entry.fFont, subsetFont.get()); - } - } - + SkPDFCanon* canon = &fCanon; + fFonts.foreach([canon](SkPDFFont* p){ p->getFontSubset(canon); }); fObjectSerializer.addObjectRecursively(docCatalog); fObjectSerializer.serializeObjects(this->getStream()); fObjectSerializer.serializeFooter(this->getStream(), docCatalog, fID); - fCanon.reset(); - renew(&fObjectSerializer); - renew(&fGlyphUsage); + this->reset(); return true; } diff --git a/src/pdf/SkPDFDocument.h b/src/pdf/SkPDFDocument.h index 86562fe42e..5221dd2728 100644 --- a/src/pdf/SkPDFDocument.h +++ b/src/pdf/SkPDFDocument.h @@ -25,7 +25,6 @@ sk_sp<SkDocument> SkPDFMakeDocument(SkWStream* stream, // keep similar functionality together. struct SkPDFObjectSerializer : SkNoncopyable { SkPDFObjNumMap fObjNumMap; - SkPDFSubstituteMap fSubstituteMap; SkTDArray<int32_t> fOffsets; sk_sp<SkPDFObject> fInfoDict; size_t fBaseOffset; @@ -70,18 +69,16 @@ public: It might go without saying that objects should not be changed after calling serialize, since those changes will be too late. - The same goes for changes to the SkPDFSubstituteMap that effect - the object or its dependencies. */ void serialize(const sk_sp<SkPDFObject>&); SkPDFCanon* canon() { return &fCanon; } - SkPDFGlyphSetMap* getGlyphUsage() { return &fGlyphUsage; } + void registerFont(SkPDFFont* f) { fFonts.add(f); } private: SkPDFObjectSerializer fObjectSerializer; SkPDFCanon fCanon; - SkPDFGlyphSetMap fGlyphUsage; SkTArray<sk_sp<SkPDFDict>> fPages; + SkTHashSet<SkPDFFont*> fFonts; sk_sp<SkPDFDict> fDests; sk_sp<SkPDFDevice> fPageDevice; sk_sp<SkCanvas> fCanvas; @@ -90,6 +87,8 @@ private: SkScalar fRasterDpi; SkDocument::PDFMetadata fMetadata; bool fPDFA; + + void reset(); }; #endif // SkPDFDocument_DEFINED diff --git a/src/pdf/SkPDFFont.cpp b/src/pdf/SkPDFFont.cpp index 290061a491..887f95001f 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 }; -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). - 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) { diff --git a/src/pdf/SkPDFFont.h b/src/pdf/SkPDFFont.h index f2f1df4c24..abf164c013 100644 --- a/src/pdf/SkPDFFont.h +++ b/src/pdf/SkPDFFont.h @@ -18,48 +18,6 @@ class SkPDFCanon; class SkPDFFont; -class SkPDFGlyphSet : SkNoncopyable { -public: - SkPDFGlyphSet(); - SkPDFGlyphSet(SkPDFGlyphSet&& o) : fBitSet(std::move(o.fBitSet)) {} - - void set(const uint16_t* glyphIDs, int numGlyphs); - bool has(uint16_t glyphID) const; - void exportTo(SkTDArray<uint32_t>* glyphIDs) const; - const SkBitSet& bitSet() const { return fBitSet; } - -private: - SkBitSet fBitSet; -}; - -class SkPDFGlyphSetMap : SkNoncopyable { -public: - struct FontGlyphSetPair : SkNoncopyable { - FontGlyphSetPair() : fFont(nullptr) {} - FontGlyphSetPair(FontGlyphSetPair&& o) - : fFont(o.fFont) - , fGlyphSet(std::move(o.fGlyphSet)) { - o.fFont = nullptr; - } - SkPDFFont* fFont; - SkPDFGlyphSet fGlyphSet; - }; - - SkPDFGlyphSetMap(); - ~SkPDFGlyphSetMap(); - - const FontGlyphSetPair* begin() const { return fMap.begin(); } - const FontGlyphSetPair* end() const { return fMap.end(); } - - void noteGlyphUsage(SkPDFFont* font, const uint16_t* glyphIDs, - int numGlyphs); - -private: - SkPDFGlyphSet* getGlyphSetForFont(SkPDFFont* font); - - SkTArray<FontGlyphSetPair> fMap; -}; - /** \class SkPDFFont A PDF Object class representing a font. The font may have resources attached to it in order to embed the font. SkPDFFonts are canonicalized @@ -112,6 +70,10 @@ public: int glyphsToPDFFontEncodingCount(const SkGlyphID* glyphIDs, int numGlyphs) const; + void noteGlyphUsage(const SkGlyphID* glyphs, int count) { + fGlyphUsage.setAll(glyphs, count); + } + /** Get the font resource for the passed typeface and glyphID. The * reference count of the object is incremented and it is the caller's * responsibility to unreference it when done. This is needed to @@ -128,14 +90,10 @@ public: static const SkAdvancedTypefaceMetrics* GetMetrics(SkTypeface* typeface, SkPDFCanon* canon); - /** Subset the font based on usage set. Returns a SkPDFFont instance with - * subset. - * @param usage Glyph subset requested. - * @return nullptr if font does not support subsetting, a new instance - * of SkPDFFont otherwise. + /** Subset the font based on current usage. + * Must be called before emitObject(). */ - virtual sk_sp<SkPDFObject> getFontSubset(SkPDFCanon* canon, - const SkPDFGlyphSet* usage); + virtual void getFontSubset(SkPDFCanon*) = 0; /** * Return false iff the typeface has its NotEmbeddable flag set. @@ -145,23 +103,24 @@ public: protected: // Common constructor to handle common members. - SkPDFFont(sk_sp<SkTypeface> typeface, - SkAdvancedTypefaceMetrics::FontType fontType); + struct Info { + sk_sp<SkTypeface> fTypeface; + SkGlyphID fFirstGlyphID; + SkGlyphID fLastGlyphID; + SkAdvancedTypefaceMetrics::FontType fFontType; + }; + SkPDFFont(Info); SkGlyphID firstGlyphID() const { return fFirstGlyphID; } SkGlyphID lastGlyphID() const { return fLastGlyphID; } - + const SkBitSet& glyphUsage() const { return fGlyphUsage; } sk_sp<SkTypeface> refTypeface() const { return fTypeface; } - /** Set fFirstGlyphID and fLastGlyphID to span at most 255 glyphs, - * including the passed glyphID. - */ - void adjustGlyphRangeForSingleByteEncoding(SkGlyphID glyphID); - void drop() override; private: sk_sp<SkTypeface> fTypeface; + SkBitSet fGlyphUsage; // The glyph IDs accessible with this font. For Type1 (non CID) fonts, // this will be a subset if the font has more than 255 glyphs. diff --git a/src/pdf/SkPDFGraphicState.cpp b/src/pdf/SkPDFGraphicState.cpp index 5a603ce8da..a78c4c51b5 100644 --- a/src/pdf/SkPDFGraphicState.cpp +++ b/src/pdf/SkPDFGraphicState.cpp @@ -176,8 +176,7 @@ sk_sp<SkPDFDict> SkPDFGraphicState::MakeNoSmaskGraphicState() { void SkPDFGraphicState::emitObject( SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) const { + const SkPDFObjNumMap& objNumMap) const { auto dict = sk_make_sp<SkPDFDict>("ExtGState"); dict->insertName("Type", "ExtGState"); @@ -207,5 +206,5 @@ void SkPDFGraphicState::emitObject( dict->insertScalar("ML", fStrokeMiter); dict->insertBool("SA", true); // SA = Auto stroke adjustment. dict->insertName("BM", as_blend_mode(xferMode)); - dict->emitObject(stream, objNumMap, substitutes); + dict->emitObject(stream, objNumMap); } diff --git a/src/pdf/SkPDFGraphicState.h b/src/pdf/SkPDFGraphicState.h index 49723bd723..0c2e4a0f49 100644 --- a/src/pdf/SkPDFGraphicState.h +++ b/src/pdf/SkPDFGraphicState.h @@ -31,8 +31,7 @@ public: // Override emitObject so that we can populate the dictionary on // demand. void emitObject(SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) const override; + const SkPDFObjNumMap& objNumMap) const override; /** Get the graphic state for the passed SkPaint. The reference count of * the object is incremented and it is the caller's responsibility to diff --git a/src/pdf/SkPDFMakeToUnicodeCmap.cpp b/src/pdf/SkPDFMakeToUnicodeCmap.cpp index 6fd8b1ca16..5186cbbda1 100644 --- a/src/pdf/SkPDFMakeToUnicodeCmap.cpp +++ b/src/pdf/SkPDFMakeToUnicodeCmap.cpp @@ -149,7 +149,7 @@ static void append_bfrange_section(const SkTDArray<BFRange>& bfrange, // one of them), the possible savings by aggressive optimization is 416KB // pre-compressed and does not provide enough motivation for implementation. void SkPDFAppendCmapSections(const SkTDArray<SkUnichar>& glyphToUnicode, - const SkPDFGlyphSet* subset, + const SkBitSet* subset, SkDynamicMemoryWStream* cmap, bool multiByteGlyphs, SkGlyphID firstGlyphID, @@ -212,7 +212,7 @@ void SkPDFAppendCmapSections(const SkTDArray<SkUnichar>& glyphToUnicode, sk_sp<SkPDFStream> SkPDFMakeToUnicodeCmap( const SkTDArray<SkUnichar>& glyphToUnicode, - const SkPDFGlyphSet* subset, + const SkBitSet* subset, bool multiByteGlyphs, SkGlyphID firstGlyphID, SkGlyphID lastGlyphID) { diff --git a/src/pdf/SkPDFMakeToUnicodeCmap.h b/src/pdf/SkPDFMakeToUnicodeCmap.h index 1bd8930742..0c4d1c37dd 100644 --- a/src/pdf/SkPDFMakeToUnicodeCmap.h +++ b/src/pdf/SkPDFMakeToUnicodeCmap.h @@ -13,14 +13,14 @@ sk_sp<SkPDFStream> SkPDFMakeToUnicodeCmap( const SkTDArray<SkUnichar>& glyphToUnicode, - const SkPDFGlyphSet* subset, + const SkBitSet* subset, bool multiByteGlyphs, SkGlyphID firstGlyphID, SkGlyphID lastGlyphID); // Exposed for unit testing. void SkPDFAppendCmapSections(const SkTDArray<SkUnichar>& glyphToUnicode, - const SkPDFGlyphSet* subset, + const SkBitSet* subset, SkDynamicMemoryWStream* cmap, bool multiByteGlyphs, SkGlyphID firstGlyphID, diff --git a/src/pdf/SkPDFMetadata.cpp b/src/pdf/SkPDFMetadata.cpp index 259249671f..46fe461be5 100644 --- a/src/pdf/SkPDFMetadata.cpp +++ b/src/pdf/SkPDFMetadata.cpp @@ -168,12 +168,11 @@ class PDFXMLObject final : public SkPDFObject { public: PDFXMLObject(SkString xml) : fXML(std::move(xml)) {} void emitObject(SkWStream* stream, - const SkPDFObjNumMap& omap, - const SkPDFSubstituteMap& smap) const override { + const SkPDFObjNumMap& omap) const override { SkPDFDict dict("Metadata"); dict.insertName("Subtype", "XML"); dict.insertInt("Length", fXML.size()); - dict.emitObject(stream, omap, smap); + dict.emitObject(stream, omap); static const char streamBegin[] = " stream\n"; stream->write(streamBegin, strlen(streamBegin)); // Do not compress this. The standard requires that a diff --git a/src/pdf/SkPDFTypes.cpp b/src/pdf/SkPDFTypes.cpp index 6bf6afc611..838b5efeb9 100644 --- a/src/pdf/SkPDFTypes.cpp +++ b/src/pdf/SkPDFTypes.cpp @@ -113,8 +113,7 @@ static void write_name_escaped(SkWStream* o, const char* name) { } void SkPDFUnion::emitObject(SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) const { + const SkPDFObjNumMap& objNumMap) const { switch (fType) { case Type::kInt: stream->writeDecAsText(fIntValue); @@ -147,20 +146,18 @@ void SkPDFUnion::emitObject(SkWStream* stream, pun(fSkString)->size()); return; case Type::kObjRef: - stream->writeDecAsText(objNumMap.getObjectNumber( - substitutes.getSubstitute(fObject))); + stream->writeDecAsText(objNumMap.getObjectNumber(fObject)); stream->writeText(" 0 R"); // Generation number is always 0. return; case Type::kObject: - fObject->emitObject(stream, objNumMap, substitutes); + fObject->emitObject(stream, objNumMap); return; default: SkDEBUGFAIL("SkPDFUnion::emitObject with bad type"); } } -void SkPDFUnion::addResources(SkPDFObjNumMap* objNumMap, - const SkPDFSubstituteMap& substituteMap) const { +void SkPDFUnion::addResources(SkPDFObjNumMap* objNumMap) const { switch (fType) { case Type::kInt: case Type::kColorComponent: @@ -171,13 +168,11 @@ void SkPDFUnion::addResources(SkPDFObjNumMap* objNumMap, case Type::kNameSkS: case Type::kStringSkS: return; // These have no resources. - case Type::kObjRef: { - SkPDFObject* obj = substituteMap.getSubstitute(fObject); - objNumMap->addObjectRecursively(obj, substituteMap); + case Type::kObjRef: + objNumMap->addObjectRecursively(fObject); return; - } case Type::kObject: - fObject->addResources(objNumMap, substituteMap); + fObject->addResources(objNumMap); return; default: SkDEBUGFAIL("SkPDFUnion::addResources with bad type"); @@ -253,13 +248,11 @@ SkPDFUnion SkPDFUnion::Object(sk_sp<SkPDFObject> objSp) { #if 0 // Enable if needed. void SkPDFAtom::emitObject(SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) const { - fValue.emitObject(stream, objNumMap, substitutes); + const SkPDFObjNumMap& objNumMap) const { + fValue.emitObject(stream, objNumMap); } -void SkPDFAtom::addResources(SkPDFObjNumMap* map, - const SkPDFSubstituteMap& substitutes) const { - fValue.addResources(map, substitutes); +void SkPDFAtom::addResources(SkPDFObjNumMap* map) const { + fValue.addResources(map); } #endif // 0 @@ -282,12 +275,11 @@ void SkPDFArray::reserve(int length) { } void SkPDFArray::emitObject(SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) const { + const SkPDFObjNumMap& objNumMap) const { SkASSERT(!fDumped); stream->writeText("["); for (int i = 0; i < fValues.count(); i++) { - fValues[i].emitObject(stream, objNumMap, substitutes); + fValues[i].emitObject(stream, objNumMap); if (i + 1 < fValues.count()) { stream->writeText(" "); } @@ -295,11 +287,10 @@ void SkPDFArray::emitObject(SkWStream* stream, stream->writeText("]"); } -void SkPDFArray::addResources(SkPDFObjNumMap* catalog, - const SkPDFSubstituteMap& substitutes) const { +void SkPDFArray::addResources(SkPDFObjNumMap* catalog) const { SkASSERT(!fDumped); for (const SkPDFUnion& value : fValues) { - value.addResources(catalog, substitutes); + value.addResources(catalog); } } @@ -364,33 +355,30 @@ SkPDFDict::SkPDFDict(const char type[]) { } void SkPDFDict::emitObject(SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) const { + const SkPDFObjNumMap& objNumMap) const { stream->writeText("<<"); - this->emitAll(stream, objNumMap, substitutes); + this->emitAll(stream, objNumMap); stream->writeText(">>"); } void SkPDFDict::emitAll(SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) const { + const SkPDFObjNumMap& objNumMap) const { SkASSERT(!fDumped); for (int i = 0; i < fRecords.count(); i++) { - fRecords[i].fKey.emitObject(stream, objNumMap, substitutes); + fRecords[i].fKey.emitObject(stream, objNumMap); stream->writeText(" "); - fRecords[i].fValue.emitObject(stream, objNumMap, substitutes); + fRecords[i].fValue.emitObject(stream, objNumMap); if (i + 1 < fRecords.count()) { stream->writeText("\n"); } } } -void SkPDFDict::addResources(SkPDFObjNumMap* catalog, - const SkPDFSubstituteMap& substitutes) const { +void SkPDFDict::addResources(SkPDFObjNumMap* catalog) const { SkASSERT(!fDumped); for (int i = 0; i < fRecords.count(); i++) { - fRecords[i].fKey.addResources(catalog, substitutes); - fRecords[i].fValue.addResources(catalog, substitutes); + fRecords[i].fKey.addResources(catalog); + fRecords[i].fValue.addResources(catalog); } } @@ -463,20 +451,17 @@ void SkPDFSharedStream::drop() { #ifdef SK_PDF_LESS_COMPRESSION void SkPDFSharedStream::emitObject( SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) const { + const SkPDFObjNumMap& objNumMap) const { SkASSERT(fAsset); std::unique_ptr<SkStreamAsset> dup(fAsset->duplicate()); SkASSERT(dup && dup->hasLength()); size_t length = dup->getLength(); stream->writeText("<<"); - fDict.emitAll(stream, objNumMap, substitutes); + fDict.emitAll(stream, objNumMap); stream->writeText("\n"); - SkPDFUnion::Name("Length").emitObject( - stream, objNumMap, substitutes); + SkPDFUnion::Name("Length").emitObject(stream, objNumMap); stream->writeText(" "); - SkPDFUnion::Int(length).emitObject( - stream, objNumMap, substitutes); + SkPDFUnion::Int(length).emitObject(stream, objNumMap); stream->writeText("\n>>stream\n"); SkStreamCopy(stream, dup.get()); stream->writeText("\nendstream"); @@ -484,8 +469,7 @@ void SkPDFSharedStream::emitObject( #else void SkPDFSharedStream::emitObject( SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) const { + const SkPDFObjNumMap& objNumMap) const { SkASSERT(fAsset); SkDynamicMemoryWStream buffer; SkDeflateWStream deflateWStream(&buffer); @@ -496,15 +480,15 @@ void SkPDFSharedStream::emitObject( deflateWStream.finalize(); size_t length = buffer.bytesWritten(); stream->writeText("<<"); - fDict.emitAll(stream, objNumMap, substitutes); + fDict.emitAll(stream, objNumMap); stream->writeText("\n"); - SkPDFUnion::Name("Length").emitObject(stream, objNumMap, substitutes); + SkPDFUnion::Name("Length").emitObject(stream, objNumMap); stream->writeText(" "); - SkPDFUnion::Int(length).emitObject(stream, objNumMap, substitutes); + SkPDFUnion::Int(length).emitObject(stream, objNumMap); stream->writeText("\n"); - SkPDFUnion::Name("Filter").emitObject(stream, objNumMap, substitutes); + SkPDFUnion::Name("Filter").emitObject(stream, objNumMap); stream->writeText(" "); - SkPDFUnion::Name("FlateDecode").emitObject(stream, objNumMap, substitutes); + SkPDFUnion::Name("FlateDecode").emitObject(stream, objNumMap); stream->writeText(">>"); stream->writeText(" stream\n"); buffer.writeToStream(stream); @@ -513,9 +497,9 @@ void SkPDFSharedStream::emitObject( #endif void SkPDFSharedStream::addResources( - SkPDFObjNumMap* catalog, const SkPDFSubstituteMap& substitutes) const { + SkPDFObjNumMap* catalog) const { SkASSERT(fAsset); - fDict.addResources(catalog, substitutes); + fDict.addResources(catalog); } @@ -534,10 +518,9 @@ SkPDFStream::SkPDFStream() {} SkPDFStream::~SkPDFStream() {} -void SkPDFStream::addResources( - SkPDFObjNumMap* catalog, const SkPDFSubstituteMap& substitutes) const { +void SkPDFStream::addResources(SkPDFObjNumMap* catalog) const { SkASSERT(fCompressedData); - fDict.addResources(catalog, substitutes); + fDict.addResources(catalog); } void SkPDFStream::drop() { @@ -546,10 +529,9 @@ void SkPDFStream::drop() { } void SkPDFStream::emitObject(SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) const { + const SkPDFObjNumMap& objNumMap) const { SkASSERT(fCompressedData); - fDict.emitObject(stream, objNumMap, substitutes); + fDict.emitObject(stream, objNumMap); // duplicate (a cheap operation) preserves const on fCompressedData. std::unique_ptr<SkStreamAsset> dup(fCompressedData->duplicate()); SkASSERT(dup); @@ -594,25 +576,6 @@ void SkPDFStream::setData(std::unique_ptr<SkStreamAsset> stream) { //////////////////////////////////////////////////////////////////////////////// -SkPDFSubstituteMap::~SkPDFSubstituteMap() { - fSubstituteMap.foreach( - [](SkPDFObject*, SkPDFObject** v) { (*v)->unref(); }); -} - -void SkPDFSubstituteMap::setSubstitute(SkPDFObject* original, - SkPDFObject* substitute) { - SkASSERT(original != substitute); - SkASSERT(!fSubstituteMap.find(original)); - fSubstituteMap.set(original, SkRef(substitute)); -} - -SkPDFObject* SkPDFSubstituteMap::getSubstitute(SkPDFObject* object) const { - SkPDFObject** found = fSubstituteMap.find(object); - return found ? *found : object; -} - -//////////////////////////////////////////////////////////////////////////////// - bool SkPDFObjNumMap::addObject(SkPDFObject* obj) { if (fObjectNumbers.find(obj)) { return false; @@ -622,10 +585,9 @@ bool SkPDFObjNumMap::addObject(SkPDFObject* obj) { return true; } -void SkPDFObjNumMap::addObjectRecursively(SkPDFObject* obj, - const SkPDFSubstituteMap& subs) { +void SkPDFObjNumMap::addObjectRecursively(SkPDFObject* obj) { if (obj && this->addObject(obj)) { - obj->addResources(this, subs); + obj->addResources(this); } } diff --git a/src/pdf/SkPDFTypes.h b/src/pdf/SkPDFTypes.h index cdfef6cb92..201d62b2ef 100644 --- a/src/pdf/SkPDFTypes.h +++ b/src/pdf/SkPDFTypes.h @@ -17,7 +17,6 @@ class SkData; class SkPDFObjNumMap; class SkPDFObject; -class SkPDFSubstituteMap; class SkStreamAsset; class SkString; class SkWStream; @@ -41,16 +40,14 @@ public: * @param stream The writable output stream to send the output to. */ virtual void emitObject(SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) const = 0; + const SkPDFObjNumMap& objNumMap) const = 0; /** * Adds all transitive dependencies of this object to the * catalog. Implementations should respect the catalog's object * substitution map. */ - virtual void addResources(SkPDFObjNumMap* catalog, - const SkPDFSubstituteMap& substitutes) const {} + virtual void addResources(SkPDFObjNumMap* catalog) const {} /** * Release all resources associated with this SkPDFObject. It is @@ -121,10 +118,8 @@ public: /** These two non-virtual methods mirror SkPDFObject's corresponding virtuals. */ - void emitObject(SkWStream*, - const SkPDFObjNumMap&, - const SkPDFSubstituteMap&) const; - void addResources(SkPDFObjNumMap*, const SkPDFSubstituteMap&) const; + void emitObject(SkWStream*, const SkPDFObjNumMap&) const; + void addResources(SkPDFObjNumMap*) const; bool isName() const; @@ -171,9 +166,8 @@ static_assert(sizeof(SkString) == sizeof(void*), "SkString_size"); class SkPDFAtom final : public SkPDFObject { public: void emitObject(SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) final; - void addResources(SkPDFObjNumMap*, const SkPDFSubstituteMap&) const final; + const SkPDFObjNumMap& objNumMap) final; + void addResources(SkPDFObjNumMap* const final; SkPDFAtom(SkPDFUnion&& v) : fValue(std::move(v) {} private: @@ -197,10 +191,8 @@ public: // The SkPDFObject interface. void emitObject(SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) const override; - void addResources(SkPDFObjNumMap*, - const SkPDFSubstituteMap&) const override; + const SkPDFObjNumMap& objNumMap) const override; + void addResources(SkPDFObjNumMap*) const override; void drop() override; /** The size of the array. @@ -247,10 +239,8 @@ public: // The SkPDFObject interface. void emitObject(SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) const override; - void addResources(SkPDFObjNumMap*, - const SkPDFSubstituteMap&) const override; + const SkPDFObjNumMap& objNumMap) const override; + void addResources(SkPDFObjNumMap*) const override; void drop() override; /** The size of the dictionary. @@ -282,8 +272,7 @@ public: /** Emit the dictionary, without the "<<" and ">>". */ void emitAll(SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) const; + const SkPDFObjNumMap& objNumMap) const; private: struct Record { @@ -312,10 +301,8 @@ public: ~SkPDFSharedStream(); SkPDFDict* dict() { return &fDict; } void emitObject(SkWStream*, - const SkPDFObjNumMap&, - const SkPDFSubstituteMap&) const override; - void addResources(SkPDFObjNumMap*, - const SkPDFSubstituteMap&) const override; + const SkPDFObjNumMap&) const override; + void addResources(SkPDFObjNumMap*) const override; void drop() override; private: @@ -346,9 +333,8 @@ public: // The SkPDFObject interface. void emitObject(SkWStream* stream, - const SkPDFObjNumMap& objNumMap, - const SkPDFSubstituteMap& substitutes) const override; - void addResources(SkPDFObjNumMap*, const SkPDFSubstituteMap&) const final; + const SkPDFObjNumMap& objNumMap) const override; + void addResources(SkPDFObjNumMap*) const final; void drop() override; protected: @@ -383,9 +369,8 @@ public: /** Add the passed object to the catalog, as well as all its dependencies. * @param obj The object to add. If nullptr, this is a noop. - * @param subs Will be passed to obj->addResources(). */ - void addObjectRecursively(SkPDFObject* obj, const SkPDFSubstituteMap& subs); + void addObjectRecursively(SkPDFObject* obj); /** Get the object number for the passed object. * @param obj The object of interest. @@ -401,32 +386,6 @@ private: //////////////////////////////////////////////////////////////////////////////// -/** \class SkPDFSubstituteMap - - The PDF Substitute Map manages substitute objects and owns the - substitutes. -*/ -class SkPDFSubstituteMap : SkNoncopyable { -public: - ~SkPDFSubstituteMap(); - /** Set substitute object for the passed object. - Refs substitute. - */ - void setSubstitute(SkPDFObject* original, SkPDFObject* substitute); - - /** Find and return any substitute object set for the passed object. If - * there is none, return the passed object. - */ - SkPDFObject* getSubstitute(SkPDFObject* object) const; - - SkPDFObject* operator()(SkPDFObject* o) const { - return this->getSubstitute(o); - } - -private: - SkTHashMap<SkPDFObject*, SkPDFObject*> fSubstituteMap; -}; - #ifdef SK_PDF_IMAGE_STATS extern SkAtomic<int> gDrawImageCalls; extern SkAtomic<int> gJpegImageObjects; |