Bug 17269: Deobfuscate CanvasRenderingContext2D.cpp
authoroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 16 Feb 2008 06:00:20 +0000 (06:00 +0000)
committeroliver@apple.com <oliver@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 16 Feb 2008 06:00:20 +0000 (06:00 +0000)
Refactor CanvasRenderingContext2D::drawImage(HTMLCanvasElement) to remove evil ifdefs

Reviewed by Dan B.

Add logic draw(ImageBuffer*) method to GraphicsContext to handle
painting the source canvas content.

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

WebCore/ChangeLog
WebCore/html/CanvasRenderingContext2D.cpp
WebCore/html/HTMLCanvasElement.cpp
WebCore/html/HTMLCanvasElement.h
WebCore/platform/graphics/GraphicsContext.h
WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
WebCore/platform/graphics/cg/GraphicsContextCG.cpp
WebCore/platform/graphics/qt/GraphicsContextQt.cpp

index 64f0f26..f85ae22 100644 (file)
@@ -1,3 +1,27 @@
+2008-02-15  Oliver Hunt  <oliver@apple.com>
+
+        Reviewed by Dan B.
+
+        Bug 17269: Deobfuscate CanvasRenderingContext2D.cpp
+        Refactor CanvasRenderingContext2D::drawImage(HTMLCanvasElement) to remove evil ifdefs
+
+        Add logic draw(ImageBuffer*) method to GraphicsContext to handle
+        painting the source canvas content.
+
+        * html/CanvasRenderingContext2D.cpp:
+        (WebCore::CanvasRenderingContext2D::drawImage):
+        * html/HTMLCanvasElement.cpp:
+        (WebCore::HTMLCanvasElement::buffer):
+        * html/HTMLCanvasElement.h:
+        * platform/graphics/GraphicsContext.h:
+        * platform/graphics/cairo/GraphicsContextCairo.cpp:
+        (WebCore::GraphicsContext::drawImage):
+        * platform/graphics/cg/GraphicsContextCG.cpp:
+        (WebCore::GraphicsContext::paintBuffer):
+        (WebCore::GraphicsContext::drawImage):
+        * platform/graphics/qt/GraphicsContextQt.cpp:
+        (WebCore::GraphicsContext::drawImage):
+
 2008-02-15  Kevin Ollivier  <kevino@theolliviers.com>
 
         Reviewed by David Hyatt.
index ea01012..aab0c0b 100644 (file)
@@ -957,65 +957,12 @@ void CanvasRenderingContext2D::drawImage(HTMLCanvasElement* canvas, const FloatR
     FloatRect destRect = c->roundToDevicePixels(dstRect);
         
     // FIXME: Do this through platform-independent GraphicsContext API.
-#if PLATFORM(CG)
-    CGImageRef platformImage = canvas->createPlatformImage();
-    if (!platformImage)
+    ImageBuffer* buffer = canvas->buffer();
+    if (!buffer)
         return;
-
+    
     willDraw(destRect);
-
-    float iw = CGImageGetWidth(platformImage);
-    float ih = CGImageGetHeight(platformImage);
-    if (sourceRect.x() == 0 && sourceRect.y() == 0 && iw == sourceRect.width() && ih == sourceRect.height()) {
-        // Fast path, yay!
-        CGContextDrawImage(c->platformContext(), destRect, platformImage);
-    } else {
-        // Slow path, boo!
-        // Create a new bitmap of the appropriate size and then draw that into our context.
-
-        size_t csw = static_cast<size_t>(ceilf(sourceRect.width()));
-        size_t csh = static_cast<size_t>(ceilf(sourceRect.height()));
-
-        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
-        size_t bytesPerRow = csw * 4;
-        void* buffer = fastMalloc(csh * bytesPerRow);
-
-        CGContextRef clippedSourceContext = CGBitmapContextCreate(buffer, csw, csh,
-            8, bytesPerRow, colorSpace, kCGImageAlphaPremultipliedLast);
-        CGColorSpaceRelease(colorSpace);
-        CGContextTranslateCTM(clippedSourceContext, -sourceRect.x(), -sourceRect.y());
-        CGContextDrawImage(clippedSourceContext, CGRectMake(0, 0, iw, ih), platformImage);
-
-        CGImageRef clippedSourceImage = CGBitmapContextCreateImage(clippedSourceContext);
-        CGContextRelease(clippedSourceContext);
-
-        CGContextDrawImage(c->platformContext(), destRect, clippedSourceImage);
-        CGImageRelease(clippedSourceImage);
-        
-        fastFree(buffer);
-    }
-
-    CGImageRelease(platformImage);
-#elif PLATFORM(QT)
-    QPixmap px = canvas->createPlatformImage();
-    if (px.isNull())
-        return;
-    willDraw(dstRect);
-    QPainter* painter = static_cast<QPainter*>(c->platformContext());
-    painter->drawPixmap(dstRect, px, srcRect);
-#elif PLATFORM(CAIRO)
-    cairo_surface_t* image = canvas->createPlatformImage();
-    if (!image)
-        return;
-    willDraw(dstRect);
-    cairo_t* cr = c->platformContext();
-    cairo_save(cr);
-    cairo_set_source_surface(cr, image, srcRect.x(), srcRect.y());
-    cairo_surface_destroy(image);
-    cairo_rectangle(cr, dstRect.x(), dstRect.y(), dstRect.width(), dstRect.height());
-    cairo_fill(cr);
-    cairo_restore(cr);
-#endif
+    c->drawImage(buffer, sourceRect, destRect);
 }
 
 // FIXME: Why isn't this just another overload of drawImage? Why have a different name?
