poppler/OptionalContent.cc | 127 +++++++++++++++++++++++++++++++++++++++++++++ poppler/OptionalContent.h | 36 ++++++++++++ 2 files changed, 162 insertions(+), 1 deletion(-)
New commits: commit 8456a6e1354126dc98357fb806595bd3bc198522 Author: Carlos Garcia Campos <[email protected]> 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 _______________________________________________ poppler mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/poppler
