[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

hyatt at apple.com hyatt at apple.com
Wed Dec 22 12:10:44 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit ffec3a476965584382e6627af5520c23e28d073d
Author: hyatt at apple.com <hyatt at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Mon Aug 16 20:44:01 2010 +0000

    https://bugs.webkit.org/show_bug.cgi?id=43507, stop ImageBuffer from copying its data when rendering after canvas changes happen.
    
    Reviewed by Anders Carlsson.
    
    This patch renames ImageBuffer::image() to ImageBuffer::copyImage(). The new method always returns a new copy that is a current
    snapshot of the ImageBuffer.
    
    To draw an ImageBuffer, you now use new GraphicsContext calls: drawImageBuffer.  Platforms can then optimize these calls to draw
    efficiently without having to copy the bits of the ImageBuffer into an Image.
    
    * WebCore.xcodeproj/project.pbxproj:
    * css/CSSCanvasValue.cpp:
    (WebCore::CSSCanvasValue::image):
    * html/HTMLCanvasElement.cpp:
    (WebCore::HTMLCanvasElement::willDraw):
    (WebCore::HTMLCanvasElement::reset):
    (WebCore::HTMLCanvasElement::paint):
    (WebCore::HTMLCanvasElement::setSurfaceSize):
    (WebCore::HTMLCanvasElement::copiedImage):
    (WebCore::HTMLCanvasElement::clearCopiedImage):
    * html/HTMLCanvasElement.h:
    * html/canvas/CanvasPattern.cpp:
    (WebCore::CanvasPattern::CanvasPattern):
    * html/canvas/CanvasPattern.h:
    (WebCore::CanvasPattern::create):
    * html/canvas/CanvasRenderingContext2D.cpp:
    (WebCore::CanvasRenderingContext2D::drawImage):
    (WebCore::CanvasRenderingContext2D::createPattern):
    (WebCore::CanvasRenderingContext2D::drawTextInternal):
    * html/canvas/WebGLRenderingContext.cpp:
    (WebCore::WebGLRenderingContext::paintRenderingResultsToCanvas):
    (WebCore::WebGLRenderingContext::reshape):
    (WebCore::WebGLRenderingContext::texImage2D):
    (WebCore::WebGLRenderingContext::texSubImage2D):
    * html/canvas/WebGLRenderingContext.h:
    (WebCore::WebGLRenderingContext::paintsIntoCanvasBuffer):
    * platform/graphics/GeneratedImage.cpp:
    (WebCore::GeneratedImage::drawPattern):
    * platform/graphics/GraphicsContext.cpp:
    (WebCore::GraphicsContext::drawImageBuffer):
    (WebCore::GraphicsContext::clipToImageBuffer):
    * platform/graphics/GraphicsContext.h:
    * platform/graphics/GraphicsContext3D.h:
    (WebCore::GraphicsContext3D::paintsIntoCanvasBuffer):
    * platform/graphics/Image.h:
    * platform/graphics/ImageBuffer.h:
    (WebCore::ImageBuffer::width):
    (WebCore::ImageBuffer::height):
    * platform/graphics/Pattern.cpp:
    (WebCore::Pattern::Pattern):
    * platform/graphics/Pattern.h:
    (WebCore::Pattern::create):
    * platform/graphics/cairo/GraphicsContextCairo.cpp:
    * platform/graphics/cairo/ImageBufferCairo.cpp:
    (WebCore::ImageBuffer::drawsUsingCopy):
    (WebCore::ImageBuffer::copyImage):
    (WebCore::ImageBuffer::clip):
    (WebCore::ImageBuffer::draw):
    (WebCore::ImageBuffer::drawPattern):
    * platform/graphics/cg/GraphicsContextCG.cpp:
    * platform/graphics/cg/ImageBufferCG.cpp:
    (WebCore::ImageBuffer::ImageBuffer):
    (WebCore::ImageBuffer::drawsUsingCopy):
    (WebCore::ImageBuffer::copyImage):
    (WebCore::ImageBuffer::draw):
    (WebCore::ImageBuffer::drawPattern):
    (WebCore::ImageBuffer::clip):
    * platform/graphics/cg/ImageBufferData.h:
    * platform/graphics/filters/FEColorMatrix.cpp:
    (WebCore::FEColorMatrix::apply):
    * platform/graphics/filters/FEComposite.cpp:
    (WebCore::FEComposite::apply):
    * platform/graphics/filters/SourceAlpha.cpp:
    (WebCore::SourceAlpha::apply):
    * platform/graphics/filters/SourceGraphic.cpp:
    (WebCore::SourceGraphic::apply):
    * platform/graphics/mac/GraphicsContext3DMac.mm:
    * platform/graphics/qt/GraphicsContext3DQt.cpp:
    * platform/graphics/qt/GraphicsContextQt.cpp:
    * platform/graphics/qt/ImageBufferData.h:
    * platform/graphics/qt/ImageBufferQt.cpp:
    (WebCore::ImageBufferData::ImageBufferData):
    (WebCore::ImageBuffer::drawsUsingCopy):
    (WebCore::ImageBuffer::copyImage):
    (WebCore::ImageBuffer::draw):
    (WebCore::ImageBuffer::drawPattern):
    (WebCore::ImageBuffer::clip):
    * platform/graphics/skia/GraphicsContextSkia.cpp:
    * platform/graphics/skia/ImageBufferSkia.cpp:
    (WebCore::ImageBuffer::drawsUsingCopy):
    (WebCore::ImageBuffer::copyImage):
    (WebCore::ImageBuffer::clip):
    (WebCore::):
    * platform/graphics/wx/GraphicsContextWx.cpp:
    * platform/graphics/wx/ImageBufferWx.cpp:
    (WebCore::ImageBuffer::drawsUsingCopy):
    (WebCore::ImageBuffer::copyImage):
    (WebCore::ImageBuffer::clip):
    (WebCore::ImageBuffer::draw):
    (WebCore::ImageBuffer::drawPattern):
    * platform/mac/ScrollbarThemeMac.mm:
    (WebCore::ScrollbarThemeMac::paint):
    * rendering/RenderBoxModelObject.cpp:
    (WebCore::RenderBoxModelObject::paintFillLayerExtended):
    * rendering/RenderSVGResourceClipper.cpp:
    (WebCore::RenderSVGResourceClipper::applyClippingToContext):
    * rendering/RenderSVGResourceFilter.cpp:
    (WebCore::RenderSVGResourceFilter::postApplyResource):
    * rendering/RenderSVGResourceGradient.cpp:
    (WebCore::clipToTextMask):
    * rendering/RenderSVGResourceMasker.cpp:
    (WebCore::RenderSVGResourceMasker::applyResource):
    * rendering/RenderSVGResourcePattern.cpp:
    (WebCore::RenderSVGResourcePattern::buildPattern):
    * rendering/RenderThemeMac.mm:
    (WebCore::RenderThemeMac::paintProgressBar):
    * svg/SVGFEImageElement.cpp:
    (WebCore::SVGFEImageElement::build):
    * svg/graphics/SVGImage.cpp:
    (WebCore::SVGImage::nativeImageForCurrentFrame):
    * svg/graphics/SVGImage.h:
    * svg/graphics/filters/SVGFEMerge.cpp:
    (WebCore::FEMerge::apply):
    * svg/graphics/filters/SVGFEOffset.cpp:
    (WebCore::FEOffset::apply):
    * svg/graphics/filters/SVGFETile.cpp:
    (WebCore::FETile::apply):
    
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@65449 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 163f6c5..a5bbc74 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,133 @@
+2010-08-16  David Hyatt  <hyatt at apple.com>
+
+        Reviewed by Anders Carlsson.
+
+        https://bugs.webkit.org/show_bug.cgi?id=43507, stop ImageBuffer from copying its data when rendering after canvas changes happen.
+        
+        This patch renames ImageBuffer::image() to ImageBuffer::copyImage(). The new method always returns a new copy that is a current
+        snapshot of the ImageBuffer.
+        
+        To draw an ImageBuffer, you now use new GraphicsContext calls: drawImageBuffer.  Platforms can then optimize these calls to draw
+        efficiently without having to copy the bits of the ImageBuffer into an Image.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * css/CSSCanvasValue.cpp:
+        (WebCore::CSSCanvasValue::image):
+        * html/HTMLCanvasElement.cpp:
+        (WebCore::HTMLCanvasElement::willDraw):
+        (WebCore::HTMLCanvasElement::reset):
+        (WebCore::HTMLCanvasElement::paint):
+        (WebCore::HTMLCanvasElement::setSurfaceSize):
+        (WebCore::HTMLCanvasElement::copiedImage):
+        (WebCore::HTMLCanvasElement::clearCopiedImage):
+        * html/HTMLCanvasElement.h:
+        * html/canvas/CanvasPattern.cpp:
+        (WebCore::CanvasPattern::CanvasPattern):
+        * html/canvas/CanvasPattern.h:
+        (WebCore::CanvasPattern::create):
+        * html/canvas/CanvasRenderingContext2D.cpp:
+        (WebCore::CanvasRenderingContext2D::drawImage):
+        (WebCore::CanvasRenderingContext2D::createPattern):
+        (WebCore::CanvasRenderingContext2D::drawTextInternal):
+        * html/canvas/WebGLRenderingContext.cpp:
+        (WebCore::WebGLRenderingContext::paintRenderingResultsToCanvas):
+        (WebCore::WebGLRenderingContext::reshape):
+        (WebCore::WebGLRenderingContext::texImage2D):
+        (WebCore::WebGLRenderingContext::texSubImage2D):
+        * html/canvas/WebGLRenderingContext.h:
+        (WebCore::WebGLRenderingContext::paintsIntoCanvasBuffer):
+        * platform/graphics/GeneratedImage.cpp:
+        (WebCore::GeneratedImage::drawPattern):
+        * platform/graphics/GraphicsContext.cpp:
+        (WebCore::GraphicsContext::drawImageBuffer):
+        (WebCore::GraphicsContext::clipToImageBuffer):
+        * platform/graphics/GraphicsContext.h:
+        * platform/graphics/GraphicsContext3D.h:
+        (WebCore::GraphicsContext3D::paintsIntoCanvasBuffer):
+        * platform/graphics/Image.h:
+        * platform/graphics/ImageBuffer.h:
+        (WebCore::ImageBuffer::width):
+        (WebCore::ImageBuffer::height):
+        * platform/graphics/Pattern.cpp:
+        (WebCore::Pattern::Pattern):
+        * platform/graphics/Pattern.h:
+        (WebCore::Pattern::create):
+        * platform/graphics/cairo/GraphicsContextCairo.cpp:
+        * platform/graphics/cairo/ImageBufferCairo.cpp:
+        (WebCore::ImageBuffer::drawsUsingCopy):
+        (WebCore::ImageBuffer::copyImage):
+        (WebCore::ImageBuffer::clip):
+        (WebCore::ImageBuffer::draw):
+        (WebCore::ImageBuffer::drawPattern):
+        * platform/graphics/cg/GraphicsContextCG.cpp:
+        * platform/graphics/cg/ImageBufferCG.cpp:
+        (WebCore::ImageBuffer::ImageBuffer):
+        (WebCore::ImageBuffer::drawsUsingCopy):
+        (WebCore::ImageBuffer::copyImage):
+        (WebCore::ImageBuffer::draw):
+        (WebCore::ImageBuffer::drawPattern):
+        (WebCore::ImageBuffer::clip):
+        * platform/graphics/cg/ImageBufferData.h:
+        * platform/graphics/filters/FEColorMatrix.cpp:
+        (WebCore::FEColorMatrix::apply):
+        * platform/graphics/filters/FEComposite.cpp:
+        (WebCore::FEComposite::apply):
+        * platform/graphics/filters/SourceAlpha.cpp:
+        (WebCore::SourceAlpha::apply):
+        * platform/graphics/filters/SourceGraphic.cpp:
+        (WebCore::SourceGraphic::apply):
+        * platform/graphics/mac/GraphicsContext3DMac.mm:
+        * platform/graphics/qt/GraphicsContext3DQt.cpp:
+        * platform/graphics/qt/GraphicsContextQt.cpp:
+        * platform/graphics/qt/ImageBufferData.h:
+        * platform/graphics/qt/ImageBufferQt.cpp:
+        (WebCore::ImageBufferData::ImageBufferData):
+        (WebCore::ImageBuffer::drawsUsingCopy):
+        (WebCore::ImageBuffer::copyImage):
+        (WebCore::ImageBuffer::draw):
+        (WebCore::ImageBuffer::drawPattern):
+        (WebCore::ImageBuffer::clip):
+        * platform/graphics/skia/GraphicsContextSkia.cpp:
+        * platform/graphics/skia/ImageBufferSkia.cpp:
+        (WebCore::ImageBuffer::drawsUsingCopy):
+        (WebCore::ImageBuffer::copyImage):
+        (WebCore::ImageBuffer::clip):
+        (WebCore::):
+        * platform/graphics/wx/GraphicsContextWx.cpp:
+        * platform/graphics/wx/ImageBufferWx.cpp:
+        (WebCore::ImageBuffer::drawsUsingCopy):
+        (WebCore::ImageBuffer::copyImage):
+        (WebCore::ImageBuffer::clip):
+        (WebCore::ImageBuffer::draw):
+        (WebCore::ImageBuffer::drawPattern):
+        * platform/mac/ScrollbarThemeMac.mm:
+        (WebCore::ScrollbarThemeMac::paint):
+        * rendering/RenderBoxModelObject.cpp:
+        (WebCore::RenderBoxModelObject::paintFillLayerExtended):
+        * rendering/RenderSVGResourceClipper.cpp:
+        (WebCore::RenderSVGResourceClipper::applyClippingToContext):
+        * rendering/RenderSVGResourceFilter.cpp:
+        (WebCore::RenderSVGResourceFilter::postApplyResource):
+        * rendering/RenderSVGResourceGradient.cpp:
+        (WebCore::clipToTextMask):
+        * rendering/RenderSVGResourceMasker.cpp:
+        (WebCore::RenderSVGResourceMasker::applyResource):
+        * rendering/RenderSVGResourcePattern.cpp:
+        (WebCore::RenderSVGResourcePattern::buildPattern):
+        * rendering/RenderThemeMac.mm:
+        (WebCore::RenderThemeMac::paintProgressBar):
+        * svg/SVGFEImageElement.cpp:
+        (WebCore::SVGFEImageElement::build):
+        * svg/graphics/SVGImage.cpp:
+        (WebCore::SVGImage::nativeImageForCurrentFrame):
+        * svg/graphics/SVGImage.h:
+        * svg/graphics/filters/SVGFEMerge.cpp:
+        (WebCore::FEMerge::apply):
+        * svg/graphics/filters/SVGFEOffset.cpp:
+        (WebCore::FEOffset::apply):
+        * svg/graphics/filters/SVGFETile.cpp:
+        (WebCore::FETile::apply):
+
 2010-08-16  Paul Sawaya  <psawaya at apple.com>
 
         Reviewed by Chris Marrin.
diff --git a/WebCore/WebCore.xcodeproj/project.pbxproj b/WebCore/WebCore.xcodeproj/project.pbxproj
index e98543f..02834d4 100644
--- a/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -4040,7 +4040,7 @@
 		B2A015A90AF6CD53006BCE0E /* GraphicsContext.h in Headers */ = {isa = PBXBuildFile; fileRef = B2A015930AF6CD53006BCE0E /* GraphicsContext.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		B2A015AA0AF6CD53006BCE0E /* GraphicsTypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2A015940AF6CD53006BCE0E /* GraphicsTypes.cpp */; };
 		B2A015AB0AF6CD53006BCE0E /* GraphicsTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = B2A015950AF6CD53006BCE0E /* GraphicsTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
-		B2A10B920B3818BD00099AA4 /* ImageBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = B2A10B910B3818BD00099AA4 /* ImageBuffer.h */; };
+		B2A10B920B3818BD00099AA4 /* ImageBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = B2A10B910B3818BD00099AA4 /* ImageBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		B2A10B940B3818D700099AA4 /* ImageBufferCG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2A10B930B3818D700099AA4 /* ImageBufferCG.cpp */; };
 		B2A1F2AA0CEF0ABF00442F6A /* SVGFontElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B2A1F2A10CEF0ABF00442F6A /* SVGFontElement.cpp */; };
 		B2A1F2AB0CEF0ABF00442F6A /* SVGFontElement.h in Headers */ = {isa = PBXBuildFile; fileRef = B2A1F2A20CEF0ABF00442F6A /* SVGFontElement.h */; };
