Update web-platform-tests to revision d8b8e0b8efe993a37404d6c6fc75e16fdc16b7d8

This commit is contained in:
WPT Sync Bot 2018-10-25 21:32:39 -04:00
parent abc0f50d20
commit e07315e6af
221 changed files with 7334 additions and 774 deletions

View file

@ -61,7 +61,7 @@ tasks:
owner: ${event.pusher.email}
source: ${event.repository.url}
payload:
image: jugglinmike/web-platform-tests:0.21
image: harjgam/web-platform-tests:0.22
maxRunTime: 7200
artifacts:
public/results:

View file

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<title>createImageBitmap: blob with wrong mime type</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/canvas-tests.js"></script>
<script>
promise_test(t => {
// Source: https://commons.wikimedia.org/wiki/File:1x1.png (Public Domain)
const IMAGE = atob("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABAQMAAAAl21bKAAAAA1BMVEUAA" +
"ACnej3aAAAAAXRSTlMAQObYZgAAAApJREFUCNdjYAAAAAIAAeIhvDMAAAAASUVORK5CYII=");
let bytes = new Array(IMAGE.length);
for (let i = 0; i < IMAGE.length; i++) {
bytes[i] = IMAGE.charCodeAt(i);
}
let blob = new Blob([new Uint8Array(bytes)], { type: "text/html"});
return window.createImageBitmap(blob)
.then(imageBitmap => {
assert_true(true, "Image created!");
assert_equals(imageBitmap.width, 1, "Image is 1x1");
assert_equals(imageBitmap.height, 1, "Image is 1x1");
});
});
</script>

View file

