Skip to content

Commit

Permalink
Implement annotation layer regression testing
Browse files Browse the repository at this point in the history
  • Loading branch information
timvandermeij committed Dec 20, 2015
1 parent e45e7d0 commit b7217a2
Show file tree
Hide file tree
Showing 3 changed files with 245 additions and 4 deletions.
73 changes: 73 additions & 0 deletions test/annotation_layer_test.css
Original file line number Diff line number Diff line change
@@ -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 changes: 167 additions & 2 deletions test/driver.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,29 @@
var WAITING_TIME = 100; // ms
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
*/
Expand Down Expand Up @@ -89,6 +112,115 @@ var rasterizeTextLayer = (function rasterizeTextLayerClosure() {
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
* @property {HTMLSpanElement} inflight - Field displaying the number of
Expand All @@ -113,6 +245,7 @@ var Driver = (function DriverClosure() {
PDFJS.cMapPacked = true;
PDFJS.cMapUrl = '../external/bcmaps/';
PDFJS.enableStats = true;
PDFJS.imageResourcesPath = '/web/images/';

// Set the passed options
this.inflight = options.inflight;
Expand Down Expand Up @@ -320,7 +453,7 @@ var Driver = (function DriverClosure() {
self.canvas.height = viewport.height;
self._clearCanvas();

var textLayerCanvas;
var textLayerCanvas, annotationLayerCanvas;
var initPromise;
if (task.type === 'text') {
// Using a dummy canvas for PDF context drawing operations
Expand All @@ -343,8 +476,36 @@ var Driver = (function DriverClosure() {
});
} else {
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 = {
canvasContext: ctx,
viewport: viewport
Expand All @@ -359,6 +520,10 @@ var Driver = (function DriverClosure() {
ctx.restore();
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();
task.stats = page.stats;
page.stats = new pdfjsSharedUtil.StatTimer();
Expand Down
7 changes: 5 additions & 2 deletions test/test_manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -1600,7 +1600,8 @@
"rounds": 1,
"lastPage": 1,
"link": true,
"type": "eq"
"type": "eq",
"annotations": true
},
{ "id": "issue1002",
"file": "pdfs/issue1002.pdf",
Expand Down Expand Up @@ -2052,6 +2053,7 @@
"md5": "56321ea830be9c4f8437ca17ac535b2d",
"rounds": 1,
"type": "eq",
"annotations": true,
"about": "Text widget annotation witout appearance streams."
},
{ "id": "gesamt",
Expand Down Expand Up @@ -2585,7 +2587,8 @@
"file": "pdfs/annotation-border-styles.pdf",
"md5": "22930fc09c7386e1131b14d936e554af",
"rounds": 1,
"type": "eq"
"type": "eq",
"annotations": true
},
{ "id": "issue5481.pdf",
"file": "pdfs/issue5481.pdf",
Expand Down

0 comments on commit b7217a2

Please sign in to comment.