<rdar://problem/10912680> Pixel access canvas APIs do not operate at backing store...
authormitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 Apr 2012 18:20:25 +0000 (18:20 +0000)
committermitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 13 Apr 2012 18:20:25 +0000 (18:20 +0000)
https://bugs.webkit.org/show_bug.cgi?id=83836

Reviewed by Darin Adler.

Source/WebCore:

Test: fast/canvas/2d.imageDataHD.html

Added getImageDataHD and putImageDataHD functions to CanvasRenderingContext2D, as proposed in
<http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2012-March/035112.html>. The functions
are prefixed with “webkit” for now.

* html/canvas/CanvasRenderingContext2D.cpp:
(WebCore::CanvasRenderingContext2D::getImageData): Added this cover function that calls
through to getImageData with LogicalCoordinateSystem.
(WebCore::CanvasRenderingContext2D::webkitGetImageDataHD): Added. Calls through to
getImageData with BackingStoreCoordinateSystem.
(WebCore::CanvasRenderingContext2D::getImageData): Added a CoordinateSystem parameter to this
now-private function. It is passed through to ImageBuffer::getUnmultipliedImageData().
(WebCore::CanvasRenderingContext2D::putImageData): Added this cover function that calls
through to putImageData with LogicalCoordinateSystem.
(WebCore::CanvasRenderingContext2D::webkitPutImageDataHD): Added. Calls through to
putImageData with BackingStoreCoordinateSystem.
(WebCore::CanvasRenderingContext2D::putImageData): Added a CoordinateSystem parameter to this
function. It is passed through to ImageBuffer::putByteArray, and used to compute the rect to
invalidate after the drawing operation.
* html/canvas/CanvasRenderingContext2D.h:
* html/canvas/CanvasRenderingContext2D.idl: Added webkitPutImageDataHD() and
webkitGetImageDataHD().
* platform/graphics/ImageBuffer.h: Added a CoordinateSystem enum with the values
LogicalCoordinateSystem and BackingStoreCoordinateSystem. Added a CoordinateSystem parameter,
which defaults to LogicalCoordinateSystem, to getUnmultipliedImageData,
getPremultipliedImageData, and putByteArray.
* platform/graphics/cairo/ImageBufferCairo.cpp:
(WebCore::ImageBuffer::getUnmultipliedImageData):
(WebCore::ImageBuffer::getPremultipliedImageData):
(WebCore::ImageBuffer::putByteArray):
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/cg/ImageBufferCG.cpp:
(WebCore::ImageBuffer::getUnmultipliedImageData): Now uses the CoordinateSystem parameter to
decide whether to ask ImageBufferDaya::getData() to apply the resolution scale or not.
(WebCore::ImageBuffer::getPremultipliedImageData): Ditto.
(WebCore::ImageBuffer::putByteArray): Now uses the CoordinateSystem parameter to decide
whether to maintain the resolution scale while drawing or not.
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/gtk/ImageBufferGtk.cpp:
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/qt/ImageBufferQt.cpp:
(WebCore::ImageBuffer::getUnmultipliedImageData):
(WebCore::ImageBuffer::getPremultipliedImageData):
(WebCore::ImageBuffer::putByteArray):
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/skia/ImageBufferSkia.cpp:
(WebCore::ImageBuffer::getUnmultipliedImageData):
(WebCore::ImageBuffer::getPremultipliedImageData):
(WebCore::ImageBuffer::putByteArray):
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/wince/ImageBufferWinCE.cpp:
(WebCore::ImageBuffer::getUnmultipliedImageData):
(WebCore::ImageBuffer::getPremultipliedImageData):
(WebCore::ImageBuffer::putByteArray):
(WebCore::ImageBuffer::toDataURL):
* platform/graphics/wx/ImageBufferWx.cpp:
(WebCore::ImageBuffer::getUnmultipliedImageData):
(WebCore::ImageBuffer::getPremultipliedImageData):
(WebCore::ImageBuffer::putByteArray):
(WebCore::ImageBuffer::toDataURL):

LayoutTests:

* fast/canvas/2d.imageDataHD-expected.txt: Added.
* fast/canvas/2d.imageDataHD.html: Added.

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

17 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/canvas/2d.imageDataHD-expected.txt [new file with mode: 0644]
LayoutTests/fast/canvas/2d.imageDataHD.html [new file with mode: 0644]
LayoutTests/platform/mac/fast/canvas/2d.imageDataHD-expected.txt [new file with mode: 0644]
LayoutTests/platform/win/fast/canvas/2d.imageDataHD-expected.txt [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
Source/WebCore/html/canvas/CanvasRenderingContext2D.h
Source/WebCore/html/canvas/CanvasRenderingContext2D.idl
Source/WebCore/platform/graphics/ImageBuffer.h
Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
Source/WebCore/platform/graphics/gtk/ImageBufferGtk.cpp
Source/WebCore/platform/graphics/qt/ImageBufferQt.cpp
Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
Source/WebCore/platform/graphics/wince/ImageBufferWinCE.cpp
Source/WebCore/platform/graphics/wx/ImageBufferWx.cpp

index b9d79e0..2a3b4f2 100644 (file)
@@ -1,3 +1,13 @@
+2012-04-13  Dan Bernstein  <mitz@apple.com>
+
+        <rdar://problem/10912680> Pixel access canvas APIs do not operate at backing store resolution
+        https://bugs.webkit.org/show_bug.cgi?id=83836
+
+        Reviewed by Darin Adler.
+
+        * fast/canvas/2d.imageDataHD-expected.txt: Added.
+        * fast/canvas/2d.imageDataHD.html: Added.
+
 2012-04-13  Anders Carlsson  <andersca@apple.com>
 
         Rebaseline a test.
diff --git a/LayoutTests/fast/canvas/2d.imageDataHD-expected.txt b/LayoutTests/fast/canvas/2d.imageDataHD-expected.txt
new file mode 100644 (file)
index 0000000..3cc4ba7
--- /dev/null
@@ -0,0 +1,2 @@
+High-DPI canvas is not enabled.
+
diff --git a/LayoutTests/fast/canvas/2d.imageDataHD.html b/LayoutTests/fast/canvas/2d.imageDataHD.html
new file mode 100644 (file)
index 0000000..b392bbd
--- /dev/null
@@ -0,0 +1,118 @@
+<pre id="console"></pre>
+<script>
+    layoutTestController.dumpAsText();
+
+    function log(message)
+    {
+        document.getElementById("console").appendChild(document.createTextNode(message + "\n"));
+    }
+
+    function formatColor(r, g, b, a)
+    {
+        return "[" + r + ", " + g + ", " + b + ", " + a + "]";
+    }
+
+    function assertBlack(imageData, i)
+    {
+        var r = imageData.data[i * 4];
+        var g = imageData.data[i * 4 + 1];
+        var b = imageData.data[i * 4 + 2];
+        var a = imageData.data[i * 4 + 3];
+        if (r == 0 && g == 0 && b == 0 && a == 255)
+            log("PASS: Pixel " + i + " is black.");
+        else
+            log("FAIL: Pixel " + i + " is not black: " + formatColor(r, g, b, a) + ".");
+    }
+
+    function assertGreen(imageData, i)
+    {
+        var r = imageData.data[i * 4];
+        var g = imageData.data[i * 4 + 1];
+        var b = imageData.data[i * 4 + 2];
+        var a = imageData.data[i * 4 + 3];
+        if (r == 0 && g == 255 && b == 0 && a == 255)
+            log("PASS: Pixel " + i + " is green.");
+        else
+            log("FAIL: Pixel " + i + " is not green: " + formatColor(r, g, b, a) + ".");
+    }
+
+    function assertBlue(imageData, i)
+    {
+        var r = imageData.data[i * 4];
+        var g = imageData.data[i * 4 + 1];
+        var b = imageData.data[i * 4 + 2];
+        var a = imageData.data[i * 4 + 3];
+        if (r == 0 && g == 0 && b == 255 && a == 255)
+            log("PASS: Pixel " + i + " is blue.");
+        else
+            log("FAIL: Pixel " + i + " is not blue: " + formatColor(r, g, b, a) + ".");
+    }
+
+    if (!window.layoutTestController)
+        log("This test requires WebKitTestRunner or DumpRenderTree.");
+
+    layoutTestController.waitUntilDone();
+    layoutTestController.setBackingScaleFactor(2, function() {
+        var canvas = document.createElement("canvas");
+        canvas.width = 8;
+        canvas.height = 8;
+
+        var context = canvas.getContext("2d");
+
+        if (context.webkitBackingStorePixelRatio === 2) {
+
+            context.fillStyle = "#0f0";
+            context.fillRect(0, 0, 4, 8);
+            context.fillStyle = "#00f";
+            context.fillRect(4, 0, 4, 8);
+
+            log("Testing getImageDataHD");
+
+            var imageData = context.webkitGetImageDataHD(7, 0, 2, 1);
+            assertGreen(imageData, 0);
+            assertBlue(imageData, 1);
+
+            log("\nTesting putImageDataHD");
+
+            context.fillStyle = "#000";
+            context.fillRect(0, 0, 8, 8);
+
+            imageData = context.createImageData(8, 8);
+            for (var i = 0; i < 128; i += 4) {
+                imageData.data[i] = 0;
+                imageData.data[i + 1] = 255;
+                imageData.data[i + 2] = 0;
+                imageData.data[i + 3] = 255;
+            }
+            for (var i = 128; i < 256; i += 4) {
+                imageData.data[i] = 0;
+                imageData.data[i + 1] = 0;
+                imageData.data[i + 2] = 255;
+                imageData.data[i + 3] = 255;
+            }
+
+            context.webkitPutImageDataHD(imageData, 2, 2);
+
+            imageData = context.getImageData(2, 0, 1, 1);
+            assertBlack(imageData, 0);
+
+            imageData = context.getImageData(2, 1, 1, 1);
+            assertGreen(imageData, 0);
+
+            imageData = context.getImageData(2, 2, 1, 1);
+            assertGreen(imageData, 0);
+
+            imageData = context.getImageData(2, 3, 1, 1);
+            assertBlue(imageData, 0);
+
+            imageData = context.getImageData(2, 4, 1, 1);
+            assertBlue(imageData, 0);
+
+            imageData = context.getImageData(2, 5, 1, 1);
+            assertBlack(imageData, 0);
+        } else
+            log("High-DPI canvas is not enabled.");
+
+        layoutTestController.notifyDone();
+    });
+</script>
diff --git a/LayoutTests/platform/mac/fast/canvas/2d.imageDataHD-expected.txt b/LayoutTests/platform/mac/fast/canvas/2d.imageDataHD-expected.txt
new file mode 100644 (file)
index 0000000..4b351d5
--- /dev/null
@@ -0,0 +1,12 @@
+Testing getImageDataHD
+PASS: Pixel 0 is green.
+PASS: Pixel 1 is blue.
+
+Testing putImageDataHD
+PASS: Pixel 0 is black.
+PASS: Pixel 0 is green.
+PASS: Pixel 0 is green.
+PASS: Pixel 0 is blue.
+PASS: Pixel 0 is blue.
+PASS: Pixel 0 is black.
+
diff --git a/LayoutTests/platform/win/fast/canvas/2d.imageDataHD-expected.txt b/LayoutTests/platform/win/fast/canvas/2d.imageDataHD-expected.txt
new file mode 100644 (file)
index 0000000..4b351d5
--- /dev/null
@@ -0,0 +1,12 @@
+Testing getImageDataHD
+PASS: Pixel 0 is green.
+PASS: Pixel 1 is blue.
+
+Testing putImageDataHD
+PASS: Pixel 0 is black.
+PASS: Pixel 0 is green.
+PASS: Pixel 0 is green.
+PASS: Pixel 0 is blue.
+PASS: Pixel 0 is blue.
+PASS: Pixel 0 is black.
+
index 77f9481..4b08b97 100644 (file)
@@ -1,3 +1,72 @@
+2012-04-13  Dan Bernstein  <mitz@apple.com>
+
+        <rdar://problem/10912680> Pixel access canvas APIs do not operate at backing store resolution
+        https://bugs.webkit.org/show_bug.cgi?id=83836
+
+        Reviewed by Darin Adler.
+
+        Test: fast/canvas/2d.imageDataHD.html
+
+        Added getImageDataHD and putImageDataHD functions to CanvasRenderingContext2D, as proposed in
+        <http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2012-March/035112.html>. The functions
+        are prefixed with “webkit” for now.
+
+        * html/canvas/CanvasRenderingContext2D.cpp:
+        (WebCore::CanvasRenderingContext2D::getImageData): Added this cover function that calls
+        through to getImageData with LogicalCoordinateSystem.
+        (WebCore::CanvasRenderingContext2D::webkitGetImageDataHD): Added. Calls through to
+        getImageData with BackingStoreCoordinateSystem.
+        (WebCore::CanvasRenderingContext2D::getImageData): Added a CoordinateSystem parameter to this
+        now-private function. It is passed through to ImageBuffer::getUnmultipliedImageData().
+        (WebCore::CanvasRenderingContext2D::putImageData): Added this cover function that calls
+        through to putImageData with LogicalCoordinateSystem.
+        (WebCore::CanvasRenderingContext2D::webkitPutImageDataHD): Added. Calls through to
+        putImageData with BackingStoreCoordinateSystem.
+        (WebCore::CanvasRenderingContext2D::putImageData): Added a CoordinateSystem parameter to this
+        function. It is passed through to ImageBuffer::putByteArray, and used to compute the rect to
+        invalidate after the drawing operation.
+        * html/canvas/CanvasRenderingContext2D.h:
+        * html/canvas/CanvasRenderingContext2D.idl: Added webkitPutImageDataHD() and
+        webkitGetImageDataHD().
+        * platform/graphics/ImageBuffer.h: Added a CoordinateSystem enum with the values
+        LogicalCoordinateSystem and BackingStoreCoordinateSystem. Added a CoordinateSystem parameter,
+        which defaults to LogicalCoordinateSystem, to getUnmultipliedImageData,
+        getPremultipliedImageData, and putByteArray.
+        * platform/graphics/cairo/ImageBufferCairo.cpp:
+        (WebCore::ImageBuffer::getUnmultipliedImageData):
+        (WebCore::ImageBuffer::getPremultipliedImageData):
+        (WebCore::ImageBuffer::putByteArray):
+        (WebCore::ImageBuffer::toDataURL):
+        * platform/graphics/cg/ImageBufferCG.cpp:
+        (WebCore::ImageBuffer::getUnmultipliedImageData): Now uses the CoordinateSystem parameter to
+        decide whether to ask ImageBufferDaya::getData() to apply the resolution scale or not.
+        (WebCore::ImageBuffer::getPremultipliedImageData): Ditto.
+        (WebCore::ImageBuffer::putByteArray): Now uses the CoordinateSystem parameter to decide
+        whether to maintain the resolution scale while drawing or not.
+        (WebCore::ImageBuffer::toDataURL):
+        * platform/graphics/gtk/ImageBufferGtk.cpp:
+        (WebCore::ImageBuffer::toDataURL):
+        * platform/graphics/qt/ImageBufferQt.cpp:
+        (WebCore::ImageBuffer::getUnmultipliedImageData):
+        (WebCore::ImageBuffer::getPremultipliedImageData):
+        (WebCore::ImageBuffer::putByteArray):
+        (WebCore::ImageBuffer::toDataURL):
+        * platform/graphics/skia/ImageBufferSkia.cpp:
+        (WebCore::ImageBuffer::getUnmultipliedImageData):
+        (WebCore::ImageBuffer::getPremultipliedImageData):
+        (WebCore::ImageBuffer::putByteArray):
+        (WebCore::ImageBuffer::toDataURL):
+        * platform/graphics/wince/ImageBufferWinCE.cpp:
+        (WebCore::ImageBuffer::getUnmultipliedImageData):
+        (WebCore::ImageBuffer::getPremultipliedImageData):
+        (WebCore::ImageBuffer::putByteArray):
+        (WebCore::ImageBuffer::toDataURL):
+        * platform/graphics/wx/ImageBufferWx.cpp:
+        (WebCore::ImageBuffer::getUnmultipliedImageData):
+        (WebCore::ImageBuffer::getPremultipliedImageData):
+        (WebCore::ImageBuffer::putByteArray):
+        (WebCore::ImageBuffer::toDataURL):
+
 2012-04-12  Shawn Singh  <shawnsingh@chromium.org>
 
         [chromium] Support CCHeadsUpDisplay in threaded compositing mode
index 7734f59..46ae04f 100644 (file)
@@ -51,7 +51,6 @@
 #include "HTMLMediaElement.h"
 #include "HTMLNames.h"
 #include "HTMLVideoElement.h"
-#include "ImageBuffer.h"
 #include "ImageData.h"
 #include "KURL.h"
 #include "Page.h"
@@ -1789,12 +1788,23 @@ PassRefPtr<ImageData> CanvasRenderingContext2D::createImageData(float sw, float
 
 PassRefPtr<ImageData> CanvasRenderingContext2D::getImageData(float sx, float sy, float sw, float sh, ExceptionCode& ec) const
 {
+    return getImageData(ImageBuffer::LogicalCoordinateSystem, sx, sy, sw, sh, ec);
+}
+
+PassRefPtr<ImageData> CanvasRenderingContext2D::webkitGetImageDataHD(float sx, float sy, float sw, float sh, ExceptionCode& ec) const
+{
+    return getImageData(ImageBuffer::BackingStoreCoordinateSystem, sx, sy, sw, sh, ec);
+}
+
+PassRefPtr<ImageData> CanvasRenderingContext2D::getImageData(ImageBuffer::CoordinateSystem coordinateSystem, float sx, float sy, float sw, float sh, ExceptionCode& ec) const
+{
     if (!canvas()->originClean()) {
         DEFINE_STATIC_LOCAL(String, consoleMessage, ("Unable to get image data from canvas because the canvas has been tainted by cross-origin data."));
         canvas()->document()->addConsoleMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, consoleMessage);
         ec = SECURITY_ERR;
         return 0;
     }
+
     if (!sw || !sh) {
         ec = INDEX_SIZE_ERR;
         return 0;
@@ -1812,7 +1822,7 @@ PassRefPtr<ImageData> CanvasRenderingContext2D::getImageData(float sx, float sy,
         sy += sh;
         sh = -sh;
     }
-    
+
     FloatRect logicalRect(sx, sy, sw, sh);
     if (logicalRect.width() < 1)
         logicalRect.setWidth(1);
@@ -1826,7 +1836,7 @@ PassRefPtr<ImageData> CanvasRenderingContext2D::getImageData(float sx, float sy,
     if (!buffer)
         return createEmptyImageData(imageDataRect.size());
 
-    RefPtr<ByteArray> byteArray = buffer->getUnmultipliedImageData(imageDataRect);
+    RefPtr<ByteArray> byteArray = buffer->getUnmultipliedImageData(imageDataRect, coordinateSystem);
     if (!byteArray)
         return 0;
 
@@ -1842,9 +1852,29 @@ void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy,
     putImageData(data, dx, dy, 0, 0, data->width(), data->height(), ec);
 }
 
+void CanvasRenderingContext2D::webkitPutImageDataHD(ImageData* data, float dx, float dy, ExceptionCode& ec)
+{
+    if (!data) {
+        ec = TYPE_MISMATCH_ERR;
+        return;
+    }
+    webkitPutImageDataHD(data, dx, dy, 0, 0, data->width(), data->height(), ec);
+}
+
 void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy, float dirtyX, float dirtyY,
                                             float dirtyWidth, float dirtyHeight, ExceptionCode& ec)
 {
+    putImageData(data, ImageBuffer::LogicalCoordinateSystem, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight, ec);
+}
+
+void CanvasRenderingContext2D::webkitPutImageDataHD(ImageData* data, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight, ExceptionCode& ec)
+{
+    putImageData(data, ImageBuffer::BackingStoreCoordinateSystem, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight, ec);
+}
+
+void CanvasRenderingContext2D::putImageData(ImageData* data, ImageBuffer::CoordinateSystem coordinateSystem, float dx, float dy, float dirtyX, float dirtyY,
+                                            float dirtyWidth, float dirtyHeight, ExceptionCode& ec)
+{
     if (!data) {
         ec = TYPE_MISMATCH_ERR;
         return;
@@ -1873,13 +1903,19 @@ void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy,
     IntSize destOffset(static_cast<int>(dx), static_cast<int>(dy));
     IntRect destRect = enclosingIntRect(clipRect);
     destRect.move(destOffset);
-    destRect.intersect(IntRect(IntPoint(), buffer->internalSize()));
+    destRect.intersect(IntRect(IntPoint(), coordinateSystem == ImageBuffer::LogicalCoordinateSystem ? buffer->logicalSize() : buffer->internalSize()));
     if (destRect.isEmpty())
         return;
     IntRect sourceRect(destRect);
     sourceRect.move(-destOffset);
 
-    buffer->putByteArray(Unmultiplied, data->data()->data(), IntSize(data->width(), data->height()), sourceRect, IntPoint(destOffset));
+    buffer->putByteArray(Unmultiplied, data->data()->data(), IntSize(data->width(), data->height()), sourceRect, IntPoint(destOffset), coordinateSystem);
+
+    if (coordinateSystem == ImageBuffer::BackingStoreCoordinateSystem) {
+        FloatRect dirtyRect = destRect;
+        dirtyRect.scale(1 / canvas()->deviceScaleFactor());
+        destRect = enclosingIntRect(dirtyRect);
+    }
     didDraw(destRect, CanvasDidDrawApplyNone); // ignore transform, shadow and clip
 }
 
index d6f073d..6ebdf21 100644 (file)
@@ -34,6 +34,7 @@
 #include "FloatSize.h"
 #include "Font.h"
 #include "GraphicsTypes.h"
+#include "ImageBuffer.h"
 #include "Path.h"
 #include "PlatformString.h"
 #include <wtf/Vector.h>
@@ -197,8 +198,11 @@ public:
     PassRefPtr<ImageData> createImageData(PassRefPtr<ImageData>, ExceptionCode&) const;
     PassRefPtr<ImageData> createImageData(float width, float height, ExceptionCode&) const;
     PassRefPtr<ImageData> getImageData(float sx, float sy, float sw, float sh, ExceptionCode&) const;
+    PassRefPtr<ImageData> webkitGetImageDataHD(float sx, float sy, float sw, float sh, ExceptionCode&) const;
     void putImageData(ImageData*, float dx, float dy, ExceptionCode&);
     void putImageData(ImageData*, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight, ExceptionCode&);
+    void webkitPutImageDataHD(ImageData*, float dx, float dy, ExceptionCode&);
+    void webkitPutImageDataHD(ImageData*, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight, ExceptionCode&);
 
     float webkitBackingStorePixelRatio() const { return canvas()->deviceScaleFactor(); }
 
@@ -313,6 +317,9 @@ private:
 
     void prepareGradientForDashboard(CanvasGradient* gradient) const;
 
+    PassRefPtr<ImageData> getImageData(ImageBuffer::CoordinateSystem, float sx, float sy, float sw, float sh, ExceptionCode&) const;
+    void putImageData(ImageData*, ImageBuffer::CoordinateSystem, float dx, float dy, float dirtyX, float dirtyY, float dirtyWidth, float dirtyHeight, ExceptionCode&);
+
     Vector<State, 1> m_stateStack;
     bool m_usesCSSCompatibilityParseMode;
 #if ENABLE(DASHBOARD_SUPPORT)
index 4267494..67b5e05 100644 (file)
@@ -204,6 +204,11 @@ module html {
         void putImageData(in ImageData imagedata, in float dx, in float dy, in float dirtyX, in float dirtyY, in float dirtyWidth, in float dirtyHeight)
             raises(DOMException);
 
+        void webkitPutImageDataHD(in ImageData imagedata, in float dx, in float dy)
+            raises(DOMException);
+        void webkitPutImageDataHD(in ImageData imagedata, in float dx, in float dy, in float dirtyX, in float dirtyY, in float dirtyWidth, in float dirtyHeight)
+            raises(DOMException);
+
         CanvasPattern createPattern(in HTMLCanvasElement canvas, in [TreatNullAs=NullString] DOMString repetitionType)
             raises (DOMException);
         CanvasPattern createPattern(in HTMLImageElement image, in [TreatNullAs=NullString] DOMString repetitionType)
@@ -221,6 +226,10 @@ module html {
                                in [Optional=DefaultIsUndefined] float sw, in [Optional=DefaultIsUndefined] float sh)
             raises(DOMException);
 
+        ImageData webkitGetImageDataHD(in [Optional=DefaultIsUndefined] float sx, in [Optional=DefaultIsUndefined] float sy,
+                                       in [Optional=DefaultIsUndefined] float sw, in [Optional=DefaultIsUndefined] float sh)
+            raises(DOMException);
+
         readonly attribute float webkitBackingStorePixelRatio;
     };
 
index e865578..ed8387f 100644 (file)
@@ -96,14 +96,16 @@ namespace WebCore {
 
         PassRefPtr<Image> copyImage(BackingStoreCopy = CopyBackingStore) const;
 
-        PassRefPtr<ByteArray> getUnmultipliedImageData(const IntRect&) const;
-        PassRefPtr<ByteArray> getPremultipliedImageData(const IntRect&) const;
+        enum CoordinateSystem { LogicalCoordinateSystem, BackingStoreCoordinateSystem };
 
-        void putByteArray(Multiply multiplied, ByteArray*, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint);
+        PassRefPtr<ByteArray> getUnmultipliedImageData(const IntRect&, CoordinateSystem = LogicalCoordinateSystem) const;
+        PassRefPtr<ByteArray> getPremultipliedImageData(const IntRect&, CoordinateSystem = LogicalCoordinateSystem) const;
+
+        void putByteArray(Multiply multiplied, ByteArray*, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem = LogicalCoordinateSystem);
         
         void convertToLuminanceMask();
         
-        String toDataURL(const String& mimeType, const double* quality = 0) const;
+        String toDataURL(const String& mimeType, const double* quality = 0, CoordinateSystem = LogicalCoordinateSystem) const;
 #if !USE(CG)
         AffineTransform baseTransform() const { return AffineTransform(); }
         void transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstColorSpace);
index 8bb01b5..efaf80f 100644 (file)
@@ -190,17 +190,17 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const ImageBufferData& d
     return result.release();
 }
 
-PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
+PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect, CoordinateSystem) const
 {
     return getImageData<Unmultiplied>(rect, m_data, m_size);
 }
 
-PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect, CoordinateSystem) const
 {
     return getImageData<Premultiplied>(rect, m_data, m_size);
 }
 
