summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-25 08:15:24 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2011-05-25 08:15:24 -0700
commitfa91a01aee5d4a80ca6c80f722116b850f09996c (patch)
treef72740e60d3c3d4f0ab144e88c03d1f134944ce3 /Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
parent96f37d6d1b390f6690858789706ee6ec25bc1677 (diff)
parentfeebf8e7a79ad68b04a1a948e2b8078d6e5f0048 (diff)
downloadexternal_webkit-fa91a01aee5d4a80ca6c80f722116b850f09996c.zip
external_webkit-fa91a01aee5d4a80ca6c80f722116b850f09996c.tar.gz
external_webkit-fa91a01aee5d4a80ca6c80f722116b850f09996c.tar.bz2
Merge changes I78ff6a85,Ic85c6405,Ibf903baa,I3a0459db,I35140385,I54790419,I6bfe5d24,Ia9f39b83,I5bcecd5a,I1de96683,I543c6810,I8a5b0878,I0ae670bf,Ide4d58dc,I28ebaf3d,I499d6631,Ie5090e0d,I6d3e5f1f
* changes: Merge WebKit at r78450: Update ThirdPartyProject.prop Merge WebKit at r78450: Add new Font::canExpandAroundIdeographsInComplexText() Merge WebKit at r78450: Add new ChromeClient::selectItemAlignmentFollowsMenuWritingDirection() Merge WebKit at r78450: FrameLoaderClient::didRunInsecureContent() signature changed Merge WebKit at r78450: HTMLAreaElement::getRect() renamed Merge WebKit at r78450: FrameLoader::url() removed Merge WebKit at r78450: HTMLParserQuirks removed Merge WebKit at r78450: TextRun::padding() renamed Merge WebKit at r78450: Use new FontMetrics Merge WebKit at r78450: GraphicsContext current path removed Merge WebKit at r78450: TransformationMatrix multiply methods renamed and meaning changed Merge WebKit at r78450: FontCustomPlatformData::fontPlatformData() signature changed Merge WebKit at r78450: IntRect::bottom()/right() renamed Merge WebKit at r78450: Fix remaining conflicts Merge WebKit at r78450: Fix conflicts due to new ENABLE_WEB_ARCHIVE guard Merge WebKit at r78450: Fix conflicts in media controls Merge WebKit at r78450: Fix Makefiles Merge WebKit at r78450: Initial merge by git.
Diffstat (limited to 'Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp')
-rw-r--r--Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp121
1 files changed, 78 insertions, 43 deletions
diff --git a/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp b/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
index 2c489ef..2721523 100644
--- a/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
+++ b/Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp
@@ -2,11 +2,11 @@
* Copyright (c) 2008, Google Inc. All rights reserved.
* Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
* Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
@@ -16,7 +16,7 @@
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -162,12 +162,14 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable)
}
template <Multiply multiplied>
-PassRefPtr<ByteArray> getImageData(const IntRect& rect, const SkBitmap& bitmap,
+PassRefPtr<ByteArray> getImageData(const IntRect& rect, SkDevice& srcDevice,
const IntSize& size)
{
RefPtr<ByteArray> result = ByteArray::create(rect.width() * rect.height() * 4);
- if (bitmap.config() == SkBitmap::kNo_Config) {
+ SkBitmap::Config srcConfig = srcDevice.accessBitmap(false).config();
+
+ if (srcConfig == SkBitmap::kNo_Config) {
// This is an empty SkBitmap that could not be configured.
ASSERT(!size.width() || !size.height());
return result.release();
@@ -177,8 +179,8 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const SkBitmap& bitmap,
if (rect.x() < 0
|| rect.y() < 0
- || rect.right() > size.width()
- || rect.bottom() > size.height())
+ || rect.maxX() > size.width()
+ || rect.maxY() > size.height())
memset(data, 0, result->length());
int originX = rect.x();
@@ -187,12 +189,12 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const SkBitmap& bitmap,
destX = -originX;
originX = 0;
}
- int endX = rect.right();
+ int endX = rect.maxX();
if (endX > size.width())
endX = size.width();
int numColumns = endX - originX;
- if (numColumns <= 0)
+ if (numColumns <= 0)
return result.release();
int originY = rect.y();
@@ -201,38 +203,42 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const SkBitmap& bitmap,
destY = -originY;
originY = 0;
}
- int endY = rect.bottom();
+ int endY = rect.maxY();
if (endY > size.height())
endY = size.height();
int numRows = endY - originY;
- if (numRows <= 0)
+ if (numRows <= 0)
return result.release();
- ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config);
- SkAutoLockPixels bitmapLock(bitmap);
+ ASSERT(srcConfig == SkBitmap::kARGB_8888_Config);
unsigned destBytesPerRow = 4 * rect.width();
+
+ SkBitmap srcBitmap;
+ srcDevice.readPixels(SkIRect::MakeXYWH(originX, originY, numColumns, numRows), &srcBitmap);
+
unsigned char* destRow = data + destY * destBytesPerRow + destX * 4;
+ // Do conversion of byte order and alpha divide (if necessary)
for (int y = 0; y < numRows; ++y) {
- uint32_t* srcRow = bitmap.getAddr32(originX, originY + y);
+ SkPMColor* srcBitmapRow = srcBitmap.getAddr32(0, y);
for (int x = 0; x < numColumns; ++x) {
+ SkPMColor srcPMColor = srcBitmapRow[x];
unsigned char* destPixel = &destRow[x * 4];
if (multiplied == Unmultiplied) {
- SkColor color = srcRow[x];
- unsigned a = SkColorGetA(color);
- destPixel[0] = a ? SkColorGetR(color) * 255 / a : 0;
- destPixel[1] = a ? SkColorGetG(color) * 255 / a : 0;
- destPixel[2] = a ? SkColorGetB(color) * 255 / a : 0;
+ unsigned char a = SkGetPackedA32(srcPMColor);
+ destPixel[0] = a ? SkGetPackedR32(srcPMColor) * 255 / a : 0;
+ destPixel[1] = a ? SkGetPackedG32(srcPMColor) * 255 / a : 0;
+ destPixel[2] = a ? SkGetPackedB32(srcPMColor) * 255 / a : 0;
destPixel[3] = a;
} else {
// Input and output are both pre-multiplied, we just need to re-arrange the
// bytes from the bitmap format to RGBA.
- destPixel[0] = SkGetPackedR32(srcRow[x]);
- destPixel[1] = SkGetPackedG32(srcRow[x]);
- destPixel[2] = SkGetPackedB32(srcRow[x]);
- destPixel[3] = SkGetPackedA32(srcRow[x]);
+ destPixel[0] = SkGetPackedR32(srcPMColor);
+ destPixel[1] = SkGetPackedG32(srcPMColor);
+ destPixel[2] = SkGetPackedB32(srcPMColor);
+ destPixel[3] = SkGetPackedA32(srcPMColor);
}
}
destRow += destBytesPerRow;
@@ -244,18 +250,18 @@ PassRefPtr<ByteArray> getImageData(const IntRect& rect, const SkBitmap& bitmap,
PassRefPtr<ByteArray> ImageBuffer::getUnmultipliedImageData(const IntRect& rect) const
{
context()->platformContext()->syncSoftwareCanvas();
- return getImageData<Unmultiplied>(rect, *context()->platformContext()->bitmap(), m_size);
+ return getImageData<Unmultiplied>(rect, *context()->platformContext()->canvas()->getDevice(), m_size);
}
PassRefPtr<ByteArray> ImageBuffer::getPremultipliedImageData(const IntRect& rect) const
{
context()->platformContext()->syncSoftwareCanvas();
- return getImageData<Premultiplied>(rect, *context()->platformContext()->bitmap(), m_size);
+ return getImageData<Premultiplied>(rect, *context()->platformContext()->canvas()->getDevice(), m_size);
}
template <Multiply multiplied>
-void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint,
- const SkBitmap& bitmap, const IntSize& size)
+void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint,
+ SkDevice* dstDevice, const IntSize& size)
{
ASSERT(sourceRect.width() > 0);
ASSERT(sourceRect.height() > 0);
@@ -265,9 +271,9 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect&
ASSERT(destX >= 0);
ASSERT(destX < size.width());
ASSERT(originX >= 0);
- ASSERT(originX < sourceRect.right());
+ ASSERT(originX < sourceRect.maxX());
- int endX = destPoint.x() + sourceRect.right();
+ int endX = destPoint.x() + sourceRect.maxX();
ASSERT(endX <= size.width());
int numColumns = endX - destX;
@@ -277,21 +283,33 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect&
ASSERT(destY >= 0);
ASSERT(destY < size.height());
ASSERT(originY >= 0);
- ASSERT(originY < sourceRect.bottom());
+ ASSERT(originY < sourceRect.maxY());
- int endY = destPoint.y() + sourceRect.bottom();
+ int endY = destPoint.y() + sourceRect.maxY();
ASSERT(endY <= size.height());
int numRows = endY - destY;
- ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config);
- SkAutoLockPixels bitmapLock(bitmap);
-
unsigned srcBytesPerRow = 4 * sourceSize.width();
- const unsigned char* srcRow = source->data() + originY * srcBytesPerRow + originX * 4;
+ SkBitmap deviceBitmap = dstDevice->accessBitmap(true);
+ SkAutoLockPixels deviceAutoLock(deviceBitmap);
+ // If the device's bitmap doesn't have pixels we will make a temp and call writePixels on the device.
+ bool temporaryBitmap = !deviceBitmap.getPixels();
+ SkBitmap destBitmap;
+
+ if (temporaryBitmap) {
+ destBitmap.setConfig(SkBitmap::kARGB_8888_Config, numColumns, numRows, srcBytesPerRow);
+ if (!destBitmap.allocPixels())
+ CRASH();
+ } else
+ deviceBitmap.extractSubset(&destBitmap, SkIRect::MakeXYWH(destX, destY, numColumns, numRows));
+
+ // Whether we made a temporary or not destBitmap is always configured to be written at 0,0
+ SkAutoLockPixels destAutoLock(destBitmap);
+ const unsigned char* srcRow = source->data() + originY * srcBytesPerRow + originX * 4;
for (int y = 0; y < numRows; ++y) {
- uint32_t* destRow = bitmap.getAddr32(destX, destY + y);
+ SkPMColor* destRow = destBitmap.getAddr32(0, y);
for (int x = 0; x < numColumns; ++x) {
const unsigned char* srcPixel = &srcRow[x * 4];
if (multiplied == Unmultiplied) {
@@ -301,22 +319,26 @@ void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect&
unsigned char b = SkMulDiv255Ceiling(srcPixel[2], alpha);
destRow[x] = SkPackARGB32(alpha, r, g, b);
} else
- destRow[x] = SkPackARGB32(srcPixel[3], srcPixel[0],
- srcPixel[1], srcPixel[2]);
+ destRow[x] = SkPackARGB32(srcPixel[3], srcPixel[0], srcPixel[1], srcPixel[2]);
}
srcRow += srcBytesPerRow;
}
+
+ // If we used a temporary then write it to the device
+ if (temporaryBitmap)
+ dstDevice->writePixels(destBitmap, destX, destY);
}
void ImageBuffer::putUnmultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
{
- context()->platformContext()->prepareForSoftwareDraw();
- putImageData<Unmultiplied>(source, sourceSize, sourceRect, destPoint, *context()->platformContext()->bitmap(), m_size);
+ context()->platformContext()->syncSoftwareCanvas();
+ putImageData<Unmultiplied>(source, sourceSize, sourceRect, destPoint, context()->platformContext()->canvas()->getDevice(), m_size);
}
void ImageBuffer::putPremultipliedImageData(ByteArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint)
{
- putImageData<Premultiplied>(source, sourceSize, sourceRect, destPoint, *context()->platformContext()->bitmap(), m_size);
+ context()->platformContext()->syncSoftwareCanvas();
+ putImageData<Premultiplied>(source, sourceSize, sourceRect, destPoint, context()->platformContext()->canvas()->getDevice(), m_size);
}
String ImageBuffer::toDataURL(const String& mimeType, const double* quality) const
@@ -324,14 +346,27 @@ String ImageBuffer::toDataURL(const String& mimeType, const double* quality) con
ASSERT(MIMETypeRegistry::isSupportedImageMIMETypeForEncoding(mimeType));
Vector<unsigned char> encodedImage;
+ SkDevice* device = context()->platformContext()->canvas()->getDevice();
+ SkBitmap bitmap = device->accessBitmap(false);
+
+ // if we can't see the pixels directly, call readPixels() to get a copy.
+ // this could happen if the device is backed by a GPU.
+ bitmap.lockPixels(); // balanced by our destructor, or explicitly if getPixels() fails
+ if (!bitmap.getPixels()) {
+ bitmap.unlockPixels();
+ SkIRect bounds = SkIRect::MakeWH(device->width(), device->height());
+ if (!device->readPixels(bounds, &bitmap))
+ return "data:,";
+ }
+
if (mimeType == "image/jpeg") {
int compressionQuality = JPEGImageEncoder::DefaultCompressionQuality;
if (quality && *quality >= 0.0 && *quality <= 1.0)
compressionQuality = static_cast<int>(*quality * 100 + 0.5);
- if (!JPEGImageEncoder::encode(*context()->platformContext()->bitmap(), compressionQuality, &encodedImage))
+ if (!JPEGImageEncoder::encode(bitmap, compressionQuality, &encodedImage))
return "data:,";
} else {
- if (!PNGImageEncoder::encode(*context()->platformContext()->bitmap(), &encodedImage))
+ if (!PNGImageEncoder::encode(bitmap, &encodedImage))
return "data:,";
ASSERT(mimeType == "image/png");
}