[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 17:05:25 UTC 2018


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.

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.)

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: parse-action-set-by-value.diff
Type: text/x-patch
Size: 2846 bytes
Desc: not available
URL: <https://lists.freedesktop.org/archives/poppler/attachments/20180416/832ed77c/attachment-0001.bin>
-------------- 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/832ed77c/attachment-0001.sig>


More information about the poppler mailing list