@ -49,7 +49,7 @@ function makeAvailableButBrokenImage(path) {
testCases = [
{
description: 'createImageBitmap with a <sourceType> source and sw set to 0',
description: 'createImageBitmap with <sourceType> source and sw set to 0',
promiseTestFunction:
(source, t) => {
return promise_rejects(t, new RangeError(),
@ -57,7 +57,7 @@ testCases = [
}
},
{
description: 'createImageBitmap with a <sourceType> source and sh set to 0',
description: 'createImageBitmap with <sourceType> source and sh set to 0',
promiseTestFunction:
(source, t) => {
return promise_rejects(t, new RangeError(),
@ -65,17 +65,23 @@ testCases = [
}
},
{
// This case is not explicitly documented in the specification for
// createImageBitmap, but it is expected that internal failures cause
// InvalidStateError.
//
// Note: https://bugs.chromium.org/p/chromium/issues/detail?id=799025
description: 'createImageBitmap with a <sourceType> source and oversized ' +
description: 'createImageBitmap with <sourceType> source and oversized ' +
'(unallocatable) crop region',
promiseTestFunction:
(source, t) => {
return promise_rejects(t, new DOMException('', 'InvalidStateError'),
createImageBitmap(source, 0, 0, 100000000, 100000000));
return createImageBitmap(source, 0, 0, 100000000, 100000000)
.then(i => {
assert_equals(i.width, 100000000);
assert_equals(i.height, 100000000);
})
.catch(e => {
// This case is not explicitly documented in the specification for
// createImageBitmap, but it is expected that internal failures
// cause InvalidStateError.
//
// Note: https://bugs.chromium.org/p/chromium/issues/detail?id=799025
assert_throws("InvalidStateError", () => { throw e });
});
}
},
];

View file

@ -0,0 +1,126 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
async_test(function(t) {
var image = new Image();
// This image is 256 by 1 and contains an opaque grayscale ramp from 0 to 255.
// The image has no embedded color profile.
image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAABCAYAAAAx" +
"WXB3AAAAG0lEQVQ4T2NkYGD4z8jIyDCKR8NgNA2MvDQAAPiPA/5tZ8G+AAAAAElFTkSuQmCC";
image.onload = function() {
var canvas = document.createElement('canvas');
canvas.width = 256;
canvas.height = 1;
var ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0);
var img = ctx.getImageData(0, 0, 256, 1);
t.step(function() {
for (var i = 0; i < 256; i++) {
assert_equals(img.data[4 * i], i, "red component");
assert_equals(img.data[4 * i + 1], i, "green component");
assert_equals(img.data[4 * i + 2], i, "blue component");
assert_equals(img.data[4 * i + 3], 255, "alpha component");
}
});
t.done();
}
}, "Verify that drawImage->getImageData round trip preserves color values " +
"when image metadata has no color space and canvas uses the default " +
"color space.");
async_test(function(t) {
var image = new Image();
// This image is 256 by 1 and contains an opaque grayscale ramp from 0 to 255.
// The image has an embedded sRGB color profile.
image.src =
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAABCAYAAAAxWXB3AAAA" +
"G0lEQVQ4T2NkYGD4z8jIyDCKR8NgNA2MvDQAAPiPA/5tZ8G+AAAAo3pUWHRSYXcgcHJvZm" +
"lsZSB0eXBlIEFQUDEAAHicZU5bCsMwDPv3KXoEv/I6TrampTC20ft/LE7WETJBkK1YQrCX" +
"ZzmP+/I+X9vxKLAYyCGoC9En77FCV10ROWNHrM8hUW7cQZ00V/026tDZMRKbUQYDt4lJJr" +
"2FxeCTJc5BV4svNE4Nxl1Tn8N1LCgMIoKJ2sHvo25sHfK/odYT02luCWMP+AA5M0KbNr61" +
"PwAAAABJRU5ErkJggg==";
image.onload = function() {
var canvas = document.createElement('canvas');
canvas.width = 256;
canvas.height = 1;
var ctx = canvas.getContext('2d', {colorSpace: 'srgb'});
ctx.drawImage(image, 0, 0);
var img = ctx.getImageData(0, 0, 256, 1);
t.step(function() {
for (var i = 0; i < 256; i++) {
assert_equals(img.data[4 * i], i, "red component");
assert_equals(img.data[4 * i + 1], i, "green component");
assert_equals(img.data[4 * i + 2], i, "blue component");
assert_equals(img.data[4 * i + 3], 255, "alpha component");
}
});
t.done();
}
}, "Verify that drawImage->getImageData round trip preserves color values " +
"when image metadata has srgb color space and canvas uses the srgb " +
"color space.");
async_test(function(t) {
var image = new Image();
// This image is 256 by 1 and contains an opaque grayscale ramp from 0 to 255.
// The image has no embedded color profile.
image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAABCAYAAAAx" +
"WXB3AAAAG0lEQVQ4T2NkYGD4z8jIyDCKR8NgNA2MvDQAAPiPA/5tZ8G+AAAAAElFTkSuQmCC";
image.onload = function() {
var canvas = document.createElement('canvas');
canvas.width = 256;
canvas.height = 1;
var ctx = canvas.getContext('2d', {colorSpace: 'srgb'});
ctx.drawImage(image, 0, 0);
var img = ctx.getImageData(0, 0, 256, 1);
t.step(function() {
for (var i = 0; i < 256; i++) {
assert_equals(img.data[4 * i], i, "red component");
assert_equals(img.data[4 * i + 1], i, "green component");
assert_equals(img.data[4 * i + 2], i, "blue component");
assert_equals(img.data[4 * i + 3], 255, "alpha component");
}
});
t.done();
}
}, "Verify that drawImage->getImageData round trip preserves color values " +
"when image metadata has no color space and canvas uses the srgb " +
"color space.");
async_test(function(t) {
var image = new Image();
// This image is 256 by 1 and contains an opaque grayscale ramp from 0 to 255.
// The image has an embedded sRGB color profile.
image.src =
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAABCAYAAAAxWXB3AAAA" +
"G0lEQVQ4T2NkYGD4z8jIyDCKR8NgNA2MvDQAAPiPA/5tZ8G+AAAAo3pUWHRSYXcgcHJvZm" +
"lsZSB0eXBlIEFQUDEAAHicZU5bCsMwDPv3KXoEv/I6TrampTC20ft/LE7WETJBkK1YQrCX" +
"ZzmP+/I+X9vxKLAYyCGoC9En77FCV10ROWNHrM8hUW7cQZ00V/026tDZMRKbUQYDt4lJJr" +
"2FxeCTJc5BV4svNE4Nxl1Tn8N1LCgMIoKJ2sHvo25sHfK/odYT02luCWMP+AA5M0KbNr61" +
"PwAAAABJRU5ErkJggg==";
image.onload = function() {
var canvas = document.createElement('canvas');
canvas.width = 256;
canvas.height = 1;
var ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0);
var img = ctx.getImageData(0, 0, 256, 1);
t.step(function() {
for (var i = 0; i < 256; i++) {
assert_equals(img.data[4 * i], i, "red component");
assert_equals(img.data[4 * i + 1], i, "green component");
assert_equals(img.data[4 * i + 2], i, "blue component");
assert_equals(img.data[4 * i + 3], 255, "alpha component");
}
});
t.done();
}
}, "Verify that drawImage->getImageData round trip preserves color values " +
"when image metadata has srgb color space and canvas uses the default " +
"color space.");
</script>

View file

@ -0,0 +1,149 @@
<!DOCTYPE HTML>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
// No matter what is the color space and pixel format of the color managed
// canvas, toBlob() and toDataURL() always create the blob in sRGB color
// space, and respect the legacy behavior by not including any color space
// information in the blob/data url.
var opaqueReferencePxiels, transparentReferencePixels;
function testPixels(actualPixels, refPixels, testScenario)
{
// Narrowing down the source of expected error:
// - Alpha values should always match.
// - Color components should be acceptably close.
if (testScenario.canvasColorParam.pixelFormat == 'uint8') {
let tolerance_color = 4;
for (let i = 0; i < actualPixels.length; i++) {
// Alpha channel
if (i % 4 == 3)
assert_equals(actualPixels[i], refPixels[i]);
else
assert_approx_equals(actualPixels[i], refPixels[i], tolerance_color);
}
} else {
// For half float backed canvas, we expect the error < 0.01.
let tolerance_color = 0.01;
for (let i = 0; i < actualPixels.length; i++) {
// Alpha channel
if (i % 4 == 3)
assert_equals(actualPixels[i], refPixels[i]);
else
assert_approx_equals(actualPixels[i], refPixels[i], tolerance_color);
}
}
}
function createCanvas(testScenario)
{
var canvas = document.createElement("canvas");
canvas.width = 2;
canvas.height = 2;
return canvas;
}
function generateFillStyle(red, green, blue, alpha) {
return "rgba(" + red + "," + green + "," + blue + "," + alpha + ")";
}
function drawPatternOnCanvsa(ctx, alpha, compositeOverBlack) {
if (compositeOverBlack) {
ctx.fillStyle = generateFillStyle(0, 0, 0, 1);
ctx.fillRect(0, 0, 2, 2);
}
ctx.fillStyle = generateFillStyle(155, 27, 27, alpha);
ctx.fillRect(0, 0, 1, 1);
ctx.fillStyle = generateFillStyle(27, 155, 27, alpha);
ctx.fillRect(1, 0, 1, 1);
ctx.fillStyle = generateFillStyle(27, 27, 155, alpha);
ctx.fillRect(0, 1, 1, 1);
ctx.fillStyle = generateFillStyle(27, 27, 27, alpha);
ctx.fillRect(1, 1, 1, 1);
}
function testScenarioToString(testScenario) {
var str = "mimeType: " + testScenario.encodeOptions.type +
", blobPixelFormat: " + testScenario.encodeOptions.pixelFormat +
", source color space: " + testScenario.canvasColorParam.colorSpace +
", pixel format: " + testScenario.canvasColorParam.pixelFormat +
", alpha: " + testScenario.alpha;
return str;
}
function runConvertToBlobTest(testScenario) {
var srcCanvas = createCanvas(testScenario);
var ctx = srcCanvas.getContext('2d', testScenario.canvasColorParam);
var compositeOverBlack = (testScenario.encodeOptions.type == "image/jpeg");
drawPatternOnCanvsa(ctx, testScenario.alpha, compositeOverBlack);
var refPixels = ctx.getImageData(0, 0, 2, 2).dataUnion;
var t = async_test("Test canvas convertToBlob(): " +
testScenarioToString(testScenario));
var image = new Image();
image.onload = t.step_func_done(function() {
var dstCanvas = createCanvas(testScenario);
var dstCtx = dstCanvas.getContext('2d', testScenario.canvasColorParam);
dstCtx.drawImage(image, 0, 0);
var actualPixels = dstCtx.getImageData(0, 0, 2, 2).dataUnion;
testPixels(actualPixels, refPixels, testScenario);
});
srcCanvas.convertToBlob(testScenario.encodeOptions).then(
t.step_func(function(blob) {
var urlCreator = window.URL || window.webkitURL;
image.src = urlCreator.createObjectURL(blob);
}),
t.step_func_done(function(e) {
assert_false("convertToBlob failed.");
})
);
}
function runAllTests() {
var mimeTypes = ['image/png', 'image/jpeg', 'image/webp'];
var blobPixelFormats = ['uint8', 'uint16'];
var encodeOptionsSet = [];
for (var i = 0; i < mimeTypes.length; i++)
for (var k = 0; k < blobPixelFormats.length; k++) {
var encodeOptions = {};
encodeOptions.quality = 1;
encodeOptions.type = mimeTypes[i];
encodeOptions.pixelFormat = blobPixelFormats[k];
encodeOptionsSet.push(encodeOptions);
}
var canvasColorParams = [
{colorSpace: 'srgb', pixelFormat: 'uint8'},
{colorSpace: 'srgb', pixelFormat: 'float16'},
];
var alphaValues = [0.5, 1];
// The *correct* way to test convertToBlob() is to directly examine the
// image file for the expected color space and pixels. Since this is not
// easy to do in javascript, we use a round-trip test here and leave the
// more thorough testing to unit tests.
var testScenarioSet = [];
for (var i = 0; i < encodeOptionsSet.length; i++)
for (var j = 0; j < canvasColorParams.length; j++)
for (var k = 0; k < alphaValues.length; k++) {
var testScenario = {};
testScenario.encodeOptions = encodeOptionsSet[i];
testScenario.canvasColorParam = canvasColorParams[j];
testScenario.alpha = alphaValues[k];
testScenarioSet.push(testScenario);
}
for (var i = 0; i < testScenarioSet.length; i++)
runConvertToBlobTest(testScenarioSet[i]);
}
runAllTests();
</script>

View file

@ -0,0 +1,145 @@
<!DOCTYPE HTML>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
// No matter what is the color space and pixel format of the color managed
// canvas, toBlob() and toDataURL() always create the blob in sRGB color
// space, and respect the legacy behavior by not including any color space
// information in the blob/data url.
var opaqueReferencePxiels, transparentReferencePixels;
function testPixels(actualPixels, alpha)
{
if (alpha == 1)
assert_array_approx_equals(actualPixels, opaqueReferencePxiels, 1);
else
assert_array_approx_equals(actualPixels, transparentReferencePixels, 2);
}
function generateFillStyle(red, green, blue, alpha) {
return "rgba(" + red + "," + green + "," + blue + "," + alpha + ")";
}
function contextDrawHelper(ctx, alpha) {
ctx.fillStyle = generateFillStyle(155, 27, 27, alpha);
ctx.fillRect(0, 0, 1, 1);
ctx.fillStyle = generateFillStyle(27, 155, 27, alpha);
ctx.fillRect(1, 0, 1, 1);
ctx.fillStyle = generateFillStyle(27, 27, 155, alpha);
ctx.fillRect(0, 1, 1, 1);
ctx.fillStyle = generateFillStyle(27, 27, 27, alpha);
ctx.fillRect(1, 1, 1, 1);
}
function prepareReferenceExpectedResults() {
var canvas1 = document.createElement("canvas");
canvas1.width = 2;
canvas1.height = 2;
var ctx1 = canvas1.getContext('2d');
contextDrawHelper(ctx1, 1);
opaqueReferencePxiels = ctx1.getImageData(0, 0, 2, 2).data;
var canvas2 = document.createElement("canvas");
canvas2.width = 2;
canvas2.height = 2;
var ctx2 = canvas2.getContext('2d');
contextDrawHelper(ctx2, 0.5);
transparentReferencePixels = ctx2.getImageData(0, 0, 2, 2).data;
}
function createCanvas(testScenario)
{
var canvas = document.createElement("canvas");
canvas.width = 2;
canvas.height = 2;
var ctx = canvas.getContext('2d', {colorSpace: testScenario.colorSpace,
pixelFormat: testScenario.pixelFormat});
contextDrawHelper(ctx, testScenario.alpha);
return canvas;
}
function testScenarioToString(testScenario) {
var str = "ImageFormat: " + testScenario.imageFormat +
", source color space: " + testScenario.colorSpace +
", pixel format: " + testScenario.pixelFormat +
", alpha: " + testScenario.alpha;
if (testScenario.hasOwnProperty('colorSpaceConversion'))
str = str + ", intermediate color space: " +
testScenario.colorSpaceConversion;
return str;
}
function runToBlobTest(testScenario) {
var srcCanvas = createCanvas(testScenario);
var t_blob = async_test("Test if toBlob() respects legacy behavior in \
color managed canvas: " + testScenarioToString(testScenario));
var image = new Image();
image.onload = t_blob.step_func_done(function() {
var dstCanvas = document.createElement("canvas");
dstCanvas.width = 2;
dstCanvas.height = 2;
var ctx = dstCanvas.getContext('2d');
ctx.drawImage(image, 0, 0);
var actualPixels = ctx.getImageData(0, 0, 2, 2).data;
testPixels(actualPixels, testScenario.alpha);
});
srcCanvas.toBlob(function(blob) {
var urlCreator = window.URL || window.webkitURL;
image.src = urlCreator.createObjectURL(blob);
}, 'image/png', 1);
}
function runToDataURLTest(testScenario) {
var srcCanvas = createCanvas(testScenario);
var t_dataURL = async_test("Test if toDataURL() respects legacy behavior \
in color managed canvas: " + testScenarioToString(testScenario));
var image = new Image();
image.onload = t_dataURL.step_func_done(function() {
var dstCanvas = document.createElement("canvas");
dstCanvas.width = 2;
dstCanvas.height = 2;
var ctx = dstCanvas.getContext('2d');
ctx.drawImage(image, 0, 0);
var actualPixels = ctx.getImageData(0, 0, 2, 2).data;
testPixels(actualPixels, testScenario.alpha);
});
image.src = srcCanvas.toDataURL();
}
function runAllTests() {
prepareReferenceExpectedResults();
var imageFormats = ['image/jpeg', 'image/png', 'image/webp'];
var colorSpaces = [
{colorSpace: 'srgb', pixelFormat: 'uint8'},
{colorSpace: 'srgb', pixelFormat: 'float16'},
];
var alphaValues = [0.5, 1];
var testScenarioSet = [];
for (var i = 0; i < imageFormats.length; i++)
for (var j = 0; j < colorSpaces.length; j++)
for (var k = 0; k < alphaValues.length; k++) {
var testScenario = {};
testScenario.imageFormat = imageFormats[i];
testScenario.colorSpace = colorSpaces[j].colorSpace;
testScenario.pixelFormat = colorSpaces[j].pixelFormat;
testScenario.alpha = alphaValues[k];
testScenarioSet.push(testScenario);
}
for (var i = 0; i < testScenarioSet.length; i++)
runToBlobTest(testScenarioSet[i]);
for (var i = 0; i < testScenarioSet.length; i++)
runToDataURLTest(testScenarioSet[i]);
}
runAllTests();
</script>

View file

@ -0,0 +1,48 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
var testScenarios = [
{testDescription: "Test default context creation parameters: srgb/uint8",
canvasColorSettings: {},
expectedColorSettings: {colorSpace: "srgb", pixelFormat: "uint8"}},
{testDescription: "Test CanvasColorSpace value srgb",
canvasColorSettings: {colorSpace: "srgb"},
expectedColorSettings: {colorSpace: "srgb", pixelFormat: "uint8"}},
{testDescription: "Test CanvasPixelFormat value uint8",
canvasColorSettings: {pixelFormat: "uint8"},
expectedColorSettings: {colorSpace: "srgb", pixelFormat: "uint8"}},
{testDescription: "Test CanvasPixelFormat value float16",
canvasColorSettings: {pixelFormat: "float16"},
expectedColorSettings: {colorSpace: "srgb", pixelFormat: "float16"}},
{testDescription: "Test supported color settings srgb/uint8",
canvasColorSettings: {colorSpace: "srgb", pixelFormat: "uint8"},
expectedColorSettings: {colorSpace: "srgb", pixelFormat: "uint8"}},
{testDescription: "Test supported color settings srgb/float16",
canvasColorSettings: {colorSpace: "srgb", pixelFormat: "float16"},
expectedColorSettings: {colorSpace: "srgb", pixelFormat: "float16"}},
];
function runTestScenario(testScenario) {
var t = test(function() {
var canvas = document. createElement('canvas');
var ctx = canvas.getContext('2d', testScenario.canvasColorSettings);
var contextAttributes = ctx.getContextAttributes();
assert_equals(contextAttributes.colorSpace,
testScenario.expectedColorSettings.colorSpace);
assert_equals(contextAttributes.pixelFormat,
testScenario.expectedColorSettings.pixelFormat);
}, testScenario.testDescription);
}
function runAllTests() {
for (var i = 0; i < testScenarios.length; i++)
runTestScenario(testScenarios[i]);
}
runAllTests();
</script>

View file

@ -0,0 +1,579 @@
<!DOCTYPE HTML>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
var transparentBlack = [0, 0, 0, 0];
var e_sRGB_Red = [1, 0, 0, 1]; // sRGB(255,0,0,255)
var e_sRGB_Green = [0, 1, 0, 1]; // sRGB(0,255,0,255)
var e_sRGB_Blue = [0, 0, 1, 1]; // sRGB(0,0,255,255)
var e_sRGB_Black = [0, 0, 0, 1]; // sRGB(0,0,0,255)
// sRGB(155,27,27,255)
var e_sRGB_OpaqueRed = [0.607422, 0.105835, 0.105835, 1];
// sRGB(27,155,27,255)
var e_sRGB_OpaqueGreen = [0.105835, 0.607422, 0.105835, 1];
// sRGB(27,27,155,255)
var e_sRGB_OpaqueBlue = [0.105835, 0.105835, 0.607422, 1];
// sRGB(27,27,27,255)
var e_sRGB_OpaqueBlack = [0.105835, 0.105835, 0.105835, 1];
// sRGB(155,27,27,128)
var e_sRGB_TransparentRed = [0.607422, 0.105835, 0.105835, 0.501953];
// sRGB(27, 155, 27, 128)
var e_sRGB_TransparentGreen = [0.105835, 0.607422, 0.105835, 0.501953];
// sRGB(27, 27, 155, 128)
var e_sRGB_TransparentBlue = [0.105835, 0.105835, 0.607422, 0.501953];
// sRGB(27, 27, 27, 128)
var e_sRGB_TransparentBlack = [0.105835, 0.105835, 0.105835, 0.501953];
// sRGB(226,31,31,128)
var e_sRGB_TransparentRedImage = [0.886230, 0.121521, 0.121521, 0.501953];
// sRGB(226,31,31,128)
var e_sRGB_TransparentGreenImage = [0.121521, 0.886230, 0.121521, 0.501953];
// sRGB(226,31,31,128)
var e_sRGB_TransparentBlueImage = [0.121521, 0.121521, 0.886230, 0.501953];
// sRGB(226,31,31,128)
var e_sRGB_TransparentBlackImage = [0.121521, 0.121521, 0.121521, 0.501953];
function testPixels(ctx, tests, sourceType)
{
var actual, expected, tolerance = 0.025;
if (sourceType === 'video')
tolerance = 0.03;
for (var i = 0; i < tests.length; i++) {
actual = ctx.getImageData(tests[i][0], tests[i][1], 1, 1).dataUnion;
expected = tests[i][2];
assert_true(actual.length === expected.length);
for (var j = 0; j < actual.length; j++)
assert_approx_equals(actual[j], expected[j], tolerance, tests[i][3]);
}
}
function checkNoCrop(imageBitmap, colorInfo, sourceType)
{
var canvas = document.createElement('canvas');
canvas.width = 50;
canvas.height = 50;
var ctx = canvas.getContext('2d',
{colorSpace: 'srgb', pixelFormat:'float16'});
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(imageBitmap, 0, 0);
var tests;
if (colorInfo == 'fullColor')
tests = [[0, 0, e_sRGB_Red, "This pixel should be e-sRGB red."],
[39, 0, e_sRGB_Green, "This pixel should be e-sRGB green."],
[0, 39, e_sRGB_Blue, "This pixel should be e-sRGB blue."],
[39, 39, e_sRGB_Black, "This pixel should be e-sRGB black."],
[41, 41, transparentBlack, "This pixel should be transparent black."]];
else if (colorInfo == 'opaque')
tests = [[0, 0, e_sRGB_OpaqueRed,
"This pixel should be e-sRGB like red."],
[39, 0, e_sRGB_OpaqueGreen,
"This pixel should be e-sRGB like green."],
[0, 39, e_sRGB_OpaqueBlue,
"This pixel should be e-sRGB like blue."],
[39, 39, e_sRGB_OpaqueBlack,
"This pixel should be e-sRGB like black."],
[41, 41, transparentBlack, "This pixel should be transparent black."]];
else if (colorInfo == 'transparent')
tests = [[0, 0, e_sRGB_TransparentRed,
"This pixel should be e-sRGB transparent red."],
[39, 0, e_sRGB_TransparentGreen,
"This pixel should be e-sRGB transparent green."],
[0, 39, e_sRGB_TransparentBlue,
"This pixel should be e-sRGB transparent blue."],
[39, 39, e_sRGB_TransparentBlack,
"This pixel should be e-sRGB transparent black."],
[41, 41, transparentBlack,
"This pixel should be transparent black."]];
else if (colorInfo === 'transparent-image')
tests = [[0, 0, e_sRGB_TransparentRedImage,
"This pixel should be e-sRGB transparent red."],
[39, 0, e_sRGB_TransparentGreenImage,
"This pixel should be e-sRGB transparent green."],
[0, 39, e_sRGB_TransparentBlueImage,
"This pixel should be e-sRGB transparent blue."],
[39, 39, e_sRGB_TransparentBlackImage,
"This pixel should be e-sRGB transparent black."],
[41, 41, transparentBlack,
"This pixel should be transparent black."]];
testPixels(ctx, tests, sourceType);
}
function checkCrop(imageBitmap, colorInfo, sourceType)
{
var canvas = document.createElement('canvas');
canvas.width = 50;
canvas.height = 50;
var ctx = canvas.getContext('2d',
{colorSpace: 'srgb', pixelFormat:'float16'});
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(imageBitmap, 0, 0);
var tests;
if (colorInfo === 'fullColor')
tests = [[0, 0, e_sRGB_Red, "This pixel should be e-sRGB red."],
[19, 0, e_sRGB_Green, "This pixel should be e-sRGB green."],
[0, 19, e_sRGB_Blue, "This pixel should be e-sRGB blue."],
[19, 19, e_sRGB_Black, "This pixel should be e-sRGB black."],
[21, 21, transparentBlack, "This pixel should be transparent black."]];
else if (colorInfo === 'opaque')
tests = [[0, 0, e_sRGB_OpaqueRed,
"This pixel should be e-sRGB like red."],
[19, 0, e_sRGB_OpaqueGreen,
"This pixel should be e-sRGB like green."],
[0, 19, e_sRGB_OpaqueBlue,
"This pixel should be e-sRGB like blue."],
[19, 19, e_sRGB_OpaqueBlack,
"This pixel should be e-sRGB like black."],
[21, 21, transparentBlack, "This pixel should be transparent black."]];
else if (colorInfo === 'transparent')
tests = [[0, 0, e_sRGB_TransparentRed,
"This pixel should be e-sRGB transparent red."],
[19, 0, e_sRGB_TransparentGreen,
"This pixel should be e-sRGB transparent green."],
[0, 19, e_sRGB_TransparentBlue,
"This pixel should be e-sRGB transparent blue."],
[19, 19, e_sRGB_TransparentBlack,
"This pixel should be e-sRGB transparent black."],
[21, 21, transparentBlack,
"This pixel should be transparent black."]];
else if (colorInfo === 'transparent-image')
tests = [[0, 0, e_sRGB_TransparentRedImage,
"This pixel should be e-sRGB transparent red."],
[19, 0, e_sRGB_TransparentGreenImage,
"This pixel should be e-sRGB transparent green."],
[0, 19, e_sRGB_TransparentBlueImage,
"This pixel should be e-sRGB transparent blue."],
[19, 19, e_sRGB_TransparentBlackImage,
"This pixel should be e-sRGB transparent black."],
[21, 21, transparentBlack,
"This pixel should be transparent black."]];
testPixels(ctx, tests, sourceType);
}
function compareBitmaps(bitmap1, bitmap2)
{
var canvas1 = document.createElement('canvas');
var canvas2 = document.createElement('canvas');
canvas1.width = 50;
canvas1.height = 50;
canvas2.width = 50;
canvas2.height = 50;
var ctx1 = canvas1.getContext('2d',
{colorSpace: 'srgb', pixelFormat:'float16'});
var ctx2 = canvas2.getContext('2d',
{colorSpace: 'srgb', pixelFormat:'float16'});
ctx1.clearRect(0, 0, canvas1.width, canvas1.height);
ctx2.clearRect(0, 0, canvas2.width, canvas2.height);
ctx1.drawImage(bitmap1, 0, 0);
ctx2.drawImage(bitmap2, 0, 0);
var data1 = ctx1.getImageData(0, 0, 50, 50).dataUnion;
var data2 = ctx2.getImageData(0, 0, 50, 50).dataUnion;
var dataMatched = true;
for (var i = 0; i < data1.length; i++) {
if (data1[i] != data2[i]) {
dataMatched = false;
break;
}
}
assert_false(dataMatched);
}
function testImageBitmap(source, colorInfo, sourceType)
{
return Promise.all([
createImageBitmap(source, {colorSpaceConversion: "srgb",
resizeWidth: 40, resizeHeight: 40, resizeQuality: "high"}),
createImageBitmap(source, {colorSpaceConversion: "srgb",
resizeWidth: 40, resizeHeight: 40, resizeQuality: "medium"}),
createImageBitmap(source, {colorSpaceConversion: "srgb",
resizeWidth: 40, resizeHeight: 40, resizeQuality: "low"}),
createImageBitmap(source, {colorSpaceConversion: "srgb",
resizeWidth: 40, resizeHeight: 40, resizeQuality: "pixelated"}),
createImageBitmap(source, 5, 5, 10, 10, {
colorSpaceConversion: "srgb",
resizeWidth: 20, resizeHeight: 20, resizeQuality: "high"}),
createImageBitmap(source, 5, 5, 10, 10, {
colorSpaceConversion: "srgb",
resizeWidth: 20, resizeHeight: 20, resizeQuality: "medium"}),
createImageBitmap(source, 5, 5, 10, 10, {
colorSpaceConversion: "srgb",
resizeWidth: 20, resizeHeight: 20, resizeQuality: "low"}),
createImageBitmap(source, 5, 5, 10, 10, {
colorSpaceConversion: "srgb",
resizeWidth: 20, resizeHeight: 20, resizeQuality: "pixelated"}),
]).then(([noCropHigh, noCropMedium, noCropLow, noCropPixelated, cropHigh,
cropMedium, cropLow, cropPixelated]) => {
checkNoCrop(noCropHigh, colorInfo, sourceType);
checkNoCrop(noCropMedium, colorInfo, sourceType);
checkNoCrop(noCropLow, colorInfo, sourceType);
checkNoCrop(noCropPixelated, colorInfo, sourceType);
checkCrop(cropHigh, colorInfo, sourceType);
checkCrop(cropMedium, colorInfo, sourceType);
checkCrop(cropLow, colorInfo, sourceType);
checkCrop(cropPixelated, colorInfo, sourceType);
// Brute-force comparison among all bitmaps is too expensive.
// In case of SVG, resize quality does not affect the images, so all
// of them are the same and the tests fail. Since, we ignore this test
// set for SVG.
if (sourceType != 'svg') {
compareBitmaps(noCropHigh, noCropMedium);
compareBitmaps(noCropLow, noCropPixelated);
compareBitmaps(cropHigh, cropMedium);
compareBitmaps(cropLow, cropPixelated);
}
});
}
function testImageBitmapTransparent(source)
{
return testImageBitmap(source, 'transparent', 'general');
}
function testImageBitmapFromTransparentImage(source)
{
return testImageBitmap(source, 'transparent-image', 'general');
}
function testImageBitmapVideoSource(source)
{
return testImageBitmap(source, 'fullColor', 'video');
}
function testImageBitmapOpaque(source)
{
return testImageBitmap(source, 'opaque', 'general');
}
function testImageBitmapFromSVG(source)
{
return testImageBitmap(source, 'opaque', 'svg');
}
function initializeTestCanvas(canvasColorSpace, canvasPixelFormat)
{
var testCanvas = document.createElement("canvas");
testCanvas.width = 20;
testCanvas.height = 20;
var testCtx = testCanvas.getContext('2d',
{colorSpace: canvasColorSpace, pixelFormat:canvasPixelFormat});
testCtx.fillStyle = "rgba(155, 27, 27, 1)";
testCtx.fillRect(0, 0, 10, 10);
testCtx.fillStyle = "rgba(27, 155, 27, 1)";
testCtx.fillRect(10, 0, 10, 10);
testCtx.fillStyle = "rgba(27, 27, 155, 1)";
testCtx.fillRect(0, 10, 10, 10);
testCtx.fillStyle = "rgba(27, 27, 27, 1)";
testCtx.fillRect(10, 10, 10, 10);
return testCanvas;
}
function initializeTestCanvasTransparent(canvasColorSpace, canvasPixelFormat)
{
var testCanvas = document.createElement("canvas");
testCanvas.width = 20;
testCanvas.height = 20;
var testCtx = testCanvas.getContext('2d',
{colorSpace: canvasColorSpace, pixelFormat:canvasPixelFormat});
testCtx.fillStyle = "rgba(155, 27, 27, 0.5)";
testCtx.fillRect(0, 0, 10, 10);
testCtx.fillStyle = "rgba(27, 155, 27, 0.5)";
testCtx.fillRect(10, 0, 10, 10);
testCtx.fillStyle = "rgba(27, 27, 155, 0.5)";
testCtx.fillRect(0, 10, 10, 10);
testCtx.fillStyle = "rgba(27, 27, 27, 0.5)";
testCtx.fillRect(10, 10, 10, 10);
return testCanvas;
}
////////////////////////////////////////////////////////////////////////////////
// HTMLImageElement - Opaque sRGB
// File formats: Bitmap, GIF, ICO, JPEG, PNG, WEBP
promise_test(function() {
return Promise.all(['bmp', 'gif', 'ico', 'jpg', 'png', 'webp'].map(
ext => new Promise((resolve,reject) => {
var image = new Image();
image.onload = function() {
resolve(image);
}
image.src = 'resources/pattern-srgb.' + ext;
}).then(testImageBitmapOpaque)));
}, 'createImageBitmap in e-sRGB from an opaque sRGB HTMLImageElement (BMP, \
GIF, ICO, JPG, PNG, WEBP) with resize.');
// HTMLImageElement - Transparent sRGB
// File formats: Bitmap, GIF, ICO, PNG, WEBP
promise_test(function() {
return Promise.all(['bmp', 'ico', 'png', 'webp'].map(
ext => new Promise((resolve,reject) => {
var image = new Image();
image.onload = function() {
resolve(image);
}
image.src = 'resources/pattern-srgb-transparent.' + ext;
}).then(testImageBitmapFromTransparentImage)));
}, 'createImageBitmap in e-sRGB from a transparent sRGB HTMLImageElement \
(BMP, ICO, PNG, WEBP) with resize.');
////////////////////////////////////////////////////////////////////////////////
// SVG Image - sRGB
promise_test(function() {
return new Promise((resolve, reject) => {
var image = new Image();
image.onload = function() {
resolve(image);
}
image.src = 'resources/pattern-srgb.svg'
}).then(testImageBitmapFromSVG);
}, 'createImageBitmap in e-sRGB from a sRGB SVG image with resize.');
////////////////////////////////////////////////////////////////////////////////
// HTMLVideoElement - sRGB
promise_test(function() {
return new Promise((resolve, reject) => {
var video = document.createElement("video");
video.oncanplaythrough = function() {
resolve(video);
}
video.src = 'resources/pattern-srgb-fullcolor.ogv'
}).then(testImageBitmapVideoSource);
}, 'createImageBitmap in e-sRGB from a sRGB HTMLVideoElement with resize.');
////////////////////////////////////////////////////////////////////////////////
// HTMLCanvasElement - Opaque sRGB
promise_test(function() {
var testCanvas = initializeTestCanvas('srgb', 'uint8');
return testImageBitmapOpaque(testCanvas);
}, 'createImageBitmap in e-sRGB from an opaque sRGB HTMLCanvasElement with resize.');
// HTMLCanvasElement - Opaque e-sRGB
promise_test(function() {
var testCanvas = initializeTestCanvas('srgb', 'float16');
return testImageBitmapOpaque(testCanvas);
}, 'createImageBitmap in e-sRGB from an opaque e-sRGB HTMLCanvasElement with resize.');
////////////////////////////////////////////////////////////////////////////////
// HTMLCanvasElement - Transparent sRGB
promise_test(function() {
var testCanvas = initializeTestCanvasTransparent('srgb', 'uint8');
return testImageBitmapTransparent(testCanvas);
}, 'createImageBitmap in e-sRGB from a transparent sRGB HTMLCanvasElement with resize.');
// HTMLCanvasElement - Transparent e-sRGB
promise_test(function() {
var testCanvas = initializeTestCanvasTransparent('srgb', 'float16');
return testImageBitmapTransparent(testCanvas);
}, 'createImageBitmap in e-sRGB from a transparent e-sRGB HTMLCanvasElement with resize.');
//////////////////////////////////////////////////////////////////////////////
// Blob from file - Opaque sRGB
promise_test(function() {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.open("GET", 'resources/pattern-srgb.png');
xhr.responseType = 'blob';
xhr.send();
xhr.onload = function() {
resolve(xhr.response);
};
}).then(testImageBitmapOpaque);
}, 'createImageBitmap in e-sRGB from an opaque sRGB Blob with resize.');
// Blob form file - Transparent sRGB
promise_test(function() {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest();
xhr.open("GET", 'resources/pattern-srgb-transparent.png');
xhr.responseType = 'blob';
xhr.send();
xhr.onload = function() {
resolve(xhr.response);
};
}).then(testImageBitmapFromTransparentImage);
}, 'createImageBitmap in e-sRGB from a transparent sRGB Blob with resize.');
// Color managed blob from canvas
function testCreateImageBitmapFromColorManagedBlob(pixelFormat, isTransparent) {
let canvasPixelFormat = 'uint8';
if (pixelFormat == 'uint16')
canvasPixelFormat = 'float16';
var testCanvas;
if (isTransparent)
testCanvas = initializeTestCanvasTransparent('srgb', canvasPixelFormat);
else
testCanvas = initializeTestCanvas('srgb', canvasPixelFormat);
var encodeOptions = {};
encodeOptions.quality = 1;
encodeOptions.type = 'image/png';
encodeOptions.pixelFormat = pixelFormat;
var t = async_test('createImageBitmap in e-sRGB from color managed Blob' +
' with resize. blobPixelFormat: ' + pixelFormat +
', transparency: ' + isTransparent);
testCanvas.convertToBlob(encodeOptions).then(
t.step_func_done(function(blob) {
if (isTransparent)
testImageBitmapTransparent(blob);
else
testImageBitmapOpaque(blob);
}));
}
function runAllCreateImageBitmapFromColorManagedBlobTests() {
var blobPixelFormats = ['uint8', 'uint16'];
var transparencies = [false, true];
for (var j = 0; j < blobPixelFormats.length; j++)
for (var k = 0; k < transparencies.length; k++) {
testCreateImageBitmapFromColorManagedBlob(
blobPixelFormats[j], transparencies[k]);
}
}
runAllCreateImageBitmapFromColorManagedBlobTests();
////////////////////////////////////////////////////////////////////////////////
// ImageData - Opaque sRGB
promise_test(function() {
var canvas = initializeTestCanvas('srgb', 'uint8');
var ctx = canvas.getContext('2d');
var data = ctx.getImageData(0, 0, 20, 20);
return testImageBitmapOpaque(data);
}, 'createImageBitmap in e-sRGB from an opaque sRGB ImageData with resize.');
// ImageData - Opaque e-sRGB
promise_test(function() {
var canvas = initializeTestCanvas('srgb', 'float16');
var ctx = canvas.getContext('2d',
{colorSpace: 'srgb', pixelFormat:'float16'});
var data = ctx.getImageData(0, 0, 20, 20);
return testImageBitmapOpaque(data);
}, 'createImageBitmap in e-sRGB from an opaque e-sRGB ImageData with resize.');
////////////////////////////////////////////////////////////////////////////////
// ImageData - Transparent sRGB
promise_test(function() {
var canvas = initializeTestCanvasTransparent('srgb', 'uint8');
var ctx = canvas.getContext('2d');
var data = ctx.getImageData(0, 0, 20, 20);
return testImageBitmapTransparent(data);
}, 'createImageBitmap in e-sRGB from a transparent sRGB ImageData with resize.');
// ImageData - Transparent e-sRGB
promise_test(function() {
var canvas = initializeTestCanvasTransparent('srgb', 'float16');
var ctx = canvas.getContext('2d',
{colorSpace: 'srgb', pixelFormat:'float16'});
var data = ctx.getImageData(0, 0, 20, 20);
return testImageBitmapTransparent(data);
}, 'createImageBitmap in e-sRGB from a transparent e-sRGB ImageData with resize.');
////////////////////////////////////////////////////////////////////////////////
// ImageBitmap - Opaque sRGB
promise_test(function() {
var testCanvas = initializeTestCanvas('srgb', 'uint8');
return createImageBitmap(testCanvas).then(testImageBitmapOpaque);
}, 'createImageBitmap in e-sRGB from an opaque sRGB ImageBitmap with resize.');
// ImageBitmap - Opaque e-sRGB
promise_test(function() {
var testCanvas = initializeTestCanvas('srgb', 'float16');
return createImageBitmap(testCanvas, {colorSpaceConversion: "srgb"}
).then(testImageBitmapOpaque);
}, 'createImageBitmap in e-sRGB from an opaque e-sRGB ImageBitmap with resize.');
////////////////////////////////////////////////////////////////////////////////
// ImageBitmap - Transparent sRGB
promise_test(function() {
var testCanvas = initializeTestCanvasTransparent('srgb', 'uint8');
return createImageBitmap(testCanvas).then(testImageBitmapTransparent);
}, 'createImageBitmap in e-sRGB from a transparent sRGB ImageBitmap with resize.');
// ImageBitmap - Transparent e-sRGB
promise_test(function() {
var testCanvas = initializeTestCanvasTransparent('srgb', 'float16');
return createImageBitmap(testCanvas, {colorSpaceConversion: "srgb"}
).then(testImageBitmapTransparent);
}, 'createImageBitmap in e-sRGB from a transparent e-sRGB ImageBitmap with resize.');
////////////////////////////////////////////////////////////////////////////////
function initializeOffscreenCanvas(canvasColorSpace, canvasPixelFormat)
{
var canvas = document.createElement("canvas");
canvas.width = 20;
canvas.height = 20;
var offscreen = canvas.transferControlToOffscreen();
var ctx = offscreen.getContext('2d',
{colorSpace: canvasColorSpace, pixelFormat:canvasPixelFormat});
ctx.fillStyle = "rgba(155, 27, 27, 1)";
ctx.fillRect(0, 0, 10, 10);
ctx.fillStyle = "rgba(27, 155, 27, 1)";
ctx.fillRect(10, 0, 10, 10);
ctx.fillStyle = "rgba(27, 27, 155, 1)";
ctx.fillRect(0, 10, 10, 10);
ctx.fillStyle = "rgba(27, 27, 27, 1)";
ctx.fillRect(10, 10, 10, 10);
return offscreen;
}
//OffscreenCanvas - Opaque sRGB
promise_test(function() {
var offscreen = initializeOffscreenCanvas('srgb', 'uint8');
return testImageBitmapOpaque(offscreen);
}, 'createImageBitmap in e-sRGB from an opaque sRGB OffscreenCanvas with resize.');
//OffscreenCanvas - Opaque e-sRGB
promise_test(function() {
var offscreen = initializeOffscreenCanvas('srgb', 'float16');
return testImageBitmapOpaque(offscreen);
}, 'createImageBitmap in e-sRGB from an opaque e-sRGB OffscreenCanvas with resize.');
////////////////////////////////////////////////////////////////////////////////
function initializeOffscreenCanvasTransparent(canvasColorSpace, canvasPixelFormat)
{
var canvas = document.createElement("canvas");
canvas.width = 20;
canvas.height = 20;
var offscreen = canvas.transferControlToOffscreen();
var ctx = offscreen.getContext('2d',
{colorSpace: canvasColorSpace, pixelFormat:canvasPixelFormat});
ctx.fillStyle = "rgba(155, 27, 27, 0.5)";
ctx.fillRect(0, 0, 10, 10);
ctx.fillStyle = "rgba(27, 155, 27, 0.5)";
ctx.fillRect(10, 0, 10, 10);
ctx.fillStyle = "rgba(27, 27, 155, 0.5)";
ctx.fillRect(0, 10, 10, 10);
ctx.fillStyle = "rgba(27, 27, 27, 0.5)";
ctx.fillRect(10, 10, 10, 10);
return offscreen;
}
//OffscreenCanvas - Transparent sRGB
promise_test(function() {
var offscreen = initializeOffscreenCanvasTransparent('srgb', 'uint8');
return testImageBitmapTransparent(offscreen);
}, 'createImageBitmap in e-sRGB from a transparent sRGB OffscreenCanvas with resize.');
//OffscreenCanvas - Transparent e-sRGB
promise_test(function() {
var offscreen = initializeOffscreenCanvasTransparent('srgb', 'float16');
return testImageBitmapTransparent(offscreen);
}, 'createImageBitmap in e-sRGB from a transparent e-sRGB OffscreenCanvas with resize.');
////////////////////////////////////////////////////////////////////////////////
</script>

