Title: [95346] trunk
Revision
95346
Author
commit-qu...@webkit.org
Date
2011-09-16 18:02:45 -0700 (Fri, 16 Sep 2011)

Log Message

Large canvas fills should not crash or create unnecessarily large image buffers
https://bugs.webkit.org/show_bug.cgi?id=67988

Source/WebCore:

When using source-in, destination-in, source-out, or destination-atop a temporary
buffer is created. This buffer only needs to be big enough to cover the intersection
of the path and the canvas. If the area of intersection between the fill and the
canvas is empty the canvas is completely cleared and a temporary buffer is not used.

This change also adds some null checks for failures to create contexts or buffers.

Patch by Ben Wells <benwe...@chromium.org> on 2011-09-16
Reviewed by Darin Adler.

Test: fast/canvas/canvas-large-fills.html

* html/canvas/CanvasRenderingContext2D.cpp:
(WebCore::CanvasRenderingContext2D::clearCanvas):
(WebCore::CanvasRenderingContext2D::fillAndDisplayTransparencyElsewhere):

LayoutTests:

Patch by Ben Wells <benwe...@chromium.org> on 2011-09-16
Reviewed by Darin Adler.

* fast/canvas/canvas-large-fills-expected.txt: Added.
* fast/canvas/canvas-large-fills.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (95345 => 95346)


--- trunk/LayoutTests/ChangeLog	2011-09-17 00:55:37 UTC (rev 95345)
+++ trunk/LayoutTests/ChangeLog	2011-09-17 01:02:45 UTC (rev 95346)
@@ -1,3 +1,13 @@
+2011-09-16  Ben Wells  <benwe...@chromium.org>
+
+        Large canvas fills should not crash or create unnecessarily large image buffers
+        https://bugs.webkit.org/show_bug.cgi?id=67988
+
+        Reviewed by Darin Adler.
+
+        * fast/canvas/canvas-large-fills-expected.txt: Added.
+        * fast/canvas/canvas-large-fills.html: Added.
+
 2011-09-16  Ryosuke Niwa  <rn...@webkit.org>
 
         Fix the rebaseline in r95325 and also rebaseline for r95335.

Added: trunk/LayoutTests/fast/canvas/canvas-large-fills-expected.txt (0 => 95346)


--- trunk/LayoutTests/fast/canvas/canvas-large-fills-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/canvas/canvas-large-fills-expected.txt	2011-09-17 01:02:45 UTC (rev 95346)
@@ -0,0 +1,35 @@
+Tests that using the different composite modes to fill large rects doesn't crash and works as expected.
+PASS Fill Size 10000, source-over: #0000FF
+PASS Fill Size 10000, source-in: #0000FF
+PASS Fill Size 10000, source-out: #000000
+PASS Fill Size 10000, source-atop: #0000FF
+PASS Fill Size 10000, destination-over: #00FF00
+PASS Fill Size 10000, destination-in: #00FF00
+PASS Fill Size 10000, destination-out: #000000
+PASS Fill Size 10000, destination-atop: #00FF00
+PASS Fill Size 10000, lighter: #00FFFF
+PASS Fill Size 10000, copy: #0000FF
+PASS Fill Size 10000, xor: #000000
+PASS Fill Size 50000, source-over: #0000FF
+PASS Fill Size 50000, source-in: #0000FF
+PASS Fill Size 50000, source-out: #000000
+PASS Fill Size 50000, source-atop: #0000FF
+PASS Fill Size 50000, destination-over: #00FF00
+PASS Fill Size 50000, destination-in: #00FF00
+PASS Fill Size 50000, destination-out: #000000
+PASS Fill Size 50000, destination-atop: #00FF00
+PASS Fill Size 50000, lighter: #00FFFF
+PASS Fill Size 50000, copy: #0000FF
+PASS Fill Size 50000, xor: #000000
+PASS Fill Size 100000, source-over: #0000FF
+PASS Fill Size 100000, source-in: #0000FF
+PASS Fill Size 100000, source-out: #000000
+PASS Fill Size 100000, source-atop: #0000FF
+PASS Fill Size 100000, destination-over: #00FF00
+PASS Fill Size 100000, destination-in: #00FF00
+PASS Fill Size 100000, destination-out: #000000
+PASS Fill Size 100000, destination-atop: #00FF00
+PASS Fill Size 100000, lighter: #00FFFF
+PASS Fill Size 100000, copy: #0000FF
+PASS Fill Size 100000, xor: #000000
+

Added: trunk/LayoutTests/fast/canvas/canvas-large-fills.html (0 => 95346)


