toDataURL() uses stale data after putImageData()
authormdelaney@apple.com <mdelaney@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 6 Feb 2012 20:54:13 +0000 (20:54 +0000)
committermdelaney@apple.com <mdelaney@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 6 Feb 2012 20:54:13 +0000 (20:54 +0000)
https://bugs.webkit.org/show_bug.cgi?id=65767

Source/WebCore:

This patch fixes the issue we've encountered of getting back
stale copies of the CGContext of accelerated ImageBuffers who have seen
putImageData calls but have not been drawn into via the CG API.
This issue is fixed by modifying the way we implement putImageData
in ImageBufferCG to draw the bits wrapped in a CGImage while the CGContext
is in a state where the data will effectively be copied (as is needed for
implementing putImageData) instead of directly modifying the bits of the IOSurface.

Reviewed by Chris Marrin.

Test: fast/canvas/check-stale-putImageData, pixel test to check that the canvas is in fact painted.

* platform/graphics/cg/ImageBufferCG.cpp: Implement new way of putting image data.
* platform/graphics/ImageBuffer.h: Merged two previously separate put data calls
    into a single and more sensibly named 'putByteArray', since that's what it does!

* WebCore.exp.in: Added new WKSI call for use in ImageBufferCG.cpp
* platform/mac/WebCoreSystemInterface.h:
* platform/mac/WebCoreSystemInterface.mm:

Using new method name.
* html/canvas/CanvasRenderingContext2D.cpp:
* platform/graphics/ImageBuffer.cpp:
* platform/graphics/ShadowBlur.cpp:
* platform/graphics/filters/FEColorMatrix.cpp:
* platform/graphics/filters/FEDropShadow.cpp:
* platform/graphics/filters/FilterEffect.cpp:

Updated other ports' ImageBuffers to use new method.
* platform/graphics/cairo/ImageBufferCairo.cpp:
* platform/graphics/qt/ImageBufferQt.cpp:
* platform/graphics/skia/ImageBufferSkia.cpp:
* platform/graphics/wince/ImageBufferWinCE.cpp:
* platform/graphics/wx/ImageBufferWx.cpp:

Source/WebKit/chromium:

Reviewed by Chris Marrin.

* src/WebViewImpl.cpp: Updated method name.
(WebKit::WebViewImpl::doPixelReadbackToCanvas):

Source/WebKit/mac:

Reviewed by Chris Marrin.

* WebCoreSupport/WebSystemInterface.mm:

Source/WebKit2:

Reviewed by Chris Marrin.

* WebProcess/WebCoreSupport/mac/WebSystemInterface.mm:
(InitWebCoreSystemInterface):

WebKitLibraries:

Added WKCGContextResetClip for use in reseting clip for new putByteArray method.

Reviewed by Chris Marrin.

* WebKitSystemInterface.h: Added WKCGContextResetClip.
* libWebKitSystemInterfaceLeopard.a:
* libWebKitSystemInterfaceSnowLeopard.a:
* libWebKitSystemInterfaceLion.a:

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

31 files changed:
LayoutTests/fast/canvas/check-stale-putImageData-expected.png [new file with mode: 0644]
LayoutTests/fast/canvas/check-stale-putImageData-expected.txt [new file with mode: 0644]
LayoutTests/fast/canvas/check-stale-putImageData.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
Source/WebCore/platform/graphics/ImageBuffer.cpp
Source/WebCore/platform/graphics/ImageBuffer.h
Source/WebCore/platform/graphics/ShadowBlur.cpp
Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
Source/WebCore/platform/graphics/cg/ImageBufferCG.cpp
Source/WebCore/platform/graphics/filters/FEColorMatrix.cpp
Source/WebCore/platform/graphics/filters/FEDropShadow.cpp
Source/WebCore/platform/graphics/filters/FilterEffect.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
Source/WebCore/platform/mac/WebCoreSystemInterface.h
Source/WebCore/platform/mac/WebCoreSystemInterface.mm
Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/src/WebViewImpl.cpp
Source/WebKit/mac/ChangeLog
Source/WebKit/mac/WebCoreSupport/WebSystemInterface.mm
Source/WebKit2/ChangeLog
Source/WebKit2/WebProcess/WebCoreSupport/mac/WebSystemInterface.mm
WebKitLibraries/ChangeLog
WebKitLibraries/WebKitSystemInterface.h
WebKitLibraries/libWebKitSystemInterfaceLeopard.a
WebKitLibraries/libWebKitSystemInterfaceLion.a
WebKitLibraries/libWebKitSystemInterfaceSnowLeopard.a

diff --git a/LayoutTests/fast/canvas/check-stale-putImageData-expected.png b/LayoutTests/fast/canvas/check-stale-putImageData-expected.png
new file mode 100644 (file)
index 0000000..00d28ec
Binary files /dev/null and b/LayoutTests/fast/canvas/check-stale-putImageData-expected.png differ
diff --git a/LayoutTests/fast/canvas/check-stale-putImageData-expected.txt b/LayoutTests/fast/canvas/check-stale-putImageData-expected.txt
new file mode 100644 (file)
index 0000000..2f8815f
--- /dev/null
@@ -0,0 +1,6 @@
+CONSOLE MESSAGE: line 28: a == b? false
+CONSOLE MESSAGE: line 35: a == c? false
+1, 3, and 4 should all show the same red square. 2 should show nothing.
+
+
+
diff --git a/LayoutTests/fast/canvas/check-stale-putImageData.html b/LayoutTests/fast/canvas/check-stale-putImageData.html
new file mode 100644 (file)
index 0000000..d7790fe
--- /dev/null
@@ -0,0 +1,42 @@
+<html><head></head><body>
+    1, 3, and 4 should all show the same red square. 2 should show nothing.
+<ol>
+<li><canvas id="canvas" width="100" height="100"></canvas></li>
+<li><img src="" id="a"></li>
+<li><img src="" id="b"></li>
+<li><img src="" id="c"></li>
+</ol>
+
+<script type="text/javascript">
+
+if (window.layoutTestController)
+  layoutTestController.dumpAsText(true);
+
+var canvas = document.getElementById( 'canvas' );
+var context = canvas.getContext( '2d' );
+var img = context.getImageData( 0, 0, canvas.width, canvas.height );
+
+var img_a = canvas.toDataURL( 'image/png' );
+
+/* fill with red */
+for ( var i = 0; i < img.data.length; i += 4 )
+       img.data[i] = img.data[i+3] = 255;
+
+context.putImageData( img, 0, 0 );
+var img_b = canvas.toDataURL( 'image/png' );
+
+console.log( 'a == b? ' + (img_a == img_b) );
+
+context.moveTo( 0, 0 ); 
+context.lineTo( 0, 0 );
+context.stroke();
+
+var img_c = canvas.toDataURL( 'image/png' );
+console.log( 'a == c? ' + (img_a == img_c) );
+
+document.getElementById( 'a' ).src = img_a;
+document.getElementById( 'b' ).src = img_b;
+document.getElementById( 'c' ).src = img_c;
+</script>
+
+</body></html>
index e271a549eb974f4d738d2a9880936667c9fc2aab..30d1de9cc7b905b461aa821a0b387e9ebd9e3e65 100644 (file)
@@ -1,3 +1,43 @@
+2012-02-06  Matthew Delaney  <mdelaney@apple.com>
+
+        toDataURL() uses stale data after putImageData()
+        https://bugs.webkit.org/show_bug.cgi?id=65767
+
+        This patch fixes the issue we've encountered of getting back
+        stale copies of the CGContext of accelerated ImageBuffers who have seen
+        putImageData calls but have not been drawn into via the CG API.
+        This issue is fixed by modifying the way we implement putImageData
+        in ImageBufferCG to draw the bits wrapped in a CGImage while the CGContext
+        is in a state where the data will effectively be copied (as is needed for
+        implementing putImageData) instead of directly modifying the bits of the IOSurface.
+
+        Reviewed by Chris Marrin.
+
+        Test: fast/canvas/check-stale-putImageData, pixel test to check that the canvas is in fact painted.
+
+        * platform/graphics/cg/ImageBufferCG.cpp: Implement new way of putting image data.
+        * platform/graphics/ImageBuffer.h: Merged two previously separate put data calls
+            into a single and more sensibly named 'putByteArray', since that's what it does!
+
+        * WebCore.exp.in: Added new WKSI call for use in ImageBufferCG.cpp
+        * platform/mac/WebCoreSystemInterface.h:
+        * platform/mac/WebCoreSystemInterface.mm:
+
+        Using new method name.
+        * html/canvas/CanvasRenderingContext2D.cpp:
+        * platform/graphics/ImageBuffer.cpp:
+        * platform/graphics/ShadowBlur.cpp:        
+        * platform/graphics/filters/FEColorMatrix.cpp:
+        * platform/graphics/filters/FEDropShadow.cpp:
+        * platform/graphics/filters/FilterEffect.cpp:
+
+        Updated other ports' ImageBuffers to use new method.
+        * platform/graphics/cairo/ImageBufferCairo.cpp:
+        * platform/graphics/qt/ImageBufferQt.cpp:
+        * platform/graphics/skia/ImageBufferSkia.cpp:
+        * platform/graphics/wince/ImageBufferWinCE.cpp:
+        * platform/graphics/wx/ImageBufferWx.cpp:
+
 2012-02-06  Caio Marcelo de Oliveira Filho  <caio.oliveira@openbossa.org>
 
         Provide more attribute methods in Element
