Override 32BPP format in SkCanvas::readPixels

Review URL: http://codereview.appspot.com/5330073/



git-svn-id: http://skia.googlecode.com/svn/trunk@2600 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bsalomon@google.com 2011-11-03 20:29:47 +00:00
Родитель 15356a68b2
Коммит 6850eab42b
9 изменённых файлов: 426 добавлений и 86 удалений

Просмотреть файл

@ -105,37 +105,76 @@ public:
///////////////////////////////////////////////////////////////////////////
/**
* This enum can be used with readPixels to perform a readback into an 8888
* format other than Skia's native format (SkPMColor). There are three byte
* orders supported: native, BGRA, and RGBA. Each has a premultiplied and
* unpremultiplied variant. Unlike the other 8888 configs, the native 8888
* config is defined by shift values rather than byte order. The conversion
* from the native config to a byte order must consider endianness.
*/
enum Config8888 {
/**
* Skia's native order specified by:
* SK_A32_SHIFT, SK_R32_SHIFT, SK_G32_SHIFT, and SK_B32_SHIFT
*
* kNative_Premul_Config8888 is equivalent to SkPMColor
* kNative_Unpremul_Config8888 has the same component order as SkPMColor
* but is not premultiplied.
*/
kNative_Premul_Config8888,
kNative_Unpremul_Config8888,
/**
* low byte to high byte: B, G, R, A.
*/
kBGRA_Premul_Config8888,
kBGRA_Unpremul_Config8888,
/**
* low byte to high byte: R, G, B, A.
*/
kRGBA_Premul_Config8888,
kRGBA_Unpremul_Config8888,
};
/**
* On success (returns true), copy the canvas pixels into the bitmap.
* On failure, the bitmap parameter is left unchanged and false is
* returned.
*
* If the canvas is backed by a non-raster device (e.g. PDF) then
* readPixels will fail.
* The canvas' pixels are converted to the bitmap's config. The only
* supported config is kARGB_8888_Config, though this is likely to be
* relaxed in the future. The meaning of config kARGB_8888_Config is
* modified by the enum param config8888. The default value interprets
* kARGB_8888_Config as SkPMColor
*
* If the bitmap has pixels already allocated, the canvas pixels will be
* written there. If not, bitmap->allocPixels() will be called
* automatically. If the bitmap is backed by a texture readPixels will
* fail.
*
* The canvas' pixels are converted to the bitmap's config. The only
* supported config is kARGB_8888_Config, though this may be relaxed in
* future.
*
* The actual pixels written is the intersection of the canvas' bounds, and
* the rectangle formed by the bitmap's width,height and the specified x,y.
* If bitmap pixels extend outside of that intersection, they will not be
* modified.
*
* Example that reads the entire canvas into a bitmap:
* SkISize size = canvas->getDeviceSize();
* bitmap->setConfig(SkBitmap::kARGB_8888_Config, size.fWidth,
* size.fHeight);
* if (canvas->readPixels(bitmap, 0, 0)) {
* // use the pixels
* }
* Other failure conditions:
* * If the canvas is backed by a non-raster device (e.g. PDF) then
* readPixels will fail.
* * If bitmap is texture-backed then readPixels will fail. (This may be
* relaxed in the future.)
*
* Example that reads the entire canvas into a bitmap using the native
* SkPMColor:
* SkISize size = canvas->getDeviceSize();
* bitmap->setConfig(SkBitmap::kARGB_8888_Config, size.fWidth,
* size.fHeight);
* if (canvas->readPixels(bitmap, 0, 0)) {
* // use the pixels
* }
*/
bool readPixels(SkBitmap* bitmap, int x, int y);
bool readPixels(SkBitmap* bitmap,
int x, int y,
Config8888 config8888 = kNative_Premul_Config8888);
/**
* DEPRECATED: This will be removed as soon as webkit is no longer relying

Просмотреть файл

@ -107,26 +107,8 @@ public:
const SkBitmap& accessBitmap(bool changePixels);
/**
* Copy the pixels from the device into bitmap. Returns true on success.
* If false is returned, then the bitmap parameter is left unchanged. The
* rectangle read is defined by x, y and the bitmap's width and height.
*
* If the bitmap has pixels allocated the canvas will write directly to
* into that memory (if the call succeeds).
*
* The read is clipped to the device bounds. If bitmap pixels were
* preallocated then pixels outside the clip are left unmodified. If the
* call allocates bitmap pixels then pixels outside the clip will be
* uninitialized.
*
* Currently bitmap must have kARGB_8888_Config or readPixels will fail.
* This will likely be relaxed in the future.
*
* The bitmap parameter is not modified if the call fails.
*/
bool readPixels(SkBitmap* bitmap, int x, int y);
/**
* DEPRECATED: This will be made protected once WebKit stops using it.
* Instead use Canvas' writePixels method.
* Similar to draw sprite, this method will copy the pixels in bitmap onto
* the device, with the top/left corner specified by (x, y). The pixel
* values in the device are completely replaced: there is no blending.
@ -254,6 +236,37 @@ protected:
virtual void drawDevice(const SkDraw&, SkDevice*, int x, int y,
const SkPaint&);
/**
* On success (returns true), copy the device pixels into the bitmap.
* On failure, the bitmap parameter is left unchanged and false is
* returned.
*
* The device's pixels are converted to the bitmap's config. The only
* supported config is kARGB_8888_Config, though this is likely to be
* relaxed in the future. The meaning of config kARGB_8888_Config is
* modified by the enum param config8888. The default value interprets
* kARGB_8888_Config as SkPMColor
*
* If the bitmap has pixels already allocated, the device pixels will be
* written there. If not, bitmap->allocPixels() will be called
* automatically. If the bitmap is backed by a texture readPixels will
* fail.
*
* The actual pixels written is the intersection of the device's bounds,
* and the rectangle formed by the bitmap's width,height and the specified
* x,y. If bitmap pixels extend outside of that intersection, they will not
* be modified.
*
* Other failure conditions:
* * If the device is not a raster device (e.g. PDF) then readPixels will
* fail.
* * If bitmap is texture-backed then readPixels will fail. (This may be
* relaxed in the future.)
*/
bool readPixels(SkBitmap* bitmap,
int x, int y,
SkCanvas::Config8888 config8888);
///////////////////////////////////////////////////////////////////////////
/** Update as needed the pixel value in the bitmap, so that the caller can access
@ -276,8 +289,9 @@ protected:
* 3. The rectangle (x, y, x + bitmap->width(), y + bitmap->height()) is
* contained in the device bounds.
*/
virtual bool onReadPixels(const SkBitmap& bitmap, int x, int y);
virtual bool onReadPixels(const SkBitmap& bitmap,
int x, int y,
SkCanvas::Config8888 config8888);
/** Called when this device is installed into a Canvas. Balanaced by a call
to unlockPixels() when the device is removed from a Canvas.
@ -285,6 +299,10 @@ protected:
virtual void lockPixels();
virtual void unlockPixels();
// This is equal kBGRA_Premul_Config8888 or kRGBA_Premul_Config8888 if
// either is identical to kNative_Premul_Config8888. Otherwise, -1.
static const SkCanvas::Config8888 kPMColorAlias;
private:
friend class SkCanvas;
friend struct DeviceCM; //for setMatrixClip

Просмотреть файл

@ -143,7 +143,8 @@ protected:
virtual bool onReadPixels(const SkBitmap& bitmap,
int x,
int y) SK_OVERRIDE {
int y,
SkCanvas::Config8888) SK_OVERRIDE {
return false;
}

Просмотреть файл

@ -142,7 +142,8 @@ protected:
// overrides from SkDevice
virtual bool onReadPixels(const SkBitmap& bitmap,
int x, int y) SK_OVERRIDE;
int x, int y,
SkCanvas::Config8888 config8888) SK_OVERRIDE;
private:

Просмотреть файл

@ -159,7 +159,8 @@ public:
protected:
virtual bool onReadPixels(const SkBitmap& bitmap,
int x, int y) SK_OVERRIDE {
int x, int y,
SkCanvas::Config8888) SK_OVERRIDE {
return false;
}

Просмотреть файл

@ -550,12 +550,14 @@ SkDevice* SkCanvas::setBitmapDevice(const SkBitmap& bitmap) {
return device;
}
bool SkCanvas::readPixels(SkBitmap* bitmap, int x, int y) {
bool SkCanvas::readPixels(SkBitmap* bitmap,
int x, int y,
Config8888 config8888) {
SkDevice* device = this->getDevice();
if (!device) {
return false;
}
return device->readPixels(bitmap, x, y);
return device->readPixels(bitmap, x, y, config8888);
}
bool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {

Просмотреть файл

@ -102,7 +102,8 @@ void SkDevice::setMatrixClip(const SkMatrix& matrix, const SkRegion& region,
///////////////////////////////////////////////////////////////////////////////
bool SkDevice::readPixels(SkBitmap* bitmap, int x, int y) {
bool SkDevice::readPixels(SkBitmap* bitmap, int x, int y,
SkCanvas::Config8888 config8888) {
if (SkBitmap::kARGB_8888_Config != bitmap->config() ||
NULL != bitmap->getTexture()) {
return false;
@ -135,14 +136,149 @@ bool SkDevice::readPixels(SkBitmap* bitmap, int x, int y) {
SkBitmap bmpSubset;
bmp->extractSubset(&bmpSubset, subrect);
bool result = this->onReadPixels(bmpSubset, srcRect.fLeft, srcRect.fTop);
bool result = this->onReadPixels(bmpSubset,
srcRect.fLeft,
srcRect.fTop,
config8888);
if (result && bmp == &tmp) {
tmp.swap(*bitmap);
}
return result;
}
bool SkDevice::onReadPixels(const SkBitmap& bitmap, int x, int y) {
#ifdef SK_CPU_LENDIAN
#if 24 == SK_A32_SHIFT && 16 == SK_R32_SHIFT && \
8 == SK_G32_SHIFT && 0 == SK_B32_SHIFT
const SkCanvas::Config8888 SkDevice::kPMColorAlias =
SkCanvas::kBGRA_Premul_Config8888;
#elif 24 == SK_A32_SHIFT && 0 == SK_R32_SHIFT && \
8 == SK_G32_SHIFT && 16 == SK_B32_SHIFT
const SkCanvas::Config8888 SkDevice::kPMColorAlias =
SkCanvas::kRGBA_Premul_Config8888;
#else
const SkCanvas::Config8888 SkDevice::kPMColorAlias =
(SkCanvas::Config8888) -1;
#endif
static const int NATIVE_A_IDX = SK_A32_SHIFT / 8;
static const int NATIVE_R_IDX = SK_R32_SHIFT / 8;
static const int NATIVE_G_IDX = SK_G32_SHIFT / 8;
static const int NATIVE_B_IDX = SK_B32_SHIFT / 8;
#else
#if 0 == SK_A32_SHIFT && 8 == SK_R32_SHIFT && \
16 == SK_G32_SHIFT && 24 == SK_B32_SHIFT
const SkCanvas::Config8888 SkDevice::kPMColorAlias =
SkCanvas::kBGRA_Premul_Config8888;
#elif 0 == SK_A32_SHIFT && 24 == SK_R32_SHIFT && \
16 == SK_G32_SHIFT && 8 == SK_B32_SHIFT
const SkCanvas::Config8888 SkDevice::kPMColorAlias =
SkCanvas::kRGBA_Premul_Config8888;
#else
const SkCanvas::Config8888 SkDevice::kPMColorAlias =
(SkCanvas::Config8888) -1;
#endif
static const int NATIVE_A_IDX = 3 - (SK_A32_SHIFT / 8);
static const int NATIVE_R_IDX = 3 - (SK_R32_SHIFT / 8);
static const int NATIVE_G_IDX = 3 - (SK_G32_SHIFT / 8);
static const int NATIVE_B_IDX = 3 - (SK_B32_SHIFT / 8);
#endif
#include <SkColorPriv.h>
namespace {
template <int A_IDX, int R_IDX, int G_IDX, int B_IDX>
inline uint32_t pack_config8888(uint32_t a, uint32_t r,
uint32_t g, uint32_t b) {
#ifdef SK_CPU_LENDIAN
return (a << (A_IDX * 8)) | (r << (R_IDX * 8)) |
(g << (G_IDX * 8)) | (b << (B_IDX * 8));
#else
return (a << ((3-A_IDX) * 8)) | (r << ((3-R_IDX) * 8)) |
(g << ((3-G_IDX) * 8)) | (b << ((3-B_IDX) * 8));
#endif
}
template <bool UNPM, int A_IDX, int R_IDX, int G_IDX, int B_IDX>
inline void bitmap_copy_to_config8888(const SkBitmap& srcBmp,
uint32_t* dstPixels,
size_t dstRowBytes) {
SkASSERT(SkBitmap::kARGB_8888_Config == srcBmp.config());
SkAutoLockPixels alp(srcBmp);
int w = srcBmp.width();
int h = srcBmp.height();
size_t srcRowBytes = srcBmp.rowBytes();
intptr_t src = reinterpret_cast<intptr_t>(srcBmp.getPixels());
intptr_t dst = reinterpret_cast<intptr_t>(dstPixels);
for (int y = 0; y < h; ++y) {
const SkPMColor* srcRow = reinterpret_cast<SkPMColor*>(src);
uint32_t* dstRow = reinterpret_cast<uint32_t*>(dst);
for (int x = 0; x < w; ++x) {
SkPMColor pmcolor = srcRow[x];
if (UNPM) {
U8CPU a, r, g, b;
a = SkGetPackedA32(pmcolor);
if (a) {
// We're doing the explicit divide to match WebKit layout
// test expectations. We can modify and rebaseline if there
// it can be shown that there is a more performant way to
// unpremul.
r = SkGetPackedR32(pmcolor) * 0xff / a;
g = SkGetPackedG32(pmcolor) * 0xff / a;
b = SkGetPackedB32(pmcolor) * 0xff / a;
dstRow[x] = pack_config8888<A_IDX, R_IDX,
G_IDX, B_IDX>(a, r, g, b);
} else {
dstRow[x] = 0;
}
} else {
dstRow[x] = pack_config8888<A_IDX, R_IDX,
G_IDX, B_IDX>(
SkGetPackedA32(pmcolor),
SkGetPackedR32(pmcolor),
SkGetPackedG32(pmcolor),
SkGetPackedB32(pmcolor));
}
}
dst += dstRowBytes;
src += srcRowBytes;
}
}
inline void bitmap_copy_to_native(const SkBitmap& srcBmp,
uint32_t* dstPixels,
size_t dstRowBytes) {
SkASSERT(SkBitmap::kARGB_8888_Config == srcBmp.config());
SkAutoLockPixels alp(srcBmp);
int w = srcBmp.width();
int h = srcBmp.height();
size_t srcRowBytes = srcBmp.rowBytes();
size_t tightRowBytes = w * 4;
char* src = reinterpret_cast<char*>(srcBmp.getPixels());
char* dst = reinterpret_cast<char*>(dstPixels);
if (tightRowBytes == srcRowBytes &&
tightRowBytes == dstRowBytes) {
memcpy(dst, src, tightRowBytes * h);
} else {
for (int y = 0; y < h; ++y) {
memcpy(dst, src, tightRowBytes);
dst += dstRowBytes;
src += srcRowBytes;
}
}
}
}
bool SkDevice::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())));
@ -157,15 +293,53 @@ bool SkDevice::onReadPixels(const SkBitmap& bitmap, int x, int y) {
}
if (SkBitmap::kARGB_8888_Config != subset.config()) {
// It'd be preferable to do this directly to bitmap.
// We'd need a SkBitmap::copyPixelsTo that takes a config
// or make copyTo lazily allocate.
subset.copyTo(&subset, SkBitmap::kARGB_8888_Config);
}
SkAutoLockPixels alp(bitmap);
return subset.copyPixelsTo(bitmap.getPixels(),
bitmap.getSize(),
bitmap.rowBytes(),
true);
uint32_t* bmpPixels = reinterpret_cast<uint32_t*>(bitmap.getPixels());
if ((SkCanvas::kNative_Premul_Config8888 == config8888 ||
kPMColorAlias == config8888)) {
bitmap_copy_to_native(subset, bmpPixels, bitmap.rowBytes());
} else {
switch (config8888) {
case SkCanvas::kNative_Premul_Config8888:
bitmap_copy_to_config8888<false,
NATIVE_A_IDX, NATIVE_R_IDX,
NATIVE_G_IDX, NATIVE_B_IDX>(
subset,
bmpPixels,
bitmap.rowBytes());
break;
case SkCanvas::kNative_Unpremul_Config8888:
bitmap_copy_to_config8888<true,
NATIVE_A_IDX, NATIVE_R_IDX,
NATIVE_G_IDX, NATIVE_B_IDX>(
subset,
bmpPixels,
bitmap.rowBytes());
break;
case SkCanvas::kBGRA_Premul_Config8888:
bitmap_copy_to_config8888<false, 3, 2, 1, 0> (
subset, bmpPixels, bitmap.rowBytes());
break;
case SkCanvas::kBGRA_Unpremul_Config8888:
bitmap_copy_to_config8888<true, 3, 2, 1, 0> (
subset, bmpPixels, bitmap.rowBytes());
break;
case SkCanvas::kRGBA_Premul_Config8888:
bitmap_copy_to_config8888<false, 3, 0, 1, 2> (
subset, bmpPixels, bitmap.rowBytes());
break;
case SkCanvas::kRGBA_Unpremul_Config8888:
bitmap_copy_to_config8888<true, 3, 0, 1, 2> (
subset, bmpPixels, bitmap.rowBytes());
break;
default:
SkASSERT(false && "unexpected Config8888");
break;
}
}
return true;
}
void SkDevice::writePixels(const SkBitmap& bitmap, int x, int y) {

Просмотреть файл

@ -256,7 +256,13 @@ void SkGpuDevice::makeRenderTargetCurrent() {
///////////////////////////////////////////////////////////////////////////////
bool SkGpuDevice::onReadPixels(const SkBitmap& bitmap, int x, int y) {
bool SkGpuDevice::onReadPixels(const SkBitmap& bitmap,
int x, int y,
SkCanvas::Config8888 config8888) {
// support for non-native configs coming soon
if (config8888 != SkCanvas::kNative_Premul_Config8888) {
return false;
}
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())));

Просмотреть файл

@ -21,18 +21,81 @@ namespace {
SkPMColor getCanvasColor(int x, int y) {
SkASSERT(x >= 0 && x < DEV_W);
SkASSERT(y >= 0 && y < DEV_H);
return SkPackARGB32(0xff, x, y, 0x0);
U8CPU r = x;
U8CPU g = y;
U8CPU b = 0xc;
U8CPU a = 0xff;
switch (x % 5) {
case 0:
a = 0xff;
break;
case 1:
a = 0x80;
break;
case 2:
a = 0xCC;
break;
case 4:
a = 0x01;
break;
case 3:
a = 0x00;
break;
}
return SkPremultiplyARGBInline(a, r, g, b);
}
SkPMColor getBitmapColor(int x, int y, int w, int h) {
int n = y * w + x;
U8CPU b = n & 0xff;
U8CPU g = (n >> 8) & 0xff;
U8CPU r = (n >> 16) & 0xff;
return SkPackARGB32(0xff, r, g , b);
}
SkPMColor convertConfig8888ToPMColor(SkCanvas::Config8888 config8888,
uint32_t color) {
const uint8_t* c = reinterpret_cast<uint8_t*>(&color);
U8CPU a,r,g,b;
bool mul = false;
switch (config8888) {
case SkCanvas::kNative_Premul_Config8888:
return color;
case SkCanvas::kNative_Unpremul_Config8888:
mul = true;
a = SkGetPackedA32(color);
r = SkGetPackedR32(color);
g = SkGetPackedG32(color);
b = SkGetPackedB32(color);
break;
case SkCanvas::kBGRA_Unpremul_Config8888:
mul = true; // fallthru
case SkCanvas::kBGRA_Premul_Config8888:
a = static_cast<U8CPU>(c[3]);
r = static_cast<U8CPU>(c[2]);
g = static_cast<U8CPU>(c[1]);
b = static_cast<U8CPU>(c[0]);
break;
case SkCanvas::kRGBA_Unpremul_Config8888:
mul = true; // fallthru
case SkCanvas::kRGBA_Premul_Config8888:
a = static_cast<U8CPU>(c[3]);
r = static_cast<U8CPU>(c[0]);
g = static_cast<U8CPU>(c[1]);
b = static_cast<U8CPU>(c[2]);
break;
}
if (mul) {
r = SkMulDiv255Ceiling(r, a);
g = SkMulDiv255Ceiling(g, a);
b = SkMulDiv255Ceiling(b, a);
}
return SkPackARGB32(a, r, g, b);
}
void fillCanvas(SkCanvas* canvas) {
static SkBitmap bmp;
if (bmp.isNull()) {
@ -77,9 +140,12 @@ void fillBitmap(SkBitmap* bitmap) {
bool checkRead(skiatest::Reporter* reporter,
const SkBitmap& bitmap,
int x, int y,
bool preFilledBmp) {
bool checkCanvasPixels,
bool checkBitmapPixels,
SkCanvas::Config8888 config8888) {
SkASSERT(SkBitmap::kARGB_8888_Config == bitmap.config());
SkASSERT(!bitmap.isNull());
SkASSERT(checkCanvasPixels || checkBitmapPixels);
int bw = bitmap.width();
int bh = bitmap.height();
@ -100,11 +166,15 @@ bool checkRead(skiatest::Reporter* reporter,
SkPMColor pixel = *reinterpret_cast<SkPMColor*>(pixels + by * bitmap.rowBytes() + bx * bitmap.bytesPerPixel());
if (clippedSrcRect.contains(devx, devy)) {
REPORTER_ASSERT(reporter, getCanvasColor(devx, devy) == pixel);
if (getCanvasColor(devx, devy) != pixel) {
return false;
if (checkCanvasPixels) {
SkPMColor canvasPixel = getCanvasColor(devx, devy);
pixel = convertConfig8888ToPMColor(config8888, pixel);
REPORTER_ASSERT(reporter, canvasPixel == pixel);
if (getCanvasColor(devx, devy) != pixel) {
return false;
}
}
} else if (preFilledBmp) {
} else if (checkBitmapPixels) {
REPORTER_ASSERT(reporter, getBitmapColor(bx, by, bw, bh) == pixel);
if (getBitmapColor(bx, by, bw, bh) != pixel) {
return false;
@ -207,51 +277,79 @@ void ReadPixelsTest(skiatest::Reporter* reporter, GrContext* context) {
for (int dtype = 0; dtype < 2; ++dtype) {
if (0 == dtype) {
canvas.setDevice(new SkDevice(SkBitmap::kARGB_8888_Config, DEV_W, DEV_H, false))->unref();
canvas.setDevice(new SkDevice(SkBitmap::kARGB_8888_Config,
DEV_W,
DEV_H,
false))->unref();
} else {
#if SK_SCALAR_IS_FIXED
// GPU device known not to work in the fixed pt build.
continue;
#endif
canvas.setDevice(new SkGpuDevice(context, SkBitmap::kARGB_8888_Config, DEV_W, DEV_H))->unref();
canvas.setDevice(new SkGpuDevice(context,
SkBitmap::kARGB_8888_Config,
DEV_W,
DEV_H))->unref();
}
fillCanvas(&canvas);
static const SkCanvas::Config8888 gReadConfigs[] = {
SkCanvas::kNative_Premul_Config8888,
SkCanvas::kNative_Unpremul_Config8888,
SkCanvas::kBGRA_Premul_Config8888,
SkCanvas::kBGRA_Unpremul_Config8888,
SkCanvas::kRGBA_Premul_Config8888,
SkCanvas::kRGBA_Unpremul_Config8888,
};
for (int rect = 0; rect < SK_ARRAY_COUNT(testRects); ++rect) {
SkBitmap bmp;
for (BitmapInit bmi = kFirstBitmapInit; bmi < kBitmapInitCnt; bmi = nextBMI(bmi)) {
const SkIRect& srcRect = testRects[rect];
for (BitmapInit bmi = kFirstBitmapInit;
bmi < kBitmapInitCnt;
bmi = nextBMI(bmi)) {
for (int c = 0; c < SK_ARRAY_COUNT(gReadConfigs); ++c) {
SkCanvas::Config8888 config8888 = gReadConfigs[c];
SkBitmap bmp;
init_bitmap(&bmp, srcRect, bmi);
const SkIRect& srcRect = testRects[rect];
// if the bitmap has pixels allocated before the readPixels,
// note that and fill them with pattern
bool startsWithPixels = !bmp.isNull();
if (startsWithPixels) {
fillBitmap(&bmp);
}
init_bitmap(&bmp, srcRect, bmi);
bool success =
canvas.readPixels(&bmp, srcRect.fLeft,
srcRect.fTop, config8888);
// if the bitmap has pixels allocated before the readPixels, note
// that and fill them with pattern
bool startsWithPixels = !bmp.isNull();
if (startsWithPixels) {
fillBitmap(&bmp);
// non-native not implemented on GPU yet
bool expectSuccess =
SkIRect::Intersects(srcRect, DEV_RECT) &&
!(1 == dtype &&
config8888 != SkCanvas::kNative_Premul_Config8888);
// determine whether we expected the read to succeed.
REPORTER_ASSERT(reporter, success == expectSuccess);
if (success || startsWithPixels) {
checkRead(reporter, bmp, srcRect.fLeft, srcRect.fTop,
success, startsWithPixels, config8888);
} else {
// if we had no pixels beforehand and the readPixels
// failed then our bitmap should still not have pixels
REPORTER_ASSERT(reporter, bmp.isNull());
}
}
bool success = canvas.readPixels(&bmp, srcRect.fLeft, srcRect.fTop);
// determine whether we expected the read to succeed.
REPORTER_ASSERT(reporter, success == SkIRect::Intersects(srcRect, DEV_RECT));
if (success || startsWithPixels) {
checkRead(reporter, bmp, srcRect.fLeft, srcRect.fTop, startsWithPixels);
} else {
// if we had no pixels beforehand and the readPixels failed then
// our bitmap should still not have any pixels
REPORTER_ASSERT(reporter, bmp.isNull());
}
// check the old webkit version of readPixels that clips the bitmap size
// check the old webkit version of readPixels that clips the
// bitmap size
SkBitmap wkbmp;
success = canvas.readPixels(srcRect, &wkbmp);
bool success = canvas.readPixels(srcRect, &wkbmp);
SkIRect clippedRect = DEV_RECT;
if (clippedRect.intersect(srcRect)) {
REPORTER_ASSERT(reporter, success);
checkRead(reporter, wkbmp, clippedRect.fLeft, clippedRect.fTop, false);
checkRead(reporter, wkbmp, clippedRect.fLeft,
clippedRect.fTop, true, false,
SkCanvas::kNative_Premul_Config8888);
} else {
REPORTER_ASSERT(reporter, !success);
}