-void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
+void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem)
 {
     ASSERT(cairo_surface_get_type(m_data.m_surface) == CAIRO_SURFACE_TYPE_IMAGE);
 
@@ -265,7 +265,7 @@ static cairo_status_t writeFunction(void* closure, const unsigned char* data, un
     return CAIRO_STATUS_SUCCESS;
 }
 
-String ImageBuffer::toDataURL(const String& mimeType, const double*) const
+String ImageBuffer::toDataURL(const String& mimeType, const double*, CoordinateSystem) const
 {
     cairo_surface_t* image = cairo_get_target(context()->platformContext()->cr());
     if (!image)
index ca56d08..6ef374f 100644 (file)
@@ -306,7 +306,7 @@ void ImageBuffer::clip(GraphicsContext* contextToClip, const FloatRect& rect) co
     CGContextTranslateCTM(platformContextToClip, -rect.x(), -rect.y() - rect.height());
 }
 
-PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
+PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect, CoordinateSystem coordinateSystem) const
 {
     if (m_context->isAcceleratedContext()) {
         CGContextFlush(context()->platformContext());
@@ -314,10 +314,10 @@ PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect)
         m_data.m_lastFlushTime = currentTimeMS();
 #endif
     }
-    return m_data.getData(rect, internalSize(), m_context->isAcceleratedContext(), true, m_resolutionScale);
+    return m_data.getData(rect, internalSize(), m_context->isAcceleratedContext(), true, coordinateSystem == LogicalCoordinateSystem ? m_resolutionScale : 1);
 }
 
-PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect, CoordinateSystem coordinateSystem) const
 {
     if (m_context->isAcceleratedContext()) {
         CGContextFlush(context()->platformContext());
@@ -325,13 +325,13 @@ PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect
         m_data.m_lastFlushTime = currentTimeMS();
 #endif
     }
-    return m_data.getData(rect, internalSize(), m_context->isAcceleratedContext(), false, m_resolutionScale);
+    return m_data.getData(rect, internalSize(), m_context->isAcceleratedContext(), false, coordinateSystem == LogicalCoordinateSystem ? m_resolutionScale : 1);
 }
 
-void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
+void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem coordinateSystem)
 {
     if (!m_context->isAcceleratedContext()) {
-        m_data.putData(source, sourceSize, sourceRect, destPoint, internalSize(), m_context->isAcceleratedContext(), multiplied == Unmultiplied, m_resolutionScale);
+        m_data.putData(source, sourceSize, sourceRect, destPoint, internalSize(), m_context->isAcceleratedContext(), multiplied == Unmultiplied, coordinateSystem == LogicalCoordinateSystem ? m_resolutionScale : 1);
         return;
     }
 
@@ -347,7 +347,10 @@ void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const Int
     // Set up context for using drawImage as a direct bit copy
     CGContextRef destContext = context()->platformContext();
     CGContextSaveGState(destContext);
-    CGContextConcatCTM(destContext, AffineTransform(wkGetUserToBaseCTM(destContext)).inverse());
+    if (coordinateSystem == LogicalCoordinateSystem)
+        CGContextConcatCTM(destContext, AffineTransform(wkGetUserToBaseCTM(destContext)).inverse());
+    else
+        CGContextConcatCTM(destContext, AffineTransform(CGContextGetCTM(destContext)).inverse());
     wkCGContextResetClip(destContext);
     CGContextSetInterpolationQuality(destContext, kCGInterpolationNone);
     CGContextSetAlpha(destContext, 1.0);
@@ -355,7 +358,7 @@ void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const Int
     CGContextSetShadowWithColor(destContext, CGSizeZero, 0, 0);
 
     // Draw the image in CG coordinate space
-    IntPoint destPointInCGCoords(destPoint.x() + sourceRect.x(), logicalSize().height() - (destPoint.y()+sourceRect.y()) - sourceRect.height());
+    IntPoint destPointInCGCoords(destPoint.x() + sourceRect.x(), (coordinateSystem == LogicalCoordinateSystem ? logicalSize() : internalSize()).height() - (destPoint.y() + sourceRect.y()) - sourceRect.height());
     IntRect destRectInCGCoords(destPointInCGCoords, sourceCopySize);
     RetainPtr<CGImageRef> sourceCopyImage(AdoptCF, sourceCopy->copyNativeImage());
     CGContextDrawImage(destContext, destRectInCGCoords, sourceCopyImage.get());
@@ -430,7 +433,7 @@ static String CGImageToDataURL(CGImageRef image, const String& mimeType, const d
     return "data:" + mimeType + ";base64," + out;
 }
 
-String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const
+String ImageBuffer::toDataURL(const String& mimeType, const double* quality, CoordinateSystem) const
 {
     ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
     RetainPtr<CGImageRef> image;
index a43baf8..d8a7783 100644 (file)
@@ -54,7 +54,7 @@ static bool encodeImage(cairo_surface_t* surface, const String& mimeType, const
     return !error;
 }
 
-String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const
+String ImageBuffer::toDataURL(const String& mimeType, const double* quality, CoordinateSystem) const
 {
     ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
 
index 78dd019..5242302 100644 (file)
@@ -271,12 +271,12 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const ImageBufferData& i
     return result.release();
 }
 
-PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
+PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect, CoordinateSystem) const
 {
     return getImageData<Unmultiplied>(rect, m_data, m_size);
 }
 
-PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect, CoordinateSystem) const
 {
     return getImageData<Premultiplied>(rect, m_data, m_size);
 }
