diff options
author | Jay Berkenbilt <ejb@ql.org> | 2012-06-21 15:18:49 +0200 |
---|---|---|
committer | Jay Berkenbilt <ejb@ql.org> | 2012-06-21 21:01:02 +0200 |
commit | e01ae1968b79841797b2ae59eda00b867604e3f9 (patch) | |
tree | 242373161cbb58c64434413e5e9b6bbba7f41c96 /libqpdf | |
parent | df493c352f3936b7b6597791c289175dffb3db57 (diff) | |
download | qpdf-e01ae1968b79841797b2ae59eda00b867604e3f9.tar.zst |
Split page handling APIs into a separate source file
Diffstat (limited to 'libqpdf')
-rw-r--r-- | libqpdf/QPDF.cc | 189 | ||||
-rw-r--r-- | libqpdf/QPDF_pages.cc | 195 | ||||
-rw-r--r-- | libqpdf/build.mk | 1 |
3 files changed, 196 insertions, 189 deletions
diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index d36aebe2..dd572fd3 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -4,7 +4,6 @@ #include <map> #include <string.h> #include <memory.h> -#include <assert.h> #include <qpdf/QTC.hh> #include <qpdf/QUtil.hh> @@ -2165,191 +2164,3 @@ QPDF::decodeStreams() } } } - -std::vector<QPDFObjectHandle> const& -QPDF::getAllPages() -{ - if (this->all_pages.empty()) - { - getAllPagesInternal( - this->trailer.getKey("/Root").getKey("/Pages"), this->all_pages); - } - return this->all_pages; -} - -void -QPDF::getAllPagesInternal(QPDFObjectHandle cur_pages, - std::vector<QPDFObjectHandle>& result) -{ - std::string type = cur_pages.getKey("/Type").getName(); - if (type == "/Pages") - { - QPDFObjectHandle kids = cur_pages.getKey("/Kids"); - int n = kids.getArrayNItems(); - for (int i = 0; i < n; ++i) - { - getAllPagesInternal(kids.getArrayItem(i), result); - } - } - else if (type == "/Page") - { - result.push_back(cur_pages); - } - else - { - throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), - this->last_object_description, - this->file->getLastOffset(), - ": invalid Type in page tree"); - } -} - -// FIXXX here down - -void -QPDF::clearPagesCache() -{ - this->all_pages.clear(); - this->pageobj_to_pages_pos.clear(); -} - -void -QPDF::flattenPagesTree() -{ - clearPagesCache(); - - // FIXME: more specific method, we don't want to generate the extra stuff. - // We also need cheap fixup after addPage/removePage. - - // no compressed objects to be produced here... - std::map<int, int> object_stream_data; - optimize(object_stream_data); // push down inheritance - - std::vector<QPDFObjectHandle> kids = this->getAllPages(); - QPDFObjectHandle pages = this->trailer.getKey("/Root").getKey("/Pages"); - - const int len = kids.size(); - for (int pos = 0; pos < len; ++pos) - { - // populate pageobj_to_pages_pos - ObjGen og(kids[pos].getObjectID(), kids[pos].getGeneration()); - if (! this->pageobj_to_pages_pos.insert(std::make_pair(og, pos)).second) - { - // insert failed: duplicate entry found - *out_stream << "WARNING: duplicate page reference found, " - << "but currently not fully supported." << std::endl; - } - - // fix parent links - kids[pos].replaceKey("/Parent", pages); - } - - pages.replaceKey("/Kids", QPDFObjectHandle::newArray(kids)); - // /Count has not changed - assert(pages.getKey("/Count").getIntValue() == len); -} - -int -QPDF::findPage(int objid, int generation) -{ - if (this->pageobj_to_pages_pos.empty()) - { - flattenPagesTree(); - } - std::map<ObjGen, int>::iterator it = - this->pageobj_to_pages_pos.find(ObjGen(objid, generation)); - if (it != this->pageobj_to_pages_pos.end()) - { - return (*it).second; - } - return -1; // throw? -} - -int -QPDF::findPage(QPDFObjectHandle const& pageoh) -{ - if (!pageoh.isInitialized()) - { - return -1; - // TODO? throw - } - return findPage(pageoh.getObjectID(), pageoh.getGeneration()); -} - -void -QPDF::addPage(QPDFObjectHandle newpage, bool first) -{ - if (this->pageobj_to_pages_pos.empty()) - { - flattenPagesTree(); - } - - newpage.assertPageObject(); // FIXME: currently private - - QPDFObjectHandle pages = this->trailer.getKey("/Root").getKey("/Pages"); - QPDFObjectHandle kids = pages.getKey("/Kids"); - - newpage.replaceKey("/Parent", pages); - if (first) - { - kids.insertItem(0, newpage); - } - else - { - kids.appendItem(newpage); - } - pages.replaceKey("/Count", - QPDFObjectHandle::newInteger(kids.getArrayNItems())); - - // FIXME: this is overkill, but cache is now stale - clearPagesCache(); -} - -void -QPDF::addPageAt(QPDFObjectHandle newpage, bool before, - QPDFObjectHandle const &refpage) -{ - int refpos = findPage(refpage); // also ensures flat /Pages - if (refpos == -1) - { - throw "Could not find refpage"; - } - - newpage.assertPageObject(); - - QPDFObjectHandle pages = this->trailer.getKey("/Root").getKey("/Pages"); - QPDFObjectHandle kids = pages.getKey("/Kids"); - - if (! before) - { - ++refpos; - } - - newpage.replaceKey("/Parent", pages); - kids.insertItem(refpos, newpage); - pages.replaceKey("/Count", - QPDFObjectHandle::newInteger(kids.getArrayNItems())); - - // FIXME: this is overkill, but cache is now stale - clearPagesCache(); -} - -void -QPDF::removePage(QPDFObjectHandle const& pageoh) -{ - int pos = findPage(pageoh); // also ensures flat /Pages - if (pos == -1) - { - throw "Can't remove non-existing page"; - } - - QPDFObjectHandle pages = this->trailer.getKey("/Root").getKey("/Pages"); - QPDFObjectHandle kids = pages.getKey("/Kids"); - - kids.eraseItem(pos); - pages.replaceKey("/Count", - QPDFObjectHandle::newInteger(kids.getArrayNItems())); - - // FIXME: this is overkill, but cache is now stale - clearPagesCache(); -} diff --git a/libqpdf/QPDF_pages.cc b/libqpdf/QPDF_pages.cc new file mode 100644 index 00000000..bd631c96 --- /dev/null +++ b/libqpdf/QPDF_pages.cc @@ -0,0 +1,195 @@ +#include <qpdf/QPDF.hh> + +#include <assert.h> + +#include <qpdf/QTC.hh> +#include <qpdf/QUtil.hh> +#include <qpdf/QPDFExc.hh> + +std::vector<QPDFObjectHandle> const& +QPDF::getAllPages() +{ + if (this->all_pages.empty()) + { + getAllPagesInternal( + this->trailer.getKey("/Root").getKey("/Pages"), this->all_pages); + } + return this->all_pages; +} + +void +QPDF::getAllPagesInternal(QPDFObjectHandle cur_pages, + std::vector<QPDFObjectHandle>& result) +{ + std::string type = cur_pages.getKey("/Type").getName(); + if (type == "/Pages") + { + QPDFObjectHandle kids = cur_pages.getKey("/Kids"); + int n = kids.getArrayNItems(); + for (int i = 0; i < n; ++i) + { + getAllPagesInternal(kids.getArrayItem(i), result); + } + } + else if (type == "/Page") + { + result.push_back(cur_pages); + } + else + { + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), + this->last_object_description, + this->file->getLastOffset(), + ": invalid Type in page tree"); + } +} + +// FIXXX here down + +void +QPDF::clearPagesCache() +{ + this->all_pages.clear(); + this->pageobj_to_pages_pos.clear(); +} + +void +QPDF::flattenPagesTree() +{ + clearPagesCache(); + + // FIXME: more specific method, we don't want to generate the extra stuff. + // We also need cheap fixup after addPage/removePage. + + // no compressed objects to be produced here... + std::map<int, int> object_stream_data; + optimize(object_stream_data); // push down inheritance + + std::vector<QPDFObjectHandle> kids = this->getAllPages(); + QPDFObjectHandle pages = this->trailer.getKey("/Root").getKey("/Pages"); + + const int len = kids.size(); + for (int pos = 0; pos < len; ++pos) + { + // populate pageobj_to_pages_pos + ObjGen og(kids[pos].getObjectID(), kids[pos].getGeneration()); + if (! this->pageobj_to_pages_pos.insert(std::make_pair(og, pos)).second) + { + // insert failed: duplicate entry found + *out_stream << "WARNING: duplicate page reference found, " + << "but currently not fully supported." << std::endl; + } + + // fix parent links + kids[pos].replaceKey("/Parent", pages); + } + + pages.replaceKey("/Kids", QPDFObjectHandle::newArray(kids)); + // /Count has not changed + assert(pages.getKey("/Count").getIntValue() == len); +} + +int +QPDF::findPage(int objid, int generation) +{ + if (this->pageobj_to_pages_pos.empty()) + { + flattenPagesTree(); + } + std::map<ObjGen, int>::iterator it = + this->pageobj_to_pages_pos.find(ObjGen(objid, generation)); + if (it != this->pageobj_to_pages_pos.end()) + { + return (*it).second; + } + return -1; // throw? +} + +int +QPDF::findPage(QPDFObjectHandle const& pageoh) +{ + if (!pageoh.isInitialized()) + { + return -1; + // TODO? throw + } + return findPage(pageoh.getObjectID(), pageoh.getGeneration()); +} + +void +QPDF::addPage(QPDFObjectHandle newpage, bool first) +{ + if (this->pageobj_to_pages_pos.empty()) + { + flattenPagesTree(); + } + + newpage.assertPageObject(); // FIXME: currently private + + QPDFObjectHandle pages = this->trailer.getKey("/Root").getKey("/Pages"); + QPDFObjectHandle kids = pages.getKey("/Kids"); + + newpage.replaceKey("/Parent", pages); + if (first) + { + kids.insertItem(0, newpage); + } + else + { + kids.appendItem(newpage); + } + pages.replaceKey("/Count", + QPDFObjectHandle::newInteger(kids.getArrayNItems())); + + // FIXME: this is overkill, but cache is now stale + clearPagesCache(); +} + +void +QPDF::addPageAt(QPDFObjectHandle newpage, bool before, + QPDFObjectHandle const &refpage) +{ + int refpos = findPage(refpage); // also ensures flat /Pages + if (refpos == -1) + { + throw "Could not find refpage"; + } + + newpage.assertPageObject(); + + QPDFObjectHandle pages = this->trailer.getKey("/Root").getKey("/Pages"); + QPDFObjectHandle kids = pages.getKey("/Kids"); + + if (! before) + { + ++refpos; + } + + newpage.replaceKey("/Parent", pages); + kids.insertItem(refpos, newpage); + pages.replaceKey("/Count", + QPDFObjectHandle::newInteger(kids.getArrayNItems())); + + // FIXME: this is overkill, but cache is now stale + clearPagesCache(); +} + +void +QPDF::removePage(QPDFObjectHandle const& pageoh) +{ + int pos = findPage(pageoh); // also ensures flat /Pages + if (pos == -1) + { + throw "Can't remove non-existing page"; + } + + QPDFObjectHandle pages = this->trailer.getKey("/Root").getKey("/Pages"); + QPDFObjectHandle kids = pages.getKey("/Kids"); + + kids.eraseItem(pos); + pages.replaceKey("/Count", + QPDFObjectHandle::newInteger(kids.getArrayNItems())); + + // FIXME: this is overkill, but cache is now stale + clearPagesCache(); +} diff --git a/libqpdf/build.mk b/libqpdf/build.mk index c5549202..ebd534b3 100644 --- a/libqpdf/build.mk +++ b/libqpdf/build.mk @@ -43,6 +43,7 @@ SRCS_libqpdf = \ libqpdf/QPDF_encryption.cc \ libqpdf/QPDF_linearization.cc \ libqpdf/QPDF_optimization.cc \ + libqpdf/QPDF_pages.cc \ libqpdf/QTC.cc \ libqpdf/QUtil.cc \ libqpdf/RC4.cc \ |