[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