Commit 8456a6e1 authored by Carlos Garcia Campos's avatar Carlos Garcia Campos

xpdf303: Add OCDisplayNode

It's not used by poppler yet, but we might want to use it from the
frontends after the merge.
parent 06c6660d
......@@ -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);
}
......@@ -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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment