[poppler] 7 commits - CMakeLists.txt cpp/CMakeLists.txt poppler/GfxState.cc poppler/Link.cc poppler/Link.h qt5/src
Adam Reichold
adam.reichold at t-online.de
Mon Apr 16 18:36:37 UTC 2018
Hello again,
Am 16.04.2018 um 20:22 schrieb Albert Astals Cid:
> El dilluns, 16 d’abril de 2018, a les 19:05:25 CEST, Adam Reichold va
> escriure:
>> Hello,
>>
>> concerning df8a4ee51e18a39f85568c4122e5edd8c03d61df, I think there is a
>> problem in the "isArray" branch where a moved-from value
>> "seenNextActions" is used if the array contains more than one dict. I
>> think this is generally undefined behavior (even though it is probably
>> fine in this case since a moved-from std::unique_ptr is probably just
>> empty, but the only guarantee is that it can be destructed safely).
>>
>> But I also think that it is not how the function is supposed to work
>> since every call to parseActions should start we the same prefix of
>> already-seen actions, hence needs to start with the same value of
>> seenNextActions modifying its private copy if actual branching takes
>> place, so that the copies probably cannot be elided in that part of the
>> function.
>
> You're right, good catch!
>
>> Also if this is about performance, I think this could be a bit lazier by
>> initializing the set the first when it will really be used, it could use
>> std::unordered_set since we only check membership and a single lookup
>> should suffice since it returns whether insertion actually took place.
>>
>> But also since an empty instance of std::set does not allocate any
>> nodes, wouldn't it be even simpler to just pass that set by value moving
>> the set and not the pointer to it where that is possible? (It is
>> basically the size of two pointers instead of one, but also looses one
>> indirection.)
>
> But your patch does exactly what i want to avoid, you're copying the set in
>
> auto seenNextActionsAux = seenNextActions;
>
> This other patch I'm attaching should fix the problem too with less copying,
> right?
It does not copy, but it is not functionally equivalent to the original
implementation which would not share the already-seen actions between
the branches in the array (as this does not imply circular connections).
Also std::shared_ptr uses atomic reference counts behind the scenes and
is hence a rather heavy weight abstraction w.r.t performance.
So if any repetitions and not just circular paths are forbidden, the
easiest option would probably be to have parseAction just become
static LinkAction* doParseAction(const Object*, const GooString*, const
std::std<int>&);
with an additional helper
static LinkAction parseAction(const Object* obj, const GooString* baseURI) {
std::set<int> seenNextActions;
return doParseAction(obj, baseURI, seenNextActions);
}
To keep the original semantics one must copy if I understand things
correctly.
> Cheers,
> Albert
Best regards, Adam.
>>
>> Best regards,
>> Adam
>>
>> Am 16.04.2018 um 18:10 schrieb Albert Astals Cid:
>>> CMakeLists.txt | 7 ++
>>> cpp/CMakeLists.txt | 1
>>> poppler/GfxState.cc | 5 +
>>> poppler/Link.cc | 103
>>> ++++++++++++++++++++++++++++++++++++++++- poppler/Link.h
>>> | 54 ++++++++++++++++++++-
>>> qt5/src/poppler-annotation.cc | 6 ++
>>> qt5/src/poppler-link-private.h | 26 ++++++++++
>>> qt5/src/poppler-link.cc | 35 +++++++++++++
>>> qt5/src/poppler-link.h | 50 +++++++++++++++++++
>>> qt5/src/poppler-page.cc | 25 +++++++++
>>> 10 files changed, 303 insertions(+), 9 deletions(-)
>>>
>>> New commits:
>>> commit 88c99f1f6f4faf31faabccd35d9d094958020ebc
>>> Author: Albert Astals Cid <aacid at kde.org>
>>> Date: Mon Apr 16 17:59:35 2018 +0200
>>>
>>> Fix crash on malformed documents
>>>
>>> In GfxGouraudTriangleShading::parse
>>>
>>> Bug #106061
>>>
>>> diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc
>>> index 95699355..5d7cc6ba 100644
>>> --- a/poppler/GfxState.cc
>>> +++ b/poppler/GfxState.cc
>>> @@ -4916,7 +4916,7 @@ GfxGouraudTriangleShading
>>> *GfxGouraudTriangleShading::parse(GfxResources *res, i>
>>> }
>>>
>>> }
>>> delete bitBuf;
>>>
>>> - if (typeA == 5 && nVerticesA > 0) {
>>> + if (typeA == 5 && nVerticesA > 0 && vertsPerRow > 0) {
>>>
>>> nRows = nVerticesA / vertsPerRow;
>>> nTrianglesA = (nRows - 1) * 2 * (vertsPerRow - 1);
>>> trianglesA = (int (*)[3])gmallocn_checkoverflow(nTrianglesA * 3,
>>> sizeof(int));>
>>> commit df8a4ee51e18a39f85568c4122e5edd8c03d61df
>>> Author: Albert Astals Cid <aacid at kde.org>
>>> Date: Mon Apr 16 17:46:10 2018 +0200
>>>
>>> Make it so we copy seenNextActions a bit less
>>>
>>> diff --git a/poppler/Link.cc b/poppler/Link.cc
>>> index 2f853125..42bdaf1b 100644
>>> --- a/poppler/Link.cc
>>> +++ b/poppler/Link.cc
>>> @@ -71,7 +71,7 @@ LinkAction *LinkAction::parseDest(const Object *obj) {
>>>
>>> }
>>>
>>> LinkAction *LinkAction::parseAction(const Object *obj, const GooString
>>> *baseURI,>
>>> - const std::set<int> *seenNextActions)
>>> { + std::unique_ptr<std::set<int>>
>>> seenNextActions) {>
>>> LinkAction *action;
>>>
>>> if (!obj->isDict()) {
>>>
>>> @@ -160,18 +160,19 @@ LinkAction *LinkAction::parseAction(const Object
>>> *obj, const GooString *baseURI,>
>>> // Prevent circles in the tree by checking the ref against used refs
>>> in
>>> // our current tree branch.
>>> const Object nextRefObj = obj->dictLookupNF("Next");
>>>
>>> - std::set<int> seenNextActionsAux = seenNextActions ? *seenNextActions
>>> : std::set<int> (); + if (!seenNextActions)
>>> + seenNextActions.reset(new std::set<int>);
>>>
>>> if (nextRefObj.isRef()) {
>>>
>>> const Ref ref = nextRefObj.getRef();
>>>
>>> - if (seenNextActionsAux.find(ref.num) != seenNextActionsAux.end())
>>> { + if (seenNextActions->find(ref.num) != seenNextActions->end())
>>> {>
>>> error(errSyntaxWarning, -1, "parseAction: Circular next
>>> actions detected."); return action;
>>>
>>> }
>>>
>>> - seenNextActionsAux.insert(ref.num);
>>> + seenNextActions->insert(ref.num);
>>>
>>> }
>>>
>>> actionList = new GooList(1);
>>>
>>> - actionList->append(parseAction(&nextObj, nullptr,
>>> &seenNextActionsAux)); + actionList->append(parseAction(&nextObj,
>>> nullptr, std::move(seenNextActions)));>
>>> } else if (nextObj.isArray()) {
>>>
>>> const Array *a = nextObj.getArray();
>>> const int n = a->getLength();
>>>
>>> @@ -184,18 +185,19 @@ LinkAction *LinkAction::parseAction(const Object
>>> *obj, const GooString *baseURI,>
>>> }
>>>
>>> // Similar circle check as above.
>>>
>>> - std::set<int> seenNextActionsAux = seenNextActions ?
>>> *seenNextActions : std::set<int> (); + if (!seenNextActions)
>>> + seenNextActions.reset(new std::set<int>);
>>>
>>> const Object obj3Ref = a->getNF(i);
>>> if (obj3Ref.isRef()) {
>>>
>>> const Ref ref = obj3Ref.getRef();
>>>
>>> - if (seenNextActionsAux.find(ref.num) !=
>>> seenNextActionsAux.end()) { + if (seenNextActions->find(ref.num)
>>> != seenNextActions->end()) {>
>>> error(errSyntaxWarning, -1, "parseAction: Circular next
>>> actions detected in array."); return action;
>>>
>>> }
>>>
>>> - seenNextActionsAux.insert(ref.num);
>>> + seenNextActions->insert(ref.num);
>>>
>>> }
>>>
>>> - actionList->append(parseAction(&obj3, nullptr,
>>> &seenNextActionsAux)); + actionList->append(parseAction(&obj3,
>>> nullptr, std::move(seenNextActions)));>
>>> }
>>>
>>> }
>>>
>>> diff --git a/poppler/Link.h b/poppler/Link.h
>>> index 806e30f6..77d224d9 100644
>>> --- a/poppler/Link.h
>>> +++ b/poppler/Link.h
>>> @@ -34,6 +34,7 @@
>>>
>>> #endif
>>>
>>> #include "Object.h"
>>>
>>> +#include <memory>
>>>
>>> #include <set>
>>>
>>> class GooString;
>>>
>>> @@ -85,7 +86,7 @@ public:
>>> // Parse an action dictionary.
>>> static LinkAction *parseAction(const Object *obj, const GooString
>>> *baseURI = nullptr,>
>>> - const std::set<int> *seenNextActions =
>>> nullptr); +
>>> std::unique_ptr<std::set<int>> seenNextActions = nullptr);>
>>> // A List of the next actions to execute in order.
>>> // The list contains pointer to LinkAction objects.
>>>
>>> commit bd9fb431941916174e1c3b2201bf5f422bcf61bd
>>> Author: Aleix Pol <aleixpol at kde.org>
>>> Date: Mon Apr 16 16:38:09 2018 +0200
>>>
>>> Make it possible to build poppler on Android without fontconfig
>>>
>>> Didn't manage to make fontconfig build, still nice to have poppler
>>> available.
>>>
>>> diff --git a/CMakeLists.txt b/CMakeLists.txt
>>> index efa6c3f4..e2ebc44d 100644
>>> --- a/CMakeLists.txt
>>> +++ b/CMakeLists.txt
>>> @@ -89,10 +89,13 @@ endif()
>>>
>>> if(WIN32)
>>>
>>> set(_default_fontconfiguration "win32")
>>>
>>> +elseif(ANDROID)
>>> + # on android we don't have fontconfig and we don't want window-specific
>>> code + set(_default_fontconfiguration "generic")
>>>
>>> else()
>>>
>>> set(_default_fontconfiguration "fontconfig")
>>>
>>> endif()
>>>
>>> -set(FONT_CONFIGURATION "${_default_fontconfiguration}" CACHE STRING "The
>>> font configuration backend (win32|fontconfig).") +set(FONT_CONFIGURATION
>>> "${_default_fontconfiguration}" CACHE STRING "The font configuration
>>> backend (win32|generic|fontconfig).")>
>>> string(TOLOWER "${FONT_CONFIGURATION}" font_configuration)
>>> set(WITH_FONTCONFIGURATION_WIN32 OFF)
>>> set(WITH_FONTCONFIGURATION_FONTCONFIG OFF)
>>>
>>> @@ -100,6 +103,8 @@ if(font_configuration STREQUAL "win32")
>>>
>>> set(WITH_FONTCONFIGURATION_WIN32 ON)
>>>
>>> elseif(font_configuration STREQUAL "fontconfig")
>>>
>>> set(WITH_FONTCONFIGURATION_FONTCONFIG ON)
>>>
>>> +elseif(font_configuration STREQUAL "generic")
>>> + message(STATUS "no fontconfig or win32 specific code")
>>>
>>> else()
>>>
>>> message(FATAL_ERROR "Invalid font configuration setting:
>>> ${FONT_CONFIGURATION}")>
>>> endif()
>>>
>>> commit 34a44e5b95230b1ed03bb030e9963d0187b01951
>>> Author: Aleix Pol <aleixpol at kde.org>
>>> Date: Mon Apr 16 16:35:47 2018 +0200
>>>
>>> Do not assume that iconv is in /usr/include
>>>
>>> We find it explicitly because it may be elsewhere.
>>>
>>> diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt
>>> index ea252088..a08ee263 100644
>>> --- a/cpp/CMakeLists.txt
>>> +++ b/cpp/CMakeLists.txt
>>> @@ -1,6 +1,7 @@
>>>
>>> include_directories(
>>>
>>> ${CMAKE_CURRENT_SOURCE_DIR}
>>> ${CMAKE_CURRENT_BINARY_DIR}
>>>
>>> + ${ICONV_INCLUDE_DIR}
>>>
>>> )
>>>
>>> configure_file(poppler-version.h.in
>>> ${CMAKE_CURRENT_BINARY_DIR}/poppler-version.h @ONLY)>
>>> commit bdd8db389c7b09cd9042267f36214f809e4c5f60
>>> Author: Andre Heinecke <aheinecke at intevation.de>
>>> Date: Mon Apr 16 17:13:05 2018 +0200
>>>
>>> Add support for Next actions following an action
>>>
>>> Next actions are action dictionaries or an array
>>> of action dictonaries. "Next" is an entry in the
>>> general action dictionary.
>>>
>>> These actions are supposed to be performed after each other.
>>> So that a single button press can for example
>>> both trigger a Hide action and a JavaScript action.
>>>
>>> diff --git a/poppler/Link.cc b/poppler/Link.cc
>>> index a748d69e..2f853125 100644
>>> --- a/poppler/Link.cc
>>> +++ b/poppler/Link.cc
>>> @@ -52,6 +52,12 @@
>>>
>>> //-----------------------------------------------------------------------
>>> -
>>> // LinkAction
>>> //-----------------------------------------------------------------------
>>> -
>>>
>>> +LinkAction::LinkAction() : nextActionList(nullptr) {
>>> +}
>>> +
>>> +LinkAction::~LinkAction() {
>>> + delete nextActionList;
>>> +}
>>>
>>> LinkAction *LinkAction::parseDest(const Object *obj) {
>>>
>>> LinkAction *action;
>>>
>>> @@ -64,7 +70,8 @@ LinkAction *LinkAction::parseDest(const Object *obj) {
>>>
>>> return action;
>>>
>>> }
>>>
>>> -LinkAction *LinkAction::parseAction(const Object *obj, const GooString
>>> *baseURI) { +LinkAction *LinkAction::parseAction(const Object *obj, const
>>> GooString *baseURI, + const
>>> std::set<int> *seenNextActions) {>
>>> LinkAction *action;
>>>
>>> if (!obj->isDict()) {
>>>
>>> @@ -140,9 +147,72 @@ LinkAction *LinkAction::parseAction(const Object
>>> *obj, const GooString *baseURI)>
>>> delete action;
>>> return nullptr;
>>>
>>> }
>>>
>>> +
>>> + if (!action) {
>>> + return nullptr;
>>> + }
>>> +
>>> + // parse the next actions
>>> + const Object nextObj = obj->dictLookup("Next");
>>> + GooList *actionList = nullptr;
>>> + if (nextObj.isDict()) {
>>> +
>>> + // Prevent circles in the tree by checking the ref against used refs
>>> in + // our current tree branch.
>>> + const Object nextRefObj = obj->dictLookupNF("Next");
>>> + std::set<int> seenNextActionsAux = seenNextActions ? *seenNextActions
>>> : std::set<int> (); + if (nextRefObj.isRef()) {
>>> + const Ref ref = nextRefObj.getRef();
>>> + if (seenNextActionsAux.find(ref.num) != seenNextActionsAux.end())
>>> { + error(errSyntaxWarning, -1, "parseAction: Circular next
>>> actions detected."); + return action;
>>> + }
>>> + seenNextActionsAux.insert(ref.num);
>>> + }
>>> +
>>> + actionList = new GooList(1);
>>> + actionList->append(parseAction(&nextObj, nullptr,
>>> &seenNextActionsAux)); + } else if (nextObj.isArray()) {
>>> + const Array *a = nextObj.getArray();
>>> + const int n = a->getLength();
>>> + actionList = new GooList(n);
>>> + for (int i = 0; i < n; ++i) {
>>> + const Object obj3 = a->get(i);
>>> + if (!obj3.isDict()) {
>>> + error(errSyntaxWarning, -1, "parseAction: Next array does not
>>> contain only dicts"); + continue;
>>> + }
>>> +
>>> + // Similar circle check as above.
>>> + std::set<int> seenNextActionsAux = seenNextActions ?
>>> *seenNextActions : std::set<int> (); + const Object obj3Ref =
>>> a->getNF(i);
>>> + if (obj3Ref.isRef()) {
>>> + const Ref ref = obj3Ref.getRef();
>>> + if (seenNextActionsAux.find(ref.num) !=
>>> seenNextActionsAux.end()) { + error(errSyntaxWarning, -1,
>>> "parseAction: Circular next actions detected in array."); +
>>> return action;
>>> + }
>>> + seenNextActionsAux.insert(ref.num);
>>> + }
>>> +
>>> + actionList->append(parseAction(&obj3, nullptr,
>>> &seenNextActionsAux)); + }
>>> + }
>>> +
>>> + action->setNextActions(actionList);
>>> +
>>>
>>> return action;
>>>
>>> }
>>>
>>> +const GooList *LinkAction::nextActions() const {
>>> + return nextActionList;
>>> +}
>>> +
>>> +void LinkAction::setNextActions(GooList *actions) {
>>> + delete nextActionList;
>>> + nextActionList = actions;
>>> +}
>>> +
>>>
>>> //-----------------------------------------------------------------------
>>> -
>>> // LinkDest
>>> //-----------------------------------------------------------------------
>>> -
>>>
>>> diff --git a/poppler/Link.h b/poppler/Link.h
>>> index 229a8431..806e30f6 100644
>>> --- a/poppler/Link.h
>>> +++ b/poppler/Link.h
>>> @@ -34,6 +34,7 @@
>>>
>>> #endif
>>>
>>> #include "Object.h"
>>>
>>> +#include <set>
>>>
>>> class GooString;
>>> class GooList;
>>>
>>> @@ -66,12 +67,12 @@ enum LinkActionKind {
>>>
>>> class LinkAction {
>>>
>>> public:
>>> - LinkAction() = default;
>>> + LinkAction();
>>>
>>> LinkAction(const LinkAction &) = delete;
>>> LinkAction& operator=(const LinkAction &other) = delete;
>>>
>>> // Destructor.
>>>
>>> - virtual ~LinkAction() {}
>>> + virtual ~LinkAction();
>>>
>>> // Was the LinkAction created successfully?
>>> virtual GBool isOk() const = 0;
>>>
>>> @@ -83,7 +84,18 @@ public:
>>> static LinkAction *parseDest(const Object *obj);
>>>
>>> // Parse an action dictionary.
>>>
>>> - static LinkAction *parseAction(const Object *obj, const GooString
>>> *baseURI = NULL); + static LinkAction *parseAction(const Object *obj,
>>> const GooString *baseURI = nullptr, +
>>> const std::set<int> *seenNextActions = nullptr); +
>>> + // A List of the next actions to execute in order.
>>> + // The list contains pointer to LinkAction objects.
>>> + const GooList *nextActions() const;
>>> +
>>> + // Sets the next action list. Takes ownership of the actions.
>>> + void setNextActions(GooList *actions);
>>> +
>>> +private:
>>> + GooList *nextActionList;
>>>
>>> };
>>>
>>> //-----------------------------------------------------------------------
>>> -
>>>
>>> diff --git a/qt5/src/poppler-link-private.h
>>> b/qt5/src/poppler-link-private.h index e54c8f86..766f1899 100644
>>> --- a/qt5/src/poppler-link-private.h
>>> +++ b/qt5/src/poppler-link-private.h
>>> @@ -24,6 +24,8 @@ class LinkOCGState;
>>>
>>> namespace Poppler {
>>>
>>> +class Link;
>>> +
>>>
>>> class LinkPrivate
>>> {
>>>
>>> public:
>>> @@ -34,12 +36,19 @@ public:
>>> virtual ~LinkPrivate()
>>> {
>>>
>>> + qDeleteAll(nextLinks);
>>> + }
>>> +
>>> + static LinkPrivate *get( Link *link )
>>> + {
>>> + return link->d_ptr;
>>>
>>> }
>>>
>>> LinkPrivate(const LinkPrivate &) = delete;
>>> LinkPrivate& operator=(const LinkPrivate &) = delete;
>>>
>>> QRectF linkArea;
>>>
>>> + QVector <Link *> nextLinks;
>>>
>>> };
>>>
>>> diff --git a/qt5/src/poppler-link.cc b/qt5/src/poppler-link.cc
>>> index 1279e0b2..1086afce 100644
>>> --- a/qt5/src/poppler-link.cc
>>> +++ b/qt5/src/poppler-link.cc
>>> @@ -427,7 +427,12 @@ class LinkMoviePrivate : public LinkPrivate
>>>
>>> Q_D( const Link );
>>> return d->linkArea;
>>>
>>> }
>>>
>>> -
>>> +
>>> + QVector< Link * > Link::nextLinks() const
>>> + {
>>> + return d_ptr->nextLinks;
>>> + }
>>> +
>>>
>>> // LinkGoto
>>> LinkGoto::LinkGoto( const QRectF &linkArea, QString extFileName,
> const
>>> LinkDestination & destination )>
>>> : Link( *new LinkGotoPrivate( linkArea, destination ) )
>>>
>>> diff --git a/qt5/src/poppler-link.h b/qt5/src/poppler-link.h
>>> index 5a59b6f3..0ce4c0d1 100644
>>> --- a/qt5/src/poppler-link.h
>>> +++ b/qt5/src/poppler-link.h
>>> @@ -29,6 +29,7 @@
>>>
>>> #include <QtCore/QString>
>>> #include <QtCore/QRectF>
>>> #include <QtCore/QSharedDataPointer>
>>>
>>> +#include <QtCore/QVector>
>>>
>>> #include "poppler-export.h"
>>>
>>> struct Ref;
>>>
>>> @@ -177,6 +178,7 @@ class POPPLER_QT5_EXPORT LinkDestination
>>>
>>> class POPPLER_QT5_EXPORT Link
>>> {
>>>
>>> friend class OptContentModel;
>>>
>>> + friend class LinkPrivate;
>>>
>>> public:
>>> /// \cond PRIVATE
>>>
>>> @@ -220,7 +222,14 @@ class POPPLER_QT5_EXPORT Link
>>>
>>> * a general action. The area is given in 0..1 range
>>> */
>>>
>>> QRectF linkArea() const;
>>>
>>> -
>>> +
>>> + /**
>>> + * Get the next links to be activiated / executed after this
> link.
>>> + *
>>> + * \since 0.64
>>> + */
>>> + QVector<Link *> nextLinks() const;
>>> +
>>>
>>> protected:
>>> /// \cond PRIVATE
>>> Link( LinkPrivate &dd );
>>>
>>> diff --git a/qt5/src/poppler-page.cc b/qt5/src/poppler-page.cc
>>> index 3ed98846..b48ee959 100644
>>> --- a/qt5/src/poppler-page.cc
>>> +++ b/qt5/src/poppler-page.cc
>>> @@ -358,6 +358,20 @@ Link* PageData::convertLinkActionToLink(::LinkAction
>>> * a, DocumentData *parentDo>
>>> break;
>>>
>>> }
>>>
>>> + if ( popplerLink )
>>> + {
>>> + const GooList *nextActions = a->nextActions();
>>> + if ( nextActions )
>>> + {
>>> + QVector<Link *> links;
>>> + for ( int i = 0; i < nextActions->getLength(); ++i )
>>> + {
>>> + links << convertLinkActionToLink( static_cast< ::LinkAction * >(
>>> nextActions->get( i ) ), parentDoc, linkArea ); + }
>>> + LinkPrivate::get(popplerLink)->nextLinks = links;
>>> + }
>>> + }
>>> +
>>>
>>> return popplerLink;
>>>
>>> }
>>>
>>> commit ab72205dd14efe9c5c8d12e6b1ae538208bce168
>>> Author: Andre Heinecke <aheinecke at intevation.de>
>>> Date: Mon Apr 16 16:31:38 2018 +0200
>>>
>>> Add support for hide action
>>>
>>> The hide action can be used to show / hide fields.
>>>
>>> diff --git a/poppler/Link.cc b/poppler/Link.cc
>>> index 9be6a8c1..a748d69e 100644
>>> --- a/poppler/Link.cc
>>> +++ b/poppler/Link.cc
>>> @@ -21,6 +21,7 @@
>>>
>>> // Copyright (C) 2009 Ilya Gorenbein <igorenbein at finjan.com>
>>> // Copyright (C) 2012 Tobias Koening <tobias.koenig at kdab.com>
>>> // Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company,
>>> <info at kdab.com>. Work sponsored by the LiMux project of the city of
>>> Munich>
>>> +// Copyright (C) 2018 Intevation GmbH <intevation at intevation.de>
>>>
>>> //
>>> // To see a description of the changes please see the Changelog file that
>>> // came with your tarball or type make ChangeLog if you are building from
>>> git>
>>> @@ -120,6 +121,10 @@ LinkAction *LinkAction::parseAction(const Object
>>> *obj, const GooString *baseURI)>
>>> } else if (obj2.isName("SetOCGState")) {
>>>
>>> action = new LinkOCGState(obj);
>>>
>>> + // Hide action
>>> + } else if (obj2.isName("Hide")) {
>>> + action = new LinkHide(obj);
>>> +
>>>
>>> // unknown action
>>> } else if (obj2.isName()) {
>>>
>>> action = new LinkUnknown(obj2.getName());
>>>
>>> @@ -811,6 +816,30 @@ LinkOCGState::StateList::~StateList() {
>>>
>>> }
>>>
>>> //-----------------------------------------------------------------------
>>> -
>>>
>>> +// LinkHide
>>> +//-----------------------------------------------------------------------
>>> -
>>> +
>>> +LinkHide::LinkHide(const Object *hideObj) {
>>> + targetName = nullptr;
>>> + show = false; // Default
>>> +
>>> + if (hideObj->isDict()) {
>>> + const Object targetObj = hideObj->dictLookup("T");
>>> + if (targetObj.isString()) {
>>> + targetName = targetObj.getString()->copy();
>>> + }
>>> + const Object shouldHide = hideObj->dictLookup("H");
>>> + if (shouldHide.isBool()) {
>>> + show = !shouldHide.getBool();
>>> + }
>>> + }
>>> +}
>>> +
>>> +LinkHide::~LinkHide() {
>>> + delete targetName;
>>> +}
>>> +
>>> +//-----------------------------------------------------------------------
>>> -
>>>
>>> // LinkUnknown
>>> //-----------------------------------------------------------------------
>>> -
>>>
>>> diff --git a/poppler/Link.h b/poppler/Link.h
>>> index 90496c42..229a8431 100644
>>> --- a/poppler/Link.h
>>> +++ b/poppler/Link.h
>>> @@ -19,6 +19,7 @@
>>>
>>> // Copyright (C) 2012 Tobias Koening <tobias.koenig at kdab.com>
>>> // Copyright (C) 2018 Albert Astals Cid <aacid at kde.org>
>>> // Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company,
>>> <info at kdab.com>. Work sponsored by the LiMux project of the city of
>>> Munich>
>>> +// Copyright (C) 2018 Intevation GmbH <intevation at intevation.de>
>>>
>>> //
>>> // To see a description of the changes please see the Changelog file that
>>> // came with your tarball or type make ChangeLog if you are building from
>>> git>
>>> @@ -58,6 +59,7 @@ enum LinkActionKind {
>>>
>>> actionSound, // sound action
>>> actionJavaScript, // JavaScript action
>>> actionOCGState, // Set-OCG-State action
>>>
>>> + actionHide, // Hide action
>>>
>>> actionUnknown // anything else
>>>
>>> };
>>>
>>> @@ -452,6 +454,39 @@ private:
>>> };
>>>
>>> //-----------------------------------------------------------------------
>>> -
>>>
>>> +// LinkHide
>>> +//-----------------------------------------------------------------------
>>> -
>>> +
>>> +class LinkHide: public LinkAction {
>>> +public:
>>> + LinkHide(const Object *hideObj);
>>> +
>>> + ~LinkHide();
>>> +
>>> + GBool isOk() const override { return targetName != nullptr; }
>>> + LinkActionKind getKind() const override { return actionHide; }
>>> +
>>> + // According to spec the target can be either:
>>> + // a) A text string containing the fully qualified name of the target
>>> + // field.
>>> + // b) An indirect reference to an annotation dictionary.
>>> + // c) An array of "such dictionaries or text strings".
>>> + //
>>> + // While b / c appear to be very uncommon and can't easily be
>>> + // created with Adobe Acrobat DC. So only support hide
>>> + // actions with named targets (yet).
>>> + GBool hasTargetName() const { return targetName != nullptr; }
>>> + const GooString *getTargetName() const { return targetName; }
>>> +
>>> + // Should this action show or hide.
>>> + GBool isShowAction() const { return show; }
>>> +
>>> +private:
>>> + GooString *targetName;
>>> + GBool show;
>>> +};
>>> +
>>> +//-----------------------------------------------------------------------
>>> -
>>>
>>> // LinkUnknown
>>> //-----------------------------------------------------------------------
>>> -
>>>
>>> diff --git a/qt5/src/poppler-annotation.cc b/qt5/src/poppler-annotation.cc
>>> index 6a2ec893..2394ffc5 100644
>>> --- a/qt5/src/poppler-annotation.cc
>>> +++ b/qt5/src/poppler-annotation.cc
>>> @@ -6,6 +6,7 @@
>>>
>>> * Copyright (C) 2012, 2015, Tobias Koenig <tobias.koenig at kdab.com>
>>> * Copyright (C) 2018 Adam Reichold <adam.reichold at t-online.de>
>>> * Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company,
>>> <info at kdab.com>. Work sponsored by the LiMux project of the city of
>>> Munich>
>>> + * Copyright (C) 2018 Intevation GmbH <intevation at intevation.de>
>>>
>>> * Adapting code from
>>> * Copyright (C) 2004 by Enrico Ros <eros.kde at email.it>
>>> *
>>>
>>> @@ -3946,6 +3947,11 @@ void LinkAnnotation::store( QDomNode & node,
>>> QDomDocument & document ) const>
>>> hyperlinkElement.setAttribute( QStringLiteral("type"),
>>> QStringLiteral("OCGState") ); break;
>>>
>>> }
>>>
>>> + case Poppler::Link::Hide:
>>> + {
>>> + hyperlinkElement.setAttribute( QStringLiteral("type"),
>>> QStringLiteral("Hide") ); + break;
>>> + }
>>>
>>> case Poppler::Link::None:
>>> break;
>>>
>>> }
>>>
>>> diff --git a/qt5/src/poppler-link-private.h
>>> b/qt5/src/poppler-link-private.h index 6bc5cb9f..e54c8f86 100644
>>> --- a/qt5/src/poppler-link-private.h
>>> +++ b/qt5/src/poppler-link-private.h
>>> @@ -1,5 +1,6 @@
>>>
>>> /* poppler-link-private.h: qt interface to poppler
>>>
>>> * Copyright (C) 2016, 2018, Albert Astals Cid <aacid at kde.org>
>>>
>>> + * Copyright (C) 2018 Intevation GmbH <intevation at intevation.de>
>>>
>>> *
>>> * This program is free software; you can redistribute it and/or modify
>>> * it under the terms of the GNU General Public License as published by
>>>
>>> @@ -55,6 +56,22 @@ public:
>>> ::LinkOCGState *popplerLinkOCGState;
>>>
>>> };
>>>
>>> +
>>> +
>>> +class LinkHidePrivate : public LinkPrivate
>>> +{
>>> +public:
>>> + LinkHidePrivate( const QRectF &area, const QString &tName, bool show
>>> )
>>> + : LinkPrivate( area )
>>> + , targetName( tName )
>>> + , isShow( show )
>>> + {
>>> + }
>>> +
>>> + QString targetName;
>>> + bool isShow;
>>> +};
>>> +
>>>
>>> }
>>>
>>> #endif
>>>
>>> diff --git a/qt5/src/poppler-link.cc b/qt5/src/poppler-link.cc
>>> index ffa3e74d..1279e0b2 100644
>>> --- a/qt5/src/poppler-link.cc
>>> +++ b/qt5/src/poppler-link.cc
>>> @@ -4,6 +4,7 @@
>>>
>>> * Copyright (C) 2010 Hib Eris <hib at hiberis.nl>
>>> * Copyright (C) 2012, Tobias Koenig <tokoe at kdab.com>
>>> * Copyright (C) 2012, Guillermo A. Amaral B. <gamaral at kde.org>
>>>
>>> + * Copyright (C) 2018 Intevation GmbH <intevation at intevation.de>
>>>
>>> * Adapting code from
>>> * Copyright (C) 2004 by Enrico Ros <eros.kde at email.it>
>>> *
>>>
>>> @@ -704,4 +705,31 @@ class LinkMoviePrivate : public LinkPrivate
>>>
>>> {
>>>
>>> return OCGState;
>>>
>>> }
>>>
>>> +
>>> + // LinkHide
>>> + LinkHide::LinkHide( LinkHidePrivate *lhidep )
>>> + : Link( *lhidep )
>>> + {
>>> + }
>>> +
>>> + LinkHide::~LinkHide()
>>> + {
>>> + }
>>> +
>>> + Link::LinkType LinkHide::linkType() const
>>> + {
>>> + return Hide;
>>> + }
>>> +
>>> + QVector < QString > LinkHide::targets() const
>>> + {
>>> + Q_D( const LinkHide );
>>> + return QVector< QString >() << d->targetName;
>>> + }
>>> +
>>> + bool LinkHide::isShowAction() const
>>> + {
>>> + Q_D( const LinkHide );
>>> + return d->isShow;
>>> + }
>>>
>>> }
>>>
>>> diff --git a/qt5/src/poppler-link.h b/qt5/src/poppler-link.h
>>> index 0753ce99..5a59b6f3 100644
>>> --- a/qt5/src/poppler-link.h
>>> +++ b/qt5/src/poppler-link.h
>>> @@ -4,6 +4,7 @@
>>>
>>> * Copyright (C) 2010, 2012, Guillermo Amaral <gamaral at kdab.com>
>>> * Copyright (C) 2012, Tobias Koenig <tokoe at kdab.com>
>>> * Copyright (C) 2013, Anthony Granger <grangeranthony at gmail.com>
>>>
>>> + * Copyright (C) 2018 Intevation GmbH <intevation at intevation.de>
>>>
>>> * Adapting code from
>>> * Copyright (C) 2004 by Enrico Ros <eros.kde at email.it>
>>> *
>>>
>>> @@ -49,6 +50,7 @@ class LinkDestinationData;
>>>
>>> class LinkDestinationPrivate;
>>> class LinkRenditionPrivate;
>>> class LinkOCGStatePrivate;
>>>
>>> +class LinkHidePrivate;
>>>
>>> class MediaRendition;
>>> class SoundObject;
>>>
>>> @@ -197,7 +199,8 @@ class POPPLER_QT5_EXPORT Link
>>>
>>> Movie, ///< An action to be executed on a movie
>>> Rendition, ///< A rendition link \since 0.20
>>> JavaScript, ///< A JavaScript code to be interpreted \since
> 0.10
>>>
>>> - OCGState ///< An Optional Content Group state change
> \since
>>> 0.50 + OCGState, ///< An Optional Content Group state
> change
>>> \since 0.50 + Hide, ///< An action to hide a field \since 0.64
>>>
>>> };
>>>
>>> /**
>>>
>>> @@ -627,6 +630,40 @@ class POPPLER_QT5_EXPORT LinkOCGState : public Link
>>>
>>> Q_DISABLE_COPY( LinkOCGState )
>>>
>>> };
>>>
>>> +/**
>>> + * Hide: an action to show / hide a field.
>>> + *
>>> + * \since 0.64
>>> + */
>>> +class POPPLER_QT5_EXPORT LinkHide: public Link
>>> +{
>>> + public:
>>> + /**
>>> + * Create a new Hide link. This is only used by Poppler::Page.
>>> + */
>>> + LinkHide( LinkHidePrivate *lhidep );
>>> + /**
>>> + * Destructor.
>>> + */
>>> + ~LinkHide();
>>> +
>>> + LinkType linkType() const override;
>>> +
>>> + /**
>>> + * The fully qualified target names of the action.
>>> + */
>>> + QVector< QString > targets() const;
>>> +
>>> + /**
>>> + * Should this action change the visibility of the target to
> true.
>>> + */
>>> + bool isShowAction() const;
>>> +
>>> + private:
>>> + Q_DECLARE_PRIVATE( LinkHide )
>>> + Q_DISABLE_COPY( LinkHide )
>>> +};
>>> +
>>>
>>> }
>>>
>>> #endif
>>>
>>> diff --git a/qt5/src/poppler-page.cc b/qt5/src/poppler-page.cc
>>> index 48dbe8ff..3ed98846 100644
>>> --- a/qt5/src/poppler-page.cc
>>> +++ b/qt5/src/poppler-page.cc
>>> @@ -20,6 +20,7 @@
>>>
>>> * Copyright (C) 2017, 2018, Oliver Sander <oliver.sander at tu-dresden.de>
>>> * Copyright (C) 2017 Adrian Johnson <ajohnson at redneon.com>
>>> * Copyright (C) 2017, 2018 Klarälvdalens Datakonsult AB, a KDAB Group
>>> company, <info at kdab.com>. Work sponsored by the LiMux project of the
>>> city of Munich>
>>> + * Copyright (C) 2018 Intevation GmbH <intevation at intevation.de>
>>>
>>> *
>>> * This program is free software; you can redistribute it and/or modify
>>> * it under the terms of the GNU General Public License as published by
>>>
>>> @@ -342,6 +343,16 @@ Link* PageData::convertLinkActionToLink(::LinkAction
>>> * a, DocumentData *parentDo>
>>> LinkOCGStatePrivate *locgp = new LinkOCGStatePrivate( linkArea,
>>> plocg );
>>> popplerLink = new LinkOCGState( locgp );
>>>
>>> }
>>>
>>> + break;
>>> +
>>> + case actionHide:
>>> + {
>>> + ::LinkHide *lh = (::LinkHide *)a;
>>> +
>>> + LinkHidePrivate *lhp = new LinkHidePrivate( linkArea,
>>> lh->hasTargetName() ? UnicodeParsedString( lh->getTargetName() ) :
>>> QString(), lh->isShowAction() ); + popplerLink = new LinkHide( lhp
>>> );
>>> + }
>>> + break;
>>>
>>> case actionUnknown:
>>> break;
>>>
>>> commit 022ccd4e1c61f4e89c7ffad83d9a5a896f65dc40
>>> Author: Albert Astals Cid <aacid at kde.org>
>>> Date: Mon Apr 16 16:22:55 2018 +0200
>>>
>>> GfxGouraudTriangleShading::parse: Fix memory leak on malformed files
>>>
>>> Bug #106059
>>>
>>> diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc
>>> index 3d564138..95699355 100644
>>> --- a/poppler/GfxState.cc
>>> +++ b/poppler/GfxState.cc
>>> @@ -4922,6 +4922,9 @@ GfxGouraudTriangleShading
>>> *GfxGouraudTriangleShading::parse(GfxResources *res, i>
>>> trianglesA = (int (*)[3])gmallocn_checkoverflow(nTrianglesA * 3,
>>> sizeof(int)); if (unlikely(!trianglesA)) {
>>>
>>> gfree(verticesA);
>>>
>>> + for (i = 0; i < nFuncsA; ++i) {
>>> + delete funcsA[i];
>>> + }
>>>
>>> return nullptr;
>>>
>>> }
>>> k = 0;
>>>
>>> _______________________________________________
>>> poppler mailing list
>>> poppler at lists.freedesktop.org
>>> https://lists.freedesktop.org/mailman/listinfo/poppler
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: OpenPGP digital signature
URL: <https://lists.freedesktop.org/archives/poppler/attachments/20180416/d041169a/attachment-0001.sig>
More information about the poppler
mailing list