blob: 83317d95e49f47bbdd34e4eae2090321a9bc6d1f [file] [log] [blame]
msarettdc27a642016-06-06 12:02:31 -07001/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "Resources.h"
9#include "SkCodec.h"
msarettc0444612016-09-16 11:45:58 -070010#include "SkCodecPriv.h"
msarettdc27a642016-06-06 12:02:31 -070011#include "SkColorPriv.h"
12#include "SkColorSpace.h"
raftias25636012016-11-11 15:27:39 -080013#include "SkColorSpace_A2B.h"
msarettdc27a642016-06-06 12:02:31 -070014#include "SkColorSpace_Base.h"
raftias94888332016-10-18 10:02:51 -070015#include "SkColorSpace_XYZ.h"
msarett31d097e82016-10-11 12:15:03 -070016#include "SkColorSpaceXform_Base.h"
msarettdc27a642016-06-06 12:02:31 -070017#include "Test.h"
18
raftias54761282016-12-01 13:44:07 -050019static constexpr int kChannels = 3;
20
msarettdc27a642016-06-06 12:02:31 -070021class ColorSpaceXformTest {
22public:
mtkleinb4359632016-07-18 11:16:14 -070023 static std::unique_ptr<SkColorSpaceXform> CreateIdentityXform(const sk_sp<SkGammas>& gammas) {
24 // Logically we can pass any matrix here. For simplicty, pass I(), i.e. D50 XYZ gamut.
raftias94888332016-10-18 10:02:51 -070025 sk_sp<SkColorSpace> space(new SkColorSpace_XYZ(
Matt Sarettf3880932017-03-24 10:06:03 -040026 kNonStandard_SkGammaNamed, gammas, SkMatrix::I(), nullptr));
msarett9dc6cf62016-08-23 17:53:06 -070027
28 // Use special testing entry point, so we don't skip the xform, even though src == dst.
raftias94888332016-10-18 10:02:51 -070029 return SlowIdentityXform(static_cast<SkColorSpace_XYZ*>(space.get()));
msarettdc27a642016-06-06 12:02:31 -070030 }
raftias25636012016-11-11 15:27:39 -080031
32 static std::unique_ptr<SkColorSpaceXform> CreateIdentityXform_A2B(
33 SkGammaNamed gammaNamed, const sk_sp<SkGammas>& gammas) {
34 std::vector<SkColorSpace_A2B::Element> srcElements;
35 // sRGB
36 const float values[16] = {
37 0.4358f, 0.3853f, 0.1430f, 0.0f,
38 0.2224f, 0.7170f, 0.0606f, 0.0f,
39 0.0139f, 0.0971f, 0.7139f, 0.0f,
40 0.0000f, 0.0000f, 0.0000f, 1.0f
41 };
42 SkMatrix44 arbitraryMatrix{SkMatrix44::kUninitialized_Constructor};
43 arbitraryMatrix.setRowMajorf(values);
44 if (kNonStandard_SkGammaNamed == gammaNamed) {
raftias54761282016-12-01 13:44:07 -050045 SkASSERT(gammas);
raftias25636012016-11-11 15:27:39 -080046 srcElements.push_back(SkColorSpace_A2B::Element(gammas));
47 } else {
raftias54761282016-12-01 13:44:07 -050048 srcElements.push_back(SkColorSpace_A2B::Element(gammaNamed, kChannels));
raftias25636012016-11-11 15:27:39 -080049 }
50 srcElements.push_back(SkColorSpace_A2B::Element(arbitraryMatrix));
raftias54761282016-12-01 13:44:07 -050051 auto srcSpace =
52 ColorSpaceXformTest::CreateA2BSpace(SkColorSpace_A2B::PCS::kXYZ,
Matt Sarett523116d2017-01-12 18:36:38 -050053 SkColorSpace_Base::kRGB_ICCTypeFlag,
raftias54761282016-12-01 13:44:07 -050054 std::move(srcElements));
raftias25636012016-11-11 15:27:39 -080055 sk_sp<SkColorSpace> dstSpace(new SkColorSpace_XYZ(gammaNamed, gammas, arbitraryMatrix,
Matt Sarettf3880932017-03-24 10:06:03 -040056 nullptr));
raftias25636012016-11-11 15:27:39 -080057
58 return SkColorSpaceXform::New(static_cast<SkColorSpace_A2B*>(srcSpace.get()),
59 static_cast<SkColorSpace_XYZ*>(dstSpace.get()));
60 }
61
62 static sk_sp<SkColorSpace> CreateA2BSpace(SkColorSpace_A2B::PCS pcs,
Matt Sarett523116d2017-01-12 18:36:38 -050063 SkColorSpace_Base::ICCTypeFlag iccType,
raftias25636012016-11-11 15:27:39 -080064 std::vector<SkColorSpace_A2B::Element> elements) {
Matt Sarett523116d2017-01-12 18:36:38 -050065 return sk_sp<SkColorSpace>(new SkColorSpace_A2B(iccType, std::move(elements),
raftias54761282016-12-01 13:44:07 -050066 pcs, nullptr));
raftias25636012016-11-11 15:27:39 -080067 }
msarettdc27a642016-06-06 12:02:31 -070068};
69
Mike Kleinc7d9c0b2017-04-17 14:43:59 -040070static bool almost_equal(int x, int y, int tol=1) {
71 return SkTAbs(x-y) <= tol;
msarettb3906762016-06-22 14:07:48 -070072}
73
Matt Sarettf4898862016-10-16 10:20:41 -040074static void test_identity_xform(skiatest::Reporter* r, const sk_sp<SkGammas>& gammas,
75 bool repeat) {
msarettdc27a642016-06-06 12:02:31 -070076 // Arbitrary set of 10 pixels
77 constexpr int width = 10;
78 constexpr uint32_t srcPixels[width] = {
79 0xFFABCDEF, 0xFF146829, 0xFF382759, 0xFF184968, 0xFFDE8271,
msarettb3906762016-06-22 14:07:48 -070080 0xFF32AB52, 0xFF0383BC, 0xFF000102, 0xFFFFFFFF, 0xFFDDEEFF, };
msarettdc27a642016-06-06 12:02:31 -070081 uint32_t dstPixels[width];
82
mtkleinb4359632016-07-18 11:16:14 -070083 // Create and perform an identity xform.
84 std::unique_ptr<SkColorSpaceXform> xform = ColorSpaceXformTest::CreateIdentityXform(gammas);
msarett31d097e82016-10-11 12:15:03 -070085 bool result = xform->apply(select_xform_format(kN32_SkColorType), dstPixels,
86 SkColorSpaceXform::kBGRA_8888_ColorFormat, srcPixels, width,
87 kOpaque_SkAlphaType);
88 REPORTER_ASSERT(r, result);
msarettdc27a642016-06-06 12:02:31 -070089
mtkleinb4359632016-07-18 11:16:14 -070090 // Since the src->dst matrix is the identity, and the gamma curves match,
91 // the pixels should be unchanged.
msarettdc27a642016-06-06 12:02:31 -070092 for (int i = 0; i < width; i++) {
msarettb3906762016-06-22 14:07:48 -070093 REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 0) & 0xFF),
msarettcf7b8772016-09-22 12:37:04 -070094 SkGetPackedB32(dstPixels[i])));
msarettb3906762016-06-22 14:07:48 -070095 REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 8) & 0xFF),
msarett9dc6cf62016-08-23 17:53:06 -070096 SkGetPackedG32(dstPixels[i])));
msarettb3906762016-06-22 14:07:48 -070097 REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 16) & 0xFF),
msarettcf7b8772016-09-22 12:37:04 -070098 SkGetPackedR32(dstPixels[i])));
msarettb3906762016-06-22 14:07:48 -070099 REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 24) & 0xFF),
msarett9dc6cf62016-08-23 17:53:06 -0700100 SkGetPackedA32(dstPixels[i])));
msarettdc27a642016-06-06 12:02:31 -0700101 }
Matt Sarettf4898862016-10-16 10:20:41 -0400102
103 if (repeat) {
104 // We should cache part of the transform after the run. So it is interesting
105 // to make sure it still runs correctly the second time.
106 test_identity_xform(r, gammas, false);
107 }
msarettdc27a642016-06-06 12:02:31 -0700108}
109
raftias25636012016-11-11 15:27:39 -0800110static void test_identity_xform_A2B(skiatest::Reporter* r, SkGammaNamed gammaNamed,
Mike Kleinc7d9c0b2017-04-17 14:43:59 -0400111 const sk_sp<SkGammas>& gammas, int tol=1) {
raftias25636012016-11-11 15:27:39 -0800112 // Arbitrary set of 10 pixels
113 constexpr int width = 10;
114 constexpr uint32_t srcPixels[width] = {
115 0xFFABCDEF, 0xFF146829, 0xFF382759, 0xFF184968, 0xFFDE8271,
116 0xFF32AB52, 0xFF0383BC, 0xFF000102, 0xFFFFFFFF, 0xFFDDEEFF, };
117 uint32_t dstPixels[width];
118
119 // Create and perform an identity xform.
120 auto xform = ColorSpaceXformTest::CreateIdentityXform_A2B(gammaNamed, gammas);
121 bool result = xform->apply(select_xform_format(kN32_SkColorType), dstPixels,
122 SkColorSpaceXform::kBGRA_8888_ColorFormat, srcPixels, width,
123 kOpaque_SkAlphaType);
124 REPORTER_ASSERT(r, result);
125
126 // Since the src->dst matrix is the identity, and the gamma curves match,
Mike Kleinc7d9c0b2017-04-17 14:43:59 -0400127 // the pixels should be ~unchanged.
raftias25636012016-11-11 15:27:39 -0800128 for (int i = 0; i < width; i++) {
129 REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 0) & 0xFF),
Mike Kleinc7d9c0b2017-04-17 14:43:59 -0400130 SkGetPackedB32(dstPixels[i]), tol));
raftias25636012016-11-11 15:27:39 -0800131 REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 8) & 0xFF),
Mike Kleinc7d9c0b2017-04-17 14:43:59 -0400132 SkGetPackedG32(dstPixels[i]), tol));
raftias25636012016-11-11 15:27:39 -0800133 REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 16) & 0xFF),
Mike Kleinc7d9c0b2017-04-17 14:43:59 -0400134 SkGetPackedR32(dstPixels[i]), tol));
raftias25636012016-11-11 15:27:39 -0800135 REPORTER_ASSERT(r, almost_equal(((srcPixels[i] >> 24) & 0xFF),
Mike Kleinc7d9c0b2017-04-17 14:43:59 -0400136 SkGetPackedA32(dstPixels[i]), tol));
raftias25636012016-11-11 15:27:39 -0800137 }
raftias25636012016-11-11 15:27:39 -0800138}
139
msarettdc27a642016-06-06 12:02:31 -0700140DEF_TEST(ColorSpaceXform_TableGamma, r) {
141 // Lookup-table based gamma curves
msarettdc27a642016-06-06 12:02:31 -0700142 constexpr size_t tableSize = 10;
msarett1b93bd12016-07-21 07:11:26 -0700143 void* memory = sk_malloc_throw(sizeof(SkGammas) + sizeof(float) * tableSize);
raftias54761282016-12-01 13:44:07 -0500144 sk_sp<SkGammas> gammas = sk_sp<SkGammas>(new (memory) SkGammas(kChannels));
145 for (int i = 0; i < kChannels; ++i) {
146 gammas->fType[i] = SkGammas::Type::kTable_Type;
147 gammas->fData[i].fTable.fSize = tableSize;
148 gammas->fData[i].fTable.fOffset = 0;
149 }
150
msarett1b93bd12016-07-21 07:11:26 -0700151 float* table = SkTAddOffset<float>(memory, sizeof(SkGammas));
msarett1b93bd12016-07-21 07:11:26 -0700152 table[0] = 0.00f;
153 table[1] = 0.05f;
154 table[2] = 0.10f;
155 table[3] = 0.15f;
156 table[4] = 0.25f;
157 table[5] = 0.35f;
158 table[6] = 0.45f;
159 table[7] = 0.60f;
160 table[8] = 0.75f;
161 table[9] = 1.00f;
Mike Kleinc7d9c0b2017-04-17 14:43:59 -0400162 // This table's pretty small compared to real ones in the wild (think 256),
163 // so we give test_identity_xform_A2B a wide tolerance.
164 // This lets us implement table transfer functions with a single lookup.
165 const int tolerance = 13;
166
Matt Sarettf4898862016-10-16 10:20:41 -0400167 test_identity_xform(r, gammas, true);
Mike Kleinc7d9c0b2017-04-17 14:43:59 -0400168 test_identity_xform_A2B(r, kNonStandard_SkGammaNamed, gammas, tolerance);
msarettdc27a642016-06-06 12:02:31 -0700169}
170
171DEF_TEST(ColorSpaceXform_ParametricGamma, r) {
172 // Parametric gamma curves
Matt Sarettdf44fc52016-10-11 16:57:50 -0400173 void* memory = sk_malloc_throw(sizeof(SkGammas) + sizeof(SkColorSpaceTransferFn));
raftias54761282016-12-01 13:44:07 -0500174 sk_sp<SkGammas> gammas = sk_sp<SkGammas>(new (memory) SkGammas(kChannels));
175 for (int i = 0; i < kChannels; ++i) {
176 gammas->fType[i] = SkGammas::Type::kParam_Type;
177 gammas->fData[i].fParamOffset = 0;
178 }
179
Matt Sarettdf44fc52016-10-11 16:57:50 -0400180 SkColorSpaceTransferFn* params = SkTAddOffset<SkColorSpaceTransferFn>
181 (memory, sizeof(SkGammas));
msarettdc27a642016-06-06 12:02:31 -0700182
Matt Sarett24107172016-12-19 14:33:35 -0500183 // Interval.
msarett1b93bd12016-07-21 07:11:26 -0700184 params->fD = 0.04045f;
msarettdc27a642016-06-06 12:02:31 -0700185
msarettb3906762016-06-22 14:07:48 -0700186 // First equation:
Matt Sarett24107172016-12-19 14:33:35 -0500187 params->fC = 1.0f / 12.92f;
msarett1b93bd12016-07-21 07:11:26 -0700188 params->fF = 0.0f;
msarettdc27a642016-06-06 12:02:31 -0700189
msarettb3906762016-06-22 14:07:48 -0700190 // Second equation:
191 // Note that the function is continuous (it's actually sRGB).
msarett1b93bd12016-07-21 07:11:26 -0700192 params->fA = 1.0f / 1.055f;
193 params->fB = 0.055f / 1.055f;
Matt Sarett24107172016-12-19 14:33:35 -0500194 params->fE = 0.0f;
msarett1b93bd12016-07-21 07:11:26 -0700195 params->fG = 2.4f;
Matt Sarettf4898862016-10-16 10:20:41 -0400196 test_identity_xform(r, gammas, true);
raftias54761282016-12-01 13:44:07 -0500197 test_identity_xform_A2B(r, kNonStandard_SkGammaNamed, gammas);
msarettdc27a642016-06-06 12:02:31 -0700198}
199
200DEF_TEST(ColorSpaceXform_ExponentialGamma, r) {
201 // Exponential gamma curves
raftias54761282016-12-01 13:44:07 -0500202 sk_sp<SkGammas> gammas = sk_sp<SkGammas>(new SkGammas(kChannels));
203 for (int i = 0; i < kChannels; ++i) {
204 gammas->fType[i] = SkGammas::Type::kValue_Type;
205 gammas->fData[i].fValue = 1.4f;
206 }
Matt Sarettf4898862016-10-16 10:20:41 -0400207 test_identity_xform(r, gammas, true);
raftias54761282016-12-01 13:44:07 -0500208 test_identity_xform_A2B(r, kNonStandard_SkGammaNamed, gammas);
msarett1b93bd12016-07-21 07:11:26 -0700209}
210
msarett55bcc8e2016-09-09 07:48:05 -0700211DEF_TEST(ColorSpaceXform_NamedGamma, r) {
raftias54761282016-12-01 13:44:07 -0500212 sk_sp<SkGammas> gammas = sk_sp<SkGammas>(new SkGammas(kChannels));
213 gammas->fType[0] = gammas->fType[1] = gammas->fType[2] = SkGammas::Type::kNamed_Type;
214 gammas->fData[0].fNamed = kSRGB_SkGammaNamed;
215 gammas->fData[1].fNamed = k2Dot2Curve_SkGammaNamed;
216 gammas->fData[2].fNamed = kLinear_SkGammaNamed;
Matt Sarettf4898862016-10-16 10:20:41 -0400217 test_identity_xform(r, gammas, true);
raftias54761282016-12-01 13:44:07 -0500218 test_identity_xform_A2B(r, kNonStandard_SkGammaNamed, gammas);
219 test_identity_xform_A2B(r, kSRGB_SkGammaNamed, nullptr);
220 test_identity_xform_A2B(r, k2Dot2Curve_SkGammaNamed, nullptr);
221 test_identity_xform_A2B(r, kLinear_SkGammaNamed, nullptr);
msarett55bcc8e2016-09-09 07:48:05 -0700222}
223
msarett1b93bd12016-07-21 07:11:26 -0700224DEF_TEST(ColorSpaceXform_NonMatchingGamma, r) {
225 constexpr size_t tableSize = 10;
226 void* memory = sk_malloc_throw(sizeof(SkGammas) + sizeof(float) * tableSize +
Matt Sarettdf44fc52016-10-11 16:57:50 -0400227 sizeof(SkColorSpaceTransferFn));
raftias54761282016-12-01 13:44:07 -0500228 sk_sp<SkGammas> gammas = sk_sp<SkGammas>(new (memory) SkGammas(kChannels));
msarett1b93bd12016-07-21 07:11:26 -0700229
230 float* table = SkTAddOffset<float>(memory, sizeof(SkGammas));
231 table[0] = 0.00f;
232 table[1] = 0.15f;
233 table[2] = 0.20f;
234 table[3] = 0.25f;
235 table[4] = 0.35f;
236 table[5] = 0.45f;
237 table[6] = 0.55f;
238 table[7] = 0.70f;
239 table[8] = 0.85f;
240 table[9] = 1.00f;
241
Matt Sarettdf44fc52016-10-11 16:57:50 -0400242 SkColorSpaceTransferFn* params = SkTAddOffset<SkColorSpaceTransferFn>(memory,
243 sizeof(SkGammas) + sizeof(float) * tableSize);
msarett1b93bd12016-07-21 07:11:26 -0700244 params->fA = 1.0f / 1.055f;
245 params->fB = 0.055f / 1.055f;
Matt Sarett24107172016-12-19 14:33:35 -0500246 params->fC = 1.0f / 12.92f;
msarett1b93bd12016-07-21 07:11:26 -0700247 params->fD = 0.04045f;
Matt Sarett24107172016-12-19 14:33:35 -0500248 params->fE = 0.0f;
msarett1b93bd12016-07-21 07:11:26 -0700249 params->fF = 0.0f;
250 params->fG = 2.4f;
251
raftias54761282016-12-01 13:44:07 -0500252 gammas->fType[0] = SkGammas::Type::kValue_Type;
253 gammas->fData[0].fValue = 1.2f;
msarett1b93bd12016-07-21 07:11:26 -0700254
Mike Klein44375172017-04-17 19:32:05 -0400255 // See ColorSpaceXform_TableGamma... we've decided to allow some tolerance
256 // for SkJumper's implementation of tables.
257 const int tolerance = 12;
raftias54761282016-12-01 13:44:07 -0500258 gammas->fType[1] = SkGammas::Type::kTable_Type;
259 gammas->fData[1].fTable.fSize = tableSize;
260 gammas->fData[1].fTable.fOffset = 0;
msarett1b93bd12016-07-21 07:11:26 -0700261
raftias54761282016-12-01 13:44:07 -0500262 gammas->fType[2] = SkGammas::Type::kParam_Type;
263 gammas->fData[2].fParamOffset = sizeof(float) * tableSize;
msarett1b93bd12016-07-21 07:11:26 -0700264
Matt Sarettf4898862016-10-16 10:20:41 -0400265 test_identity_xform(r, gammas, true);
Mike Klein44375172017-04-17 19:32:05 -0400266 test_identity_xform_A2B(r, kNonStandard_SkGammaNamed, gammas, tolerance);
raftias25636012016-11-11 15:27:39 -0800267}
268
269DEF_TEST(ColorSpaceXform_A2BCLUT, r) {
270 constexpr int inputChannels = 3;
271 constexpr int gp = 4; // # grid points
272
273 constexpr int numEntries = gp*gp*gp*3;
raftias54761282016-12-01 13:44:07 -0500274 const uint8_t gridPoints[3] = {gp, gp, gp};
raftias25636012016-11-11 15:27:39 -0800275 void* memory = sk_malloc_throw(sizeof(SkColorLookUpTable) + sizeof(float) * numEntries);
276 sk_sp<SkColorLookUpTable> colorLUT(new (memory) SkColorLookUpTable(inputChannels, gridPoints));
277 // make a CLUT that rotates R, G, and B ie R->G, G->B, B->R
278 float* table = SkTAddOffset<float>(memory, sizeof(SkColorLookUpTable));
279 for (int r = 0; r < gp; ++r) {
280 for (int g = 0; g < gp; ++g) {
281 for (int b = 0; b < gp; ++b) {
282 table[3*(gp*gp*r + gp*g + b) + 0] = g * (1.f / (gp - 1.f));
283 table[3*(gp*gp*r + gp*g + b) + 1] = b * (1.f / (gp - 1.f));
284 table[3*(gp*gp*r + gp*g + b) + 2] = r * (1.f / (gp - 1.f));
285 }
286 }
287 }
288
289 // build an even distribution of pixels every (7 / 255) steps
290 // to test the xform on
291 constexpr int pixelgp = 7;
292 constexpr int numPixels = pixelgp*pixelgp*pixelgp;
293 SkAutoTMalloc<uint32_t> srcPixels(numPixels);
294 int srcIndex = 0;
295 for (int r = 0; r < pixelgp; ++r) {
296 for (int g = 0; g < pixelgp; ++g) {
297 for (int b = 0; b < pixelgp; ++b) {
298 const int red = (int) (r * (255.f / (pixelgp - 1.f)));
299 const int green = (int) (g * (255.f / (pixelgp - 1.f)));
300 const int blue = (int) (b * (255.f / (pixelgp - 1.f)));
301 srcPixels[srcIndex] = SkColorSetRGB(red, green, blue);
302 ++srcIndex;
303 }
304 }
305 }
306 SkAutoTMalloc<uint32_t> dstPixels(numPixels);
307
308 // src space is identity besides CLUT
309 std::vector<SkColorSpace_A2B::Element> srcElements;
310 srcElements.push_back(SkColorSpace_A2B::Element(std::move(colorLUT)));
311 auto srcSpace = ColorSpaceXformTest::CreateA2BSpace(SkColorSpace_A2B::PCS::kXYZ,
Matt Sarett523116d2017-01-12 18:36:38 -0500312 SkColorSpace_Base::kRGB_ICCTypeFlag,
raftias25636012016-11-11 15:27:39 -0800313 std::move(srcElements));
314 // dst space is entirely identity
315 auto dstSpace = SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma, SkMatrix44::I());
316 auto xform = SkColorSpaceXform::New(srcSpace.get(), dstSpace.get());
317 bool result = xform->apply(SkColorSpaceXform::kRGBA_8888_ColorFormat, dstPixels.get(),
318 SkColorSpaceXform::kRGBA_8888_ColorFormat, srcPixels.get(),
319 numPixels, kOpaque_SkAlphaType);
320 REPORTER_ASSERT(r, result);
321
322 for (int i = 0; i < numPixels; ++i) {
323 REPORTER_ASSERT(r, almost_equal(SkColorGetR(srcPixels[i]),
324 SkColorGetG(dstPixels[i])));
325 REPORTER_ASSERT(r, almost_equal(SkColorGetG(srcPixels[i]),
326 SkColorGetB(dstPixels[i])));
327 REPORTER_ASSERT(r, almost_equal(SkColorGetB(srcPixels[i]),
328 SkColorGetR(dstPixels[i])));
329 }
msarettdc27a642016-06-06 12:02:31 -0700330}
raftiasc6cc28c2016-09-29 14:31:44 -0400331
Matt Sarettc55bc9a2017-01-13 13:58:57 -0500332DEF_TEST(SkColorSpaceXform_LoadTail, r) {
Matt Sarettacdb6d32017-01-13 15:42:45 -0500333 std::unique_ptr<uint64_t[]> srcPixel(new uint64_t[1]);
Matt Sarettc55bc9a2017-01-13 13:58:57 -0500334 srcPixel[0] = 0;
335 uint32_t dstPixel;
Matt Sarett77a7a1b2017-02-07 13:56:11 -0500336 sk_sp<SkColorSpace> adobe = SkColorSpace_Base::MakeNamed(SkColorSpace_Base::kAdobeRGB_Named);
337 sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
Matt Sarettc55bc9a2017-01-13 13:58:57 -0500338 std::unique_ptr<SkColorSpaceXform> xform = SkColorSpaceXform::New(adobe.get(), srgb.get());
339
340 // ASAN will catch us if we read past the tail.
341 bool success = xform->apply(SkColorSpaceXform::kRGBA_8888_ColorFormat, &dstPixel,
Matt Sarettacdb6d32017-01-13 15:42:45 -0500342 SkColorSpaceXform::kRGBA_U16_BE_ColorFormat, srcPixel.get(), 1,
Matt Sarettc55bc9a2017-01-13 13:58:57 -0500343 kUnpremul_SkAlphaType);
344 REPORTER_ASSERT(r, success);
345}
346