@@ -4772,6 +4772,7 @@
 		BCA8C83111E3D53200812FB7 /* BackForwardControllerClient.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA8C83011E3D53200812FB7 /* BackForwardControllerClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		BCA8CA5F11E4E6D100812FB7 /* BackForwardListImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCA8CA5D11E4E6D100812FB7 /* BackForwardListImpl.cpp */; };
 		BCA8CA6011E4E6D100812FB7 /* BackForwardListImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA8CA5E11E4E6D100812FB7 /* BackForwardListImpl.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		BCA979171215D055005C485C /* ImageBufferData.h in Headers */ = {isa = PBXBuildFile; fileRef = BCA979161215D055005C485C /* ImageBufferData.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		BCAA90C30A7EBA60008B1229 /* Scrollbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCAA90C20A7EBA60008B1229 /* Scrollbar.cpp */; };
 		BCACF3BC1072921A00C0C8A3 /* UserContentURLPattern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCACF3BA1072921A00C0C8A3 /* UserContentURLPattern.cpp */; };
 		BCACF3BD1072921A00C0C8A3 /* UserContentURLPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = BCACF3BB1072921A00C0C8A3 /* UserContentURLPattern.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -10526,6 +10527,7 @@
 		BCA8C83011E3D53200812FB7 /* BackForwardControllerClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BackForwardControllerClient.h; sourceTree = "<group>"; };
 		BCA8CA5D11E4E6D100812FB7 /* BackForwardListImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BackForwardListImpl.cpp; sourceTree = "<group>"; };
 		BCA8CA5E11E4E6D100812FB7 /* BackForwardListImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BackForwardListImpl.h; sourceTree = "<group>"; };
+		BCA979161215D055005C485C /* ImageBufferData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageBufferData.h; sourceTree = "<group>"; };
 		BCAA90C20A7EBA60008B1229 /* Scrollbar.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Scrollbar.cpp; path = platform/Scrollbar.cpp; sourceTree = SOURCE_ROOT; };
 		BCACF3BA1072921A00C0C8A3 /* UserContentURLPattern.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UserContentURLPattern.cpp; sourceTree = "<group>"; };
 		BCACF3BB1072921A00C0C8A3 /* UserContentURLPattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserContentURLPattern.h; sourceTree = "<group>"; };
@@ -15615,6 +15617,7 @@
 				B2ED97700B1F55CE00257D0F /* GraphicsContextCG.cpp */,
 				A80D67070E9E9DEB00E420F0 /* GraphicsContextPlatformPrivateCG.h */,
 				B2A10B930B3818D700099AA4 /* ImageBufferCG.cpp */,
+				BCA979161215D055005C485C /* ImageBufferData.h */,
 				B27535300B053814002CE64F /* ImageCG.cpp */,
 				B27535310B053814002CE64F /* ImageSourceCG.cpp */,
 				4B3480920EEF50D400AC1B41 /* ImageSourceCG.h */,
@@ -20188,6 +20191,7 @@
 				97DD4D870FDF4D6E00ECF9A4 /* XSSAuditor.h in Headers */,
 				CE172E011136E8CE0062A533 /* ZoomMode.h in Headers */,
 				C50B561712119D23008B46E0 /* GroupSettings.h in Headers */,
+				BCA979171215D055005C485C /* ImageBufferData.h in Headers */,
 				490707E71219C04300D90E51 /* ANGLEWebKitBridge.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
@@ -20248,7 +20252,6 @@
 			isa = PBXProject;
 			buildConfigurationList = 149C284308902B11008A9EFC /* Build configuration list for PBXProject "WebCore" */;
 			compatibilityVersion = "Xcode 2.4";
-			developmentRegion = English;
 			hasScannedForEncodings = 1;
 			knownRegions = (
 				English,
diff --git a/WebCore/css/CSSCanvasValue.cpp b/WebCore/css/CSSCanvasValue.cpp
index 0c1c3f9..767c11e 100644
--- a/WebCore/css/CSSCanvasValue.cpp
+++ b/WebCore/css/CSSCanvasValue.cpp
@@ -90,7 +90,7 @@ Image* CSSCanvasValue::image(RenderObject* renderer, const IntSize& /*size*/)
     HTMLCanvasElement* elt = element(renderer->document());
     if (!elt || !elt->buffer())
         return 0;
-    return elt->buffer()->image();
+    return elt->copiedImage();
 }
 
 } // namespace WebCore
