From 6c89d4b35bda528813b7ae9a39a1819af16a1fd0 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Thu, 21 Jun 2018 20:16:05 -0400 Subject: When splitting files, remove unreferenced objects (fixes #203) --- libqpdf/QPDFPageObjectHelper.cc | 64 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) (limited to 'libqpdf/QPDFPageObjectHelper.cc') diff --git a/libqpdf/QPDFPageObjectHelper.cc b/libqpdf/QPDFPageObjectHelper.cc index 47bc2117..e9e09d73 100644 --- a/libqpdf/QPDFPageObjectHelper.cc +++ b/libqpdf/QPDFPageObjectHelper.cc @@ -1,4 +1,5 @@ #include +#include QPDFPageObjectHelper::Members::~Members() { @@ -93,3 +94,66 @@ QPDFPageObjectHelper::addContentTokenFilter( { this->oh.addContentTokenFilter(token_filter); } + +class NameWatcher: public QPDFObjectHandle::TokenFilter +{ + public: + virtual ~NameWatcher() + { + } + virtual void handleToken(QPDFTokenizer::Token const&); + std::set names; +}; + +void +NameWatcher::handleToken(QPDFTokenizer::Token const& token) +{ + if (token.getType() == QPDFTokenizer::tt_name) + { + // Create a name object and get its name. This canonicalizes + // the representation of the name + this->names.insert( + QPDFObjectHandle::newName(token.getValue()).getName()); + } + writeToken(token); +} + +void +QPDFPageObjectHelper::removeUnreferencedResources() +{ + NameWatcher nw; + filterPageContents(&nw); + // Walk through /Font and /XObject dictionaries, removing any + // resources that are not referenced. We must make copies of + // resource dictionaries down into the dictionaries are mutating + // to prevent mutating one dictionary from having the side effect + // of mutating the one it was copied from. + std::vector to_filter; + to_filter.push_back("/Font"); + to_filter.push_back("/XObject"); + QPDFObjectHandle resources = this->oh.getKey("/Resources"); + if (resources.isDictionary()) + { + resources = resources.shallowCopy(); + this->oh.replaceKey("/Resources", resources); + } + for (std::vector::iterator d_iter = to_filter.begin(); + d_iter != to_filter.end(); ++d_iter) + { + QPDFObjectHandle dict = resources.getKey(*d_iter); + if (! dict.isDictionary()) + { + continue; + } + resources.replaceKey(*d_iter, dict); + std::set keys = dict.getKeys(); + for (std::set::iterator k_iter = keys.begin(); + k_iter != keys.end(); ++k_iter) + { + if (! nw.names.count(*k_iter)) + { + dict.removeKey(*k_iter); + } + } + } +} -- cgit v1.2.3-70-g09d2