[poppler] glib/poppler-document.cc poppler/Object.h poppler/OptionalContent.cc poppler/OptionalContent.h poppler/StructTreeRoot.cc poppler/StructTreeRoot.h qt5/src utils/pdfinfo.cc

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Sep 17 22:27:32 UTC 2018


 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 <adam.reichold at t-online.de>
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++) {


More information about the poppler mailing list