Skip to content

Commit cf6d40f

Browse files
committed
Merge pull request mozilla#6214 from timvandermeij/annotation-color
Refactor annotation color handling and add unit tests
2 parents 2817f00 + a2e9845 commit cf6d40f

File tree

3 files changed

+112
-36
lines changed

3 files changed

+112
-36
lines changed

src/core/annotation.js

Lines changed: 45 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
/* globals PDFJS, Util, isDict, isName, stringToPDFString, warn, Dict, Stream,
1818
stringToBytes, Promise, isArray, ObjectLoader, OperatorList,
1919
isValidUrl, OPS, createPromiseCapability, AnnotationType,
20-
stringToUTF8String, AnnotationBorderStyleType */
20+
stringToUTF8String, AnnotationBorderStyleType, ColorSpace */
2121

2222
'use strict';
2323

@@ -79,28 +79,8 @@ var Annotation = (function AnnotationClosure() {
7979
data.rect = Util.normalizeRect(rect);
8080
data.annotationFlags = dict.get('F');
8181

82-
var color = dict.get('C');
83-
if (!color) {
84-
// The PDF spec does not mention how a missing color array is interpreted.
85-
// Adobe Reader seems to default to black in this case.
86-
data.color = [0, 0, 0];
87-
} else if (isArray(color)) {
88-
switch (color.length) {
89-
case 0:
90-
// Empty array denotes transparent border.
91-
data.color = null;
92-
break;
93-
case 1:
94-
// TODO: implement DeviceGray
95-
break;
96-
case 3:
97-
data.color = color;
98-
break;
99-
case 4:
100-
// TODO: implement DeviceCMYK
101-
break;
102-
}
103-
}
82+
this.setColor(dict.get('C'));
83+
data.color = this.color;
10484

10585
this.borderStyle = data.borderStyle = new AnnotationBorderStyle();
10686
this.setBorderStyle(dict);
@@ -111,6 +91,48 @@ var Annotation = (function AnnotationClosure() {
11191
}
11292

11393
Annotation.prototype = {
94+
/**
95+
* Set the color and take care of color space conversion.
96+
*
97+
* @public
98+
* @memberof Annotation
99+
* @param {Array} color - The color array containing either 0
100+
* (transparent), 1 (grayscale), 3 (RGB) or
101+
* 4 (CMYK) elements
102+
*/
103+
setColor: function Annotation_setColor(color) {
104+
var rgbColor = new Uint8Array(3); // Black in RGB color space (default)
105+
if (!isArray(color)) {
106+
this.color = rgbColor;
107+
return;
108+
}
109+
110+
switch (color.length) {
111+
case 0: // Transparent, which we indicate with a null value
112+
this.color = null;
113+
break;
114+
115+
case 1: // Convert grayscale to RGB
116+
ColorSpace.singletons.gray.getRgbItem(color, 0, rgbColor, 0);
117+
this.color = rgbColor;
118+
break;
119+
120+
case 3: // Convert RGB percentages to RGB
121+
ColorSpace.singletons.rgb.getRgbItem(color, 0, rgbColor, 0);
122+
this.color = rgbColor;
123+
break;
124+
125+
case 4: // Convert CMYK to RGB
126+
ColorSpace.singletons.cmyk.getRgbItem(color, 0, rgbColor, 0);
127+
this.color = rgbColor;
128+
break;
129+
130+
default:
131+
this.color = rgbColor;
132+
break;
133+
}
134+
},
135+
114136
/**
115137
* Set the border style (as AnnotationBorderStyle object).
116138
*

src/display/annotation_helper.js

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,12 @@ var AnnotationUtils = (function AnnotationUtilsClosure() {
100100
// Border color
101101
if (item.color) {
102102
container.style.borderColor =
103-
Util.makeCssRgb(Math.round(item.color[0] * 255),
104-
Math.round(item.color[1] * 255),
105-
Math.round(item.color[2] * 255));
103+
Util.makeCssRgb(item.color[0] | 0,
104+
item.color[1] | 0,
105+
item.color[2] | 0);
106106
} else {
107-
// Default color is black, but that's not obvious from the spec.
108-
container.style.borderColor = 'rgb(0,0,0)';
107+
// Transparent (invisible) border, so do not draw it at all.
108+
container.style.borderWidth = 0;
109109
}
110110
}
111111

@@ -172,17 +172,15 @@ var AnnotationUtils = (function AnnotationUtilsClosure() {
172172
content.setAttribute('hidden', true);
173173

174174
var i, ii;
175-
if (item.hasBgColor) {
175+
if (item.hasBgColor && item.color) {
176176
var color = item.color;
177177

178178
// Enlighten the color (70%)
179179
var BACKGROUND_ENLIGHT = 0.7;
180-
var r = BACKGROUND_ENLIGHT * (1.0 - color[0]) + color[0];
181-
var g = BACKGROUND_ENLIGHT * (1.0 - color[1]) + color[1];
182-
var b = BACKGROUND_ENLIGHT * (1.0 - color[2]) + color[2];
183-
content.style.backgroundColor = Util.makeCssRgb((r * 255) | 0,
184-
(g * 255) | 0,
185-
(b * 255) | 0);
180+
var r = BACKGROUND_ENLIGHT * (255 - color[0]) + color[0];
181+
var g = BACKGROUND_ENLIGHT * (255 - color[1]) + color[1];
182+
var b = BACKGROUND_ENLIGHT * (255 - color[2]) + color[2];
183+
content.style.backgroundColor = Util.makeCssRgb(r | 0, g | 0, b | 0);
186184
}
187185

188186
var title = document.createElement('h1');

test/unit/annotation_layer_spec.js

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,67 @@
11
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
22
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
3-
/* globals expect, it, describe, Dict, AnnotationBorderStyle,
3+
/* globals expect, it, describe, Dict, Annotation, AnnotationBorderStyle,
44
AnnotationBorderStyleType */
55

66
'use strict';
77

88
describe('Annotation layer', function() {
9+
describe('Annotation', function() {
10+
it('should reject a color if it is not an array', function() {
11+
var dict = new Dict();
12+
dict.set('Subtype', '');
13+
var annotation = new Annotation({ dict: dict, ref: 0 });
14+
annotation.setColor('red');
15+
16+
expect(annotation.color).toEqual([0, 0, 0]);
17+
});
18+
19+
it('should set and get a transparent color', function() {
20+
var dict = new Dict();
21+
dict.set('Subtype', '');
22+
var annotation = new Annotation({ dict: dict, ref: 0 });
23+
annotation.setColor([]);
24+
25+
expect(annotation.color).toEqual(null);
26+
});
27+
28+
it('should set and get a grayscale color', function() {
29+
var dict = new Dict();
30+
dict.set('Subtype', '');
31+
var annotation = new Annotation({ dict: dict, ref: 0 });
32+
annotation.setColor([0.4]);
33+
34+
expect(annotation.color).toEqual([102, 102, 102]);
35+
});
36+
37+
it('should set and get an RGB color', function() {
38+
var dict = new Dict();
39+
dict.set('Subtype', '');
40+
var annotation = new Annotation({ dict: dict, ref: 0 });
41+
annotation.setColor([0, 0, 1]);
42+
43+
expect(annotation.color).toEqual([0, 0, 255]);
44+
});
45+
46+
it('should set and get a CMYK color', function() {
47+
var dict = new Dict();
48+
dict.set('Subtype', '');
49+
var annotation = new Annotation({ dict: dict, ref: 0 });
50+
annotation.setColor([0.1, 0.92, 0.84, 0.02]);
51+
52+
expect(annotation.color).toEqual([233, 59, 47]);
53+
});
54+
55+
it('should not set and get an invalid color', function() {
56+
var dict = new Dict();
57+
dict.set('Subtype', '');
58+
var annotation = new Annotation({ dict: dict, ref: 0 });
59+
annotation.setColor([0.4, 0.6]);
60+
61+
expect(annotation.color).toEqual([0, 0, 0]);
62+
});
63+
});
64+
965
describe('AnnotationBorderStyle', function() {
1066
it('should set and get a valid width', function() {
1167
var borderStyle = new AnnotationBorderStyle();

0 commit comments

Comments
 (0)