index 37fb021..b4aade2 100644 (file)
@@ -212,9 +212,14 @@ void HTMLCanvasElement::createDrawingContext() const
 
 GraphicsContext* HTMLCanvasElement::drawingContext() const
 {
+    return buffer()->context();
+}
+
+ImageBuffer* HTMLCanvasElement::buffer() const
+{
     if (!m_createdDrawingContext)
         createDrawingContext();
-    return m_data->context();
+    return m_data.get();
 }
 
 #if PLATFORM(CG)
index 1895c40..348b860 100644 (file)
@@ -75,6 +75,7 @@ public:
 
     GraphicsContext* drawingContext() const;
 
+    ImageBuffer* buffer() const; 
 #if PLATFORM(CG)
     CGImageRef createPlatformImage() const;
 #elif PLATFORM(QT)
index 075caf4..732c8e3 100644 (file)
@@ -145,11 +145,13 @@ namespace WebCore {
         void drawImage(Image*, const IntRect& destRect, const IntRect& srcRect, CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
         void drawImage(Image*, const FloatRect& destRect, const FloatRect& srcRect = FloatRect(0, 0, -1, -1),
                        CompositeOperator = CompositeSourceOver, bool useLowQualityScale = false);
+        void drawImage(ImageBuffer*, const FloatRect& srcRect, const FloatRect& destRect);
         void drawTiledImage(Image*, const IntRect& destRect, const IntPoint& srcPoint, const IntSize& tileSize,
                        CompositeOperator = CompositeSourceOver);
         void drawTiledImage(Image*, const IntRect& destRect, const IntRect& srcRect, 
                             Image::TileRule hRule = Image::StretchTile, Image::TileRule vRule = Image::StretchTile,
                             CompositeOperator = CompositeSourceOver);
+
         void paintBuffer(ImageBuffer*, const IntRect&);
 #if PLATFORM(CG)
         void setUseLowQualityImageInterpolation(bool = true);
index 2f81c0b..9baf780 100644 (file)
@@ -909,6 +909,16 @@ void GraphicsContext::paintBuffer(ImageBuffer* buffer, const IntRect& r)
     cairo_restore(cr);
 }
 
+void GraphicsContext::drawImage(ImageBuffer* buffer, const FloatRect& srcRect, const FloatRect& destRect)
+{
+    cairo_surface_flush(m_data->surface());    
+    cairo_save(platformContext());
+    cairo_set_source_surface(platformContext(), m_data->surface(), srcRect.x(), srcRect.y());
+    cairo_rectangle(platformContext(), dstRect.x(), dstRect.y(), dstRect.width(), dstRect.height());
+    cairo_fill(platformContext());
+    cairo_restore(platformContext());
+}
+
 } // namespace WebCore
 
 #endif // PLATFORM(CAIRO)
