From 7770a1b036433be7a47b65da7c34297353c7e77d Mon Sep 17 00:00:00 2001 From: Tobias Hoffmann Date: Fri, 22 Jun 2012 17:50:02 +0200 Subject: [PATCH] Added public method QPDF::pushInheritedAttributesToPage Refactored optimizePagesTree to pushInheritedAttributesToPage and made public --- include/qpdf/QPDF.hh | 11 ++++++--- libqpdf/QPDF_optimization.cc | 46 ++++++++++++++++++++---------------- libqpdf/QPDF_pages.cc | 3 +-- 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/include/qpdf/QPDF.hh b/include/qpdf/QPDF.hh index 93927a50..a6d88941 100644 --- a/include/qpdf/QPDF.hh +++ b/include/qpdf/QPDF.hh @@ -374,6 +374,11 @@ class QPDF QPDF_DLL 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 QPDF_DLL void addPage(QPDFObjectHandle newpage, bool first); @@ -903,11 +908,11 @@ class QPDF // Methods to support optimization - void optimizePagesTree(bool allow_changes); - void optimizePagesTreeInternal( + void pushInheritedAttributesToPage(bool allow_changes); + void pushInheritedAttributesToPageInternal( QPDFObjectHandle, std::map >&, - int& pageno, bool allow_changes); + bool allow_changes); void updateObjectMaps(ObjUser const& ou, QPDFObjectHandle oh); void updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh, std::set& visited, bool top); diff --git a/libqpdf/QPDF_optimization.cc b/libqpdf/QPDF_optimization.cc index f2d33863..f5895dd6 100644 --- a/libqpdf/QPDF_optimization.cc +++ b/libqpdf/QPDF_optimization.cc @@ -167,7 +167,16 @@ QPDF::optimize(std::map const& object_stream_data, // Traverse pages tree pushing all inherited resources down to the // 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 std::set keys = this->trailer.getKeys(); @@ -212,26 +221,32 @@ QPDF::optimize(std::map const& object_stream_data, } 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 // page level. // key_ancestors is a mapping of page attribute keys to a stack of - // Pages nodes that contain values for them. pageno is the - // current page sequence number numbered from 0. + // Pages nodes that contain values for them. std::map > key_ancestors; - int pageno = 0; - optimizePagesTreeInternal(this->trailer.getKey("/Root").getKey("/Pages"), - key_ancestors, pageno, allow_changes); + pushInheritedAttributesToPageInternal( + this->trailer.getKey("/Root").getKey("/Pages"), + key_ancestors, allow_changes); assert(key_ancestors.empty()); } void -QPDF::optimizePagesTreeInternal( +QPDF::pushInheritedAttributesToPageInternal( QPDFObjectHandle cur_pages, std::map >& key_ancestors, - int& pageno, bool allow_changes) + bool allow_changes) { // Extract the underlying dictionary object std::string type = cur_pages.getKey("/Type").getName(); @@ -301,8 +316,8 @@ QPDF::optimizePagesTreeInternal( int n = kids.getArrayNItems(); for (int i = 0; i < n; ++i) { - optimizePagesTreeInternal( - kids.getArrayItem(i), key_ancestors, pageno, allow_changes); + pushInheritedAttributesToPageInternal( + kids.getArrayItem(i), key_ancestors, allow_changes); } // 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"); } } - - // 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 { diff --git a/libqpdf/QPDF_pages.cc b/libqpdf/QPDF_pages.cc index 3c94d428..f98ed95a 100644 --- a/libqpdf/QPDF_pages.cc +++ b/libqpdf/QPDF_pages.cc @@ -102,7 +102,7 @@ QPDF::flattenPagesTree() } // Push inherited objects down to the /Page level - optimizePagesTree(true); + pushInheritedAttributesToPage(); getAllPages(); QPDFObjectHandle pages = getRoot().getKey("/Pages"); @@ -225,7 +225,6 @@ QPDF::addPageAt(QPDFObjectHandle newpage, bool before, insertPage(newpage, refpos); } - void QPDF::addPage(QPDFObjectHandle newpage, bool first) {