diff --git a/WebCore/html/HTMLCanvasElement.cpp b/WebCore/html/HTMLCanvasElement.cpp
index 3629776..84ab227 100644
--- a/WebCore/html/HTMLCanvasElement.cpp
+++ b/WebCore/html/HTMLCanvasElement.cpp
@@ -209,8 +209,7 @@ CanvasRenderingContext* HTMLCanvasElement::getContext(const String& type, Canvas
 
 void HTMLCanvasElement::willDraw(const FloatRect& rect)
 {
-    if (m_imageBuffer)
-        m_imageBuffer->clearImage();
+    m_copiedImage.clear(); // Clear our image snapshot if we have one.
 
     if (RenderBox* ro = renderBox()) {
         FloatRect destRect = ro->contentBoxRect();
@@ -242,10 +241,10 @@ void HTMLCanvasElement::reset()
         h = DefaultHeight;
 
     IntSize oldSize = size();
-    setSurfaceSize(IntSize(w, h));
+    setSurfaceSize(IntSize(w, h)); // The image buffer gets cleared here.
 
 #if ENABLE(3D_CANVAS)
-    if (m_context && m_context->is3d())
+    if (m_context && m_context->is3d() && oldSize != size())
         static_cast<WebGLRenderingContext*>(m_context.get())->reshape(width(), height());
 #endif
 
@@ -277,23 +276,21 @@ void HTMLCanvasElement::paint(GraphicsContext* context, const IntRect& r)
     WebGLRenderingContext* context3D = 0;
     if (m_context && m_context->is3d()) {
         context3D = static_cast<WebGLRenderingContext*>(m_context.get());
-        context3D->beginPaint();
+        if (!context3D->paintsIntoCanvasBuffer())
+            return;
+        context3D->paintRenderingResultsToCanvas();
     }
 #endif
 
     if (hasCreatedImageBuffer()) {
         ImageBuffer* imageBuffer = buffer();
         if (imageBuffer) {
-            Image* image = imageBuffer->imageForRendering();
-            if (image)
-                context->drawImage(image, DeviceColorSpace, r);
+            if (imageBuffer->drawsUsingCopy())
+                context->drawImage(copiedImage(), DeviceColorSpace, r);
+            else
+                context->drawImageBuffer(imageBuffer, DeviceColorSpace, r);
         }
     }
-
-#if ENABLE(3D_CANVAS)
-    if (context3D)
-        context3D->endPaint();
-#endif
 }
 
 #if ENABLE(3D_CANVAS)    
@@ -325,6 +322,7 @@ void HTMLCanvasElement::setSurfaceSize(const IntSize& size)
     m_size = size;
     m_hasCreatedImageBuffer = false;
     m_imageBuffer.clear();
+    m_copiedImage.clear();
 }
 
 String HTMLCanvasElement::toDataURL(const String& mimeType, const double* quality, ExceptionCode& ec)
@@ -420,6 +418,18 @@ ImageBuffer* HTMLCanvasElement::buffer() const
     return m_imageBuffer.get();
 }
 
+Image* HTMLCanvasElement::copiedImage() const
+{
+    if (!m_copiedImage && buffer())
+        m_copiedImage = buffer()->copyImage();
+    return m_copiedImage.get();
+}
+
+void HTMLCanvasElement::clearCopiedImage()
+{
+    m_copiedImage.clear();
+}
+
 AffineTransform HTMLCanvasElement::baseTransform() const
 {
     ASSERT(m_hasCreatedImageBuffer);
diff --git a/WebCore/html/HTMLCanvasElement.h b/WebCore/html/HTMLCanvasElement.h
index b222007..a52cc9c 100644
--- a/WebCore/html/HTMLCanvasElement.h
+++ b/WebCore/html/HTMLCanvasElement.h
@@ -38,6 +38,7 @@ class CanvasContextAttributes;
 class CanvasRenderingContext;
 class GraphicsContext;
 class HTMLCanvasElement;
+class Image;
 class ImageBuffer;
 class IntSize;
 
@@ -93,6 +94,8 @@ public:
     CanvasRenderingContext* renderingContext() const { return m_context.get(); }
 
     ImageBuffer* buffer() const;
+    Image* copiedImage() const;
+    void clearCopiedImage();
 
     IntRect convertLogicalToDevice(const FloatRect&) const;
     IntSize convertLogicalToDevice(const FloatSize&) const;
@@ -149,6 +152,8 @@ private:
     // m_createdImageBuffer means we tried to malloc the buffer.  We didn't necessarily get it.
     mutable bool m_hasCreatedImageBuffer;
     mutable OwnPtr<ImageBuffer> m_imageBuffer;
+    
+    mutable RefPtr<Image> m_copiedImage; // FIXME: This is temporary for platforms that have to copy the image buffer to render (and for CSSCanvasValue).
 };
 
 } //namespace
diff --git a/WebCore/html/canvas/CanvasPattern.cpp b/WebCore/html/canvas/CanvasPattern.cpp
index 62a4620..818d7d3 100644
--- a/WebCore/html/canvas/CanvasPattern.cpp
+++ b/WebCore/html/canvas/CanvasPattern.cpp
@@ -57,7 +57,7 @@ void CanvasPattern::parseRepetitionType(const String& type, bool& repeatX, bool&
     ec = SYNTAX_ERR;
 }
 
-CanvasPattern::CanvasPattern(Image* image, bool repeatX, bool repeatY, bool originClean)
+CanvasPattern::CanvasPattern(PassRefPtr<Image> image, bool repeatX, bool repeatY, bool originClean)
     : m_pattern(Pattern::create(image, repeatX, repeatY))
     , m_originClean(originClean)
 {
diff --git a/WebCore/html/canvas/CanvasPattern.h b/WebCore/html/canvas/CanvasPattern.h
index 91e0794..58848a9 100644
--- a/WebCore/html/canvas/CanvasPattern.h
+++ b/WebCore/html/canvas/CanvasPattern.h
@@ -41,7 +41,7 @@ namespace WebCore {
     public:
         static void parseRepetitionType(const String&, bool& repeatX, bool& repeatY, ExceptionCode&);
 
-        static PassRefPtr<CanvasPattern> create(Image* image, bool repeatX, bool repeatY, bool originClean)
+        static PassRefPtr<CanvasPattern> create(PassRefPtr<Image> image, bool repeatX, bool repeatY, bool originClean)
         {
             return adoptRef(new CanvasPattern(image, repeatX, repeatY, originClean));
         }
@@ -51,7 +51,7 @@ namespace WebCore {
         bool originClean() const { return m_originClean; }
 
     private:
-        CanvasPattern(Image*, bool repeatX, bool repeatY, bool originClean);
+        CanvasPattern(PassRefPtr<Image>, bool repeatX, bool repeatY, bool originClean);
 
         RefPtr<Pattern> m_pattern;
         bool m_originClean;
diff --git a/WebCore/html/canvas/CanvasRenderingContext2D.cpp b/WebCore/html/canvas/CanvasRenderingContext2D.cpp
index 559ddda..702b109 100644
--- a/WebCore/html/canvas/CanvasRenderingContext2D.cpp
+++ b/WebCore/html/canvas/CanvasRenderingContext2D.cpp
@@ -1264,7 +1264,7 @@ void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* sourceCanvas, const
 
     sourceCanvas->makeRenderingResultsAvailable();
 
-    c->drawImage(buffer->image(), DeviceColorSpace, destRect, sourceRect, state().m_globalComposite);
+    c->drawImageBuffer(buffer, DeviceColorSpace, destRect, sourceRect, state().m_globalComposite);
     willDraw(destRect); // This call comes after drawImage, since the buffer we draw into may be our own, and we need to make sure it is dirty.
                         // FIXME: Arguably willDraw should become didDraw and occur after drawing calls and not before them to avoid problems like this.
 }
@@ -1464,7 +1464,7 @@ PassRefPtr<CanvasPattern> CanvasRenderingContext2D::createPattern(HTMLCanvasElem
     CanvasPattern::parseRepetitionType(repetitionType, repeatX, repeatY, ec);
     if (ec)
         return 0;
-    return CanvasPattern::create(canvas->buffer()->image(), repeatX, repeatY, canvas->originClean());
+    return CanvasPattern::create(canvas->copiedImage(), repeatX, repeatY, canvas->originClean());
 }
 
 void CanvasRenderingContext2D::willDraw(const FloatRect& r, unsigned options)
@@ -1820,7 +1820,7 @@ void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo
         maskImageContext->drawBidiText(font, textRun, location);
 
         c->save();
-        c->clipToImageBuffer(maskRect, maskImage.get());
+        c->clipToImageBuffer(maskImage.get(), maskRect);
         drawStyle->applyFillColor(c);
         c->fillRect(maskRect);
         c->restore();
diff --git a/WebCore/html/canvas/WebGLRenderingContext.cpp b/WebCore/html/canvas/WebGLRenderingContext.cpp
index b4ea464..4465833 100644
--- a/WebCore/html/canvas/WebGLRenderingContext.cpp
+++ b/WebCore/html/canvas/WebGLRenderingContext.cpp
@@ -158,27 +158,11 @@ void WebGLRenderingContext::markContextChanged()
 
 void WebGLRenderingContext::paintRenderingResultsToCanvas()
 {
-    if (m_markedCanvasDirty) {
-        // FIXME: It should not be necessary to clear the image before doing a readback.
-        // Investigate why this is needed and remove if possible.
-        canvas()->buffer()->clearImage();
-        m_markedCanvasDirty = false;
-        m_context->paintRenderingResultsToCanvas(this);
-    }
-}
-
-void WebGLRenderingContext::beginPaint()
-{
-    if (m_markedCanvasDirty)
-        m_context->beginPaint(this);
-}
-
-void WebGLRenderingContext::endPaint()
-{
-    if (m_markedCanvasDirty) {
-        m_markedCanvasDirty = false;
-        m_context->endPaint();
-    }
+    if (!m_markedCanvasDirty)
+        return;
+    canvas()->clearCopiedImage();
+    m_markedCanvasDirty = false;
+    m_context->paintRenderingResultsToCanvas(this);
 }
 
 void WebGLRenderingContext::reshape(int width, int height)
@@ -191,7 +175,9 @@ void WebGLRenderingContext::reshape(int width, int height)
 #endif
         m_needsUpdate = false;
     }
-    
+
+    // We don't have to mark the canvas as dirty, since the newly created image buffer will also start off
+    // clear (and this matches what reshape will do).
     m_context->reshape(width, height);
 }
 
