Let non-viewable Popup Annotations inherit the parent's Annotation Flags if the parent is viewable
Fixes http://www.pdf-archive.com/2013/09/30/file2/file2.pdf. Note how it's not possible to show the various Popup Annotations in the above document. To fix that, this patch lets the Popup inherit the flags of the parent, in the special case where the parent is `viewable` *and* the Popup is not. In general, I don't think that a Popup must have the same flags set as the parent. However, it seems very strange to have a `viewable` parent annotation, and then not being able to view the Popup. Annoyingly the PDF specification doesn't, as far as I can find, mention anything about how this case should be handled, but this patch seem consistent with the actual behaviour in Adobe Reader.
This commit is contained in:
parent
47b929be26
commit
98fe094d18
@ -190,28 +190,49 @@ var Annotation = (function AnnotationClosure() {
|
||||
}
|
||||
|
||||
Annotation.prototype = {
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_hasFlag: function Annotation_hasFlag(flags, flag) {
|
||||
return !!(flags & flag);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_isViewable: function Annotation_isViewable(flags) {
|
||||
return !this._hasFlag(flags, AnnotationFlag.INVISIBLE) &&
|
||||
!this._hasFlag(flags, AnnotationFlag.HIDDEN) &&
|
||||
!this._hasFlag(flags, AnnotationFlag.NOVIEW);
|
||||
},
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
_isPrintable: function AnnotationFlag_isPrintable(flags) {
|
||||
return this._hasFlag(flags, AnnotationFlag.PRINT) &&
|
||||
!this._hasFlag(flags, AnnotationFlag.INVISIBLE) &&
|
||||
!this._hasFlag(flags, AnnotationFlag.HIDDEN);
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {boolean}
|
||||
*/
|
||||
get viewable() {
|
||||
if (this.flags) {
|
||||
return !this.hasFlag(AnnotationFlag.INVISIBLE) &&
|
||||
!this.hasFlag(AnnotationFlag.HIDDEN) &&
|
||||
!this.hasFlag(AnnotationFlag.NOVIEW);
|
||||
}
|
||||
if (this.flags === 0) {
|
||||
return true;
|
||||
}
|
||||
return this._isViewable(this.flags);
|
||||
},
|
||||
|
||||
/**
|
||||
* @return {boolean}
|
||||
*/
|
||||
get printable() {
|
||||
if (this.flags) {
|
||||
return this.hasFlag(AnnotationFlag.PRINT) &&
|
||||
!this.hasFlag(AnnotationFlag.INVISIBLE) &&
|
||||
!this.hasFlag(AnnotationFlag.HIDDEN);
|
||||
}
|
||||
if (this.flags === 0) {
|
||||
return false;
|
||||
}
|
||||
return this._isPrintable(this.flags);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -224,11 +245,7 @@ var Annotation = (function AnnotationClosure() {
|
||||
* @see {@link shared/util.js}
|
||||
*/
|
||||
setFlags: function Annotation_setFlags(flags) {
|
||||
if (isInt(flags)) {
|
||||
this.flags = flags;
|
||||
} else {
|
||||
this.flags = 0;
|
||||
}
|
||||
this.flags = (isInt(flags) && flags > 0) ? flags : 0;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -242,10 +259,7 @@ var Annotation = (function AnnotationClosure() {
|
||||
* @see {@link shared/util.js}
|
||||
*/
|
||||
hasFlag: function Annotation_hasFlag(flag) {
|
||||
if (this.flags) {
|
||||
return (this.flags & flag) > 0;
|
||||
}
|
||||
return false;
|
||||
return this._hasFlag(this.flags, flag);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -823,6 +837,16 @@ var PopupAnnotation = (function PopupAnnotationClosure() {
|
||||
this.setColor(parentItem.getArray('C'));
|
||||
this.data.color = this.color;
|
||||
}
|
||||
|
||||
// If the Popup annotation is not viewable, but the parent annotation is,
|
||||
// that is most likely a bug. Fallback to inherit the flags from the parent
|
||||
// annotation (this is consistent with the behaviour in Adobe Reader).
|
||||
if (!this.viewable) {
|
||||
var parentFlags = parentItem.get('F');
|
||||
if (this._isViewable(parentFlags)) {
|
||||
this.setFlags(parentFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Util.inherit(PopupAnnotation, Annotation, {});
|
||||
|
1
test/pdfs/.gitignore
vendored
1
test/pdfs/.gitignore
vendored
@ -99,6 +99,7 @@
|
||||
!pr4922.pdf
|
||||
!pr6531_1.pdf
|
||||
!pr6531_2.pdf
|
||||
!pr7352.pdf
|
||||
!bug900822.pdf
|
||||
!issue918.pdf
|
||||
!issue1905.pdf
|
||||
|
BIN
test/pdfs/pr7352.pdf
Normal file
BIN
test/pdfs/pr7352.pdf
Normal file
Binary file not shown.
@ -1838,6 +1838,14 @@
|
||||
"type": "eq",
|
||||
"annotations": true
|
||||
},
|
||||
{ "id": "pr7352",
|
||||
"file": "pdfs/pr7352.pdf",
|
||||
"md5": "336abca4b313cb215b0569883f1f683d",
|
||||
"link": false,
|
||||
"rounds": 1,
|
||||
"type": "eq",
|
||||
"annotations": true
|
||||
},
|
||||
{ "id": "issue1002",
|
||||
"file": "pdfs/issue1002.pdf",
|
||||
"md5": "af62d6cd95079322d4af18edd960d15c",
|
||||
|
@ -15,6 +15,17 @@ describe('Annotation layer', function() {
|
||||
}
|
||||
};
|
||||
|
||||
var annotationFactory;
|
||||
|
||||
beforeAll(function (done) {
|
||||
annotationFactory = new AnnotationFactory();
|
||||
done();
|
||||
});
|
||||
|
||||
afterAll(function () {
|
||||
annotationFactory = null;
|
||||
});
|
||||
|
||||
describe('Annotation', function() {
|
||||
it('should set and get flags', function() {
|
||||
var dict = new Dict();
|
||||
@ -185,17 +196,6 @@ describe('Annotation layer', function() {
|
||||
});
|
||||
|
||||
describe('LinkAnnotation', function() {
|
||||
var annotationFactory;
|
||||
|
||||
beforeAll(function (done) {
|
||||
annotationFactory = new AnnotationFactory();
|
||||
done();
|
||||
});
|
||||
|
||||
afterAll(function () {
|
||||
annotationFactory = null;
|
||||
});
|
||||
|
||||
it('should correctly parse a URI action', function() {
|
||||
var actionDict = new Dict();
|
||||
actionDict.set('Type', Name.get('Action'));
|
||||
@ -358,4 +358,32 @@ describe('Annotation layer', function() {
|
||||
expect(annotation.file.content).toEqual(stringToBytes('Test attachment'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('PopupAnnotation', function() {
|
||||
it('should inherit the parent flags when the Popup is not viewable, ' +
|
||||
'but the parent is (PR 7352)', function () {
|
||||
var parentDict = new Dict();
|
||||
parentDict.set('Type', Name.get('Annot'));
|
||||
parentDict.set('Subtype', Name.get('Text'));
|
||||
parentDict.set('F', 28); // viewable
|
||||
|
||||
var popupDict = new Dict();
|
||||
popupDict.set('Type', Name.get('Annot'));
|
||||
popupDict.set('Subtype', Name.get('Popup'));
|
||||
popupDict.set('F', 25); // not viewable
|
||||
popupDict.set('Parent', parentDict);
|
||||
|
||||
var xrefMock = new XrefMock([popupDict]);
|
||||
var popupRef = new Ref(13, 0);
|
||||
|
||||
var popupAnnotation = annotationFactory.create(xrefMock, popupRef);
|
||||
var data = popupAnnotation.data;
|
||||
expect(data.annotationType).toEqual(AnnotationType.POPUP);
|
||||
|
||||
// Should not modify the `annotationFlags` returned e.g. through the API.
|
||||
expect(data.annotationFlags).toEqual(25);
|
||||
// The Popup should inherit the `viewable` property of the parent.
|
||||
expect(popupAnnotation.viewable).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user