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(&copy, 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