aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf/QPDFPageObjectHelper.cc
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2021-01-01 13:31:54 +0100
committerJay Berkenbilt <ejb@ql.org>2021-01-02 18:29:31 +0100
commita139d2b36da39fbfb018ef6973e9316a64a4ca6c (patch)
tree6e7ea711324e717fba197d031550dfe7ae0f2f94 /libqpdf/QPDFPageObjectHelper.cc
parentafb48d23a984ab1fe27a57ecbb3d56ac2e3a2099 (diff)
downloadqpdf-a139d2b36da39fbfb018ef6973e9316a64a4ca6c.tar.zst
Add several methods for working with form XObjects (fixes #436)
Make some more methods in QPDFPageObjectHelper work with form XObjects, provide forEach methods to walk through nested form XObjects, possibly recursively. This should make it easier to work with form XObjects from user code.
Diffstat (limited to 'libqpdf/QPDFPageObjectHelper.cc')
-rw-r--r--libqpdf/QPDFPageObjectHelper.cc108
1 files changed, 83 insertions, 25 deletions
diff --git a/libqpdf/QPDFPageObjectHelper.cc b/libqpdf/QPDFPageObjectHelper.cc
index ce244253..ef563dc2 100644
--- a/libqpdf/QPDFPageObjectHelper.cc
+++ b/libqpdf/QPDFPageObjectHelper.cc
@@ -386,6 +386,73 @@ QPDFPageObjectHelper::getMediaBox(bool copy_if_shared)
return getAttribute("/MediaBox", copy_if_shared);
}
+void
+QPDFPageObjectHelper::forEachXObject(
+ bool recursive,
+ std::function<void(QPDFObjectHandle& obj,
+ QPDFObjectHandle& xobj_dict,
+ std::string const& key)> action,
+ std::function<bool(QPDFObjectHandle)> selector)
+{
+ QTC::TC("qpdf", "QPDFPageObjectHelper::forEachXObject",
+ recursive
+ ? (this->oh.isFormXObject() ? 0 : 1)
+ : (this->oh.isFormXObject() ? 2 : 3));
+ std::set<QPDFObjGen> seen;
+ std::list<QPDFPageObjectHelper> queue;
+ queue.push_back(*this);
+ while (! queue.empty())
+ {
+ QPDFPageObjectHelper ph = queue.front();
+ queue.pop_front();
+ QPDFObjGen og = ph.oh.getObjGen();
+ if (seen.count(og))
+ {
+ continue;
+ }
+ seen.insert(og);
+ QPDFObjectHandle resources = ph.getAttribute("/Resources", false);
+ if (resources.isDictionary() && resources.hasKey("/XObject"))
+ {
+ QPDFObjectHandle xobj_dict = resources.getKey("/XObject");
+ for (auto const& key: xobj_dict.getKeys())
+ {
+ QPDFObjectHandle obj = xobj_dict.getKey(key);
+ if ((! selector) || selector(obj))
+ {
+ action(obj, xobj_dict, key);
+ }
+ if (recursive && obj.isFormXObject())
+ {
+ queue.push_back(QPDFPageObjectHelper(obj));
+ }
+ }
+ }
+ }
+}
+
+void
+QPDFPageObjectHelper::forEachImage(
+ bool recursive,
+ std::function<void(QPDFObjectHandle& obj,
+ QPDFObjectHandle& xobj_dict,
+ std::string const& key)> action)
+{
+ forEachXObject(recursive, action,
+ [](QPDFObjectHandle obj) { return obj.isImage(); });
+}
+
+void
+QPDFPageObjectHelper::forEachFormXObject(
+ bool recursive,
+ std::function<void(QPDFObjectHandle& obj,
+ QPDFObjectHandle& xobj_dict,
+ std::string const& key)> action)
+{
+ forEachXObject(recursive, action,
+ [](QPDFObjectHandle obj) { return obj.isFormXObject(); });
+}
+
std::map<std::string, QPDFObjectHandle>
QPDFPageObjectHelper::getPageImages()
{
@@ -396,32 +463,23 @@ std::map<std::string, QPDFObjectHandle>
QPDFPageObjectHelper::getImages()
{
std::map<std::string, QPDFObjectHandle> result;
- QPDFObjectHandle resources = getAttribute("/Resources", false);
- if (resources.isDictionary())
- {
- if (resources.hasKey("/XObject"))
- {
- QPDFObjectHandle xobject = resources.getKey("/XObject");
- std::set<std::string> keys = xobject.getKeys();
- for (std::set<std::string>::iterator iter = keys.begin();
- iter != keys.end(); ++iter)
- {
- std::string key = (*iter);
- QPDFObjectHandle value = xobject.getKey(key);
- if (value.isStream())
- {
- QPDFObjectHandle dict = value.getDict();
- if (dict.hasKey("/Subtype") &&
- (dict.getKey("/Subtype").getName() == "/Image") &&
- (! dict.hasKey("/ImageMask")))
- {
- result[key] = value;
- }
- }
- }
- }
- }
+ forEachImage(false, [&result](QPDFObjectHandle& obj,
+ QPDFObjectHandle&,
+ std::string const& key) {
+ result[key] = obj;
+ });
+ return result;
+}
+std::map<std::string, QPDFObjectHandle>
+QPDFPageObjectHelper::getFormXObjects()
+{
+ std::map<std::string, QPDFObjectHandle> result;
+ forEachFormXObject(false, [&result](QPDFObjectHandle& obj,
+ QPDFObjectHandle&,
+ std::string const& key) {
+ result[key] = obj;
+ });
return result;
}