index b6f000916d9f68c9c00c8de5bbf563e5bf53feff..079bfe9f21cfe9405b969c7931c1c3ecb7bc8b50 100644 (file)
@@ -1487,6 +1487,7 @@ _stringIsCaseInsensitiveEqualToString
 _suggestedFilenameWithMIMEType
 _wkAdvanceDefaultButtonPulseAnimation
 _wkCGContextGetShouldSmoothFonts
+_wkCGContextResetClip
 _wkCGPatternCreateWithImageAndTransform
 _wkCopyCFLocalizationPreferredName
 _wkCopyCFURLResponseSuggestedFilename
index 020a52785380ffa59fa3b08b0da6dea30229f0c4..6a2b71da7bf694c4002a17efcaadec9fd9982d74 100644 (file)
@@ -1971,7 +1971,7 @@ void CanvasRenderingContext2D::putImageData(ImageData* data, float dx, float dy,
     IntRect sourceRect(destRect);
     sourceRect.move(-destOffset);
 
-    buffer->putUnmultipliedImageData(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));
     didDraw(destRect, CanvasDidDrawApplyNone); // ignore transform, shadow and clip
 }
 
index 176de72102b0b78bc383759b5f2ae04231f3e622..5391c381564829c1a7dd7cc955f57d78ab3f8bb1 100644 (file)
@@ -86,7 +86,7 @@ inline void ImageBuffer::genericConvertToLuminanceMask()
         double luma = (r * 0.2125 + g * 0.7154 + b * 0.0721) * ((double)a / 255.0);
         srcPixelArray->set(pixelOffset + 3, luma);
     }
-    putUnmultipliedImageData(srcPixelArray.get(), luminanceRect.size(), luminanceRect, IntPoint());
+    putByteArray(Unmultiplied, srcPixelArray.get(), luminanceRect.size(), luminanceRect, IntPoint());
 }
 
 void ImageBuffer::convertToLuminanceMask()
index ebc5bfa52d82e275bfd0e815e44403b7304ee63b..f97dc793920750cc757091f11dad51e29c4ce792 100644 (file)
@@ -101,8 +101,7 @@ namespace WebCore {
         PassRefPtr<ByteArray> getUnmultipliedImageData(const IntRect&) const;
         PassRefPtr<ByteArray> getPremultipliedImageData(const IntRect&) const;
 
-        void putUnmultipliedImageData(ByteArray*, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint);
-        void putPremultipliedImageData(ByteArray*, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint);
+        void putByteArray(Multiply multiplied, ByteArray*, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint);
         
         void convertToLuminanceMask();
         
index 72fdffb4eb26dcfdaabe2a49a1ca68d985e3ba17..b002312159c2e9129efcc46db979432e1cf10ca2 100644 (file)
@@ -828,7 +828,7 @@ void ShadowBlur::blurShadowBuffer(const IntSize& templateSize)
     IntRect blurRect(IntPoint(), templateSize);
     RefPtr<ByteArray> layerData = m_layerImage->getUnmultipliedImageData(blurRect);
     blurLayerImage(layerData->data(), blurRect.size(), blurRect.width() * 4);
-    m_layerImage->putUnmultipliedImageData(layerData.get(), blurRect.size(), blurRect, IntPoint());
+    m_layerImage->putByteArray(Unmultiplied, layerData.get(), blurRect.size(), blurRect, IntPoint());
 }
 
 void ShadowBlur::blurAndColorShadowBuffer(const IntSize& templateSize)
index f4d2ea22ca47a808782f07cc95c0fdce68402c3a..7ae5024a69091496b0cf6310529345d954f46177 100644 (file)
@@ -204,12 +204,11 @@ PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect
     return getImageData<Premultiplied>(rect, m_data, m_size);
 }
 