--- trunk/LayoutTests/fast/canvas/canvas-large-fills.html	                        (rev 0)
+++ trunk/LayoutTests/fast/canvas/canvas-large-fills.html	2011-09-17 01:02:45 UTC (rev 95346)
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+
+<script src=""
+
+<pre id="console"></pre>
+<canvas id="c" class="output" width="100" height="50"><p class="fallback">FAIL (fallback content)</p></canvas>
+
+<script>
+var canvas = document.getElementById("c");
+var ctx = canvas.getContext("2d");
+
+function clearContextToGreen() {
+    ctx.globalCompositeOperation="source-over";
+    ctx.fillStyle = "rgb(0, 255, 0)";
+    ctx.fillRect(0, 0, canvas.width, canvas.height);
+}
+
+var testData = [
+    {compositeMode: 'source-over', expected: [0, 0, 255]},
+    {compositeMode: 'source-in', expected: [0, 0, 255]},
+    {compositeMode: 'source-out', expected: [0, 0, 0]},
+    {compositeMode: 'source-atop', expected: [0, 0, 255]},
+    {compositeMode: 'destination-over', expected: [0, 255, 0]},
+    {compositeMode: 'destination-in', expected: [0, 255, 0]},
+    {compositeMode: 'destination-out', expected: [0, 0, 0]},
+    {compositeMode: 'destination-atop', expected: [0, 255, 0]},
+    {compositeMode: 'lighter', expected: [0, 255, 255]},
+    {compositeMode: 'copy', expected: [0, 0, 255]},
+    {compositeMode: 'xor', expected: [0, 0, 0]},
+];
+
+function toHexString(number) {
+    var hexString = number.toString(16).toUpperCase();
+    if (number <= 9)
+        hexString = '0' + hexString;
+    return hexString;
+}
+
+function doTest(dataItem, fillSize) {
+    clearContextToGreen();
+    ctx.fillStyle = "rgb(0, 0, 255)";
+    ctx.globalCompositeOperation = dataItem.compositeMode;
+    ctx.fillRect(0, 0, fillSize, fillSize);
+
+    var data = "" 0, canvas.width, canvas.height);
+    var pixelOK = true;
+    var pixelString = '#';
+    var expectedString = '#';
+
+    for (var x = 0; x < 3; x++) {
+        pixelString = pixelString + toHexString(data.data[x]);
+        expectedString = expectedString + toHexString(dataItem.expected[x]);
+        if (data.data[x] != dataItem.expected[x])
+            pixelOK = false;
+    }
+
+    var testName = "Fill Size " + fillSize + ', ' + dataItem.compositeMode;
+    if (pixelOK)
+        testPassed(testName + ': ' + pixelString);
+    else
+        testFailed(testName + ': EXPECTED ' + expectedString + ', GOT ' + pixelString);
+}
+
+debug("Tests that using the different composite modes to fill large rects doesn't crash and works as expected.");
+[10000, 50000, 100000].forEach(function(fillSize) {
+    testData.forEach(function(dataItem) {
+        doTest(dataItem, fillSize)
+    })});
+
+</script>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (95345 => 95346)


--- trunk/Source/WebCore/ChangeLog	2011-09-17 00:55:37 UTC (rev 95345)
+++ trunk/Source/WebCore/ChangeLog	2011-09-17 01:02:45 UTC (rev 95346)
@@ -1,3 +1,23 @@
+2011-09-16  Ben Wells  <benwe...@chromium.org>
+
+        Large canvas fills should not crash or create unnecessarily large image buffers
+        https://bugs.webkit.org/show_bug.cgi?id=67988
+
+        When using source-in, destination-in, source-out, or destination-atop a temporary
+        buffer is created. This buffer only needs to be big enough to cover the intersection
+        of the path and the canvas. If the area of intersection between the fill and the
+        canvas is empty the canvas is completely cleared and a temporary buffer is not used.
+
+        This change also adds some null checks for failures to create contexts or buffers.
+
+        Reviewed by Darin Adler.
+
+        Test: fast/canvas/canvas-large-fills.html
+
+        * html/canvas/CanvasRenderingContext2D.cpp:
+        (WebCore::CanvasRenderingContext2D::clearCanvas):
+        (WebCore::CanvasRenderingContext2D::fillAndDisplayTransparencyElsewhere):
+
 2011-09-16  Shawn Singh  <shawnsi...@chromium.org>
 
         Remove default NULL argument in LayerChromium::create().

Modified: trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp (95345 => 95346)


--- trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp	2011-09-17 00:55:37 UTC (rev 95345)
+++ trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp	2011-09-17 01:02:45 UTC (rev 95346)
@@ -1468,6 +1468,8 @@
 {
     FloatRect canvasRect(0, 0, canvas()->width(), canvas()->height());
     GraphicsContext* c = drawingContext();
+    if (!c)
+        return;
 
     c->save();
     c->setCTM(canvas()->baseTransform());
@@ -1503,20 +1505,32 @@
 {
     ASSERT(shouldDisplayTransparencyElsewhere());
 
+    IntRect canvasRect(0, 0, canvas()->width(), canvas()->height());
+    canvasRect = canvas()->baseTransform().mapRect(canvasRect);
     Path path = transformAreaToDevice(area);
     IntRect bufferRect = enclosingIntRect(path.boundingRect());
+    bufferRect.intersect(canvasRect);
+
+    if (bufferRect.isEmpty()) {
+        clearCanvas();
+        return;
+    }
+
     path.translate(FloatSize(-bufferRect.x(), -bufferRect.y()));
 
     RenderingMode renderMode = isAccelerated() ? Accelerated : Unaccelerated;
     OwnPtr<ImageBuffer> buffer = ImageBuffer::create(bufferRect.size(), ColorSpaceDeviceRGB, renderMode);
+    if (!buffer)
+        return;
+
     buffer->context()->setCompositeOperation(CompositeSourceOver);
     state().m_fillStyle->applyFillColor(buffer->context());
     buffer->context()->fillPath(path);
 
-    FloatRect canvasRect(0, 0, canvas()->width(), canvas()->height());
-    canvasRect = canvas()->baseTransform().mapRect(canvasRect);
+    GraphicsContext* c = drawingContext();
+    if (!c)
+        return;
 
-    GraphicsContext* c = drawingContext();
     c->save();
     c->setCTM(AffineTransform());
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to