From f78ea057ca766e083c53f1c0284944b96a42b1b8 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Wed, 2 Jan 2019 21:44:10 -0500 Subject: Switch annotation flattening to use the form xobjects Instead of directly putting the contents of the annotation appearance streams into the page's content stream, add commands to render the form xobjects directly. This is a more robust way to do it than the original solution as it works properly with patterns and avoids problems with resource name clashes between the pages and the form xobjects. --- libqpdf/QPDFObjectHandle.cc | 80 +++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 39 deletions(-) (limited to 'libqpdf/QPDFObjectHandle.cc') diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index 300027b9..a0d45c86 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -826,23 +826,8 @@ QPDFObjectHandle::isOrHasName(std::string const& value) } void -QPDFObjectHandle::mergeDictionary(QPDFObjectHandle other) +QPDFObjectHandle::mergeResources(QPDFObjectHandle other) { - std::set visiting; - mergeDictionaryInternal(other, visiting, 0); -} - -void -QPDFObjectHandle::mergeDictionaryInternal( - QPDFObjectHandle other, - std::set& visiting, - int depth) -{ - if (depth > 100) - { - // Arbitrarily limit depth to avoid stack overflow - return; - } if (! (isDictionary() && other.isDictionary())) { QTC::TC("qpdf", "QPDFObjectHandle merge top type mismatch"); @@ -859,33 +844,22 @@ QPDFObjectHandle::mergeDictionaryInternal( QPDFObjectHandle this_val = getKey(key); if (this_val.isDictionary() && other_val.isDictionary()) { - if (this_val.isIndirect() && other_val.isIndirect() && - (this_val.getObjGen() == other_val.getObjGen())) + if (this_val.isIndirect()) { - QTC::TC("qpdf", "QPDFObjectHandle merge equal indirect"); + QTC::TC("qpdf", "QPDFObjectHandle replace with copy"); + this_val = this_val.shallowCopy(); + replaceKey(key, this_val); } - else if (this_val.isIndirect() && - (visiting.count(this_val.getObjGen()))) + std::set other_val_keys = other_val.getKeys(); + for (std::set::iterator i2 = + other_val_keys.begin(); + i2 != other_val_keys.end(); ++i2) { - QTC::TC("qpdf", "QPDFObjectHandle merge loop"); - } - else - { - QPDFObjGen loop; - if (this_val.isIndirect()) + if (! this_val.hasKey(*i2)) { - loop = this_val.getObjGen(); - visiting.insert(loop); QTC::TC("qpdf", "QPDFObjectHandle merge shallow copy"); - this_val = this_val.shallowCopy(); - replaceKey(key, this_val); - } - QTC::TC("qpdf", "QPDFObjectHandle nested merge"); - this_val.mergeDictionaryInternal( - other_val, visiting, 1 + depth); - if (loop.getObj()) - { - visiting.erase(loop); + this_val.replaceKey( + *i2, other_val.getKey(*i2).shallowCopy()); } } } @@ -923,9 +897,37 @@ QPDFObjectHandle::mergeDictionaryInternal( else { QTC::TC("qpdf", "QPDFObjectHandle merge copy from other"); - replaceKey(key, other_val); + replaceKey(key, other_val.shallowCopy()); + } + } +} + +std::set +QPDFObjectHandle::getResourceNames() +{ + // Return second-level dictionary keys + std::set result; + if (! isDictionary()) + { + return result; + } + std::set keys = getKeys(); + for (std::set::iterator iter = keys.begin(); + iter != keys.end(); ++iter) + { + std::string const& key = *iter; + QPDFObjectHandle val = getKey(key); + if (val.isDictionary()) + { + std::set val_keys = val.getKeys(); + for (std::set::iterator i2 = val_keys.begin(); + i2 != val_keys.end(); ++i2) + { + result.insert(*i2); + } } } + return result; } // Indirect object accessors -- cgit v1.2.3-54-g00ecf