-template <Multiply multiplied>
-void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, ImageBufferData& data, const IntSize& size)
+void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
 {
-    ASSERT(cairo_surface_get_type(data.m_surface) == CAIRO_SURFACE_TYPE_IMAGE);
+    ASSERT(cairo_surface_get_type(m_data.m_surface) == CAIRO_SURFACE_TYPE_IMAGE);
 
-    unsigned char* dataDst = cairo_image_surface_get_data(data.m_surface);
+    unsigned char* dataDst = cairo_image_surface_get_data(m_data.m_surface);
 
     ASSERT(sourceRect.width() > 0);
     ASSERT(sourceRect.height() > 0);
@@ -217,28 +216,28 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect&
     int originx = sourceRect.x();
     int destx = destPoint.x() + sourceRect.x();
     ASSERT(destx >= 0);
-    ASSERT(destx < size.width());
+    ASSERT(destx < m_size.width());
     ASSERT(originx >= 0);
     ASSERT(originx <= sourceRect.maxX());
 
     int endx = destPoint.x() + sourceRect.maxX();
-    ASSERT(endx <= size.width());
+    ASSERT(endx <= m_size.width());
 
     int numColumns = endx - destx;
 
     int originy = sourceRect.y();
     int desty = destPoint.y() + sourceRect.y();
     ASSERT(desty >= 0);
-    ASSERT(desty < size.height());
+    ASSERT(desty < m_size.height());
     ASSERT(originy >= 0);
     ASSERT(originy <= sourceRect.maxY());
 
     int endy = destPoint.y() + sourceRect.maxY();
-    ASSERT(endy <= size.height());
+    ASSERT(endy <= m_size.height());
     int numRows = endy - desty;
 
     unsigned srcBytesPerRow = 4 * sourceSize.width();
-    int stride = cairo_image_surface_get_stride(data.m_surface);
+    int stride = cairo_image_surface_get_stride(m_data.m_surface);
 
     unsigned char* srcRows = source->data() + originy * srcBytesPerRow + originx * 4;
     for (int y = 0; y < numRows; ++y) {
@@ -257,21 +256,11 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect&
         }
         srcRows += srcBytesPerRow;
     }
-    cairo_surface_mark_dirty_rectangle (data.m_surface,
+    cairo_surface_mark_dirty_rectangle(m_data.m_surface,
                                         destx, desty,
                                         numColumns, numRows);
 }
 
-void ImageBuffer::putUnmultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
-{
-    putImageData<Unmultiplied>(source, sourceSize, sourceRect, destPoint, m_data, m_size);
-}
-
-void ImageBuffer::putPremultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
-{
-    putImageData<Premultiplied>(source, sourceSize, sourceRect, destPoint, m_data, m_size);
-}
-
 #if !PLATFORM(GTK)
 static cairo_status_t writeFunction(void* closure, const unsigned char* data, unsigned int length)
 {
index 02ba8cffd245102122ac0a84cc21ddc2e64f1537..72fcd1e51b5fae58db30fd5b59c94ef7ee621772 100644 (file)
@@ -307,26 +307,36 @@ PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect
     return m_data.getData(rect, m_size, m_context->isAcceleratedContext(), false);
 }
 
-void ImageBuffer::putUnmultipliedImageData(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)
 {
-    if (m_context->isAcceleratedContext()) {
-        CGContextFlush(context()->platformContext());
-#if defined(BUILDING_ON_LION)
-        m_data.m_lastFlushTime = currentTimeMS();
-#endif
+    if (!m_context->isAcceleratedContext()) {
+        m_data.putData(source, sourceSize, sourceRect, destPoint, m_size, m_context->isAcceleratedContext(), multiplied == Unmultiplied);
+        return;
     }
-    m_data.putData(source, sourceSize, sourceRect, destPoint, m_size, m_context->isAcceleratedContext(), true);
-}
 
-void ImageBuffer::putPremultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
-{
-    if (m_context->isAcceleratedContext()) {
-        CGContextFlush(context()->platformContext());
-#if defined(BUILDING_ON_LION)
-        m_data.m_lastFlushTime = currentTimeMS();
-#endif
-    }
-    m_data.putData(source, sourceSize, sourceRect, destPoint, m_size, m_context->isAcceleratedContext(), false);
+    // Make a copy of the source to ensure the bits don't change before being drawn
+    IntSize sourceCopySize(sourceRect.width(), sourceRect.height());
+    OwnPtr<ImageBuffer> sourceCopy = ImageBuffer::create(sourceCopySize, ColorSpaceDeviceRGB, Unaccelerated);
+    if (!sourceCopy)
+        return;
+    sourceCopy->m_data.putData(source, sourceSize, sourceRect, IntPoint(-sourceRect.x(), -sourceRect.y()), sourceCopy->size(), sourceCopy->context()->isAcceleratedContext(), multiplied == Unmultiplied);
+
+    // Set up context for using drawImage as a direct bit copy
+    CGContextRef destContext = context()->platformContext();
+    CGContextSaveGState(destContext);
+    CGContextConcatCTM(destContext, AffineTransform(CGContextGetCTM(destContext)).inverse());
+    wkCGContextResetClip(destContext);
+    CGContextSetInterpolationQuality(destContext, kCGInterpolationNone);
+    CGContextSetAlpha(destContext, 1.0);
+    CGContextSetBlendMode(destContext, kCGBlendModeCopy);
+    CGContextSetShadowWithColor(destContext, CGSizeZero, 0, 0);
+
+    // Draw the image in CG coordinate space
+    IntPoint destPointInCGCoords(destPoint.x() + sourceRect.x(), m_size.height() - (destPoint.y()+sourceRect.y()) - sourceRect.height());
+    IntRect destRectInCGCoords(destPointInCGCoords, sourceCopySize);
+    RetainPtr<CGImageRef> sourceCopyImage(AdoptCF, sourceCopy->copyNativeImage());
+    CGContextDrawImage(destContext, destRectInCGCoords, sourceCopyImage.get());
+    CGContextRestoreGState(destContext);
 }
 
 static inline CFStringRef jpegUTI()
index ed6cb90dc46a9e4e0e85cfba45aa9658239f0115..00b600abdaa98c5556f8c5fd5b8c8d546615660d 100644 (file)
@@ -187,7 +187,7 @@ void FEColorMatrix::platformApplySoftware()
         break;
     }
 
