+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.
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?
}
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)
GraphicsContext* drawingContext() const;
+ ImageBuffer* buffer() const;
#if PLATFORM(CG)
CGImageRef createPlatformImage() const;
#elif PLATFORM(QT)
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);
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)
#include <CoreGraphics/CGBitmapContext.h>
#include <CoreGraphics/CGPDFContext.h>
#include <wtf/MathExtras.h>
+#include <wtf/OwnArrayPtr.h>
#include <wtf/RetainPtr.h>
using namespace std;
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());
+ }
}
-
+
}
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