View file

@ -0,0 +1,142 @@
<!DOCTYPE html>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
var xWidth = xHeight = 10;
function checkImageData(canvasColorSettings, imageData) {
var imageDataColorSettings = imageData.getColorSettings();
assert_equals(canvasColorSettings.colorSpace, imageDataColorSettings.colorSpace);
if (canvasColorSettings.pixelFormat == "uint8") {
assert_equals("uint8", imageDataColorSettings.storageFormat);
assert_equals(imageData.data.length, 4 * xWidth * xHeight);
} else {
assert_equals("float32", imageDataColorSettings.storageFormat);
assert_equals(imageData.dataUnion.length, 4 * xWidth * xHeight);
}
}
// Test createImageData when the canvas is color managed
var helperImageData = new ImageData(xWidth, xHeight);
function runTestCreateImageData(canvasColorSettings) {
var aCanvas = document.createElement("canvas");
aCanvas.width = xWidth;
aCanvas.height = xHeight;
var ctx = aCanvas.getContext('2d', canvasColorSettings);
var imageData = ctx.createImageData(xWidth, xHeight);
checkImageData(canvasColorSettings, imageData);
imageData = ctx.createImageData(helperImageData);
checkImageData(canvasColorSettings, imageData);
}
var testScenariosCreateImageData = [
["Test color managed cretateImageData: {srgb, uint8} -> {srgb, uint8}",
{colorSpace: "srgb", pixelFormat: "uint8"}],
["Test color managed cretateImageData: {srgb, float16} -> {srgb, float32}",
{colorSpace: "srgb", pixelFormat: "float16"}],
];
function runCreateImageDataTests() {
for (var i = 0; i < testScenariosCreateImageData.length; i++){
var t = test(function() {
runTestCreateImageData(testScenariosCreateImageData[i][1]);
}, testScenariosCreateImageData[i][0]);
}
}
runCreateImageDataTests();
// Test getImageData when the canvas is color managed
function runTestGetImageData(canvasColorSettings) {
var aCanvas = document.createElement("canvas");
aCanvas.width = xWidth;
aCanvas.height = xHeight;
var ctx = aCanvas.getContext('2d', canvasColorSettings);
var imageData = ctx.getImageData(0, 0, xWidth, xHeight);
checkImageData(canvasColorSettings, imageData);
}
var testScenariosGetImageData = [
["Test color managed getImageData: {srgb, uint8} -> {srgb, uint8}",
{colorSpace: "srgb", pixelFormat: "uint8"}],
["Test color managed getImageData: {srgb, float16} -> {srgb, float32}",
{colorSpace: "srgb", pixelFormat: "float16"}],
];
function runGetImageDataTests() {
for (var i = 0; i < testScenariosGetImageData.length; i++){
var t = test(function() {
runTestGetImageData(testScenariosGetImageData[i][1]);
}, testScenariosGetImageData[i][0]);
}
}
runGetImageDataTests();
// Test putImageData when the canvas is color managed.
var dataU8 = new Uint8ClampedArray(4 * xWidth * xHeight);
var dataU16 = new Uint16Array(4 * xWidth * xHeight);
var dataF32 = new Float32Array(4 * xWidth * xHeight);
function prepareDataArrays() {
for (i = 0; i < 4 * xWidth * xHeight; i++) {
dataU8[i] = (i % 4 == 3) ? 255 : i % 256;
dataU16[i] = dataU8[i] * 257;
dataF32[i] = dataU8[i] / 255.0;
}
}
var testScenariosPutImageData = [];
function prepareTestScenariosPutImageData() {
var colorSpaces = ["srgb"];
var imageDataStorageFormats = ["uint8", "uint16", "float32"];
var canvasPixelFormats = ["uint8", "float16"];
for (i = 0; i < colorSpaces.length; i++)
for (j = 0; j < imageDataStorageFormats.length; j++)
for (k = 0; k < colorSpaces.length; k++)
for (l = 0; l < canvasPixelFormats.length; l++) {
testTitle = "Test color managed putImageData: ".concat(
"{", colorSpaces[i], ", ", imageDataStorageFormats[j], "} -> {", colorSpaces[k],
", ", canvasPixelFormats[l], "}");
imageDataColorSettings =
{colorSpace: colorSpaces[i], storageFormat: imageDataStorageFormats[j]};
canvasColorSettings =
{colorSpace: colorSpaces[k], pixelFormat: canvasPixelFormats[l]};
testScenariosPutImageData.push([testTitle, imageDataColorSettings, canvasColorSettings]);
}
}
function createAndPutImageData(data, imageDataColorSettings, canvasColorSettings) {
// create color managed canvas
var aCanvas = document.createElement("canvas");
aCanvas.width = xWidth;
aCanvas.height = xHeight;
var ctx = aCanvas.getContext('2d', canvasColorSettings);
// create color managed ImageData
var imageData = ctx.createImageData(data, xWidth, xHeight, imageDataColorSettings);
// put image data into canvas. test succeeds if this does not crash.
ctx.putImageData(imageData, 0, 0);
}
function runTestPutImageData(imageDataColorSettings, canvasColorSettings) {
createAndPutImageData(dataU8, imageDataColorSettings, canvasColorSettings);
createAndPutImageData(dataU16, imageDataColorSettings, canvasColorSettings);
createAndPutImageData(dataF32, imageDataColorSettings, canvasColorSettings);
}
prepareDataArrays();
prepareTestScenariosPutImageData();
function runPutImageDataTests() {
for (var i = 0; i < testScenariosPutImageData.length; i++){
var t = test(function() {
runTestPutImageData(testScenariosPutImageData[i][1]);
}, testScenariosPutImageData[i][0]);
}
}
runPutImageDataTests();
</script>
</body>

