2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-06-02 02:10:52 +00:00

Added public method QPDF::pushInheritedAttributesToPage

Refactored optimizePagesTree to pushInheritedAttributesToPage and made
public
This commit is contained in:
Tobias Hoffmann 2012-06-22 17:50:02 +02:00 committed by Jay Berkenbilt
parent 235188df85
commit 7770a1b036
3 changed files with 35 additions and 25 deletions

View File

@ -374,6 +374,11 @@ class QPDF
QPDF_DLL QPDF_DLL
void updateAllPagesCache(); void updateAllPagesCache();
// The PDF /Pages tree allows inherited values. Working with
// the pages of a pdf is much easier when the inheritance is
// 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
QPDF_DLL QPDF_DLL
void addPage(QPDFObjectHandle newpage, bool first); void addPage(QPDFObjectHandle newpage, bool first);
@ -903,11 +908,11 @@ class QPDF
// Methods to support optimization // Methods to support optimization
void optimizePagesTree(bool allow_changes); void pushInheritedAttributesToPage(bool allow_changes);
void optimizePagesTreeInternal( void pushInheritedAttributesToPageInternal(
QPDFObjectHandle, QPDFObjectHandle,
std::map<std::string, std::vector<QPDFObjectHandle> >&, std::map<std::string, std::vector<QPDFObjectHandle> >&,
int& pageno, bool allow_changes); bool allow_changes);
void updateObjectMaps(ObjUser const& ou, QPDFObjectHandle oh); void updateObjectMaps(ObjUser const& ou, QPDFObjectHandle oh);
void updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh, void updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh,
std::set<ObjGen>& visited, bool top); std::set<ObjGen>& visited, bool top);

View File

@ -167,7 +167,16 @@ QPDF::optimize(std::map<int, int> const& object_stream_data,
// Traverse pages tree pushing all inherited resources down to the // Traverse pages tree pushing all inherited resources down to the
// page level. // page level.
optimizePagesTree(allow_changes); pushInheritedAttributesToPage(allow_changes);
getAllPages();
// Traverse pages
int n = this->all_pages.size();
for (int pageno = 0; pageno < n; ++pageno)
{
updateObjectMaps(ObjUser(ObjUser::ou_page, pageno),
this->all_pages[pageno]);
}
// Traverse document-level items // Traverse document-level items
std::set<std::string> keys = this->trailer.getKeys(); std::set<std::string> keys = this->trailer.getKeys();
@ -212,26 +221,32 @@ QPDF::optimize(std::map<int, int> const& object_stream_data,
} }
void void
QPDF::optimizePagesTree(bool allow_changes) QPDF::pushInheritedAttributesToPage()
{
// Public API should not have access to allow_changes.
pushInheritedAttributesToPage(true);
}
void
QPDF::pushInheritedAttributesToPage(bool allow_changes)
{ {
// Traverse pages tree pushing all inherited resources down to the // Traverse pages tree pushing all inherited resources down to the
// page level. // page level.
// key_ancestors is a mapping of page attribute keys to a stack of // key_ancestors is a mapping of page attribute keys to a stack of
// Pages nodes that contain values for them. pageno is the // Pages nodes that contain values for them.
// current page sequence number numbered from 0.
std::map<std::string, std::vector<QPDFObjectHandle> > key_ancestors; std::map<std::string, std::vector<QPDFObjectHandle> > key_ancestors;
int pageno = 0; pushInheritedAttributesToPageInternal(
optimizePagesTreeInternal(this->trailer.getKey("/Root").getKey("/Pages"), this->trailer.getKey("/Root").getKey("/Pages"),
key_ancestors, pageno, allow_changes); key_ancestors, allow_changes);
assert(key_ancestors.empty()); assert(key_ancestors.empty());
} }
void void
QPDF::optimizePagesTreeInternal( QPDF::pushInheritedAttributesToPageInternal(
QPDFObjectHandle cur_pages, QPDFObjectHandle cur_pages,
std::map<std::string, std::vector<QPDFObjectHandle> >& key_ancestors, std::map<std::string, std::vector<QPDFObjectHandle> >& key_ancestors,
int& pageno, bool allow_changes) bool allow_changes)
{ {
// Extract the underlying dictionary object // Extract the underlying dictionary object
std::string type = cur_pages.getKey("/Type").getName(); std::string type = cur_pages.getKey("/Type").getName();
@ -301,8 +316,8 @@ QPDF::optimizePagesTreeInternal(
int n = kids.getArrayNItems(); int n = kids.getArrayNItems();
for (int i = 0; i < n; ++i) for (int i = 0; i < n; ++i)
{ {
optimizePagesTreeInternal( pushInheritedAttributesToPageInternal(
kids.getArrayItem(i), key_ancestors, pageno, allow_changes); kids.getArrayItem(i), key_ancestors, allow_changes);
} }
// For each inheritable key, pop the stack. If the stack // For each inheritable key, pop the stack. If the stack
@ -350,15 +365,6 @@ QPDF::optimizePagesTreeInternal(
QTC::TC("qpdf", "QPDF opt page resource hides ancestor"); QTC::TC("qpdf", "QPDF opt page resource hides ancestor");
} }
} }
// Traverse from this point, updating the mappings of object
// users to objects and objects to object users.
updateObjectMaps(ObjUser(ObjUser::ou_page, pageno), cur_pages);
// Increment pageno so that its value will be correct for the
// next page.
++pageno;
} }
else else
{ {

View File

@ -102,7 +102,7 @@ QPDF::flattenPagesTree()
} }
// Push inherited objects down to the /Page level // Push inherited objects down to the /Page level
optimizePagesTree(true); pushInheritedAttributesToPage();
getAllPages(); getAllPages();
QPDFObjectHandle pages = getRoot().getKey("/Pages"); QPDFObjectHandle pages = getRoot().getKey("/Pages");
@ -225,7 +225,6 @@ QPDF::addPageAt(QPDFObjectHandle newpage, bool before,
insertPage(newpage, refpos); insertPage(newpage, refpos);
} }
void void
QPDF::addPage(QPDFObjectHandle newpage, bool first) QPDF::addPage(QPDFObjectHandle newpage, bool first)
{ {