@@ -2197,7 +2183,8 @@ void WebGLRenderingContext::texImage2D(unsigned target, unsigned level, unsigned
         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
         return;
     }
-    texImage2DImpl(target, level, internalformat, format, type, canvas->buffer()->image(),
+    
+    texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(),
                    m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
 }
 
@@ -2347,7 +2334,8 @@ void WebGLRenderingContext::texSubImage2D(unsigned target, unsigned level, unsig
         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
         return;
     }
-    texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->buffer()->image(),
+    
+    texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(),
                       m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
 }
 
diff --git a/WebCore/html/canvas/WebGLRenderingContext.h b/WebCore/html/canvas/WebGLRenderingContext.h
index 6fe96b0..48fa7c8 100644
--- a/WebCore/html/canvas/WebGLRenderingContext.h
+++ b/WebCore/html/canvas/WebGLRenderingContext.h
@@ -279,12 +279,10 @@ public:
 
     virtual void paintRenderingResultsToCanvas();
 
-    // Helpers for notification about paint events.
-    void beginPaint();
-    void endPaint();
-
     void removeObject(WebGLObject*);
 
+    bool paintsIntoCanvasBuffer() const { return m_context->paintsIntoCanvasBuffer(); }
+
   private:
     friend class WebGLObject;
 
diff --git a/WebCore/platform/graphics/GeneratedImage.cpp b/WebCore/platform/graphics/GeneratedImage.cpp
index cd0748e..5df2608 100644
--- a/WebCore/platform/graphics/GeneratedImage.cpp
+++ b/WebCore/platform/graphics/GeneratedImage.cpp
@@ -63,11 +63,8 @@ void GeneratedImage::drawPattern(GraphicsContext* context, const FloatRect& srcR
     GraphicsContext* graphicsContext = imageBuffer->context();
     graphicsContext->fillRect(FloatRect(FloatPoint(), adjustedSize), *m_generator.get());
 
-    // Grab the final image from the image buffer.
-    Image* bitmap = imageBuffer->image();
-
-    // Now just call drawTiled on that image.
-    bitmap->drawPattern(context, adjustedSrcRect, patternTransform, phase, styleColorSpace, compositeOp, destRect);
+    // Tile the image buffer into the context.
+    imageBuffer->drawPattern(context, adjustedSrcRect, patternTransform, phase, styleColorSpace, compositeOp, destRect);
 }
 
 }
diff --git a/WebCore/platform/graphics/GraphicsContext.cpp b/WebCore/platform/graphics/GraphicsContext.cpp
index c23ca1c..67a35ec 100644
--- a/WebCore/platform/graphics/GraphicsContext.cpp
+++ b/WebCore/platform/graphics/GraphicsContext.cpp
@@ -30,6 +30,7 @@
 #include "Font.h"
 #include "Generator.h"
 #include "GraphicsContextPrivate.h"
+#include "ImageBuffer.h"
 
 using namespace std;
 
@@ -442,6 +443,57 @@ void GraphicsContext::drawTiledImage(Image* image, ColorSpace styleColorSpace, c
         restore();
 }
 
