Skip to content
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

Refactor annotation flags code #6672

Merged
merged 1 commit into from
Nov 22, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 71 additions & 41 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, isInt */

'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,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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this.flags instead of this.data.flags?
Only the data object is exposed with Page.getAnnotationsData method so this will remove the ability to read annotation flags from viewer/third-party code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be addressed by #6677.

} 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.
*
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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));
}
Expand Down Expand Up @@ -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);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a nice simplification, compared to the previous code!


// Building the full field name by collecting the field and
// its ancestors 'T' data and joining them using '.'.
var fieldName = [];
Expand Down Expand Up @@ -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;
})();
Expand Down
3 changes: 1 addition & 2 deletions src/core/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
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.viewable).toEqual(true);
expect(annotation.printable).toEqual(false);
});

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