Commit 7e9b6f1d authored by Adam Reichold's avatar Adam Reichold Committed by Albert Astals Cid

Fix TODO in OCGs by creating a look-up table from Ref to OptionalContentGroup...

Fix TODO in OCGs by creating a look-up table from Ref to OptionalContentGroup (and make Ref a regular type to do so).
parent 94527d5a
Pipeline #4443 passed with stage
in 5 minutes and 1 second
......@@ -2494,15 +2494,11 @@ get_optional_content_items (OCGs *ocg)
if (order) {
items = get_optional_content_items_sorted (ocg, nullptr, order);
} else {
GooList *ocgs;
int i;
const auto &ocgs = ocg->getOCGs ();
for (const auto &oc : ocgs) {
Layer *layer = layer_new (oc.second.get());
ocgs = ocg->getOCGs ();
for (i = 0; i < ocgs->getLength (); ++i) {
OptionalContentGroup *oc = (OptionalContentGroup *) ocgs->get (i);
Layer *layer = layer_new (oc);
items = g_list_prepend (items, layer);
}
......
......@@ -89,14 +89,33 @@ struct Ref {
int gen; // generation number
};
struct RefCompare {
bool operator() (const Ref& lhs, const Ref& rhs) const {
if (lhs.num != rhs.num)
return lhs.num < rhs.num;
return lhs.gen < rhs.gen;
}
inline bool operator== (const Ref& lhs, const Ref& rhs) noexcept {
return lhs.num == rhs.num && lhs.gen == rhs.gen;
}
inline bool operator< (const Ref& lhs, const Ref& rhs) noexcept {
if (lhs.num != rhs.num)
return lhs.num < rhs.num;
return lhs.gen < rhs.gen;
}
namespace std
{
template<>
struct hash<Ref>
{
using argument_type = Ref;
using result_type = size_t;
result_type operator() (const argument_type &ref) const noexcept
{
return std::hash<int>{}(ref.num) ^ (std::hash<int>{}(ref.gen) << 1);
}
};
}
//------------------------------------------------------------------------
// object types
//------------------------------------------------------------------------
......
......@@ -40,8 +40,6 @@ OCGs::OCGs(Object *ocgObject, XRef *xref) :
{
// we need to parse the dictionary here, and build optionalContentGroups
ok = gTrue;
optionalContentGroups = new GooList();
display = nullptr;
Object ocgList = ocgObject->dictLookup("OCGs");
if (!ocgList.isArray()) {
......@@ -62,11 +60,10 @@ OCGs::OCGs(Object *ocgObject, XRef *xref) :
delete thisOptionalContentGroup;
break;
}
// TODO: we should create a lookup map from Ref to the OptionalContentGroup
thisOptionalContentGroup->setRef( ocg.getRef() );
// the default is ON - we change state later, depending on BaseState, ON and OFF
thisOptionalContentGroup->setState(OptionalContentGroup::On);
optionalContentGroups->append(thisOptionalContentGroup);
optionalContentGroups.emplace(ocg.getRef(), thisOptionalContentGroup);
}
Object defaultOcgConfig = ocgObject->dictLookup("D");
......@@ -78,11 +75,8 @@ OCGs::OCGs(Object *ocgObject, XRef *xref) :
Object baseState = defaultOcgConfig.dictLookup("BaseState");
if (baseState.isName("OFF")) {
for (int i = 0; i < optionalContentGroups->getLength(); ++i) {
OptionalContentGroup *group;
group = (OptionalContentGroup *)optionalContentGroups->get(i);
group->setState(OptionalContentGroup::Off);
for (auto &group : optionalContentGroups) {
group.second->setState(OptionalContentGroup::Off);
}
}
......@@ -126,42 +120,26 @@ OCGs::OCGs(Object *ocgObject, XRef *xref) :
rbgroups = defaultOcgConfig.dictLookup("RBGroups");
}
OCGs::~OCGs()
{
deleteGooList(optionalContentGroups, OptionalContentGroup);
delete display;
}
bool OCGs::hasOCGs() const
{
return ( optionalContentGroups->getLength() > 0 );
return !( optionalContentGroups.empty() );
}
OptionalContentGroup* OCGs::findOcgByRef( const Ref &ref)
OptionalContentGroup* OCGs::findOcgByRef( const Ref &ref )
{
//TODO: make this more efficient
OptionalContentGroup *ocg = nullptr;
for (int i=0; i < optionalContentGroups->getLength(); ++i) {
ocg = (OptionalContentGroup*)optionalContentGroups->get(i);
if ( (ocg->getRef().num == ref.num) && (ocg->getRef().gen == ref.gen) ) {
return ocg;
}
}
// not found
return nullptr;
const auto ocg = optionalContentGroups.find( ref );
return ocg != optionalContentGroups.end() ? ocg->second.get() : nullptr;
}
OCDisplayNode *OCGs::getDisplayRoot()
{
if (display)
return display;
return display.get();
if (order.isArray())
display = OCDisplayNode::parse(&order, this, m_xref);
display.reset(OCDisplayNode::parse(&order, this, m_xref));
return display;
return display.get();
}
bool OCGs::optContentIsVisible( Object *dictRef )
......
......@@ -19,6 +19,8 @@
#include "Object.h"
#include "CharTypes.h"
#include <unordered_map>
#include <memory>
class GooString;
class GooList;
......@@ -33,7 +35,6 @@ class OCGs {
public:
OCGs(Object *ocgObject, XRef *xref);
~OCGs();
OCGs(const OCGs &) = delete;
OCGs& operator=(const OCGs &) = delete;
......@@ -42,7 +43,7 @@ public:
GBool isOk() const { return ok; }
bool hasOCGs() const;
GooList *getOCGs() const { return optionalContentGroups; }
const std::unordered_map< Ref, std::unique_ptr< OptionalContentGroup > > &getOCGs() const { return optionalContentGroups; }
OptionalContentGroup* findOcgByRef( const Ref &ref);
......@@ -66,12 +67,12 @@ private:
bool anyOn( Array *ocgArray );
bool anyOff( Array *ocgArray );
GooList *optionalContentGroups;
std::unordered_map< Ref, std::unique_ptr< OptionalContentGroup > > optionalContentGroups;
Object order;
Object rbgroups;
XRef *m_xref;
OCDisplayNode *display; // root node of display tree
std::unique_ptr< OCDisplayNode > display; // root node of display tree
};
//------------------------------------------------------------------------
......
......@@ -110,7 +110,7 @@ void StructTreeRoot::parse(Dict *root)
}
// refToParentMap is only used during parsing. Ensure all memory used by it is freed.
std::multimap<Ref, Parent*, RefCompare>().swap(refToParentMap);
std::multimap<Ref, Parent*>().swap(refToParentMap);
}
void StructTreeRoot::parseNumberTreeNode(Dict *node)
......
......@@ -79,7 +79,7 @@ private:
Object classMap;
ElemPtrArray elements;
std::map<int, std::vector<Parent> > parentTree;
std::multimap<Ref, Parent*, RefCompare> refToParentMap;
std::multimap<Ref, Parent*> refToParentMap;
void parse(Dict *rootDict);
void parseNumberTreeNode(Dict *node);
......
......@@ -35,11 +35,6 @@
#include "Link.h"
#include "Rendition.h"
static bool operator==( const Ref &r1, const Ref &r2 )
{
return r1.num == r2.num && r1.gen == r2.gen;
}
namespace Poppler {
class LinkDestinationPrivate : public QSharedData
......
......@@ -165,12 +165,11 @@ namespace Poppler
: q(qq)
{
m_rootNode = new OptContentItem();
GooList *ocgs = optContent->getOCGs();
const auto &ocgs = optContent->getOCGs();
for (int i = 0; i < ocgs->getLength(); ++i) {
OptionalContentGroup *ocg = static_cast<OptionalContentGroup*>(ocgs->get(i));
OptContentItem *node = new OptContentItem( ocg );
m_optContentItems.insert( QString::number(ocg->getRef().num), node);
for (const auto& ocg : ocgs) {
OptContentItem *node = new OptContentItem( ocg.second.get() );
m_optContentItems.insert( QString::number( ocg.first.num ), node );
}
if ( optContent->getOrderArray() == nullptr ) {
......
......@@ -372,7 +372,7 @@ static void printLinkDest(LinkDest *dest) {
}
static void printDestinations(PDFDoc *doc, UnicodeMap *uMap) {
std::map<Ref,std::map<GooString*,LinkDest*,GooStringCompare>, RefCompare > map;
std::map<Ref,std::map<GooString*,LinkDest*,GooStringCompare> > map;
int numDests = doc->getCatalog()->numDestNameTree();
for (int i = 0; i < numDests; i++) {
......
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