index 289e399..de546ac 100644 (file)
@@ -36,6 +36,7 @@
 #include <CoreGraphics/CGBitmapContext.h>
 #include <CoreGraphics/CGPDFContext.h>
 #include <wtf/MathExtras.h>
+#include <wtf/OwnArrayPtr.h>
 #include <wtf/RetainPtr.h>
 
 using namespace std;
@@ -930,14 +931,46 @@ void GraphicsContext::setCompositeOperation(CompositeOperator mode)
 
 void GraphicsContext::paintBuffer(ImageBuffer* buffer, const IntRect& r)
 {
-    if (paintingDisabled())
+    CGContextRef context = buffer->context()->platformContext();
+    if (!context)
         return;
+    CGContextFlush(context);
+    if (CGImageRef image = CGBitmapContextCreateImage(context)) {
+        CGContextDrawImage(platformContext(), roundToDevicePixels(r), image);
+        CGImageRelease(image);
+    }
+}
 
-    RetainPtr<CGImageRef> image(AdoptCF, CGBitmapContextCreateImage(buffer->context()->platformContext()));
-    if (!image)
-        return;
-    CGContextDrawImage(platformContext(), roundToDevicePixels(r), image.get());
+void GraphicsContext::drawImage(ImageBuffer* buffer, const FloatRect& srcRect, const FloatRect& destRect)
+{
+    CGContextRef context = buffer->context()->platformContext();
+    CGContextFlush(context);
+    RetainPtr<CGImageRef> image(AdoptCF, CGBitmapContextCreateImage(context));
+    float iw = CGImageGetWidth(image.get());
+    float ih = CGImageGetHeight(image.get());
+    if (srcRect.x() == 0 && srcRect.y() == 0 && iw == srcRect.width() && ih == srcRect.height()) {
+        // Fast path, yay!
+        CGContextDrawImage(platformContext(), destRect, image.get());
+    } else {
+        // Slow path, boo!
+        // FIXME: We can do this without creating a separate image
+        
+        size_t csw = static_cast<size_t>(ceilf(srcRect.width()));
+        size_t csh = static_cast<size_t>(ceilf(srcRect.height()));
+        
+        RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
+        size_t bytesPerRow = csw * 4;
+        OwnArrayPtr<char> buffer(new char[csh * bytesPerRow]);
+        RetainPtr<CGContextRef> clippedSourceContext(AdoptCF, CGBitmapContextCreate(buffer.get(), csw, csh,
+                                                                8, bytesPerRow, colorSpace.get(), kCGImageAlphaPremultipliedLast));
+        CGContextTranslateCTM(clippedSourceContext.get(), -srcRect.x(), -srcRect.y());
+        CGContextDrawImage(clippedSourceContext.get(), CGRectMake(0, 0, iw, ih), image.get());
+        
+        RetainPtr<CGImageRef> clippedSourceImage(AdoptCF, CGBitmapContextCreateImage(clippedSourceContext.get()));
+        
+        CGContextDrawImage(platformContext(), destRect, clippedSourceImage.get());
+    }
 }
-    
+
 }
 
index 0d91630..6f97a97 100644 (file)
@@ -929,6 +929,15 @@ void GraphicsContext::paintBuffer(ImageBuffer* buffer, const IntRect& r)
     painter->setBackground(currentBackground);
 }
 
+void GraphicsContext::drawImage(ImageBuffer* buffer, const FloatRect& srcRect, const FloatRect& destRect)
+{
+    QPainter* painter = static_cast<QPainter*>(platformContext());
+    QPixmap px = *buffer->pixmap();
+    if (px.isNull())
+        return;
+    painter->drawPixmap(dstRect, px, srcRect);
+}
+
 }
 
 // vim: ts=4 sw=4 et