summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/cg/ImageBufferCG.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/graphics/cg/ImageBufferCG.cpp')
-rw-r--r--WebCore/platform/graphics/cg/ImageBufferCG.cpp89
1 files changed, 71 insertions, 18 deletions
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>