Diff
Modified: trunk/LayoutTests/ChangeLog (223924 => 223925)
--- trunk/LayoutTests/ChangeLog 2017-10-24 21:35:30 UTC (rev 223924)
+++ trunk/LayoutTests/ChangeLog 2017-10-24 21:46:41 UTC (rev 223925)
@@ -1,3 +1,27 @@
+2017-10-24 Dean Jackson <d...@apple.com>
+
+ Implement resizing options for ImageBitmap rendering
+ https://bugs.webkit.org/show_bug.cgi?id=178687
+ <rdar://problem/35135417>
+
+ Reviewed by Sam Weinig.
+
+ More ImageBitmap tests, this time focusing on sizing.
+
+ * http/wpt/2dcontext/imagebitmap/common.js:
+ (createCanvasOfSize):
+ (create9x9CanvasWith2dContext):
+ (create18x18CanvasWith2dContext):
+
+ Helper functions.
+
+ * http/wpt/2dcontext/imagebitmap/createImageBitmap-sizing-expected.txt: Added.
+ * http/wpt/2dcontext/imagebitmap/createImageBitmap-sizing.html: Added.
+ * http/wpt/2dcontext/imagebitmap/drawImage-ImageBitmap.html:
+ * http/wpt/2dcontext/imagebitmap/resources/target-blue-dot-no-intrinsic.svg: Added.
+ * http/wpt/2dcontext/imagebitmap/resources/target-blue-dot.png: Renamed from LayoutTests/http/wpt/2dcontext/imagebitmap/target-blue-dot.png.
+ * http/wpt/2dcontext/imagebitmap/resources/target-blue-dot.svg: Added.
+
2017-10-24 Chris Dumez <cdu...@apple.com>
Add initial implementation for serviceWorker.postMessage()
Modified: trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/common.js (223924 => 223925)
--- trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/common.js 2017-10-24 21:35:30 UTC (rev 223924)
+++ trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/common.js 2017-10-24 21:46:41 UTC (rev 223925)
@@ -57,10 +57,22 @@
imgData.data[i * width * 4 + j * 4 + 2] = 255;
}
+function createCanvasOfSize(width, height)
+{
+ const c = document.createElement("canvas");
+ c.width = width;
+ c.height = height;
+ return c;
+}
+
function create9x9CanvasWith2dContext()
{
- let c = document.createElement("canvas");
- c.width = 9;
- c.height = 9;
+ const c = createCanvasOfSize(9, 9);
return [c, c.getContext("2d")];
}
+
+function create18x18CanvasWith2dContext()
+{
+ const c = createCanvasOfSize(18, 18);
+ return [c, c.getContext("2d")];
+}
Added: trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/createImageBitmap-sizing-expected.txt (0 => 223925)
--- trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/createImageBitmap-sizing-expected.txt (rev 0)
+++ trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/createImageBitmap-sizing-expected.txt 2017-10-24 21:46:41 UTC (rev 223925)
@@ -0,0 +1,11 @@
+
+PASS createImageBitmap rejects with TypeError if resizeWidth is negative
+PASS createImageBitmap rejects with TypeError if resizeHeight is negative
+PASS createImageBitmap with cropped source
+PASS createImageBitmap with a cropping rectangle that is bigger than the source
+PASS createImageBitmap with resizeWidth and resizeHeight
+PASS createImageBitmap with only resizeHeight should calculate resizeWidth
+PASS createImageBitmap with only resizeWidth should calculate resizeHeight
+PASS createImageBitmap with an SVG uses intrinsic size
+PASS createImageBitmap with an SVG that has no intrinsic size uses resize parameters
+
Property changes on: trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/createImageBitmap-sizing-expected.txt
___________________________________________________________________
Added: svn:eol-style
+native
\ No newline at end of property
Added: svn:keywords
+Date Revision
\ No newline at end of property
Added: svn:mime-type
+text/plain
\ No newline at end of property
Added: trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/createImageBitmap-sizing.html (0 => 223925)
--- trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/createImageBitmap-sizing.html (rev 0)
+++ trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/createImageBitmap-sizing.html 2017-10-24 21:46:41 UTC (rev 223925)
@@ -0,0 +1,189 @@
+<!DOCTYPE html>
+<html>
+<title>createImageBitmap with sizing test</title>
+<script src=""
+<script src=""
+<script src=""
+<script src=""
+<link rel="stylesheet" href=""
+<body>
+<script>
+(function() {
+
+ // The ImageBitmap part of the HTML specification says this should be an InvalidStateError, but
+ // the IDL requires an unsigned value, so the TypeError will hit first.
+ promise_test(function(t) {
+ return promise_rejects(t, new TypeError, createImageBitmap(new Image(), 0, 0, 10, 10, { resizeWidth: -10, resizeHeight: 10 }));
+ }, "createImageBitmap rejects with TypeError if resizeWidth is negative");
+
+ promise_test(function(t) {
+ return promise_rejects(t, new TypeError, createImageBitmap(new Image(), 0, 0, 10, 10, { resizeWidth: 10, resizeHeight: -10 }));
+ }, "createImageBitmap rejects with TypeError if resizeHeight is negative");
+
+ promise_test(function() {
+ return new Promise(function(resolve, reject) {
+ let img = new Image();
+ img._onload_ = function() { resolve(img); };
+ img.src = ""
+ }).then(function(img) {
+ // Crop the 9x9 image into 5x5.
+ return createImageBitmap(img, 0, 0, 5, 5);
+ }).then(function(imageBitmap) {
+ assert_equals(imageBitmap.width, 5, "ImageBitmap width should be 5");
+ assert_equals(imageBitmap.height, 5, "ImageBitmap height should be 5");
+
+ let [canvas, ctx] = create9x9CanvasWith2dContext();
+ ctx.drawImage(imageBitmap, 0, 0);
+ _assertPixel(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255");
+ _assertPixel(canvas, 4,3, 0,255,0,255, "4,3", "0,255,0,255");
+ _assertPixel(canvas, 3,4, 0,255,0,255, "3,4", "0,255,0,255");
+ _assertPixel(canvas, 4,4, 0,0,255,255, "4,4", "0,0,255,255"); // Target blue dot.
+ _assertPixel(canvas, 5,4, 0,0,0,0, "5,4", "0,0,0,0"); // Outside source rectangle so transparent.
+ _assertPixel(canvas, 4,5, 0,0,0,0, "4,5", "0,0,0,0"); // Outside source rectangle so transparent.
+ });
+ }, "createImageBitmap with cropped source");
+
+ promise_test(function() {
+ return new Promise(function(resolve, reject) {
+ let img = new Image();
+ img._onload_ = function() { resolve(img); };
+ img.src = ""
+ }).then(function(img) {
+ // Source is only 9x9, so the 100x100 will be clamped.
+ return createImageBitmap(img, 0, 0, 100, 100);
+ }).then(function(imageBitmap) {
+ assert_equals(imageBitmap.width, 9, "ImageBitmap width should be 9");
+ assert_equals(imageBitmap.height, 9, "ImageBitmap height should be 9");
+
+ let [canvas, ctx] = create9x9CanvasWith2dContext();
+ ctx.drawImage(imageBitmap, 0, 0);
+ _assertPixel(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255");
+ _assertPixel(canvas, 4,3, 0,255,0,255, "4,3", "0,255,0,255");
+ _assertPixel(canvas, 3,4, 0,255,0,255, "3,4", "0,255,0,255");
+ _assertPixel(canvas, 4,4, 0,0,255,255, "4,4", "0,0,255,255"); // Target blue dot.
+ _assertPixel(canvas, 5,4, 0,255,0,255, "5,4", "0,255,0,255");
+ _assertPixel(canvas, 4,5, 0,255,0,255, "4,5", "0,255,0,255");
+ });
+ }, "createImageBitmap with a cropping rectangle that is bigger than the source");
+
+ promise_test(function() {
+ return new Promise(function(resolve, reject) {
+ let img = new Image();
+ img._onload_ = function() { resolve(img); };
+ img.src = ""
+ }).then(function(img) {
+ // Resize the 9x9 into 18x18, but without interpolation so that
+ // we can still do accurate pixel tests.
+ return createImageBitmap(img, 0, 0, 9, 9, { resizeWidth: 18, resizeHeight: 18, resizeQuality: "pixelated" });
+ }).then(function(imageBitmap) {
+ assert_equals(imageBitmap.width, 18, "ImageBitmap width should be 18");
+ assert_equals(imageBitmap.height, 18, "ImageBitmap height should be 18");
+
+ let [canvas, ctx] = create18x18CanvasWith2dContext();
+ ctx.drawImage(imageBitmap, 0, 0);
+ // All the target points are now 2x what they would be normally.
+ _assertPixel(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255");
+ _assertPixel(canvas, 8,6, 0,255,0,255, "8,6", "0,255,0,255");
+ _assertPixel(canvas, 6,8, 0,255,0,255, "6,8", "0,255,0,255");
+ _assertPixel(canvas, 8,8, 0,0,255,255, "8,8", "0,0,255,255"); // Target blue dot.
+ _assertPixel(canvas, 9,9, 0,0,255,255, "9,9", "0,0,255,255"); // Target blue dot.
+ _assertPixel(canvas, 10,8, 0,255,0,255, "10,8", "0,255,0,255");
+ _assertPixel(canvas, 8,10, 0,255,0,255, "8,10", "0,255,0,255");
+
+ });
+ }, "createImageBitmap with resizeWidth and resizeHeight");
+
+ promise_test(function() {
+ return new Promise(function(resolve, reject) {
+ let img = new Image();
+ img._onload_ = function() { resolve(img); };
+ img.src = ""
+ }).then(function(img) {
+ // Only provide resizeHeight.
+ return createImageBitmap(img, 0, 0, 9, 9, { resizeHeight: 18, resizeQuality: "pixelated" });
+ }).then(function(imageBitmap) {
+ assert_equals(imageBitmap.width, 18, "ImageBitmap width should be 18");
+ assert_equals(imageBitmap.height, 18, "ImageBitmap height should be 18");
+
+ let [canvas, ctx] = create18x18CanvasWith2dContext();
+ ctx.drawImage(imageBitmap, 0, 0);
+ // All the target points are now 2x what they would be normally.
+ _assertPixel(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255");
+ _assertPixel(canvas, 8,6, 0,255,0,255, "8,6", "0,255,0,255");
+ _assertPixel(canvas, 6,8, 0,255,0,255, "6,8", "0,255,0,255");
+ _assertPixel(canvas, 8,8, 0,0,255,255, "8,8", "0,0,255,255"); // Target blue dot.
+ _assertPixel(canvas, 9,9, 0,0,255,255, "9,9", "0,0,255,255"); // Target blue dot.
+ _assertPixel(canvas, 10,8, 0,255,0,255, "10,8", "0,255,0,255");
+ _assertPixel(canvas, 8,10, 0,255,0,255, "8,10", "0,255,0,255");
+
+ });
+ }, "createImageBitmap with only resizeHeight should calculate resizeWidth");
+
+ promise_test(function() {
+ return new Promise(function(resolve, reject) {
+ let img = new Image();
+ img._onload_ = function() { resolve(img); };
+ img.src = ""
+ }).then(function(img) {
+ // Only provide resizeWidth.
+ return createImageBitmap(img, 0, 0, 9, 9, { resizeWidth: 18, resizeQuality: "pixelated" });
+ }).then(function(imageBitmap) {
+ assert_equals(imageBitmap.width, 18, "ImageBitmap width should be 18");
+ assert_equals(imageBitmap.height, 18, "ImageBitmap height should be 18");
+
+ let [canvas, ctx] = create18x18CanvasWith2dContext();
+ ctx.drawImage(imageBitmap, 0, 0);
+ // All the target points are now 2x what they would be normally.
+ _assertPixel(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255");
+ _assertPixel(canvas, 8,6, 0,255,0,255, "8,6", "0,255,0,255");
+ _assertPixel(canvas, 6,8, 0,255,0,255, "6,8", "0,255,0,255");
+ _assertPixel(canvas, 8,8, 0,0,255,255, "8,8", "0,0,255,255"); // Target blue dot.
+ _assertPixel(canvas, 9,9, 0,0,255,255, "9,9", "0,0,255,255"); // Target blue dot.
+ _assertPixel(canvas, 10,8, 0,255,0,255, "10,8", "0,255,0,255");
+ _assertPixel(canvas, 8,10, 0,255,0,255, "8,10", "0,255,0,255");
+
+ });
+ }, "createImageBitmap with only resizeWidth should calculate resizeHeight");
+
+ promise_test(function() {
+ return new Promise(function(resolve, reject) {
+ let img = new Image();
+ img._onload_ = function() { resolve(img); };
+ img.src = ""
+ }).then(function(img) {
+ return createImageBitmap(img);
+ }).then(function(imageBitmap) {
+ let [canvas, ctx] = create9x9CanvasWith2dContext();
+ ctx.drawImage(imageBitmap, 0, 0);
+ _assertPixel(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255");
+ _assertPixel(canvas, 4,3, 0,255,0,255, "4,3", "0,255,0,255");
+ _assertPixel(canvas, 3,4, 0,255,0,255, "3,4", "0,255,0,255");
+ _assertPixel(canvas, 4,4, 0,0,255,255, "4,4", "0,0,255,255"); // Target blue dot.
+ _assertPixel(canvas, 5,4, 0,255,0,255, "5,4", "0,255,0,255");
+ _assertPixel(canvas, 4,5, 0,255,0,255, "4,5", "0,255,0,255");
+ });
+ }, "createImageBitmap with an SVG uses intrinsic size");
+
+ promise_test(function() {
+ return new Promise(function(resolve, reject) {
+ let img = new Image();
+ img._onload_ = function() { resolve(img); };
+ img.src = ""
+ }).then(function(img) {
+ return createImageBitmap(img, { resizeWidth: 9, resizeHeight: 9 });
+ }).then(function(imageBitmap) {
+ let [canvas, ctx] = create9x9CanvasWith2dContext();
+ ctx.drawImage(imageBitmap, 0, 0);
+ _assertPixel(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255");
+ _assertPixel(canvas, 4,3, 0,255,0,255, "4,3", "0,255,0,255");
+ _assertPixel(canvas, 3,4, 0,255,0,255, "3,4", "0,255,0,255");
+ _assertPixel(canvas, 4,4, 0,0,255,255, "4,4", "0,0,255,255"); // Target blue dot.
+ _assertPixel(canvas, 5,4, 0,255,0,255, "5,4", "0,255,0,255");
+ _assertPixel(canvas, 4,5, 0,255,0,255, "4,5", "0,255,0,255");
+ });
+ }, "createImageBitmap with an SVG that has no intrinsic size uses resize parameters");
+
+})();
+</script>
+</body>
+</html>
Property changes on: trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/createImageBitmap-sizing.html
___________________________________________________________________
Added: svn:eol-style
+native
\ No newline at end of property
Added: svn:keywords
+Date Revision
\ No newline at end of property
Added: svn:mime-type
+text/html
\ No newline at end of property
Modified: trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/createImageBitmap.html (223924 => 223925)
--- trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/createImageBitmap.html 2017-10-24 21:35:30 UTC (rev 223924)
+++ trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/createImageBitmap.html 2017-10-24 21:46:41 UTC (rev 223925)
@@ -30,7 +30,7 @@
promise_test(function() {
return new Promise(function(resolve, reject) {
- var img = new Image();
+ let img = new Image();
img._onload_ = function() { resolve(img); };
img.src = ""
}).then(function(img) {
@@ -43,7 +43,7 @@
promise_test(function() {
return new Promise(function(resolve, reject) {
- var img = new Image();
+ let img = new Image();
img._onload_ = function() { resolve(img); };
img.src = ""
}).then(function(img) {
Modified: trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/drawImage-ImageBitmap.html (223924 => 223925)
--- trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/drawImage-ImageBitmap.html 2017-10-24 21:35:30 UTC (rev 223924)
+++ trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/drawImage-ImageBitmap.html 2017-10-24 21:46:41 UTC (rev 223925)
@@ -8,7 +8,7 @@
<link rel="stylesheet" href=""
<body>
<script>
-// The target-blue-dot.png image is a 9x9 bitmap with a #00ff00 background
+// The resources/target-blue-dot.png image is a 9x9 bitmap with a #00ff00 background
// and a single #0000ff pixel right in the middle (at 4,4).
(function() {
@@ -16,7 +16,7 @@
return new Promise(function(resolve, reject) {
let img = new Image();
img._onload_ = function() { resolve(img); };
- img.src = ""
+ img.src = ""
}).then(function(img) {
return createImageBitmap(img);
}).then(function(imageBitmap) {
@@ -23,11 +23,11 @@
let [canvas, ctx] = create9x9CanvasWith2dContext();
ctx.drawImage(imageBitmap, 0, 0);
_assertPixel(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255");
- _assertPixel(canvas, 4,3, 0,255,0,255, "0,0", "0,255,0,255");
- _assertPixel(canvas, 3,4, 0,255,0,255, "0,0", "0,255,0,255");
- _assertPixel(canvas, 4,4, 0,0,255,255, "5,5", "0,0,255,255"); // Target blue dot.
- _assertPixel(canvas, 5,4, 0,255,0,255, "0,0", "0,255,0,255");
- _assertPixel(canvas, 4,5, 0,255,0,255, "0,0", "0,255,0,255");
+ _assertPixel(canvas, 4,3, 0,255,0,255, "4,3", "0,255,0,255");
+ _assertPixel(canvas, 3,4, 0,255,0,255, "3,4", "0,255,0,255");
+ _assertPixel(canvas, 4,4, 0,0,255,255, "4,4", "0,0,255,255"); // Target blue dot.
+ _assertPixel(canvas, 5,4, 0,255,0,255, "5,4", "0,255,0,255");
+ _assertPixel(canvas, 4,5, 0,255,0,255, "4,5", "0,255,0,255");
});
}, "drawImage of ImageBitmap");
@@ -35,7 +35,7 @@
return new Promise(function(resolve, reject) {
let img = new Image();
img._onload_ = function() { resolve(img); };
- img.src = ""
+ img.src = ""
}).then(function(img) {
return createImageBitmap(img);
}).then(function(imageBitmap) {
@@ -42,11 +42,11 @@
let [canvas, ctx] = create9x9CanvasWith2dContext();
ctx.drawImage(imageBitmap, 0, 0, 5, 5, 0, 0, 5, 5);
_assertPixel(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255");
- _assertPixel(canvas, 4,3, 0,255,0,255, "0,0", "0,255,0,255");
- _assertPixel(canvas, 3,4, 0,255,0,255, "0,0", "0,255,0,255");
- _assertPixel(canvas, 4,4, 0,0,255,255, "5,5", "0,0,255,255"); // Target blue dot.
- _assertPixel(canvas, 5,4, 0,0,0,0, "0,0", "0,0,0,0"); // Didn't draw into these parts.
- _assertPixel(canvas, 4,5, 0,0,0,0, "0,0", "0,0,0,0");
+ _assertPixel(canvas, 4,3, 0,255,0,255, "4,3", "0,255,0,255");
+ _assertPixel(canvas, 3,4, 0,255,0,255, "3,4", "0,255,0,255");
+ _assertPixel(canvas, 4,4, 0,0,255,255, "4,4", "0,0,255,255"); // Target blue dot.
+ _assertPixel(canvas, 5,4, 0,0,0,0, "5,4", "0,0,0,0"); // Didn't draw into these parts.
+ _assertPixel(canvas, 4,5, 0,0,0,0, "4,5", "0,0,0,0");
});
}, "drawImage of ImageBitmap with cropping");
@@ -54,7 +54,7 @@
return new Promise(function(resolve, reject) {
let img = new Image();
img._onload_ = function() { resolve(img); };
- img.src = ""
+ img.src = ""
}).then(function(img) {
return createImageBitmap(img);
}).then(function(imageBitmap) {
@@ -61,12 +61,12 @@
let [canvas, ctx] = create9x9CanvasWith2dContext();
ctx.drawImage(imageBitmap, 2, 2, 5, 5, 0, 0, 5, 5);
_assertPixel(canvas, 0,0, 0,255,0,255, "0,0", "0,255,0,255");
- _assertPixel(canvas, 2,1, 0,255,0,255, "0,0", "0,255,0,255");
- _assertPixel(canvas, 1,2, 0,255,0,255, "0,0", "0,255,0,255");
- _assertPixel(canvas, 2,2, 0,0,255,255, "5,5", "0,0,255,255");
- _assertPixel(canvas, 3,2, 0,255,0,255, "0,0", "0,255,0,255");
- _assertPixel(canvas, 2,3, 0,255,0,255, "0,0", "0,255,0,255");
- _assertPixel(canvas, 8,8, 0,0,0,0, "0,0", "0,0,0,0");
+ _assertPixel(canvas, 2,1, 0,255,0,255, "2,1", "0,255,0,255");
+ _assertPixel(canvas, 1,2, 0,255,0,255, "1,2", "0,255,0,255");
+ _assertPixel(canvas, 2,2, 0,0,255,255, "2,2", "0,0,255,255");
+ _assertPixel(canvas, 3,2, 0,255,0,255, "3,2", "0,255,0,255");
+ _assertPixel(canvas, 2,3, 0,255,0,255, "2,3", "0,255,0,255");
+ _assertPixel(canvas, 8,8, 0,0,0,0, "8,8", "0,0,0,0");
});
}, "drawImage of ImageBitmap with cropping and different origin");
@@ -74,7 +74,7 @@
return new Promise(function(resolve, reject) {
let img = new Image();
img._onload_ = function() { resolve(img); };
- img.src = ""
+ img.src = ""
}).then(function(img) {
return createImageBitmap(img);
}).then(function(imageBitmap) {
@@ -81,12 +81,12 @@
let [canvas, ctx] = create9x9CanvasWith2dContext();
ctx.drawImage(imageBitmap, 2, 2, 5, 5, 2, 2, 5, 5);
_assertPixel(canvas, 0,0, 0,0,0,0, "0,0", "0,0,0,0"); // Didn't draw here.
- _assertPixel(canvas, 4,3, 0,255,0,255, "0,0", "0,255,0,255");
- _assertPixel(canvas, 3,4, 0,255,0,255, "0,0", "0,255,0,255");
- _assertPixel(canvas, 4,4, 0,0,255,255, "5,5", "0,0,255,255"); // Target blue dot.
- _assertPixel(canvas, 5,4, 0,255,0,255, "0,0", "0,255,0,255");
- _assertPixel(canvas, 4,5, 0,255,0,255, "0,0", "0,255,0,255");
- _assertPixel(canvas, 8,8, 0,0,0,0, "0,0", "0,0,0,0");
+ _assertPixel(canvas, 4,3, 0,255,0,255, "4,3", "0,255,0,255");
+ _assertPixel(canvas, 3,4, 0,255,0,255, "3,4", "0,255,0,255");
+ _assertPixel(canvas, 4,4, 0,0,255,255, "4,4", "0,0,255,255"); // Target blue dot.
+ _assertPixel(canvas, 5,4, 0,255,0,255, "5,4", "0,255,0,255");
+ _assertPixel(canvas, 4,5, 0,255,0,255, "4,5", "0,255,0,255");
+ _assertPixel(canvas, 8,8, 0,0,0,0, "8,8", "0,0,0,0");
});
}, "drawImage of ImageBitmap with cropping and different non-zero origin");
@@ -97,13 +97,13 @@
return new Promise(function(resolve, reject) {
let img = new Image();
img._onload_ = function() { resolve(img); };
- img.src = ""
+ img.src = ""
}).then(function(img) {
return createImageBitmap(img);
}).then(function(imageBitmap) {
imageBitmap.close();
let [canvas, ctx] = create9x9CanvasWith2dContext();
- assert_throws('InvalidStateError', function () {
+ assert_throws("InvalidStateError", function () {
ctx.drawImage(imageBitmap, 0, 0);
}, "A closed ImageBitmap can't be drawn.");
});
@@ -113,12 +113,12 @@
return new Promise(function(resolve, reject) {
let img = new Image();
img._onload_ = function() { resolve(img); };
- img.src = ""
+ img.src = ""
}).then(function(img) {
return createImageBitmap(img);
}).then(function(imageBitmap) {
let [canvas, ctx] = create9x9CanvasWith2dContext();
- assert_throws('IndexSizeError', function () {
+ assert_throws("IndexSizeError", function () {
ctx.drawImage(imageBitmap, 0, 0, 0, 0, 0, 0, 9, 9);
}, "drawImage with an empty source rectangle should fail.");
});
Added: trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/resources/target-blue-dot-no-intrinsic.svg (0 => 223925)
--- trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/resources/target-blue-dot-no-intrinsic.svg (rev 0)
+++ trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/resources/target-blue-dot-no-intrinsic.svg 2017-10-24 21:46:41 UTC (rev 223925)
@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 9 9">
+ <rect width="9" height="9" fill="#00ff00"/>
+ <rect x="4" y="4" width="1" height="1" fill="#0000ff"/>
+</svg>
Property changes on: trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/resources/target-blue-dot-no-intrinsic.svg
___________________________________________________________________
Added: svn:eol-style
+native
\ No newline at end of property
Added: svn:keywords
+Date Revision
\ No newline at end of property
Added: svn:mime-type
+text/xml
\ No newline at end of property
Copied: trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/resources/target-blue-dot.png (from rev 223924, trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/target-blue-dot.png)
(Binary files differ)
Added: trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/resources/target-blue-dot.svg (0 => 223925)
--- trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/resources/target-blue-dot.svg (rev 0)
+++ trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/resources/target-blue-dot.svg 2017-10-24 21:46:41 UTC (rev 223925)
@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="9" height="9" viewBox="0 0 9 9">
+ <rect width="9" height="9" fill="#00ff00"/>
+ <rect x="4" y="4" width="1" height="1" fill="#0000ff"/>
+</svg>
Property changes on: trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/resources/target-blue-dot.svg
___________________________________________________________________
Added: svn:eol-style
+native
\ No newline at end of property
Added: svn:keywords
+Date Revision
\ No newline at end of property
Added: svn:mime-type
+text/xml
\ No newline at end of property
Deleted: trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/target-blue-dot.png
(Binary files differ)
Modified: trunk/Source/WebCore/ChangeLog (223924 => 223925)
--- trunk/Source/WebCore/ChangeLog 2017-10-24 21:35:30 UTC (rev 223924)
+++ trunk/Source/WebCore/ChangeLog 2017-10-24 21:46:41 UTC (rev 223925)
@@ -1,3 +1,37 @@
+2017-10-24 Dean Jackson <d...@apple.com>
+
+ Implement resizing options for ImageBitmap rendering
+ https://bugs.webkit.org/show_bug.cgi?id=178687
+ <rdar://problem/35135417>
+
+ Reviewed by Sam Weinig.
+
+ Implement many of the sizing options for createImageBitmap.
+
+ Test: http/wpt/2dcontext/imagebitmap/createImageBitmap-sizing.html
+
+ * html/ImageBitmap.cpp:
+ (WebCore::croppedSourceRectangleWithFormatting):
+
+ Implement the first bit of the algorithm from
+ the HTML specification.
+
+ (WebCore::outputSizeForSourceRectangle):
+
+ ... and then the second bit. Leave the rest in
+ comments for now.
+
+ (WebCore::interpolationQualityForResizeQuality):
+
+ Helper function to map ImageBitmapOptions to
+ GraphicsContext.
+
+ (WebCore::ImageBitmap::createPromise):
+
+ Implement more of the sizing algorithm.
+
+ * html/ImageBitmap.h: Origin tainting is defined to be false by default.
+
2017-10-24 Chris Dumez <cdu...@apple.com>
Add initial implementation for serviceWorker.postMessage()
Modified: trunk/Source/WebCore/html/ImageBitmap.cpp (223924 => 223925)
--- trunk/Source/WebCore/html/ImageBitmap.cpp 2017-10-24 21:35:30 UTC (rev 223924)
+++ trunk/Source/WebCore/html/ImageBitmap.cpp 2017-10-24 21:46:41 UTC (rev 223925)
@@ -54,6 +54,7 @@
static RenderingMode bufferRenderingMode = Unaccelerated;
#endif
+
Ref<ImageBitmap> ImageBitmap::create()
{
return adoptRef(*new ImageBitmap);
@@ -104,11 +105,112 @@
return false;
}
+// https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#cropped-to-the-source-rectangle-with-formatting
+static ExceptionOr<IntRect> croppedSourceRectangleWithFormatting(IntSize inputSize, ImageBitmapOptions& options, std::optional<IntRect> rect)
+{
+ // 2. If either or both of resizeWidth and resizeHeight members of options are less
+ // than or equal to 0, then return a promise rejected with "InvalidStateError"
+ // DOMException and abort these steps.
+ if ((options.resizeWidth && options.resizeWidth.value() <= 0) || (options.resizeHeight && options.resizeHeight.value() <= 0))
+ return Exception { InvalidStateError, "Invalid resize dimensions" };
+
+ // 3. If sx, sy, sw and sh are specified, let sourceRectangle be a rectangle whose
+ // corners are the four points (sx, sy), (sx+sw, sy),(sx+sw, sy+sh), (sx,sy+sh).
+ // Otherwise let sourceRectangle be a rectangle whose corners are the four points
+ // (0,0), (width of input, 0), (width of input, height of input), (0, height of
+ // input).
+ auto sourceRectangle = rect.value_or(IntRect { 0, 0, inputSize.width(), inputSize.height() });
+
+ // 4. Clip sourceRectangle to the dimensions of input.
+
+ sourceRectangle.setWidth(std::min(sourceRectangle.width(), inputSize.width()));
+ sourceRectangle.setHeight(std::min(sourceRectangle.height(), inputSize.height()));
+
+ return sourceRectangle;
+}
+
+static IntSize outputSizeForSourceRectangle(IntRect sourceRectangle, ImageBitmapOptions& options)
+{
+ // 5. Let outputWidth be determined as follows:
+ auto outputWidth = [&] () -> int {
+ if (options.resizeWidth)
+ return options.resizeWidth.value();
+ if (options.resizeHeight)
+ return ceil(sourceRectangle.width() * static_cast<double>(options.resizeHeight.value()) / sourceRectangle.height());
+ return sourceRectangle.width();
+ }();
+
+ // 6. Let outputHeight be determined as follows:
+ auto outputHeight = [&] () -> int {
+ if (options.resizeHeight)
+ return options.resizeHeight.value();
+ if (options.resizeWidth)
+ return ceil(sourceRectangle.height() * static_cast<double>(options.resizeWidth.value()) / sourceRectangle.width());
+ return sourceRectangle.height();
+ }();
+
+ return { outputWidth, outputHeight };
+}
+
+static InterpolationQuality interpolationQualityForResizeQuality(ImageBitmapOptions::ResizeQuality resizeQuality)
+{
+ switch (resizeQuality) {
+ case ImageBitmapOptions::ResizeQuality::Pixelated:
+ return InterpolationNone;
+ case ImageBitmapOptions::ResizeQuality::Low:
+ return InterpolationDefault; // Low is the default.
+ case ImageBitmapOptions::ResizeQuality::Medium:
+ return InterpolationMedium;
+ case ImageBitmapOptions::ResizeQuality::High:
+ return InterpolationHigh;
+ }
+}
+
+// FIXME: More steps from https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#cropped-to-the-source-rectangle-with-formatting
+
+// 7. Place input on an infinite transparent black grid plane, positioned so that its
+// top left corner is at the origin of the plane, with the x-coordinate increasing
+// to the right, and the y-coordinate increasing down, and with each pixel in the
+// input image data occupying a cell on the plane's grid.
+
+// 8. Let output be the rectangle on the plane denoted by sourceRectangle.
+
+// 9. Scale output to the size specified by outputWidth and outputHeight. The user
+// agent should use the value of the resizeQuality option to guide the choice of
+// scaling algorithm.
+
+// 10. If the value of the imageOrientation member of options is "flipY", output must
+// be flipped vertically, disregarding any image orientation metadata of the source
+// (such as EXIF metadata), if any.
+
+// 11. If image is an img element or a Blob object, let val be the value of the
+// colorSpaceConversion member of options, and then run these substeps:
+//
+// 1. If val is "default", the color space conversion behavior is implementation-specific,
+// and should be chosen according to the color space that the implementation uses for
+// drawing images onto the canvas.
+//
+// 2. If val is "none", output must be decoded without performing any color space
+// conversions. This means that the image decoding algorithm must ignore color profile
+// metadata embedded in the source data as well as the display device color profile.
+
+// 12. Let val be the value of premultiplyAlpha member of options, and then run these substeps:
+//
+// 1. If val is "default", the alpha premultiplication behavior is implementation-specific,
+// and should be chosen according to implementation deems optimal for drawing images
+// onto the canvas.
+//
+// 2. If val is "premultiply", the output that is not premultiplied by alpha must have its
+// color components multiplied by alpha and that is premultiplied by alpha must be left
+// untouched.
+//
+// 3. If val is "none", the output that is not premultiplied by alpha must be left untouched
+// and that is premultiplied by alpha must have its color components divided by alpha.
+
+// 13. Return output.
+
void ImageBitmap::createPromise(ScriptExecutionContext&, RefPtr<HTMLImageElement>& imageElement, ImageBitmapOptions&& options, std::optional<IntRect> rect, ImageBitmap::Promise&& promise)
{
- UNUSED_PARAM(options);
- UNUSED_PARAM(rect);
-
// 2. If image is not completely available, then return a promise rejected with
// an "InvalidStateError" DOMException and abort these steps.
@@ -123,18 +225,36 @@
// resizeHeight options are not specified, then return a promise rejected with
// an "InvalidStateError" DOMException and abort these steps.
+ auto imageSize = cachedImage->imageSizeForRenderer(imageElement->renderer(), 1.0f);
+ if ((!imageSize.width() || !imageSize.height()) && (!options.resizeWidth || !options.resizeHeight)) {
+ promise.reject(InvalidStateError, "Cannot create ImageBitmap from a source with no intrinsic size without providing resize dimensions");
+ return;
+ }
+
// 4. If image's media data has no intrinsic dimensions (e.g. it's a vector graphics
// with no specified content size), it should be rendered to a bitmap of the size
// specified by the resizeWidth and the resizeHeight options.
+ if (!imageSize.width() && !imageSize.height()) {
+ imageSize.setWidth(options.resizeWidth.value());
+ imageSize.setHeight(options.resizeHeight.value());
+ }
+
// 5. If the sw and sh arguments are not specified and image's media data has both or
// either of its intrinsic width and intrinsic height values equal to 0, then return
// a promise rejected with an "InvalidStateError" DOMException and abort these steps.
-
// 6. If the sh argument is not specified and image's media data has an intrinsic height
// of 0, then return a promise rejected with an "InvalidStateError" DOMException and
// abort these steps.
+ // FIXME: It's unclear how these steps can happen, since step 4 required setting a
+ // width and height for the image.
+
+ if (!rect && (!imageSize.width() || !imageSize.height())) {
+ promise.reject(InvalidStateError, "Cannot create ImageBitmap from a source with no intrinsic size without providing dimensions");
+ return;
+ }
+
// 7. Create a new ImageBitmap object.
auto imageBitmap = create();
@@ -145,17 +265,27 @@
// one that the format defines is to be used when animation is not supported or is disabled),
// or, if there is no such image, the first frame of the animation.
- // FIXME: Move this into a separate function and handle the cropping/resizing.
- auto bitmapData = ImageBuffer::create(FloatSize(imageElement->width(), imageElement->height()), bufferRenderingMode);
+ auto sourceRectangle = croppedSourceRectangleWithFormatting(roundedIntSize(imageSize), options, WTFMove(rect));
+ if (sourceRectangle.hasException()) {
+ promise.reject(sourceRectangle.releaseException());
+ return;
+ }
- auto imageForRender = imageElement->cachedImage()->imageForRenderer(imageElement->renderer());
+ auto outputSize = outputSizeForSourceRectangle(sourceRectangle.returnValue(), options);
+ auto bitmapData = ImageBuffer::create(FloatSize(outputSize.width(), outputSize.height()), bufferRenderingMode);
+
+ auto imageForRender = cachedImage->imageForRenderer(imageElement->renderer());
if (!imageForRender) {
promise.reject(InvalidStateError, "Cannot create ImageBitmap from image that can't be rendered");
return;
}
- FloatRect drawRect(FloatPoint(), FloatSize(imageElement->width(), imageElement->height()));
- bitmapData->context().drawImage(*imageForRender, drawRect, drawRect);
+ FloatRect destRect(FloatPoint(), outputSize);
+ ImagePaintingOptions paintingOptions;
+ paintingOptions.m_interpolationQuality = interpolationQualityForResizeQuality(options.resizeQuality);
+
+ bitmapData->context().drawImage(*imageForRender, destRect, sourceRectangle.releaseReturnValue(), paintingOptions);
+
imageBitmap->m_bitmapData = WTFMove(bitmapData);
// 9. If the origin of image's image is not the same origin as the origin specified by the
Modified: trunk/Source/WebCore/html/ImageBitmap.h (223924 => 223925)
--- trunk/Source/WebCore/html/ImageBitmap.h 2017-10-24 21:35:30 UTC (rev 223924)
+++ trunk/Source/WebCore/html/ImageBitmap.h 2017-10-24 21:46:41 UTC (rev 223925)
@@ -91,7 +91,7 @@
std::unique_ptr<ImageBuffer> m_bitmapData;
bool m_detached { false };
- bool m_originClean { false };
+ bool m_originClean { true };
};
}