-    resultImage->putUnmultipliedImageData(pixelArray.get(), imageRect.size(), imageRect, IntPoint());
+    resultImage->putByteArray(Unmultiplied, pixelArray.get(), imageRect.size(), imageRect, IntPoint());
 }
 
 void FEColorMatrix::dump()
index 5d807785b7a96b4572e246f3cb83609f49bf8d58..5944feca5954630c723836ee264d28add17fae49 100644 (file)
@@ -108,7 +108,7 @@ void FEDropShadow::platformApplySoftware()
 
     contextShadow.blurLayerImage(srcPixelArray->data(), shadowArea.size(), 4 * shadowArea.size().width());
 
-    resultImage->putPremultipliedImageData(srcPixelArray.get(), shadowArea.size(), shadowArea, IntPoint());
+    resultImage->putByteArray(Premultiplied, srcPixelArray.get(), shadowArea.size(), shadowArea, IntPoint());
 
     resultContext->setCompositeOperation(CompositeSourceIn);
     resultContext->fillRect(FloatRect(FloatPoint(), absolutePaintRect().size()), m_shadowColor, ColorSpaceDeviceRGB);
index fbeb4bbcb04fdc6de28e8e6c08ddab174bd867f4..f972c98a4cf57621aa838095158687a2ff0107f8 100644 (file)
@@ -130,9 +130,9 @@ ImageBuffer* FilterEffect::asImageBuffer()
     m_imageBufferResult = ImageBuffer::create(m_absolutePaintRect.size(), ColorSpaceLinearRGB, m_filter->renderingMode());
     IntRect destinationRect(IntPoint(), m_absolutePaintRect.size());
     if (m_premultipliedImageResult)
-        m_imageBufferResult->putPremultipliedImageData(m_premultipliedImageResult.get(), destinationRect.size(), destinationRect, IntPoint());
+        m_imageBufferResult->putByteArray(Premultiplied, m_premultipliedImageResult.get(), destinationRect.size(), destinationRect, IntPoint());
     else
-        m_imageBufferResult->putUnmultipliedImageData(m_unmultipliedImageResult.get(), destinationRect.size(), destinationRect, IntPoint());
+        m_imageBufferResult->putByteArray(Unmultiplied, m_unmultipliedImageResult.get(), destinationRect.size(), destinationRect, IntPoint());
     return m_imageBufferResult.get();
 }
 
index eabcef6fb9167cf647cbceeb99cf4479993ccc97..15f89b7aea8e28370d5b6e0feaef07de3d74327e 100644 (file)
@@ -301,8 +301,7 @@ static inline unsigned int premultiplyABGRtoARGB(unsigned int x)
     return x;
 }
 
-template <Multiply multiplied>
-void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, ImageBufferData& data, const IntSize& size)
+void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
 {
     ASSERT(sourceRect.width() > 0);
     ASSERT(sourceRect.height() > 0);
@@ -310,24 +309,24 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect&
     int originx = sourceRect.x();
     int destx = destPoint.x() + sourceRect.x();
     ASSERT(destx >= 0);
-    ASSERT(destx < size.width());
+    ASSERT(destx < m_size.width());
     ASSERT(originx >= 0);
     ASSERT(originx <= sourceRect.maxX());
 
     int endx = destPoint.x() + sourceRect.maxX();
-    ASSERT(endx <= size.width());
+    ASSERT(endx <= m_size.width());
 
     int numColumns = endx - destx;
 
     int originy = sourceRect.y();
     int desty = destPoint.y() + sourceRect.y();
     ASSERT(desty >= 0);
-    ASSERT(desty < size.height());
+    ASSERT(desty < m_size.height());
     ASSERT(originy >= 0);
     ASSERT(originy <= sourceRect.maxY());
 
     int endy = destPoint.y() + sourceRect.maxY();
-    ASSERT(endy <= size.height());
+    ASSERT(endy <= m_size.height());
     int numRows = endy - desty;
 
     unsigned srcBytesPerRow = 4 * sourceSize.width();
@@ -361,35 +360,25 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect&
         }
     }
 
-    bool isPainting = data.m_painter->isActive();
+    bool isPainting = m_data.m_painter->isActive();
     if (!isPainting)