+void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const IntPoint& p, CompositeOperator op)
+{
+    drawImageBuffer(image, styleColorSpace, p, IntRect(0, 0, -1, -1), op);
+}
+
+void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const IntRect& r, CompositeOperator op, bool useLowQualityScale)
+{
+    drawImageBuffer(image, styleColorSpace, r, IntRect(0, 0, -1, -1), op, useLowQualityScale);
+}
+
+void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const IntPoint& dest, const IntRect& srcRect, CompositeOperator op)
+{
+    drawImageBuffer(image, styleColorSpace, IntRect(dest, srcRect.size()), srcRect, op);
+}
+
+void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const IntRect& dest, const IntRect& srcRect, CompositeOperator op, bool useLowQualityScale)
+{
+    drawImageBuffer(image, styleColorSpace, FloatRect(dest), srcRect, op, useLowQualityScale);
+}
+
+void GraphicsContext::drawImageBuffer(ImageBuffer* image, ColorSpace styleColorSpace, const FloatRect& dest, const FloatRect& src, CompositeOperator op, bool useLowQualityScale)
+{
+    if (paintingDisabled() || !image)
+        return;
+        
+    float tsw = src.width();
+    float tsh = src.height();
+    float tw = dest.width();
+    float th = dest.height();
+
+    if (tsw == -1)
+        tsw = image->width();
+    if (tsh == -1)
+        tsh = image->height();
+
+    if (tw == -1)
+        tw = image->width();
+    if (th == -1)
+        th = image->height();
+
+    if (useLowQualityScale) {
+        save();
+        setImageInterpolationQuality(InterpolationNone);
+    }
+
+    image->draw(this, styleColorSpace, dest, src, op, useLowQualityScale);
+    
+    if (useLowQualityScale)
+        restore();
+}
+
 void GraphicsContext::addRoundedRectClip(const IntRect& rect, const IntSize& topLeft, const IntSize& topRight,
     const IntSize& bottomLeft, const IntSize& bottomRight)
 {
@@ -460,6 +512,13 @@ void GraphicsContext::clipOutRoundedRect(const IntRect& rect, const IntSize& top
     clipOut(Path::createRoundedRectangle(rect, topLeft, topRight, bottomLeft, bottomRight));
 }
 
+void GraphicsContext::clipToImageBuffer(ImageBuffer* buffer, const FloatRect& rect)
+{
+    if (paintingDisabled())
+        return;
+    buffer->clip(this, rect);
+}
+
 int GraphicsContext::textDrawingMode()
 {
     return m_common->state.textDrawingMode;
diff --git a/WebCore/platform/graphics/GraphicsContext.h b/WebCore/platform/graphics/GraphicsContext.h
index c903ed7..5c43a4e 100644
--- a/WebCore/platform/graphics/GraphicsContext.h
+++ b/WebCore/platform/graphics/GraphicsContext.h
@@ -238,6 +238,13 @@ namespace WebCore {
                             Image::TileRule hRule = Image::StretchTile, Image::TileRule vRule = Image::StretchTile,
                             CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
 
+        void drawImageBuffer(ImageBuffer*, ColorSpace styleColorSpace, const IntPoint&, CompositeOperator = CompositeSourceOver);
+        void drawImageBuffer(ImageBuffer*, ColorSpace styleColorSpace, const IntRect&, CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
+        void drawImageBuffer(ImageBuffer*, ColorSpace styleColorSpace, const IntPoint& destPoint, const IntRect& srcRect, CompositeOperator = CompositeSourceOver);
+        void drawImageBuffer(ImageBuffer*, ColorSpace styleColorSpace, const IntRect& destRect, const IntRect& srcRect, CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
+        void drawImageBuffer(ImageBuffer*, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect = FloatRect(0, 0, -1, -1),
+                             CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
+
         void setImageInterpolationQuality(InterpolationQuality);
         InterpolationQuality imageInterpolationQuality() const;
 
@@ -248,8 +255,8 @@ namespace WebCore {
         void clipOutEllipseInRect(const IntRect&);
         void clipOutRoundedRect(const IntRect&, const IntSize& topLeft, const IntSize& topRight, const IntSize& bottomLeft, const IntSize& bottomRight);
         void clipPath(WindRule);
-        void clipToImageBuffer(const FloatRect&, const ImageBuffer*);
         void clipConvexPolygon(size_t numPoints, const FloatPoint*, bool antialias = true);
+        void clipToImageBuffer(ImageBuffer*, const FloatRect&);
 
         int textDrawingMode();
         void setTextDrawingMode(int);
diff --git a/WebCore/platform/graphics/GraphicsContext3D.h b/WebCore/platform/graphics/GraphicsContext3D.h
index 3c5eb50..165f197 100644
--- a/WebCore/platform/graphics/GraphicsContext3D.h
+++ b/WebCore/platform/graphics/GraphicsContext3D.h
@@ -720,11 +720,11 @@ public:
 
     void paintRenderingResultsToCanvas(CanvasRenderingContext* context);
 
-    // Helpers for notification about paint events
-    void beginPaint(CanvasRenderingContext* context);
-    void endPaint();
 #if PLATFORM(QT)
     void paint(QPainter* painter, const QRect& rect) const;
+    bool paintsIntoCanvasBuffer() const { return true; }
+#else
+    bool paintsIntoCanvasBuffer() const { return false; }
 #endif
 
     // Support for buffer creation and deletion
diff --git a/WebCore/platform/graphics/Image.h b/WebCore/platform/graphics/Image.h
index 17be9e0..5c2b715 100644
--- a/WebCore/platform/graphics/Image.h
+++ b/WebCore/platform/graphics/Image.h
@@ -150,6 +150,9 @@ public:
     static PassRefPtr<Image> loadPlatformThemeIcon(const char* name, int size);
 #endif
 
+    virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform,
+                             const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect);
+
 protected:
     Image(ImageObserver* = 0);
 
@@ -167,9 +170,6 @@ protected:
     virtual bool mayFillWithSolidColor() { return false; }
     virtual Color solidColor() const { return Color(); }
     
-    virtual void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform,
-                             const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect);
-
 private:
     RefPtr<SharedBuffer> m_data; // The encoded raw data for the image. 
     ImageObserver* m_imageObserver;
diff --git a/WebCore/platform/graphics/ImageBuffer.h b/WebCore/platform/graphics/ImageBuffer.h
index a54c721..3c0508e 100644
--- a/WebCore/platform/graphics/ImageBuffer.h
+++ b/WebCore/platform/graphics/ImageBuffer.h
@@ -29,6 +29,7 @@
 #define ImageBuffer_h
 
 #include "AffineTransform.h"
+#include "FloatRect.h"
 #include "Image.h"
 #include "IntSize.h"
 #include "ImageBufferData.h"
@@ -71,16 +72,13 @@ namespace WebCore {
         ~ImageBuffer();
 
         const IntSize& size() const { return m_size; }
+        int width() const { return m_size.width(); }
+        int height() const { return m_size.height(); }
+        
         GraphicsContext* context() const;
 
-        Image* image() const;
-#if PLATFORM(QT)
-        Image* imageForRendering() const;
-#else
-        Image* imageForRendering() const { return image(); }
-#endif
-
-        void clearImage() { m_image.clear(); }
+        bool drawsUsingCopy() const; // If the image buffer has to render using a copied image, it will return true.
+        PassRefPtr<Image> copyImage() const; // Return a new image that is a copy of the buffer.
 
         PassRefPtr<ImageData> getUnmultipliedImageData(const IntRect&) const;
         PassRefPtr<ImageData> getPremultipliedImageData(const IntRect&) const;
@@ -96,12 +94,23 @@ namespace WebCore {
 #else
         AffineTransform baseTransform() const { return AffineTransform(1, 0, 0, -1, 0, m_size.height()); }
 #endif
+
+    private:
+        void clip(GraphicsContext*, const FloatRect&) const;
+
+        // The draw method draws the contents of the buffer without copying it.
+        void draw(GraphicsContext*, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect = FloatRect(0, 0, -1, -1),
+                             CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
+        void drawPattern(GraphicsContext*, const FloatRect& srcRect, const AffineTransform& patternTransform,
+                         const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect);
+        friend class GraphicsContext;
+        friend class GeneratedImage;
+
     private:
         ImageBufferData m_data;
 
         IntSize m_size;
         OwnPtr<GraphicsContext> m_context;
-        mutable RefPtr<Image> m_image;
 
 #if !PLATFORM(CG)
         Vector<int> m_linearRgbLUT;
diff --git a/WebCore/platform/graphics/Pattern.cpp b/WebCore/platform/graphics/Pattern.cpp
index bb07307..82d0a24 100644
--- a/WebCore/platform/graphics/Pattern.cpp
+++ b/WebCore/platform/graphics/Pattern.cpp
@@ -31,7 +31,7 @@
 
 namespace WebCore {
 
-Pattern::Pattern(Image* image, bool repeatX, bool repeatY)
+Pattern::Pattern(PassRefPtr<Image> image, bool repeatX, bool repeatY)
     : m_tileImage(image)
     , m_repeatX(repeatX)
     , m_repeatY(repeatY)
@@ -39,7 +39,7 @@ Pattern::Pattern(Image* image, bool repeatX, bool repeatY)
     , m_pattern(0)
 #endif
 {
-    ASSERT(image);
+    ASSERT(m_tileImage);
 }
 
 Pattern::~Pattern()
diff --git a/WebCore/platform/graphics/Pattern.h b/WebCore/platform/graphics/Pattern.h
index 48e8d8b..e215f3d 100644
--- a/WebCore/platform/graphics/Pattern.h
+++ b/WebCore/platform/graphics/Pattern.h
@@ -29,6 +29,7 @@
 #define Pattern_h
 
 #include "AffineTransform.h"
+#include "Image.h"
 
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
@@ -64,11 +65,10 @@ typedef void* PlatformPatternPtr;
 namespace WebCore {
 
 class AffineTransform;
-class Image;
 
 class Pattern : public RefCounted<Pattern> {
 public:
-    static PassRefPtr<Pattern> create(Image* tileImage, bool repeatX, bool repeatY)
+    static PassRefPtr<Pattern> create(PassRefPtr<Image> tileImage, bool repeatX, bool repeatY)
     {
         return adoptRef(new Pattern(tileImage, repeatX, repeatY));
     }
@@ -91,7 +91,7 @@ public:
     bool repeatY() const { return m_repeatY; }
 
 private:
-    Pattern(Image*, bool repeatX, bool repeatY);
+    Pattern(PassRefPtr<Image>, bool repeatX, bool repeatY);
 
     RefPtr<Image> m_tileImage;
     bool m_repeatX;
diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
index f3fc943..8810984 100644
--- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
+++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
@@ -908,14 +908,6 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
     cairo_set_fill_rule(cr, savedFillRule);
 }
 
-void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer* imageBuffer)
-{
-    if (paintingDisabled())
-        return;
-
-    notImplemented();
-}
-
 void GraphicsContext::setPlatformShadow(FloatSize const& size, float, Color const&, ColorSpace)
 {
     // Cairo doesn't support shadows natively, they are drawn manually in the draw*
diff --git a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
index 1a43e54..3826114 100644
--- a/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
+++ b/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
@@ -97,26 +97,34 @@ GraphicsContext* ImageBuffer::context() const
     return m_context.get();
 }
 
-Image* ImageBuffer::image() const
+bool ImageBuffer::drawsUsingCopy() const
 {
-    if (!m_image) {
-        // It's assumed that if image() is called, the actual rendering to the
-        // GraphicsContext must be done.
-        ASSERT(context());
-
-        // This creates a COPY of the image and will cache that copy. This means
-        // that if subsequent operations take place on the context, neither the
-        // currently-returned image, nor the results of future image() calls,
-        // will contain that operation.
-        //
-        // This seems silly, but is the way the CG port works: image() is
-        // intended to be used only when rendering is "complete."
-        cairo_surface_t* newsurface = copySurface(m_data.m_surface);
-
-        // BitmapImage will release the passed in surface on destruction
-        m_image = BitmapImage::create(newsurface);
-    }
-    return m_image.get();
+    return true;
+}
+
+PassRefPtr<Image> ImageBuffer::copyImage() const
+{
+    // BitmapImage will release the passed in surface on destruction
+    return BitmapImage::create(copySurface(m_data.m_surface));
+}
+
+void ImageBuffer::clip(GraphicsContext* context, const FloatRect&) const
+{
+    notImplemented();
+}
+
+void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect,
+                       CompositeOperator op , bool useLowQualityScale)
+{
+    RefPtr<Image> imageCopy = copyImage();
+    context->drawImage(imageCopy.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
+}
+
+void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform,
+                              const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
+{
+    RefPtr<Image> imageCopy = copyImage();
+    imageCopy->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
 }
 
 void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
diff --git a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
index c3d4c07..e5079dc 100644
--- a/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
+++ b/WebCore/platform/graphics/cg/GraphicsContextCG.cpp
@@ -753,18 +753,6 @@ void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect, int thickness
     CGContextEOClip(context);
 }
 
-void GraphicsContext::clipToImageBuffer(const FloatRect& rect, const ImageBuffer* imageBuffer)
-{
-    if (paintingDisabled())
-        return;
-
-    CGContextTranslateCTM(platformContext(), rect.x(), rect.y() + rect.height());
-    CGContextScaleCTM(platformContext(), 1, -1);
-    CGContextClipToMask(platformContext(), FloatRect(FloatPoint(), rect.size()), imageBuffer->image()->getCGImageRef());
-    CGContextScaleCTM(platformContext(), 1, -1);
-    CGContextTranslateCTM(platformContext(), -rect.x(), -rect.y() - rect.height());
-}
-
 void GraphicsContext::beginTransparencyLayer(float opacity)
 {
     if (paintingDisabled())
diff --git a/WebCore/platform/graphics/cg/ImageBufferCG.cpp b/WebCore/platform/graphics/cg/ImageBufferCG.cpp
index feb8cec..ecbcf60 100644
--- a/WebCore/platform/graphics/cg/ImageBufferCG.cpp
+++ b/WebCore/platform/graphics/cg/ImageBufferCG.cpp
@@ -46,6 +46,11 @@ using namespace std;
 
 namespace WebCore {
 
+static void releaseImageData(void*, const void* data, size_t)
+{
+    fastFree(const_cast<void*>(data));
+}
+
 ImageBufferData::ImageBufferData(const IntSize&)
     : m_data(0)
 {
@@ -56,42 +61,46 @@ ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, b
     , m_size(size)
 {
     success = false;  // Make early return mean failure.
-    unsigned bytesPerRow;
     if (size.width() < 0 || size.height() < 0)
         return;
-    bytesPerRow = size.width();
+
+    unsigned bytesPerRow = size.width();
     if (imageColorSpace != GrayScale) {
         // Protect against overflow
         if (bytesPerRow > 0x3FFFFFFF)
             return;
         bytesPerRow *= 4;
     }
+    m_data.m_bytesPerRow = bytesPerRow;
 
+    size_t dataSize = size.height() * bytesPerRow;
     if (!tryFastCalloc(size.height(), bytesPerRow).getValue(m_data.m_data))
         return;
 
     ASSERT((reinterpret_cast<size_t>(m_data.m_data) & 2) == 0);
 
-    RetainPtr<CGColorSpaceRef> colorSpace;
     switch(imageColorSpace) {
         case DeviceRGB:
-            colorSpace.adoptCF(CGColorSpaceCreateDeviceRGB());
+            m_data.m_colorSpace.adoptCF(CGColorSpaceCreateDeviceRGB());
             break;
         case GrayScale:
-            colorSpace.adoptCF(CGColorSpaceCreateDeviceGray());
+            m_data.m_colorSpace.adoptCF(CGColorSpaceCreateDeviceGray());
             break;
 #if ((PLATFORM(MAC) || PLATFORM(CHROMIUM)) && !defined(BUILDING_ON_TIGER))
         case LinearRGB:
-            colorSpace.adoptCF(CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear));
+            m_data.m_colorSpace.adoptCF(CGColorSpaceCreateWithName(kCGColorSpaceGenericRGBLinear));
             break;
+            
 #endif
         default:
-            colorSpace.adoptCF(CGColorSpaceCreateDeviceRGB());
+            m_data.m_colorSpace.adoptCF(CGColorSpaceCreateDeviceRGB());
             break;
     }
 
+    m_data.m_grayScale = imageColorSpace == GrayScale;
+    m_data.m_bitmapInfo = m_data.m_grayScale ? kCGImageAlphaNone : kCGImageAlphaPremultipliedLast;
     RetainPtr<CGContextRef> cgContext(AdoptCF, CGBitmapContextCreate(m_data.m_data, size.width(), size.height(), 8, bytesPerRow,
-        colorSpace.get(), (imageColorSpace == GrayScale) ? kCGImageAlphaNone : kCGImageAlphaPremultipliedLast));
+                                                                     m_data.m_colorSpace.get(), m_data.m_bitmapInfo));
     if (!cgContext)
         return;
 
@@ -99,11 +108,13 @@ ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace imageColorSpace, b
     m_context->scale(FloatSize(1, -1));
     m_context->translate(0, -size.height());
     success = true;
+    
+    // Create a live image that wraps the data.
+    m_data.m_dataProvider.adoptCF(CGDataProviderCreateWithData(0, m_data.m_data, dataSize, releaseImageData));
 }
 
 ImageBuffer::~ImageBuffer()
 {
-    fastFree(m_data.m_data);
 }
 
 GraphicsContext* ImageBuffer::context() const
@@ -111,17 +122,59 @@ GraphicsContext* ImageBuffer::context() const
     return m_context.get();
 }
 
-Image* ImageBuffer::image() const
+bool ImageBuffer::drawsUsingCopy() const
+{
+    return false;
+}
+
+PassRefPtr<Image> ImageBuffer::copyImage() const
+{
+    // BitmapImage will release the passed in CGImage on destruction
+    return BitmapImage::create(CGBitmapContextCreateImage(context()->platformContext()));
+}
+
+static CGImageRef cgImage(const IntSize& size, const ImageBufferData& data)
 {
-    if (!m_image) {
-        // It's assumed that if image() is called, the actual rendering to the
-        // GraphicsContext must be done.
-        ASSERT(context());
-        CGImageRef cgImage = CGBitmapContextCreateImage(context()->platformContext());
-        // BitmapImage will release the passed in CGImage on destruction
-        m_image = BitmapImage::create(cgImage);
+    return CGImageCreate(size.width(), size.height(), 8, data.m_grayScale ? 8 : 32, data.m_bytesPerRow,
+                         data.m_colorSpace.get(), data.m_bitmapInfo, data.m_dataProvider.get(), 0, true, kCGRenderingIntentDefault);
+}
+
+void ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect,
+                       CompositeOperator op, bool useLowQualityScale)
+{
+    if (destContext == context()) {
+        // We're drawing into our own buffer.  In order for this to work, we need to copy the source buffer first.
+        RefPtr<Image> copy = copyImage();
+        destContext->drawImage(copy.get(), DeviceColorSpace, destRect, srcRect, op, useLowQualityScale);
+    } else {
+        RefPtr<Image> imageForRendering = BitmapImage::create(cgImage(m_size, m_data));
+        destContext->drawImage(imageForRendering.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
+    }
+}
+
+void ImageBuffer::drawPattern(GraphicsContext* destContext, const FloatRect& srcRect, const AffineTransform& patternTransform,
+                              const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
+{
+    if (destContext == context()) {
+        // We're drawing into our own buffer.  In order for this to work, we need to copy the source buffer first.
+        RefPtr<Image> copy = copyImage();
+        copy->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
+    } else {
+        RefPtr<Image> imageForRendering = BitmapImage::create(cgImage(m_size, m_data));
+        imageForRendering->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
     }
-    return m_image.get();
+}
+
+void ImageBuffer::clip(GraphicsContext* context, const FloatRect& rect) const
+{
+    RetainPtr<CGImageRef> image(AdoptCF, cgImage(m_size, m_data));
+                                                                                          
+    CGContextRef platformContext = context->platformContext();
+    CGContextTranslateCTM(platformContext, rect.x(), rect.y() + rect.height());
+    CGContextScaleCTM(platformContext, 1, -1);
+    CGContextClipToMask(platformContext, FloatRect(FloatPoint(), rect.size()), image.get());
+    CGContextScaleCTM(platformContext, 1, -1);
+    CGContextTranslateCTM(platformContext, -rect.x(), -rect.y() - rect.height());
 }
 
 template <Multiply multiplied>
diff --git a/WebCore/platform/graphics/cg/ImageBufferData.h b/WebCore/platform/graphics/cg/ImageBufferData.h
index 5e6fc4c..2f9d854 100644
--- a/WebCore/platform/graphics/cg/ImageBufferData.h
+++ b/WebCore/platform/graphics/cg/ImageBufferData.h
@@ -26,6 +26,14 @@
 #ifndef ImageBufferData_h
 #define ImageBufferData_h
 
+#include "Image.h"
+#include <wtf/RefPtr.h>
+#include <wtf/RetainPtr.h>
+
+typedef struct CGColorSpace *CGColorSpaceRef;
+typedef struct CGDataProvider *CGDataProviderRef;
+typedef uint32_t CGBitmapInfo;
+
 namespace WebCore {
 
 class IntSize;
@@ -35,6 +43,12 @@ public:
     ImageBufferData(const IntSize&);
 
     void* m_data;
+    
+    RetainPtr<CGDataProviderRef> m_dataProvider;
+    CGBitmapInfo m_bitmapInfo;
+    bool m_grayScale;
+    unsigned m_bytesPerRow;
+    RetainPtr<CGColorSpaceRef> m_colorSpace;
 };
 
 }  // namespace WebCore
diff --git a/WebCore/platform/graphics/filters/FEColorMatrix.cpp b/WebCore/platform/graphics/filters/FEColorMatrix.cpp
index c5ae3b9..7718066 100644
--- a/WebCore/platform/graphics/filters/FEColorMatrix.cpp
+++ b/WebCore/platform/graphics/filters/FEColorMatrix.cpp
@@ -164,7 +164,7 @@ void FEColorMatrix::apply(Filter* filter)
     if (!filterContext)
         return;
 
-    filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
+    filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
 
     IntRect imageRect(IntPoint(), resultImage()->size());
     PassRefPtr<ImageData> imageData(resultImage()->getUnmultipliedImageData(imageRect));
diff --git a/WebCore/platform/graphics/filters/FEComposite.cpp b/WebCore/platform/graphics/filters/FEComposite.cpp
index 18df3b2..0bafc48 100644
--- a/WebCore/platform/graphics/filters/FEComposite.cpp
+++ b/WebCore/platform/graphics/filters/FEComposite.cpp
@@ -131,26 +131,26 @@ void FEComposite::apply(Filter* filter)
     FloatRect srcRect = FloatRect(0.f, 0.f, -1.f, -1.f);
     switch (m_type) {
     case FECOMPOSITE_OPERATOR_OVER:
-        filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
-        filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
+        filterContext->drawImageBuffer(m_in2->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
+        filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
         break;
     case FECOMPOSITE_OPERATOR_IN:
         filterContext->save();
-        filterContext->clipToImageBuffer(calculateDrawingRect(m_in2->scaledSubRegion()), m_in2->resultImage());
-        filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
+        filterContext->clipToImageBuffer(m_in->resultImage(), calculateDrawingRect(m_in2->scaledSubRegion()));
+        filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
         filterContext->restore();
         break;
     case FECOMPOSITE_OPERATOR_OUT:
-        filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
-        filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()), srcRect, CompositeDestinationOut);
+        filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()));
+        filterContext->drawImageBuffer(m_in2->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()), srcRect, CompositeDestinationOut);
         break;
     case FECOMPOSITE_OPERATOR_ATOP:
-        filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
-        filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeSourceAtop);
+        filterContext->drawImageBuffer(m_in2->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
+        filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeSourceAtop);
         break;
     case FECOMPOSITE_OPERATOR_XOR:
-        filterContext->drawImage(m_in2->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
-        filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeXOR);
+        filterContext->drawImageBuffer(m_in2->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in2->scaledSubRegion()));
+        filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, calculateDrawingRect(m_in->scaledSubRegion()), srcRect, CompositeXOR);
         break;
     case FECOMPOSITE_OPERATOR_ARITHMETIC: {
         IntRect effectADrawingRect = calculateDrawingIntRect(m_in->scaledSubRegion());
diff --git a/WebCore/platform/graphics/filters/SourceAlpha.cpp b/WebCore/platform/graphics/filters/SourceAlpha.cpp
index eb23814..37b0023 100644
--- a/WebCore/platform/graphics/filters/SourceAlpha.cpp
+++ b/WebCore/platform/graphics/filters/SourceAlpha.cpp
@@ -63,9 +63,9 @@ void SourceAlpha::apply(Filter* filter)
 
     setIsAlphaImage(true);
 
-    FloatRect imageRect(FloatPoint(), filter->sourceImage()->image()->size());
+    FloatRect imageRect(FloatPoint(), filter->sourceImage()->size());
     filterContext->save();
-    filterContext->clipToImageBuffer(imageRect, filter->sourceImage());
+    filterContext->clipToImageBuffer(filter->sourceImage(), imageRect);
     filterContext->fillRect(imageRect, Color::black, DeviceColorSpace);
     filterContext->restore();
 }
diff --git a/WebCore/platform/graphics/filters/SourceGraphic.cpp b/WebCore/platform/graphics/filters/SourceGraphic.cpp
index a1864d6..5730d34 100644
--- a/WebCore/platform/graphics/filters/SourceGraphic.cpp
+++ b/WebCore/platform/graphics/filters/SourceGraphic.cpp
@@ -60,7 +60,7 @@ void SourceGraphic::apply(Filter* filter)
     if (!filterContext)
         return;
 
-    filterContext->drawImage(filter->sourceImage()->image(), DeviceColorSpace, IntPoint());
+    filterContext->drawImageBuffer(filter->sourceImage(), DeviceColorSpace, IntPoint());
 }
 
 void SourceGraphic::dump()
diff --git a/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
index b798832..be1d278 100644
--- a/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
+++ b/WebCore/platform/graphics/mac/GraphicsContext3DMac.mm
@@ -307,15 +307,6 @@ void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* co
                   canvas->width(), canvas->height(), imageBuffer->context()->platformContext());
 }
 
