304a07c6c9
Bug: skia:6828 Change-Id: Ib5049c28c11b7320bece20f5a0a886de8b2a4343 Reviewed-on: https://skia-review.googlesource.com/22728 Reviewed-by: Leon Scroggins <scroggo@google.com> Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Mike Reed <reed@google.com>
226 lines
7.7 KiB
C++
226 lines
7.7 KiB
C++
/*
|
|
* Copyright 2011 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#include "SkBitmap.h"
|
|
#include "SkRect.h"
|
|
#include "SkTemplates.h"
|
|
#include "Test.h"
|
|
#include "sk_tool_utils.h"
|
|
|
|
static void init_src(const SkBitmap& bitmap) {
|
|
if (bitmap.getPixels()) {
|
|
if (bitmap.getColorTable()) {
|
|
sk_bzero(bitmap.getPixels(), bitmap.getSize());
|
|
} else {
|
|
bitmap.eraseColor(SK_ColorWHITE);
|
|
}
|
|
}
|
|
}
|
|
|
|
struct Pair {
|
|
SkColorType fColorType;
|
|
const char* fValid;
|
|
};
|
|
|
|
// Utility functions for copyPixelsTo()/copyPixelsFrom() tests.
|
|
// getPixel()
|
|
// setPixel()
|
|
// getSkConfigName()
|
|
// struct Coordinates
|
|
// reportCopyVerification()
|
|
// writeCoordPixels()
|
|
|
|
// Helper struct to contain pixel locations, while avoiding need for STL.
|
|
struct Coordinates {
|
|
|
|
const int length;
|
|
SkIPoint* const data;
|
|
|
|
explicit Coordinates(int _length): length(_length)
|
|
, data(new SkIPoint[length]) { }
|
|
|
|
~Coordinates(){
|
|
delete [] data;
|
|
}
|
|
|
|
SkIPoint* operator[](int i) const {
|
|
// Use with care, no bounds checking.
|
|
return data + i;
|
|
}
|
|
};
|
|
|
|
static const Pair gPairs[] = {
|
|
{ kUnknown_SkColorType, "0000000" },
|
|
{ kAlpha_8_SkColorType, "0100000" },
|
|
{ kRGB_565_SkColorType, "0101011" },
|
|
{ kARGB_4444_SkColorType, "0101111" },
|
|
{ kN32_SkColorType, "0101111" },
|
|
{ kRGBA_F16_SkColorType, "0101011" },
|
|
};
|
|
|
|
static const int W = 20;
|
|
static const int H = 33;
|
|
|
|
static void setup_src_bitmaps(SkBitmap* srcOpaque, SkBitmap* srcPremul,
|
|
SkColorType ct) {
|
|
sk_sp<SkColorSpace> colorSpace = nullptr;
|
|
if (kRGBA_F16_SkColorType == ct) {
|
|
colorSpace = SkColorSpace::MakeSRGBLinear();
|
|
}
|
|
|
|
srcOpaque->allocPixels(SkImageInfo::Make(W, H, ct, kOpaque_SkAlphaType, colorSpace));
|
|
srcPremul->allocPixels(SkImageInfo::Make(W, H, ct, kPremul_SkAlphaType, colorSpace));
|
|
init_src(*srcOpaque);
|
|
init_src(*srcPremul);
|
|
}
|
|
|
|
DEF_TEST(BitmapCopy_extractSubset, reporter) {
|
|
for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) {
|
|
SkBitmap srcOpaque, srcPremul;
|
|
setup_src_bitmaps(&srcOpaque, &srcPremul, gPairs[i].fColorType);
|
|
|
|
SkBitmap bitmap(srcOpaque);
|
|
SkBitmap subset;
|
|
SkIRect r;
|
|
// Extract a subset which has the same width as the original. This
|
|
// catches a bug where we cloned the genID incorrectly.
|
|
r.set(0, 1, W, 3);
|
|
bitmap.setIsVolatile(true);
|
|
// Relies on old behavior of extractSubset failing if colortype is unknown
|
|
if (kUnknown_SkColorType != bitmap.colorType() && bitmap.extractSubset(&subset, r)) {
|
|
REPORTER_ASSERT(reporter, subset.width() == W);
|
|
REPORTER_ASSERT(reporter, subset.height() == 2);
|
|
REPORTER_ASSERT(reporter, subset.alphaType() == bitmap.alphaType());
|
|
REPORTER_ASSERT(reporter, subset.isVolatile() == true);
|
|
|
|
// Test copying an extracted subset.
|
|
for (size_t j = 0; j < SK_ARRAY_COUNT(gPairs); j++) {
|
|
SkBitmap copy;
|
|
bool success = sk_tool_utils::copy_to(©, gPairs[j].fColorType, subset);
|
|
if (!success) {
|
|
// Skip checking that success matches fValid, which is redundant
|
|
// with the code below.
|
|
REPORTER_ASSERT(reporter, gPairs[i].fColorType != gPairs[j].fColorType);
|
|
continue;
|
|
}
|
|
|
|
// When performing a copy of an extracted subset, the gen id should
|
|
// change.
|
|
REPORTER_ASSERT(reporter, copy.getGenerationID() != subset.getGenerationID());
|
|
|
|
REPORTER_ASSERT(reporter, copy.width() == W);
|
|
REPORTER_ASSERT(reporter, copy.height() == 2);
|
|
|
|
if (gPairs[i].fColorType == gPairs[j].fColorType) {
|
|
// they should both have, or both not-have, a colortable
|
|
bool hasCT = subset.getColorTable() != nullptr;
|
|
REPORTER_ASSERT(reporter, (copy.getColorTable() != nullptr) == hasCT);
|
|
}
|
|
}
|
|
}
|
|
|
|
bitmap = srcPremul;
|
|
bitmap.setIsVolatile(false);
|
|
if (bitmap.extractSubset(&subset, r)) {
|
|
REPORTER_ASSERT(reporter, subset.alphaType() == bitmap.alphaType());
|
|
REPORTER_ASSERT(reporter, subset.isVolatile() == false);
|
|
}
|
|
}
|
|
}
|
|
|
|
#include "SkColorPriv.h"
|
|
#include "SkUtils.h"
|
|
|
|
/**
|
|
* Construct 4x4 pixels where we can look at a color and determine where it should be in the grid.
|
|
* alpha = 0xFF, blue = 0x80, red = x, green = y
|
|
*/
|
|
static void fill_4x4_pixels(SkPMColor colors[16]) {
|
|
for (int y = 0; y < 4; ++y) {
|
|
for (int x = 0; x < 4; ++x) {
|
|
colors[y*4+x] = SkPackARGB32(0xFF, x, y, 0x80);
|
|
}
|
|
}
|
|
}
|
|
|
|
static bool check_4x4_pixel(SkPMColor color, unsigned x, unsigned y) {
|
|
SkASSERT(x < 4 && y < 4);
|
|
return 0xFF == SkGetPackedA32(color) &&
|
|
x == SkGetPackedR32(color) &&
|
|
y == SkGetPackedG32(color) &&
|
|
0x80 == SkGetPackedB32(color);
|
|
}
|
|
|
|
/**
|
|
* Fill with all zeros, which will never match any value from fill_4x4_pixels
|
|
*/
|
|
static void clear_4x4_pixels(SkPMColor colors[16]) {
|
|
sk_memset32(colors, 0, 16);
|
|
}
|
|
|
|
// Much of readPixels is exercised by copyTo testing, since readPixels is the backend for that
|
|
// method. Here we explicitly test subset copies.
|
|
//
|
|
DEF_TEST(BitmapReadPixels, reporter) {
|
|
const int W = 4;
|
|
const int H = 4;
|
|
const size_t rowBytes = W * sizeof(SkPMColor);
|
|
const SkImageInfo srcInfo = SkImageInfo::MakeN32Premul(W, H);
|
|
SkPMColor srcPixels[16];
|
|
fill_4x4_pixels(srcPixels);
|
|
SkBitmap srcBM;
|
|
srcBM.installPixels(srcInfo, srcPixels, rowBytes);
|
|
|
|
SkImageInfo dstInfo = SkImageInfo::MakeN32Premul(W, H);
|
|
SkPMColor dstPixels[16];
|
|
|
|
const struct {
|
|
bool fExpectedSuccess;
|
|
SkIPoint fRequestedSrcLoc;
|
|
SkISize fRequestedDstSize;
|
|
// If fExpectedSuccess, check these, otherwise ignore
|
|
SkIPoint fExpectedDstLoc;
|
|
SkIRect fExpectedSrcR;
|
|
} gRec[] = {
|
|
{ true, { 0, 0 }, { 4, 4 }, { 0, 0 }, { 0, 0, 4, 4 } },
|
|
{ true, { 1, 1 }, { 2, 2 }, { 0, 0 }, { 1, 1, 3, 3 } },
|
|
{ true, { 2, 2 }, { 4, 4 }, { 0, 0 }, { 2, 2, 4, 4 } },
|
|
{ true, {-1,-1 }, { 2, 2 }, { 1, 1 }, { 0, 0, 1, 1 } },
|
|
{ false, {-1,-1 }, { 1, 1 }, { 0, 0 }, { 0, 0, 0, 0 } },
|
|
};
|
|
|
|
for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {
|
|
clear_4x4_pixels(dstPixels);
|
|
|
|
dstInfo = dstInfo.makeWH(gRec[i].fRequestedDstSize.width(),
|
|
gRec[i].fRequestedDstSize.height());
|
|
bool success = srcBM.readPixels(dstInfo, dstPixels, rowBytes,
|
|
gRec[i].fRequestedSrcLoc.x(), gRec[i].fRequestedSrcLoc.y());
|
|
|
|
REPORTER_ASSERT(reporter, gRec[i].fExpectedSuccess == success);
|
|
if (success) {
|
|
const SkIRect srcR = gRec[i].fExpectedSrcR;
|
|
const int dstX = gRec[i].fExpectedDstLoc.x();
|
|
const int dstY = gRec[i].fExpectedDstLoc.y();
|
|
// Walk the dst pixels, and check if we got what we expected
|
|
for (int y = 0; y < H; ++y) {
|
|
for (int x = 0; x < W; ++x) {
|
|
SkPMColor dstC = dstPixels[y*4+x];
|
|
// get into src coordinates
|
|
int sx = x - dstX + srcR.x();
|
|
int sy = y - dstY + srcR.y();
|
|
if (srcR.contains(sx, sy)) {
|
|
REPORTER_ASSERT(reporter, check_4x4_pixel(dstC, sx, sy));
|
|
} else {
|
|
REPORTER_ASSERT(reporter, 0 == dstC);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|