@@ -297,7 +297,7 @@ static inline unsigned int premultiplyABGRtoARGB(unsigned int x)
     return x;
 }
 
-void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
+void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem)
 {
     ASSERT(sourceRect.width() > 0);
     ASSERT(sourceRect.height() > 0);
@@ -391,7 +391,7 @@ static bool encodeImage(const QPixmap& pixmap, const String& format, const doubl
     return success;
 }
 
-String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const
+String ImageBuffer::toDataURL(const String& mimeType, const double* quality, CoordinateSystem) const
 {
     ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
 
index 6e8919a..3644131 100644 (file)
@@ -262,17 +262,17 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, SkCanvas* canvas,
     return result.release();
 }
 
-PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
+PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect, CoordinateSystem) const
 {
     return getImageData<Unmultiplied>(rect, context()->platformContext()->canvas(), m_size);
 }
 
-PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect, CoordinateSystem) const
 {
     return getImageData<Premultiplied>(rect, context()->platformContext()->canvas(), m_size);
 }
 
-void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
+void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem)
 {
     SkCanvas* canvas = context()->platformContext()->canvas();
     ASSERT(sourceRect.width() > 0);
@@ -343,7 +343,7 @@ static bool encodeImage(T& source, const String& mimeType, const double* quality
     return true;
 }
 
-String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const
+String ImageBuffer::toDataURL(const String& mimeType, const double* quality, CoordinateSystem) const
 {
     ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
 
index 909591b..28c7209 100644 (file)
@@ -170,17 +170,17 @@ static PassRefPtr<ByteArray> getImageData(const IntRect& rect, const SharedBitma
     return imageData.release();
 }
 
-PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
+PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect, CoordinateSystem) const
 {
     return getImageData<false>(rect, m_data.m_bitmap.get());
 }
 
-PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect, CoordinateSystem) const
 {
     return getImageData<true>(rect, m_data.m_bitmap.get());
 }
 
-void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
+void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem)
 {
     SharedBitmap* bitmap = m_data.m_bitmap.get();
     unsigned char* dst = (unsigned char*)bitmap->bytes();
@@ -231,7 +231,7 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
     notImplemented();
 }
 
-String ImageBuffer::toDataURL(const String& mimeType, const double*) const
+String ImageBuffer::toDataURL(const String& mimeType, const double*, CoordinateSystem) const
 {
     if (!m_data.m_bitmap->bytes())
         return "data:,";
index b3a7869..6b8e2d3 100644 (file)
@@ -122,24 +122,24 @@ GraphicsContext* ImageBuffer::context() const
     return m_context.get();
 }
 
-PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
+PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect, CoordinateSystem) const
 {
     notImplemented();
     return 0;
 }
 
-PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
+PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect, CoordinateSystem) const
 {
     notImplemented();
     return 0;
 }
 
-void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
+void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem)
 {
     notImplemented();
 }
     
-String ImageBuffer::toDataURL(const String& mimeType, const double*) const
+String ImageBuffer::toDataURL(const String& mimeType, const double*, CoordinateSystem) const
 {
     notImplemented();
     return String();