[poppler] Branch 'xpdf303merge' - poppler/OptionalContent.cc poppler/OptionalContent.h

Carlos Garcia Campos carlosgc at kemper.freedesktop.org
Sun Sep 18 07:09:10 PDT 2011


 poppler/OptionalContent.cc |  127 +++++++++++++++++++++++++++++++++++++++++++++
 poppler/OptionalContent.h  |   36 ++++++++++++
 2 files changed, 162 insertions(+), 1 deletion(-)

New commits:
commit 8456a6e1354126dc98357fb806595bd3bc198522
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Sun Sep 18 16:07:54 2011 +0200

    xpdf303: Add OCDisplayNode
    
    It's not used by poppler yet, but we might want to use it from the
    frontends after the merge.

diff --git a/poppler/OptionalContent.cc b/poppler/OptionalContent.cc
index 01a5a8b..e0d49bc 100644
--- a/poppler/OptionalContent.cc
+++ b/poppler/OptionalContent.cc
@@ -29,6 +29,10 @@
 // infinite loops in the visibility expression object structure.
 #define visibilityExprRecursionLimit 50
 
+// Max depth of nested display nodes.  This is used to catch infinite
+// loops in the "Order" object structure.
+#define displayNodeRecursionLimit 50
+
 //------------------------------------------------------------------------
 
 OCGs::OCGs(Object *ocgObject, XRef *xref) :
@@ -37,6 +41,7 @@ OCGs::OCGs(Object *ocgObject, XRef *xref) :
   // we need to parse the dictionary here, and build optionalContentGroups
   ok = gTrue;
   optionalContentGroups = new GooList();
+  display = NULL;
 
   Object ocgList;
   ocgObject->dictLookup("OCGs", &ocgList);
@@ -145,6 +150,8 @@ OCGs::~OCGs()
 {
   deleteGooList(optionalContentGroups, OptionalContentGroup);
   order.free();
+  if (display)
+    delete display;
   rbgroups.free();
 }
 
@@ -169,6 +176,17 @@ OptionalContentGroup* OCGs::findOcgByRef( const Ref &ref)
   return NULL;
 }
 
+OCDisplayNode *OCGs::getDisplayRoot()
+{
+  if (display)
+    return display;
+
+  if (order.isArray())
+    display = OCDisplayNode::parse(&order, this, m_xref);
+
+  return display;
+}
+
 bool OCGs::optContentIsVisible( Object *dictRef )
 {
   Object dictObj;
@@ -424,3 +442,112 @@ OptionalContentGroup::~OptionalContentGroup()
   delete m_name;
 }
 
