[poppler] [Patch] Parse Additional Actions for Widget Annots.

Carlos Garcia Campos carlosgc at gnome.org
Tue Mar 29 10:31:06 PDT 2011


Excerpts from jose.aliste at gmail.com's message of mar mar 29 10:35:08 +0200 2011:
> Hi,
> 
> Here is a patch to parse the additional actions dict that is present
> in Widget Annots. This is one of the first patches we will need to get
> javascript support as many of the javascript in the pdfs are encoded
> in JavascriptActions that are associated to the AditionalActions
> dictionary. All comments welcome, specially about the way I am saving
> the AditionalActions as an Array of Pointers to LinkActions.
> 
> 
> Greetings,
> 
> 
> José

> From deb6fa54b20858d1aff74f87262b6ddc7b303335 Mon Sep 17 00:00:00 2001
> From: =?UTF-8?q?Jos=C3=A9=20Aliste?= <jaliste at src.gnome.org>
> Date: Tue, 29 Mar 2011 04:27:15 -0400
> Subject: [PATCH] Parse additionActions dictionary for Widget annots.

> ---
>  poppler/Annot.cc |   45 ++++++++++++++++++++++++++++++++++++++++++++-
>  poppler/Annot.h  |   19 +++++++++++++++++--
>  2 files changed, 61 insertions(+), 3 deletions(-)

Additional actions are not specific to Widget annotations, Screen
annotation also have an AA entry, only Fo and Bl (focus-in, focus-out)
events are specific to widget annots. 

> diff --git a/poppler/Annot.cc b/poppler/Annot.cc
> index 1f77c71..2996be9 100644
> --- a/poppler/Annot.cc
> +++ b/poppler/Annot.cc
> @@ -2759,7 +2759,50 @@ void AnnotWidget::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
>    obj1.free();
 
>    if(dict->lookup("AA", &obj1)->isDict()) {
> -    additionActions = NULL;
> +    Dict *addActionDict = obj1.getDict();
> +    Object obj2;
> +    additionActions = (LinkAction **) gmallocn ((NumberOfEvents), sizeof(LinkAction *));

We know the array size at compile time so we can use a stack allocated
array instead. 

> +    for (int i = 0; i < NumberOfEvents; i++) {
> +      additionActions[i] = NULL;
> +    }

Use memset instead.

> +    for (int i = 0; i < addActionDict->getLength(); i++) {
> +      GooString key(addActionDict->getKey(i));
> +      int triggerEvent = -1;
> +
> +      if (key.cmp("E")) {
> +        triggerEvent = eventCursorEnter;
> +      } else if (key.cmp("X")) {
> +        triggerEvent = eventCursorExit;
> +      } else if (key.cmp("D")) {
> +        triggerEvent = eventMouseDown;
> +      } else if (key.cmp("U")) {
> +        triggerEvent = eventMouseUp;
> +      } else if (key.cmp("Fo")) {
> +        triggerEvent = eventFocusIn;
> +      } else if (key.cmp("Bl")) {
> +        triggerEvent = eventFocusOut;
> +      } else if (key.cmp("PO")) {
> +        triggerEvent = eventPageOpen;
> +      } else if (key.cmp("PC")) {
> +        triggerEvent = eventPageClose;
> +      } else if (key.cmp("PV")) {
> +        triggerEvent = eventPageVisible;
> +      } else if (key.cmp("PI")) {
> +        triggerEvent = eventPageInvisible;
> +      }

We don't usually do this in poppler, instead of iterate the whole
dictionary comparing every entry we check the entries we are
interested in.

if (additionalActions.dictLookup("E", &obj1)->isDict())
  additionActions[eventCursorEnter] = LinkAction::parseAction (&obj1, catalog->getBaseURI());
obj1.free();

if (additionalActions.dictLookup("X", &obj1)->isDict())
  additionActions[eventCursorExit] = LinkAction::parseAction (&obj1, catalog->getBaseURI());
obj1.free();

......


something like that. 
  
> +      if (triggerEvent > 0) {
> +        Object obj3;
> +
> +        addActionDict->getVal(i,&obj3);
> +	additionActions[triggerEvent] = LinkAction::parseAction (&obj3,  catalog->getBaseURI());
> +	obj3.free();
> +      }
> +
> +    }
> +
>    } else {
>      additionActions = NULL;
>    }

The actions should be freed (deleted) in the destructor.

> diff --git a/poppler/Annot.h b/poppler/Annot.h
> index 93f82bf..4f522d7 100644
> --- a/poppler/Annot.h
> +++ b/poppler/Annot.h
> @@ -453,6 +453,21 @@ public:
>      type3D              // 3D             25
>    };
 
> +  enum AnnotTriggerEvent {
> +    eventCursorEnter,	// E
> +    eventCursorExit,	// X
> +    eventMouseDown,	// D
> +    eventMouseUp,	// U
> +    eventFocusIn,	// Fo
> +    eventFocusOut,	// Bl
> +    eventPageOpen,	// PO
> +    eventPageClose,	// PC
> +    eventPageVisible,	// PV
> +    eventPageInvisible,	// PI
> +    NumberOfEvents
> +  };
> +
> +
>    Annot(XRef *xrefA, PDFRectangle *rectA, Catalog *catalog);
>    Annot(XRef *xrefA, Dict *dict, Catalog *catalog);
>    Annot(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj);
> @@ -1147,7 +1162,7 @@ public:
>    AnnotWidgetHighlightMode getMode() { return mode; }
>    AnnotAppearanceCharacs *getAppearCharacs() { return appearCharacs; }
>    LinkAction *getAction() { return action; }
> -  Dict *getAdditionActions() { return additionActions; }
> +  LinkAction **getAdditionActions() { return additionActions; }

A method that returns the action for a given event might be useful
too.

LinkAction* getAdditionalAction(AnnotTriggerEvent event);

>    Dict *getParent() { return parent; }
 
>  private:
> @@ -1170,7 +1185,7 @@ private:
>    AnnotWidgetHighlightMode mode;          // H  (Default I)
>    AnnotAppearanceCharacs *appearCharacs;  // MK
>    LinkAction *action;                     // A
> -  Dict *additionActions;                  // AA
> +  LinkAction **additionActions;           // AA
>    // inherited  from Annot
>    // AnnotBorderBS border;                // BS
>    Dict *parent;                           // Parent
> -- 
> 1.7.3.5

Regards, 
-- 
Carlos Garcia Campos
PGP key: http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x523E6462
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/poppler/attachments/20110329/a9e171d3/attachment.pgp>


More information about the poppler mailing list