glib/poppler-document.cc | 12 ++++-------- poppler/Object.h | 31 +++++++++++++++++++++++++------ poppler/OptionalContent.cc | 42 ++++++++++-------------------------------- poppler/OptionalContent.h | 9 +++++---- poppler/StructTreeRoot.cc | 2 +- poppler/StructTreeRoot.h | 2 +- qt5/src/poppler-link.cc | 5 ----- qt5/src/poppler-optcontent.cc | 9 ++++----- utils/pdfinfo.cc | 2 +- 9 files changed, 51 insertions(+), 63 deletions(-)
New commits: commit 7e9b6f1dba716e7adba1ed2ecd765b207def9747 Author: Adam Reichold <[email protected]> Date: Sat Sep 15 09:54:01 2018 +0200 Fix TODO in OCGs by creating a look-up table from Ref to OptionalContentGroup (and make Ref a regular type to do so). diff --git a/glib/poppler-document.cc b/glib/poppler-document.cc index b343eb90..d4900f3b 100644 --- a/glib/poppler-document.cc +++ b/glib/poppler-document.cc @@ -2494,15 +2494,11 @@ get_optional_content_items (OCGs *ocg) if (order) { items = get_optional_content_items_sorted (ocg, nullptr, order); } else { - GooList *ocgs; - int i; + const auto &ocgs = ocg->getOCGs (); + + for (const auto &oc : ocgs) { + Layer *layer = layer_new (oc.second.get()); - ocgs = ocg->getOCGs (); - - for (i = 0; i < ocgs->getLength (); ++i) { - OptionalContentGroup *oc = (OptionalContentGroup *) ocgs->get (i); - Layer *layer = layer_new (oc); - items = g_list_prepend (items, layer); } diff --git a/poppler/Object.h b/poppler/Object.h index 58d0f2e5..3dcf9e6b 100644 --- a/poppler/Object.h +++ b/poppler/Object.h @@ -89,14 +89,33 @@ struct Ref { int gen; // generation number }; -struct RefCompare { - bool operator() (const Ref& lhs, const Ref& rhs) const { - if (lhs.num != rhs.num) - return lhs.num < rhs.num; - return lhs.gen < rhs.gen; - } +inline bool operator== (const Ref& lhs, const Ref& rhs) noexcept { + return lhs.num == rhs.num && lhs.gen == rhs.gen; +} + +inline bool operator< (const Ref& lhs, const Ref& rhs) noexcept { + if (lhs.num != rhs.num) + return lhs.num < rhs.num; + return lhs.gen < rhs.gen; +} + +namespace std +{ + +template<> +struct hash<Ref> +{ + using argument_type = Ref; + using result_type = size_t; + + result_type operator() (const argument_type &ref) const noexcept + { + return std::hash<int>{}(ref.num) ^ (std::hash<int>{}(ref.gen) << 1); + } }; +} + //------------------------------------------------------------------------ // object types //------------------------------------------------------------------------ diff --git a/poppler/OptionalContent.cc b/poppler/OptionalContent.cc index 3f0ef264..116b6ba9 100644 --- a/poppler/OptionalContent.cc +++ b/poppler/OptionalContent.cc @@ -40,8 +40,6 @@ OCGs::OCGs(Object *ocgObject, XRef *xref) : { // we need to parse the dictionary here, and build optionalContentGroups ok = gTrue; - optionalContentGroups = new GooList(); - display = nullptr; Object ocgList = ocgObject->dictLookup("OCGs"); if (!ocgList.isArray()) { @@ -62,11 +60,10 @@ OCGs::OCGs(Object *ocgObject, XRef *xref) : delete thisOptionalContentGroup; break; } - // TODO: we should create a lookup map from Ref to the OptionalContentGroup thisOptionalContentGroup->setRef( ocg.getRef() ); // the default is ON - we change state later, depending on BaseState, ON and OFF thisOptionalContentGroup->setState(OptionalContentGroup::On); - optionalContentGroups->append(thisOptionalContentGroup); + optionalContentGroups.emplace(ocg.getRef(), thisOptionalContentGroup); } Object defaultOcgConfig = ocgObject->dictLookup("D"); @@ -78,11 +75,8 @@ OCGs::OCGs(Object *ocgObject, XRef *xref) : Object baseState = defaultOcgConfig.dictLookup("BaseState"); if (baseState.isName("OFF")) { - for (int i = 0; i < optionalContentGroups->getLength(); ++i) { - OptionalContentGroup *group; - - group = (OptionalContentGroup *)optionalContentGroups->get(i); - group->setState(OptionalContentGroup::Off); + for (auto &group : optionalContentGroups) { + group.second->setState(OptionalContentGroup::Off); } } @@ -126,42 +120,26 @@ OCGs::OCGs(Object *ocgObject, XRef *xref) : rbgroups = defaultOcgConfig.dictLookup("RBGroups"); } -OCGs::~OCGs() -{ - deleteGooList(optionalContentGroups, OptionalContentGroup); - delete display; -} - - bool OCGs::hasOCGs() const { - return ( optionalContentGroups->getLength() > 0 ); + return !( optionalContentGroups.empty() ); } -OptionalContentGroup* OCGs::findOcgByRef( const Ref &ref) +OptionalContentGroup* OCGs::findOcgByRef( const Ref &ref ) { - //TODO: make this more efficient - OptionalContentGroup *ocg = nullptr; - for (int i=0; i < optionalContentGroups->getLength(); ++i) { - ocg = (OptionalContentGroup*)optionalContentGroups->get(i); - if ( (ocg->getRef().num == ref.num) && (ocg->getRef().gen == ref.gen) ) { - return ocg; - } - } - - // not found - return nullptr; + const auto ocg = optionalContentGroups.find( ref ); + return ocg != optionalContentGroups.end() ? ocg->second.get() : nullptr; } OCDisplayNode *OCGs::getDisplayRoot() { if (display) - return display; + return display.get(); if (order.isArray()) - display = OCDisplayNode::parse(&order, this, m_xref); + display.reset(OCDisplayNode::parse(&order, this, m_xref)); - return display; + return display.get(); } bool OCGs::optContentIsVisible( Object *dictRef ) diff --git a/poppler/OptionalContent.h b/poppler/OptionalContent.h index ea5618e4..b62b0ee6 100644 --- a/poppler/OptionalContent.h +++ b/poppler/OptionalContent.h @@ -19,6 +19,8 @@ #include "Object.h" #include "CharTypes.h" +#include <unordered_map> +#include <memory> class GooString; class GooList; @@ -33,7 +35,6 @@ class OCGs { public: OCGs(Object *ocgObject, XRef *xref); - ~OCGs(); OCGs(const OCGs &) = delete; OCGs& operator=(const OCGs &) = delete; @@ -42,7 +43,7 @@ public: GBool isOk() const { return ok; } bool hasOCGs() const; - GooList *getOCGs() const { return optionalContentGroups; } + const std::unordered_map< Ref, std::unique_ptr< OptionalContentGroup > > &getOCGs() const { return optionalContentGroups; } OptionalContentGroup* findOcgByRef( const Ref &ref); @@ -66,12 +67,12 @@ private: bool anyOn( Array *ocgArray ); bool anyOff( Array *ocgArray ); - GooList *optionalContentGroups; + std::unordered_map< Ref, std::unique_ptr< OptionalContentGroup > > optionalContentGroups; Object order; Object rbgroups; XRef *m_xref; - OCDisplayNode *display; // root node of display tree + std::unique_ptr< OCDisplayNode > display; // root node of display tree }; //------------------------------------------------------------------------ diff --git a/poppler/StructTreeRoot.cc b/poppler/StructTreeRoot.cc index 58a4b6a6..4491f901 100644 --- a/poppler/StructTreeRoot.cc +++ b/poppler/StructTreeRoot.cc @@ -110,7 +110,7 @@ void StructTreeRoot::parse(Dict *root) } // refToParentMap is only used during parsing. Ensure all memory used by it is freed. - std::multimap<Ref, Parent*, RefCompare>().swap(refToParentMap); + std::multimap<Ref, Parent*>().swap(refToParentMap); } void StructTreeRoot::parseNumberTreeNode(Dict *node) diff --git a/poppler/StructTreeRoot.h b/poppler/StructTreeRoot.h index 89c7941c..e71b2ff7 100644 --- a/poppler/StructTreeRoot.h +++ b/poppler/StructTreeRoot.h @@ -79,7 +79,7 @@ private: Object classMap; ElemPtrArray elements; std::map<int, std::vector<Parent> > parentTree; - std::multimap<Ref, Parent*, RefCompare> refToParentMap; + std::multimap<Ref, Parent*> refToParentMap; void parse(Dict *rootDict); void parseNumberTreeNode(Dict *node); diff --git a/qt5/src/poppler-link.cc b/qt5/src/poppler-link.cc index 1086afce..b85ee493 100644 --- a/qt5/src/poppler-link.cc +++ b/qt5/src/poppler-link.cc @@ -35,11 +35,6 @@ #include "Link.h" #include "Rendition.h" -static bool operator==( const Ref &r1, const Ref &r2 ) -{ - return r1.num == r2.num && r1.gen == r2.gen; -} - namespace Poppler { class LinkDestinationPrivate : public QSharedData diff --git a/qt5/src/poppler-optcontent.cc b/qt5/src/poppler-optcontent.cc index 18997b6e..f5fc6d7e 100644 --- a/qt5/src/poppler-optcontent.cc +++ b/qt5/src/poppler-optcontent.cc @@ -165,12 +165,11 @@ namespace Poppler : q(qq) { m_rootNode = new OptContentItem(); - GooList *ocgs = optContent->getOCGs(); + const auto &ocgs = optContent->getOCGs(); - for (int i = 0; i < ocgs->getLength(); ++i) { - OptionalContentGroup *ocg = static_cast<OptionalContentGroup*>(ocgs->get(i)); - OptContentItem *node = new OptContentItem( ocg ); - m_optContentItems.insert( QString::number(ocg->getRef().num), node); + for (const auto& ocg : ocgs) { + OptContentItem *node = new OptContentItem( ocg.second.get() ); + m_optContentItems.insert( QString::number( ocg.first.num ), node ); } if ( optContent->getOrderArray() == nullptr ) { diff --git a/utils/pdfinfo.cc b/utils/pdfinfo.cc index 91423ebd..41708bd7 100644 --- a/utils/pdfinfo.cc +++ b/utils/pdfinfo.cc @@ -372,7 +372,7 @@ static void printLinkDest(LinkDest *dest) { } static void printDestinations(PDFDoc *doc, UnicodeMap *uMap) { - std::map<Ref,std::map<GooString*,LinkDest*,GooStringCompare>, RefCompare > map; + std::map<Ref,std::map<GooString*,LinkDest*,GooStringCompare> > map; int numDests = doc->getCatalog()->numDestNameTree(); for (int i = 0; i < numDests; i++) { _______________________________________________ poppler mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/poppler
