summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/skia/src/core/SkBitmapDevice.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/skia/src/core/SkBitmapDevice.cpp')
-rw-r--r--chromium/third_party/skia/src/core/SkBitmapDevice.cpp319
1 files changed, 194 insertions, 125 deletions
diff --git a/chromium/third_party/skia/src/core/SkBitmapDevice.cpp b/chromium/third_party/skia/src/core/SkBitmapDevice.cpp
index 1668618cf74..0f3cc2be501 100644
--- a/chromium/third_party/skia/src/core/SkBitmapDevice.cpp
+++ b/chromium/third_party/skia/src/core/SkBitmapDevice.cpp
@@ -10,48 +10,95 @@
#include "SkDraw.h"
#include "SkRasterClip.h"
#include "SkShader.h"
+#include "SkSurface.h"
#define CHECK_FOR_ANNOTATION(paint) \
do { if (paint.getAnnotation()) { return; } } while (0)
-SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap)
- : fBitmap(bitmap) {
- SkASSERT(SkBitmap::kARGB_4444_Config != bitmap.config());
+static bool valid_for_bitmap_device(const SkImageInfo& info,
+ SkAlphaType* newAlphaType) {
+ if (info.width() < 0 || info.height() < 0) {
+ return false;
+ }
+
+ // TODO: can we stop supporting kUnknown in SkBitmkapDevice?
+ if (kUnknown_SkColorType == info.colorType()) {
+ if (newAlphaType) {
+ *newAlphaType = kIgnore_SkAlphaType;
+ }
+ return true;
+ }
+
+ switch (info.alphaType()) {
+ case kPremul_SkAlphaType:
+ case kOpaque_SkAlphaType:
+ break;
+ default:
+ return false;
+ }
+
+ SkAlphaType canonicalAlphaType = info.alphaType();
+
+ switch (info.colorType()) {
+ case kAlpha_8_SkColorType:
+ break;
+ case kRGB_565_SkColorType:
+ canonicalAlphaType = kOpaque_SkAlphaType;
+ break;
+ case kN32_SkColorType:
+ break;
+ default:
+ return false;
+ }
+
+ if (newAlphaType) {
+ *newAlphaType = canonicalAlphaType;
+ }
+ return true;
+}
+
+SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap) : fBitmap(bitmap) {
+ SkASSERT(valid_for_bitmap_device(bitmap.info(), NULL));
}
SkBitmapDevice::SkBitmapDevice(const SkBitmap& bitmap, const SkDeviceProperties& deviceProperties)
: SkBaseDevice(deviceProperties)
- , fBitmap(bitmap) {
+ , fBitmap(bitmap)
+{
+ SkASSERT(valid_for_bitmap_device(bitmap.info(), NULL));
}
-SkBitmapDevice::SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque) {
- fBitmap.setConfig(config, width, height, 0, isOpaque ?
- kOpaque_SkAlphaType : kPremul_SkAlphaType);
- if (!fBitmap.allocPixels()) {
- fBitmap.setConfig(config, 0, 0, 0, isOpaque ?
- kOpaque_SkAlphaType : kPremul_SkAlphaType);
+SkBitmapDevice* SkBitmapDevice::Create(const SkImageInfo& origInfo,
+ const SkDeviceProperties* props) {
+ SkImageInfo info = origInfo;
+ if (!valid_for_bitmap_device(info, &info.fAlphaType)) {
+ return NULL;
}
- if (!isOpaque) {
- fBitmap.eraseColor(SK_ColorTRANSPARENT);
- }
-}
-SkBitmapDevice::SkBitmapDevice(SkBitmap::Config config, int width, int height, bool isOpaque,
- const SkDeviceProperties& deviceProperties)
- : SkBaseDevice(deviceProperties) {
+ SkBitmap bitmap;
- fBitmap.setConfig(config, width, height, 0, isOpaque ?
- kOpaque_SkAlphaType : kPremul_SkAlphaType);
- if (!fBitmap.allocPixels()) {
- fBitmap.setConfig(config, 0, 0, 0, isOpaque ?
- kOpaque_SkAlphaType : kPremul_SkAlphaType);
+ if (kUnknown_SkColorType == info.colorType()) {
+ if (!bitmap.setInfo(info)) {
+ return NULL;
+ }
+ } else {
+ if (!bitmap.allocPixels(info)) {
+ return NULL;
+ }
+ if (!bitmap.info().isOpaque()) {
+ bitmap.eraseColor(SK_ColorTRANSPARENT);
+ }
}
- if (!isOpaque) {
- fBitmap.eraseColor(SK_ColorTRANSPARENT);
+
+ if (props) {
+ return SkNEW_ARGS(SkBitmapDevice, (bitmap, *props));
+ } else {
+ return SkNEW_ARGS(SkBitmapDevice, (bitmap));
}
}
-SkBitmapDevice::~SkBitmapDevice() {
+SkImageInfo SkBitmapDevice::imageInfo() const {
+ return fBitmap.info();
}
void SkBitmapDevice::replaceBitmapBackendForRasterSurface(const SkBitmap& bm) {
@@ -61,18 +108,8 @@ void SkBitmapDevice::replaceBitmapBackendForRasterSurface(const SkBitmap& bm) {
fBitmap.lockPixels();
}
-SkBaseDevice* SkBitmapDevice::onCreateCompatibleDevice(SkBitmap::Config config,
- int width, int height,
- bool isOpaque,
- Usage usage) {
- SkBitmapDevice* device = SkNEW_ARGS(SkBitmapDevice,(config, width, height,
- isOpaque, this->getDeviceProperties()));
- // Check if allocation failed and delete device if it did fail
- if ((device->width() != width) || (device->height() != height)) {
- SkDELETE(device);
- device = NULL;
- }
- return device;
+SkBaseDevice* SkBitmapDevice::onCreateDevice(const SkImageInfo& info, Usage usage) {
+ return SkBitmapDevice::Create(info, &this->getDeviceProperties());
}
void SkBitmapDevice::lockPixels() {
@@ -95,113 +132,127 @@ const SkBitmap& SkBitmapDevice::onAccessBitmap() {
return fBitmap;
}
-bool SkBitmapDevice::canHandleImageFilter(SkImageFilter*) {
+bool SkBitmapDevice::canHandleImageFilter(const SkImageFilter*) {
return false;
}
-bool SkBitmapDevice::filterImage(SkImageFilter* filter, const SkBitmap& src,
- const SkMatrix& ctm, SkBitmap* result,
+bool SkBitmapDevice::filterImage(const SkImageFilter* filter, const SkBitmap& src,
+ const SkImageFilter::Context& ctx, SkBitmap* result,
SkIPoint* offset) {
return false;
}
-bool SkBitmapDevice::allowImageFilter(SkImageFilter*) {
+bool SkBitmapDevice::allowImageFilter(const SkImageFilter*) {
return true;
}
-bool SkBitmapDevice::onReadPixels(const SkBitmap& bitmap,
- int x, int y,
- SkCanvas::Config8888 config8888) {
- SkASSERT(SkBitmap::kARGB_8888_Config == bitmap.config());
- SkASSERT(!bitmap.isNull());
- SkASSERT(SkIRect::MakeWH(this->width(), this->height()).contains(SkIRect::MakeXYWH(x, y,
- bitmap.width(),
- bitmap.height())));
+void* SkBitmapDevice::onAccessPixels(SkImageInfo* info, size_t* rowBytes) {
+ if (fBitmap.getPixels()) {
+ *info = fBitmap.info();
+ *rowBytes = fBitmap.rowBytes();
+ return fBitmap.getPixels();
+ }
+ return NULL;
+}
+
+static void rect_memcpy(void* dst, size_t dstRB, const void* src, size_t srcRB, size_t bytesPerRow,
+ int rowCount) {
+ SkASSERT(bytesPerRow <= srcRB);
+ SkASSERT(bytesPerRow <= dstRB);
+ for (int i = 0; i < rowCount; ++i) {
+ memcpy(dst, src, bytesPerRow);
+ dst = (char*)dst + dstRB;
+ src = (const char*)src + srcRB;
+ }
+}
- SkIRect srcRect = SkIRect::MakeXYWH(x, y, bitmap.width(), bitmap.height());
- const SkBitmap& src = this->accessBitmap(false);
+#include "SkConfig8888.h"
- SkBitmap subset;
- if (!src.extractSubset(&subset, srcRect)) {
+static bool copy_pixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
+ const SkImageInfo& srcInfo, const void* srcPixels, size_t srcRowBytes) {
+ if (srcInfo.dimensions() != dstInfo.dimensions()) {
return false;
}
- if (SkBitmap::kARGB_8888_Config != subset.config()) {
- // It'd be preferable to do this directly to bitmap.
- subset.copyTo(&subset, SkBitmap::kARGB_8888_Config);
+ if (4 == srcInfo.bytesPerPixel() && 4 == dstInfo.bytesPerPixel()) {
+ SkDstPixelInfo dstPI;
+ dstPI.fColorType = dstInfo.colorType();
+ dstPI.fAlphaType = dstInfo.alphaType();
+ dstPI.fPixels = dstPixels;
+ dstPI.fRowBytes = dstRowBytes;
+
+ SkSrcPixelInfo srcPI;
+ srcPI.fColorType = srcInfo.colorType();
+ srcPI.fAlphaType = srcInfo.alphaType();
+ srcPI.fPixels = srcPixels;
+ srcPI.fRowBytes = srcRowBytes;
+
+ return srcPI.convertPixelsTo(&dstPI, srcInfo.width(), srcInfo.height());
}
- SkAutoLockPixels alp(bitmap);
- uint32_t* bmpPixels = reinterpret_cast<uint32_t*>(bitmap.getPixels());
- SkCopyBitmapToConfig8888(bmpPixels, bitmap.rowBytes(), config8888, subset);
- return true;
+ if (srcInfo.colorType() == dstInfo.colorType()) {
+ switch (srcInfo.colorType()) {
+ case kRGB_565_SkColorType:
+ case kAlpha_8_SkColorType:
+ break;
+ case kARGB_4444_SkColorType:
+ if (srcInfo.alphaType() != dstInfo.alphaType()) {
+ return false;
+ }
+ break;
+ default:
+ return false;
+ }
+ rect_memcpy(dstPixels, dstRowBytes, srcPixels, srcRowBytes,
+ srcInfo.width() * srcInfo.bytesPerPixel(), srcInfo.height());
+ }
+ // TODO: add support for more conversions as needed
+ return false;
}
-void SkBitmapDevice::writePixels(const SkBitmap& bitmap,
- int x, int y,
- SkCanvas::Config8888 config8888) {
- if (bitmap.isNull() || bitmap.getTexture()) {
- return;
+bool SkBitmapDevice::onWritePixels(const SkImageInfo& srcInfo, const void* srcPixels,
+ size_t srcRowBytes, int x, int y) {
+ // since we don't stop creating un-pixeled devices yet, check for no pixels here
+ if (NULL == fBitmap.getPixels()) {
+ return false;
}
- const SkBitmap* sprite = &bitmap;
- // check whether we have to handle a config8888 that doesn't match SkPMColor
- if (SkBitmap::kARGB_8888_Config == bitmap.config() &&
- SkCanvas::kNative_Premul_Config8888 != config8888 &&
- kPMColorAlias != config8888) {
-
- // We're going to have to convert from a config8888 to the native config
- // First we clip to the device bounds.
- SkBitmap dstBmp = this->accessBitmap(true);
- SkIRect spriteRect = SkIRect::MakeXYWH(x, y,
- bitmap.width(), bitmap.height());
- SkIRect devRect = SkIRect::MakeWH(dstBmp.width(), dstBmp.height());
- if (!spriteRect.intersect(devRect)) {
- return;
- }
- // write directly to the device if it has pixels and is SkPMColor
- bool drawSprite;
- if (SkBitmap::kARGB_8888_Config == dstBmp.config() && !dstBmp.isNull()) {
- // we can write directly to the dst when doing the conversion
- dstBmp.extractSubset(&dstBmp, spriteRect);
- drawSprite = false;
- } else {
- // we convert to a temporary bitmap and draw that as a sprite
- dstBmp.setConfig(SkBitmap::kARGB_8888_Config,
- spriteRect.width(),
- spriteRect.height());
- if (!dstBmp.allocPixels()) {
- return;
- }
- drawSprite = true;
- }
+ SkImageInfo dstInfo = fBitmap.info();
+ dstInfo.fWidth = srcInfo.width();
+ dstInfo.fHeight = srcInfo.height();
- // copy pixels to dstBmp and convert from config8888 to native config.
- SkAutoLockPixels alp(bitmap);
- uint32_t* srcPixels = bitmap.getAddr32(spriteRect.fLeft - x,
- spriteRect.fTop - y);
- SkCopyConfig8888ToBitmap(dstBmp,
- srcPixels,
- bitmap.rowBytes(),
- config8888);
-
- if (drawSprite) {
- // we've clipped the sprite when we made a copy
- x = spriteRect.fLeft;
- y = spriteRect.fTop;
- sprite = &dstBmp;
- } else {
- return;
- }
+ void* dstPixels = fBitmap.getAddr(x, y);
+ size_t dstRowBytes = fBitmap.rowBytes();
+
+ if (copy_pixels(dstInfo, dstPixels, dstRowBytes, srcInfo, srcPixels, srcRowBytes)) {
+ fBitmap.notifyPixelsChanged();
+ return true;
+ }
+ return false;
+}
+
+bool SkBitmapDevice::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, size_t dstRowBytes,
+ int x, int y) {
+ // since we don't stop creating un-pixeled devices yet, check for no pixels here
+ if (NULL == fBitmap.getPixels()) {
+ return false;
}
- SkPaint paint;
- paint.setXfermodeMode(SkXfermode::kSrc_Mode);
- SkRasterClip clip(SkIRect::MakeWH(fBitmap.width(), fBitmap.height()));
- SkDraw draw;
- draw.fRC = &clip;
- draw.fClip = &clip.bwRgn();
- draw.fBitmap = &fBitmap; // canvas should have already called accessBitmap
- draw.fMatrix = &SkMatrix::I();
- this->drawSprite(draw, *sprite, x, y, paint);
+ SkImageInfo srcInfo = fBitmap.info();
+
+ // perhaps can relax these in the future
+ if (4 != dstInfo.bytesPerPixel()) {
+ return false;
+ }
+ if (4 != srcInfo.bytesPerPixel()) {
+ return false;
+ }
+
+ srcInfo.fWidth = dstInfo.width();
+ srcInfo.fHeight = dstInfo.height();
+
+ const void* srcPixels = fBitmap.getAddr(x, y);
+ const size_t srcRowBytes = fBitmap.rowBytes();
+
+ return copy_pixels(dstInfo, dstPixels, dstRowBytes, srcInfo, srcPixels, srcRowBytes);
}
///////////////////////////////////////////////////////////////////////////////
@@ -330,11 +381,11 @@ void SkBitmapDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
// construct a shader, so we can call drawRect with the dst
SkShader* s = SkShader::CreateBitmapShader(*bitmapPtr,
SkShader::kClamp_TileMode,
- SkShader::kClamp_TileMode);
+ SkShader::kClamp_TileMode,
+ &matrix);
if (NULL == s) {
return;
}
- s->setLocalMatrix(matrix);
SkPaint paintWithShader(paint);
paintWithShader.setStyle(SkPaint::kFill_Style);
@@ -384,6 +435,24 @@ void SkBitmapDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
draw.drawSprite(src, x, y, paint);
}
+SkSurface* SkBitmapDevice::newSurface(const SkImageInfo& info) {
+ return SkSurface::NewRaster(info);
+}
+
+const void* SkBitmapDevice::peekPixels(SkImageInfo* info, size_t* rowBytes) {
+ const SkImageInfo bmInfo = fBitmap.info();
+ if (fBitmap.getPixels() && (kUnknown_SkColorType != bmInfo.colorType())) {
+ if (info) {
+ *info = bmInfo;
+ }
+ if (rowBytes) {
+ *rowBytes = fBitmap.rowBytes();
+ }
+ return fBitmap.getPixels();
+ }
+ return NULL;
+}
+
///////////////////////////////////////////////////////////////////////////////
bool SkBitmapDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
@@ -392,7 +461,7 @@ bool SkBitmapDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) {
return false;
}
- if (SkBitmap::kARGB_8888_Config != fBitmap.config() ||
+ if (kN32_SkColorType != fBitmap.colorType() ||
paint.getRasterizer() ||
paint.getPathEffect() ||
paint.isFakeBoldText() ||