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

Generate test images at different output scales. #14545

Merged
merged 1 commit into from
Feb 24, 2022
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
61 changes: 49 additions & 12 deletions test/driver.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function loadStyles(styles) {
return Promise.all(promises);
}

function writeSVG(svgElement, ctx) {
function writeSVG(svgElement, ctx, outputScale) {
// We need to have UTF-8 encoded XML.
const svg_xml = unescape(
encodeURIComponent(new XMLSerializer().serializeToString(svgElement))
Expand Down Expand Up @@ -102,15 +102,18 @@ function inlineImages(images) {
return Promise.all(imagePromises);
}

async function convertCanvasesToImages(annotationCanvasMap) {
async function convertCanvasesToImages(annotationCanvasMap, outputScale) {
const results = new Map();
const promises = [];
for (const [key, canvas] of annotationCanvasMap) {
promises.push(
new Promise(resolve => {
canvas.toBlob(blob => {
const image = document.createElement("img");
image.onload = resolve;
image.onload = function () {
image.style.width = Math.floor(image.width / outputScale) + "px";
resolve();
};
results.set(key, image);
image.src = URL.createObjectURL(blob);
});
Expand Down Expand Up @@ -198,6 +201,7 @@ class Rasterize {
static async annotationLayer(
ctx,
viewport,
outputScale,
annotations,
annotationCanvasMap,
page,
Expand All @@ -213,7 +217,8 @@ class Rasterize {

const annotationViewport = viewport.clone({ dontFlip: true });
const annotationImageMap = await convertCanvasesToImages(
annotationCanvasMap
annotationCanvasMap,
outputScale
);

// Rendering annotation layer as HTML.
Expand Down Expand Up @@ -600,13 +605,38 @@ class Driver {
ctx = this.canvas.getContext("2d", { alpha: false });
task.pdfDoc.getPage(task.pageNum).then(
page => {
const viewport = page.getViewport({
// Default to creating the test images at the devices pixel ratio,
// unless the test explicitly specifies an output scale.
const outputScale = task.outputScale || window.devicePixelRatio;
let viewport = page.getViewport({
scale: PixelsPerInch.PDF_TO_CSS_UNITS,
});
this.canvas.width = viewport.width;
this.canvas.height = viewport.height;
// Restrict the test from creating a canvas that is too big.
const MAX_CANVAS_PIXEL_DIMENSION = 4096;
const largestDimension = Math.max(viewport.width, viewport.height);
if (
Math.floor(largestDimension * outputScale) >
MAX_CANVAS_PIXEL_DIMENSION
) {
const rescale = MAX_CANVAS_PIXEL_DIMENSION / largestDimension;
viewport = viewport.clone({
scale: PixelsPerInch.PDF_TO_CSS_UNITS * rescale,
});
}
const pixelWidth = Math.floor(viewport.width * outputScale);
const pixelHeight = Math.floor(viewport.height * outputScale);
task.viewportWidth = Math.floor(viewport.width);
task.viewportHeight = Math.floor(viewport.height);
task.outputScale = outputScale;
this.canvas.width = pixelWidth;
this.canvas.height = pixelHeight;
this.canvas.style.width = Math.floor(viewport.width) + "px";
this.canvas.style.height = Math.floor(viewport.height) + "px";
this._clearCanvas();

const transform =
outputScale !== 1 ? [outputScale, 0, 0, outputScale, 0, 0] : null;

// Initialize various `eq` test subtypes, see comment below.
let renderAnnotations = false,
renderForms = false,
Expand All @@ -631,15 +661,16 @@ class Driver {
textLayerCanvas = document.createElement("canvas");
this.textLayerCanvas = textLayerCanvas;
}
textLayerCanvas.width = viewport.width;
textLayerCanvas.height = viewport.height;
textLayerCanvas.width = pixelWidth;
textLayerCanvas.height = pixelHeight;
const textLayerContext = textLayerCanvas.getContext("2d");
textLayerContext.clearRect(
0,
0,
textLayerCanvas.width,
textLayerCanvas.height
);
textLayerContext.scale(outputScale, outputScale);
const enhanceText = !!task.enhance;
// The text builder will draw its content on the test canvas
initPromise = page
Expand Down Expand Up @@ -672,15 +703,16 @@ class Driver {
annotationLayerCanvas = document.createElement("canvas");
this.annotationLayerCanvas = annotationLayerCanvas;
}
annotationLayerCanvas.width = viewport.width;
annotationLayerCanvas.height = viewport.height;
annotationLayerCanvas.width = pixelWidth;
annotationLayerCanvas.height = pixelHeight;
annotationLayerContext = annotationLayerCanvas.getContext("2d");
annotationLayerContext.clearRect(
0,
0,
annotationLayerCanvas.width,
annotationLayerCanvas.height
);
annotationLayerContext.scale(outputScale, outputScale);

if (!renderXfa) {
// The annotation builder will draw its content
Expand Down Expand Up @@ -709,6 +741,7 @@ class Driver {
viewport,
optionalContentConfigPromise: task.optionalContentConfigPromise,
annotationCanvasMap,
transform,
};
if (renderForms) {
renderContext.annotationMode = AnnotationMode.ENABLE_FORMS;
Expand All @@ -725,7 +758,7 @@ class Driver {
ctx.save();
ctx.globalCompositeOperation = "screen";
ctx.fillStyle = "rgb(128, 255, 128)"; // making it green
ctx.fillRect(0, 0, viewport.width, viewport.height);
ctx.fillRect(0, 0, pixelWidth, pixelHeight);
ctx.restore();
ctx.drawImage(textLayerCanvas, 0, 0);
}
Expand Down Expand Up @@ -755,6 +788,7 @@ class Driver {
Rasterize.annotationLayer(
annotationLayerContext,
viewport,
outputScale,
data,
annotationCanvasMap,
page,
Expand Down Expand Up @@ -864,6 +898,9 @@ class Driver {
page: task.pageNum,
snapshot,
stats: task.stats.times,
viewportWidth: task.viewportWidth,
viewportHeight: task.viewportHeight,
outputScale: task.outputScale,
});
this._send("/submit_task_results", result, callback);
}
Expand Down
4 changes: 2 additions & 2 deletions test/resources/reftest-analyzer.html
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ <h1>Reftest analyzer</h1>
</filter>
</defs>
<g id="magnify">
<image x="0" y="0" width="100%" height="100%" id="image1" />
<image x="0" y="0" width="100%" height="100%" id="image2" />
<image x="0" y="0" id="image1" />
<image x="0" y="0" id="image2" />
</g>
<rect id="diffrect" filter="url(#showDifferences)" pointer-events="none" x="0" y="0" width="100%" height="100%" />
</svg>
Expand Down
44 changes: 29 additions & 15 deletions test/resources/reftest-analyzer.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,10 +228,15 @@ window.onload = function () {
});
continue;
}
match = line.match(/^ {2}IMAGE[^:]*: (.*)$/);
match = line.match(/^ {2}IMAGE[^:]*\((\d+)x(\d+)x(\d+)\): (.*)$/);
if (match) {
const item = gTestItems[gTestItems.length - 1];
item.images.push(match[1]);
item.images.push({
width: parseFloat(match[1]),
height: parseFloat(match[2]),
outputScale: parseFloat(match[3]),
file: match[4],
});
}
}
buildViewer();
Expand Down Expand Up @@ -335,16 +340,31 @@ window.onload = function () {
const cell = ID("images");

ID("image1").style.display = "";
const scale = item.images[0].outputScale / window.devicePixelRatio;
ID("image1").setAttribute("width", item.images[0].width * scale);
ID("image1").setAttribute("height", item.images[0].height * scale);

ID("svg").setAttribute("width", item.images[0].width * scale);
ID("svg").setAttribute("height", item.images[0].height * scale);

ID("image2").style.display = "none";
if (item.images[1]) {
ID("image2").setAttribute("width", item.images[1].width * scale);
ID("image2").setAttribute("height", item.images[1].height * scale);
}
ID("diffrect").style.display = "none";
ID("imgcontrols").reset();

ID("image1").setAttributeNS(XLINK_NS, "xlink:href", gPath + item.images[0]);
ID("image1").setAttributeNS(
XLINK_NS,
"xlink:href",
gPath + item.images[0].file
);
// Making the href be #image1 doesn't seem to work
ID("feimage1").setAttributeNS(
XLINK_NS,
"xlink:href",
gPath + item.images[0]
gPath + item.images[0].file
);
if (item.images.length === 1) {
ID("imgcontrols").style.display = "none";
Expand All @@ -353,30 +373,24 @@ window.onload = function () {
ID("image2").setAttributeNS(
XLINK_NS,
"xlink:href",
gPath + item.images[1]
gPath + item.images[1].file
);
// Making the href be #image2 doesn't seem to work
ID("feimage2").setAttributeNS(
XLINK_NS,
"xlink:href",
gPath + item.images[1]
gPath + item.images[1].file
);
}
cell.style.display = "";
getImageData(item.images[0], function (data) {
getImageData(item.images[0].file, function (data) {
gImage1Data = data;
syncSVGSize(gImage1Data);
});
getImageData(item.images[1], function (data) {
getImageData(item.images[1].file, function (data) {
gImage2Data = data;
});
}

function syncSVGSize(imageData) {
ID("svg").setAttribute("width", imageData.width);
ID("svg").setAttribute("height", imageData.height);
}

function showImage(i) {
if (i === 1) {
ID("image1").style.display = "";
Expand Down Expand Up @@ -414,7 +428,7 @@ window.onload = function () {
}

function canvasPixelAsHex(data, x, y) {
const offset = (y * data.width + x) * 4;
const offset = (y * data.width + x) * 4 * window.devicePixelRatio;
const r = data.data[offset];
const g = data.data[offset + 1];
const b = data.data[offset + 2];
Expand Down
14 changes: 9 additions & 5 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,8 @@ function checkEq(task, results, browser, masterMode) {
if (!pageResults[page]) {
continue;
}
var testSnapshot = pageResults[page].snapshot;
const pageResult = pageResults[page];
let testSnapshot = pageResult.snapshot;
if (testSnapshot && testSnapshot.startsWith("data:image/png;base64,")) {
testSnapshot = Buffer.from(testSnapshot.substring(22), "base64");
} else {
Expand Down Expand Up @@ -492,8 +493,8 @@ function checkEq(task, results, browser, masterMode) {
refSnapshot
);

// NB: this follows the format of Mozilla reftest output so that
// we can reuse its reftest-analyzer script
// This no longer follows the format of Mozilla reftest output.
const viewportString = `(${pageResult.viewportWidth}x${pageResult.viewportHeight}x${pageResult.outputScale})`;
fs.appendFileSync(
eqLog,
"REFTEST TEST-UNEXPECTED-FAIL | " +
Expand All @@ -503,10 +504,10 @@ function checkEq(task, results, browser, masterMode) {
"-page" +
(page + 1) +
" | image comparison (==)\n" +
"REFTEST IMAGE 1 (TEST): " +
`REFTEST IMAGE 1 (TEST)${viewportString}: ` +
path.join(testSnapshotDir, page + 1 + ".png") +
"\n" +
"REFTEST IMAGE 2 (REFERENCE): " +
`REFTEST IMAGE 2 (REFERENCE)${viewportString}: ` +
path.join(testSnapshotDir, page + 1 + "_ref.png") +
"\n"
);
Expand Down Expand Up @@ -735,6 +736,9 @@ function refTestPostHandler(req, res) {
taskResults[round][page] = {
failure,
snapshot,
viewportWidth: data.viewportWidth,
viewportHeight: data.viewportHeight,
outputScale: data.outputScale,
};
if (stats) {
stats.push({
Expand Down
12 changes: 12 additions & 0 deletions test/test_manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6115,6 +6115,18 @@
"forms": true,
"lastPage": 1
},
{
"id": "issue12716-hidpi",
"file": "pdfs/issue12716.pdf",
"md5": "9bdc9c552bcfccd629f5f97385e79ca5",
"rounds": 1,
"link": true,
"type": "eq",
"forms": true,
"lastPage": 1,
"outputScale": 2,
"about": "This tests draws to another canvas for the button, so it's a good test to ensure output scale is working."
},
{ "id": "xfa_issue13500",
"file": "pdfs/xfa_issue13500.pdf",
"md5": "b81274a19f5a95c1466db3648f1be491",
Expand Down