-        data.m_painter->begin(&data.m_pixmap);
+        m_data.m_painter->begin(&m_data.m_pixmap);
     else {
-        data.m_painter->save();
+        m_data.m_painter->save();
 
         // putImageData() should be unaffected by painter state
-        data.m_painter->resetTransform();
-        data.m_painter->setOpacity(1.0);
-        data.m_painter->setClipping(false);
+        m_data.m_painter->resetTransform();
+        m_data.m_painter->setOpacity(1.0);
+        m_data.m_painter->setClipping(false);
     }
 
-    data.m_painter->setCompositionMode(QPainter::CompositionMode_Source);
-    data.m_painter->drawImage(destx, desty, image);
+    m_data.m_painter->setCompositionMode(QPainter::CompositionMode_Source);
+    m_data.m_painter->drawImage(destx, desty, image);
 
     if (!isPainting)
-        data.m_painter->end();
+        m_data.m_painter->end();
     else
-        data.m_painter->restore();
-}
-
-void ImageBuffer::putUnmultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
-{
-    putImageData<Unmultiplied>(source, sourceSize, sourceRect, destPoint, m_data, m_size);
-}
-
-void ImageBuffer::putPremultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
-{
-    putImageData<Premultiplied>(source, sourceSize, sourceRect, destPoint, m_data, m_size);
+        m_data.m_painter->restore();
 }
 
 // We get a mimeType here but QImageWriter does not support mimetypes but
index 88771f607c6a2fbedcb67944b13e8481560ca93f..e0b52a318f9a8698df1079e6728fe9cae54af24c 100644 (file)
@@ -275,34 +275,33 @@ PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect
     return getImageData<Premultiplied>(rect, context()->platformContext()->canvas(), m_size);
 }
 
-template <Multiply multiplied>
-void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint,
-                  SkCanvas* canvas, const IntSize& size)
+void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
 {
+    SkCanvas* canvas = context()->platformContext()->canvas();
     ASSERT(sourceRect.width() > 0);
     ASSERT(sourceRect.height() > 0);
 
     int originX = sourceRect.x();
     int destX = destPoint.x() + sourceRect.x();
     ASSERT(destX >= 0);
-    ASSERT(destX < size.width());
+    ASSERT(destX < m_size.width());
     ASSERT(originX >= 0);
     ASSERT(originX < sourceRect.maxX());
 
     int endX = destPoint.x() + sourceRect.maxX();
-    ASSERT(endX <= size.width());
+    ASSERT(endX <= m_size.width());
 
     int numColumns = endX - destX;
 
     int originY = sourceRect.y();
     int destY = destPoint.y() + sourceRect.y();
     ASSERT(destY >= 0);
-    ASSERT(destY < size.height());
+    ASSERT(destY < m_size.height());
     ASSERT(originY >= 0);
     ASSERT(originY < sourceRect.maxY());
 
     int endY = destPoint.y() + sourceRect.maxY();
-    ASSERT(endY <= size.height());
+    ASSERT(endY <= m_size.height());
     int numRows = endY - destY;
 
     unsigned srcBytesPerRow = 4 * sourceSize.width();
@@ -319,16 +318,6 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect&
     canvas->writePixels(srcBitmap, destX, destY, config8888);
 }
 
-void ImageBuffer::putUnmultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
-{
-    putImageData<Unmultiplied>(source, sourceSize, sourceRect, destPoint, context()->platformContext()->canvas(), m_size);
-}
-
-void ImageBuffer::putPremultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
-{
-    putImageData<Premultiplied>(source, sourceSize, sourceRect, destPoint, context()->platformContext()->canvas(), m_size);
-}
-
 template <typename T>
 static bool encodeImage(T& source, const String& mimeType, const double* quality, Vector<char>* output)
 {
index 39ef15503e4dd6bbf982ec9bca7d93afbd1becc3..0d4e0ba609636bc655bf8d80f975bed6548922df 100644 (file)
@@ -183,9 +183,9 @@ PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect
     return getImageData<true>(rect, m_data.m_bitmap.get());
 }
 
