Implement annotation layer regression testing
This commit is contained in:
parent
e45e7d0f3c
commit
b7217a2274
73
test/annotation_layer_test.css
Normal file
73
test/annotation_layer_test.css
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/* Copyright 2015 Mozilla Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Used for annotation layer tests */
|
||||||
|
|
||||||
|
.annotationLayer {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationLayer > section {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationLayer .annotLink > a {
|
||||||
|
position: absolute;
|
||||||
|
font-size: 1em;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
opacity: 0.2;
|
||||||
|
background: #ff0;
|
||||||
|
box-shadow: 0px 2px 10px #ff0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationLayer .annotText > img {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationLayer .annotTextContentWrapper {
|
||||||
|
position: absolute;
|
||||||
|
width: 20em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationLayer .annotTextContent {
|
||||||
|
z-index: 200;
|
||||||
|
float: left;
|
||||||
|
max-width: 20em;
|
||||||
|
background-color: #FFFF99;
|
||||||
|
box-shadow: 0px 2px 5px #333;
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 0.6em;
|
||||||
|
display: block !important;
|
||||||
|
font: message-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationLayer .annotTextContent > h1 {
|
||||||
|
font-size: 1em;
|
||||||
|
border-bottom: 1px solid #000000;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0 0.2em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotationLayer .annotTextContent > p {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.2em 0 0 0;
|
||||||
|
}
|
169
test/driver.js
169
test/driver.js
@ -19,6 +19,29 @@
|
|||||||
var WAITING_TIME = 100; // ms
|
var WAITING_TIME = 100; // ms
|
||||||
var PDF_TO_CSS_UNITS = 96.0 / 72.0;
|
var PDF_TO_CSS_UNITS = 96.0 / 72.0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
var LinkServiceMock = (function LinkServiceMockClosure() {
|
||||||
|
function LinkServiceMock() {}
|
||||||
|
|
||||||
|
LinkServiceMock.prototype = {
|
||||||
|
navigateTo: function (dest) {},
|
||||||
|
|
||||||
|
getDestinationHash: function (dest) {
|
||||||
|
return '#';
|
||||||
|
},
|
||||||
|
|
||||||
|
getAnchorUrl: function (hash) {
|
||||||
|
return '#';
|
||||||
|
},
|
||||||
|
|
||||||
|
executeNamedAction: function (action) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
return LinkServiceMock;
|
||||||
|
})();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class
|
* @class
|
||||||
*/
|
*/
|
||||||
@ -89,6 +112,115 @@ var rasterizeTextLayer = (function rasterizeTextLayerClosure() {
|
|||||||
return rasterizeTextLayer;
|
return rasterizeTextLayer;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
var rasterizeAnnotationLayer = (function rasterizeAnnotationLayerClosure() {
|
||||||
|
var SVG_NS = 'http://www.w3.org/2000/svg';
|
||||||
|
|
||||||
|
var annotationLayerStylePromise = null;
|
||||||
|
function getAnnotationLayerStyle() {
|
||||||
|
if (annotationLayerStylePromise) {
|
||||||
|
return annotationLayerStylePromise;
|
||||||
|
}
|
||||||
|
annotationLayerStylePromise = new Promise(function (resolve) {
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('GET', './annotation_layer_test.css');
|
||||||
|
xhr.onload = function () {
|
||||||
|
resolve(xhr.responseText);
|
||||||
|
};
|
||||||
|
xhr.send(null);
|
||||||
|
});
|
||||||
|
return annotationLayerStylePromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function inlineAnnotationImages(images) {
|
||||||
|
var imagePromises = [];
|
||||||
|
for (var i = 0, ii = images.length; i < ii; i++) {
|
||||||
|
var imagePromise = new Promise(function(resolve) {
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.responseType = 'blob';
|
||||||
|
xhr.onload = function() {
|
||||||
|
var reader = new FileReader();
|
||||||
|
reader.onloadend = function() {
|
||||||
|
resolve(reader.result);
|
||||||
|
};
|
||||||
|
reader.readAsDataURL(xhr.response);
|
||||||
|
};
|
||||||
|
xhr.onerror = function() {
|
||||||
|
resolve('');
|
||||||
|
};
|
||||||
|
xhr.open('GET', images[i].src);
|
||||||
|
xhr.send();
|
||||||
|
});
|
||||||
|
imagePromises.push(imagePromise);
|
||||||
|
}
|
||||||
|
return imagePromises;
|
||||||
|
}
|
||||||
|
|
||||||
|
function rasterizeAnnotationLayer(ctx, viewport, annotations, page) {
|
||||||
|
return new Promise(function (resolve) {
|
||||||
|
// Building SVG with size of the viewport.
|
||||||
|
var svg = document.createElementNS(SVG_NS, 'svg:svg');
|
||||||
|
svg.setAttribute('width', viewport.width + 'px');
|
||||||
|
svg.setAttribute('height', viewport.height + 'px');
|
||||||
|
|
||||||
|
// Adding element to host our HTML (style + annotation layer div).
|
||||||
|
var foreignObject = document.createElementNS(SVG_NS, 'svg:foreignObject');
|
||||||
|
foreignObject.setAttribute('x', '0');
|
||||||
|
foreignObject.setAttribute('y', '0');
|
||||||
|
foreignObject.setAttribute('width', viewport.width + 'px');
|
||||||
|
foreignObject.setAttribute('height', viewport.height + 'px');
|
||||||
|
var style = document.createElement('style');
|
||||||
|
var stylePromise = getAnnotationLayerStyle();
|
||||||
|
foreignObject.appendChild(style);
|
||||||
|
var div = document.createElement('div');
|
||||||
|
div.className = 'annotationLayer';
|
||||||
|
|
||||||
|
// Rendering annotation layer as HTML.
|
||||||
|
stylePromise.then(function (styles) {
|
||||||
|
style.textContent = styles;
|
||||||
|
|
||||||
|
var annotation_viewport = viewport.clone({ dontFlip: true });
|
||||||
|
var parameters = {
|
||||||
|
viewport: annotation_viewport,
|
||||||
|
div: div,
|
||||||
|
annotations: annotations,
|
||||||
|
page: page,
|
||||||
|
linkService: new LinkServiceMock()
|
||||||
|
};
|
||||||
|
PDFJS.AnnotationLayer.render(parameters);
|
||||||
|
|
||||||
|
// Inline SVG images from text annotations.
|
||||||
|
var images = div.getElementsByTagName('img');
|
||||||
|
var imagePromises = inlineAnnotationImages(images);
|
||||||
|
var converted = Promise.all(imagePromises).then(function(data) {
|
||||||
|
for (var i = 0, ii = data.length; i < ii; i++) {
|
||||||
|
images[i].src = data[i];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
foreignObject.appendChild(div);
|
||||||
|
svg.appendChild(foreignObject);
|
||||||
|
|
||||||
|
// We need to have UTF-8 encoded XML.
|
||||||
|
converted.then(function() {
|
||||||
|
var svg_xml = unescape(encodeURIComponent(
|
||||||
|
(new XMLSerializer()).serializeToString(svg)));
|
||||||
|
var img = new Image();
|
||||||
|
img.src = 'data:image/svg+xml;base64,' + btoa(svg_xml);
|
||||||
|
img.onload = function () {
|
||||||
|
ctx.drawImage(img, 0, 0);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return rasterizeAnnotationLayer;
|
||||||
|
})();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} DriverOptions
|
* @typedef {Object} DriverOptions
|
||||||
* @property {HTMLSpanElement} inflight - Field displaying the number of
|
* @property {HTMLSpanElement} inflight - Field displaying the number of
|
||||||
@ -113,6 +245,7 @@ var Driver = (function DriverClosure() {
|
|||||||
PDFJS.cMapPacked = true;
|
PDFJS.cMapPacked = true;
|
||||||
PDFJS.cMapUrl = '../external/bcmaps/';
|
PDFJS.cMapUrl = '../external/bcmaps/';
|
||||||
PDFJS.enableStats = true;
|
PDFJS.enableStats = true;
|
||||||
|
PDFJS.imageResourcesPath = '/web/images/';
|
||||||
|
|
||||||
// Set the passed options
|
// Set the passed options
|
||||||
this.inflight = options.inflight;
|
this.inflight = options.inflight;
|
||||||
@ -320,7 +453,7 @@ var Driver = (function DriverClosure() {
|
|||||||
self.canvas.height = viewport.height;
|
self.canvas.height = viewport.height;
|
||||||
self._clearCanvas();
|
self._clearCanvas();
|
||||||
|
|
||||||
var textLayerCanvas;
|
var textLayerCanvas, annotationLayerCanvas;
|
||||||
var initPromise;
|
var initPromise;
|
||||||
if (task.type === 'text') {
|
if (task.type === 'text') {
|
||||||
// Using a dummy canvas for PDF context drawing operations
|
// Using a dummy canvas for PDF context drawing operations
|
||||||
@ -343,8 +476,36 @@ var Driver = (function DriverClosure() {
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
textLayerCanvas = null;
|
textLayerCanvas = null;
|
||||||
initPromise = Promise.resolve();
|
|
||||||
|
// Render the annotation layer if necessary.
|
||||||
|
if (task.annotations) {
|
||||||
|
// Create a dummy canvas for the drawing operations.
|
||||||
|
annotationLayerCanvas = self.annotationLayerCanvas;
|
||||||
|
if (!annotationLayerCanvas) {
|
||||||
|
annotationLayerCanvas = document.createElement('canvas');
|
||||||
|
self.annotationLayerCanvas = annotationLayerCanvas;
|
||||||
|
}
|
||||||
|
annotationLayerCanvas.width = viewport.width;
|
||||||
|
annotationLayerCanvas.height = viewport.height;
|
||||||
|
var annotationLayerContext =
|
||||||
|
annotationLayerCanvas.getContext('2d');
|
||||||
|
annotationLayerContext.clearRect(0, 0,
|
||||||
|
annotationLayerCanvas.width, annotationLayerCanvas.height);
|
||||||
|
|
||||||
|
// The annotation builder will draw its content on the canvas.
|
||||||
|
initPromise =
|
||||||
|
page.getAnnotations({ intent: 'display' }).then(
|
||||||
|
function(annotations) {
|
||||||
|
return rasterizeAnnotationLayer(annotationLayerContext,
|
||||||
|
viewport, annotations,
|
||||||
|
page);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
annotationLayerCanvas = null;
|
||||||
|
initPromise = Promise.resolve();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var renderContext = {
|
var renderContext = {
|
||||||
canvasContext: ctx,
|
canvasContext: ctx,
|
||||||
viewport: viewport
|
viewport: viewport
|
||||||
@ -359,6 +520,10 @@ var Driver = (function DriverClosure() {
|
|||||||
ctx.restore();
|
ctx.restore();
|
||||||
ctx.drawImage(textLayerCanvas, 0, 0);
|
ctx.drawImage(textLayerCanvas, 0, 0);
|
||||||
}
|
}
|
||||||
|
// If we have annotation layer, compose it on top of the page.
|
||||||
|
if (annotationLayerCanvas) {
|
||||||
|
ctx.drawImage(annotationLayerCanvas, 0, 0);
|
||||||
|
}
|
||||||
page.cleanup();
|
page.cleanup();
|
||||||
task.stats = page.stats;
|
task.stats = page.stats;
|
||||||
page.stats = new pdfjsSharedUtil.StatTimer();
|
page.stats = new pdfjsSharedUtil.StatTimer();
|
||||||
|
@ -1600,7 +1600,8 @@
|
|||||||
"rounds": 1,
|
"rounds": 1,
|
||||||
"lastPage": 1,
|
"lastPage": 1,
|
||||||
"link": true,
|
"link": true,
|
||||||
"type": "eq"
|
"type": "eq",
|
||||||
|
"annotations": true
|
||||||
},
|
},
|
||||||
{ "id": "issue1002",
|
{ "id": "issue1002",
|
||||||
"file": "pdfs/issue1002.pdf",
|
"file": "pdfs/issue1002.pdf",
|
||||||
@ -2052,6 +2053,7 @@
|
|||||||
"md5": "56321ea830be9c4f8437ca17ac535b2d",
|
"md5": "56321ea830be9c4f8437ca17ac535b2d",
|
||||||
"rounds": 1,
|
"rounds": 1,
|
||||||
"type": "eq",
|
"type": "eq",
|
||||||
|
"annotations": true,
|
||||||
"about": "Text widget annotation witout appearance streams."
|
"about": "Text widget annotation witout appearance streams."
|
||||||
},
|
},
|
||||||
{ "id": "gesamt",
|
{ "id": "gesamt",
|
||||||
@ -2585,7 +2587,8 @@
|
|||||||
"file": "pdfs/annotation-border-styles.pdf",
|
"file": "pdfs/annotation-border-styles.pdf",
|
||||||
"md5": "22930fc09c7386e1131b14d936e554af",
|
"md5": "22930fc09c7386e1131b14d936e554af",
|
||||||
"rounds": 1,
|
"rounds": 1,
|
||||||
"type": "eq"
|
"type": "eq",
|
||||||
|
"annotations": true
|
||||||
},
|
},
|
||||||
{ "id": "issue5481.pdf",
|
{ "id": "issue5481.pdf",
|
||||||
"file": "pdfs/issue5481.pdf",
|
"file": "pdfs/issue5481.pdf",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user