diff options
Diffstat (limited to 'Build/source/libs/poppler/poppler-0.29.0/poppler/StructTreeRoot.cc')
-rw-r--r-- | Build/source/libs/poppler/poppler-0.29.0/poppler/StructTreeRoot.cc | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/Build/source/libs/poppler/poppler-0.29.0/poppler/StructTreeRoot.cc b/Build/source/libs/poppler/poppler-0.29.0/poppler/StructTreeRoot.cc new file mode 100644 index 00000000000..e46e3e28388 --- /dev/null +++ b/Build/source/libs/poppler/poppler-0.29.0/poppler/StructTreeRoot.cc @@ -0,0 +1,175 @@ +//======================================================================== +// +// StructTreeRoot.cc +// +// This file is licensed under the GPLv2 or later +// +// Copyright 2013, 2014 Igalia S.L. +// Copyright 2014 Fabio D'Urso <fabiodurso@hotmail.it> +// +//======================================================================== + +#ifdef USE_GCC_PRAGMAS +#pragma interface +#endif + +#include "goo/GooString.h" +#include "StructTreeRoot.h" +#include "StructElement.h" +#include "PDFDoc.h" +#include "Object.h" +#include "Dict.h" +#include <set> +#include <assert.h> + + +StructTreeRoot::StructTreeRoot(PDFDoc *docA, Dict *structTreeRootDict): + doc(docA) +{ + assert(doc); + assert(structTreeRootDict); + parse(structTreeRootDict); +} + +StructTreeRoot::~StructTreeRoot() +{ + for (ElemPtrArray::iterator i = elements.begin(); i != elements.end(); ++i) + delete *i; + classMap.free(); + roleMap.free(); +} + +void StructTreeRoot::parse(Dict *root) +{ + // The RoleMap/ClassMap dictionaries are needed by all the parsing + // functions, which will resolve the custom names to canonical + // standard names. + root->lookup("RoleMap", &roleMap); + root->lookup("ClassMap", &classMap); + + // ParentTree (optional). If present, it must be a number tree, + // otherwise it is not possible to map stream objects to their + // corresponsing structure element. Here only the references are + // loaded into the array, the pointers to the StructElements will + // be filled-in later when parsing them. + Object obj; + if (root->lookup("ParentTree", &obj)->isDict()) { + Object nums; + if (obj.dictLookup("Nums", &nums)->isArray()) { + if (nums.arrayGetLength() % 2 == 0) { + parentTree.resize(nums.arrayGetLength() / 2); + // Index numbers in even positions, references in odd ones + for (int i = 0; i < nums.arrayGetLength(); i += 2) { + Object index, value; + + if (!nums.arrayGet(i, &index)->isInt()) { + error(errSyntaxError, -1, "Nums item at position {0:d} is wrong type ({1:s})", i, index.getTypeName()); + index.free(); + continue; + } + if (index.getInt() < 0) { + error(errSyntaxError, -1, "Nums item at position {0:d} is invalid value ({1:d})", i, index.getInt()); + index.free(); + continue; + } + + const unsigned idx = index.getInt(); + if (nums.arrayGetNF(i + 1, &value)->isRef()) { + parentTree[idx].resize(1); + parentTree[idx][0].ref = value.getRef(); + } else if (nums.arrayGet(i + 1, &value)->isArray()) { + parentTree[idx].resize(value.arrayGetLength()); + for (int j = 0; j < value.arrayGetLength(); j++) { + Object itemvalue; + if (value.arrayGetNF(j, &itemvalue)->isRef()) + parentTree[idx][j].ref = itemvalue.getRef(); + else + error(errSyntaxError, -1, "Nums array item at position {0:d}/{1:d} is invalid type ({2:s})", i, j, itemvalue.getTypeName()); + itemvalue.free(); + } + } else { + error(errSyntaxError, -1, "Nums item at position {0:d} is wrong type ({1:s})", i + 1, value.getTypeName()); + } + + value.free(); + index.free(); + } + } else { + error(errSyntaxError, -1, "Nums array length is not a even ({0:d})", nums.arrayGetLength()); + } + } else { + error(errSyntaxError, -1, "Nums object is wrong type ({0:s})", nums.getTypeName()); + } + nums.free(); + } + obj.free(); + + std::set<int> seenElements; + + // Parse the children StructElements + const GBool marked = doc->getCatalog()->getMarkInfo() & Catalog::markInfoMarked; + Object kids; + if (root->lookup("K", &kids)->isArray()) { + if (marked && kids.arrayGetLength() > 1) { + error(errSyntaxWarning, -1, "K in StructTreeRoot has more than one children in a tagged PDF"); + } + for (int i = 0; i < kids.arrayGetLength(); i++) { + Object obj, ref; + kids.arrayGetNF(i, &ref); + if (ref.isRef()) { + seenElements.insert(ref.getRefNum()); + } + if (kids.arrayGet(i, &obj)->isDict()) { + StructElement *child = new StructElement(obj.getDict(), this, NULL, seenElements); + if (child->isOk()) { + if (marked && !(child->getType() == StructElement::Document || + child->getType() == StructElement::Part || + child->getType() == StructElement::Art || + child->getType() == StructElement::Div)) { + error(errSyntaxWarning, -1, "StructTreeRoot element of tagged PDF is wrong type ({0:s})", child->getTypeName()); + } + appendChild(child); + if (ref.isRef()) { + parentTreeAdd(ref.getRef(), child); + } + } else { + error(errSyntaxWarning, -1, "StructTreeRoot element could not be parsed"); + delete child; + } + } else { + error(errSyntaxWarning, -1, "K has a child of wrong type ({0:s})", obj.getTypeName()); + } + obj.free(); + ref.free(); + } + } else if (kids.isDict()) { + if (marked) { + error(errSyntaxWarning, -1, "K has a child of wrong type for a tagged PDF ({0:s})", kids.getTypeName()); + } + StructElement *child = new StructElement(kids.getDict(), this, NULL, seenElements); + if (child->isOk()) { + appendChild(child); + Object ref; + if (root->lookupNF("K", &ref)->isRef()) + parentTreeAdd(ref.getRef(), child); + ref.free(); + } else { + error(errSyntaxWarning, -1, "StructTreeRoot element could not be parsed"); + delete child; + } + } else if (!kids.isNull()) { + error(errSyntaxWarning, -1, "K in StructTreeRoot is wrong type ({0:s})", kids.getTypeName()); + } + + kids.free(); +} + +void StructTreeRoot::parentTreeAdd(const Ref &objectRef, StructElement *element) +{ + for (std::vector< std::vector<Parent> >::iterator i = parentTree.begin(); i != parentTree.end(); ++i) { + for (std::vector<Parent>::iterator j = i->begin(); j != i->end(); ++j) { + if (j->ref.num == objectRef.num && j->ref.gen == objectRef.gen) + j->element = element; + } + } +} |