View file

@ -0,0 +1,109 @@
<!DOCTYPE HTML>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
var testImagesPath = "resources/png-16bit/";
// Source of pixel comparison error in these tests:
// - color conversion from different color profiles (sRGB, Adobe RGB, Display P3,
// ProPhoto and Rec 2020) to target canvas color space (sRGB, e-sRGB).
// - comparing the result of drawing 8 bit and 16 bit PNGs with each other.
var defaultColorConversionTolerance = 8;
var wideGamutColorConversionTolerance = 0.05;
function runTest(testScenario) {
var _8bitImageSrc = testImagesPath + testScenario._8bitImagePath;
var _16bitImageSrc = testImagesPath + testScenario._16bitImagePath;
var tolerance = defaultColorConversionTolerance;
if (testScenario.canvasColorParams.pixelFormat == 'float16')
tolerance = wideGamutColorConversionTolerance;
var _8bitImage = new Image();
var _16bitImage = new Image();
var t_image = async_test(testScenarioToString(testScenario));
_8bitImage.onload = t_image.step_func(function() {
_16bitImage.onload = function() {
var refCanvas = document.createElement("canvas");
refCanvas.width = refCanvas.height = 2;
var refCtx = refCanvas.getContext(
'2d', testScenario.canvasColorParams);
refCtx.drawImage(_8bitImage, 0, 0);
var refPixels = refCtx.getImageData(0, 0, 2, 2).dataUnion;
var testCanvas = document.createElement("canvas");
testCanvas.width = testCanvas.height = 2;
var testCtx = testCanvas.getContext(
'2d', testScenario.canvasColorParams);
testCtx.drawImage(_16bitImage, 0, 0);
var testPixels = testCtx.getImageData(0, 0, 2, 2).dataUnion;
assert_array_approx_equals(refPixels, testPixels, tolerance);
t_image.done();
};
_16bitImage.src = _16bitImageSrc;
});
_8bitImage.src = _8bitImageSrc;
}
function runAllTests() {
var pngColorSpaces = [
"_sRGB",
"_AdobeRGB",
"_DisplayP3",
"_ProPhoto",
"_Rec2020",
];
var pngTransparencyStatus = [
"_opaque",
"_transparent",
];
var pngInterlaceStatus = [
"", // non-interlaced
"_interlaced",
];
var _8bitPngPrefix = "2x2_8bit";
var _16bitPngPrefix = "2x2_16bit";
var canvasColorParams = [
{colorSpace: 'srgb', pixelFormat: 'uint8'},
{colorSpace: 'srgb', pixelFormat: 'float16'},
];
var testScenarioSet = [];
var id = 1;
for (var i = 0; i < canvasColorParams.length; i++) {
for (var j = 0; j < pngColorSpaces.length; j++) {
for (var k = 0; k < pngTransparencyStatus.length; k++) {
for (var m = 0; m < pngInterlaceStatus.length; m++) {
var testScenario = {};
testScenario.canvasColorParams = canvasColorParams[i];
testScenario._8bitImagePath = _8bitPngPrefix +
pngColorSpaces[j] + pngTransparencyStatus[k] + ".png";
testScenario._16bitImagePath = _16bitPngPrefix +
pngInterlaceStatus[m] + pngColorSpaces[j] +
pngTransparencyStatus[k] + ".png";
testScenarioSet.push(testScenario);
}
}
}
}
for (var i = 0; i < testScenarioSet.length; i++)
runTest(testScenarioSet[i]);
}
function testScenarioToString(testScenario) {
var str = "Canvas color params: " +
testScenario.canvasColorParams.colorSpace + ", " +
testScenario.canvasColorParams.pixelFormat + ". Testing " +
testScenario._8bitImagePath + " vs " + testScenario._16bitImagePath;
return str;
}
runAllTests();
</script>

View file

@ -0,0 +1,53 @@
<!DOCTYPE HTML>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
// sRGB(226,31,31,128)
var e_sRGB_TransparentRed = [0.886230, 0.121521, 0.121521, 0.501953];
// sRGB(226,31,31,128)
var e_sRGB_TransparentGreen = [0.121521, 0.886230, 0.121521, 0.501953];
// sRGB(226,31,31,128)
var e_sRGB_TransparentBlue = [0.121521, 0.121521, 0.886230, 0.501953];
// sRGB(226,31,31,128)
var e_sRGB_TransparentBlack = [0.121521, 0.121521, 0.121521, 0.501953];
function testPixels(ctx, tests)
{
var actual, expected, tolerance = 0.01;
for (var i = 0; i < tests.length; i++) {
actual = ctx.getImageData(tests[i].x, tests[i].y, 1, 1).dataUnion;
expected = tests[i].color;
assert_true(actual.length === expected.length);
for (var j = 0; j < actual.length; j++)
assert_approx_equals(actual[j], expected[j], tolerance);
}
}
function drawSRGBImageOnExtendedSRGBCanvas(source)
{
var canvas = document.createElement('canvas');
canvas.width = 20;
canvas.height = 20;
var ctx = canvas.getContext('2d',
{colorSpace: 'srgb', pixelFormat:'float16'});
ctx.drawImage(source, 0, 0);
var tests = [{x: 5, y: 5, color: e_sRGB_TransparentRed},
{x: 15, y: 5, color: e_sRGB_TransparentGreen},
{x: 5, y: 15, color: e_sRGB_TransparentBlue},
{x: 15, y: 15, color: e_sRGB_TransparentBlack}];
testPixels(ctx, tests);
}
promise_test(function() {
return new Promise((resolve, reject) => {
var image = new Image();
image.onload = function() {
resolve(image);
}
image.src = 'resources/pattern-semitransparent-srgb.png'
}).then(drawSRGBImageOnExtendedSRGBCanvas);
}, 'Draw SRGB image on an e-sRGB canvas and read back the e-sRGB pixels.');
</script>

View file

@ -0,0 +1,176 @@
<!DOCTYPE HTML>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
function initializeBlankCanvas(canvasColorSpace, canvasPixelFormat)
{
var testCanvas = document.createElement("canvas");
testCanvas.width = 4;
testCanvas.height = 4;
var testCtx = testCanvas.getContext('2d',
{colorSpace: canvasColorSpace, pixelFormat:canvasPixelFormat});
return testCtx;
}
function initializeCanvas(canvasColorSpace, canvasPixelFormat)
{
var testCanvas = document.createElement("canvas");
testCanvas.width = 4;
testCanvas.height = 4;
var testCtx = testCanvas.getContext('2d',
{colorSpace: canvasColorSpace, pixelFormat:canvasPixelFormat});
testCtx.fillStyle = "rgba(155, 27, 27, 1)";
testCtx.fillRect(0, 0, 2, 2);
testCtx.fillStyle = "rgba(27, 155, 27, 1)";
testCtx.fillRect(2, 0, 2, 2);
testCtx.fillStyle = "rgba(27, 27, 155, 1)";
testCtx.fillRect(0, 2, 2, 2);
testCtx.fillStyle = "rgba(27, 27, 27, 1)";
testCtx.fillRect(2, 2, 2, 2);
return testCtx;
}
function initializeCanvasTransparent(canvasColorSpace, canvasPixelFormat)
{
var testCanvas = document.createElement("canvas");
testCanvas.width = 4;
testCanvas.height = 4;
var testCtx = testCanvas.getContext('2d',
{colorSpace: canvasColorSpace, pixelFormat:canvasPixelFormat});
testCtx.fillStyle = "rgba(155, 27, 27, 0.5)";
testCtx.fillRect(0, 0, 2, 2);
testCtx.fillStyle = "rgba(27, 155, 27, 0.5)";
testCtx.fillRect(2, 0, 2, 2);
testCtx.fillStyle = "rgba(27, 27, 155, 0.5)";
testCtx.fillRect(0, 2, 2, 2);
testCtx.fillStyle = "rgba(27, 27, 27, 0.5)";
testCtx.fillRect(2, 2, 2, 2);
return testCtx;
}
function initializeOffscreenCanvas(canvasColorSpace, canvasPixelFormat)
{
var canvas = document.createElement("canvas");
canvas.width = 4;
canvas.height = 4;
var offscreen = canvas.transferControlToOffscreen();
var ctx = offscreen.getContext('2d',
{colorSpace: canvasColorSpace, pixelFormat:canvasPixelFormat});
ctx.fillStyle = "rgba(155, 27, 27, 1)";
ctx.fillRect(0, 0, 2, 2);
ctx.fillStyle = "rgba(27, 155, 27, 1)";
ctx.fillRect(2, 0, 2, 2);
ctx.fillStyle = "rgba(27, 27, 155, 1)";
ctx.fillRect(0, 2, 2, 2);
ctx.fillStyle = "rgba(27, 27, 27, 1)";
ctx.fillRect(2, 2, 2, 2);
return offscreen;
}
function initializeOffscreenCanvasTransparent(canvasColorSpace, canvasPixelFormat)
{
var canvas = document.createElement("canvas");
canvas.width = 4;
canvas.height = 4;
var offscreen = canvas.transferControlToOffscreen();
var ctx = offscreen.getContext('2d',
{colorSpace: canvasColorSpace, pixelFormat:canvasPixelFormat});
ctx.fillStyle = "rgba(155, 27, 27, 0.5)";
ctx.fillRect(0, 0, 2, 2);
ctx.fillStyle = "rgba(27, 155, 27, 0.5)";
ctx.fillRect(2, 0, 2, 2);
ctx.fillStyle = "rgba(27, 27, 155, 0.5)";
ctx.fillRect(0, 2, 2, 2);
ctx.fillStyle = "rgba(27, 27, 27, 0.5)";
ctx.fillRect(2, 2, 2, 2);
return offscreen;
}
function testPixels(testCtx, refCtx, pixelFormat, isTrnasparent)
{
var actual = testCtx.getImageData(0, 0, 4, 4).dataUnion;
var expected = refCtx.getImageData(0, 0, 4, 4).dataUnion;
var tolerance = 4;
if (pixelFormat === 'float16')
tolerance = 0.02;
if (isTrnasparent)
tolerance = tolerance * 2;
assert_array_approx_equals(actual, expected, tolerance);
}
function runDrawOffscreenCanvasTestOpaque(testScenario) {
var canvas_ctx_opaque = initializeCanvas(
testScenario.canvasColorSpace, testScenario.canvasPixelFormat);
var canvas_ctx_blank = initializeBlankCanvas(
testScenario.canvasColorSpace, testScenario.canvasPixelFormat);
var offscreen_canvas_opaque = initializeOffscreenCanvas(
testScenario.imageColorSpace, testScenario.imagePixelFormat);
canvas_ctx_blank.drawImage(offscreen_canvas_opaque, 0, 0);
testPixels(canvas_ctx_blank, canvas_ctx_opaque,
testScenario.canvasPixelFormat, false);
}
function runDrawOffscreenCanvasTestTransparent(testScenario) {
var canvas_ctx_transparent = initializeCanvasTransparent(
testScenario.canvasColorSpace, testScenario.canvasPixelFormat);
var canvas_ctx_blank = initializeBlankCanvas(
testScenario.canvasColorSpace, testScenario.canvasPixelFormat);
var offscreen_canvas_transparent = initializeOffscreenCanvasTransparent(
testScenario.imageColorSpace, testScenario.imagePixelFormat);
canvas_ctx_blank.drawImage(offscreen_canvas_transparent, 0, 0);
testPixels(canvas_ctx_blank, canvas_ctx_transparent,
testScenario.canvasPixelFormat, true);
}
function runAllTests() {
var canvasColorSpaces = ['srgb'];
var canvasPixelFormats = ['uint8', 'float16'];
var testScenarioSet = [];
for (var i = 0; i < canvasColorSpaces.length; i++) {
for (var j = 0; j < canvasPixelFormats.length; j++) {
var canvas_color_space = canvasColorSpaces[i];
var canvas_pixel_format = canvasPixelFormats[j];
for (var k = 0; k < canvasColorSpaces.length; k++) {
for (var m = 0; m < canvasPixelFormats.length; m++) {
var image_host_color_space = canvasColorSpaces[k];
var image_host_pixel_format = canvasPixelFormats[m];
var testScenario = {};
testScenario.canvasColorSpace = canvas_color_space;
testScenario.canvasPixelFormat = canvas_pixel_format;
testScenario.imageColorSpace = image_host_color_space;
testScenario.imagePixelFormat = image_host_pixel_format;
testScenarioSet.push(testScenario);
}
}
}
}
for (var i = 0; i < testScenarioSet.length; i++) {
test(function(t) {
runDrawOffscreenCanvasTestOpaque(testScenarioSet[i]);
runDrawOffscreenCanvasTestTransparent(testScenarioSet[i]);
}, testScenarioToString(testScenarioSet[i]));
}
}
function testScenarioToString(testScenario) {
var str = "Test drawing color managed OffscreenCanvas: " +
"Canvas color params: " +
testScenario.canvasColorSpace + ", " +
testScenario.canvasPixelFormat +
"; OffscreenCanvas color params: " +
testScenario.imageColorSpace + ", " +
testScenario.imagePixelFormat;
return str;
}
runAllTests();
</script>

