-
Notifications
You must be signed in to change notification settings - Fork 10.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Interactive forms: render choice widget annotations #7671
Interactive forms: render choice widget annotations #7671
Conversation
73ac9c0
to
bcfe533
Compare
/botio test |
From: Bot.io (Linux)ReceivedCommand cmd_test from @timvandermeij received. Current queue size: 0 Live output at: http://107.21.233.14:8877/c8e571ed4b2bc6a/output.txt |
From: Bot.io (Linux)FailedFull output at http://107.21.233.14:8877/c8e571ed4b2bc6a/output.txt Total script time: 29.28 mins
Image differences available at: http://107.21.233.14:8877/c8e571ed4b2bc6a/reftest-analyzer.html#web=eq.log |
The bots received an update to Firefox 51, which causes a lot of reference test changes. I do wonder, however, why the Windows bot did not do anything... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll try to do a proper review later in the week!
Taking a quick look at the PR I've noticed two things so far, please see the inline comment and the error below.
When opening annotation-choice-widget.pdf
locally against master
with forms disabled, I get the following error:
An error occurred while rendering the page.
PDF.js v1.5.488 (build: 6c263c1)
Message: str.charCodeAt is not a function
Stack: stringToPDFString@resource://pdf.js/build/pdf.worker.js:2035:42
WidgetAnnotation@resource://pdf.js/build/pdf.worker.js:40776:23
AnnotationFactory_create@resource://pdf.js/build/pdf.worker.js:40266:16
get annotations@resource://pdf.js/build/pdf.worker.js:41471:26
LocalPdfManager_ensure/<@resource://pdf.js/build/pdf.worker.js:41862:15
LocalPdfManager_ensure@resource://pdf.js/build/pdf.worker.js:41860:14
Page_getOperatorList@resource://pdf.js/build/pdf.worker.js:41389:32
wphSetupRenderPage/<@resource://pdf.js/build/pdf.worker.js:42660:9
Async*wphSetupRenderPage@resource://pdf.js/build/pdf.worker.js:42653:7
messageHandlerComObjOnMessage@resource://pdf.js/build/pdf.worker.js:2607:9
EventListener.handleEvent*MessageHandler@resource://pdf.js/build/pdf.worker.js:2613:3
wphCreateDocumentHandler@resource://pdf.js/build/pdf.worker.js:42301:19
wphSetupDoc@resource://pdf.js/build/pdf.worker.js:42288:14
messageHandlerComObjOnMessage/<@resource://pdf.js/build/pdf.worker.js:2584:18
Async*messageHandlerComObjOnMessage@resource://pdf.js/build/pdf.worker.js:2583:9
EventListener.handleEvent*MessageHandler@resource://pdf.js/build/pdf.worker.js:2613:3
initializeWorker@resource://pdf.js/build/pdf.worker.js:42812:17
pdfjsWrapper/<@resource://pdf.js/build/pdf.worker.js:42820:3
pdfjsWrapper/<@resource://pdf.js/build/pdf.worker.js:41975:5
pdfjsWrapper@resource://pdf.js/build/pdf.worker.js:41973:2
@resource://pdf.js/build/pdf.worker.js:40:13
@resource://pdf.js/build/pdf.worker.js:25:1
@resource://pdf.js/build/pdf.worker.js:18:2
// it to an array of arrays as well for convenience in the display layer. | ||
this.data.options = []; | ||
|
||
var options = params.dict.get('Opt'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To prevent strange, and hard to find, bugs later on you probably want to use getArray
here (or maybe var option = params.xref.fetchIfRef(options[i]);
below).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good find. I'll fix that when the comments from the full review are also present.
The error is in fact a bug in the current |
I've just tested this, it works beautifully. You can merge this before #7664 if you want, I can rebase and merge after that. |
@Snuffleupagus Do you have more review comments or can I start fixing this up with your current comments so we can land this? |
Really sorry for the delay here! However, I'll try to review this either tonight or tomorrow; again sorry for the delay here! |
No worries! I also read that thread and it bugged me a bit as well, so you're not alone there... Thanks, I'll fix up this PR when the review comments are added. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, sorry for the delay here! The PR itself looks good, however it exposes a couple of existing issues in the code; please see the inline comments.
r=me, with comments addressed and passing tests.
]); | ||
|
||
var choiceWidgetAnnotation = annotationFactory.create(xref, | ||
choiceWidgetRef); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here, and in the other tests, you may also want to explicitly check that you actually get the expected annotation type, e.g. like this:
expect(data.annotationType).toEqual(AnnotationType.WIDGET);
// Determine the field value. In this case, it may be a string or an | ||
// array of strings. For convenience in the display layer, convert the | ||
// string to an array of one string as well. | ||
if (!isArray(this.data.fieldValue)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to my other comment about references inside of arrays, if this.data.fieldValue
already is an array you will have problems in the display
layer if an array element is a Ref
.
Please refer to the comment on the data.fieldValue = Util.getInheritableProperty(dict, 'V');
line for a suggested solution.
@@ -619,8 +621,7 @@ var WidgetAnnotation = (function WidgetAnnotationClosure() { | |||
var data = this.data; | |||
|
|||
data.annotationType = AnnotationType.WIDGET; | |||
data.fieldValue = stringToPDFString( | |||
Util.getInheritableProperty(dict, 'V') || ''); | |||
data.fieldValue = Util.getInheritableProperty(dict, 'V'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the V
entry can be an array, you probably need to modify Util.getInheritableProperty
to handle that. I can see two possible solutions:
- Modify
Util.getInheritableProperty
to use always useDict_getArray
instead ofDict_get
. Even though it only looks like this utility function is used fromsrc/core/annotation.js
, I'm not sure that this is such a great solution! - Add a parameter to
Util.getInheritableProperty
that controls whetherDict_getArray
is used, e.g. something like this:
diff --git a/src/core/annotation.js b/src/core/annotation.js
index 13aa204..d7ef2ca 100644
--- a/src/core/annotation.js
+++ b/src/core/annotation.js
@@ -619,8 +619,8 @@ var WidgetAnnotation = (function WidgetAnnotationClosure() {
var data = this.data;
data.annotationType = AnnotationType.WIDGET;
- data.fieldValue = stringToPDFString(
- Util.getInheritableProperty(dict, 'V') || '');
+ data.fieldValue = Util.getInheritableProperty(dict, 'V',
+ /* getArray = */ true);
data.alternativeText = stringToPDFString(dict.get('TU') || '');
data.defaultAppearance = Util.getInheritableProperty(dict, 'DA') || '';
var fieldType = Util.getInheritableProperty(dict, 'FT');
diff --git a/src/shared/util.js b/src/shared/util.js
index 48876da..614e7a0 100644
--- a/src/shared/util.js
+++ b/src/shared/util.js
@@ -874,9 +874,10 @@ var Util = (function UtilClosure() {
};
Util.getInheritableProperty = function Util_getInheritableProperty(dict,
- name) {
+ name,
+ getArray) {
while (dict && !dict.has(name)) {
- dict = dict.get('Parent');
+ dict = getArray ? dict.getArray('Parent') : dict.get('Parent');
}
if (!dict) {
return null;
var ChoiceWidgetAnnotationElement = ( | ||
function ChoiceWidgetAnnotationElementClosure() { | ||
function ChoiceWidgetAnnotationElement(parameters) { | ||
WidgetAnnotationElement.call(this, parameters); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When we only supported TextWidgetAnnotation
s, I suppose it didn't matter too much that we set the isRenderable
parameter inside of WidgetAnnotationElement
, however now I don't think that's correct anymore!
Note: For TextWidgetAnnotation
there's a meaningful fallback in the case where no Appearance
stream existed, and was thus not rendered in the core
layer, but for the ChoiceWidgetAnnotationElement
we're not rendering anything in the display
layer by default.
I believe that we should thus modify the current code like below, which will help not only here but when implementing other widget's later.
diff --git a/src/display/annotation_layer.js b/src/display/annotation_layer.js
index 29ed79a..76a8b73 100644
--- a/src/display/annotation_layer.js
+++ b/src/display/annotation_layer.js
@@ -400,9 +400,7 @@ var TextAnnotationElement = (function TextAnnotationElementClosure() {
* @alias WidgetAnnotationElement
*/
var WidgetAnnotationElement = (function WidgetAnnotationElementClosure() {
- function WidgetAnnotationElement(parameters) {
- var isRenderable = parameters.renderInteractiveForms ||
- (!parameters.data.hasAppearance && !!parameters.data.fieldValue);
+ function WidgetAnnotationElement(parameters, isRenderable) {
AnnotationElement.call(this, parameters, isRenderable);
}
@@ -432,7 +430,9 @@ var TextWidgetAnnotationElement = (
var TEXT_ALIGNMENT = ['left', 'center', 'right'];
function TextWidgetAnnotationElement(parameters) {
- WidgetAnnotationElement.call(this, parameters);
+ var isRenderable = parameters.renderInteractiveForms ||
+ (!parameters.data.hasAppearance && !!parameters.data.fieldValue);
+ WidgetAnnotationElement.call(this, parameters, isRenderable);
}
Util.inherit(TextWidgetAnnotationElement, WidgetAnnotationElement, {
Then this line becomes
WidgetAnnotationElement.call(this, parameters, parameters.renderInteractiveForms);
and the if (this.renderInteractiveForms) {
condition is no longer necessary inside of render
.
render: function ChoiceWidgetAnnotationElement_render() { | ||
this.container.className = 'choiceWidgetAnnotation'; | ||
|
||
if (this.renderInteractiveForms) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This if
can be removed with the above comment addressed.
bcfe533
to
f85f324
Compare
/botio-linux preview |
From: Bot.io (Linux)ReceivedCommand cmd_preview from @timvandermeij received. Current queue size: 0 Live output at: http://107.21.233.14:8877/24712ec8981cf8d/output.txt |
From: Bot.io (Linux)SuccessFull output at http://107.21.233.14:8877/24712ec8981cf8d/output.txt Total script time: 1.03 mins Published |
/botio test |
From: Bot.io (Windows)ReceivedCommand cmd_test from @timvandermeij received. Current queue size: 0 Live output at: http://107.22.172.223:8877/0e9f062377017fa/output.txt |
From: Bot.io (Linux)ReceivedCommand cmd_test from @timvandermeij received. Current queue size: 0 Live output at: http://107.21.233.14:8877/d421c325da2e200/output.txt |
From: Bot.io (Windows)FailedFull output at http://107.22.172.223:8877/0e9f062377017fa/output.txt Total script time: 25.71 mins
Image differences available at: http://107.22.172.223:8877/0e9f062377017fa/reftest-analyzer.html#web=eq.log |
From: Bot.io (Linux)FailedFull output at http://107.21.233.14:8877/d421c325da2e200/output.txt Total script time: 28.55 mins
Image differences available at: http://107.21.233.14:8877/d421c325da2e200/reftest-analyzer.html#web=eq.log |
/botio makeref |
From: Bot.io (Windows)ReceivedCommand cmd_makeref from @Snuffleupagus received. Current queue size: 0 Live output at: http://107.22.172.223:8877/6f9600046d338d9/output.txt |
From: Bot.io (Linux)ReceivedCommand cmd_makeref from @Snuffleupagus received. Current queue size: 0 Live output at: http://107.21.233.14:8877/d32df0d1bc864db/output.txt |
From: Bot.io (Windows)FailedFull output at http://107.22.172.223:8877/6f9600046d338d9/output.txt Total script time: 4.50 mins
|
/botio-windows makeref |
From: Bot.io (Windows)ReceivedCommand cmd_makeref from @timvandermeij received. Current queue size: 0 Live output at: http://107.22.172.223:8877/46aa938fc0e92bf/output.txt |
From: Bot.io (Linux)FailedFull output at http://107.21.233.14:8877/d32df0d1bc864db/output.txt Total script time: 21.80 mins
|
/botio-linux makeref |
From: Bot.io (Linux)ReceivedCommand cmd_makeref from @timvandermeij received. Current queue size: 0 Live output at: http://107.21.233.14:8877/55945b682744213/output.txt |
From: Bot.io (Windows)SuccessFull output at http://107.22.172.223:8877/46aa938fc0e92bf/output.txt Total script time: 25.30 mins
|
From: Bot.io (Linux)SuccessFull output at http://107.21.233.14:8877/55945b682744213/output.txt Total script time: 28.36 mins
|
…choice-fields Interactive forms: render choice widget annotations
This patch is another part of #7613.
readOnly
property has been moved to theWidgetAnnotation
class as the specification says that all types of widget annotations may use this flag, and indeed we need it for choice widget annotations as well.fieldValue
property is now only fetched in theWidgetAnnotation
class and verification is done in the inheriting classes. This is required because for text widget annotations it's a string, whereas for choice widget annotations it may be an array as well.