aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2012-06-21 15:18:49 +0200
committerJay Berkenbilt <ejb@ql.org>2012-06-21 21:01:02 +0200
commite01ae1968b79841797b2ae59eda00b867604e3f9 (patch)
tree242373161cbb58c64434413e5e9b6bbba7f41c96
parentdf493c352f3936b7b6597791c289175dffb3db57 (diff)
downloadqpdf-e01ae1968b79841797b2ae59eda00b867604e3f9.tar.zst
Split page handling APIs into a separate source file
-rw-r--r--libqpdf/QPDF.cc189
-rw-r--r--libqpdf/QPDF_pages.cc195
-rw-r--r--libqpdf/build.mk1
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 \