-void GraphicsContext3D::beginPaint(CanvasRenderingContext* context)
-{
-    UNUSED_PARAM(context);
-}
-
-void GraphicsContext3D::endPaint()
-{
-}
-
 bool GraphicsContext3D::isGLES2Compliant() const
 {
     return false;
diff --git a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
index 273e2dd..d5e7b3f 100644
--- a/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsContext3DQt.cpp
@@ -512,15 +512,6 @@ void GraphicsContext3D::makeContextCurrent()
     m_internal->m_glWidget->makeCurrent();
 }
 
-void GraphicsContext3D::beginPaint(CanvasRenderingContext* context)
-{
-    paintRenderingResultsToCanvas();
-}
-
-void GraphicsContext3D::endPaint()
-{
-}
-
 void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* context)
 {
     m_internal->m_glWidget->makeCurrent();
diff --git a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
index 059fc96..5779b96 100644
--- a/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
+++ b/WebCore/platform/graphics/qt/GraphicsContextQt.cpp
@@ -1213,23 +1213,6 @@ void GraphicsContext::clipOutEllipseInRect(const IntRect& rect)
     }
 }
 
-void GraphicsContext::clipToImageBuffer(const FloatRect& floatRect, const ImageBuffer* image)
-{
-    if (paintingDisabled())
-        return;
-
-    QPixmap* nativeImage = image->image()->nativeImageForCurrentFrame();
-    if (!nativeImage)
-        return;
-
-    IntRect rect(floatRect);
-    QPixmap alphaMask = *nativeImage;
-    if (alphaMask.width() != rect.width() || alphaMask.height() != rect.height())
-        alphaMask = alphaMask.scaled(rect.width(), rect.height());
-
-    m_data->layers.push(new TransparencyLayer(m_data->p(), m_data->p()->transform().mapRect(rect), 1.0, alphaMask));
-}
-
 void GraphicsContext::addInnerRoundedRectClip(const IntRect& rect,
                                               int thickness)
 {
diff --git a/WebCore/platform/graphics/qt/ImageBufferData.h b/WebCore/platform/graphics/qt/ImageBufferData.h
index 222dabe..aa32253 100644
--- a/WebCore/platform/graphics/qt/ImageBufferData.h
+++ b/WebCore/platform/graphics/qt/ImageBufferData.h
@@ -26,6 +26,9 @@
 #ifndef ImageBufferData_h
 #define ImageBufferData_h
 
+#include "Image.h"
+#include <wtf/RefPtr.h>
+
 #include <QPainter>
 #include <QPixmap>
 
@@ -41,6 +44,7 @@ public:
 
     QPixmap m_pixmap;
     OwnPtr<QPainter> m_painter;
+    RefPtr<Image> m_image;
 };
 
 }  // namespace WebCore
