1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2013 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h" 9cb93a386Sopenharmony_ci#include "include/core/SkColor.h" 10cb93a386Sopenharmony_ci#include "include/core/SkImageInfo.h" 11cb93a386Sopenharmony_ci#include "include/core/SkMallocPixelRef.h" 12cb93a386Sopenharmony_ci#include "include/core/SkPixelRef.h" 13cb93a386Sopenharmony_ci#include "include/core/SkPixmap.h" 14cb93a386Sopenharmony_ci#include "include/core/SkRefCnt.h" 15cb93a386Sopenharmony_ci#include "include/core/SkScalar.h" 16cb93a386Sopenharmony_ci#include "include/core/SkTypes.h" 17cb93a386Sopenharmony_ci#include "include/private/SkFloatingPoint.h" 18cb93a386Sopenharmony_ci#include "include/utils/SkRandom.h" 19cb93a386Sopenharmony_ci#include "tests/Test.h" 20cb93a386Sopenharmony_ci#include "tools/ToolUtils.h" 21cb93a386Sopenharmony_ci 22cb93a386Sopenharmony_ci#include <initializer_list> 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_cistatic void test_peekpixels(skiatest::Reporter* reporter) { 25cb93a386Sopenharmony_ci const SkImageInfo info = SkImageInfo::MakeN32Premul(10, 10); 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_ci SkPixmap pmap; 28cb93a386Sopenharmony_ci SkBitmap bm; 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_ci // empty should return false 31cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !bm.peekPixels(nullptr)); 32cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !bm.peekPixels(&pmap)); 33cb93a386Sopenharmony_ci 34cb93a386Sopenharmony_ci // no pixels should return false 35cb93a386Sopenharmony_ci bm.setInfo(SkImageInfo::MakeN32Premul(10, 10)); 36cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !bm.peekPixels(nullptr)); 37cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !bm.peekPixels(&pmap)); 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_ci // real pixels should return true 40cb93a386Sopenharmony_ci bm.allocPixels(info); 41cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, bm.peekPixels(nullptr)); 42cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, bm.peekPixels(&pmap)); 43cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pmap.info() == bm.info()); 44cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pmap.addr() == bm.getPixels()); 45cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, pmap.rowBytes() == bm.rowBytes()); 46cb93a386Sopenharmony_ci} 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_ci// https://code.google.com/p/chromium/issues/detail?id=446164 49cb93a386Sopenharmony_cistatic void test_bigalloc(skiatest::Reporter* reporter) { 50cb93a386Sopenharmony_ci const int width = 0x40000001; 51cb93a386Sopenharmony_ci const int height = 0x00000096; 52cb93a386Sopenharmony_ci const SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_ci SkBitmap bm; 55cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !bm.tryAllocPixels(info)); 56cb93a386Sopenharmony_ci 57cb93a386Sopenharmony_ci sk_sp<SkPixelRef> pr = SkMallocPixelRef::MakeAllocate(info, info.minRowBytes()); 58cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !pr); 59cb93a386Sopenharmony_ci} 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_cistatic void test_allocpixels(skiatest::Reporter* reporter) { 62cb93a386Sopenharmony_ci const int width = 10; 63cb93a386Sopenharmony_ci const int height = 10; 64cb93a386Sopenharmony_ci const SkImageInfo info = SkImageInfo::MakeN32Premul(width, height); 65cb93a386Sopenharmony_ci const size_t explicitRowBytes = info.minRowBytes() + 24; 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_ci SkBitmap bm; 68cb93a386Sopenharmony_ci bm.setInfo(info); 69cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, info.minRowBytes() == bm.rowBytes()); 70cb93a386Sopenharmony_ci bm.allocPixels(); 71cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, info.minRowBytes() == bm.rowBytes()); 72cb93a386Sopenharmony_ci bm.reset(); 73cb93a386Sopenharmony_ci bm.allocPixels(info); 74cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, info.minRowBytes() == bm.rowBytes()); 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ci bm.setInfo(info, explicitRowBytes); 77cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, explicitRowBytes == bm.rowBytes()); 78cb93a386Sopenharmony_ci bm.allocPixels(); 79cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, explicitRowBytes == bm.rowBytes()); 80cb93a386Sopenharmony_ci bm.reset(); 81cb93a386Sopenharmony_ci bm.allocPixels(info, explicitRowBytes); 82cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, explicitRowBytes == bm.rowBytes()); 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_ci bm.reset(); 85cb93a386Sopenharmony_ci bm.setInfo(info, 0); 86cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, info.minRowBytes() == bm.rowBytes()); 87cb93a386Sopenharmony_ci bm.reset(); 88cb93a386Sopenharmony_ci bm.allocPixels(info, 0); 89cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, info.minRowBytes() == bm.rowBytes()); 90cb93a386Sopenharmony_ci 91cb93a386Sopenharmony_ci bm.reset(); 92cb93a386Sopenharmony_ci bool success = bm.setInfo(info, info.minRowBytes() - 1); // invalid for 32bit 93cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !success); 94cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, bm.isNull()); 95cb93a386Sopenharmony_ci 96cb93a386Sopenharmony_ci for (SkColorType ct : { 97cb93a386Sopenharmony_ci kAlpha_8_SkColorType, 98cb93a386Sopenharmony_ci kRGB_565_SkColorType, 99cb93a386Sopenharmony_ci kARGB_4444_SkColorType, 100cb93a386Sopenharmony_ci kRGBA_8888_SkColorType, 101cb93a386Sopenharmony_ci kBGRA_8888_SkColorType, 102cb93a386Sopenharmony_ci kRGB_888x_SkColorType, 103cb93a386Sopenharmony_ci kRGBA_1010102_SkColorType, 104cb93a386Sopenharmony_ci kRGB_101010x_SkColorType, 105cb93a386Sopenharmony_ci kGray_8_SkColorType, 106cb93a386Sopenharmony_ci kRGBA_F16Norm_SkColorType, 107cb93a386Sopenharmony_ci kRGBA_F16_SkColorType, 108cb93a386Sopenharmony_ci kRGBA_F32_SkColorType, 109cb93a386Sopenharmony_ci kR8G8_unorm_SkColorType, 110cb93a386Sopenharmony_ci kA16_unorm_SkColorType, 111cb93a386Sopenharmony_ci kR16G16_unorm_SkColorType, 112cb93a386Sopenharmony_ci kA16_float_SkColorType, 113cb93a386Sopenharmony_ci kR16G16_float_SkColorType, 114cb93a386Sopenharmony_ci kR16G16B16A16_unorm_SkColorType, 115cb93a386Sopenharmony_ci }) { 116cb93a386Sopenharmony_ci SkImageInfo imageInfo = info.makeColorType(ct); 117cb93a386Sopenharmony_ci for (int rowBytesPadding = 1; rowBytesPadding <= 17; rowBytesPadding++) { 118cb93a386Sopenharmony_ci bm.reset(); 119cb93a386Sopenharmony_ci success = bm.setInfo(imageInfo, imageInfo.minRowBytes() + rowBytesPadding); 120cb93a386Sopenharmony_ci if (rowBytesPadding % imageInfo.bytesPerPixel() == 0) { 121cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, success); 122cb93a386Sopenharmony_ci success = bm.tryAllocPixels(); 123cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, success); 124cb93a386Sopenharmony_ci } else { 125cb93a386Sopenharmony_ci // Not pixel aligned. 126cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !success); 127cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, bm.isNull()); 128cb93a386Sopenharmony_ci } 129cb93a386Sopenharmony_ci } 130cb93a386Sopenharmony_ci } 131cb93a386Sopenharmony_ci} 132cb93a386Sopenharmony_ci 133cb93a386Sopenharmony_cistatic void test_bigwidth(skiatest::Reporter* reporter) { 134cb93a386Sopenharmony_ci SkBitmap bm; 135cb93a386Sopenharmony_ci int width = 1 << 29; // *4 will be the high-bit of 32bit int 136cb93a386Sopenharmony_ci 137cb93a386Sopenharmony_ci SkImageInfo info = SkImageInfo::MakeA8(width, 1); 138cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, bm.setInfo(info)); 139cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, bm.setInfo(info.makeColorType(kRGB_565_SkColorType))); 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_ci // for a 4-byte config, this width will compute a rowbytes of 0x80000000, 142cb93a386Sopenharmony_ci // which does not fit in a int32_t. setConfig should detect this, and fail. 143cb93a386Sopenharmony_ci 144cb93a386Sopenharmony_ci // TODO: perhaps skia can relax this, and only require that rowBytes fit 145cb93a386Sopenharmony_ci // in a uint32_t (or larger), but for now this is the constraint. 146cb93a386Sopenharmony_ci 147cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, !bm.setInfo(info.makeColorType(kN32_SkColorType))); 148cb93a386Sopenharmony_ci} 149cb93a386Sopenharmony_ci 150cb93a386Sopenharmony_ciDEF_TEST(Bitmap, reporter) { 151cb93a386Sopenharmony_ci // Zero-sized bitmaps are allowed 152cb93a386Sopenharmony_ci for (int width = 0; width < 2; ++width) { 153cb93a386Sopenharmony_ci for (int height = 0; height < 2; ++height) { 154cb93a386Sopenharmony_ci SkBitmap bm; 155cb93a386Sopenharmony_ci bool setConf = bm.setInfo(SkImageInfo::MakeN32Premul(width, height)); 156cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, setConf); 157cb93a386Sopenharmony_ci if (setConf) { 158cb93a386Sopenharmony_ci bm.allocPixels(); 159cb93a386Sopenharmony_ci } 160cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, SkToBool(width & height) != bm.empty()); 161cb93a386Sopenharmony_ci } 162cb93a386Sopenharmony_ci } 163cb93a386Sopenharmony_ci 164cb93a386Sopenharmony_ci test_bigwidth(reporter); 165cb93a386Sopenharmony_ci test_allocpixels(reporter); 166cb93a386Sopenharmony_ci test_bigalloc(reporter); 167cb93a386Sopenharmony_ci test_peekpixels(reporter); 168cb93a386Sopenharmony_ci} 169cb93a386Sopenharmony_ci 170cb93a386Sopenharmony_ci/** 171cb93a386Sopenharmony_ci * This test checks that getColor works for both swizzles. 172cb93a386Sopenharmony_ci */ 173cb93a386Sopenharmony_ciDEF_TEST(Bitmap_getColor_Swizzle, r) { 174cb93a386Sopenharmony_ci SkBitmap source; 175cb93a386Sopenharmony_ci source.allocN32Pixels(1,1); 176cb93a386Sopenharmony_ci source.eraseColor(SK_ColorRED); 177cb93a386Sopenharmony_ci SkColorType colorTypes[] = { 178cb93a386Sopenharmony_ci kRGBA_8888_SkColorType, 179cb93a386Sopenharmony_ci kBGRA_8888_SkColorType, 180cb93a386Sopenharmony_ci }; 181cb93a386Sopenharmony_ci for (SkColorType ct : colorTypes) { 182cb93a386Sopenharmony_ci SkBitmap copy; 183cb93a386Sopenharmony_ci if (!ToolUtils::copy_to(©, ct, source)) { 184cb93a386Sopenharmony_ci ERRORF(r, "SkBitmap::copy failed %d", (int)ct); 185cb93a386Sopenharmony_ci continue; 186cb93a386Sopenharmony_ci } 187cb93a386Sopenharmony_ci REPORTER_ASSERT(r, source.getColor(0, 0) == copy.getColor(0, 0)); 188cb93a386Sopenharmony_ci } 189cb93a386Sopenharmony_ci} 190cb93a386Sopenharmony_ci 191cb93a386Sopenharmony_cistatic void test_erasecolor_premul(skiatest::Reporter* reporter, SkColorType ct, SkColor input, 192cb93a386Sopenharmony_ci SkColor expected) { 193cb93a386Sopenharmony_ci SkBitmap bm; 194cb93a386Sopenharmony_ci bm.allocPixels(SkImageInfo::Make(1, 1, ct, kPremul_SkAlphaType)); 195cb93a386Sopenharmony_ci bm.eraseColor(input); 196cb93a386Sopenharmony_ci INFOF(reporter, "expected: %x actual: %x\n", expected, bm.getColor(0, 0)); 197cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, bm.getColor(0, 0) == expected); 198cb93a386Sopenharmony_ci} 199cb93a386Sopenharmony_ci 200cb93a386Sopenharmony_ci/** 201cb93a386Sopenharmony_ci * This test checks that eraseColor premultiplies the color correctly. 202cb93a386Sopenharmony_ci */ 203cb93a386Sopenharmony_ciDEF_TEST(Bitmap_eraseColor_Premul, r) { 204cb93a386Sopenharmony_ci SkColor color = 0x80FF0080; 205cb93a386Sopenharmony_ci test_erasecolor_premul(r, kAlpha_8_SkColorType, color, 0x80000000); 206cb93a386Sopenharmony_ci test_erasecolor_premul(r, kRGB_565_SkColorType, color, 0xFF840042); 207cb93a386Sopenharmony_ci test_erasecolor_premul(r, kARGB_4444_SkColorType, color, 0x88FF0080); 208cb93a386Sopenharmony_ci test_erasecolor_premul(r, kRGBA_8888_SkColorType, color, color); 209cb93a386Sopenharmony_ci test_erasecolor_premul(r, kBGRA_8888_SkColorType, color, color); 210cb93a386Sopenharmony_ci} 211cb93a386Sopenharmony_ci 212cb93a386Sopenharmony_ci// Test that SkBitmap::ComputeOpaque() is correct for various colortypes. 213cb93a386Sopenharmony_ciDEF_TEST(Bitmap_compute_is_opaque, r) { 214cb93a386Sopenharmony_ci 215cb93a386Sopenharmony_ci for (int i = 1; i <= kLastEnum_SkColorType; ++i) { 216cb93a386Sopenharmony_ci SkColorType ct = (SkColorType) i; 217cb93a386Sopenharmony_ci SkBitmap bm; 218cb93a386Sopenharmony_ci SkAlphaType at = SkColorTypeIsAlwaysOpaque(ct) ? kOpaque_SkAlphaType : kPremul_SkAlphaType; 219cb93a386Sopenharmony_ci bm.allocPixels(SkImageInfo::Make(13, 17, ct, at)); 220cb93a386Sopenharmony_ci bm.eraseColor(SkColorSetARGB(255, 10, 20, 30)); 221cb93a386Sopenharmony_ci REPORTER_ASSERT(r, SkBitmap::ComputeIsOpaque(bm)); 222cb93a386Sopenharmony_ci 223cb93a386Sopenharmony_ci bm.eraseColor(SkColorSetARGB(128, 255, 255, 255)); 224cb93a386Sopenharmony_ci bool isOpaque = SkBitmap::ComputeIsOpaque(bm); 225cb93a386Sopenharmony_ci bool shouldBeOpaque = (at == kOpaque_SkAlphaType); 226cb93a386Sopenharmony_ci REPORTER_ASSERT(r, isOpaque == shouldBeOpaque); 227cb93a386Sopenharmony_ci } 228cb93a386Sopenharmony_ci} 229cb93a386Sopenharmony_ci 230cb93a386Sopenharmony_ci// Test that erase+getColor round trips with RGBA_F16 pixels. 231cb93a386Sopenharmony_ciDEF_TEST(Bitmap_erase_f16_erase_getColor, r) { 232cb93a386Sopenharmony_ci SkRandom random; 233cb93a386Sopenharmony_ci SkPixmap pm; 234cb93a386Sopenharmony_ci SkBitmap bm; 235cb93a386Sopenharmony_ci bm.allocPixels(SkImageInfo::Make(1, 1, kRGBA_F16_SkColorType, kPremul_SkAlphaType)); 236cb93a386Sopenharmony_ci REPORTER_ASSERT(r, bm.peekPixels(&pm)); 237cb93a386Sopenharmony_ci for (unsigned i = 0; i < 0x100; ++i) { 238cb93a386Sopenharmony_ci // Test all possible values of blue component. 239cb93a386Sopenharmony_ci SkColor color1 = (SkColor)((random.nextU() & 0xFFFFFF00) | i); 240cb93a386Sopenharmony_ci // Test all possible values of alpha component. 241cb93a386Sopenharmony_ci SkColor color2 = (SkColor)((random.nextU() & 0x00FFFFFF) | (i << 24)); 242cb93a386Sopenharmony_ci for (SkColor color : {color1, color2}) { 243cb93a386Sopenharmony_ci pm.erase(color); 244cb93a386Sopenharmony_ci if (SkColorGetA(color) != 0) { 245cb93a386Sopenharmony_ci REPORTER_ASSERT(r, color == pm.getColor(0, 0)); 246cb93a386Sopenharmony_ci } else { 247cb93a386Sopenharmony_ci REPORTER_ASSERT(r, 0 == SkColorGetA(pm.getColor(0, 0))); 248cb93a386Sopenharmony_ci } 249cb93a386Sopenharmony_ci } 250cb93a386Sopenharmony_ci } 251cb93a386Sopenharmony_ci} 252cb93a386Sopenharmony_ci 253cb93a386Sopenharmony_ci// Verify that SkBitmap::erase erases in SRGB, regardless of the SkColorSpace of the 254cb93a386Sopenharmony_ci// SkBitmap. 255cb93a386Sopenharmony_ciDEF_TEST(Bitmap_erase_srgb, r) { 256cb93a386Sopenharmony_ci SkBitmap bm; 257cb93a386Sopenharmony_ci // Use a color spin from SRGB. 258cb93a386Sopenharmony_ci bm.allocPixels(SkImageInfo::Make(1, 1, kN32_SkColorType, kPremul_SkAlphaType, 259cb93a386Sopenharmony_ci SkColorSpace::MakeSRGB()->makeColorSpin())); 260cb93a386Sopenharmony_ci // RED will be converted into the spun color space. 261cb93a386Sopenharmony_ci bm.eraseColor(SK_ColorRED); 262cb93a386Sopenharmony_ci // getColor doesn't take the color space into account, so the returned color 263cb93a386Sopenharmony_ci // is different due to the color spin. 264cb93a386Sopenharmony_ci REPORTER_ASSERT(r, bm.getColor(0, 0) == SK_ColorBLUE); 265cb93a386Sopenharmony_ci} 266cb93a386Sopenharmony_ci 267cb93a386Sopenharmony_ci// Make sure that the bitmap remains valid when pixelref is removed. 268cb93a386Sopenharmony_ciDEF_TEST(Bitmap_clear_pixelref_keep_info, r) { 269cb93a386Sopenharmony_ci SkBitmap bm; 270cb93a386Sopenharmony_ci bm.allocPixels(SkImageInfo::MakeN32Premul(100,100)); 271cb93a386Sopenharmony_ci bm.setPixelRef(nullptr, 0, 0); 272cb93a386Sopenharmony_ci SkDEBUGCODE(bm.validate();) 273cb93a386Sopenharmony_ci} 274cb93a386Sopenharmony_ci 275cb93a386Sopenharmony_ci// At the time of writing, SkBitmap::erase() works when the color is zero for all formats, 276cb93a386Sopenharmony_ci// but some formats failed when the color is non-zero! 277cb93a386Sopenharmony_ciDEF_TEST(Bitmap_erase, r) { 278cb93a386Sopenharmony_ci SkColorType colorTypes[] = { 279cb93a386Sopenharmony_ci kRGB_565_SkColorType, 280cb93a386Sopenharmony_ci kARGB_4444_SkColorType, 281cb93a386Sopenharmony_ci kRGB_888x_SkColorType, 282cb93a386Sopenharmony_ci kRGBA_8888_SkColorType, 283cb93a386Sopenharmony_ci kBGRA_8888_SkColorType, 284cb93a386Sopenharmony_ci kRGB_101010x_SkColorType, 285cb93a386Sopenharmony_ci kRGBA_1010102_SkColorType, 286cb93a386Sopenharmony_ci }; 287cb93a386Sopenharmony_ci 288cb93a386Sopenharmony_ci for (SkColorType ct : colorTypes) { 289cb93a386Sopenharmony_ci SkImageInfo info = SkImageInfo::Make(1,1, (SkColorType)ct, kPremul_SkAlphaType); 290cb93a386Sopenharmony_ci 291cb93a386Sopenharmony_ci SkBitmap bm; 292cb93a386Sopenharmony_ci bm.allocPixels(info); 293cb93a386Sopenharmony_ci 294cb93a386Sopenharmony_ci bm.eraseColor(0x00000000); 295cb93a386Sopenharmony_ci if (SkColorTypeIsAlwaysOpaque(ct)) { 296cb93a386Sopenharmony_ci REPORTER_ASSERT(r, bm.getColor(0,0) == 0xff000000); 297cb93a386Sopenharmony_ci } else { 298cb93a386Sopenharmony_ci REPORTER_ASSERT(r, bm.getColor(0,0) == 0x00000000); 299cb93a386Sopenharmony_ci } 300cb93a386Sopenharmony_ci 301cb93a386Sopenharmony_ci bm.eraseColor(0xaabbccdd); 302cb93a386Sopenharmony_ci REPORTER_ASSERT(r, bm.getColor(0,0) != 0xff000000); 303cb93a386Sopenharmony_ci REPORTER_ASSERT(r, bm.getColor(0,0) != 0x00000000); 304cb93a386Sopenharmony_ci } 305cb93a386Sopenharmony_ci} 306cb93a386Sopenharmony_ci 307cb93a386Sopenharmony_cistatic void check_alphas(skiatest::Reporter* reporter, const SkBitmap& bm, 308cb93a386Sopenharmony_ci bool (*pred)(float expected, float actual), SkColorType ct) { 309cb93a386Sopenharmony_ci SkASSERT(bm.width() == 16); 310cb93a386Sopenharmony_ci SkASSERT(bm.height() == 16); 311cb93a386Sopenharmony_ci 312cb93a386Sopenharmony_ci int alpha = 0; 313cb93a386Sopenharmony_ci for (int y = 0; y < 16; ++y) { 314cb93a386Sopenharmony_ci for (int x = 0; x < 16; ++x) { 315cb93a386Sopenharmony_ci float expected = alpha / 255.0f; 316cb93a386Sopenharmony_ci float actual = bm.getAlphaf(x, y); 317cb93a386Sopenharmony_ci if (!pred(expected, actual)) { 318cb93a386Sopenharmony_ci ERRORF(reporter, "%s: got %g, want %g\n", 319cb93a386Sopenharmony_ci ToolUtils::colortype_name(ct), actual, expected); 320cb93a386Sopenharmony_ci } 321cb93a386Sopenharmony_ci alpha += 1; 322cb93a386Sopenharmony_ci } 323cb93a386Sopenharmony_ci } 324cb93a386Sopenharmony_ci} 325cb93a386Sopenharmony_ci 326cb93a386Sopenharmony_cistatic bool unit_compare(float expected, float actual, float tol = 1.0f/(1<<12)) { 327cb93a386Sopenharmony_ci SkASSERT(expected >= 0 && expected <= 1); 328cb93a386Sopenharmony_ci SkASSERT( actual >= 0 && actual <= 1); 329cb93a386Sopenharmony_ci if (expected == 0 || expected == 1) { 330cb93a386Sopenharmony_ci return actual == expected; 331cb93a386Sopenharmony_ci } else { 332cb93a386Sopenharmony_ci return SkScalarNearlyEqual(expected, actual, tol); 333cb93a386Sopenharmony_ci } 334cb93a386Sopenharmony_ci} 335cb93a386Sopenharmony_ci 336cb93a386Sopenharmony_cistatic float unit_discretize(float value, float scale) { 337cb93a386Sopenharmony_ci SkASSERT(value >= 0 && value <= 1); 338cb93a386Sopenharmony_ci if (value == 1) { 339cb93a386Sopenharmony_ci return 1; 340cb93a386Sopenharmony_ci } else { 341cb93a386Sopenharmony_ci return sk_float_floor(value * scale + 0.5f) / scale; 342cb93a386Sopenharmony_ci } 343cb93a386Sopenharmony_ci} 344cb93a386Sopenharmony_ci 345cb93a386Sopenharmony_ciDEF_TEST(getalphaf, reporter) { 346cb93a386Sopenharmony_ci SkImageInfo info = SkImageInfo::MakeN32Premul(16, 16); 347cb93a386Sopenharmony_ci SkBitmap bm; 348cb93a386Sopenharmony_ci bm.allocPixels(info); 349cb93a386Sopenharmony_ci 350cb93a386Sopenharmony_ci int alpha = 0; 351cb93a386Sopenharmony_ci for (int y = 0; y < 16; ++y) { 352cb93a386Sopenharmony_ci for (int x = 0; x < 16; ++x) { 353cb93a386Sopenharmony_ci *bm.getAddr32(x, y) = alpha++ << 24; 354cb93a386Sopenharmony_ci } 355cb93a386Sopenharmony_ci } 356cb93a386Sopenharmony_ci 357cb93a386Sopenharmony_ci auto nearly = [](float expected, float actual) -> bool { 358cb93a386Sopenharmony_ci return unit_compare(expected, actual); 359cb93a386Sopenharmony_ci }; 360cb93a386Sopenharmony_ci auto nearly4bit = [](float expected, float actual) -> bool { 361cb93a386Sopenharmony_ci expected = unit_discretize(expected, 15); 362cb93a386Sopenharmony_ci return unit_compare(expected, actual); 363cb93a386Sopenharmony_ci }; 364cb93a386Sopenharmony_ci auto nearly2bit = [](float expected, float actual) -> bool { 365cb93a386Sopenharmony_ci expected = unit_discretize(expected, 3); 366cb93a386Sopenharmony_ci return unit_compare(expected, actual); 367cb93a386Sopenharmony_ci }; 368cb93a386Sopenharmony_ci auto opaque = [](float expected, float actual) -> bool { 369cb93a386Sopenharmony_ci return actual == 1.0f; 370cb93a386Sopenharmony_ci }; 371cb93a386Sopenharmony_ci 372cb93a386Sopenharmony_ci auto nearly_half = [](float expected, float actual) -> bool { 373cb93a386Sopenharmony_ci return unit_compare(expected, actual, 1.0f/(1<<10)); 374cb93a386Sopenharmony_ci }; 375cb93a386Sopenharmony_ci 376cb93a386Sopenharmony_ci const struct { 377cb93a386Sopenharmony_ci SkColorType fColorType; 378cb93a386Sopenharmony_ci bool (*fPred)(float, float); 379cb93a386Sopenharmony_ci } recs[] = { 380cb93a386Sopenharmony_ci { kRGB_565_SkColorType, opaque }, 381cb93a386Sopenharmony_ci { kGray_8_SkColorType, opaque }, 382cb93a386Sopenharmony_ci { kR8G8_unorm_SkColorType, opaque }, 383cb93a386Sopenharmony_ci { kR16G16_unorm_SkColorType, opaque }, 384cb93a386Sopenharmony_ci { kR16G16_float_SkColorType, opaque }, 385cb93a386Sopenharmony_ci { kRGB_888x_SkColorType, opaque }, 386cb93a386Sopenharmony_ci { kRGB_101010x_SkColorType, opaque }, 387cb93a386Sopenharmony_ci 388cb93a386Sopenharmony_ci { kAlpha_8_SkColorType, nearly }, 389cb93a386Sopenharmony_ci { kA16_unorm_SkColorType, nearly }, 390cb93a386Sopenharmony_ci { kA16_float_SkColorType, nearly_half }, 391cb93a386Sopenharmony_ci { kRGBA_8888_SkColorType, nearly }, 392cb93a386Sopenharmony_ci { kBGRA_8888_SkColorType, nearly }, 393cb93a386Sopenharmony_ci { kR16G16B16A16_unorm_SkColorType, nearly }, 394cb93a386Sopenharmony_ci { kRGBA_F16_SkColorType, nearly_half }, 395cb93a386Sopenharmony_ci { kRGBA_F32_SkColorType, nearly }, 396cb93a386Sopenharmony_ci 397cb93a386Sopenharmony_ci { kRGBA_1010102_SkColorType, nearly2bit }, 398cb93a386Sopenharmony_ci 399cb93a386Sopenharmony_ci { kARGB_4444_SkColorType, nearly4bit }, 400cb93a386Sopenharmony_ci }; 401cb93a386Sopenharmony_ci 402cb93a386Sopenharmony_ci for (const auto& rec : recs) { 403cb93a386Sopenharmony_ci SkBitmap tmp; 404cb93a386Sopenharmony_ci tmp.allocPixels(bm.info().makeColorType(rec.fColorType)); 405cb93a386Sopenharmony_ci if (bm.readPixels(tmp.pixmap())) { 406cb93a386Sopenharmony_ci check_alphas(reporter, tmp, rec.fPred, rec.fColorType); 407cb93a386Sopenharmony_ci } else { 408cb93a386Sopenharmony_ci SkDebugf("can't readpixels\n"); 409cb93a386Sopenharmony_ci } 410cb93a386Sopenharmony_ci } 411cb93a386Sopenharmony_ci} 412cb93a386Sopenharmony_ci 413cb93a386Sopenharmony_ci/* computeByteSize() is documented to return 0 if height is zero, but does not 414cb93a386Sopenharmony_ci * special-case width==0, so computeByteSize() can return non-zero for that 415cb93a386Sopenharmony_ci * (since it is defined to return (height-1)*rb + ... 416cb93a386Sopenharmony_ci * 417cb93a386Sopenharmony_ci * Test that allocPixels() respects this, and allocates a buffer as large as 418cb93a386Sopenharmony_ci * computeByteSize()... even though the bitmap is logicallly empty. 419cb93a386Sopenharmony_ci */ 420cb93a386Sopenharmony_ciDEF_TEST(bitmap_zerowidth_crbug_1103827, reporter) { 421cb93a386Sopenharmony_ci const size_t big_rb = 1 << 16; 422cb93a386Sopenharmony_ci 423cb93a386Sopenharmony_ci struct { 424cb93a386Sopenharmony_ci int width, height; 425cb93a386Sopenharmony_ci size_t rowbytes, expected_size; 426cb93a386Sopenharmony_ci } rec[] = { 427cb93a386Sopenharmony_ci { 2, 0, big_rb, 0 }, // zero-height means zero-size 428cb93a386Sopenharmony_ci { 0, 2, big_rb, big_rb }, // zero-width is computed normally 429cb93a386Sopenharmony_ci }; 430cb93a386Sopenharmony_ci 431cb93a386Sopenharmony_ci for (const auto& r : rec) { 432cb93a386Sopenharmony_ci auto info = SkImageInfo::Make(r.width, r.height, 433cb93a386Sopenharmony_ci kRGBA_8888_SkColorType, kPremul_SkAlphaType); 434cb93a386Sopenharmony_ci size_t size = info.computeByteSize(r.rowbytes); 435cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, size == r.expected_size); 436cb93a386Sopenharmony_ci 437cb93a386Sopenharmony_ci SkBitmap bm; 438cb93a386Sopenharmony_ci bm.setInfo(info, r.rowbytes); 439cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, size == bm.computeByteSize()); 440cb93a386Sopenharmony_ci 441cb93a386Sopenharmony_ci // Be sure we can actually write to that much memory. If the bitmap underallocated 442cb93a386Sopenharmony_ci // the buffer, this should trash memory and crash (we hope). 443cb93a386Sopenharmony_ci bm.allocPixels(); 444cb93a386Sopenharmony_ci sk_bzero(bm.getPixels(), size); 445cb93a386Sopenharmony_ci } 446cb93a386Sopenharmony_ci} 447