Skip to content

Commit

Permalink
Refactor annotation flags code
Browse files Browse the repository at this point in the history
This patch makes it possible to set and get all possible flags that the PDF specification defines. Even though we do not support all possible annotation types and not all possible annotation flags yet, this general framework makes it easy to access all flags for each annotation such that annotation type implementations can use with this information.

We add constants for all possible annotation flags such that we do not need to hardcode the flags in the code anymore. The `isViewable()` and `isPrintable()` methods are now much easier to read. Additionally, unit tests have been added to ensure correct behavior.

This is another part of #5218.
  • Loading branch information
timvandermeij committed Nov 21, 2015
1 parent df46b64 commit 536e1ca
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 29 deletions.
96 changes: 68 additions & 28 deletions src/core/annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

'use strict';

Expand Down Expand Up @@ -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;
Expand All @@ -138,6 +140,70 @@ var Annotation = (function AnnotationClosure() {
}

Annotation.prototype = {
/**
* 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 (flags === (flags | 0)) {
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;
},

/**
* Check if the annotation is viewable.
*
* @public
* @memberof Annotation
* @return {boolean}
*/
isViewable: function Annotation_isViewable() {
if (this.flags) {
return !this.hasFlag(AnnotationFlag.INVISIBLE) &&
!this.hasFlag(AnnotationFlag.HIDDEN) &&
!this.hasFlag(AnnotationFlag.NOVIEW);
}
return true;
},

/**
* Check if the annotation is printable.
*
* @public
* @memberof Annotation
* @return {boolean}
*/
isPrintable: function Annotation_isPrintable() {
if (this.flags) {
return this.hasFlag(AnnotationFlag.PRINT);
}
return false;
},

/**
* Set the rectangle.
*
Expand Down Expand Up @@ -237,32 +303,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) {
Expand Down
13 changes: 13 additions & 0 deletions src/shared/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
23 changes: 22 additions & 1 deletion test/unit/annotation_layer_spec.js
Original file line number Diff line number Diff line change
@@ -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.isViewable()).toEqual(true);
expect(annotation.isPrintable()).toEqual(false);
});

it('should set and get a valid rectangle', function() {
var dict = new Dict();
dict.set('Subtype', '');
Expand Down

0 comments on commit 536e1ca

Please sign in to comment.