Bug 17486: Support HTML5 Canvas.getImageData API
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 23 Feb 2008 01:16:16 +0000 (01:16 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 23 Feb 2008 01:16:16 +0000 (01:16 +0000)
Support Canvas.getImageData and Canvas.createImageData

Reviewed by Sam W.

This patch adds support for all the pixel reading portions
of the HTML5 Canvas spec.  There are two new types ImageData
and CanvasPixelArray which are used to provide the HTML5
ImageData object, and the required semantics for assignment
to the ImageData data array.

We only implement the CG version of ImageBuffer::getImageData,
but the logic is null safe, so this will not introduce any
crashes into other platforms, unfortunately it will result in
JS Object detection "lying" on non-CG platforms.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@30506 268f45cc-cd09-0410-ab3c-d52691b4dbfc

31 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/canvas/canvas-ImageData-behaviour-expected.txt [new file with mode: 0644]
LayoutTests/fast/canvas/canvas-ImageData-behaviour.html [new file with mode: 0644]
LayoutTests/fast/canvas/canvas-ImageData-behaviour.js [new file with mode: 0644]
LayoutTests/fast/canvas/canvas-getImageData-expected.txt [new file with mode: 0644]
LayoutTests/fast/canvas/canvas-getImageData.html [new file with mode: 0644]
WebCore/ChangeLog
WebCore/DerivedSources.make
WebCore/GNUmakefile.am
WebCore/WebCore.pro
WebCore/WebCore.vcproj/WebCore.vcproj
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/bindings/js/JSCanvasPixelArrayCustom.cpp [new file with mode: 0644]
WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp
WebCore/bindings/scripts/CodeGeneratorJS.pm
WebCore/html/CanvasPixelArray.cpp [new file with mode: 0644]
WebCore/html/CanvasPixelArray.h [new file with mode: 0644]
WebCore/html/CanvasPixelArray.idl [new file with mode: 0644]
WebCore/html/CanvasRenderingContext2D.cpp
WebCore/html/CanvasRenderingContext2D.h
WebCore/html/CanvasRenderingContext2D.idl
WebCore/html/HTMLCanvasElement.cpp
WebCore/html/HTMLCanvasElement.h
WebCore/html/ImageData.cpp [new file with mode: 0644]
WebCore/html/ImageData.h [new file with mode: 0644]
WebCore/html/ImageData.idl [new file with mode: 0644]
WebCore/platform/graphics/ImageBuffer.h
WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
WebCore/platform/graphics/cg/ImageBufferCG.cpp
WebCore/platform/graphics/qt/ImageBufferQt.cpp
WebCore/platform/graphics/wx/ImageBufferWx.cpp

index da48d2a..3efc302 100644 (file)
@@ -1,3 +1,18 @@
+2008-02-22  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Sam W.
+
+        Bug 17486: Support HTML5 Canvas.getImageData API
+        Support Canvas.getImageData and Canvas.createImageData
+
+        Test cases for ImageData behaviour and getImageData correctness
+
+        * fast/canvas/canvas-ImageData-behaviour-expected.txt: Added.
+        * fast/canvas/canvas-ImageData-behaviour.html: Added.
+        * fast/canvas/canvas-ImageData-behaviour.js: Added.
+        * fast/canvas/canvas-getImageData-expected.txt: Added.
+        * fast/canvas/canvas-getImageData.html: Added.
+
 2008-02-22  Geoffrey Garen  <ggaren@apple.com>
 
         Reviewed by Sam Weinig.
diff --git a/LayoutTests/fast/canvas/canvas-ImageData-behaviour-expected.txt b/LayoutTests/fast/canvas/canvas-ImageData-behaviour-expected.txt
new file mode 100644 (file)
index 0000000..90ea45a
--- /dev/null
@@ -0,0 +1,51 @@
+Series of tests to ensure correct behaviour of the ImageData object
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS imageData.width is 2
+PASS imageData.height is 2
+PASS imageData.data.length is 16
+PASS imageData.data[0] is 0
+PASS imageData.data[1] is 0
+PASS imageData.data[2] is 0
+PASS imageData.data[3] is 0
+PASS imageData.data[4] is 0
+PASS imageData.data[5] is 0
+PASS imageData.data[6] is 0
+PASS imageData.data[7] is 0
+PASS imageData.data[8] is 0
+PASS imageData.data[9] is 0
+PASS imageData.data[10] is 0
+PASS imageData.data[11] is 0
+PASS imageData.data[12] is 0
+PASS imageData.data[13] is 0
+PASS imageData.data[14] is 0
+PASS imageData.data[15] is 0
+PASS imageData.data[0] = NaN, imageData.data[0] is 0
+PASS imageData.data[0] = true, imageData.data[0] is 1
+PASS imageData.data[0] = false, imageData.data[0] is 0
+PASS imageData.data[0] = "garbage", imageData.data[0] is 0
+PASS imageData.data[0] = -1, imageData.data[0] is 0
+PASS imageData.data[0] = "0", imageData.data[0] is 0
+PASS imageData.data[0] = "1", imageData.data[0] is 1
+PASS imageData.data[0] = "2", imageData.data[0] is 2
+PASS imageData.data[0] = Infinity, imageData.data[0] is 255
+PASS imageData.data[0] = -Infinity, imageData.data[0] is 0
+PASS imageData.data[0] = -5, imageData.data[0] is 0
+PASS imageData.data[0] = -0.5, imageData.data[0] is 0
+PASS imageData.data[0] = 0, imageData.data[0] is 0
+PASS imageData.data[0] = 0.5, imageData.data[0] is 1
+PASS imageData.data[0] = 5, imageData.data[0] is 5
+PASS imageData.data[0] = 5.4, imageData.data[0] is 5
+PASS imageData.data[0] = 255, imageData.data[0] is 255
+PASS imageData.data[0] = 256, imageData.data[0] is 255
+PASS imageData.data[0] = null, imageData.data[0] is 0
+PASS imageData.data[0] = undefined, imageData.data[0] is 0
+PASS imageData.data['foo']='garbage',imageData.data['foo'] is 'garbage'
+PASS imageData.data[-1]='garbage',imageData.data[-1] is 'garbage'
+PASS imageData.data[17]='garbage',imageData.data[17] is undefined
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/canvas/canvas-ImageData-behaviour.html b/LayoutTests/fast/canvas/canvas-ImageData-behaviour.html
new file mode 100644 (file)
index 0000000..1703ae7
--- /dev/null
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<link rel="stylesheet" href="../js/resources/js-test-style.css">
+<script src="../js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<canvas id="canvas"></canvas>
+<script src="canvas-ImageData-behaviour.js"></script>
+<script src="../js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/canvas/canvas-ImageData-behaviour.js b/LayoutTests/fast/canvas/canvas-ImageData-behaviour.js
new file mode 100644 (file)
index 0000000..d5b9161
--- /dev/null
@@ -0,0 +1,27 @@
+description("Series of tests to ensure correct behaviour of the ImageData object");
+
+imageData = document.getElementById("canvas").getContext("2d").getImageData(0,0,2,2);
+
+shouldBe("imageData.width", "2");
+shouldBe("imageData.height", "2");
+shouldBe("imageData.data.length", "16");
+for (var i = 0; i < imageData.data.length; i++)
+    shouldBe("imageData.data["+i+"]", "0");
+
+var testValues = [NaN, true, false, "\"garbage\"", "-1",
+                  "\"0\"", "\"1\"", "\"2\"", Infinity, -Infinity,
+                  -5, -0.5, 0, 0.5, 5,
+                  5.4, 255, 256, null, undefined];
+var testResults = [0, 1, 0, 0, 0,
+                   0, 1, 2, 255, 0,
+                   0, 0, 0, 1, 5,
+                   5, 255, 255, 0, 0];
+for (var i = 0; i < testValues.length; i++) {
+    shouldBe("imageData.data[0] = "+testValues[i]+", imageData.data[0]", ""+testResults[i]);
+}
+
+shouldBe("imageData.data['foo']='garbage',imageData.data['foo']", "'garbage'");
+shouldBe("imageData.data[-1]='garbage',imageData.data[-1]", "'garbage'");
+shouldBe("imageData.data[17]='garbage',imageData.data[17]", "undefined");
+
+var successfullyParsed = true;
diff --git a/LayoutTests/fast/canvas/canvas-getImageData-expected.txt b/LayoutTests/fast/canvas/canvas-getImageData-expected.txt
new file mode 100644 (file)
index 0000000..770aadf
--- /dev/null
@@ -0,0 +1,150 @@
+This test ensures that getImageData works correctly.
+PASS: pixel at (0,0) was [0,0,0,255]
+PASS: pixel at (4,0) was [0,11,0,255]
+PASS: pixel at (8,0) was [0,21,0,255]
+PASS: pixel at (12,0) was [0,32,0,255]
+PASS: pixel at (16,0) was [0,43,0,255]
+PASS: pixel at (20,0) was [0,53,0,255]
+PASS: pixel at (24,0) was [0,64,0,255]
+PASS: pixel at (28,0) was [0,74,0,255]
+PASS: pixel at (32,0) was [0,85,0,255]
+PASS: pixel at (36,0) was [0,96,0,255]
+PASS: pixel at (40,0) was [0,106,0,255]
+PASS: pixel at (44,0) was [0,117,0,255]
+PASS: pixel at (48,0) was [0,128,0,255]
+PASS: pixel at (52,0) was [0,138,0,255]
+PASS: pixel at (56,0) was [0,149,0,255]
+PASS: pixel at (60,0) was [0,159,0,255]
+PASS: pixel at (64,0) was [0,170,0,255]
+PASS: pixel at (68,0) was [0,181,0,255]
+PASS: pixel at (72,0) was [0,191,0,255]
+PASS: pixel at (76,0) was [0,202,0,255]
+PASS: pixel at (80,0) was [0,213,0,255]
+PASS: pixel at (84,0) was [0,223,0,255]
+PASS: pixel at (88,0) was [0,234,0,255]
+PASS: pixel at (92,0) was [0,244,0,255]
+PASS: pixel at (96,0) was [0,255,0,255]
+PASS: pixel at (5,5) was [64,128,191,255]
+PASS: Correct data for content outside canvas bounds
+PASS: pixel at (50,50) was [0,0,0,0]
+PASS: pixel at (50,54) was [0,0,0,1]
+PASS: pixel at (50,58) was [0,0,0,2]
+PASS: pixel at (50,62) was [0,0,0,16]
+PASS: pixel at (50,66) was [0,0,0,32]
+PASS: pixel at (50,70) was [0,0,0,64]
+PASS: pixel at (50,74) was [0,0,0,96]
+PASS: pixel at (50,78) was [0,0,0,128]
+PASS: pixel at (50,82) was [0,0,0,192]
+PASS: pixel at (50,86) was [0,0,0,254]
+PASS: pixel at (50,90) was [0,0,0,255]
+PASS: pixel at (54,50) was [0,0,0,0]
+PASS: pixel at (54,54) was [0,0,0,1]
+PASS: pixel at (54,58) was [0,0,0,2]
+PASS: pixel at (54,62) was [0,0,0,16]
+PASS: pixel at (54,66) was [0,0,0,32]
+PASS: pixel at (54,70) was [0,0,0,64]
+PASS: pixel at (54,74) was [0,0,0,96]
+PASS: pixel at (54,78) was [1,0,0,128]
+PASS: pixel at (54,82) was [1,0,0,192]
+PASS: pixel at (54,86) was [1,0,0,254]
+PASS: pixel at (54,90) was [1,0,0,255]
+PASS: pixel at (58,50) was [0,0,0,0]
+PASS: pixel at (58,54) was [0,0,0,1]
+PASS: pixel at (58,58) was [0,0,0,2]
+PASS: pixel at (58,62) was [0,0,0,16]
+PASS: pixel at (58,66) was [0,0,0,32]
+PASS: pixel at (58,70) was [3,0,0,64]
+PASS: pixel at (58,74) was [2,0,0,96]
+PASS: pixel at (58,78) was [1,0,0,128]
+PASS: pixel at (58,82) was [2,0,0,192]
+PASS: pixel at (58,86) was [2,0,0,254]
+PASS: pixel at (58,90) was [2,0,0,255]
+PASS: pixel at (62,50) was [0,0,0,0]
+PASS: pixel at (62,54) was [0,0,0,1]
+PASS: pixel at (62,58) was [0,0,0,2]
+PASS: pixel at (62,62) was [15,0,0,16]
+PASS: pixel at (62,66) was [15,0,0,32]
+PASS: pixel at (62,70) was [15,0,0,64]
+PASS: pixel at (62,74) was [15,0,0,96]
+PASS: pixel at (62,78) was [15,0,0,128]
+PASS: pixel at (62,82) was [15,0,0,192]
+PASS: pixel at (62,86) was [16,0,0,254]
+PASS: pixel at (62,90) was [16,0,0,255]
+PASS: pixel at (66,50) was [0,0,0,0]
+PASS: pixel at (66,54) was [0,0,0,1]
+PASS: pixel at (66,58) was [0,0,0,2]
+PASS: pixel at (66,62) was [31,0,0,16]
+PASS: pixel at (66,66) was [31,0,0,32]
+PASS: pixel at (66,70) was [31,0,0,64]
+PASS: pixel at (66,74) was [31,0,0,96]
+PASS: pixel at (66,78) was [31,0,0,128]
+PASS: pixel at (66,82) was [31,0,0,192]
+PASS: pixel at (66,86) was [32,0,0,254]
+PASS: pixel at (66,90) was [32,0,0,255]
+PASS: pixel at (70,50) was [0,0,0,0]
+PASS: pixel at (70,54) was [0,0,0,1]
+PASS: pixel at (70,58) was [127,0,0,2]
+PASS: pixel at (70,62) was [63,0,0,16]
+PASS: pixel at (70,66) was [63,0,0,32]
+PASS: pixel at (70,70) was [63,0,0,64]
+PASS: pixel at (70,74) was [63,0,0,96]
+PASS: pixel at (70,78) was [63,0,0,128]
+PASS: pixel at (70,82) was [63,0,0,192]
+PASS: pixel at (70,86) was [64,0,0,254]
+PASS: pixel at (70,90) was [64,0,0,255]
+PASS: pixel at (74,50) was [0,0,0,0]
+PASS: pixel at (74,54) was [0,0,0,1]
+PASS: pixel at (74,58) was [127,0,0,2]
+PASS: pixel at (74,62) was [95,0,0,16]
+PASS: pixel at (74,66) was [95,0,0,32]
+PASS: pixel at (74,70) was [95,0,0,64]
+PASS: pixel at (74,74) was [95,0,0,96]
+PASS: pixel at (74,78) was [95,0,0,128]
+PASS: pixel at (74,82) was [95,0,0,192]
+PASS: pixel at (74,86) was [96,0,0,254]
+PASS: pixel at (74,90) was [96,0,0,255]
+PASS: pixel at (78,50) was [0,0,0,0]
+PASS: pixel at (78,54) was [255,0,0,1]
+PASS: pixel at (78,58) was [127,0,0,2]
+PASS: pixel at (78,62) was [127,0,0,16]
+PASS: pixel at (78,66) was [127,0,0,32]
+PASS: pixel at (78,70) was [127,0,0,64]
+PASS: pixel at (78,74) was [127,0,0,96]
+PASS: pixel at (78,78) was [127,0,0,128]
+PASS: pixel at (78,82) was [127,0,0,192]
+PASS: pixel at (78,86) was [127,0,0,254]
+PASS: pixel at (78,90) was [128,0,0,255]
+PASS: pixel at (82,50) was [0,0,0,0]
+PASS: pixel at (82,54) was [255,0,0,1]
+PASS: pixel at (82,58) was [255,0,0,2]
+PASS: pixel at (82,62) was [191,0,0,16]
+PASS: pixel at (82,66) was [191,0,0,32]
+PASS: pixel at (82,70) was [191,0,0,64]
+PASS: pixel at (82,74) was [191,0,0,96]
+PASS: pixel at (82,78) was [191,0,0,128]
+PASS: pixel at (82,82) was [192,0,0,192]
+PASS: pixel at (82,86) was [191,0,0,254]
+PASS: pixel at (82,90) was [192,0,0,255]
+PASS: pixel at (86,50) was [0,0,0,0]
+PASS: pixel at (86,54) was [255,0,0,1]
+PASS: pixel at (86,58) was [255,0,0,2]
+PASS: pixel at (86,62) was [255,0,0,16]
+PASS: pixel at (86,66) was [255,0,0,32]
+PASS: pixel at (86,70) was [255,0,0,64]
+PASS: pixel at (86,74) was [255,0,0,96]
+PASS: pixel at (86,78) was [253,0,0,128]
+PASS: pixel at (86,82) was [253,0,0,192]
+PASS: pixel at (86,86) was [253,0,0,254]
+PASS: pixel at (86,90) was [254,0,0,255]
+PASS: pixel at (90,50) was [0,0,0,0]
+PASS: pixel at (90,54) was [255,0,0,1]
+PASS: pixel at (90,58) was [255,0,0,2]
+PASS: pixel at (90,62) was [255,0,0,16]
+PASS: pixel at (90,66) was [255,0,0,32]
+PASS: pixel at (90,70) was [255,0,0,64]
+PASS: pixel at (90,74) was [255,0,0,96]
+PASS: pixel at (90,78) was [255,0,0,128]
+PASS: pixel at (90,82) was [255,0,0,192]
+PASS: pixel at (90,86) was [255,0,0,254]
+PASS: pixel at (90,90) was [255,0,0,255]
+
diff --git a/LayoutTests/fast/canvas/canvas-getImageData.html b/LayoutTests/fast/canvas/canvas-getImageData.html
new file mode 100644 (file)
index 0000000..1865960
--- /dev/null
@@ -0,0 +1,95 @@
+This test ensures that getImageData works correctly.
+<div id="log"></div>
+<script>
+if (window.layoutTestController)
+    layoutTestController.dumpAsText();
+
+var canvas = document.createElement("canvas");
+canvas.width = 200;
+canvas.height = 200;
+var context = canvas.getContext("2d");
+
+function log(msg){
+    document.getElementById("log").innerHTML += msg + "<br/>";
+}
+
+function dataToArray(data) {
+    var result = new Array(data.length)
+    for (var i = 0; i < data.length; i++)
+        result[i] = data[i];
+    return result;
+}
+
+function getPixel(ctx, x, y) {
+    var data = ctx.getImageData(x,y,1,1);
+    if (!data) // getImageData failed, which should never happen
+        return [-1,-1,-1,-1];
+    return dataToArray(data.data);
+}
+
+function pixelShouldBe(ctx, x, y, colour) {
+    var ctxColour = getPixel(ctx, x, y);
+    var correct = true;
+    for (var i = 0; i < 4; i++)
+        if (colour[i] != ctxColour[i]) {
+            correct = false;
+            break;
+        }
+    if (correct)
+        log("PASS: pixel at ("+[x,y]+") was ["+colour+"]");
+    else
+        log("FAIL: pixel at ("+[x,y]+") was ["+ctxColour+"], expected ["+colour+"]");
+}
+
+if (!context.setFillColor)
+    context.setFillColor = function(r,g,b,a) {
+        this.fillStyle = "rgba("+[Math.round(r*255),Math.round(g*255),Math.round(b*255),Math.round(a*255)]+")"
+    }
+
+// Check that getImageData is return the data for the right portion of the image
+for(var x = 0; x < 100; x+=4) {
+    context.setFillColor(0, x/96, 0, 1);
+    context.fillRect(x,0,1,1);
+    pixelShouldBe(context, x, 0, [0, Math.round(255*x/96), 0, 255]);
+}
+
+// Check rgba ordering
+context.clearRect(0,0,100,100);
+context.setFillColor(0.25, 0.5, 0.75, 1);
+context.fillRect(5,5,1,1);
+pixelShouldBe(context, 5, 5, [Math.round(0.25*255), Math.round(0.5*255), Math.round(0.75*255), 255]);
+
+// Check that we return transparent black for regions outside the canvas proper
+context.fillStyle = "rgba(255,255,255,255)";
+context.fillRect(198, 5, 4, 1); // final 2 pixels horizontally should be clipped
+var content = dataToArray(context.getImageData(198, 5, 4, 1).data);
+var expected = [255,255,255,255,255,255,255,255,
+                0,0,0,0,0,0,0,0];
+var matched = true;
+for (var i = 0; i < 16; i++)
+    if (content[i] != expected[i]) {
+        matched = false;
+        break;
+    }
+if (matched)
+    log("PASS: Correct data for content outside canvas bounds");
+else
+    log("FAIL: Did not get correct data for content outside canvas bounds: "+content);
+
+// Ensure returned values are not premultiplied
+var values = [0,1,2,16,32,64,96,128,192,254,255];
+
+// this function simply accounts for truncation due to premultiplication in the canvas implementation
+function premult(value, alpha) {
+    return alpha ? Math.floor(Math.round(value*alpha/255)*255/alpha) : 0;
+}
+
+for (var i = 0; i < values.length; i++) {
+    for (var a = 0; a < values.length; a++) {
+        context.fillStyle = "rgba(" + [values[i], 0, 0, values[a]/255] +")";
+        context.fillRect(50+i*4,50+a*4,2,2);
+        pixelShouldBe(context, 50+i*4, 50+a*4, [premult(values[i], values[a]), 0, 0, values[a]]);
+    }
+}
+
+</script>
index 82e703c..f34bfc1 100644 (file)
@@ -1,3 +1,70 @@
+2008-02-22  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Sam W.
+
+        Support Canvas.getImageData and Canvas.createImageData
+        
+        This patch adds support for all the pixel reading portions
+        of the HTML5 Canvas spec.  There are two new types ImageData
+        and CanvasPixelArray which are used to provide the HTML5
+        ImageData object, and the required semantics for assignment
+        to the ImageData data array.
+        
+        We only implement the CG version of ImageBuffer::getImageData,
+        but the logic is null safe, so this will not introduce any
+        crashes into other platforms, unfortunately it will result in
+        JS Object detection "lying" on non-CG platforms.
+
+        Tests: fast/canvas/canvas-ImageData-behaviour.html
+               fast/canvas/canvas-getImageData.html
+
+        * DerivedSources.make:
+        * GNUmakefile.am:
+        * WebCore.pro:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/js/JSCanvasPixelArrayCustom.cpp: Added.
+        (WebCore::JSCanvasPixelArray::indexGetter):
+        (WebCore::JSCanvasPixelArray::indexSetter):
+        (WebCore::toJS):
+        * bindings/js/JSCanvasRenderingContext2DCustom.cpp:
+        * bindings/scripts/CodeGeneratorJS.pm:
+        * html/CanvasPixelArray.cpp: Added.
+        (WebCore::CanvasPixelArray::create):
+        * html/CanvasPixelArray.h: Added.
+        (WebCore::CanvasPixelArray::data):
+        (WebCore::CanvasPixelArray::length):
+        (WebCore::CanvasPixelArray::set):
+        (WebCore::CanvasPixelArray::get):
+        * html/CanvasPixelArray.idl: Added.
+        * html/CanvasRenderingContext2D.cpp:
+        (WebCore::createEmptyImageData):
+        (WebCore::CanvasRenderingContext2D::createImageData):
+        (WebCore::CanvasRenderingContext2D::getImageData):
+        * html/CanvasRenderingContext2D.h:
+        * html/CanvasRenderingContext2D.idl:
+        * html/HTMLCanvasElement.cpp:
+        (WebCore::HTMLCanvasElement::convertLogicalToDevice):
+        (WebCore::HTMLCanvasElement::createImageBuffer):
+        * html/HTMLCanvasElement.h:
+        * html/ImageData.cpp: Added.
+        (WebCore::ImageData::create):
+        (WebCore::ImageData::ImageData):
+        * html/ImageData.h: Added.
+        (WebCore::ImageData::width):
+        (WebCore::ImageData::height):
+        (WebCore::ImageData::data):
+        * html/ImageData.idl: Added.
+        * platform/graphics/ImageBuffer.h:
+        * platform/graphics/cairo/ImageBufferCairo.cpp:
+        (WebCore::ImageBuffer::getImageData):
+        * platform/graphics/cg/ImageBufferCG.cpp:
+        (WebCore::ImageBuffer::getImageData):
+        * platform/graphics/qt/ImageBufferQt.cpp:
+        (WebCore::ImageBuffer::getImageData):
+        * platform/graphics/wx/ImageBufferWx.cpp:
+        (WebCore::ImageBuffer::getImageData):
+
 2008-02-22  Sam Weinig  <sam@webkit.org>
 
         Rubber-stamped by Adam Roben.
index bd29151..58fc579 100644 (file)
@@ -327,6 +327,7 @@ all : \
     JSCSSValueList.h \
     JSCanvasGradient.h \
     JSCanvasPattern.h \
+    JSCanvasPixelArray.h \
     JSCanvasRenderingContext2D.h \
     JSCharacterData.h \
     JSComment.h \
@@ -414,6 +415,7 @@ all : \
     JSHTMLUListElement.h \
     JSHTMLVideoElement.h \
     JSHistory.h \
+    JSImageData.h \
     JSKeyboardEvent.h \
     JSLocation.lut.h \
     JSMediaError.h \
index 5198f7e..7a44aaa 100644 (file)
@@ -88,6 +88,7 @@ webcore_built_sources += \
        DerivedSources/JSCSSValueList.h \
        DerivedSources/JSCanvasGradient.h \
        DerivedSources/JSCanvasPattern.h \
+       DerivedSources/JSCanvasPixelArray.h \
        DerivedSources/JSCanvasRenderingContext2D.h \
        DerivedSources/JSCharacterData.h \
        DerivedSources/JSComment.h \
@@ -167,6 +168,7 @@ webcore_built_sources += \
        DerivedSources/JSHTMLTitleElement.h \
        DerivedSources/JSHTMLUListElement.h \
        DerivedSources/JSHistory.h \
+       DerivedSources/JSImageData.h \
        DerivedSources/JSKeyboardEvent.h \
        DerivedSources/JSMediaList.h \
        DerivedSources/JSMouseEvent.h \
@@ -211,6 +213,7 @@ webcore_built_sources += \
        DerivedSources/JSCSSValueList.cpp \
        DerivedSources/JSCanvasGradient.cpp \
        DerivedSources/JSCanvasPattern.cpp \
+       DerivedSources/JSCanvasPixelArray.cpp \
        DerivedSources/JSCanvasRenderingContext2D.cpp \
        DerivedSources/JSCharacterData.cpp \
        DerivedSources/JSComment.cpp \
@@ -290,6 +293,7 @@ webcore_built_sources += \
        DerivedSources/JSHTMLTitleElement.cpp \
        DerivedSources/JSHTMLUListElement.cpp \
        DerivedSources/JSHistory.cpp \
+       DerivedSources/JSImageData.cpp \
        DerivedSources/JSKeyboardEvent.cpp \
        DerivedSources/JSMediaList.cpp \
        DerivedSources/JSMouseEvent.cpp \
@@ -448,6 +452,7 @@ webcore_headers += \
 webcore_sources += \
        WebCore/bindings/js/GCController.cpp \
        WebCore/bindings/js/JSAttrCustom.cpp \
+       WebCore/bindings/js/JSCanvasPixelArrayCustom.cpp \
        WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp \
        WebCore/bindings/js/JSCSSRuleCustom.cpp \
        WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp \
@@ -659,6 +664,7 @@ webcore_sources += \
        WebCore/history/PageCache.cpp \
        WebCore/html/CanvasGradient.cpp \
        WebCore/html/CanvasPattern.cpp \
+       WebCore/html/CanvasPixelArray.cpp \
        WebCore/html/CanvasRenderingContext2D.cpp \
        WebCore/html/CanvasStyle.cpp \
        WebCore/html/FormDataList.cpp \
@@ -738,6 +744,7 @@ webcore_sources += \
        WebCore/html/HTMLTokenizer.cpp \
        WebCore/html/HTMLUListElement.cpp \
        WebCore/html/HTMLViewSourceDocument.cpp \
+       WebCore/html/ImageData.cpp \
        WebCore/loader/Cache.cpp \
        WebCore/loader/CachedCSSStyleSheet.cpp \
        WebCore/loader/CachedFont.cpp \
index 44f0160..9dff26c 100644 (file)
@@ -312,6 +312,7 @@ IDL_BINDINGS += \
     dom/WheelEvent.idl \
     html/CanvasGradient.idl \
     html/CanvasPattern.idl \
+    html/CanvasPixelArray.idl \
     html/CanvasRenderingContext2D.idl \
     html/HTMLAnchorElement.idl \
     html/HTMLAppletElement.idl \
@@ -373,6 +374,7 @@ IDL_BINDINGS += \
     html/HTMLTextAreaElement.idl \
     html/HTMLTitleElement.idl \
     html/HTMLUListElement.idl \
+    html/ImageData.idl \
     page/BarInfo.idl \
     page/Console.idl \
     page/DOMSelection.idl \
@@ -387,6 +389,7 @@ IDL_BINDINGS += \
 SOURCES += \
     bindings/js/GCController.cpp \
     bindings/js/JSAttrCustom.cpp \
+    bindings/js/JSCanvasPixelArrayCustom.cpp \
     bindings/js/JSCanvasRenderingContext2DCustom.cpp \
     bindings/js/JSCSSRuleCustom.cpp \
     bindings/js/JSCSSStyleDeclarationCustom.cpp \
@@ -598,6 +601,7 @@ SOURCES += \
     history/PageCache.cpp \
     html/CanvasGradient.cpp \
     html/CanvasPattern.cpp \
+    html/CanvasPixelArray.cpp \
     html/CanvasRenderingContext2D.cpp \
     html/CanvasStyle.cpp \
     html/FormDataList.cpp \
@@ -677,6 +681,7 @@ SOURCES += \
     html/HTMLTokenizer.cpp \
     html/HTMLUListElement.cpp \
     html/HTMLViewSourceDocument.cpp \
+    html/ImageData.cpp \
     loader/Cache.cpp \
     loader/CachedCSSStyleSheet.cpp \
     loader/CachedFont.cpp \
index d028161..4406a73 100644 (file)
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSCanvasPixelArray.cpp"\r
+                               >\r
+                       <File\r
+                               RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSCanvasPixelArray.h"\r
+                               >\r
+                       <File\r
                                RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSCanvasRenderingContext2D.cpp"\r
                                >\r
                        </File>\r
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSImageData.cpp"\r
+                               >\r
+                       <File\r
+                               RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSImageData.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
                                RelativePath="$(WebKitOutputDir)\obj\$(ProjectName)\DerivedSources\JSKeyboardEvent.cpp"\r
                                >\r
                        </File>\r
                        <File\r
                                RelativePath="..\html\CanvasPattern.h"\r
                                >\r
+                       <File\r
+                               RelativePath="..\html\CanvasPixelArray.cpp"\r
+                               >\r
+                       <File\r
+                               RelativePath="..\html\CanvasPixelArray.h"\r
+                               >\r
                        </File>\r
                        <File\r
                                RelativePath="..\html\CanvasRenderingContext2D.cpp"\r
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath="..\html\ImageData.cpp"\r
+                               >\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\html\ImageData.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
                                RelativePath="..\html\MediaError.h"\r
                                >\r
                        </File>\r
                                        >\r
                                </File>\r
                                <File\r
+                                       RelativePath="..\bindings\js\JSCanvasPixelArrayCustom.cpp"\r
+                                       >\r
+                               <File\r
                                        RelativePath="..\bindings\js\JSLocation.cpp"\r
                                        >\r
                                </File>\r
index 29f54b6..19e159f 100644 (file)
                A71878900B2D04AC00A16ECE /* DragControllerMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = A718788F0B2D04AC00A16ECE /* DragControllerMac.mm */; };
                A7352C190B1BB89D00A986D0 /* RenderSVGBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7352C170B1BB89D00A986D0 /* RenderSVGBlock.cpp */; };
                A7352C1A0B1BB89D00A986D0 /* RenderSVGBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = A7352C180B1BB89D00A986D0 /* RenderSVGBlock.h */; };