diff --git a/WebCore/platform/graphics/qt/ImageBufferQt.cpp b/WebCore/platform/graphics/qt/ImageBufferQt.cpp
index 761a4fe..ed8f07c 100644
--- a/WebCore/platform/graphics/qt/ImageBufferQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageBufferQt.cpp
@@ -33,6 +33,7 @@
 #include "ImageData.h"
 #include "MIMETypeRegistry.h"
 #include "StillImageQt.h"
+#include "TransparencyLayer.h"
 #include <wtf/text/CString.h>
 
 #include <QBuffer>
@@ -74,6 +75,8 @@ ImageBufferData::ImageBufferData(const IntSize& size)
     brush.setColor(Qt::black);
     painter->setBrush(brush);
     painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
+    
+    m_data.m_image = StillImage::createForRendering(&m_data.m_pixmap);
 }
 
 ImageBuffer::ImageBuffer(const IntSize& size, ImageColorSpace, bool& success)
@@ -98,24 +101,50 @@ GraphicsContext* ImageBuffer::context() const
     return m_context.get();
 }
 
-Image* ImageBuffer::imageForRendering() const
+bool ImageBuffer::drawsUsingCopy() const
 {
-    if (!m_image)
-        m_image = StillImage::createForRendering(&m_data.m_pixmap);
+    return false;
+}
 
-    return m_image.get();
+PassRefPtr<Image> ImageBuffer::copyImage() const
+{
+    return StillImage::create(m_data.m_pixmap);
 }
 
-Image* ImageBuffer::image() const
+void ImageBuffer::draw(GraphicsContext* destContext, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect,
+                       CompositeOperator op, bool useLowQualityScale)
 {
-    if (!m_image) {
-        // It's assumed that if image() is called, the actual rendering to the
-        // GraphicsContext must be done.
-        ASSERT(context());
-        m_image = StillImage::create(m_data.m_pixmap);
-    }
+    if (destContext == context()) {
+        // We're drawing into our own buffer.  In order for this to work, we need to copy the source buffer first.
+        RefPtr<Image> copy = copyImage();
+        destContext->drawImage(copy.get(), DeviceColorSpace, destRect, srcRect, op, useLowQualityScale);
+    } else
+        destContext->drawImage(m_data.m_image.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
+}
+
+void ImageBuffer::drawPattern(GraphicsContext* destContext, const FloatRect& srcRect, const AffineTransform& patternTransform,
+                              const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
+{
+    if (destContext == context()) {
+        // We're drawing into our own buffer.  In order for this to work, we need to copy the source buffer first.
+        RefPtr<Image> copy = copyImage();
+        copy->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
+    } else
+        m_data.m_image->drawPattern(destContext, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
+}
+
+void ImageBuffer::clip(GraphicsContext* context, const FloatRect& floatRect)
+{
+    QPixmap* nativeImage = m_data.m_image->nativeImageForCurrentFrame();
+    if (!nativeImage)
+        return;
+
+    IntRect rect(floatRect);
+    QPixmap alphaMask = *nativeImage;
+    if (alphaMask.width() != rect.width() || alphaMask.height() != rect.height())
+        alphaMask = alphaMask.scaled(rect.width(), rect.height());
 
-    return m_image.get();
+    m_data->layers.push(new TransparencyLayer(m_data->p(), m_data->p()->transform().mapRect(rect), 1.0, alphaMask));
 }
 
 void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
diff --git a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
index f2a0a16..fe7f6ce 100644
--- a/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
+++ b/WebCore/platform/graphics/skia/GraphicsContextSkia.cpp
@@ -456,17 +456,6 @@ void GraphicsContext::clipPath(WindRule clipRule)
     platformContext()->clipPathAntiAliased(path);
 }
 
-void GraphicsContext::clipToImageBuffer(const FloatRect& rect,
-                                        const ImageBuffer* imageBuffer)
-{
-    if (paintingDisabled())
-        return;
-
-#if OS(LINUX) || OS(WINDOWS)
-    platformContext()->beginLayerClippedToImage(rect, imageBuffer);
-#endif
-}
-
 void GraphicsContext::concatCTM(const AffineTransform& affine)
 {
     if (paintingDisabled())
diff --git a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
index eaa91ec..a63eec5 100644
--- a/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
+++ b/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
@@ -87,20 +87,35 @@ GraphicsContext* ImageBuffer::context() const
     return m_context.get();
 }
 
-Image* ImageBuffer::image() const
+bool ImageBuffer::drawsUsingCopy() const
 {
-    if (!m_image) {
-        // This creates a COPY of the image and will cache that copy. This means
-        // that if subsequent operations take place on the context, neither the
-        // currently-returned image, nor the results of future image() calls,
-        // will contain that operation.
-        //
-        // This seems silly, but is the way the CG port works: image() is
-        // intended to be used only when rendering is "complete."
-        m_image = BitmapImageSingleFrameSkia::create(
-            *m_data.m_platformContext.bitmap());
-    }
-    return m_image.get();
+    return true;
+}
+
+PassRefPtr<Image> ImageBuffer::copyImage() const
+{
+    return BitmapImageSingleFrameSkia::create(*m_data.m_platformContext.bitmap());
+}
+
+void ImageBuffer::clip(GraphicsContext* context, const FloatRect& rect) const
+{
+#if OS(LINUX) || OS(WINDOWS)
+    context->platformContext()->beginLayerClippedToImage(rect, this);
+#endif
+}
+
+void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect,
+                       CompositeOperator op, bool useLowQualityScale)
+{
+    RefPtr<Image> imageCopy = copyImage();
+    context->drawImage(imageCopy.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
+}
+
+void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform,
+                              const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
+{
+    RefPtr<Image> imageCopy = copyImage();
+    imageCopy->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
 }
 
 void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
diff --git a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
index 4d5afd7..2428e7e 100644
--- a/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
+++ b/WebCore/platform/graphics/wx/GraphicsContextWx.cpp
@@ -378,11 +378,6 @@ void GraphicsContext::canvasClip(const Path& path)
     clip(path);
 }
 
-void GraphicsContext::clipToImageBuffer(const FloatRect&, const ImageBuffer*)
-{
-    notImplemented();
-}
-
 AffineTransform GraphicsContext::getCTM() const
 { 
 #if USE(WXGC)
diff --git a/WebCore/platform/graphics/wx/ImageBufferWx.cpp b/WebCore/platform/graphics/wx/ImageBufferWx.cpp
index 775e018..2522cbd 100644
--- a/WebCore/platform/graphics/wx/ImageBufferWx.cpp
+++ b/WebCore/platform/graphics/wx/ImageBufferWx.cpp
@@ -82,12 +82,36 @@ String ImageBuffer::toDataURL(const String&, const double*) const
     return String();
 }
 
-Image* ImageBuffer::image() const
+bool ImageBuffer::drawsUsingCopy() const
+{
+    return true;
+}
+
+PassRefPtr<Image> ImageBuffer::copyImage() const
 {
     notImplemented();
     return 0;
 }
 
+void ImageBuffer::clip(GraphicsContext*, const FloatRect&) const
+{
+    notImplemented();
+}
+
+void ImageBuffer::draw(GraphicsContext* context, ColorSpace styleColorSpace, const FloatRect& destRect, const FloatRect& srcRect,
+                       CompositeOperator op, bool useLowQualityScale)
+{
+    RefPtr<Image> imageCopy = copyImage();
+    context->drawImage(imageCopy.get(), styleColorSpace, destRect, srcRect, op, useLowQualityScale);
+}
+
+void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect, const AffineTransform& patternTransform,
+                              const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator op, const FloatRect& destRect)
+{
+    RefPtr<Image> imageCopy = copyImage();
+    imageCopy->drawPattern(context, srcRect, patternTransform, phase, styleColorSpace, op, destRect);
+}
+
 void ImageBuffer::platformTransformColorSpace(const Vector<int>&)
 {
     notImplemented();
diff --git a/WebCore/platform/mac/ScrollbarThemeMac.mm b/WebCore/platform/mac/ScrollbarThemeMac.mm
index 067f28f..bfa584a 100644
--- a/WebCore/platform/mac/ScrollbarThemeMac.mm
+++ b/WebCore/platform/mac/ScrollbarThemeMac.mm
@@ -396,7 +396,7 @@ bool ScrollbarThemeMac::paint(Scrollbar* scrollbar, GraphicsContext* context, co
             return true;
         
         HIThemeDrawTrack(&trackInfo, 0, imageBuffer->context()->platformContext(), kHIThemeOrientationNormal);
-        context->drawImage(imageBuffer->image(), DeviceColorSpace, scrollbar->frameRect().location());
+        context->drawImageBuffer(imageBuffer.get(), DeviceColorSpace, scrollbar->frameRect().location());
     }
 
     return true;
diff --git a/WebCore/rendering/RenderBoxModelObject.cpp b/WebCore/rendering/RenderBoxModelObject.cpp
index 9117ed8..78618d1 100644
--- a/WebCore/rendering/RenderBoxModelObject.cpp
+++ b/WebCore/rendering/RenderBoxModelObject.cpp
@@ -531,7 +531,7 @@ void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, co
         
         // The mask has been created.  Now we just need to clip to it.
         context->save();
-        context->clipToImageBuffer(maskRect, maskImage.get());
+        context->clipToImageBuffer(maskImage.get(), maskRect);
     }
     
     StyleImage* bg = bgLayer->image();