+//------------------------------------------------------------------------
+
+OCDisplayNode *OCDisplayNode::parse(Object *obj, OCGs *oc,
+				    XRef *xref, int recursion) {
+  Object obj2, obj3;
+  OptionalContentGroup *ocgA;
+  OCDisplayNode *node, *child;
+  int i;
+
+  if (recursion > displayNodeRecursionLimit) {
+    error(errSyntaxError, -1, "Loop detected in optional content order");
+    return NULL;
+  }
+  if (obj->isRef()) {
+    if ((ocgA = oc->findOcgByRef(obj->getRef()))) {
+      return new OCDisplayNode(ocgA);
+    }
+  }
+  obj->fetch(xref, &obj2);
+  if (!obj2.isArray()) {
+    obj2.free();
+    return NULL;
+  }
+  i = 0;
+  if (obj2.arrayGetLength() >= 1) {
+    if (obj2.arrayGet(0, &obj3)->isString()) {
+      node = new OCDisplayNode(obj3.getString());
+      i = 1;
+    } else {
+      node = new OCDisplayNode();
+    }
+    obj3.free();
+  } else {
+    node = new OCDisplayNode();
+  }
+  for (; i < obj2.arrayGetLength(); ++i) {
+    obj2.arrayGetNF(i, &obj3);
+    if ((child = OCDisplayNode::parse(&obj3, oc, xref, recursion + 1))) {
+      if (!child->ocg && !child->name && node->getNumChildren() > 0) {
+	node->getChild(node->getNumChildren() - 1)->addChildren(child->takeChildren());
+	delete child;
+      } else {
+	node->addChild(child);
+      }
+    }
+    obj3.free();
+  }
+  obj2.free();
+  return node;
+}
+
+OCDisplayNode::OCDisplayNode() {
+  name = NULL;
+  ocg = NULL;
+  children = NULL;
+}
+
+OCDisplayNode::OCDisplayNode(GooString *nameA) {
+  name = new GooString(nameA);
+  ocg = NULL;
+  children = NULL;
+}
+
+OCDisplayNode::OCDisplayNode(OptionalContentGroup *ocgA) {
+  name = (ocgA->getName()) ? ocgA->getName()->copy() : NULL;
+  ocg = ocgA;
+  children = NULL;
+}
+
+void OCDisplayNode::addChild(OCDisplayNode *child) {
+  if (!children) {
+    children = new GooList();
+  }
+  children->append(child);
+}
+
+void OCDisplayNode::addChildren(GooList *childrenA) {
+  if (!children) {
+    children = new GooList();
+  }
+  children->append(childrenA);
+  delete childrenA;
+}
+
+GooList *OCDisplayNode::takeChildren() {
+  GooList *childrenA;
+
+  childrenA = children;
+  children = NULL;
+  return childrenA;
+}
+
+OCDisplayNode::~OCDisplayNode() {
+  gfree(name);
+  if (children) {
+    deleteGooList(children, OCDisplayNode);
+  }
+}
+
+int OCDisplayNode::getNumChildren() {
+  if (!children) {
+    return 0;
+  }
+  return children->getLength();
+}
+
+OCDisplayNode *OCDisplayNode::getChild(int idx) {
+  return (OCDisplayNode *)children->get(idx);
+}
diff --git a/poppler/OptionalContent.h b/poppler/OptionalContent.h
index 56e6b71..02c9a47 100644
--- a/poppler/OptionalContent.h
+++ b/poppler/OptionalContent.h
@@ -23,7 +23,8 @@ class GooString;
 class GooList;
 class XRef;
 
-class OptionalContentGroup; 
+class OptionalContentGroup;
+class OCDisplayNode;
 
 //------------------------------------------------------------------------
 
@@ -41,6 +42,10 @@ public:
 
   OptionalContentGroup* findOcgByRef( const Ref &ref);
 
+  // Get the root node of the optional content group display tree
+  // (which does not necessarily include all of the OCGs).
+  OCDisplayNode *getDisplayRoot();
+
   Array* getOrderArray() 
     { return (order.isArray() && order.arrayGetLength() > 0) ? order.getArray() : NULL; }
   Array* getRBGroupsArray() 
@@ -62,6 +67,7 @@ private:
   Object order;
   Object rbgroups;
   XRef *m_xref;
+  OCDisplayNode *display; // root node of display tree
 };
 
 //------------------------------------------------------------------------
@@ -103,4 +109,32 @@ private:
   UsageState printState; // suggested state when printing
 };
 
+//------------------------------------------------------------------------
+
+class OCDisplayNode {
+public:
+
+  static OCDisplayNode *parse(Object *obj, OCGs *oc, XRef *xref, int recursion = 0);
+  OCDisplayNode();
+  ~OCDisplayNode();
+
+  GooString *getName() { return name; }
+  OptionalContentGroup *getOCG() { return ocg; }
+  int getNumChildren();
+  OCDisplayNode *getChild(int idx);
+
+private:
+
+  OCDisplayNode(GooString *nameA);
+  OCDisplayNode(OptionalContentGroup *ocgA);
+  void addChild(OCDisplayNode *child);
+  void addChildren(GooList *childrenA);
+  GooList *takeChildren();
+
+  GooString *name;		// display name (may be NULL)
+  OptionalContentGroup *ocg;	// NULL for display labels
+  GooList *children;		// NULL if there are no children
+				//   [OCDisplayNode]
+};
+
 #endif


More information about the poppler mailing list