Commit 41251457 authored by sigbjornf@opera.com's avatar sigbjornf@opera.com

Implement ImageData constructors.

The spec now defines a pair of ImageData constructors,

  http://www.whatwg.org/specs/web-apps/current-work/#imagedata

Provide an implementation of both here.

R=
BUG=338804

Review URL: https://codereview.chromium.org/196343032

git-svn-id: svn://svn.chromium.org/blink/trunk@170325 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 07ee81b3
...@@ -206,3 +206,7 @@ webkit.org/b/49629 compositing/lots-of-img-layers-with-opacity.html [ WontFix ] ...@@ -206,3 +206,7 @@ webkit.org/b/49629 compositing/lots-of-img-layers-with-opacity.html [ WontFix ]
# Don't want to just delete this test since the virtual/softwarecompositing version passes. # Don't want to just delete this test since the virtual/softwarecompositing version passes.
crbug.com/245630 compositing/overflow/overflow-positioning.html [ WontFix ] crbug.com/245630 compositing/overflow/overflow-positioning.html [ WontFix ]
# Out-of-date imported test; spec now supports ImageData constructors.
crbug.com/338804 canvas/philip/tests/2d.imageData.object.ctor.html [ WontFix ]
crbug.com/338804 virtual/gpu/canvas/philip/tests/2d.imageData.object.ctor.html [ WontFix ]
Test ImageData constructor
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
PASS ImageData is defined.
PASS ImageData.length is 2
PASS imageData is non-null.
PASS imageData.data is non-null.
PASS imageData.width is 100
PASS imageData.height is 50
PASS getRGBA(imageData.data, 4) is [0, 0, 0, 0]
PASS getRGBA(imageData.data, 4) is testColor
PASS new ImageData(10) threw exception TypeError: Failed to construct 'ImageData': 2 arguments required, but only 1 present..
PASS new ImageData(0, 10) threw exception IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number..
PASS new ImageData(10, 0) threw exception IndexSizeError: Failed to construct 'ImageData': The source height is zero or not a number..
PASS new ImageData('width', 'height') threw exception IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number..
PASS new ImageData(1 << 31, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The requested image size exceeds the supported range..
PASS new ImageData(new Uint8ClampedArray(0)) threw exception TypeError: Failed to construct 'ImageData': 2 arguments required, but only 1 present..
PASS new ImageData(new Uint8Array(100), 25) threw exception IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number..
PASS new ImageData(new Uint8ClampedArray(27), 2) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of 4..
PASS new ImageData(new Uint8ClampedArray(104), 14) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width)..
PASS new ImageData(imageData.data, 0) threw exception IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number..
PASS new ImageData(imageData.data, 13) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width)..
PASS new ImageData(imageData.data, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width)..
PASS new ImageData(imageData.data, 'biggish') threw exception IndexSizeError: Failed to construct 'ImageData': The source width is zero or not a number..
PASS new ImageData(imageData.data, 1 << 24, 1 << 31) threw exception IndexSizeError: Failed to construct 'ImageData': The input data byte length is not a multiple of (4 * width)..
PASS imageDataFromData.width is 100
PASS imageDataFromData.height is 50
PASS imageDataFromData.data is imageData.data
PASS getRGBA(imageDataFromData.data, 10) is getRGBA(imageData.data, 10)
PASS getRGBA(imageDataFromData.data, 10) is getRGBA(imageData.data, 10)
PASS imageDataFromData.width is 20
PASS imageDataFromData.height is 5
PASS imageDataFromData.data is data
PASS getRGBA(imageDataFromData.data, 2) is getRGBA(data, 2)
PASS getRGBA(imageDataFromData.data, 2) is getRGBA(data, 2)
PASS successfullyParsed is true
TEST COMPLETE
<!DOCTYPE HTML>
<script src="../../resources/js-test.js"></script>
<script src="script-tests/canvas-ImageData.js"></script>
description("Test ImageData constructor");
function setRGBA(imageData, i, rgba) {
var s = i * 4;
imageData[s] = rgba[0];
imageData[s + 1] = rgba[1];
imageData[s + 2] = rgba[2];
imageData[s + 3] = rgba[3];
}
function getRGBA(imageData, i) {
var result = [];
var s = i * 4;
for (var j = 0; j < 4; j++) {
result[j] = imageData[s + j];
}
return result;
}
shouldBeDefined("ImageData");
shouldBe("ImageData.length", "2");
imageData = new ImageData(100, 50);
shouldBeNonNull("imageData");
shouldBeNonNull("imageData.data");
shouldBe("imageData.width", "100");
shouldBe("imageData.height", "50");
shouldBe("getRGBA(imageData.data, 4)", "[0, 0, 0, 0]");
var testColor = [0, 255, 255, 128];
setRGBA(imageData.data, 4, testColor);
shouldBe("getRGBA(imageData.data, 4)", "testColor");
shouldThrow("new ImageData(10)");
shouldThrow("new ImageData(0, 10)");
shouldThrow("new ImageData(10, 0)");
shouldThrow("new ImageData('width', 'height')");
shouldThrow("new ImageData(1 << 31, 1 << 31)");
shouldThrow("new ImageData(new Uint8ClampedArray(0))");
shouldThrow("new ImageData(new Uint8Array(100), 25)");
shouldThrow("new ImageData(new Uint8ClampedArray(27), 2)");
shouldThrow("new ImageData(new Uint8ClampedArray(104), 14)");
shouldThrow("new ImageData(imageData.data, 0)");
shouldThrow("new ImageData(imageData.data, 13)");
shouldThrow("new ImageData(imageData.data, 1 << 31)");
shouldThrow("new ImageData(imageData.data, 'biggish')");
shouldThrow("new ImageData(imageData.data, 1 << 24, 1 << 31)");
imageDataFromData = new ImageData(imageData.data, 100);
shouldBe("imageDataFromData.width", "100");
shouldBe("imageDataFromData.height", "50");
shouldBe("imageDataFromData.data", "imageData.data");
shouldBe("getRGBA(imageDataFromData.data, 10)", "getRGBA(imageData.data, 10)");
setRGBA(imageData.data, 10, testColor);
shouldBe("getRGBA(imageDataFromData.data, 10)", "getRGBA(imageData.data, 10)");
var data = new Uint8ClampedArray(400);
data[22] = 129;
imageDataFromData = new ImageData(data, 20, 5);
shouldBe("imageDataFromData.width", "20");
shouldBe("imageDataFromData.height", "5");
shouldBe("imageDataFromData.data", "data");
shouldBe("getRGBA(imageDataFromData.data, 2)", "getRGBA(data, 2)");
setRGBA(imageDataFromData.data, 2, testColor);
shouldBe("getRGBA(imageDataFromData.data, 2)", "getRGBA(data, 2)");
...@@ -29,6 +29,10 @@ ...@@ -29,6 +29,10 @@
#include "config.h" #include "config.h"
#include "core/html/ImageData.h" #include "core/html/ImageData.h"
#include "RuntimeEnabledFeatures.h"
#include "bindings/v8/ExceptionState.h"
#include "core/dom/ExceptionCode.h"
namespace WebCore { namespace WebCore {
PassRefPtr<ImageData> ImageData::create(const IntSize& size) PassRefPtr<ImageData> ImageData::create(const IntSize& size)
...@@ -57,6 +61,69 @@ PassRefPtr<ImageData> ImageData::create(const IntSize& size, PassRefPtr<Uint8Cla ...@@ -57,6 +61,69 @@ PassRefPtr<ImageData> ImageData::create(const IntSize& size, PassRefPtr<Uint8Cla
return adoptRef(new ImageData(size, byteArray)); return adoptRef(new ImageData(size, byteArray));
} }
PassRefPtr<ImageData> ImageData::create(unsigned width, unsigned height, ExceptionState& exceptionState)
{
if (!RuntimeEnabledFeatures::imageDataConstructorEnabled()) {
exceptionState.throwTypeError("Illegal constructor");
return nullptr;
}
if (!width || !height) {
exceptionState.throwDOMException(IndexSizeError, String::format("The source %s is zero or not a number.", width ? "height" : "width"));
return nullptr;
}
Checked<unsigned, RecordOverflow> dataSize = 4;
dataSize *= width;
dataSize *= height;
if (dataSize.hasOverflowed()) {
exceptionState.throwDOMException(IndexSizeError, "The requested image size exceeds the supported range.");
return nullptr;
}
RefPtr<ImageData> imageData = adoptRef(new ImageData(IntSize(width, height)));
imageData->data()->zeroFill();
return imageData.release();
}
PassRefPtr<ImageData> ImageData::create(Uint8ClampedArray* data, unsigned width, unsigned height, ExceptionState& exceptionState)
{
if (!RuntimeEnabledFeatures::imageDataConstructorEnabled()) {
exceptionState.throwTypeError("Illegal constructor");
return nullptr;
}
if (!data) {
exceptionState.throwTypeError("Expected a Uint8ClampedArray as first argument.");
return nullptr;
}
if (!width) {
exceptionState.throwDOMException(IndexSizeError, "The source width is zero or not a number.");
return nullptr;
}
unsigned length = data->length();
if (!length) {
exceptionState.throwDOMException(IndexSizeError, "The input data has a zero byte length.");
return nullptr;
}
if (length % 4) {
exceptionState.throwDOMException(IndexSizeError, "The input data byte length is not a multiple of 4.");
return nullptr;
}
length /= 4;
if (length % width) {
exceptionState.throwDOMException(IndexSizeError, "The input data byte length is not a multiple of (4 * width).");
return nullptr;
}
if (!height) {
height = length / width;
} else if (height != length / width) {
exceptionState.throwDOMException(IndexSizeError, "The input data byte length is not equal to (4 * width * height).");
return nullptr;
}
return adoptRef(new ImageData(IntSize(width, height), data));
}
ImageData::ImageData(const IntSize& size) ImageData::ImageData(const IntSize& size)
: m_size(size) : m_size(size)
, m_data(Uint8ClampedArray::createUninitialized(size.width() * size.height() * 4)) , m_data(Uint8ClampedArray::createUninitialized(size.width() * size.height() * 4))
......
...@@ -37,10 +37,14 @@ ...@@ -37,10 +37,14 @@
namespace WebCore { namespace WebCore {
class ExceptionState;
class ImageData : public RefCounted<ImageData>, public ScriptWrappable { class ImageData : public RefCounted<ImageData>, public ScriptWrappable {
public: public:
static PassRefPtr<ImageData> create(const IntSize&); static PassRefPtr<ImageData> create(const IntSize&);
static PassRefPtr<ImageData> create(const IntSize&, PassRefPtr<Uint8ClampedArray>); static PassRefPtr<ImageData> create(const IntSize&, PassRefPtr<Uint8ClampedArray>);
static PassRefPtr<ImageData> create(unsigned width, unsigned height, ExceptionState&);
static PassRefPtr<ImageData> create(Uint8ClampedArray*, unsigned width, unsigned height, ExceptionState&);
IntSize size() const { return m_size; } IntSize size() const { return m_size; }
int width() const { return m_size.width(); } int width() const { return m_size.width(); }
......
...@@ -27,7 +27,10 @@ ...@@ -27,7 +27,10 @@
*/ */
[ [
Constructor(Uint8ClampedArray data, unsigned long width, [Default=Undefined] optional unsigned long height),
Constructor(unsigned long width, unsigned long height),
Custom=Wrap, Custom=Wrap,
RaisesException=Constructor,
] interface ImageData { ] interface ImageData {
readonly attribute long width; readonly attribute long width;
readonly attribute long height; readonly attribute long height;
......
...@@ -62,6 +62,7 @@ Gamepad status=stable ...@@ -62,6 +62,7 @@ Gamepad status=stable
HTMLImports status=test HTMLImports status=test
HighResolutionTimeInWorkers status=stable HighResolutionTimeInWorkers status=stable
IMEAPI status=experimental IMEAPI status=experimental
ImageDataConstructor status=experimental
IndexedDBExperimental status=experimental IndexedDBExperimental status=experimental
InputModeAttribute status=experimental InputModeAttribute status=experimental
LangAttributeAwareFormControlUI LangAttributeAwareFormControlUI
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment