diff --git a/src/core/annotation.js b/src/core/annotation.js index 120afef3b87eb..8735dd4200611 100644 --- a/src/core/annotation.js +++ b/src/core/annotation.js @@ -15,7 +15,8 @@ /* globals PDFJS, Util, isDict, isName, stringToPDFString, warn, Dict, Stream, stringToBytes, Promise, isArray, ObjectLoader, OperatorList, isValidUrl, OPS, createPromiseCapability, AnnotationType, - stringToUTF8String, AnnotationBorderStyleType, ColorSpace */ + stringToUTF8String, AnnotationBorderStyleType, ColorSpace, + AnnotationFlag, isInt */ 'use strict'; @@ -121,7 +122,8 @@ var Annotation = (function AnnotationClosure() { var data = this.data = {}; data.subtype = dict.get('Subtype').name; - data.annotationFlags = dict.get('F'); + + this.setFlags(dict.get('F')); this.setRectangle(dict.get('Rect')); data.rect = this.rectangle; @@ -138,6 +140,64 @@ var Annotation = (function AnnotationClosure() { } Annotation.prototype = { + /** + * @return {boolean} + */ + get viewable() { + if (this.flags) { + return !this.hasFlag(AnnotationFlag.INVISIBLE) && + !this.hasFlag(AnnotationFlag.HIDDEN) && + !this.hasFlag(AnnotationFlag.NOVIEW); + } + return true; + }, + + /** + * @return {boolean} + */ + get printable() { + if (this.flags) { + return this.hasFlag(AnnotationFlag.PRINT) && + !this.hasFlag(AnnotationFlag.INVISIBLE) && + !this.hasFlag(AnnotationFlag.HIDDEN); + } + return false; + }, + + /** + * Set the flags. + * + * @public + * @memberof Annotation + * @param {number} flags - Unsigned 32-bit integer specifying annotation + * characteristics + * @see {@link shared/util.js} + */ + setFlags: function Annotation_setFlags(flags) { + if (isInt(flags)) { + this.flags = flags; + } else { + this.flags = 0; + } + }, + + /** + * Check if a provided flag is set. + * + * @public + * @memberof Annotation + * @param {number} flag - Hexadecimal representation for an annotation + * characteristic + * @return {boolean} + * @see {@link shared/util.js} + */ + hasFlag: function Annotation_hasFlag(flag) { + if (this.flags) { + return (this.flags & flag) > 0; + } + return false; + }, + /** * Set the rectangle. * @@ -237,32 +297,6 @@ var Annotation = (function AnnotationClosure() { } }, - isInvisible: function Annotation_isInvisible() { - var data = this.data; - return !!(data && - data.annotationFlags && // Default: not invisible - data.annotationFlags & 0x1); // Invisible - }, - - isViewable: function Annotation_isViewable() { - var data = this.data; - return !!(!this.isInvisible() && - data && - (!data.annotationFlags || - !(data.annotationFlags & 0x22)) && // Hidden or NoView - data.rect); // rectangle is necessary - }, - - isPrintable: function Annotation_isPrintable() { - var data = this.data; - return !!(!this.isInvisible() && - data && - data.annotationFlags && // Default: not printable - data.annotationFlags & 0x4 && // Print - !(data.annotationFlags & 0x2) && // Hidden - data.rect); // rectangle is necessary - }, - loadResources: function Annotation_loadResources(keys) { return new Promise(function (resolve, reject) { this.appearance.dict.getAsync('Resources').then(function (resources) { @@ -329,8 +363,8 @@ var Annotation = (function AnnotationClosure() { var annotationPromises = []; for (var i = 0, n = annotations.length; i < n; ++i) { - if (intent === 'display' && annotations[i].isViewable() || - intent === 'print' && annotations[i].isPrintable()) { + if (intent === 'display' && annotations[i].viewable || + intent === 'print' && annotations[i].printable) { annotationPromises.push( annotations[i].getOperatorList(partialEvaluator, task)); } @@ -506,6 +540,12 @@ var WidgetAnnotation = (function WidgetAnnotationClosure() { data.fieldFlags = Util.getInheritableProperty(dict, 'Ff') || 0; this.fieldResources = Util.getInheritableProperty(dict, 'DR') || Dict.empty; + // Hide unsupported Widget signatures. + if (data.fieldType === 'Sig') { + warn('unimplemented annotation type: Widget signature'); + this.setFlags(AnnotationFlag.HIDDEN); + } + // Building the full field name by collecting the field and // its ancestors 'T' data and joining them using '.'. var fieldName = []; @@ -539,17 +579,7 @@ var WidgetAnnotation = (function WidgetAnnotationClosure() { data.fullName = fieldName.join('.'); } - var parent = Annotation.prototype; - Util.inherit(WidgetAnnotation, Annotation, { - isViewable: function WidgetAnnotation_isViewable() { - if (this.data.fieldType === 'Sig') { - warn('unimplemented annotation type: Widget signature'); - return false; - } - - return parent.isViewable.call(this); - } - }); + Util.inherit(WidgetAnnotation, Annotation, {}); return WidgetAnnotation; })(); diff --git a/src/core/core.js b/src/core/core.js index 9ff10cd56e80f..502081d0103c3 100644 --- a/src/core/core.js +++ b/src/core/core.js @@ -268,8 +268,7 @@ var Page = (function PageClosure() { for (var i = 0, n = annotationRefs.length; i < n; ++i) { var annotationRef = annotationRefs[i]; var annotation = annotationFactory.create(this.xref, annotationRef); - if (annotation && - (annotation.isViewable() || annotation.isPrintable())) { + if (annotation && (annotation.viewable || annotation.printable)) { annotations.push(annotation); } } diff --git a/src/shared/util.js b/src/shared/util.js index a99b05df909f3..6845a5fd44cc5 100644 --- a/src/shared/util.js +++ b/src/shared/util.js @@ -48,6 +48,19 @@ var AnnotationType = { LINK: 3 }; +var AnnotationFlag = { + INVISIBLE: 0x01, + HIDDEN: 0x02, + PRINT: 0x04, + NOZOOM: 0x08, + NOROTATE: 0x10, + NOVIEW: 0x20, + READONLY: 0x40, + LOCKED: 0x80, + TOGGLENOVIEW: 0x100, + LOCKEDCONTENTS: 0x200 +}; + var AnnotationBorderStyleType = { SOLID: 1, DASHED: 2, diff --git a/test/unit/annotation_layer_spec.js b/test/unit/annotation_layer_spec.js index 99d2f5adc51b0..d97861abaa86f 100644 --- a/test/unit/annotation_layer_spec.js +++ b/test/unit/annotation_layer_spec.js @@ -1,10 +1,31 @@ /* globals expect, it, describe, Dict, Name, Annotation, AnnotationBorderStyle, - AnnotationBorderStyleType */ + AnnotationBorderStyleType, AnnotationFlag */ 'use strict'; describe('Annotation layer', function() { describe('Annotation', function() { + it('should set and get flags', function() { + var dict = new Dict(); + dict.set('Subtype', ''); + var annotation = new Annotation({ dict: dict, ref: 0 }); + annotation.setFlags(13); + + expect(annotation.hasFlag(AnnotationFlag.INVISIBLE)).toEqual(true); + expect(annotation.hasFlag(AnnotationFlag.NOZOOM)).toEqual(true); + expect(annotation.hasFlag(AnnotationFlag.PRINT)).toEqual(true); + expect(annotation.hasFlag(AnnotationFlag.READONLY)).toEqual(false); + }); + + it('should be viewable and not printable by default', function() { + var dict = new Dict(); + dict.set('Subtype', ''); + var annotation = new Annotation({ dict: dict, ref: 0 }); + + expect(annotation.viewable).toEqual(true); + expect(annotation.printable).toEqual(false); + }); + it('should set and get a valid rectangle', function() { var dict = new Dict(); dict.set('Subtype', '');