aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf/QPDFPageObjectHelper.cc
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2018-06-22 02:16:05 +0200
committerJay Berkenbilt <ejb@ql.org>2018-06-22 03:03:30 +0200
commit6c89d4b35bda528813b7ae9a39a1819af16a1fd0 (patch)
tree3479e54ecf1a6c547d76c092565a48609bb08847 /libqpdf/QPDFPageObjectHelper.cc
parentddd78c1b7f53f09710431d58cd94659271f325cc (diff)
downloadqpdf-6c89d4b35bda528813b7ae9a39a1819af16a1fd0.tar.zst
When splitting files, remove unreferenced objects (fixes #203)
Diffstat (limited to 'libqpdf/QPDFPageObjectHelper.cc')
-rw-r--r--libqpdf/QPDFPageObjectHelper.cc64
1 files changed, 64 insertions, 0 deletions
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 <qpdf/QPDFPageObjectHelper.hh>
+#include <qpdf/QTC.hh>
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<std::string> 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<std::string> 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<std::string>::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<std::string> keys = dict.getKeys();
+ for (std::set<std::string>::iterator k_iter = keys.begin();
+ k_iter != keys.end(); ++k_iter)
+ {
+ if (! nw.names.count(*k_iter))
+ {
+ dict.removeKey(*k_iter);
+ }
+ }
+ }
+}