diff options
author | Steve Block <steveblock@google.com> | 2011-05-25 08:15:24 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-05-25 08:15:24 -0700 |
commit | fa91a01aee5d4a80ca6c80f722116b850f09996c (patch) | |
tree | f72740e60d3c3d4f0ab144e88c03d1f134944ce3 /Source/WebCore/platform/graphics/skia/ImageBufferSkia.cpp | |
parent | 96f37d6d1b390f6690858789706ee6ec25bc1677 (diff) | |
parent | feebf8e7a79ad68b04a1a948e2b8078d6e5f0048 (diff) | |
download | external_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.cpp | 121 |
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"); } |