Diff
Modified: trunk/LayoutTests/ChangeLog (223818 => 223819)
--- trunk/LayoutTests/ChangeLog 2017-10-21 21:42:51 UTC (rev 223818)
+++ trunk/LayoutTests/ChangeLog 2017-10-21 21:48:17 UTC (rev 223819)
@@ -1,3 +1,20 @@
+2017-10-21 Dean Jackson <[email protected]>
+
+ createImageBitmap with basic HTMLImageElement
+ https://bugs.webkit.org/show_bug.cgi?id=178619
+ <rdar://problem/35104118>
+
+ Reviewed by Antoine Quint.
+
+ Make a better test for createImageBitmap. This will be
+ submitted to Web Platform Tests.
+
+ * http/wpt/2dcontext/imagebitmap/createImageBitmap-expected.txt: Added.
+ * http/wpt/2dcontext/imagebitmap/createImageBitmap.html: Added.
+ * http/wpt/common/canvas-tests.css: Added.
+ * http/wpt/common/canvas-tests.js: Added.
+ * http/wpt/images/pattern.png: Added.
+
2017-10-21 Antti Koivisto <[email protected]>
Support ::before/::after pseudo elements with display:contents
Added: trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/createImageBitmap-expected.txt (0 => 223819)
--- trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/createImageBitmap-expected.txt (rev 0)
+++ trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/createImageBitmap-expected.txt 2017-10-21 21:48:17 UTC (rev 223819)
@@ -0,0 +1,9 @@
+
+PASS createImageBitmap rejects with RangeError if width is zero
+PASS createImageBitmap rejects with RangeError if height is zero
+PASS createImageBitmap rejects with RangeError if width is negative
+PASS createImageBitmap rejects with RangeError if height is negative
+PASS createImageBitmap rejects with InvalidStateError on an HTMLImageElement with no image data
+PASS createImageBitmap from an HTMLImageElement with image data
+PASS A closed ImageBitmap has zero width and height
+
Property changes on: trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/createImageBitmap-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.html (0 => 223819)
--- trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/createImageBitmap.html (rev 0)
+++ trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/createImageBitmap.html 2017-10-21 21:48:17 UTC (rev 223819)
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html>
+<title>createImageBitmap test</title>
+<script src=""
+<script src=""
+<script src=""
+<link rel="stylesheet" href=""
+<body>
+<script>
+(function() {
+ promise_test(function(t) {
+ return promise_rejects(t, new RangeError, createImageBitmap(new Image(), 0, 0, 0, 10));
+ }, "createImageBitmap rejects with RangeError if width is zero");
+
+ promise_test(function(t) {
+ return promise_rejects(t, new RangeError, createImageBitmap(new Image(), 0, 0, 10, 0));
+ }, "createImageBitmap rejects with RangeError if height is zero");
+
+ promise_test(function(t) {
+ return promise_rejects(t, new RangeError, createImageBitmap(new Image(), 0, 0, -10, 10));
+ }, "createImageBitmap rejects with RangeError if width is negative");
+
+ promise_test(function(t) {
+ return promise_rejects(t, new RangeError, createImageBitmap(new Image(), 0, 0, 10, -10));
+ }, "createImageBitmap rejects with RangeError if height is negative");
+
+ promise_test(function(t) {
+ return promise_rejects(t, "InvalidStateError", createImageBitmap(new Image()));
+ }, "createImageBitmap rejects with InvalidStateError on an HTMLImageElement with no image data");
+
+ promise_test(function() {
+ return new Promise(function(resolve, reject) {
+ var img = new Image();
+ img._onload_ = function() { resolve(img); };
+ img.src = ""
+ }).then(function(img) {
+ return createImageBitmap(img);
+ }).then(function(imageBitmap) {
+ assert_equals(imageBitmap.width, 20, "ImageBitmap width should be 20");
+ assert_equals(imageBitmap.height, 20, "ImageBitmap height should be 20");
+ });
+ }, "createImageBitmap from an HTMLImageElement with image data");
+
+ promise_test(function() {
+ return new Promise(function(resolve, reject) {
+ var img = new Image();
+ img._onload_ = function() { resolve(img); };
+ img.src = ""
+ }).then(function(img) {
+ return createImageBitmap(img);
+ }).then(function(imageBitmap) {
+ imageBitmap.close();
+ assert_equals(imageBitmap.width, 0, "A closed ImageBitmap width should be 0");
+ assert_equals(imageBitmap.height, 0, "A closed ImageBitmap height should be 0");
+ });
+ }, "A closed ImageBitmap has zero width and height");
+
+})();
+</script>
+</body>
+</html>
Property changes on: trunk/LayoutTests/http/wpt/2dcontext/imagebitmap/createImageBitmap.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
Added: trunk/LayoutTests/http/wpt/common/canvas-tests.css (0 => 223819)
--- trunk/LayoutTests/http/wpt/common/canvas-tests.css (rev 0)
+++ trunk/LayoutTests/http/wpt/common/canvas-tests.css 2017-10-21 21:48:17 UTC (rev 223819)
@@ -0,0 +1,134 @@
+html.fail {
+ background: #f66;
+}
+html.pass {
+ background: #6f6;
+}
+html.needs_check {
+ background: #99f;
+}
+
+body {
+ font-size: small;
+ font-family: sans-serif;
+ color: black;
+}
+
+a:link {
+ color: #00c;
+}
+a:visited {
+ color: #808;
+}
+
+body.framed {
+ font-size: x-small;
+}
+
+h1 {
+ font-size: larger;
+ margin: 0;
+ padding-left: 0.5em;
+ text-indent: -0.5em;
+}
+
+p {
+ margin: 0;
+}
+
+p.notes {
+ margin-bottom: 0.5em;
+ font-style: italic;
+}
+
+ul {
+ margin: 0;
+ margin-bottom: 0.5em;
+ padding: 0;
+ padding-left: 1em;
+}
+
+.refs {
+ font-style: italic;
+ margin-bottom: 0.5em;
+}
+
+.refs ul {
+ display: inline;
+ margin: 0;
+ padding: 0;
+}
+
+.refs li {
+ display: inline;
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+}
+
+canvas {
+ display: none;
+ visibility: hidden;
+ border: 2px #f0f solid;
+ background: url(../images/background.png);
+}
+
+img.expected {
+ display: none;
+ border: 2px #f0f solid;
+ background: url(../images/background.png);
+}
+
+iframe {
+ border: 2px #f0f solid;
+}
+
+.output {
+ display: none;
+}
+
+.show_output .output, .needs_check .output {
+ display: block !important;
+ visibility: visible !important;
+}
+
+.show_output #show_output {
+ display: none;
+}
+
+.resource {
+ visibility: hidden;
+ height: 0;
+}
+
+.fallback {
+ font-size: 2em;
+ font-weight: bold;
+ color: #a00;
+}
+
+
+html.minimal body {
+ color: white;
+}
+html.fail.minimal {
+ background: #f00;
+}
+html.pass.minimal {
+ background: #080;
+}
+html.needs_check.minimal {
+ background: #008;
+}
+.minimal #d {
+ display: none !important;
+}
+.minimal .expectedtext {
+ visibility: hidden !important;
+}
+#passtext, #failtext {
+ display: none;
+}
+.minimal.pass #passtext, .minimal.fail #failtext {
+ display: block;
+}
Property changes on: trunk/LayoutTests/http/wpt/common/canvas-tests.css
___________________________________________________________________
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/css
\ No newline at end of property
Added: trunk/LayoutTests/http/wpt/common/canvas-tests.js (0 => 223819)
--- trunk/LayoutTests/http/wpt/common/canvas-tests.js (rev 0)
+++ trunk/LayoutTests/http/wpt/common/canvas-tests.js 2017-10-21 21:48:17 UTC (rev 223819)
@@ -0,0 +1,105 @@
+function _valToString(val)
+{
+ if (val === undefined || val === null)
+ return '[' + typeof(val) + ']';
+ return val.toString() + '[' + typeof(val) + ']';
+}
+
+function _assert(cond, text)
+{
+ assert_true(!!cond, text);
+}
+
+function _assertSame(a, b, text_a, text_b)
+{
+ var msg = text_a + ' === ' + text_b + ' (got ' + _valToString(a) +
+ ', expected ' + _valToString(b) + ')';
+ assert_equals(a, b, msg);
+}
+
+function _assertDifferent(a, b, text_a, text_b)
+{
+ var msg = text_a + ' !== ' + text_b + ' (got ' + _valToString(a) +
+ ', expected not ' + _valToString(b) + ')';
+ assert_not_equals(a, b, msg);
+}
+
+
+function _getPixel(canvas, x,y)
+{
+ var ctx = canvas.getContext('2d');
+ var imgdata = ctx.getImageData(x, y, 1, 1);
+ return [ imgdata.data[0], imgdata.data[1], imgdata.data[2], imgdata.data[3] ];
+}
+
+function _assertPixel(canvas, x,y, r,g,b,a, pos, colour)
+{
+ var c = _getPixel(canvas, x,y);
+ assert_equals(c[0], r, 'Red channel of the pixel at (' + x + ', ' + y + ')');
+ assert_equals(c[1], g, 'Green channel of the pixel at (' + x + ', ' + y + ')');
+ assert_equals(c[2], b, 'Blue channel of the pixel at (' + x + ', ' + y + ')');
+ assert_equals(c[3], a, 'Alpha channel of the pixel at (' + x + ', ' + y + ')');
+}
+
+function _assertPixelApprox(canvas, x,y, r,g,b,a, pos, colour, tolerance)
+{
+ var c = _getPixel(canvas, x,y);
+ assert_approx_equals(c[0], r, tolerance, 'Red channel of the pixel at (' + x + ', ' + y + ')');
+ assert_approx_equals(c[1], g, tolerance, 'Green channel of the pixel at (' + x + ', ' + y + ')');
+ assert_approx_equals(c[2], b, tolerance, 'Blue channel of the pixel at (' + x + ', ' + y + ')');
+ assert_approx_equals(c[3], a, tolerance, 'Alpha channel of the pixel at (' + x + ', ' + y + ')');
+}
+
+function _addTest(testFn)
+{
+ var deferred = false;
+ window.deferTest = function () { deferred = true; };
+ on_event(window, "load", function()
+ {
+ t.step(function() {
+ var canvas = document.getElementById('c');
+ var ctx = canvas.getContext('2d');
+ t.step(testFn, window, canvas, ctx);
+ });
+
+ if (!deferred) {
+ t.done();
+ }
+ });
+}
+
+function _assertGreen(ctx, canvasWidth, canvasHeight)
+{
+ var testColor = function(d, idx, expected) {
+ assert_equals(d[idx], expected, "d[" + idx + "]", String(expected));
+ };
+ var imagedata = ctx.getImageData(0, 0, canvasWidth, canvasHeight);
+ var w = imagedata.width, h = imagedata.height, d = imagedata.data;
+ for (var i = 0; i < h; ++i) {
+ for (var j = 0; j < w; ++j) {
+ testColor(d, 4 * (w * i + j) + 0, 0);
+ testColor(d, 4 * (w * i + j) + 1, 255);
+ testColor(d, 4 * (w * i + j) + 2, 0);
+ testColor(d, 4 * (w * i + j) + 3, 255);
+ }
+ }
+}
+
+function addCrossOriginYellowImage()
+{
+ var img = new Image();
+ img.id = "yellow.png";
+ img.className = "resource";
+ img.src = "" + "/images/yellow.png";
+ document.body.appendChild(img);
+}
+
+function addCrossOriginRedirectYellowImage()
+{
+ var img = new Image();
+ img.id = "yellow.png";
+ img.className = "resource";
+ img.src = "" + "/common/redirect.py?location=" +
+ get_host_info().HTTP_REMOTE_ORIGIN + "/images/yellow.png";
+ document.body.appendChild(img);
+}
Property changes on: trunk/LayoutTests/http/wpt/common/canvas-tests.js
___________________________________________________________________
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/images/pattern.png
(Binary files differ)
Index: trunk/LayoutTests/http/wpt/images/pattern.png
===================================================================
--- trunk/LayoutTests/http/wpt/images/pattern.png 2017-10-21 21:42:51 UTC (rev 223818)
+++ trunk/LayoutTests/http/wpt/images/pattern.png 2017-10-21 21:48:17 UTC (rev 223819)
Property changes on: trunk/LayoutTests/http/wpt/images/pattern.png
___________________________________________________________________
Added: svn:mime-type
+image/png
\ No newline at end of property
Modified: trunk/Source/WebCore/ChangeLog (223818 => 223819)
--- trunk/Source/WebCore/ChangeLog 2017-10-21 21:42:51 UTC (rev 223818)
+++ trunk/Source/WebCore/ChangeLog 2017-10-21 21:48:17 UTC (rev 223819)
@@ -1,3 +1,21 @@
+2017-10-21 Dean Jackson <[email protected]>
+
+ createImageBitmap with basic HTMLImageElement
+ https://bugs.webkit.org/show_bug.cgi?id=178619
+ <rdar://problem/35104118>
+
+ Reviewed by Antoine Quint.
+
+ Implement the basic infrastructure for creating
+ an ImageBitmap from an HTMLImageElement.
+
+ Test: http/wpt/2dcontext/imagebitmap/createImageBitmap.html
+
+ * html/ImageBitmap.cpp:
+ (WebCore::ImageBitmap::createPromise): Create the image buffer
+ and draw the image into its backing store.
+ * html/ImageBitmap.h:
+
2017-10-21 Antoine Quint <[email protected]>
[Web Animations] Add bindings to unified sources
Modified: trunk/Source/WebCore/html/ImageBitmap.cpp (223818 => 223819)
--- trunk/Source/WebCore/html/ImageBitmap.cpp 2017-10-21 21:42:51 UTC (rev 223818)
+++ trunk/Source/WebCore/html/ImageBitmap.cpp 2017-10-21 21:48:17 UTC (rev 223819)
@@ -32,6 +32,7 @@
#include "ExceptionOr.h"
#include "FileReaderLoader.h"
#include "FileReaderLoaderClient.h"
+#include "GraphicsContext.h"
#include "HTMLCanvasElement.h"
#include "HTMLImageElement.h"
#include "HTMLVideoElement.h"
@@ -41,11 +42,18 @@
#include "IntRect.h"
#include "JSImageBitmap.h"
#include "LayoutSize.h"
+#include "RenderElement.h"
#include "SharedBuffer.h"
#include <wtf/StdLibExtras.h>
namespace WebCore {
+#if PLATFORM(COCOA)
+static RenderingMode bufferRenderingMode = Accelerated;
+#else
+static RenderingMode bufferRenderingMode = Unaccelerated;
+#endif
+
Ref<ImageBitmap> ImageBitmap::create()
{
return adoptRef(*new ImageBitmap);
@@ -69,6 +77,11 @@
return;
}
+ if (sw < 0 || sh < 0) {
+ promise.reject(RangeError, "Cannot create ImageBitmap with a negative width or height");
+ return;
+ }
+
WTF::switchOn(source,
[&] (auto& specificSource) {
createPromise(scriptExecutionContext, specificSource, WTFMove(options), IntRect { sx, sy, sw, sh }, WTFMove(promise));
@@ -78,7 +91,6 @@
void ImageBitmap::createPromise(ScriptExecutionContext&, RefPtr<HTMLImageElement>& imageElement, ImageBitmapOptions&& options, std::optional<IntRect> rect, ImageBitmap::Promise&& promise)
{
- UNUSED_PARAM(imageElement);
UNUSED_PARAM(options);
UNUSED_PARAM(rect);
@@ -85,6 +97,12 @@
// 2. If image is not completely available, then return a promise rejected with
// an "InvalidStateError" DOMException and abort these steps.
+ auto* cachedImage = imageElement->cachedImage();
+ if (!cachedImage || !imageElement->complete()) {
+ promise.reject(InvalidStateError, "Cannot create ImageBitmap that is not completely available");
+ return;
+ }
+
// 3. If image's media data has no intrinsic dimensions (e.g. it's a vector graphic
// with no specified content size), and both or either of the resizeWidth and
// resizeHeight options are not specified, then return a promise rejected with
@@ -103,6 +121,7 @@
// abort these steps.
// 7. Create a new ImageBitmap object.
+
auto imageBitmap = create();
// 8. Let the ImageBitmap object's bitmap data be a copy of image's media data, cropped to
@@ -111,13 +130,26 @@
// 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 imageForRender = imageElement->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);
+
+ imageBitmap->m_bitmapData = WTFMove(bitmapData);
+
// 9. If the origin of image's image is not the same origin as the origin specified by the
// entry settings object, then set the origin-clean flag of the ImageBitmap object's
// bitmap to false.
// 10. Return a new promise, but continue running these steps in parallel.
+ // 11. Resolve the promise with the new ImageBitmap object as the value.
- // 11. Resolve the promise with the new ImageBitmap object as the value.
return promise.resolve(WTFMove(imageBitmap));
}
@@ -146,6 +178,7 @@
return promise.resolve(WTFMove(imageBitmap));
}
+#if ENABLE(VIDEO)
void ImageBitmap::createPromise(ScriptExecutionContext&, RefPtr<HTMLVideoElement>& videoElement, ImageBitmapOptions&& options, std::optional<IntRect> rect, ImageBitmap::Promise&& promise)
{
UNUSED_PARAM(videoElement);
@@ -177,6 +210,7 @@
// 8. Resolve the promise with the new ImageBitmap object as the value.
return promise.resolve(WTFMove(imageBitmap));
}
+#endif
void ImageBitmap::createPromise(ScriptExecutionContext&, RefPtr<ImageBitmap>& existingImageBitmap, ImageBitmapOptions&& options, std::optional<IntRect> rect, ImageBitmap::Promise&& promise)
{
Modified: trunk/Source/WebCore/html/ImageBitmap.h (223818 => 223819)
--- trunk/Source/WebCore/html/ImageBitmap.h 2017-10-21 21:42:51 UTC (rev 223818)
+++ trunk/Source/WebCore/html/ImageBitmap.h 2017-10-21 21:48:17 UTC (rev 223819)
@@ -77,8 +77,10 @@
ImageBitmap();
static void createPromise(ScriptExecutionContext&, RefPtr<HTMLImageElement>&, ImageBitmapOptions&&, std::optional<IntRect>, Promise&&);
+#if ENABLE(VIDEO)
+ static void createPromise(ScriptExecutionContext&, RefPtr<HTMLVideoElement>&, ImageBitmapOptions&&, std::optional<IntRect>, Promise&&);
+#endif
static void createPromise(ScriptExecutionContext&, RefPtr<HTMLCanvasElement>&, ImageBitmapOptions&&, std::optional<IntRect>, Promise&&);
- static void createPromise(ScriptExecutionContext&, RefPtr<HTMLVideoElement>&, ImageBitmapOptions&&, std::optional<IntRect>, Promise&&);
static void createPromise(ScriptExecutionContext&, RefPtr<ImageBitmap>&, ImageBitmapOptions&&, std::optional<IntRect>, Promise&&);
static void createPromise(ScriptExecutionContext&, RefPtr<Blob>&, ImageBitmapOptions&&, std::optional<IntRect>, Promise&&);
static void createPromise(ScriptExecutionContext&, RefPtr<ImageData>&, ImageBitmapOptions&&, std::optional<IntRect>, Promise&&);