-template <bool premultiplied>
-static void putImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, SharedBitmap* bitmap)
+void ImageBuffer::putByteArray(Multiply multiplied, ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
 {
+    SharedBitmap* bitmap = m_data.m_bitmap.get();
     unsigned char* dst = (unsigned char*)bitmap->bytes();
     if (!dst)
         return;
@@ -211,7 +211,7 @@ static void putImageData(ByteArray* source, const IntSize& sourceSize, const Int
             int green = *src++;
             int blue = *src++;
             int alpha = *src++;
-            if (premultiplied) {
+            if (multiplied == Premultiplied) {
                 *dst++ = static_cast<unsigned char>(blue * 255 / alpha);
                 *dst++ = static_cast<unsigned char>(green * 255 / alpha);
                 *dst++ = static_cast<unsigned char>(red * 255 / alpha);
@@ -228,16 +228,6 @@ static void putImageData(ByteArray* source, const IntSize& sourceSize, const Int
     }
 }
 
-void ImageBuffer::putUnmultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
-{
-    putImageData<false>(source, sourceSize, sourceRect, destPoint, m_data.m_bitmap.get());
-}
-
-void ImageBuffer::putPremultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
-{
-    putImageData<true>(source, sourceSize, sourceRect, destPoint, m_data.m_bitmap.get());
-}
-
 void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
 {
     UNUSED_PARAM(lookUpTable);
index 7c909b54dba06c16ad2c85895bcff56f3ceaff70..2dbb1961db382997c1391e7766d9507ee70ef39c 100644 (file)
@@ -72,12 +72,7 @@ PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect
     return 0;
 }
 
-void ImageBuffer::putUnmultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
-{
-    notImplemented();
-}
-
-void ImageBuffer::putPremultipliedImageData(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)
 {
     notImplemented();
 }
index 21eb94a18e30e9cc43a45928d5070a15e9a3fd1e..15753c89dd6cd79123a59274848c2541a9da1376 100644 (file)
@@ -113,6 +113,7 @@ typedef enum {
     wkPatternTilingConstantSpacing
 } wkPatternTiling;
 extern CGPatternRef (*wkCGPatternCreateWithImageAndTransform)(CGImageRef, CGAffineTransform, int);
+extern void (*wkCGContextResetClip)(CGContextRef);
 extern CFReadStreamRef (*wkCreateCustomCFReadStream)(void *(*formCreate)(CFReadStreamRef, void *), 
     void (*formFinalize)(CFReadStreamRef, void *), 
     Boolean (*formOpen)(CFReadStreamRef, CFStreamError *, Boolean *, void *), 
index f01747d5f3d22499c090cfa3d83c0e7329cb83b4..50055a5d838270dedb9be382cf74feb674c3b169 100644 (file)
@@ -132,6 +132,7 @@ CTLineRef (*wkCreateCTLineWithUniCharProvider)(const UniChar* (*provide)(CFIndex
 #if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
 CTTypesetterRef (*wkCreateCTTypesetterWithUniCharProviderAndOptions)(const UniChar* (*provide)(CFIndex stringIndex, CFIndex* charCount, CFDictionaryRef* attributes, void*), void (*dispose)(const UniChar* chars, void*), void*, CFDictionaryRef options);
 
+void (*wkCGContextResetClip)(CGContextRef);
 CGContextRef (*wkIOSurfaceContextCreate)(IOSurfaceRef surface, unsigned width, unsigned height, CGColorSpaceRef colorSpace);
 CGImageRef (*wkIOSurfaceContextCreateImage)(CGContextRef context);
 
index e96f2ed1e056ed23b904de5f10a842094ad2c63b..bcd17d1a86a5402a32a83af460fa352eba4535fa 100644 (file)
@@ -1,3 +1,13 @@
+2012-02-06  Matthew Delaney  <mdelaney@apple.com>
+
+        toDataURL() uses stale data after putImageData()
+        https://bugs.webkit.org/show_bug.cgi?id=65767
+
+        Reviewed by Chris Marrin.
+
+        * src/WebViewImpl.cpp: Updated method name.
+        (WebKit::WebViewImpl::doPixelReadbackToCanvas):
+
 2012-02-06  Caio Marcelo de Oliveira Filho  <caio.oliveira@openbossa.org>
 
         Provide more attribute methods in Element
index 84de7729cce5ad936b5066d741d71ffcee510886..4629cbb32abe5b4324e56a097fe37d685755ea04 100644 (file)
@@ -1206,7 +1206,7 @@ void WebViewImpl::doPixelReadbackToCanvas(WebCanvas* canvas, const IntRect& rect
     RefPtr<ByteArray> pixelArray(ByteArray::create(rect.width() * rect.height() * 4));
     if (imageBuffer && pixelArray) {
         m_layerTreeHost->compositeAndReadback(pixelArray->data(), invertRect);
-        imageBuffer->putPremultipliedImageData(pixelArray.get(), rect.size(), IntRect(IntPoint(), rect.size()), IntPoint());
+        imageBuffer->putByteArray(Premultiplied, pixelArray.get(), rect.size(), IntRect(IntPoint(), rect.size()), IntPoint());
         gc.save();
         gc.translate(IntSize(0, bitmapHeight));
         gc.scale(FloatSize(1.0f, -1.0f));
index 58fd9fe3b1eb53fdde411694fb23991306a98620..f5a6828bc5604de470811bce1013bf2431354a94 100644 (file)
@@ -1,3 +1,12 @@
+2012-02-06  Matthew Delaney  <mdelaney@apple.com>
+
+        toDataURL() uses stale data after putImageData()
+        https://bugs.webkit.org/show_bug.cgi?id=65767
+
+        Reviewed by Chris Marrin.
+
+        * WebCoreSupport/WebSystemInterface.mm: 
+
 2012-02-03  Antti Koivisto  <antti@apple.com>
 
         Rename CSSMutableStyleDeclaration.h/.cpp to StylePropertySet.h/.cpp 
index 5c3cdb3ee3da3ecbf23801902f48921285e0a143..2a76c98a9eeb21730f4bbf90d6ac2a4fb750fc78 100644 (file)
@@ -45,6 +45,7 @@ void InitWebCoreSystemInterface(void)
     INIT(AdvanceDefaultButtonPulseAnimation);
     INIT(CGContextGetShouldSmoothFonts);
     INIT(CGPatternCreateWithImageAndTransform);
+    INIT(CGContextResetClip);
     INIT(CopyCFLocalizationPreferredName);
     INIT(CopyCONNECTProxyResponse);
     INIT(CopyNSURLResponseStatusLine);
index e7ef835ddb4b7c62c5631f955364bd0a6088d952..c6b93500c09a1f8d4c304643d7c711a71679a9b4 100644 (file)
@@ -1,3 +1,13 @@
+2012-02-06  Matthew Delaney  <mdelaney@apple.com>
+
+        toDataURL() uses stale data after putImageData()
+        https://bugs.webkit.org/show_bug.cgi?id=65767
+
+        Reviewed by Chris Marrin.
+
+        * WebProcess/WebCoreSupport/mac/WebSystemInterface.mm:
+        (InitWebCoreSystemInterface):
+
 2012-02-06  Ryosuke Niwa  <rniwa@webkit.org>
 
         gcc build fix after r106749.
index c40a68ab803d3efeac3a945227d8dec24d3e1821..8d36fab5f42494d7fb790674451e96c82a7787f1 100644 (file)
@@ -40,6 +40,7 @@ void InitWebCoreSystemInterface(void)
         INIT(CopyCFLocalizationPreferredName);
         INIT(CGContextGetShouldSmoothFonts);
         INIT(CGPatternCreateWithImageAndTransform);
+        INIT(CGContextResetClip);
         INIT(CopyCONNECTProxyResponse);
         INIT(CopyNSURLResponseStatusLine);
         INIT(CreateCTLineWithUniCharProvider);
index c68b76a7889eb74da707f3d5bfa292a018214113..82bf1b58d30e6f635552c8a8eae69b41a9813af7 100644 (file)
@@ -1,3 +1,17 @@
+2012-02-06  Matthew Delaney  <mdelaney@apple.com>
+
+        toDataURL() uses stale data after putImageData()
+        https://bugs.webkit.org/show_bug.cgi?id=65767
+
+        Added WKCGContextResetClip for use in reseting clip for new putByteArray method.
+
+        Reviewed by Chris Marrin.
+        
+        * WebKitSystemInterface.h: Added WKCGContextResetClip.
+        * libWebKitSystemInterfaceLeopard.a:
+        * libWebKitSystemInterfaceSnowLeopard.a:
+        * libWebKitSystemInterfaceLion.a:
+
 2012-02-02  Chris Marrin  <cmarrin@apple.com>
 
         Turn on CSS Filters on Windows
index e8fed684436114d001aabcace6ed2ace16a30705..d5c1c9e0ac778a5a87223abd207fee176cbc634f 100644 (file)
@@ -454,7 +454,11 @@ NSCursor *WKCursor(const char *name);
 dispatch_source_t WKCreateVMPressureDispatchOnMainQueue(void);
 
 #endif
-    
+
+#if !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION)
+NSString *WKGetMacOSXVersionString(void);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
index 8fabbd2486431645555ddac22b55209c09b0d492..4eba79cdf3d7a93890fe136d8a22b13ce985d48f 100644 (file)
Binary files a/WebKitLibraries/libWebKitSystemInterfaceLeopard.a and b/WebKitLibraries/libWebKitSystemInterfaceLeopard.a differ
index 714d05b64214b543dc33e2af4a9ac66278db20ae..627e0d6e72bbef01ae5bbf4a6ba87993180afa04 100644 (file)
Binary files a/WebKitLibraries/libWebKitSystemInterfaceLion.a and b/WebKitLibraries/libWebKitSystemInterfaceLion.a differ
index f2899712d720534bb498e2597b6235f59a44cb7c..6a41f92eb55e4ee4915a84a27832d3d1d084a3ca 100644 (file)
Binary files a/WebKitLibraries/libWebKitSystemInterfaceSnowLeopard.a and b/WebKitLibraries/libWebKitSystemInterfaceSnowLeopard.a differ