From ce3d3a6ff8e4cb7db302deffdac54951655afc8f Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Thu, 15 Oct 2020 19:42:36 +0200 Subject: [PATCH] Get urls if any in AA::D dictionary for pushbuttons --- src/core/annotation.js | 8 +++-- src/core/obj.js | 21 ++++++++++--- test/unit/annotation_spec.js | 57 ++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+), 6 deletions(-) diff --git a/src/core/annotation.js b/src/core/annotation.js index d8c29011e..2fddb1836 100644 --- a/src/core/annotation.js +++ b/src/core/annotation.js @@ -1905,12 +1905,16 @@ class ButtonWidgetAnnotation extends WidgetAnnotation { } _processPushButton(params) { - if (!params.dict.has("A") && !this.data.alternativeText) { + if ( + !params.dict.has("A") && + !params.dict.has("AA") && + !this.data.alternativeText + ) { warn("Push buttons without action dictionaries are not supported"); return; } - this.data.isTooltipOnly = !params.dict.has("A"); + this.data.isTooltipOnly = !params.dict.has("A") && !params.dict.has("AA"); Catalog.parseDestDictionary({ destDict: params.dict, diff --git a/src/core/obj.js b/src/core/obj.js index ae281f571..8a4aec574 100644 --- a/src/core/obj.js +++ b/src/core/obj.js @@ -1165,10 +1165,23 @@ class Catalog { let action = destDict.get("A"), url, dest; - if (!isDict(action) && destDict.has("Dest")) { - // A /Dest entry should *only* contain a Name or an Array, but some bad - // PDF generators ignore that and treat it as an /A entry. - action = destDict.get("Dest"); + if (!isDict(action)) { + if (destDict.has("Dest")) { + // A /Dest entry should *only* contain a Name or an Array, but some bad + // PDF generators ignore that and treat it as an /A entry. + action = destDict.get("Dest"); + } else { + action = destDict.get("AA"); + if (isDict(action)) { + if (action.has("D")) { + // MouseDown + action = action.get("D"); + } else if (action.has("U")) { + // MouseUp + action = action.get("U"); + } + } + } } if (isDict(action)) { diff --git a/test/unit/annotation_spec.js b/test/unit/annotation_spec.js index c390a7aea..020cae788 100644 --- a/test/unit/annotation_spec.js +++ b/test/unit/annotation_spec.js @@ -2658,6 +2658,63 @@ describe("annotation", function () { done(); }, done.fail); }); + + it("should handle URL in A dict in push buttons", function (done) { + const buttonWidgetRef = Ref.get(124, 0); + buttonWidgetDict.set("Ff", AnnotationFieldFlag.PUSHBUTTON); + + const actionDict = new Dict(); + actionDict.set("S", Name.get("JavaScript")); + actionDict.set( + "JS", + "app.launchURL('https://developer.mozilla.org/en-US/', true)" + ); + buttonWidgetDict.set("A", actionDict); + + const xref = new XRefMock([ + { ref: buttonWidgetRef, data: buttonWidgetDict }, + ]); + + AnnotationFactory.create( + xref, + buttonWidgetRef, + pdfManagerMock, + idFactoryMock + ).then(({ data }) => { + expect(data.url).toEqual("https://developer.mozilla.org/en-US/"); + done(); + }, done.fail); + }); + + it("should handle URL in AA dict in push buttons", function (done) { + const buttonWidgetRef = Ref.get(124, 0); + buttonWidgetDict.set("Ff", AnnotationFieldFlag.PUSHBUTTON); + + // D stands for MouseDown + const dDict = new Dict(); + dDict.set("S", Name.get("JavaScript")); + dDict.set( + "JS", + "app.launchURL('https://developer.mozilla.org/en-US/', true)" + ); + const actionDict = new Dict(); + actionDict.set("D", dDict); + buttonWidgetDict.set("AA", actionDict); + + const xref = new XRefMock([ + { ref: buttonWidgetRef, data: buttonWidgetDict }, + ]); + + AnnotationFactory.create( + xref, + buttonWidgetRef, + pdfManagerMock, + idFactoryMock + ).then(({ data }) => { + expect(data.url).toEqual("https://developer.mozilla.org/en-US/"); + done(); + }, done.fail); + }); }); describe("ChoiceWidgetAnnotation", function () {