View file

@ -0,0 +1,96 @@
<!DOCTYPE html>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
test(drawSRGBThenGetImageData_e_sRGB, 'tests drawing SRGB color on e-sRGB \
canvas and getting e-sRGB image data.');
test(putImageData_e_sRGBThenGetImageData_e_sRGB_InRange, 'tests putting and \
getting in-range e-sRGB image data on e-sRGB canvas.');
test(putImageData_e_sRGBThenGetImageData_e_sRGB_OutOfRange, 'tests putting and \
getting out-of-range e-sRGB image data on e-sRGB canvas.');
test(putImageDataSRGBThenGetImageData_e_sRGB, 'tests putting SRGB image data \
on e-sRGB canvas and getting e-sRGB image data.');
function assert_array_approx_equals(actual, expected, epsilon)
{
assert_true(actual.length === expected.length);
for (var i=0; i < actual.length; i++)
assert_approx_equals(actual[i], expected[i], epsilon);
}
function drawSRGBThenGetImageData_e_sRGB() {
var canvas = document.createElement('canvas');
canvas.width = 10;
canvas.height = 10;
var ctx = canvas.getContext('2d',
{colorSpace: 'srgb', pixelFormat:'float16'});
ctx.fillStyle = 'rgba(51, 102, 153, 0.8)';
ctx.fillRect(0, 0, 10, 10);
var pixel = ctx.getImageData(5, 5, 1, 1).dataUnion;
// Check against the same color in e-sRGB. 0.01 protects the test against
// color conversion deviations.
assert_array_approx_equals(pixel, [0.2, 0.4, 0.6, 0.8], 0.01);
}
function putImageData_e_sRGBThenGetImageData_e_sRGB_InRange() {
var canvas = document.createElement('canvas');
canvas.width = 10;
canvas.height = 10;
var ctx = canvas.getContext('2d',
{colorSpace: 'srgb', pixelFormat:'float16'})
var data_e_sRGB = new Float32Array(4);
data_e_sRGB[0] = 0.2;
data_e_sRGB[1] = 0.4;
data_e_sRGB[2] = 0.6;
data_e_sRGB[3] = 0.8;
var imageData = ctx.createImageData(data_e_sRGB, 1, 1,
{colorSpace: 'srgb', storageFormat:'float32'});
ctx.putImageData(imageData, 5, 5);
var pixel = ctx.getImageData(5, 5, 1, 1).dataUnion;
// Check against the same color in e-sRGB. 0.001 protects the test against
// rounding errors.
assert_array_approx_equals(pixel, [0.2, 0.4, 0.6, 0.8], 0.01);
}
function putImageData_e_sRGBThenGetImageData_e_sRGB_OutOfRange() {
var canvas = document.createElement('canvas');
canvas.width = 10;
canvas.height = 10;
var ctx = canvas.getContext('2d',
{colorSpace: 'srgb', pixelFormat:'float16'})
var data_e_sRGB = new Float32Array(4);
data_e_sRGB[0] = 1.3;
data_e_sRGB[1] = -1.13;
data_e_sRGB[2] = 0.7;
data_e_sRGB[3] = 1.8;
var imageData = ctx.createImageData(data_e_sRGB, 1, 1,
{colorSpace: 'srgb', storageFormat:'float32'});
ctx.putImageData(imageData, 5, 5);
var pixel = ctx.getImageData(5, 5, 1, 1).dataUnion;
// Check against the same color in e-sRGB. 0.001 protects the test against
// rounding errors.
assert_array_approx_equals(pixel, [1.3, -1.13, 0.7, 1.8], 0.01);
}
function putImageDataSRGBThenGetImageData_e_sRGB() {
var canvas = document.createElement('canvas');
canvas.width = 10;
canvas.height = 10;
var ctx = canvas.getContext('2d',
{colorSpace: 'srgb', pixelFormat:'float16'});
var dataSRGB = new Uint8ClampedArray(4);
dataSRGB[0] = 51;
dataSRGB[1] = 102;
dataSRGB[2] = 153;
dataSRGB[3] = 204;
var imageData = ctx.createImageData(dataSRGB, 1, 1,
{colorSpace: 'srgb', storageFormat:'uint8'});
ctx.putImageData(imageData, 5, 5);
var pixel = ctx.getImageData(5, 5, 1, 1).dataUnion;
// Check against the same color in e-sRGB. 0.01 protects the test against
// color conversion deviations.
assert_array_approx_equals(pixel, [0.2, 0.4, 0.6, 0.8], 0.01);
}
</script>
</body>

View file

@ -0,0 +1,364 @@
<!DOCTYPE HTML>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
var srgbPixels =
[[155,27,27,128, "srgbRed"], [27,155,27,128, "srgbGreen"],
[27,27,155,128, "srgbBlue"], [27,27,27,128, "srgbBlack"]];
var e_srgbPixels =
[[0.607422, 0.121521, 0.121521, 0.501953, "e_sRgbRed"],
[0.121521, 0.607422, 0.121521, 0.501953, "e_sRgbGreen"],
[0.121521, 0.121521, 0.607422, 0.501953, "e_sRgbBlue"],
[0.121521, 0.121521, 0.121521, 0.501953, "e_sRgbBlack"]];
var xWidth = xHeight = 2;
var colorCorrectionToleranceSRGB = 1;
// The error level in SRGB->WCG_U8->SRGB is higher than normal color correction
// operations as the pixels are clipped in WCG when U8 storage is used instead
// of F16 storage.
var colorCorrectionToleranceWCG_U8toSRGB_U8 = 6;
var colorCorrectionToleranceWCG = 0.02;
function testBlankPixels(actualData, width, height)
{
var message = "This pixel should be transparent black";
var blankData = new Array(4 * width * height).fill(0);
assert_array_equals(actualData, blankData, message);
}
function testPixels(actualData, expectedPixels, tolerance)
{
assert_equals(actualData.length, 4 * xWidth * xHeight);
for (var i = 0; i < xWidth * xHeight; i++) {
var message = "This pixel should be " + expectedPixels[i][4];
for (var j = 0; j < 4; j++)
assert_approx_equals(actualData[i*4+j], expectedPixels[i][j], tolerance,
message);
}
}
function checkImageDataColorSettings(canvasColorSettings, imageData) {
var imageDataColorSettings = imageData.getColorSettings();
assert_equals(canvasColorSettings.colorSpace,
imageDataColorSettings.colorSpace);
if (canvasColorSettings.pixelFormat == "uint8")
assert_equals("uint8", imageDataColorSettings.storageFormat);
else
assert_equals("float32", imageDataColorSettings.storageFormat);
}
function checkImageDataColorValues(canvasColorSettings, imageData, isBlank = '',
width = xWidth, height = xHeight, isWCG_U8toSRGB_U8 = '') {
var data = imageData.dataUnion;
if (isBlank === 'isBlank') {
testBlankPixels(data, width, height);
} else {
var expectedPixels = srgbPixels;
var tolerance = colorCorrectionToleranceSRGB;
if (isWCG_U8toSRGB_U8 === 'isWCG_U8toSRGB_U8')
tolerance = colorCorrectionToleranceWCG_U8toSRGB_U8;
if (canvasColorSettings.pixelFormat != "uint8") {
expectedPixels = e_srgbPixels;
tolerance = colorCorrectionToleranceWCG;
}
testPixels(data, expectedPixels, tolerance);
}
}
function initializeColorManagedCanvas(canvasColorSettings)
{
var canvas = document.createElement('canvas');
canvas.width = xWidth;
canvas.height = xHeight;
var ctx = canvas.getContext('2d',
{colorSpace: canvasColorSettings.colorSpace,
pixelFormat: canvasColorSettings.pixelFormat});
ctx.fillStyle = "rgba(155, 27, 27, 0.5)";
ctx.fillRect(0, 0, xWidth/2, xHeight/2);
ctx.fillStyle = "rgba(27, 155, 27, 0.5)";
ctx.fillRect(xWidth/2, 0, xWidth/2, xHeight/2);
ctx.fillStyle = "rgba(27, 27, 155, 0.5)";
ctx.fillRect(0, xHeight/2, xWidth/2, xHeight/2);
ctx.fillStyle = "rgba(27, 27, 27, 0.5)";
ctx.fillRect(xWidth/2, xHeight/2, xWidth/2, xHeight/2);
return canvas;
}
var canvasColorSettingsSet = [
{name: "SRGB", colorSettings: {colorSpace: "srgb", pixelFormat: "uint8"}},
{name: "e-SRGB", colorSettings: {colorSpace: "srgb", pixelFormat: "float16"}},
];
var srgbImageDataU8, e_srgbImageDataU16, e_srgbImageDataF32;
function PreparePredefinedImageDataObjects() {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
srgbImageDataU8 = ctx.createImageData(xWidth, xHeight,
{colorSpace: "srgb", storageFormat: "uint8"});
e_srgbImageDataU16 = ctx.createImageData(xWidth, xHeight,
{colorSpace: "srgb", storageFormat: "uint16"});
e_srgbImageDataF32 = ctx.createImageData(xWidth, xHeight,
{colorSpace: "srgb", storageFormat: "float32"});
for (var i = 0; i < xWidth * xHeight; i++)
for (var j = 0; j < 4; j++) {
srgbImageDataU8.dataUnion[i*4+j] = srgbPixels[i][j];
e_srgbImageDataU16.dataUnion[i*4+j] =
Math.round(e_srgbPixels[i][j] * 65535);
e_srgbImageDataF32.dataUnion[i*4+j] = e_srgbPixels[i][j];
}
}
PreparePredefinedImageDataObjects();
var imageDataColorSettingsSet = [
{name: "SRGB U8", colorSettings: {colorSpace: "srgb", storageFormat: "uint8"},
imageData: srgbImageDataU8},
{name: "e-SRGB U16", colorSettings: {colorSpace: "srgb",
storageFormat: "uint16"}, imageData: e_srgbImageDataU16},
{name: "e-SRGB F32", colorSettings: {colorSpace: "srgb",
storageFormat: "float32"}, imageData: e_srgbImageDataF32},
];
////////////////////////////////////////////////////////////////////////////////
// * ImageData imagedata = ctx.createImageData(width, height);
// No color conversion. imagedata follows the color settings of the canvas.
function runTestCreateImageDataWH(canvasColorSettings) {
var canvas = initializeColorManagedCanvas(canvasColorSettings);
var ctx = canvas.getContext('2d');
var imageData = ctx.createImageData(xWidth, xHeight);
checkImageDataColorSettings(canvasColorSettings, imageData);
}
var testScenariosCreateImageDataWH = [];
for (var i = 0; i < canvasColorSettingsSet.length; i++) {
var message = "Test cretateImageData(width, height) from " +
canvasColorSettingsSet[i].name + " canvas ";
testScenariosCreateImageDataWH.
push([message, canvasColorSettingsSet[i].colorSettings]);
}
function runTestCreateImageDataWHTests() {
for (var i = 0; i < testScenariosCreateImageDataWH.length; i++){
var t = test(function() {
runTestCreateImageDataWH(testScenariosCreateImageDataWH[i][1]);
}, testScenariosCreateImageDataWH[i][0]);
}
}
runTestCreateImageDataWHTests();
////////////////////////////////////////////////////////////////////////////////
// * ImageData imagedata = ctx.getImageData(sx, sy, sw, sh);
// No color conversion. imagedata follows the color settings of the canvas.
function runTestGetImageDataXYWH(canvasColorSettings) {
var canvas = initializeColorManagedCanvas(canvasColorSettings);
var ctx = canvas.getContext('2d');
var imageData = ctx.getImageData(0, 0, xWidth, xHeight);
checkImageDataColorSettings(canvasColorSettings, imageData);
checkImageDataColorValues(canvasColorSettings, imageData);
}
var testScenariosGetImageDataXYWH = [];
for (var i = 0; i < canvasColorSettingsSet.length; i++) {
var message = "Test getImageData(sx, sy, sw, sh) from " +
canvasColorSettingsSet[i].name + " canvas ";
testScenariosGetImageDataXYWH.
push([message, canvasColorSettingsSet[i].colorSettings]);
}
function runTestGetImageDataXYWHTests() {
for (var i = 0; i < testScenariosGetImageDataXYWH.length; i++){
var t = test(function() {
runTestGetImageDataXYWH(testScenariosGetImageDataXYWH[i][1]);
}, testScenariosGetImageDataXYWH[i][0]);
}
}
runTestGetImageDataXYWHTests();
////////////////////////////////////////////////////////////////////////////////
// * void ctx.putImageData(imagedata, dx, dy, ...);
// Color conversion, if needed, to the color settings of the canvas.
function runTestPutImageDataDxDy(canvasColorSettings, imageData) {
var canvas = document.createElement('canvas');
canvas.width = xWidth * 2;
canvas.height = xHeight * 2;
var ctx = canvas.getContext('2d',
{colorSpace: canvasColorSettings.colorSpace,
pixelFormat: canvasColorSettings.pixelFormat});
ctx.putImageData(imageData, xWidth/2, xHeight/2);
var ctxImageData = ctx.getImageData(xWidth/2, xHeight/2, xWidth, xHeight);
checkImageDataColorSettings(canvasColorSettings, ctxImageData);
checkImageDataColorValues(canvasColorSettings, ctxImageData, 'noBlank',
xWidth, xHeight, 'isWCG_U8toSRGB_U8');
}
var testScenariosPutImageDataDxDy = [];
for (var i = 0; i < canvasColorSettingsSet.length; i++) {
for (var j = 0; j < imageDataColorSettingsSet.length; j++) {
var message = "Test putImageData(imagedata, dx, dy): " +
canvasColorSettingsSet[i].name + " canvas, " +
imageDataColorSettingsSet[j].name + " ImageData";
testScenariosPutImageDataDxDy.
push([message, canvasColorSettingsSet[i].colorSettings,
imageDataColorSettingsSet[j].imageData]);
}
}
function runTestPutImageDataDxDyTests() {
for (var i = 0; i < testScenariosPutImageDataDxDy.length; i++){
var t = test(function() {
runTestPutImageDataDxDy(
testScenariosPutImageDataDxDy[i][1], testScenariosPutImageDataDxDy[i][2]);
}, testScenariosPutImageDataDxDy[i][0]);
}
}
runTestPutImageDataDxDyTests();
////////////////////////////////////////////////////////////////////////////////
// * ImageData imageData = ctx.createImageData(imagedata);
// Color conversion, if needed, to the color settings of the canvas. The
// returned imageData should be transparent black.
function runTestCreateImageDataFromImageData(canvasColorSettings, imageData) {
var canvas = document.createElement('canvas');
canvas.width = xWidth * 2;
canvas.height = xHeight * 2;
var ctx = canvas.getContext('2d',
{colorSpace: canvasColorSettings.colorSpace,
pixelFormat: canvasColorSettings.pixelFormat});
var ctxImageData = ctx.createImageData(imageData);
checkImageDataColorSettings(canvasColorSettings, ctxImageData);
checkImageDataColorValues(canvasColorSettings, ctxImageData, 'isBlank');
}
var testScenariosCreateImageDataFromImageData = [];
for (var i = 0; i < canvasColorSettingsSet.length; i++) {
for (var j = 0; j < imageDataColorSettingsSet.length; j++) {
var message = "Test createImageData(imagedata): " +
canvasColorSettingsSet[i].name + " canvas, " +
imageDataColorSettingsSet[j].name + " ImageData";
testScenariosCreateImageDataFromImageData.
push([message, canvasColorSettingsSet[i].colorSettings,
imageDataColorSettingsSet[j].imageData]);
}
}
function runTestCreateImageDataFromImageDataTests() {
for (var i = 0; i < testScenariosCreateImageDataFromImageData.length; i++){
var t = test(function() {
runTestCreateImageDataFromImageData(
testScenariosCreateImageDataFromImageData[i][1],
testScenariosCreateImageDataFromImageData[i][2]);
}, testScenariosCreateImageDataFromImageData[i][0]);
}
}
runTestCreateImageDataFromImageDataTests();
////////////////////////////////////////////////////////////////////////////////
// *ImageData ctx.createImageData(width, height, imageDataColorSettings);
// No color conversion to the color settings of the canvas. Blank ImageData
// should be created based on imageDataColorSettings.
function runTestCreateImageDataWHC(canvasColorSettings, imageDataColorSettings) {
var canvas = initializeColorManagedCanvas(canvasColorSettings);
var ctx = canvas.getContext('2d');
width = height = 3;
var imageData = ctx.createImageData(width, height, imageDataColorSettings);
var colorSettings = imageData.getColorSettings();
assert_equals(colorSettings.colorSpace,
imageDataColorSettings.colorSpace,
"colorSpace should match");
assert_equals(colorSettings.storageFormat,
imageDataColorSettings.storageFormat,
"storageFormat should match");
var blankData = new Array(4 * width * height).fill(0);
assert_array_equals(imageData.dataUnion, blankData,
"ImageData should be transparent black");
}
var testScenariosCreateImageDataWHC = [];
for (var i = 0; i < canvasColorSettingsSet.length; i++) {
for (var j = 0; j < imageDataColorSettingsSet.length; j++) {
message = "Test createImageData(width, height, imageDataColorSettings): " +
canvasColorSettingsSet[i].name + " canvas, " +
imageDataColorSettingsSet[j].name + " ImageData";
testScenariosCreateImageDataWHC.
push([message, canvasColorSettingsSet[i].colorSettings,
imageDataColorSettingsSet[j].colorSettings]);
}
}
function runTestCreateImageDataWHCTests() {
for (var i = 0; i < testScenariosCreateImageDataWHC.length; i++){
var t = test(function() {
runTestCreateImageDataWHC(
testScenariosCreateImageDataWHC[i][1],
testScenariosCreateImageDataWHC[i][2]);
}, testScenariosCreateImageDataWHC[i][0]);
}
}
runTestCreateImageDataWHCTests();
////////////////////////////////////////////////////////////////////////////////
// *ImageData ctx.createImageData(data, width, height, imageDataColorSettings);
// No color conversion to the color settings of the canvas. ImageData is created
// from param "data" with proper storage format and is tagged with the
// CanvasColorSpace which is given in imageDataColorSettings.
function runTestCreateImageDataDWHC(canvasColorSettings, imageData) {
var data = imageData.dataUnion;
width = xWidth;
height = xHeight;
var colorSettings = imageData.getColorSettings();
var canvas = initializeColorManagedCanvas(canvasColorSettings);
var ctx = canvas.getContext('2d');
var newImageData = ctx.createImageData(data, width, height, colorSettings);
var newColorSettings = newImageData.getColorSettings();
assert_equals(newColorSettings.colorSpace,
colorSettings.colorSpace,
"colorSpace should match");
assert_equals(newColorSettings.storageFormat,
colorSettings.storageFormat,
"storageFormat should match");
assert_array_equals(newImageData.dataUnion, imageData.dataUnion,
"ImageData should be transparent black");
}
var testScenariosCreateImageDataDWHC = [];
for (var i = 0; i < canvasColorSettingsSet.length; i++) {
for (var j = 0; j < imageDataColorSettingsSet.length; j++) {
message = "Test createImageData(data, width, height, imageDataColorSettings): " +
canvasColorSettingsSet[i].name + " canvas, " +
imageDataColorSettingsSet[j].name + " ImageData";
testScenariosCreateImageDataDWHC.
push([message, canvasColorSettingsSet[i].colorSettings,
imageDataColorSettingsSet[j].imageData]);
}
}
function runTestCreateImageDataDWHCTests() {
for (var i = 0; i < testScenariosCreateImageDataDWHC.length; i++){
var t = test(function() {
runTestCreateImageDataDWHC(
testScenariosCreateImageDataDWHC[i][1],
testScenariosCreateImageDataDWHC[i][2]);
}, testScenariosCreateImageDataDWHC[i][0]);
}
}
runTestCreateImageDataDWHCTests();
////////////////////////////////////////////////////////////////////////////////
</script>