diff --git a/WebCore/rendering/RenderSVGResourceClipper.cpp b/WebCore/rendering/RenderSVGResourceClipper.cpp
index 60081dd..626a880 100644
--- a/WebCore/rendering/RenderSVGResourceClipper.cpp
+++ b/WebCore/rendering/RenderSVGResourceClipper.cpp
@@ -173,7 +173,7 @@ bool RenderSVGResourceClipper::applyClippingToContext(RenderObject* object, cons
     if (!clipperData->clipMaskImage)
         return false;
 
-    context->clipToImageBuffer(repaintRect, clipperData->clipMaskImage.get());
+    context->clipToImageBuffer(clipperData->clipMaskImage.get(), repaintRect);
     return true;
 }
 
diff --git a/WebCore/rendering/RenderSVGResourceFilter.cpp b/WebCore/rendering/RenderSVGResourceFilter.cpp
index 54abd1e..09e83f4 100644
--- a/WebCore/rendering/RenderSVGResourceFilter.cpp
+++ b/WebCore/rendering/RenderSVGResourceFilter.cpp
@@ -270,7 +270,7 @@ void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsCo
 #if !PLATFORM(CG)
             resultImage->transformColorSpace(LinearRGB, DeviceRGB);
 #endif
-            context->drawImage(resultImage->image(), object->style()->colorSpace(), lastEffect->subRegion());
+            context->drawImageBuffer(resultImage, object->style()->colorSpace(), lastEffect->subRegion());
         }
     }
 
diff --git a/WebCore/rendering/RenderSVGResourcePattern.cpp b/WebCore/rendering/RenderSVGResourcePattern.cpp
index 698a4d3..f4f5cf4 100644
--- a/WebCore/rendering/RenderSVGResourcePattern.cpp
+++ b/WebCore/rendering/RenderSVGResourcePattern.cpp
@@ -297,14 +297,15 @@ PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(PatternData* p
 
 void RenderSVGResourcePattern::buildPattern(PatternData* patternData, PassOwnPtr<ImageBuffer> tileImage) const
 {
-    if (!tileImage->image()) {
+    RefPtr<Image> copiedImage = tileImage->copyImage();
+    if (!copiedImage) {
         patternData->pattern = 0;
         return;
     }
-
-    IntRect tileRect = tileImage->image()->rect();
+    
+    IntRect tileRect = copiedImage->rect();
     if (tileRect.width() <= patternData->boundaries.width() && tileRect.height() <= patternData->boundaries.height()) {
-        patternData->pattern = Pattern::create(tileImage->image(), true, true);
+        patternData->pattern = Pattern::create(copiedImage, true, true);
         return;
     }
 
@@ -330,13 +331,13 @@ void RenderSVGResourcePattern::buildPattern(PatternData* patternData, PassOwnPtr
         newTileImageContext->translate(0, patternData->boundaries.height());
         for (int j = numX; j > 0; --j) {
             newTileImageContext->translate(patternData->boundaries.width(), 0);
-            newTileImageContext->drawImage(tileImage->image(), style()->colorSpace(), tileRect, tileRect);
+            newTileImageContext->drawImage(copiedImage.get(), style()->colorSpace(), tileRect, tileRect);
         }
         newTileImageContext->translate(-patternData->boundaries.width() * numX, 0);
     }
     newTileImageContext->restore();
 
-    patternData->pattern = Pattern::create(newTileImage->image(), true, true);
+    patternData->pattern = Pattern::create(newTileImage->copyImage(), true, true);
 }
 
 }
diff --git a/WebCore/rendering/RenderThemeMac.mm b/WebCore/rendering/RenderThemeMac.mm
index cc2ff1f..7982834 100644
--- a/WebCore/rendering/RenderThemeMac.mm
+++ b/WebCore/rendering/RenderThemeMac.mm
@@ -963,7 +963,8 @@ bool RenderThemeMac::paintProgressBar(RenderObject* renderObject, const PaintInf
         paintInfo.context->translate(2 * rect.x() + rect.width(), 0);
         paintInfo.context->scale(FloatSize(-1, 1));
     }
-    paintInfo.context->drawImage(imageBuffer->image(), DeviceColorSpace, rect.location());
+    
+    paintInfo.context->drawImageBuffer(imageBuffer.get(), DeviceColorSpace, rect.location());
 
     paintInfo.context->restore();
     return false;
diff --git a/WebCore/rendering/SVGImageBufferTools.cpp b/WebCore/rendering/SVGImageBufferTools.cpp
index 30b6bd2..5b45ccc 100644
--- a/WebCore/rendering/SVGImageBufferTools.cpp
+++ b/WebCore/rendering/SVGImageBufferTools.cpp
@@ -64,7 +64,7 @@ void SVGImageBufferTools::clipToImageBuffer(GraphicsContext* context, const Affi
     // The mask image has been created in the device coordinate space, as the image should not be scaled.
     // So the actual masking process has to be done in the device coordinate space as well.
     context->concatCTM(absoluteTransform.inverse());
-    context->clipToImageBuffer(absoluteTargetRect, imageBuffer);
+    context->clipToImageBuffer(imageBuffer, absoluteTargetRect);
     context->concatCTM(absoluteTransform);
 }
 
diff --git a/WebCore/svg/SVGFEImageElement.cpp b/WebCore/svg/SVGFEImageElement.cpp
index f481892..92534e8 100644
--- a/WebCore/svg/SVGFEImageElement.cpp
+++ b/WebCore/svg/SVGFEImageElement.cpp
@@ -137,7 +137,7 @@ PassRefPtr<FilterEffect> SVGFEImageElement::build(SVGFilterBuilder*)
         SVGRenderSupport::renderSubtreeToImage(m_targetImage.get(), renderer);
     }
 
-    return FEImage::create(m_targetImage ? m_targetImage->image() : m_cachedImage->image(), preserveAspectRatio());
+    return FEImage::create(m_targetImage ? m_targetImage->copyImage() : m_cachedImage->image(), preserveAspectRatio());
 }
 
 void SVGFEImageElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
diff --git a/WebCore/svg/graphics/SVGImage.cpp b/WebCore/svg/graphics/SVGImage.cpp
index 990e41f..6608c9e 100644
--- a/WebCore/svg/graphics/SVGImage.cpp
+++ b/WebCore/svg/graphics/SVGImage.cpp
@@ -221,12 +221,13 @@ NativeImagePtr SVGImage::nativeImageForCurrentFrame()
     if (!m_frameCache) {
         if (!m_page)
             return 0;
-        m_frameCache = ImageBuffer::create(size());
-        if (!m_frameCache) // failed to allocate image
+        OwnPtr<ImageBuffer> buffer = ImageBuffer::create(size());
+        if (!buffer) // failed to allocate image
             return 0;
-        draw(m_frameCache->context(), rect(), rect(), DeviceColorSpace, CompositeSourceOver);
+        draw(buffer->context(), rect(), rect(), DeviceColorSpace, CompositeSourceOver);
+        m_frameCache = buffer->copyImage();
     }
-    return m_frameCache->image()->nativeImageForCurrentFrame();
+    return m_frameCache->nativeImageForCurrentFrame();
 }
 
 bool SVGImage::dataChanged(bool allDataReceived)
diff --git a/WebCore/svg/graphics/SVGImage.h b/WebCore/svg/graphics/SVGImage.h
index 1936626..01eae71 100644
--- a/WebCore/svg/graphics/SVGImage.h
+++ b/WebCore/svg/graphics/SVGImage.h
@@ -33,7 +33,6 @@
 
 namespace WebCore {
 
-    class ImageBuffer;
     class Page;
     class SVGImageChromeClient;
     
@@ -72,7 +71,7 @@ namespace WebCore {
         
         OwnPtr<SVGImageChromeClient> m_chromeClient;
         OwnPtr<Page> m_page;
-        OwnPtr<ImageBuffer> m_frameCache;
+        RefPtr<Image> m_frameCache;
     };
 }
 
diff --git a/WebCore/svg/graphics/filters/SVGFEMerge.cpp b/WebCore/svg/graphics/filters/SVGFEMerge.cpp
index 649f670..11c7407 100644
--- a/WebCore/svg/graphics/filters/SVGFEMerge.cpp
+++ b/WebCore/svg/graphics/filters/SVGFEMerge.cpp
@@ -79,7 +79,7 @@ void FEMerge::apply(Filter* filter)
 
     for (unsigned i = 0; i < m_mergeInputs.size(); i++) {
         FloatRect destRect = calculateDrawingRect(m_mergeInputs[i]->scaledSubRegion());
-        filterContext->drawImage(m_mergeInputs[i]->resultImage()->image(), DeviceColorSpace, destRect);
+        filterContext->drawImageBuffer(m_mergeInputs[i]->resultImage(), DeviceColorSpace, destRect);
     }
 }
 
diff --git a/WebCore/svg/graphics/filters/SVGFEOffset.cpp b/WebCore/svg/graphics/filters/SVGFEOffset.cpp
index f6c1a3c..e12b8e0 100644
--- a/WebCore/svg/graphics/filters/SVGFEOffset.cpp
+++ b/WebCore/svg/graphics/filters/SVGFEOffset.cpp
@@ -91,7 +91,7 @@ void FEOffset::apply(Filter* filter)
                                   m_in->scaledSubRegion().width(),
                                   m_in->scaledSubRegion().height());
 
-    filterContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, dstRect);
+    filterContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, dstRect);
 }
 
 void FEOffset::dump()
diff --git a/WebCore/svg/graphics/filters/SVGFETile.cpp b/WebCore/svg/graphics/filters/SVGFETile.cpp
index fc172ee..56cbc1e 100644
--- a/WebCore/svg/graphics/filters/SVGFETile.cpp
+++ b/WebCore/svg/graphics/filters/SVGFETile.cpp
@@ -72,8 +72,8 @@ void FETile::apply(Filter* filter)
 
     OwnPtr<ImageBuffer> tileImage = ImageBuffer::create(tileRect.size());
     GraphicsContext* tileImageContext = tileImage->context();
-    tileImageContext->drawImage(m_in->resultImage()->image(), DeviceColorSpace, IntPoint());
-    RefPtr<Pattern> pattern = Pattern::create(tileImage->image(), true, true);
+    tileImageContext->drawImageBuffer(m_in->resultImage(), DeviceColorSpace, IntPoint());
+    RefPtr<Pattern> pattern = Pattern::create(tileImage->copyImage(), true, true);
 
     AffineTransform matrix;
     matrix.translate(m_in->scaledSubRegion().x() - scaledSubRegion().x(), m_in->scaledSubRegion().y() - scaledSubRegion().y());

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list