summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2012-07-11 21:29:41 +0200
committerJay Berkenbilt <ejb@ql.org>2012-07-11 21:54:33 +0200
commite7b8f297ba92f4cadf88efcb394830dc24d54738 (patch)
tree4bc25b3928545d81c4b8029fab389af8bccfdbc5 /include
parent8a217eb3a26931453b4f003c6c18ad8569230cf1 (diff)
downloadqpdf-e7b8f297ba92f4cadf88efcb394830dc24d54738.tar.zst
Support copying objects from another QPDF object
This includes QPDF::copyForeignObject and supporting foreign objects as arguments to addPage*.
Diffstat (limited to 'include')
-rw-r--r--include/qpdf/QPDF.hh75
-rw-r--r--include/qpdf/QPDFObjectHandle.hh12
2 files changed, 84 insertions, 3 deletions
diff --git a/include/qpdf/QPDF.hh b/include/qpdf/QPDF.hh
index b5c07abb..4c8ede86 100644
--- a/include/qpdf/QPDF.hh
+++ b/include/qpdf/QPDF.hh
@@ -190,6 +190,28 @@ class QPDF
replaceReserved(QPDFObjectHandle reserved,
QPDFObjectHandle replacement);
+ // Copy an object from another QPDF to this one. The return value
+ // is an indirect reference to the copied object in this file.
+ // This method is intended to be used to copy non-page objects and
+ // will not copy page objects. To copy page objects, pass the
+ // foreign page object directly to addPage (or addPageAt). If you
+ // copy objects that contain references to pages, you should copy
+ // the pages first using addPage(At). Otherwise references to the
+ // pages that have not been copied will be replaced with nulls.
+
+ // When copying objects with this method, object structure will be
+ // preserved, so all indirectly referenced indirect objects will
+ // be copied as well. This includes any circular references that
+ // may exist. The QPDF object keeps a record of what has already
+ // been copied, so shared objects will not be copied multiple
+ // times. This also means that if you mutate an object that has
+ // already been copied and try to copy it again, it won't work
+ // since the modified object will not be recopied. Therefore, you
+ // should do all mutation on the original file that you are going
+ // to do before you start copying its objects to a new file.
+ QPDF_DLL
+ QPDFObjectHandle copyForeignObject(QPDFObjectHandle foreign);
+
// Encryption support
enum encryption_method_e { e_none, e_unknown, e_rc4, e_aes };
@@ -380,7 +402,10 @@ class QPDF
// modify /Pages structures directly, you must call this method
// afterwards. This method updates the internal list of pages, so
// after calling this method, any previous references returned by
- // getAllPages() will be valid again.
+ // getAllPages() will be valid again. It also resets any state
+ // about having pushed inherited attributes in /Pages objects down
+ // to the pages, so if you add any inheritable attributes to a
+ // /Pages object, you should also call this method.
QPDF_DLL
void updateAllPagesCache();
@@ -389,11 +414,19 @@ class QPDF
// resolved by explicitly setting the values in each /Page.
void pushInheritedAttributesToPage();
- // Add new page at the beginning or the end of the current pdf
+ // Add new page at the beginning or the end of the current pdf.
+ // The newpage parameter may be either a direct object, an
+ // indirect object from this QPDF, or an indirect object from
+ // another QPDF. If it is a direct object, it will be made
+ // indirect. If it is an indirect object from another QPDF, this
+ // method will call pushInheritedAttributesToPage on the other
+ // file and then copy the page to this QPDF using the same
+ // underlying code as copyForeignObject.
QPDF_DLL
void addPage(QPDFObjectHandle newpage, bool first);
- // Add new page before or after refpage
+ // Add new page before or after refpage. See comments for addPage
+ // for details about what newpage should be.
QPDF_DLL
void addPageAt(QPDFObjectHandle newpage, bool before,
QPDFObjectHandle refpage);
@@ -542,6 +575,29 @@ class QPDF
qpdf_offset_t end_after_space;
};
+ class ObjCopier
+ {
+ public:
+ std::map<ObjGen, QPDFObjectHandle> object_map;
+ std::vector<QPDFObjectHandle> to_copy;
+ std::set<ObjGen> visiting;
+ };
+
+ class CopiedStreamDataProvider: public QPDFObjectHandle::StreamDataProvider
+ {
+ public:
+ virtual ~CopiedStreamDataProvider()
+ {
+ }
+ virtual void provideStreamData(int objid, int generation,
+ Pipeline* pipeline);
+ void registerForeignStream(ObjGen const& local_og,
+ QPDFObjectHandle foreign_stream);
+
+ private:
+ std::map<ObjGen, QPDFObjectHandle> foreign_streams;
+ };
+
void parse(char const* password);
void warn(QPDFExc const& e);
void setTrailer(QPDFObjectHandle obj);
@@ -602,6 +658,14 @@ class QPDF
QPDFObjectHandle& stream_dict,
std::vector<PointerHolder<Pipeline> >& heap);
+ // Methods to support object copying
+ QPDFObjectHandle copyForeignObject(
+ QPDFObjectHandle foreign, bool allow_page);
+ void reserveObjects(QPDFObjectHandle foreign, ObjCopier& obj_copier,
+ bool top);
+ QPDFObjectHandle replaceForeignIndirectObjects(
+ QPDFObjectHandle foreign, ObjCopier& obj_copier, bool top);
+
// Linearization Hint table structures.
// Naming conventions:
@@ -960,7 +1024,12 @@ class QPDF
QPDFObjectHandle trailer;
std::vector<QPDFObjectHandle> all_pages;
std::map<ObjGen, int> pageobj_to_pages_pos;
+ bool pushed_inherited_attributes_to_pages;
std::vector<QPDFExc> warnings;
+ std::map<QPDF*, ObjCopier> object_copiers;
+ PointerHolder<QPDFObjectHandle::StreamDataProvider> copied_streams;
+ // copied_stream_data_provider is owned by copied_streams
+ CopiedStreamDataProvider* copied_stream_data_provider;
// Linearization data
qpdf_offset_t first_xref_item_offset; // actual value from file
diff --git a/include/qpdf/QPDFObjectHandle.hh b/include/qpdf/QPDFObjectHandle.hh
index b21a3b0c..3b0814aa 100644
--- a/include/qpdf/QPDFObjectHandle.hh
+++ b/include/qpdf/QPDFObjectHandle.hh
@@ -222,6 +222,11 @@ class QPDFObjectHandle
QPDF_DLL
bool isOrHasName(std::string const&);
+ // Return the QPDF object that owns an indirect object. Returns
+ // null for a direct object.
+ QPDF_DLL
+ QPDF* getOwningQPDF();
+
// Create a shallow copy of an object as a direct object. Since
// this is a shallow copy, for dictionaries and arrays, any keys
// or items that were indirect objects will still be indirect
@@ -454,9 +459,16 @@ class QPDFObjectHandle
void assertReserved();
QPDF_DLL
+ void assertIndirect();
+ QPDF_DLL
void assertScalar();
QPDF_DLL
void assertNumber();
+
+ QPDF_DLL
+ bool isPageObject();
+ QPDF_DLL
+ bool isPagesObject();
QPDF_DLL
void assertPageObject();