View file

@ -0,0 +1,71 @@
<!DOCTYPE html>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
var dataU8 = new Uint8ClampedArray([255, 192, 128, 64]);
var dataU16 = new Uint16Array([65535, 256*192, 256*128, 256*64]);
var dataF32 = new Float32Array([1.0, 0.75, 0.5, 0.25]);
function checkDataTypeAgainstStorageFormat(data, storageFormat) {
if (storageFormat == "uint8")
assert_equals(Object.prototype.toString.call(data), "[object Uint8ClampedArray]");
else if (storageFormat == "uint16")
assert_equals(Object.prototype.toString.call(data), "[object Uint16Array]");
else if (storageFormat == "float32")
assert_equals(Object.prototype.toString.call(data), "[object Float32Array]");
}
function checkColorSettings(colorSettings, colorSpace, storageFormat) {
assert_equals(colorSettings.colorSpace, colorSpace);
assert_equals(colorSettings.storageFormat, storageFormat);
}
function runTest(colorSettings, expectedColorSettings) {
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
imageData = ctx.createImageData(1, 1, colorSettings);
checkDataTypeAgainstStorageFormat(imageData.dataUnion, colorSettings.storageFormat);
assert_array_equals(imageData.dataUnion, [0, 0, 0, 0]);
checkColorSettings(imageData.getColorSettings(), expectedColorSettings.colorSpace, expectedColorSettings.storageFormat);
imageData = ctx.createImageData(dataU8, 1, 1, colorSettings);
assert_equals(Object.prototype.toString.call(imageData.dataUnion), "[object Uint8ClampedArray]");
assert_array_equals(imageData.dataUnion, dataU8);
checkColorSettings(imageData.getColorSettings(), expectedColorSettings.colorSpace, "uint8");
imageData = ctx.createImageData(dataU16, 1, 1, colorSettings);
assert_equals(Object.prototype.toString.call(imageData.dataUnion), "[object Uint16Array]");
assert_array_equals(imageData.dataUnion, dataU16);
checkColorSettings(imageData.getColorSettings(), expectedColorSettings.colorSpace, "uint16");
imageData = ctx.createImageData(dataF32, 1, 1, colorSettings);
assert_equals(Object.prototype.toString.call(imageData.dataUnion), "[object Float32Array]");
assert_array_equals(imageData.dataUnion, dataF32);
checkColorSettings(imageData.getColorSettings(), expectedColorSettings.colorSpace, "float32");
}
var testScenarios = [
["Test default color settings: {undefined, undefined} -> {srgb, uint8}", {}, {colorSpace: "srgb", storageFormat: "uint8"}],
["Test default color space: {undefined, float32} -> {srgb, float32}", {storageFormat: "float32"}, {colorSpace: "srgb", storageFormat: "float32"}],
["Test default storage format: {srgb, undefined} -> {srgb, uint8}", {colorSpace: "srgb"}, {colorSpace: "srgb", storageFormat: "uint8"}],
["Test color settings: {srgb, uint8}", {colorSpace: "srgb", storageFormat: "uint8"}, {colorSpace: "srgb", storageFormat: "uint8"}],
["Test color settings: {srgb, uint16}", {colorSpace: "srgb", storageFormat: "uint16"}, {colorSpace: "srgb", storageFormat: "uint16"}],
["Test color settings: {srgb, float32}", {colorSpace: "srgb", storageFormat: "float32"}, {colorSpace: "srgb", storageFormat: "float32"}],
];
function runAllTests() {
for (var i = 0; i < testScenarios.length; i++){
var t = test(function() {
runTest(testScenarios[i][1], testScenarios[i][2]);
}, testScenarios[i][0]);
}
}
runAllTests();
</script>
</body>

View file

@ -0,0 +1,26 @@
<!DOCTYPE HTML>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
test(function() {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d',
{})
var dataFloat32 = new Float32Array(4);
var imageData = ctx.createImageData(dataFloat32, 1, 1,
{});
ctx.putImageData(imageData, 5, 5);
var data = ctx.getImageData(5,5,1,1).dataUnion;
}, "Putting a float-32 ImageData with no color settings on a context 2D should not crash.");
test(function() {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d',
{})
var dataUint16 = new Uint16Array(4);
var imageData = ctx.createImageData(dataUint16, 1, 1,
{});
ctx.putImageData(imageData, 5, 5);
var data = ctx.getImageData(5,5,1,1).dataUnion;
}, "Putting a uint-16 ImageData with no color settings on a context 2D should not crash.");
</script>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 898 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 B

View file

@ -0,0 +1,6 @@
<svg width="20" height="20" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<rect x="0" y="0" width="10px" height="10px" fill="#9b1b1b"/>
<rect x="10" y="0" width="10px" height="10px" fill="#1b9b1b"/>
<rect x="0" y="10" width="10px" height="10px" fill="#1b1b9b"/>
<rect x="10" y="10" width="10px" height="10px" fill="#1b1b1b"/>
</svg>

After

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 208 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -0,0 +1,115 @@
<!DOCTYPE HTML>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
// This test examines the color managed ImageBitmapRenderingContext.
// - We first draw on 2D canvas with different color space and alpha
// properties.
// - Next, the canvas is used as a source image to create an ImageBitmap.
// Different colorSpaceConversion values are tested when creating the
// intermediate ImageBitmap object.
// - Next, ImageBitmap is transferred to an ImageBitmapRenderingContext.
// - Since we cannot read back pixels from ImageBitmapRenderingContext, we
// draw it to another 2D canvas and read back the pixels.
// - Finally, we compare the pixels read from the first 2D canvas with those
// read from the final 2D canvas. We expect them to match with some
// tolerance.
function testPixels(actualPixels, expectedPixels, testScenario)
{
var tolerance = 0;
if (testScenario.pixelFormat == "float16")
tolerance = 0.01;
assert_array_approx_equals(actualPixels, expectedPixels, tolerance);
}
function generateFillStyle(red, green, blue, alpha) {
return "rgba(" + red + "," + green + "," + blue + "," + alpha + ")";
}
function generateExpectedResult(testScenario, canvas)
{
var ctx = canvas.getContext('2d', {colorSpace: testScenario.colorSpace,
pixelFormat: testScenario.pixelFormat});
ctx.fillStyle = generateFillStyle(155, 27, 27, testScenario.alpha);
ctx.fillRect(0, 0, 1, 1);
ctx.fillStyle = generateFillStyle(27, 155, 27, testScenario.alpha);
ctx.fillRect(1, 0, 1, 1);
ctx.fillStyle = generateFillStyle(27, 27, 155, testScenario.alpha);
ctx.fillRect(0, 1, 1, 1);
ctx.fillStyle = generateFillStyle(27, 27, 27, testScenario.alpha);
ctx.fillRect(1, 1, 1, 1);
return ctx.getImageData(0, 0, 2, 2).dataUnion;
}
function generateTestName(testScenario) {
var str = "Testing ImageBitmapRenderingContext:" +
" Source color space: " + testScenario.colorSpace +
", pixel format: " + testScenario.pixelFormat +
", alpha: " + testScenario.alpha +
", intermediate color space: " +
testScenario.colorSpaceConversion;
return str;
}
function runTransferFromImageBitmapTest(testScenario) {
var canvas = document.createElement("canvas");
canvas.width = 2;
canvas.height = 2;
var expectedPixels = generateExpectedResult(testScenario, canvas);
promise_test(function() {
var options = {colorSpaceConversion: testScenario.colorSpaceConversion};
var promise = createImageBitmap(canvas, options);
return Promise.all([promise]).then(([imagebitmap]) => {
var dstCanvas = document.createElement("canvas");
dstCanvas.width = 2;
dstCanvas.height = 2;
var dstCtx = dstCanvas.getContext('bitmaprenderer');
dstCtx.transferFromImageBitmap(imagebitmap);
// ImageBitmapRenderingContext does not have ImageData, so we draw
// it on another canvas and read back the data.
var finalCanvas = document.createElement("canvas");
finalCanvas.width = 2;
finalCanvas.height = 2;
var ctx = finalCanvas.getContext('2d',
{colorSpace: testScenario.colorSpace,
pixelFormat: testScenario.pixelFormat});
ctx.drawImage(dstCanvas, 0, 0);
var actualPixels = ctx.getImageData(0, 0, 2, 2).dataUnion;
testPixels(actualPixels, expectedPixels, testScenario);
});
}, generateTestName(testScenario));
}
function runAllTests() {
var colorSpaces = [
{colorSpace: 'srgb', pixelFormat: 'uint8'},
{colorSpace: 'srgb', pixelFormat: 'float16'},
];
var alphaValues = [0.5, 1];
var colorSpaceConversions = ['none', 'default'];
var testScenarios = [];
for (var i = 0; i < colorSpaces.length; i++)
for (var j = 0; j < alphaValues.length; j++)
for (var k = 0; k < colorSpaceConversions.length; k++) {
var testScenario = {};
testScenario.colorSpace = colorSpaces[i].colorSpace;
testScenario.pixelFormat = colorSpaces[i].pixelFormat;
testScenario.alpha = alphaValues[j];
testScenario.colorSpaceConversion = colorSpaceConversions[k];
testScenarios.push(testScenario);
}
for (var i = 0; i < testScenarios.length; i++)
runTransferFromImageBitmapTest(testScenarios[i]);
}
runAllTests();
</script>

View file

@ -4,5 +4,4 @@ suggested_reviewers:
- dontcallmedom
- riju
- Honry
- alexshalamov
- rakuco

View file

@ -3,6 +3,5 @@ suggested_reviewers:
- zqzhang
- dontcallmedom
- riju
- alexshalamov
- rakuco
- Honry

View file

@ -39,6 +39,6 @@ promise_test(async t => {
assert_equals(e.name, "NotAllowedError", "Non-default devices are failing with NotAllowed error");
}
}
}, "List device, setSinkId should on the default, the rest of the devices will get a NotAlowedError");
}, "List device, setSinkId should be allowed on the default, the rest of the devices will get a NotAllowedError");
</script>

View file

@ -41,6 +41,6 @@ promise_test(async t => {
assert_equals(e.name, "NotAllowedError", "Non-default devices are failing with NotAllowed error");
}
}
}, "List device, setSinkId should on the default, the rest of the devices will get a NotAlowedError");
}, "List device, setSinkId should be allowed on the default, the rest of the devices will get a NotAllowedError");
</script>

View file

@ -7,7 +7,7 @@ test(function() {
// Payload that should cause sendBeacon to return false because it exceeds the maximum payload size.
var exceedPayload = Array(maxPayloadSize + 1).fill('z').join("");
var success = navigator.sendBeacon("http://doesnotmatter", exceedPayload);
var success = navigator.sendBeacon("http://{{hosts[][nonexistent]}}", exceedPayload);
assert_false(success, "calling 'navigator.sendBeacon()' with payload size exceeding the maximum size must fail");
}, "Verify calling 'navigator.sendBeacon()' with a large payload returns 'false'.");

View file

