From cf07918ccb22851e65b87ffdca0794c4003a69c5 Mon Sep 17 00:00:00 2001 From: Tim van der Meij Date: Sat, 18 May 2019 15:52:17 +0200 Subject: [PATCH 1/2] Implement contents for every annotation type The specification states that `Contents` can be available for every annotation types instead of only for markup annotations. --- src/core/annotation.js | 18 ++++++++++++++++-- test/unit/annotation_spec.js | 14 ++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/core/annotation.js b/src/core/annotation.js index 8ee097959..b429cf9f9 100644 --- a/src/core/annotation.js +++ b/src/core/annotation.js @@ -173,8 +173,9 @@ function getTransformMatrix(rect, bbox, matrix) { class Annotation { constructor(params) { - let dict = params.dict; + const dict = params.dict; + this.setContents(dict.get('Contents')); this.setCreationDate(dict.get('CreationDate')); this.setModificationDate(dict.get('M')); this.setFlags(dict.get('F')); @@ -188,6 +189,7 @@ class Annotation { annotationFlags: this.flags, borderStyle: this.borderStyle, color: this.color, + contents: this.contents, creationDate: this.creationDate, hasAppearance: !!this.appearance, id: params.id, @@ -242,6 +244,19 @@ class Annotation { return this._isPrintable(this.flags); } + /** + * Set the contents. + * + * @public + * @memberof Annotation + * @param {string} contents - Text to display for the annotation or, if the + * type of annotation does not display text, a + * description of the annotation's contents + */ + setContents(contents) { + this.contents = stringToPDFString(contents || ''); + } + /** * Set the creation date. * @@ -623,7 +638,6 @@ class MarkupAnnotation extends Annotation { this.data.hasPopup = dict.has('Popup'); this.data.title = stringToPDFString(dict.get('T') || ''); - this.data.contents = stringToPDFString(dict.get('Contents') || ''); } } diff --git a/test/unit/annotation_spec.js b/test/unit/annotation_spec.js index b26b40de6..05b17b4fd 100644 --- a/test/unit/annotation_spec.js +++ b/test/unit/annotation_spec.js @@ -131,6 +131,20 @@ describe('annotation', function() { dict = ref = null; }); + it('should set and get valid contents', function() { + const annotation = new Annotation({ dict, ref, }); + annotation.setContents('Foo bar baz'); + + expect(annotation.contents).toEqual('Foo bar baz'); + }); + + it('should not set and get invalid contents', function() { + const annotation = new Annotation({ dict, ref, }); + annotation.setContents(undefined); + + expect(annotation.contents).toEqual(''); + }); + it('should set and get a valid creation date', function() { const annotation = new Annotation({ dict, ref, }); annotation.setCreationDate('D:20190422'); From bc1eb49a77c684e72839a99daf86e4dc3f53ab7d Mon Sep 17 00:00:00 2001 From: Tim van der Meij Date: Sat, 25 May 2019 15:25:52 +0200 Subject: [PATCH 2/2] Implement creation date only for markup annotations The specification states that `CreationDate` is only available for markup annotations instead of for all annotation types. Moreover, popup annotations are not markup annotations according to the specification, so the creation date inheritance from the parent annotation is also removed there (note that only the modification date is used in e.g., the viewer). --- src/core/annotation.js | 39 +++++++++++++--------------- test/unit/annotation_spec.js | 49 ++++++++++++++++++++++-------------- 2 files changed, 47 insertions(+), 41 deletions(-) diff --git a/src/core/annotation.js b/src/core/annotation.js index b429cf9f9..5a2bb9448 100644 --- a/src/core/annotation.js +++ b/src/core/annotation.js @@ -176,7 +176,6 @@ class Annotation { const dict = params.dict; this.setContents(dict.get('Contents')); - this.setCreationDate(dict.get('CreationDate')); this.setModificationDate(dict.get('M')); this.setFlags(dict.get('F')); this.setRectangle(dict.getArray('Rect')); @@ -190,7 +189,6 @@ class Annotation { borderStyle: this.borderStyle, color: this.color, contents: this.contents, - creationDate: this.creationDate, hasAppearance: !!this.appearance, id: params.id, modificationDate: this.modificationDate, @@ -257,18 +255,6 @@ class Annotation { this.contents = stringToPDFString(contents || ''); } - /** - * Set the creation date. - * - * @public - * @memberof Annotation - * @param {string} creationDate - PDF date string that indicates when the - * annotation was originally created - */ - setCreationDate(creationDate) { - this.creationDate = isString(creationDate) ? creationDate : null; - } - /** * Set the modification date. * @@ -629,16 +615,31 @@ class AnnotationBorderStyle { class MarkupAnnotation extends Annotation { constructor(parameters) { super(parameters); - const dict = parameters.dict; + const dict = parameters.dict; if (!dict.has('C')) { // Fall back to the default background color. this.data.color = null; } + this.setCreationDate(dict.get('CreationDate')); + this.data.creationDate = this.creationDate; + this.data.hasPopup = dict.has('Popup'); this.data.title = stringToPDFString(dict.get('T') || ''); } + + /** + * Set the creation date. + * + * @public + * @memberof MarkupAnnotation + * @param {string} creationDate - PDF date string that indicates when the + * annotation was originally created + */ + setCreationDate(creationDate) { + this.creationDate = isString(creationDate) ? creationDate : null; + } } class WidgetAnnotation extends Annotation { @@ -989,13 +990,6 @@ class PopupAnnotation extends Annotation { this.data.title = stringToPDFString(parentItem.get('T') || ''); this.data.contents = stringToPDFString(parentItem.get('Contents') || ''); - if (!parentItem.has('CreationDate')) { - this.data.creationDate = null; - } else { - this.setCreationDate(parentItem.get('CreationDate')); - this.data.creationDate = this.creationDate; - } - if (!parentItem.has('M')) { this.data.modificationDate = null; } else { @@ -1179,4 +1173,5 @@ export { Annotation, AnnotationBorderStyle, AnnotationFactory, + MarkupAnnotation, }; diff --git a/test/unit/annotation_spec.js b/test/unit/annotation_spec.js index 05b17b4fd..b737550f3 100644 --- a/test/unit/annotation_spec.js +++ b/test/unit/annotation_spec.js @@ -14,7 +14,7 @@ */ import { - Annotation, AnnotationBorderStyle, AnnotationFactory + Annotation, AnnotationBorderStyle, AnnotationFactory, MarkupAnnotation } from '../../src/core/annotation'; import { AnnotationBorderStyleType, AnnotationFieldFlag, AnnotationFlag, @@ -145,20 +145,6 @@ describe('annotation', function() { expect(annotation.contents).toEqual(''); }); - it('should set and get a valid creation date', function() { - const annotation = new Annotation({ dict, ref, }); - annotation.setCreationDate('D:20190422'); - - expect(annotation.creationDate).toEqual('D:20190422'); - }); - - it('should set and get an invalid creation date', function() { - const annotation = new Annotation({ dict, ref, }); - annotation.setCreationDate(undefined); - - expect(annotation.creationDate).toEqual(null); - }); - it('should set and get a valid modification date', function() { const annotation = new Annotation({ dict, ref, }); annotation.setModificationDate('D:20190422'); @@ -166,7 +152,7 @@ describe('annotation', function() { expect(annotation.modificationDate).toEqual('D:20190422'); }); - it('should set and get an invalid modification date', function() { + it('should not set and get an invalid modification date', function() { const annotation = new Annotation({ dict, ref, }); annotation.setModificationDate(undefined); @@ -331,6 +317,34 @@ describe('annotation', function() { }); }); + describe('MarkupAnnotation', function() { + let dict, ref; + + beforeAll(function(done) { + dict = new Dict(); + ref = new Ref(1, 0); + done(); + }); + + afterAll(function() { + dict = ref = null; + }); + + it('should set and get a valid creation date', function() { + const markupAnnotation = new MarkupAnnotation({ dict, ref, }); + markupAnnotation.setCreationDate('D:20190422'); + + expect(markupAnnotation.creationDate).toEqual('D:20190422'); + }); + + it('should not set and get an invalid creation date', function() { + const markupAnnotation = new MarkupAnnotation({ dict, ref, }); + markupAnnotation.setCreationDate(undefined); + + expect(markupAnnotation.creationDate).toEqual(null); + }); + }); + describe('LinkAnnotation', function() { it('should correctly parse a URI action', function(done) { const actionDict = new Dict(); @@ -1446,7 +1460,6 @@ describe('annotation', function() { const parentDict = new Dict(); parentDict.set('Type', Name.get('Annot')); parentDict.set('Subtype', Name.get('Text')); - parentDict.set('CreationDate', 'D:20190422'); parentDict.set('M', 'D:20190423'); parentDict.set('C', [0, 0, 1]); @@ -1463,7 +1476,6 @@ describe('annotation', function() { AnnotationFactory.create(xref, popupRef, pdfManagerMock, idFactoryMock).then(({ data, viewable, }) => { expect(data.annotationType).toEqual(AnnotationType.POPUP); - expect(data.creationDate).toEqual('D:20190422'); expect(data.modificationDate).toEqual('D:20190423'); expect(data.color).toEqual(new Uint8ClampedArray([0, 0, 255])); done(); @@ -1488,7 +1500,6 @@ describe('annotation', function() { AnnotationFactory.create(xref, popupRef, pdfManagerMock, idFactoryMock).then(({ data, viewable, }) => { expect(data.annotationType).toEqual(AnnotationType.POPUP); - expect(data.creationDate).toEqual(null); expect(data.modificationDate).toEqual(null); expect(data.color).toEqual(null); done();