+               A766F3530D6BDE3500ABDDB3 /* JSCanvasPixelArrayCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A766F3520D6BDE3500ABDDB3 /* JSCanvasPixelArrayCustom.cpp */; };
+               A77979160D6B9D0C003851B9 /* CanvasPixelArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A77979100D6B9D0C003851B9 /* CanvasPixelArray.cpp */; };
+               A77979170D6B9D0C003851B9 /* CanvasPixelArray.h in Headers */ = {isa = PBXBuildFile; fileRef = A77979110D6B9D0C003851B9 /* CanvasPixelArray.h */; };
+               A77979180D6B9D0C003851B9 /* CanvasPixelArray.idl in Resources */ = {isa = PBXBuildFile; fileRef = A77979120D6B9D0C003851B9 /* CanvasPixelArray.idl */; };
+               A77979190D6B9D0C003851B9 /* ImageData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A77979130D6B9D0C003851B9 /* ImageData.cpp */; };
+               A779791A0D6B9D0C003851B9 /* ImageData.h in Headers */ = {isa = PBXBuildFile; fileRef = A77979140D6B9D0C003851B9 /* ImageData.h */; };
+               A779791B0D6B9D0C003851B9 /* ImageData.idl in Resources */ = {isa = PBXBuildFile; fileRef = A77979150D6B9D0C003851B9 /* ImageData.idl */; };
+               A77979260D6B9E64003851B9 /* JSCanvasPixelArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A77979220D6B9E64003851B9 /* JSCanvasPixelArray.cpp */; };
+               A77979270D6B9E64003851B9 /* JSCanvasPixelArray.h in Headers */ = {isa = PBXBuildFile; fileRef = A77979230D6B9E64003851B9 /* JSCanvasPixelArray.h */; };
+               A77979280D6B9E64003851B9 /* JSImageData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A77979240D6B9E64003851B9 /* JSImageData.cpp */; };
+               A77979290D6B9E64003851B9 /* JSImageData.h in Headers */ = {isa = PBXBuildFile; fileRef = A77979250D6B9E64003851B9 /* JSImageData.h */; };
                A784941B0B5FE507001E237A /* Clipboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A784941A0B5FE507001E237A /* Clipboard.cpp */; };
                A795463E0B5C4C80007B438F /* DragDataMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = A795463D0B5C4C80007B438F /* DragDataMac.mm */; };
                A79546430B5C4CB4007B438F /* DragData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A79546420B5C4CB4007B438F /* DragData.cpp */; };
                A718788F0B2D04AC00A16ECE /* DragControllerMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DragControllerMac.mm; sourceTree = "<group>"; };
                A7352C170B1BB89D00A986D0 /* RenderSVGBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RenderSVGBlock.cpp; sourceTree = "<group>"; };
                A7352C180B1BB89D00A986D0 /* RenderSVGBlock.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RenderSVGBlock.h; sourceTree = "<group>"; };
+               A766F3520D6BDE3500ABDDB3 /* JSCanvasPixelArrayCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCanvasPixelArrayCustom.cpp; sourceTree = "<group>"; };
+               A77979100D6B9D0C003851B9 /* CanvasPixelArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CanvasPixelArray.cpp; sourceTree = "<group>"; };
+               A77979110D6B9D0C003851B9 /* CanvasPixelArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CanvasPixelArray.h; sourceTree = "<group>"; };
+               A77979120D6B9D0C003851B9 /* CanvasPixelArray.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CanvasPixelArray.idl; sourceTree = "<group>"; };
+               A77979130D6B9D0C003851B9 /* ImageData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageData.cpp; sourceTree = "<group>"; };
+               A77979140D6B9D0C003851B9 /* ImageData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageData.h; sourceTree = "<group>"; };
+               A77979150D6B9D0C003851B9 /* ImageData.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ImageData.idl; sourceTree = "<group>"; };
+               A77979220D6B9E64003851B9 /* JSCanvasPixelArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCanvasPixelArray.cpp; sourceTree = "<group>"; };
+               A77979230D6B9E64003851B9 /* JSCanvasPixelArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCanvasPixelArray.h; sourceTree = "<group>"; };
+               A77979240D6B9E64003851B9 /* JSImageData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSImageData.cpp; sourceTree = "<group>"; };
+               A77979250D6B9E64003851B9 /* JSImageData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSImageData.h; sourceTree = "<group>"; };
                A784941A0B5FE507001E237A /* Clipboard.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Clipboard.cpp; sourceTree = "<group>"; };
                A795463D0B5C4C80007B438F /* DragDataMac.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = DragDataMac.mm; sourceTree = "<group>"; };
                A79546420B5C4CB4007B438F /* DragData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DragData.cpp; sourceTree = "<group>"; };
                93EEC1EC09C2877700C515D1 /* html */ = {
                        isa = PBXGroup;
                        children = (
+                               A77979100D6B9D0C003851B9 /* CanvasPixelArray.cpp */,
+                               A77979110D6B9D0C003851B9 /* CanvasPixelArray.h */,
+                               A77979120D6B9D0C003851B9 /* CanvasPixelArray.idl */,
+                               A77979130D6B9D0C003851B9 /* ImageData.cpp */,
+                               A77979140D6B9D0C003851B9 /* ImageData.h */,
+                               A77979150D6B9D0C003851B9 /* ImageData.idl */,
                                93EEC1F009C2877700C515D1 /* CanvasGradient.cpp */,
                                93EEC1F109C2877700C515D1 /* CanvasGradient.h */,
                                930CAB8809C49EFA00229C04 /* CanvasGradient.idl */,
                A83B79080CCAFF2B000B0825 /* HTML */ = {
                        isa = PBXGroup;
                        children = (
+                               A77979220D6B9E64003851B9 /* JSCanvasPixelArray.cpp */,
+                               A77979230D6B9E64003851B9 /* JSCanvasPixelArray.h */,
+                               A77979240D6B9E64003851B9 /* JSImageData.cpp */,
+                               A77979250D6B9E64003851B9 /* JSImageData.h */,
                                65DF323309D1DE65000BE325 /* JSCanvasGradient.cpp */,
                                65DF323409D1DE65000BE325 /* JSCanvasGradient.h */,
                                65DF323509D1DE65000BE325 /* JSCanvasPattern.cpp */,
                BC4EDEF70C08F414007EDD49 /* Custom */ = {
                        isa = PBXGroup;
                        children = (
+                               A766F3520D6BDE3500ABDDB3 /* JSCanvasPixelArrayCustom.cpp */,
                                BC2ED6BB0C6BD2F000920BFF /* JSAttrCustom.cpp */,
                                1A9EF4560A1B957D00332B63 /* JSCanvasRenderingContext2DCustom.cpp */,
                                BC46C1ED0C0DDBDF0020CFC3 /* JSCSSRuleCustom.cpp */,
                                BCC573350D695BBE006EF517 /* DOMProgressEvent.h in Headers */,
                                BCC573380D695BD7006EF517 /* DOMProgressEventInternal.h in Headers */,
                                BCC5733A0D695BF1006EF517 /* DOMTextPrivate.h in Headers */,
+                               A77979170D6B9D0C003851B9 /* CanvasPixelArray.h in Headers */,
+                               A779791A0D6B9D0C003851B9 /* ImageData.h in Headers */,
+                               A77979270D6B9E64003851B9 /* JSCanvasPixelArray.h in Headers */,
+                               A77979290D6B9E64003851B9 /* JSImageData.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                85136CA80AED665900F90A3D /* westResizeCursor.png in Resources */,
                                1AB1AE7A0C051FDE00139F4F /* zoomInCursor.png in Resources */,
                                1AB1AE7B0C051FDE00139F4F /* zoomOutCursor.png in Resources */,
+                               A77979180D6B9D0C003851B9 /* CanvasPixelArray.idl in Resources */,
+                               A779791B0D6B9D0C003851B9 /* ImageData.idl in Resources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                C0294DF30D5A6FD800CC7D6B /* UserStyleSheetLoader.cpp in Sources */,
                                37F818FE0D657606005E1F05 /* WebCoreURLResponse.mm in Sources */,
                                BCC573360D695BBE006EF517 /* DOMProgressEvent.mm in Sources */,
+                               A77979160D6B9D0C003851B9 /* CanvasPixelArray.cpp in Sources */,
+                               A77979190D6B9D0C003851B9 /* ImageData.cpp in Sources */,
+                               A77979260D6B9E64003851B9 /* JSCanvasPixelArray.cpp in Sources */,
+                               A77979280D6B9E64003851B9 /* JSImageData.cpp in Sources */,
+                               A766F3530D6BDE3500ABDDB3 /* JSCanvasPixelArrayCustom.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
diff --git a/WebCore/bindings/js/JSCanvasPixelArrayCustom.cpp b/WebCore/bindings/js/JSCanvasPixelArrayCustom.cpp
new file mode 100644 (file)
index 0000000..74798e4
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSCanvasPixelArray.h"
+
+#include "CanvasPixelArray.h"
+
+using namespace KJS;
+
+namespace WebCore {
+
+JSValue* JSCanvasPixelArray::indexGetter(ExecState* exec, JSObject*, const Identifier& propertyName, const PropertySlot& slot)
+{
+    CanvasPixelArray* array = static_cast<JSCanvasPixelArray*>(slot.slotBase())->impl();
+    unsigned index = slot.index();
+    unsigned char result;
+    if (array->get(index, result))
+        return jsNumber(result);
+    return jsUndefined();
+}
+
+void JSCanvasPixelArray::indexSetter(ExecState* exec, unsigned index, JSValue* value, int)
+{
+    if (index >= m_impl->length())
+        return;
+    double pixelValue = value->toNumber(exec);
+    if (exec->hadException())
+        return;
+    m_impl->set(index, pixelValue); 
+}
+
+JSValue* toJS(ExecState* exec, CanvasPixelArray* pixels)
+{
+    if (!pixels)
+        return jsNull();
+    
+    DOMObject* ret = ScriptInterpreter::getDOMObject(pixels);
+    if (ret)
+        return ret;
+    
+    ret = new JSCanvasPixelArray(JSCanvasPixelArrayPrototype::self(exec), pixels);
+    
+    Collector::reportExtraMemoryCost(pixels->length());
+    
+    ScriptInterpreter::putDOMObject(pixels, ret);
+    
+    return ret;
+}
+    
+} // namespace WebCore
index 68328f4..4a6390f 100644 (file)
@@ -333,4 +333,9 @@ JSValue* JSCanvasRenderingContext2D::createPattern(ExecState* exec, const List&
     return 0;
 }
 
+JSValue* JSCanvasRenderingContext2D::putImageData(ExecState* exec, const List& args)
+{
+    return jsUndefined();
+}
+
 } // namespace WebCore
index 43e02a9..48ccf56 100644 (file)
@@ -154,7 +154,7 @@ sub UsesManualToJSImplementation
 {
     my $type = shift;
 
-    return 1 if $type eq "Node" or $type eq "Document" or $type eq "HTMLCollection" or $type eq "SVGPathSeg" or $type eq "StyleSheet" or $type eq "CSSRule" or $type eq "CSSValue" or $type eq "Event";
+    return 1 if $type eq "Node" or $type eq "Document" or $type eq "HTMLCollection" or $type eq "SVGPathSeg" or $type eq "StyleSheet" or $type eq "CSSRule" or $type eq "CSSValue" or $type eq "Event" or $type eq "CanvasPixelArray";
     return 0;
 }
 
@@ -334,10 +334,18 @@ sub GenerateHeader
     # Destructor
     push(@headerContent, "    virtual ~$className();\n") if (!$hasParent or $interfaceName eq "Document");
 
+    my $hasGetter = $numAttributes > 0 
+                 || $dataNode->extendedAttributes->{"GenerateConstructor"} 
+                 || $dataNode->extendedAttributes->{"HasIndexGetter"}
+                 || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}
+                 || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}
+                 || $dataNode->extendedAttributes->{"HasNameGetter"}
+                 || $dataNode->extendedAttributes->{"HasOverridingNameGetter"};
+
     # Getters
-    if ($numAttributes > 0 || $dataNode->extendedAttributes->{"GenerateConstructor"}) {
+    if ($hasGetter) {
         push(@headerContent, "    virtual bool getOwnPropertySlot(KJS::ExecState*, const KJS::Identifier&, KJS::PropertySlot&);\n");
-        push(@headerContent, "    KJS::JSValue* getValueProperty(KJS::ExecState*, int token) const;\n");
+        push(@headerContent, "    KJS::JSValue* getValueProperty(KJS::ExecState*, int token) const;\n") if $numAttributes > 0 || $dataNode->extendedAttributes->{"GenerateConstructor"};
         push(@headerContent, "    bool customGetOwnPropertySlot(KJS::ExecState*, const KJS::Identifier&, KJS::PropertySlot&);\n") if $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"};
     }
 
@@ -349,9 +357,16 @@ sub GenerateHeader
         }
     }
 
-    push(@headerContent, "    virtual void put(KJS::ExecState*, const KJS::Identifier&, KJS::JSValue*, int attr = KJS::None);\n") if ($hasReadWriteProperties || $dataNode->extendedAttributes->{"CustomPutFunction"});
-    push(@headerContent, "    void putValueProperty(KJS::ExecState*, int, KJS::JSValue*, int attr);\n") if $hasReadWriteProperties;
-    push(@headerContent, "    bool customPut(KJS::ExecState*, const KJS::Identifier&, KJS::JSValue*, int attr);\n") if $dataNode->extendedAttributes->{"CustomPutFunction"};
+    my $hasSetter = $hasReadWriteProperties
+                 || $dataNode->extendedAttributes->{"CustomPutFunction"}
+                 || $dataNode->extendedAttributes->{"HasCustomIndexSetter"};
+
+    # Getters
+    if ($hasSetter) {
+        push(@headerContent, "    virtual void put(KJS::ExecState*, const KJS::Identifier&, KJS::JSValue*, int attr = KJS::None);\n");
+        push(@headerContent, "    void putValueProperty(KJS::ExecState*, int, KJS::JSValue*, int attr);\n") if $hasReadWriteProperties;
+        push(@headerContent, "    bool customPut(KJS::ExecState*, const KJS::Identifier&, KJS::JSValue*, int attr);\n") if $dataNode->extendedAttributes->{"CustomPutFunction"};
+    }
 
     # Class info
     push(@headerContent, "    virtual const KJS::ClassInfo* classInfo() const { return &info; }\n");
@@ -373,7 +388,7 @@ sub GenerateHeader
     push(@headerContent, "    virtual bool deleteProperty(KJS::ExecState*, const KJS::Identifier&);\n") if $dataNode->extendedAttributes->{"CustomDeleteProperty"};
 
     # Custom getPropertyNames function
-    push(@headerContent, "    virtual void getPropertyNames(KJS::ExecState*, KJS::PropertyNameArray&);\n") if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"});
+    push(@headerContent, "    virtual void getPropertyNames(KJS::ExecState*, KJS::PropertyNameArray&);\n") if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"});
     push(@headerContent, "    bool customGetPropertyNames(KJS::ExecState*, KJS::PropertyNameArray&);\n") if $dataNode->extendedAttributes->{"CustomGetPropertyNames"};
 
     # Constructor object getter
@@ -450,10 +465,6 @@ sub GenerateHeader
         }
     }
 
-    # Index setter
-    if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
-        push(@headerContent, "    void indexSetter(KJS::ExecState*, unsigned index, KJS::JSValue*, int attr);\n");
-    }
 
     if (!$hasParent) {
         if ($podType) {
@@ -478,10 +489,14 @@ sub GenerateHeader
     }
 
     # Index getter
-    if ($dataNode->extendedAttributes->{"HasIndexGetter"}) {
-        push(@headerContent, "private:\n");
+    if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
         push(@headerContent, "    static KJS::JSValue* indexGetter(KJS::ExecState*, KJS::JSObject*, const KJS::Identifier&, const KJS::PropertySlot&);\n");
     }
+
+    # Index setter
+    if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
+        push(@headerContent, "    void indexSetter(KJS::ExecState*, unsigned index, KJS::JSValue*, int attr);\n");
+    }
     # Name getter
     if ($dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasOverridingNameGetter"}) {
         push(@headerContent, "private:\n");
@@ -592,7 +607,7 @@ sub GenerateImplementation
     push(@implContentHeader, "#include \"$className.h\"\n\n");
     push(@implContentHeader, "#include <wtf/GetPtr.h>\n\n");
 
-    push(@implContentHeader, "#include <kjs/PropertyNameArray.h>\n") if $dataNode->extendedAttributes->{"HasIndexGetter"};
+    push(@implContentHeader, "#include <kjs/PropertyNameArray.h>\n") if $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"};
 
     AddIncludesForType($interfaceName);
 
@@ -828,8 +843,16 @@ sub GenerateImplementation
         push(@implContent, "{\n    ScriptInterpreter::forgetDOMObject(static_cast<${implClassName}*>(impl()));\n}\n\n");
     }
 
+    my $hasGetter = $numAttributes > 0 
+                 || $dataNode->extendedAttributes->{"GenerateConstructor"} 
+                 || $dataNode->extendedAttributes->{"HasIndexGetter"}
+                 || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}
+                 || $dataNode->extendedAttributes->{"CustomGetOwnPropertySlot"}
+                 || $dataNode->extendedAttributes->{"HasNameGetter"}
+                 || $dataNode->extendedAttributes->{"HasOverridingNameGetter"};
+
     # Attributes
-    if ($numAttributes ne 0) {
+    if ($hasGetter) {
         push(@implContent, "bool ${className}::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)\n");
         push(@implContent, "{\n");
 
@@ -851,7 +874,7 @@ sub GenerateImplementation
             &$hasNameGetterGeneration();
         }
 
-        my $requiresManualLookup = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasNameGetter"};
+        my $requiresManualLookup = $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasNameGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"};
         if ($requiresManualLookup) {
             push(@implContent, "    const HashEntry* entry = Lookup::findEntry(&${className}Table, propertyName);\n");
             push(@implContent, "    if (entry) {\n");
@@ -860,7 +883,7 @@ sub GenerateImplementation
             push(@implContent, "    }\n");
         }
 
-        if ($dataNode->extendedAttributes->{"HasIndexGetter"}) {
+        if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
             push(@implContent, "    bool ok;\n");
             push(@implContent, "    unsigned index = propertyName.toUInt32(&ok, false);\n");
             push(@implContent, "    if (ok && index < static_cast<$implClassName*>(impl())->length()) {\n");
@@ -878,101 +901,110 @@ sub GenerateImplementation
                 push(@implContent, "        return true;\n");
         }
 
-        if ($requiresManualLookup) {
-            push(@implContent, "    return Base::getOwnPropertySlot(exec, propertyName, slot);\n");
-        } else {
+        if ($numAttributes > 0) {
             push(@implContent, "    return getStaticValueSlot<$className, Base>(exec, &${className}Table, this, propertyName, slot);\n");
+        } else {
+            push(@implContent, "    return Base::getOwnPropertySlot(exec, propertyName, slot);\n");
         }
         push(@implContent, "}\n\n");
 
-        push(@implContent, "JSValue* ${className}::getValueProperty(ExecState* exec, int token) const\n{\n");
+        if ($numAttributes > 0) {
+            push(@implContent, "JSValue* ${className}::getValueProperty(ExecState* exec, int token) const\n");
+            push(@implContent, "{\n");
 
-        push(@implContent, "    switch (token) {\n");
+            push(@implContent, "    switch (token) {\n");
 
-        foreach my $attribute (@{$dataNode->attributes}) {
-            my $getterFunctionName = $codeGenerator->WK_lcfirst($attribute->signature->name);
+            foreach my $attribute (@{$dataNode->attributes}) {
+                my $getterFunctionName = $codeGenerator->WK_lcfirst($attribute->signature->name);
 
-            my $implClassNameForValueConversion = "";
-            if (!$podType and ($codeGenerator->IsSVGAnimatedType($implClassName) or $attribute->type !~ /^readonly/)) {
-                $implClassNameForValueConversion = $implClassName;
-            }
+                my $implClassNameForValueConversion = "";
+                if (!$podType and ($codeGenerator->IsSVGAnimatedType($implClassName) or $attribute->type !~ /^readonly/)) {
+                    $implClassNameForValueConversion = $implClassName;
+                }
 
-            push(@implContent, "    case " . $codeGenerator->WK_ucfirst($attribute->signature->name)
-                . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "")
-                . "AttrNum: {\n");
+                push(@implContent, "    case " . $codeGenerator->WK_ucfirst($attribute->signature->name)
+                    . ($attribute->signature->type =~ /Constructor$/ ? "Constructor" : "")
+                    . "AttrNum: {\n");
 
-            if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && 
-                !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurity"} &&
-                !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurityOnGet"}) {
-                push(@implContent, "        if (!allowsAccessFrom(exec))\n");
-                push(@implContent, "            return jsUndefined();\n");
-            }
+                if ($dataNode->extendedAttributes->{"CheckDomainSecurity"} && 
+                    !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurity"} &&
+                    !$attribute->signature->extendedAttributes->{"DoNotCheckDomainSecurityOnGet"}) {
+                    push(@implContent, "        if (!allowsAccessFrom(exec))\n");
+                    push(@implContent, "            return jsUndefined();\n");
+                }
 
-            if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"CustomGetter"}) {
-                push(@implContent, "        return $getterFunctionName(exec);\n");
-            } elsif ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) {
-                $implIncludes{"kjs_dom.h"} = 1;
-                push(@implContent, "        $implClassName* imp = static_cast<$implClassName*>(impl());\n");
-                push(@implContent, "        return checkNodeSecurity(exec, imp->$getterFunctionName()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$getterFunctionName()") . " : jsUndefined();\n");
-            } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) {
-                $implIncludes{"Document.h"} = 1;
-                $implIncludes{"kjs_dom.h"} = 1;
-                push(@implContent, "        $implClassName* imp = static_cast<$implClassName*>(impl());\n");
-                push(@implContent, "        return checkNodeSecurity(exec, imp->contentDocument()) ? " . NativeToJSValue($attribute->signature,  0, $implClassName, $implClassNameForValueConversion, "imp->$getterFunctionName()") . " : jsUndefined();\n");
-            } elsif ($attribute->signature->type =~ /Constructor$/) {
-                my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
-                $constructorType =~ s/Constructor$//;
-                push(@implContent, "        return JS" . $constructorType . "::getConstructor(exec);\n");
-            } elsif (!@{$attribute->getterExceptions}) {
-                if ($podType) {
-                    push(@implContent, "        $podType imp(*impl());\n");
-                    if ($podType eq "float") { # Special case for JSSVGNumber
-                        push(@implContent, "        return " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp") . ";\n");
+                if ($attribute->signature->extendedAttributes->{"Custom"} || $attribute->signature->extendedAttributes->{"CustomGetter"}) {
+                    push(@implContent, "        return $getterFunctionName(exec);\n");
+                } elsif ($attribute->signature->extendedAttributes->{"CheckNodeSecurity"}) {
+                    $implIncludes{"kjs_dom.h"} = 1;
+                    push(@implContent, "        $implClassName* imp = static_cast<$implClassName*>(impl());\n");
+                    push(@implContent, "        return checkNodeSecurity(exec, imp->$getterFunctionName()) ? " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$getterFunctionName()") . " : jsUndefined();\n");
+                } elsif ($attribute->signature->extendedAttributes->{"CheckFrameSecurity"}) {
+                    $implIncludes{"Document.h"} = 1;
+                    $implIncludes{"kjs_dom.h"} = 1;
+                    push(@implContent, "        $implClassName* imp = static_cast<$implClassName*>(impl());\n");
+                    push(@implContent, "        return checkNodeSecurity(exec, imp->contentDocument()) ? " . NativeToJSValue($attribute->signature,  0, $implClassName, $implClassNameForValueConversion, "imp->$getterFunctionName()") . " : jsUndefined();\n");
+                } elsif ($attribute->signature->type =~ /Constructor$/) {
+                    my $constructorType = $codeGenerator->StripModule($attribute->signature->type);
+                    $constructorType =~ s/Constructor$//;
+                    push(@implContent, "        return JS" . $constructorType . "::getConstructor(exec);\n");
+                } elsif (!@{$attribute->getterExceptions}) {
+                    if ($podType) {
+                        push(@implContent, "        $podType imp(*impl());\n");
+                        if ($podType eq "float") { # Special case for JSSVGNumber
+                            push(@implContent, "        return " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp") . ";\n");
+                        } else {
+                            push(@implContent, "        return " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$getterFunctionName()") . ";\n");
+                        }
                     } else {
-                        push(@implContent, "        return " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$getterFunctionName()") . ";\n");
+                        push(@implContent, "        $implClassName* imp = static_cast<$implClassName*>(impl());\n");
+                        my $type = $codeGenerator->StripModule($attribute->signature->type);
+                        my $jsType = NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$getterFunctionName()");
+                        if ($codeGenerator->IsSVGAnimatedType($type)) {
+                            push(@implContent, "        RefPtr<$type> obj = $jsType;\n");
+                            push(@implContent, "        return toJS(exec, obj.get(), imp);\n");
+                        } else {
+                            push(@implContent, "        return $jsType;\n");
+                        }
                     }
                 } else {
-                    push(@implContent, "        $implClassName* imp = static_cast<$implClassName*>(impl());\n");
-                    my $type = $codeGenerator->StripModule($attribute->signature->type);
-                    my $jsType = NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$getterFunctionName()");
-                    if ($codeGenerator->IsSVGAnimatedType($type)) {
-                        push(@implContent, "        RefPtr<$type> obj = $jsType;\n");
-                        push(@implContent, "        return toJS(exec, obj.get(), imp);\n");
+                    push(@implContent, "        ExceptionCode ec = 0;\n");
+
+                    if ($podType) {
+                        push(@implContent, "        $podType imp(*impl());\n");
+                        push(@implContent, "        KJS::JSValue* result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$getterFunctionName(ec)") . ";\n");
                     } else {
-                        push(@implContent, "        return $jsType;\n");
+                        push(@implContent, "        $implClassName* imp = static_cast<$implClassName*>(impl());\n");
+                        push(@implContent, "        KJS::JSValue* result = " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$getterFunctionName(ec)") . ";\n");
                     }
-                }
-            } else {
-                push(@implContent, "        ExceptionCode ec = 0;\n");
 
-                if ($podType) {
-                    push(@implContent, "        $podType imp(*impl());\n");
-                    push(@implContent, "        KJS::JSValue* result = " . NativeToJSValue($attribute->signature, 0, $implClassName, "", "imp.$getterFunctionName(ec)") . ";\n");
-                } else {
-                    push(@implContent, "        $implClassName* imp = static_cast<$implClassName*>(impl());\n");
-                    push(@implContent, "        KJS::JSValue* result = " . NativeToJSValue($attribute->signature, 0, $implClassName, $implClassNameForValueConversion, "imp->$getterFunctionName(ec)") . ";\n");
+                    push(@implContent, "        setDOMException(exec, ec);\n");
+                    push(@implContent, "        return result;\n");
                 }
+                push(@implContent, "    }\n");
+            }
 
-                push(@implContent, "        setDOMException(exec, ec);\n");
-                push(@implContent, "        return result;\n");
+            if ($dataNode->extendedAttributes->{"GenerateConstructor"}) {
+                push(@implContent, "    case ConstructorAttrNum:\n");
+                push(@implContent, "        return getConstructor(exec);\n");
             }
-            push(@implContent, "    }\n");
-        }
 
-        if ($dataNode->extendedAttributes->{"GenerateConstructor"}) {
-            push(@implContent, "    case ConstructorAttrNum:\n");
-            push(@implContent, "        return getConstructor(exec);\n");
+            push(@implContent, "    }\n");
+            push(@implContent, "    return 0;\n");
+            push(@implContent, "}\n\n");
         }
 
-        push(@implContent, "    }\n");
-        push(@implContent, "    return 0;\n}\n\n");
-
         # Check if we have any writable attributes
         my $hasReadWriteProperties = 0;
         foreach my $attribute (@{$dataNode->attributes}) {
             $hasReadWriteProperties = 1 if $attribute->type !~ /^readonly/;
         }
-        if ($hasReadWriteProperties || $dataNode->extendedAttributes->{"CustomPutFunction"}) {
+
+        my $hasSetter = $hasReadWriteProperties
+                     || $dataNode->extendedAttributes->{"CustomPutFunction"}
+                     || $dataNode->extendedAttributes->{"HasCustomIndexSetter"};
+
+        if ($hasSetter) {
             push(@implContent, "void ${className}::put(ExecState* exec, const Identifier& propertyName, JSValue* value, int attr)\n");
             push(@implContent, "{\n");
             if ($dataNode->extendedAttributes->{"HasCustomIndexSetter"}) {
@@ -987,6 +1019,7 @@ sub GenerateImplementation
                 push(@implContent, "    if (customPut(exec, propertyName, value, attr))\n");
                 push(@implContent, "        return;\n");
             }
+
             if ($hasReadWriteProperties) {
                 push(@implContent, "    lookupPut<$className, Base>(exec, propertyName, value, attr, &${className}Table, this);\n");
             } else {
@@ -1062,14 +1095,14 @@ sub GenerateImplementation
         }
     }
 
-    if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"}) {
+    if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"} || $dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
         push(@implContent, "void ${className}::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames)\n");
         push(@implContent, "{\n");
         if ($dataNode->extendedAttributes->{"CustomGetPropertyNames"}) {
             push(@implContent, "    if (customGetPropertyNames(exec, propertyNames))\n");
             push(@implContent, "        return;\n");
         }
-        if ($dataNode->extendedAttributes->{"HasIndexGetter"}) {
+        if ($dataNode->extendedAttributes->{"HasIndexGetter"} || $dataNode->extendedAttributes->{"HasCustomIndexGetter"}) {
             push(@implContent, "    for (unsigned i = 0; i < static_cast<${implClassName}*>(impl())->length(); ++i)\n");
             push(@implContent, "        propertyNames.add(Identifier::from(i));\n");
         }
@@ -1735,7 +1768,7 @@ sub WriteData
         close($IMPL);
         undef($IMPL);
 
-        @implHeaderContent = ();
+        @implContentHeader = ();
         @implContent = ();
         %implIncludes = ();
     }
diff --git a/WebCore/html/CanvasPixelArray.cpp b/WebCore/html/CanvasPixelArray.cpp
new file mode 100644 (file)
index 0000000..66aae3d
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CanvasPixelArray.h"
+
+namespace WebCore {
+
+PassRefPtr<CanvasPixelArray> CanvasPixelArray::create(unsigned size)
+{
+    return adoptRef(new CanvasPixelArray(size));
+}
+
+CanvasPixelArray::CanvasPixelArray(unsigned size)
+    : m_data(size)
+{
+}
+
+}
diff --git a/WebCore/html/CanvasPixelArray.h b/WebCore/html/CanvasPixelArray.h
new file mode 100644 (file)
index 0000000..1f25e67
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CanvasPixelArray_h
+#define CanvasPixelArray_h
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+    
+    class CanvasPixelArray : public RefCounted<CanvasPixelArray> {
+    public:
+        static PassRefPtr<CanvasPixelArray> create(unsigned size);
+        Vector<unsigned char>& data() { return m_data; }
+        unsigned length() const { return m_data.size(); }
+        void set(unsigned index, double value)
+        {
+            if (!(value > 0)) // Clamp NaN to 0
+                value = 0;
+            else if (value > 255)
+                value = 255;
+            m_data[index] = static_cast<unsigned char>(round(value));
+        }
+
+        bool get(unsigned index, unsigned char& result) const
+        {
+            if (index >= m_data.size())
+                return false;
+            result = m_data[index];
+            return true;
+        }
+
+    private:
+        CanvasPixelArray(unsigned size);
+        Vector<unsigned char> m_data;
+    };
+    
+} // namespace WebCore
+
+#endif // CanvasPixelArray_h
diff --git a/WebCore/html/CanvasPixelArray.idl b/WebCore/html/CanvasPixelArray.idl
new file mode 100644 (file)
index 0000000..e8f6342
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+module html {
+
+    interface [
+        HasCustomIndexGetter,
+        HasCustomIndexSetter,
+        GenerateToJS
+    ] CanvasPixelArray {
+        readonly attribute long length;
+    };
+
+}
index 327a43e..dab3879 100644 (file)
@@ -33,6 +33,7 @@
 #include "CachedImage.h"
 #include "CanvasGradient.h"
 #include "CanvasPattern.h"
+#include "CanvasPixelArray.h"
 #include "CanvasStyle.h"
 #include "Document.h"
 #include "ExceptionCode.h"
@@ -41,6 +42,8 @@
 #include "HTMLCanvasElement.h"
 #include "HTMLImageElement.h"
 #include "HTMLNames.h"
+#include "ImageBuffer.h"
+#include "ImageData.h"
 #include "NotImplemented.h"
 #include "RenderHTMLCanvas.h"
 #include "Settings.h"
@@ -1162,4 +1165,41 @@ void CanvasRenderingContext2D::applyFillPattern()
     state().m_appliedFillPattern = true;
 }
 
+static PassRefPtr<ImageData> createEmptyImageData(const IntSize& size)
+{
+    PassRefPtr<ImageData> data = ImageData::create(size.width(), size.height());
+    memset(data->data()->data().data(), 0, data->data()->length());
+    return data;
+}
+
+PassRefPtr<ImageData> CanvasRenderingContext2D::createImageData(float sw, float sh) const
+{
+    FloatSize unscaledSize(sw, sh);
+    IntSize scaledSize;
+    if (m_canvas)
+        scaledSize = m_canvas->convertLogicalToDevice(unscaledSize);
+    else
+        scaledSize = IntSize(ceilf(sw), ceilf(sh));
+    if (scaledSize.width() < 1)
+        scaledSize.setWidth(1);
+    if (scaledSize.height() < 1)
+        scaledSize.setHeight(1);
+    
+    return createEmptyImageData(scaledSize);
+}
+
+PassRefPtr<ImageData> CanvasRenderingContext2D::getImageData(float sx, float sy, float sw, float sh) const
+{
+    FloatRect unscaledRect(sx, sy, sw, sh);
+    IntRect scaledRect = m_canvas ? m_canvas->convertLogicalToDevice(unscaledRect) : enclosingIntRect(unscaledRect);
+    if (scaledRect.width() < 1)
+        scaledRect.setWidth(1);
+    if (scaledRect.height() < 1)
+        scaledRect.setHeight(1);
+    ImageBuffer* buffer = m_canvas ? m_canvas->buffer() : 0;
+    if (!buffer)
+        return createEmptyImageData(scaledRect.size());
+    return buffer->getImageData(scaledRect);
+}
+
 } // namespace WebCore
index 30f7a53..f4cc938 100644 (file)
@@ -45,6 +45,7 @@ namespace WebCore {
     class GraphicsContext;
     class HTMLCanvasElement;
     class HTMLImageElement;
+    class ImageData;
 
     typedef int ExceptionCode;
 
@@ -162,7 +163,10 @@ namespace WebCore {
         PassRefPtr<CanvasGradient> createRadialGradient(float x0, float y0, float r0, float x1, float y1, float r1);
         PassRefPtr<CanvasPattern> createPattern(HTMLImageElement*, const String& repetitionType, ExceptionCode&);
         PassRefPtr<CanvasPattern> createPattern(HTMLCanvasElement*, const String& repetitionType, ExceptionCode&);
-
+        
+        PassRefPtr<ImageData> createImageData(float width, float height) const;
+        PassRefPtr<ImageData> getImageData(float sx, float sy, float sw, float sh) const;
+        
         void reset();
         void detachCanvas() { m_canvas = 0; }
 
index 3d566d4..d4ea6e1 100644 (file)
@@ -101,7 +101,12 @@ module html {
         [Custom] void createPattern(/* 2 */);
         
         attribute [Custom] custom strokeStyle;
-        attribute [Custom] custom fillStyle;        
+        attribute [Custom] custom fillStyle;
+        
+        // pixel manipulation
+        ImageData createImageData(in float sw, in float sh);
+        ImageData getImageData(in float sx, in float sy, in float sw, in float sh);
+        [Custom] void putImageData(/* in ImageData imagedata, in float dx, in float dy [, in float dirtyX, in float dirtyY, in float dirtyWidth, in float dirtyHeight] */);
     };
 
 }
index d711fbf..45895c7 100644 (file)
@@ -60,7 +60,7 @@ static const int defaultHeight = 150;
 // Firefox limits width/height to 32767 pixels, but slows down dramatically before it 
 // reaches that limit. We limit by area instead, giving us larger maximum dimensions,
 // in exchange for a smaller maximum canvas size.
-static const float maxCanvasArea = 32768 * 8192; // Maximum canvas area in CSS pixels
+const float HTMLCanvasElement::MaxCanvasArea = 32768 * 8192; // Maximum canvas area in CSS pixels
 
 HTMLCanvasElement::HTMLCanvasElement(Document* doc)
     : HTMLElement(canvasTag, doc)
@@ -185,24 +185,42 @@ void HTMLCanvasElement::paint(GraphicsContext* p, const IntRect& r)
         p->paintBuffer(m_imageBuffer.get(), r);
 }
 
-void HTMLCanvasElement::createImageBuffer() const
+IntRect HTMLCanvasElement::convertLogicalToDevice(const FloatRect& logicalRect) const
 {
-    ASSERT(!m_createdImageBuffer);
-    ASSERT(!m_imageBuffer);
-
-    m_createdImageBuffer = true;
+    return IntRect(convertLogicalToDevice(logicalRect.location()), convertLogicalToDevice(logicalRect.size()));
+}
 
-    float unscaledWidth = width();
-    float unscaledHeight = height();
+IntSize HTMLCanvasElement::convertLogicalToDevice(const FloatSize& logicalSize) const
+{
     float pageScaleFactor = document()->frame() ? document()->frame()->page()->chrome()->scaleFactor() : 1.0f;
-    float wf = ceilf(unscaledWidth * pageScaleFactor);
-    float hf = ceilf(unscaledHeight * pageScaleFactor);
+    float wf = ceilf(logicalSize.width() * pageScaleFactor);
+    float hf = ceilf(logicalSize.height() * pageScaleFactor);
+    
+    if (!(wf >= 1 && hf >= 1 && wf * hf <= MaxCanvasArea))
+        return IntSize();
 
-    if (!(wf >= 1 && hf >= 1 && wf * hf <= maxCanvasArea))
-        return;
+    return IntSize(static_cast<unsigned>(wf), static_cast<unsigned>(hf));
+}
+
+IntPoint HTMLCanvasElement::convertLogicalToDevice(const FloatPoint& logicalPos) const
+{
+    float pageScaleFactor = document()->frame() ? document()->frame()->page()->chrome()->scaleFactor() : 1.0f;
+    float xf = logicalPos.x() * pageScaleFactor;
+    float yf = logicalPos.y() * pageScaleFactor;
+    
+    return IntPoint(static_cast<unsigned>(xf), static_cast<unsigned>(yf));
+}
 
-    IntSize size(static_cast<unsigned>(wf), static_cast<unsigned>(hf));
+void HTMLCanvasElement::createImageBuffer() const
+{
+    ASSERT(!m_imageBuffer);
 
+    m_createdImageBuffer = true;
+    
+    FloatSize unscaledSize(width(), height());
+    IntSize size = convertLogicalToDevice(unscaledSize);
+    if (!size.width() || !size.height())
+        return;
     m_imageBuffer.set(ImageBuffer::create(size, false).release());
 }
 
index 0836f09..2876be3 100644 (file)
@@ -45,9 +45,14 @@ namespace WebCore {
 
 class CanvasRenderingContext2D;
 typedef CanvasRenderingContext2D CanvasRenderingContext;
+class FloatPoint;
 class FloatRect;
+class FloatSize;
 class GraphicsContext;
 class ImageBuffer;
+class IntPoint;
+class InttRect;
+class IntSize;
 
 class HTMLCanvasElement : public HTMLElement {
 public:
@@ -83,7 +88,11 @@ public:
 #elif PLATFORM(CAIRO)
     cairo_surface_t* createPlatformImage() const;
 #endif
-
+    
+    IntRect convertLogicalToDevice(const FloatRect&) const;
+    IntSize convertLogicalToDevice(const FloatSize&) const;
+    IntPoint convertLogicalToDevice(const FloatPoint&) const;
+    static const float MaxCanvasArea;
 private:
     void createImageBuffer() const;
     void reset();
diff --git a/WebCore/html/ImageData.cpp b/WebCore/html/ImageData.cpp
new file mode 100644 (file)
index 0000000..3653031
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ImageData.h"
+
+#include "CanvasPixelArray.h"
+
+namespace WebCore {
+
+PassRefPtr<ImageData> ImageData::create(unsigned width, unsigned height)
+{
+    return adoptRef(new ImageData(width, height));
+}
+
+ImageData::ImageData(unsigned width, unsigned height)
+    : m_width(width)
+    , m_height(height)
+    , m_data(CanvasPixelArray::create(width * height * 4))
+{
+}
+
+}
+
diff --git a/WebCore/html/ImageData.h b/WebCore/html/ImageData.h
new file mode 100644 (file)
index 0000000..21af1f9
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ImageData_h
+#define ImageData_h
+
+#include "CanvasPixelArray.h"
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+    class ImageData : public RefCounted<ImageData> {
+    public:
+        static PassRefPtr<ImageData> create(unsigned width, unsigned height);
+
+        unsigned width() const { return m_width; }
+        unsigned height() const { return m_height; }
+        CanvasPixelArray* data() const { return m_data.get(); }
+
+    private:
+        ImageData(unsigned width, unsigned height);
+        unsigned m_width;
+        unsigned m_height;
+        RefPtr<CanvasPixelArray> m_data;
+    };
+
+} // namespace WebCore
+
+#endif // ImageData_h
diff --git a/WebCore/html/ImageData.idl b/WebCore/html/ImageData.idl
new file mode 100644 (file)
index 0000000..052f165
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+module html {
+
+    interface [
+        GenerateConstructor
+    ] ImageData {
+        readonly attribute long width;
+        readonly attribute long height;
+        readonly attribute CanvasPixelArray data;
+    };
+
+}
index a19298e..869cd71 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "IntSize.h"
 #include <wtf/OwnPtr.h>
+#include <wtf/PassRefPtr.h>
 #include <memory>
 
 #if PLATFORM(CG)
@@ -47,6 +48,8 @@ typedef struct _cairo_surface cairo_surface_t;
 namespace WebCore {
 
     class GraphicsContext;
+    class ImageData;
+    class IntRect;
     class RenderObject;
 
     class ImageBuffer : Noncopyable {
@@ -65,6 +68,7 @@ namespace WebCore {
         cairo_surface_t* surface() const;
 #endif
 
+        PassRefPtr<ImageData> getImageData(const IntRect& rect) const;
     private:
         void* m_data;
         IntSize m_size;
index 776529e..1f68ce0 100644 (file)
@@ -72,5 +72,10 @@ cairo_surface_t* ImageBuffer::surface() const
     return m_surface;
 }
 
+PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect&) const
+{
+    notImplemented();
+    return 0;
+}
 
 }
index 2d1ac01..f456ec5 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2008 Apple, Inc
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -27,6 +28,7 @@
 #include "ImageBuffer.h"
 
 #include "GraphicsContext.h"
+#include "ImageData.h"
 
 #include <ApplicationServices/ApplicationServices.h>
 #include <wtf/Assertions.h>
@@ -98,4 +100,60 @@ CGImageRef ImageBuffer::cgImage() const
     return m_cgImage;
 }
 
+PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const
+{
+    if (!m_data)
+        return 0;
+    
+    PassRefPtr<ImageData> result = ImageData::create(rect.width(), rect.height());
+    unsigned char* data = result->data()->data().data();
+    
+    if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > m_size.width() || (rect.y() + rect.height()) > m_size.height())
+        memset(data, 0, result->data()->length());
+
+    int originx = rect.x();
+    int destx = 0;
+    if (originx < 0) {
+        destx = -originx;
+        originx = 0;
+    }
+    int endx = rect.x() + rect.width();
+    if (endx > m_size.width())
+        endx = m_size.width();
+    int numColumns = endx - originx;
+    
+    int originy = rect.y();
+    int desty = 0;
+    if (originy < 0) {
+        desty = -originy;
+        originy = 0;
+    }
+    int endy = rect.y() + rect.height();
+    if (endy > m_size.height())
+        endy = m_size.height();
+    int numRows = endy - originy;
+    
+    unsigned srcBytesPerRow = 4 * m_size.width();
+    unsigned destBytesPerRow = 4 * rect.width();
+    
+    // -originy to handle the accursed flipped y axis
+    unsigned char* srcRows = reinterpret_cast<unsigned char*>(m_data) + (m_size.height() - originy - 1) * srcBytesPerRow + originx * 4;
+    unsigned char* destRows = data + desty * destBytesPerRow + destx * 4;
+    for (int y = 0; y < numRows; ++y) {
+        for (int x = 0; x < numColumns; x++) {
+            if (unsigned char alpha = srcRows[3]) {
+                destRows[0] = (srcRows[0] * 255) / alpha;
+                destRows[1] = (srcRows[1] * 255) / alpha;
+                destRows[2] = (srcRows[2] * 255) / alpha;
+                destRows[3] = alpha;
+            } else {
+                reinterpret_cast<uint32_t*>(destRows)[0] = reinterpret_cast<uint32_t*>(srcRows)[0];
+            }
+            destRows += 4;
+        }
+        srcRows -= srcBytesPerRow;
+    }
+    return result;
+}
+
 }
index c95d8c8..98bb201 100644 (file)
@@ -27,6 +27,7 @@
 #include "ImageBuffer.h"
 
 #include "GraphicsContext.h"
+#include "NotImplemented.h"
 
 #include <QPainter>
 #include <QPixmap>
@@ -69,4 +70,10 @@ QPixmap* ImageBuffer::pixmap() const
     return &m_pixmap;
 }
 
+PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect&) const
+{
+    notImplemented();
+    return 0;
+}
+
 }
index bc54a88..2f93256 100644 (file)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "ImageBuffer.h"
 #include "GraphicsContext.h"
+#include "NotImplemented.h"
 
 namespace WebCore {
 
@@ -43,4 +44,10 @@ GraphicsContext* ImageBuffer::context() const
     return 0;
 }
 
+PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect&) const
+{
+    notImplemented();
+    return 0;
+}
+
 }