@ -0,0 +1,52 @@
<!DOCTYPE HTML>
<html>
<head>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
<title>Test that a 304 response will update the CSP header</title>
</head>
<body>
<script>
var t1 = async_test("Test that the first frame uses nonce abc");
var t2 = async_test("Test that the first frame does not use nonce def");
var t3 = async_test("Test that the second frame uses nonce def");
var t4 = async_test("Test that the second frame does not use nonce abc");
var i1 = document.createElement('iframe');
// We add a random parameter to avoid previous tests cached requests.
// We want to make sure i1 gets a 200 code and i2 gets a 304 code.
i1.src = "support/304-response.py?{{$id:uuid()}}";
var i2 = document.createElement('iframe');
i2.src = "support/304-response.py?{{$id}}";
var load_second_frame = function() {
document.body.appendChild(i2);
}
window.onmessage = function(e) {
if (e.source == i1.contentWindow) {
if (e.data == "abc_executed") { t1.done(); return; }
if (e.data == "script-src 'nonce-abc' 'sha256-IIB78ZS1RMMrAWpsLg/RrDbVPhI14rKm3sFOeKPYulw=';") { t2.done(); return; }
t1.step(function() { assert_unreached("Unexpected message received"); });
t2.step(function() { assert_unreached("Unexpected message received"); });
}
if (e.source == i2.contentWindow) {
if (e.data == "def_executed") { t3.done(); return; }
if (e.data == "script-src 'nonce-def' 'sha256-IIB78ZS1RMMrAWpsLg/RrDbVPhI14rKm3sFOeKPYulw=';") { t4.done(); return; }
t3.step(function() { assert_unreached("Unexpected message received"); });
t4.step(function() { assert_unreached("Unexpected message received"); });
}
};
i1.onload = load_second_frame;
document.body.appendChild(i1);
</script>
</body>
</html>

View file

@ -0,0 +1,33 @@
def main(request, response):
if request.headers.get("If-None-Match"):
# we are now receing the second request, we will send back a different CSP
# with the 304 response
response.status = 304
headers = [("Content-Type", "text/html"),
("Content-Security-Policy", "script-src 'nonce-def' 'sha256-IIB78ZS1RMMrAWpsLg/RrDbVPhI14rKm3sFOeKPYulw=';"),
("Cache-Control", "private, max-age=0, must-revalidate"),
("ETag", "123456")]
return headers, ""
else:
headers = [("Content-Type", "text/html"),
("Content-Security-Policy", "script-src 'nonce-abc' 'sha256-IIB78ZS1RMMrAWpsLg/RrDbVPhI14rKm3sFOeKPYulw=';"),
("Cache-Control", "private, max-age=0, must-revalidate"),
("Etag", "123456")]
return headers, '''
<!DOCTYPE html>
<html>
<head>
<script>
window.addEventListener("securitypolicyviolation", function(e) {
top.postMessage(e.originalPolicy, '*');
});
</script>
<script nonce="abc">
top.postMessage('abc_executed', '*');
</script>
<script nonce="def">
top.postMessage('def_executed', '*');
</script>
</head>
</html>
'''

View file

@ -35,6 +35,12 @@ main() {
exit 1
fi
# The maximum Unicode code point is U+10FFFF = 1114111
if [ `$PYTHON -c 'import sys; print(sys.maxunicode)'` != "1114111" ]; then
echo "UCS-4 support for Python is required"
exit 1
fi
virtualenv -p $PYTHON $VENV || { echo "Please ensure virtualenv is installed"; exit 2; }
fi

View file

@ -2,3 +2,4 @@ spec: https://drafts.csswg.org/css-align/
suggested_reviewers:
- dholbert
- emilio
- javifernandez

View file

@ -22,13 +22,13 @@
}
.flexbox > div {
background: red;
background: teal;
flex-grow: 1;
}
span {
.flexbox span {
height: 100%;
background: green;
background: orange;
display: block;
}
</style>
@ -38,19 +38,20 @@ span {
<body onload="checkLayout('.flexbox')">
<div id=log></div>
<p>You should see no red</p>
<!-- The wrapper divs are here to give the flexbox something to fill -->
<!-- This wrapper div is solely here to setup the max height so it can be computed consistently since body at 100% won't be consistent across devices -->
<!-- definite unwrapped column flexbox -->
<div style="height: 100px;">
<div class="flexbox column">
<div class="flexbox column" style="height: 0">
<div>
<span data-expected-height="100"></span>
</div>
</div>
</div>
<!-- definite wrapped column flexbox -->
<div style="height: 100px;">
<div class="flexbox column-wrap">
<div class="flexbox column-wrap" style="height: 0">
<div>
<span data-expected-height="50"></span>
</div>
@ -60,5 +61,26 @@ span {
</div>
</div>
<!-- indefinite unwrapped column flexbox -->
<div style="height: 100px;">
<div class="flexbox column">
<div>
<span data-expected-height="0"></span>
</div>
</div>
</div>
<!-- indefinite wrapped column flexbox -->
<div style="height: 100px;">
<div class="flexbox column-wrap">
<div>
<span data-expected-height="0"></span>
</div>
<div>
<span data-expected-height="0"></span>
</div>
</div>
</div>
</body>
</html>

View file

@ -9,8 +9,8 @@
<desc class="assert">Style properties on content elements of clipPath
must be ignored. A green square should be visible.</desc>
</g>
<clipPath id="clip1" clip-path="url(#clip1)">
<rect x="50" y="50" width="100" height="100" stroke="black" stroke-wdith="10" stroke-dasharray="10 10" fill="none"/>
<clipPath id="clip1">
<rect x="50" y="50" width="100" height="100" stroke="black" stroke-width="10" stroke-dasharray="10 10" fill="none"/>
</clipPath>
<rect width="200" height="200" fill="green" clip-path="url(#clip1)"/>
</svg>
</svg>

Before

Width:  |  Height:  |  Size: 907 B

After

Width:  |  Height:  |  Size: 884 B

Before After
Before After

View file

@ -0,0 +1,45 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Inheritance of CSS Multi-column Layout properties</title>
<link rel="help" href="https://drafts.csswg.org/css-multicol/#property-index">
<meta name="assert" content="Properties should not inherit.">
<meta name="assert" content="Properties have initial values according to the spec.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/inheritance-testcommon.js"></script>
</head>
<body>
<div id="reference"></div>
<div id="container">
<div id="target"></div>
</div>
<style>
#reference {
border-style: dotted; /* Avoid border-top-width computed style 0 */
border-top-width: medium;
}
#container {
color: rgba(42, 53, 64, 0.75);
column-rule-style: dotted; /* Avoid column-rule-width computed style 0 */
}
#target {
column-rule-style: dotted;
}
</style>
<script>
const mediumWidth = getComputedStyle(reference).borderTopWidth; // e.g. 3px
reference.style.display = 'none';
assert_not_inherited('column-count', 'auto', '2');
assert_not_inherited('column-fill', 'balance', 'auto');
assert_not_inherited('column-gap', 'normal', '10px');
assert_not_inherited('column-rule-color', 'rgba(42, 53, 64, 0.75)', 'rgba(2, 3, 5, 0.5)');
assert_not_inherited('column-rule-style', 'none', 'dashed');
assert_not_inherited('column-rule-width', mediumWidth, '10px');
assert_not_inherited('column-span', 'none', 'all');
assert_not_inherited('column-width', 'auto', '10px');
</script>
</body>
</html>

View file

@ -0,0 +1,19 @@
<!DOCTYPE html>
<link rel="author" title="Morten Stenshorne" href="mstensho@chromium.org">
<link rel="help" href="https://www.w3.org/TR/css-multicol-1/#filling-columns">
<link rel="help" href="https://www.w3.org/TR/css-break-3/#widows-orphans">
<meta name="assert" content="Make sure that orphans and widows handling inside an inner balanced multicol container doesn't get messed up by the constraining height of an outer multicol container">
<p>There should be three columns below. The text in each column should match the
column number that the text actually ends up in.</p>
<div style="columns:2; height:250px; line-height:50px; column-fill:auto;">
<div style="columns:3; column-rule:solid;" id="inner">
1<br>1<br>2<br>2<br>3<br>3<br>
</div>
</div>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
test(()=> {
assert_equals(inner.offsetHeight, 100);
}, "Check that orphans and widows don't make a multicol container taller than necessary");
</script>

View file

@ -25,12 +25,12 @@ assert_not_inherited('scroll-margin-right', '0px', '10px');
assert_not_inherited('scroll-margin-top', '0px', '10px');
assert_not_inherited('scroll-padding-block-end', 'auto', '10px');
assert_not_inherited('scroll-padding-block-start', 'auto', '10px');
assert_not_inherited('scroll-padding-bottom', '0px', '10px');
assert_not_inherited('scroll-padding-bottom', 'auto', '10px');
assert_not_inherited('scroll-padding-inline-end', 'auto', '10px');
assert_not_inherited('scroll-padding-inline-start', 'auto', '10px');
assert_not_inherited('scroll-padding-left', '0px', '10px');
assert_not_inherited('scroll-padding-right', '0px', '10px');
assert_not_inherited('scroll-padding-top', '0px', '10px');
assert_not_inherited('scroll-padding-left', 'auto', '10px');
assert_not_inherited('scroll-padding-right', 'auto', '10px');
assert_not_inherited('scroll-padding-top', 'auto', '10px');
assert_not_inherited('scroll-snap-align', 'none', 'start end');
assert_not_inherited('scroll-snap-stop', 'normal', 'always');
assert_not_inherited('scroll-snap-type', 'none', 'inline proximity');

View file

@ -458,15 +458,18 @@ function setupFonts(func) {
savedValues[key] = document.body.style.getPropertyValue(key);
document.body.style.setProperty(key, value);
});
func.apply(this, arguments);
each(fontProperties, function (key, value) {
if (value) {
document.body.style.setProperty(key, value);
}
else {
document.body.style.removeProperty(key);
}
});
try {
func.apply(this, arguments);
} finally {
each(savedValues, function (key, value) {
if (value) {
document.body.style.setProperty(key, value);
}
else {
document.body.style.removeProperty(key);
}
});
}
};
}

View file

@ -0,0 +1,35 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Inheritance of CSS Text properties</title>
<link rel="help" href="https://drafts.csswg.org/css-text/#property-index">
<meta name="assert" content="Properties inherit according to the spec.">
<meta name="assert" content="Properties have initial values according to the spec.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/inheritance-testcommon.js"></script>
</head>
<body>
<div id="container">
<div id="target"></div>
</div>
<script>
assert_inherited('hanging-punctuation', 'none', 'first last');
assert_inherited('hyphens', 'manual', 'none');
assert_inherited('letter-spacing', 'normal', '10px');
assert_inherited('line-break', 'auto', 'strict');
assert_inherited('overflow-wrap', 'normal', 'break-word');
assert_inherited('tab-size', '8', '10px');
assert_inherited('text-align-all', 'start', 'right');
assert_inherited('text-align-last', 'auto', 'right');
assert_inherited('text-indent', '0px', '10px');
assert_inherited('text-justify', 'auto', 'inter-character');
assert_inherited('text-transform', 'none', 'uppercase');
assert_inherited('white-space', 'normal', 'pre-wrap');
assert_inherited('word-break', 'normal', 'break-all');
assert_inherited('word-spacing', '0px', '10px');
assert_inherited('word-wrap', 'normal', 'break-word');
</script>
</body>
</html>

View file

@ -0,0 +1,36 @@
<!doctype html>
<meta charset="utf-8">
<title>Matrix interpolation</title>
<link rel="help" href="https://drafts.csswg.org/css-transforms-2/#interpolation-of-3d-matrices">
<meta name="assert" content="When interpolating between two matrices, each matrix is decomposed into the corresponding translation, rotation, scale, skew and (for a 3D matrix) perspective values">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/interpolation-testcommon.js"></script>
<body>
<script>
// Test interpolation of quaternions when the dot product is -1.
//
// We need to be particularly careful not to use a rotate function with a zero
// angle since the handling of zero angle rotations may change in future as per:
//
// https://github.com/w3c/csswg-drafts/issues/3236
//
// For rotateY(360deg) we should get a quaternion of:
// [ 0, sin(2 * PI / 2), 0, cos(2 * PI / 2) ]
// = [ 0, 0, 0, -1 ]
//
// For rotateX(720deg) we should get a quaternion of:
// [ 0, 0, sin(4 * PI / 2), cos(4 * PI / 2) ]
// = [ 0, 0, 0, 1 ]
//
// Dot product = 0 * 0 + 0 * 0 + 0 * 0 + 1 * -1 = -1
test_interpolation(
{
property: 'transform',
from: 'rotateY(360deg)',
to: 'rotateX(720deg)',
},
[{ at: 0.5, expect: 'matrix(1, 0, 0, 1, 0, 0)' }]
);
</script>
</body>

View file

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Inheritance of CSS Basic User Interface properties</title>
<link rel="help" href="https://drafts.csswg.org/css-ui/#property-index">
<meta name="assert" content="Properties inherit or not according to the spec.">
<meta name="assert" content="Properties have initial values according to the spec.">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/css/support/inheritance-testcommon.js"></script>
</head>
<body>
<div id="reference"></div>
<div id="container">
<div id="target"></div>
</div>
<style>
#reference {
border-style: dotted; /* Avoid border-top-width computed style 0 */
border-top-width: medium;
}
#container, #target {
outline-style: dotted; /* Avoid outline-width computed style 0 */
}
</style>
<script>
const mediumWidth = getComputedStyle(reference).borderTopWidth; // e.g. 3px
assert_not_inherited('appearance', 'auto', 'none');
assert_inherited('caret-color', 'auto', 'rgba(42, 53, 64, 0.75)');
assert_inherited('caret-shape', 'auto', 'bar');
assert_inherited('cursor', 'auto', 'pointer');
assert_not_inherited('nav-down', 'auto', '#foo');
assert_not_inherited('nav-left', 'auto', '#foo');
assert_not_inherited('nav-right', 'auto', '#foo');
assert_not_inherited('nav-up', 'auto', '#foo');
assert_not_inherited('outline-color', 'invert', 'rgba(42, 53, 64, 0.75)');
assert_not_inherited('outline-offset', '0px', '10px');
assert_not_inherited('outline-style', 'none', 'auto');
assert_not_inherited('outline-width', mediumWidth, '10px');
assert_not_inherited('resize', 'none', 'vertical');
assert_not_inherited('user-select', 'auto', 'none');
</script>
</body>
</html>

View file

@ -0,0 +1,36 @@
<!doctype html>
<title>CSS Test Reference.</title>
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
<link rel="author" title="Mozilla" href="https://mozilla.org">
<style>
* {
margin: 0;
padding: 0;
}
:root, #outer {
width: 100vw;
height: 100vh;
overflow: hidden;
}
#outer {
transform-origin: 0 0;
transform: scale(5);
}
#pad {
/* So that scaling by five it takes half of the viewport */
height: 10vh;
}
#filtered {
width: 100%;
height: 10vh;
background: green;
}
</style>
<div id="outer">
<div id="pad"></div>
<div id="filtered"></div>
</div>

View file

@ -0,0 +1,47 @@
<!doctype html>
<title>CSS Test: Blur filter scaling.</title>
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
<link rel="author" title="Mozilla" href="https://mozilla.org">
<link rel="help" href="https://drafts.fxtf.org/filter-effects/#FilterProperty">
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1224207">
<link rel="match" href="filter-scaling-001-ref.html">
<style>
* {
margin: 0;
padding: 0;
}
:root, #outer {
width: 100vw;
height: 100vh;
overflow: hidden;
}
#outer {
transform-origin: 0 0;
transform: scale(5);
}
#pad {
/* So that scaling by five it takes half of the viewport */
height: 10vh;
}
#filtered {
filter: url(#blur);
width: 100%;
height: 10vh;
background: green;
}
</style>
<div id="outer">
<div id="pad"></div>
<div id="filtered"></div>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<filter id="blur">
<feGaussianBlur in="SourceGraphic" stdDeviation="0,0"></feGaussianBlur>
</filter>
</defs>
</svg>
</div>

View file

@ -10,6 +10,14 @@ function assert_initial(property, initial) {
}, 'Property ' + property + ' has initial value ' + initial);
}
/**
* Create tests that a CSS property inherits and has the given initial value.
*
* @param {string} property The name of the CSS property being tested.
* @param {string} initial The computed value for 'initial'.
* @param {string} other An arbitrary value for the property that round
* trips and is distinct from the initial value.
*/
function assert_inherited(property, initial, other) {
assert_initial(property, initial);
@ -33,6 +41,15 @@ function assert_inherited(property, initial, other) {
}, 'Property ' + property + ' inherits');
}
/**
* Create tests that a CSS property does not inherit, and that it has the
* given initial value.
*
* @param {string} property The name of the CSS property being tested.
* @param {string} initial The computed value for 'initial'.
* @param {string} other An arbitrary value for the property that round
* trips and is distinct from the initial value.
*/
function assert_not_inherited(property, initial, other) {
assert_initial(property, initial);

View file

@ -0,0 +1,11 @@
---
layout: page
title: Email Filters
order: 3
---
See the [GitHub support page](https://help.github.com/articles/about-email-notifications/)
for how to filter certain types of email notifications. However, the most
useful `Cc` email address is not listed on that page:
`review_requested@noreply.github.com` is for when you are added as a reviewer
on a pull request.

View file

@ -20,10 +20,9 @@ context (and not therefore in any frame or window opened from it).
### action_sequence
Usage: `test_driver.action_sequence(actions)`
* `actions`: <[Array]<[Object]>> an array of Action objects`
* `action`: <[Object]> A single action. See [spec](https://www.w3.org/TR/webdriver/#actions) for format
* `actions`: an array of `Action` objects
This function causes a sequence of actions to be sent to the browser. It is based of the [WebDriver API](https://www.w3.org/TR/webdriver/#actions).
This function causes a sequence of actions to be sent to the browser. It is based of the [WebDriver API](https://w3c.github.io/webdriver/#actions).
The action can be a keyboard action, a pointer action or a pause. It returns a `Promise` that
resolves after the actions have been sent or rejects if an error was thrown.

View file

@ -3,6 +3,12 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<!-- First test shared pre-insertion checks that work similarly for replaceChild
and insertBefore -->
<script>
var insertFunc = Node.prototype.insertBefore;
</script>
<script src="pre-insertion-checks.js"></script>
<script>
function testLeafNode(nodeName, createNodeFunction) {
test(function() {

View file

@ -5,6 +5,12 @@
<script src="/resources/testharnessreport.js"></script>
<body><a><b></b><c></c></a>
<div id="log"></div>
<!-- First test shared pre-insertion checks that work similarly for replaceChild
and insertBefore -->
<script>
var insertFunc = Node.prototype.replaceChild;
</script>
<script src="pre-insertion-checks.js"></script>
<script>
// IDL.
test(function() {
@ -22,7 +28,7 @@ test(function() {
});
}, "Passing null to replaceChild should throw a TypeError.")
// Step 1.
// Step 3.
test(function() {
var a = document.createElement("div");
var b = document.createElement("div");
@ -39,14 +45,11 @@ test(function() {
assert_throws("NotFoundError", function() {
a.replaceChild(b, a);
});
}, "If child's parent is not the context node, a NotFoundError exception should be thrown")
}, "If child's parent is not the context node, a NotFoundError exception should be thrown");
// Step 1.
test(function() {
var nodes = [
document.implementation.createDocumentType("html", "", ""),
document.createTextNode("text"),
document.implementation.createDocument(null, "foo", null).createProcessingInstruction("foo", "bar"),
document.createComment("comment")
];
var nodes = getNonParentNodes();
var a = document.createElement("div");
var b = document.createElement("div");
@ -55,7 +58,7 @@ test(function() {
node.replaceChild(a, b);
});
});
}, "If the context node is not a node that can contain children, a NotFoundError exception should be thrown")
}, "If the context node is not a node that can contain children, a HierarchyRequestError exception should be thrown")
// Step 2.
test(function() {
@ -78,7 +81,7 @@ test(function() {
});
}, "If node is an inclusive ancestor of the context node, a HierarchyRequestError should be thrown.")
// Step 3.1.
// Steps 4/5.
test(function() {
var doc = document.implementation.createHTMLDocument("title");
var doc2 = document.implementation.createHTMLDocument("title2");
@ -91,7 +94,7 @@ test(function() {
});
}, "If the context node is a document, inserting a document or text node should throw a HierarchyRequestError.")
// Step 3.2.1.
// Step 6.1.
test(function() {
var doc = document.implementation.createHTMLDocument("title");
@ -127,7 +130,7 @@ test(function() {
});
}, "If the context node is a document (without element children), inserting a DocumentFragment that contains multiple elements should throw a HierarchyRequestError.")
// Step 3.2.2.
// Step 6.1.
test(function() {
// The context node has an element child that is not /child/.
var doc = document.implementation.createHTMLDocument("title");
@ -157,7 +160,7 @@ test(function() {
});
}, "If the context node is a document, inserting a DocumentFragment with an element before the doctype should throw a HierarchyRequestError.")
// Step 3.3.
// Step 6.2.
test(function() {
var doc = document.implementation.createHTMLDocument("title");
var comment = doc.appendChild(doc.createComment("foo"));
@ -183,7 +186,7 @@ test(function() {
});
}, "If the context node is a document, inserting an element before the doctype should throw a HierarchyRequestError.")
// Step 3.4.
// Step 6.3.
test(function() {
var doc = document.implementation.createHTMLDocument("title");
var comment = doc.insertBefore(doc.createComment("foo"), doc.firstChild);
@ -209,7 +212,7 @@ test(function() {
});
}, "If the context node is a document, inserting a doctype after the document element should throw a HierarchyRequestError.")
// Step 4.
// Steps 4/5.
test(function() {
var df = document.createDocumentFragment();
var a = df.appendChild(document.createElement("a"));
@ -342,4 +345,5 @@ test(function() {
parent.replaceChild(df, child);
assert_equals(document.getElementById(TEST_ID), fragChild, "should not be null");
}, "Replacing an element with a DocumentFragment should allow a child of the DocumentFragment to be found by Id.")
</script>

View file

@ -0,0 +1,108 @@
function getNonParentNodes() {
return [
document.implementation.createDocumentType("html", "", ""),
document.createTextNode("text"),
document.implementation.createDocument(null, "foo", null).createProcessingInstruction("foo", "bar"),
document.createComment("comment"),
document.implementation.createDocument(null, "foo", null).createCDATASection("data"),
];
}
function getNonInsertableNodes() {
return [
document.implementation.createHTMLDocument("title")
];
}
function getNonDocumentParentNodes() {
return [
document.createElement("div"),
document.createDocumentFragment(),
];
}
// Test that the steps happen in the right order, to the extent that it's
// observable. The variable names "parent", "child", and "node" match the
// corresponding variables in the replaceChild algorithm in these tests.
// Step 1 happens before step 3.
test(function() {
var illegalParents = getNonParentNodes();
var child = document.createElement("div");
var node = document.createElement("div");
illegalParents.forEach(function (parent) {
assert_throws("HierarchyRequestError", function() {
insertFunc.call(parent, node, child);
});
});
}, "Should check the 'parent' type before checking whether 'child' is a child of 'parent'");
// Step 2 happens before step 3.
test(function() {
var parent = document.createElement("div");
var child = document.createElement("div");
var node = document.createElement("div");
node.appendChild(parent);
assert_throws("HierarchyRequestError", function() {
insertFunc.call(parent, node, child);
});
}, "Should check that 'node' is not an ancestor of 'parent' before checking whether 'child' is a child of 'parent'");
// Step 3 happens before step 4.
test(function() {
var parent = document.createElement("div");
var child = document.createElement("div");
var illegalChildren = getNonInsertableNodes();
illegalChildren.forEach(function (node) {
assert_throws("NotFoundError", function() {
insertFunc.call(parent, node, child);
});
});
}, "Should check whether 'child' is a child of 'parent' before checking whether 'node' is of a type that can have a parent.");
// Step 3 happens before step 5.
test(function() {
var child = document.createElement("div");
var node = document.createTextNode("");
var parent = document.implementation.createDocument(null, "foo", null);
assert_throws("NotFoundError", function() {
insertFunc.call(parent, node, child);
});
node = document.implementation.createDocumentType("html", "", "");
getNonDocumentParentNodes().forEach(function (parent) {
assert_throws("NotFoundError", function() {
insertFunc.call(parent, node, child);
});
});
}, "Should check whether 'child' is a child of 'parent' before checking whether 'node' is of a type that can have a parent of the type that 'parent' is.");
// Step 3 happens before step 6.
test(function() {
var child = document.createElement("div");
var parent = document.implementation.createDocument(null, null, null);
var node = document.createDocumentFragment();
node.appendChild(document.createElement("div"));
node.appendChild(document.createElement("div"));
assert_throws("NotFoundError", function() {
insertFunc.call(parent, node, child);
});
node = document.createElement("div");
parent.appendChild(document.createElement("div"));
assert_throws("NotFoundError", function() {
insertFunc.call(parent, node, child);
});
parent.firstChild.remove();
parent.appendChild(document.implementation.createDocumentType("html", "", ""));
node = document.implementation.createDocumentType("html", "", "")
assert_throws("NotFoundError", function() {
insertFunc.call(parent, node, child);
});
}, "Should check whether 'child' is a child of 'parent' before checking whether 'node' can be inserted into the document given the kids the document has right now.");

View file

@ -0,0 +1,38 @@
<!DOCTYPE html>
<title>DOMParser: &lt;parsererror> element added on error</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
const xhtml_prologue = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"' +
' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n' +
'<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n' +
'<body>\n',
xhtml_epilogue = '</body>\n</html>\n';
[
'<span x:test="testing">1</span>', // undeclared 'x' namespace prefix
'< span>2</span>', // bad start tag
'<span :test="testing">3</span>', // empty namespace prefix
'<span><em>4</span></em>', // staggered tags
'<span>5', // missing end </span> tag
'6</span>', // missing start <span> tag
'<span>7< /span>', // bad end tag
'<span>8</ span>', // bad end tag
'<span novalue>9</span>', // missing attribute value
'<span ="noattr">10</span>', // missing attribute name
'<span ::="test">11</span>', // bad namespace prefix
'<span xmlns:="urn:x-test:test">12</span>', // missing namespace prefix
'<span xmlns:xmlns="">13</span>', // invalid namespace prefix
'<span data-test=testing>14</span>', // unquoted attribute value
'15<span', // bad start tag
'<8:test xmlns:8="urn:x-test:test">16</8:test>', // invalid namespace prefix
'<span xmlns:p1 xmlns:p2="urn:x-test:test"/>17', // missing namespace URI
].forEach(fragment => {
test(() => {
var document_string = xhtml_prologue + fragment + xhtml_epilogue;
var doc = (new DOMParser).parseFromString(document_string, "application/xhtml+xml");
var parsererrors = doc.getElementsByTagName("parsererror");
assert_equals(parsererrors.length, 1, 'expecting one parsererror');
}, document.title + ', ' + fragment);
});
</script>

View file

@ -0,0 +1,11 @@
def main(request, response):
body = request.GET.first("body", None)
type = request.GET.first("type", None)
response.add_required_headers = False
response.writer.write_status(200)
response.writer.write_header("content-length", len(body))
response.writer.write_header("content-type", type)
response.writer.end_headers()
response.writer.write(body)

View file

@ -0,0 +1,83 @@
<!DOCTYPE html>
<!-- Test verifies CORB will block responses beginning with a JSON parser
breaker regardless of their MIME type (excluding text/css - see below).
A JSON parser breaker is a prefix added to resources with sensitive data to
prevent cross-site script inclusion (XSSI) and similar attacks. For example,
it may be included in JSON files to prevent them from leaking data via a
<script> tag, making the response only useful to a fetch or XmlHttpRequest.
See also https://chromium.googlesource.com/chromium/src/+/master/services/network/cross_origin_read_blocking_explainer.md#Protecting-JSON
The assumption is that all images, other media, scripts, fonts and other
resources that may be embedded cross-origin will never begin with a JSON
parser breaker. For example an JPEG image should always being with FF D8 FF,
a PNG image with 89 50 4E 47 0D 0A 1A 0A bytes and an SVG image with "<?xml"
substring.
The assumption above excludes text/css which (as shown by
style-css-with-json-parser-breaker.sub.html) can parse as valid stylesheet
even in presence of a JSON parser breaker.
-->
<meta charset="utf-8">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id=log></div>
<script>
setup({allow_uncaught_exception : true});
// A subset of JSON security prefixes (only ones that are parser breakers).
json_parser_breakers = [
")]}'",
"{}&&",
"{} &&",
]
// JSON parser breaker should trigger CORB blocking for any Content-Type - even
// for resources that claim to be of a MIME type that is normally allowed to be
// embedded in cross-origin documents (like images and/or scripts).
mime_types = [
// CORB-protected MIME types
"text/html",
"text/xml",
"text/json",
"text/plain",
// MIME types that normally are allowed by CORB.
"application/javascript",
"image/png",
"image/svg+xml",
// Other types.
"application/pdf",
"application/zip",
]
function test(mime_type, body) {
async_test(function(t) {
var script = document.createElement("script")
// Without CORB, the JSON parser breaker would cause a syntax error when
// parsed as JavaScript, but with CORB there should be no errors (because
// CORB will replace the response body with an empty body).
script.onload = t.step_func_done(function(){})
addEventListener("error",function(e) {
t.step(function() {
assert_unreached("Empty body of a CORS-blocked response shouldn't trigger syntax errors.");
t.done();
})
});
// www1 is cross-origin, so the HTTP response is CORB-eligible.
var src_prefix = "http://{{domains[www1]}}:{{ports[http][0]}}/fetch/corb/resources/sniffable-resource.py";
script.src = src_prefix + "?type=" + mime_type + "&body=" + encodeURIComponent(body);
document.body.appendChild(script)
}, "CORB-blocks '" + mime_type + "' that starts with the following JSON parser breaker: " + body);
}
mime_types.forEach(function(type) {
json_parser_breakers.forEach(function(body) {
test(type, body);
});
});
</script>

View file

@ -120,6 +120,36 @@
}
]
},
{
name: "Content-* header",
requests: [
{
response_headers: [
["Expires", -5000],
["ETag", "GHI"],
["Content-Test-Header", "A"]
]
},
{
response_headers: [
["Expires", 3000],
["ETag", "GHI"],
["Content-Test-Header", "B"]
],
expected_type: "etag_validated",
expected_response_headers: [
["Content-Test-Header", "B"]
],
pause_after: true
},
{
expected_type: "cached",
expected_response_headers: [
["Content-Test-Header", "B"]
]
}
]
},
];
run_tests(tests);
</script>

View file

@ -3,6 +3,5 @@ suggested_reviewers:
- zqzhang
- dontcallmedom
- riju
- alexshalamov
- rakuco
- Honry

View file

@ -4,5 +4,4 @@ suggested_reviewers:
- dontcallmedom
- riju
- Honry
- alexshalamov
- rakuco

View file

@ -116,7 +116,7 @@ idl_test(
CanvasGradient: [],
CanvasPattern: [],
TextMetrics: [],
ImageData: [],
ImageData: ['new ImageData(10, 10)'],
HTMLMapElement: ['document.createElement("map")'],
HTMLAreaElement: ['document.createElement("area")'],
HTMLTableElement: ['document.createElement("table")'],

View file

@ -41,7 +41,9 @@ partial interface Window {
// client
[Replaceable] readonly attribute long screenX;
[Replaceable] readonly attribute long screenLeft;
[Replaceable] readonly attribute long screenY;
[Replaceable] readonly attribute long screenTop;
[Replaceable] readonly attribute long outerWidth;
[Replaceable] readonly attribute long outerHeight;
[Replaceable] readonly attribute double devicePixelRatio;

View file

@ -4,5 +4,4 @@ suggested_reviewers:
- dontcallmedom
- riju
- Honry
- alexshalamov
- rakuco

View file

@ -86,6 +86,9 @@ function bindEvents(element, resolveEventName, rejectEventName) {
resolve(e);
});
element.addEventListener(rejectEventName || "error", function(e) {
// Chromium starts propagating errors from worker.onerror to
// window.onerror. This handles the uncaught exceptions in tests.
e.preventDefault();
reject(e);
});
});

View file

@ -4,5 +4,4 @@ suggested_reviewers:
- dontcallmedom
- riju
- Honry
- alexshalamov
- rakuco

View file

@ -14,6 +14,9 @@ promise_test(async t => {
.then(pipWindow => {
assert_not_equals(pipWindow.width, 0);
assert_not_equals(pipWindow.height, 0);
const videoAspectRatio = video.videoWidth / video.videoHeight;
const pipWindowAspectRatio = pipWindow.width / pipWindow.height;
assert_equals(videoAspectRatio, pipWindowAspectRatio);
});
}, 'Picture-in-Picture window dimensions are set after entering Picture-in-Picture');

Some files were not shown because too many files have changed in this diff Show more