OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkCanvas.h" | 8 #include "SkCanvas.h" |
9 #include "SkColorPriv.h" | 9 #include "SkColorPriv.h" |
10 #include "SkColorShader.h" | 10 #include "SkColorShader.h" |
11 #include "SkGradientShader.h" | 11 #include "SkGradientShader.h" |
12 #include "SkShader.h" | 12 #include "SkShader.h" |
13 #include "SkSurface.h" | 13 #include "SkSurface.h" |
14 #include "SkTemplates.h" | 14 #include "SkTemplates.h" |
15 #include "Test.h" | 15 #include "Test.h" |
16 | 16 |
17 // https://code.google.com/p/chromium/issues/detail?id=448299 | 17 // https://code.google.com/p/chromium/issues/detail?id=448299 |
18 // Giant (inverse) matrix causes overflow when converting/computing using 32.32 | 18 // Giant (inverse) matrix causes overflow when converting/computing using 32.32 |
19 // Before the fix, we would assert (and then crash). | 19 // Before the fix, we would assert (and then crash). |
20 static void test_big_grad(skiatest::Reporter* reporter) { | 20 static void test_big_grad(skiatest::Reporter* reporter) { |
21 const SkColor colors[] = { SK_ColorRED, SK_ColorBLUE }; | 21 const SkColor colors[] = { SK_ColorRED, SK_ColorBLUE }; |
22 const SkPoint pts[] = {{ 15, 14.7112684f }, { 0.709064007f, 12.6108112f }}; | 22 const SkPoint pts[] = {{ 15, 14.7112684f }, { 0.709064007f, 12.6108112f }}; |
| 23 SkShader* s = SkGradientShader::CreateLinear(pts, colors, nullptr, 2, SkShad
er::kClamp_TileMode); |
23 SkPaint paint; | 24 SkPaint paint; |
24 paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, 2, | 25 paint.setShader(s)->unref(); |
25 SkShader::kClamp_TileMode)); | |
26 | 26 |
27 SkBitmap bm; | 27 SkBitmap bm; |
28 bm.allocN32Pixels(2000, 1); | 28 bm.allocN32Pixels(2000, 1); |
29 SkCanvas c(bm); | 29 SkCanvas c(bm); |
30 | 30 |
31 const SkScalar affine[] = { | 31 const SkScalar affine[] = { |
32 1.06608627e-06f, 4.26434525e-07f, 6.2855f, 2.6611f, 273.4393f, 244.0046f | 32 1.06608627e-06f, 4.26434525e-07f, 6.2855f, 2.6611f, 273.4393f, 244.0046f |
33 }; | 33 }; |
34 SkMatrix matrix; | 34 SkMatrix matrix; |
35 matrix.setAffine(affine); | 35 matrix.setAffine(affine); |
36 c.concat(matrix); | 36 c.concat(matrix); |
37 | 37 |
38 c.drawPaint(paint); | 38 c.drawPaint(paint); |
39 } | 39 } |
40 | 40 |
41 struct GradRec { | 41 struct GradRec { |
42 int fColorCount; | 42 int fColorCount; |
43 const SkColor* fColors; | 43 const SkColor* fColors; |
44 const SkScalar* fPos; | 44 const SkScalar* fPos; |
45 const SkPoint* fPoint; // 2 | 45 const SkPoint* fPoint; // 2 |
46 const SkScalar* fRadius; // 2 | 46 const SkScalar* fRadius; // 2 |
47 SkShader::TileMode fTileMode; | 47 SkShader::TileMode fTileMode; |
48 | 48 |
49 void gradCheck(skiatest::Reporter* reporter, const sk_sp<SkShader>& shader, | 49 void gradCheck(skiatest::Reporter* reporter, SkShader* shader, |
50 SkShader::GradientInfo* info, | 50 SkShader::GradientInfo* info, |
51 SkShader::GradientType gt) const { | 51 SkShader::GradientType gt) const { |
52 SkAutoTMalloc<SkColor> colorStorage(fColorCount); | 52 SkAutoTMalloc<SkColor> colorStorage(fColorCount); |
53 SkAutoTMalloc<SkScalar> posStorage(fColorCount); | 53 SkAutoTMalloc<SkScalar> posStorage(fColorCount); |
54 | 54 |
55 info->fColorCount = fColorCount; | 55 info->fColorCount = fColorCount; |
56 info->fColors = colorStorage; | 56 info->fColors = colorStorage; |
57 info->fColorOffsets = posStorage.get(); | 57 info->fColorOffsets = posStorage.get(); |
58 REPORTER_ASSERT(reporter, shader->asAGradient(info) == gt); | 58 REPORTER_ASSERT(reporter, shader->asAGradient(info) == gt); |
59 | 59 |
60 REPORTER_ASSERT(reporter, info->fColorCount == fColorCount); | 60 REPORTER_ASSERT(reporter, info->fColorCount == fColorCount); |
61 REPORTER_ASSERT(reporter, | 61 REPORTER_ASSERT(reporter, |
62 !memcmp(info->fColors, fColors, fColorCount * sizeof(SkC
olor))); | 62 !memcmp(info->fColors, fColors, fColorCount * sizeof(SkC
olor))); |
63 REPORTER_ASSERT(reporter, | 63 REPORTER_ASSERT(reporter, |
64 !memcmp(info->fColorOffsets, fPos, fColorCount * sizeof(
SkScalar))); | 64 !memcmp(info->fColorOffsets, fPos, fColorCount * sizeof(
SkScalar))); |
65 REPORTER_ASSERT(reporter, fTileMode == info->fTileMode); | 65 REPORTER_ASSERT(reporter, fTileMode == info->fTileMode); |
66 } | 66 } |
67 }; | 67 }; |
68 | 68 |
69 | 69 |
70 static void none_gradproc(skiatest::Reporter* reporter, const GradRec&) { | 70 static void none_gradproc(skiatest::Reporter* reporter, const GradRec&) { |
71 sk_sp<SkShader> s(SkShader::MakeEmptyShader()); | 71 SkAutoTUnref<SkShader> s(SkShader::CreateEmptyShader()); |
72 REPORTER_ASSERT(reporter, SkShader::kNone_GradientType == s->asAGradient(nul
lptr)); | 72 REPORTER_ASSERT(reporter, SkShader::kNone_GradientType == s->asAGradient(nul
lptr)); |
73 } | 73 } |
74 | 74 |
75 static void color_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { | 75 static void color_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { |
76 SkAutoTUnref<SkShader> s(new SkColorShader(rec.fColors[0])); | 76 SkAutoTUnref<SkShader> s(new SkColorShader(rec.fColors[0])); |
77 REPORTER_ASSERT(reporter, SkShader::kColor_GradientType == s->asAGradient(nu
llptr)); | 77 REPORTER_ASSERT(reporter, SkShader::kColor_GradientType == s->asAGradient(nu
llptr)); |
78 | 78 |
79 SkShader::GradientInfo info; | 79 SkShader::GradientInfo info; |
80 info.fColors = nullptr; | 80 info.fColors = nullptr; |
81 info.fColorCount = 0; | 81 info.fColorCount = 0; |
82 s->asAGradient(&info); | 82 s->asAGradient(&info); |
83 REPORTER_ASSERT(reporter, 1 == info.fColorCount); | 83 REPORTER_ASSERT(reporter, 1 == info.fColorCount); |
84 } | 84 } |
85 | 85 |
86 static void linear_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { | 86 static void linear_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { |
87 sk_sp<SkShader> s(SkGradientShader::MakeLinear(rec.fPoint, rec.fColors, rec.
fPos, | 87 SkAutoTUnref<SkShader> s(SkGradientShader::CreateLinear(rec.fPoint, |
88 rec.fColorCount, rec.fTileMod
e)); | 88 rec.fColors, |
| 89 rec.fPos, |
| 90 rec.fColorCount, |
| 91 rec.fTileMode)); |
89 | 92 |
90 SkShader::GradientInfo info; | 93 SkShader::GradientInfo info; |
91 rec.gradCheck(reporter, s, &info, SkShader::kLinear_GradientType); | 94 rec.gradCheck(reporter, s, &info, SkShader::kLinear_GradientType); |
92 REPORTER_ASSERT(reporter, !memcmp(info.fPoint, rec.fPoint, 2 * sizeof(SkPoin
t))); | 95 REPORTER_ASSERT(reporter, !memcmp(info.fPoint, rec.fPoint, 2 * sizeof(SkPoin
t))); |
93 } | 96 } |
94 | 97 |
95 static void radial_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { | 98 static void radial_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { |
96 sk_sp<SkShader> s(SkGradientShader::MakeRadial(rec.fPoint[0], rec.fRadius[0]
, rec.fColors, | 99 SkAutoTUnref<SkShader> s(SkGradientShader::CreateRadial(rec.fPoint[0], |
97 rec.fPos, rec.fColorCount, re
c.fTileMode)); | 100 rec.fRadius[0], |
| 101 rec.fColors, |
| 102 rec.fPos, |
| 103 rec.fColorCount, |
| 104 rec.fTileMode)); |
98 | 105 |
99 SkShader::GradientInfo info; | 106 SkShader::GradientInfo info; |
100 rec.gradCheck(reporter, s, &info, SkShader::kRadial_GradientType); | 107 rec.gradCheck(reporter, s, &info, SkShader::kRadial_GradientType); |
101 REPORTER_ASSERT(reporter, info.fPoint[0] == rec.fPoint[0]); | 108 REPORTER_ASSERT(reporter, info.fPoint[0] == rec.fPoint[0]); |
102 REPORTER_ASSERT(reporter, info.fRadius[0] == rec.fRadius[0]); | 109 REPORTER_ASSERT(reporter, info.fRadius[0] == rec.fRadius[0]); |
103 } | 110 } |
104 | 111 |
105 static void sweep_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { | 112 static void sweep_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { |
106 sk_sp<SkShader> s(SkGradientShader::MakeSweep(rec.fPoint[0].fX, rec.fPoint[0
].fY, rec.fColors, | 113 SkAutoTUnref<SkShader> s(SkGradientShader::CreateSweep(rec.fPoint[0].fX, |
107 rec.fPos, rec.fColorCount)); | 114 rec.fPoint[0].fY, |
| 115 rec.fColors, |
| 116 rec.fPos, |
| 117 rec.fColorCount)); |
108 | 118 |
109 SkShader::GradientInfo info; | 119 SkShader::GradientInfo info; |
110 rec.gradCheck(reporter, s, &info, SkShader::kSweep_GradientType); | 120 rec.gradCheck(reporter, s, &info, SkShader::kSweep_GradientType); |
111 REPORTER_ASSERT(reporter, info.fPoint[0] == rec.fPoint[0]); | 121 REPORTER_ASSERT(reporter, info.fPoint[0] == rec.fPoint[0]); |
112 } | 122 } |
113 | 123 |
114 static void conical_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { | 124 static void conical_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { |
115 sk_sp<SkShader> s(SkGradientShader::MakeTwoPointConical(rec.fPoint[0], | 125 SkAutoTUnref<SkShader> s(SkGradientShader::CreateTwoPointConical(rec.fPoint[
0], |
116 rec.fRadius[0], | 126 rec.fRadius[0], |
117 rec.fPoint[1], | 127 rec.fPoint[1], |
118 rec.fRadius[1], | 128 rec.fRadius[1], |
119 rec.fColors, | 129 rec.fColors, |
120 rec.fPos, | 130 rec.fPos, |
121 rec.fColorCount, | 131 rec.fColorCount, |
122 rec.fTileMode)); | 132 rec.fTileMode)); |
123 | 133 |
124 SkShader::GradientInfo info; | 134 SkShader::GradientInfo info; |
125 rec.gradCheck(reporter, s, &info, SkShader::kConical_GradientType); | 135 rec.gradCheck(reporter, s, &info, SkShader::kConical_GradientType); |
126 REPORTER_ASSERT(reporter, !memcmp(info.fPoint, rec.fPoint, 2 * sizeof(SkPoin
t))); | 136 REPORTER_ASSERT(reporter, !memcmp(info.fPoint, rec.fPoint, 2 * sizeof(SkPoin
t))); |
127 REPORTER_ASSERT(reporter, !memcmp(info.fRadius, rec.fRadius, 2 * sizeof(SkSc
alar))); | 137 REPORTER_ASSERT(reporter, !memcmp(info.fRadius, rec.fRadius, 2 * sizeof(SkSc
alar))); |
128 } | 138 } |
129 | 139 |
130 // Ensure that repeated color gradients behave like drawing a single color | 140 // Ensure that repeated color gradients behave like drawing a single color |
131 static void TestConstantGradient(skiatest::Reporter*) { | 141 static void TestConstantGradient(skiatest::Reporter*) { |
132 const SkPoint pts[] = { | 142 const SkPoint pts[] = { |
133 { 0, 0 }, | 143 { 0, 0 }, |
134 { SkIntToScalar(10), 0 } | 144 { SkIntToScalar(10), 0 } |
135 }; | 145 }; |
136 SkColor colors[] = { SK_ColorBLUE, SK_ColorBLUE }; | 146 SkColor colors[] = { SK_ColorBLUE, SK_ColorBLUE }; |
137 const SkScalar pos[] = { 0, SK_Scalar1 }; | 147 const SkScalar pos[] = { 0, SK_Scalar1 }; |
138 SkPaint paint; | 148 SkAutoTUnref<SkShader> s(SkGradientShader::CreateLinear(pts, |
139 paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 2, SkShader::
kClamp_TileMode)); | 149 colors, |
| 150 pos, |
| 151 2, |
| 152 SkShader::kClamp_Til
eMode)); |
140 SkBitmap outBitmap; | 153 SkBitmap outBitmap; |
141 outBitmap.allocN32Pixels(10, 1); | 154 outBitmap.allocN32Pixels(10, 1); |
| 155 SkPaint paint; |
| 156 paint.setShader(s.get()); |
142 SkCanvas canvas(outBitmap); | 157 SkCanvas canvas(outBitmap); |
143 canvas.drawPaint(paint); | 158 canvas.drawPaint(paint); |
144 SkAutoLockPixels alp(outBitmap); | 159 SkAutoLockPixels alp(outBitmap); |
145 for (int i = 0; i < 10; i++) { | 160 for (int i = 0; i < 10; i++) { |
146 // The following is commented out because it currently fails | 161 // The following is commented out because it currently fails |
147 // Related bug: https://code.google.com/p/skia/issues/detail?id=1098 | 162 // Related bug: https://code.google.com/p/skia/issues/detail?id=1098 |
148 | 163 |
149 // REPORTER_ASSERT(reporter, SK_ColorBLUE == outBitmap.getColor(i, 0)); | 164 // REPORTER_ASSERT(reporter, SK_ColorBLUE == outBitmap.getColor(i, 0)); |
150 } | 165 } |
151 } | 166 } |
(...skipping 30 matching lines...) Expand all Loading... |
182 gProcs[i](reporter, rec); | 197 gProcs[i](reporter, rec); |
183 } | 198 } |
184 } | 199 } |
185 | 200 |
186 static void test_nearly_vertical(skiatest::Reporter* reporter) { | 201 static void test_nearly_vertical(skiatest::Reporter* reporter) { |
187 SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(200, 200)); | 202 SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(200, 200)); |
188 | 203 |
189 const SkPoint pts[] = {{ 100, 50 }, { 100.0001f, 50000 }}; | 204 const SkPoint pts[] = {{ 100, 50 }, { 100.0001f, 50000 }}; |
190 const SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE }; | 205 const SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE }; |
191 const SkScalar pos[] = { 0, 1 }; | 206 const SkScalar pos[] = { 0, 1 }; |
| 207 SkAutoTUnref<SkShader> gradient( |
| 208 SkGradientShader::CreateLinear(pts, colors, pos, 2, SkShader::kClamp_Til
eMode)); |
| 209 |
192 SkPaint paint; | 210 SkPaint paint; |
193 paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 2, SkShader::
kClamp_TileMode)); | 211 paint.setShader(gradient); |
194 | 212 |
195 surface->getCanvas()->drawPaint(paint); | 213 surface->getCanvas()->drawPaint(paint); |
196 } | 214 } |
197 | 215 |
198 // A linear gradient interval can, due to numerical imprecision (likely in the d
ivide) | 216 // A linear gradient interval can, due to numerical imprecision (likely in the d
ivide) |
199 // finish an interval with the final fx not landing outside of [p0...p1]. | 217 // finish an interval with the final fx not landing outside of [p0...p1]. |
200 // The old code had an assert which this test triggered. | 218 // The old code had an assert which this test triggered. |
201 // We now explicitly clamp the resulting fx value. | 219 // We now explicitly clamp the resulting fx value. |
202 static void test_linear_fuzz(skiatest::Reporter* reporter) { | 220 static void test_linear_fuzz(skiatest::Reporter* reporter) { |
203 SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(1300, 630)); | 221 SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(1300, 630)); |
204 | 222 |
205 const SkPoint pts[] = {{ 179.5f, -179.5f }, { 1074.5f, 715.5f }}; | 223 const SkPoint pts[] = {{ 179.5f, -179.5f }, { 1074.5f, 715.5f }}; |
206 const SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_C
olorWHITE }; | 224 const SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_C
olorWHITE }; |
207 const SkScalar pos[] = {0, 0.200000003f, 0.800000012f, 1 }; | 225 const SkScalar pos[] = {0, 0.200000003f, 0.800000012f, 1 }; |
208 | 226 |
| 227 |
| 228 SkAutoTUnref<SkShader> gradient( |
| 229 SkGradientShader::CreateLinear(pts, colors, pos, 4, SkShader:
:kClamp_TileMode)); |
| 230 |
209 SkPaint paint; | 231 SkPaint paint; |
210 paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 4, SkShader::
kClamp_TileMode)); | 232 paint.setShader(gradient); |
211 | |
212 SkRect r = {0, 83, 1254, 620}; | 233 SkRect r = {0, 83, 1254, 620}; |
213 surface->getCanvas()->drawRect(r, paint); | 234 surface->getCanvas()->drawRect(r, paint); |
214 } | 235 } |
215 | 236 |
216 // https://bugs.chromium.org/p/skia/issues/detail?id=5023 | 237 // https://bugs.chromium.org/p/skia/issues/detail?id=5023 |
217 // We should still shade pixels for which the radius is exactly 0. | 238 // We should still shade pixels for which the radius is exactly 0. |
218 static void test_two_point_conical_zero_radius(skiatest::Reporter* reporter) { | 239 static void test_two_point_conical_zero_radius(skiatest::Reporter* reporter) { |
219 SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(5, 5)); | 240 SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(5, 5)); |
220 surface->getCanvas()->clear(SK_ColorRED); | 241 surface->getCanvas()->clear(SK_ColorRED); |
221 | 242 |
222 const SkColor colors[] = { SK_ColorGREEN, SK_ColorBLUE }; | 243 const SkColor colors[] = { SK_ColorGREEN, SK_ColorBLUE }; |
223 SkPaint p; | 244 SkAutoTUnref<SkShader> shader(SkGradientShader::CreateTwoPointConical( |
224 p.setShader(SkGradientShader::MakeTwoPointConical( | |
225 SkPoint::Make(2.5f, 2.5f), 0, | 245 SkPoint::Make(2.5f, 2.5f), 0, |
226 SkPoint::Make(3.0f, 3.0f), 10, | 246 SkPoint::Make(3.0f, 3.0f), 10, |
227 colors, nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode)); | 247 colors, nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode)); |
| 248 SkPaint p; |
| 249 p.setShader(shader); |
228 surface->getCanvas()->drawPaint(p); | 250 surface->getCanvas()->drawPaint(p); |
229 | 251 |
230 // r == 0 for the center pixel. | 252 // r == 0 for the center pixel. |
231 // verify that we draw it (no red bleed) | 253 // verify that we draw it (no red bleed) |
232 SkPMColor centerPMColor; | 254 SkPMColor centerPMColor; |
233 surface->readPixels(SkImageInfo::MakeN32Premul(1, 1), ¢erPMColor, sizeof
(SkPMColor), 2, 2); | 255 surface->readPixels(SkImageInfo::MakeN32Premul(1, 1), ¢erPMColor, sizeof
(SkPMColor), 2, 2); |
234 REPORTER_ASSERT(reporter, SkGetPackedR32(centerPMColor) == 0); | 256 REPORTER_ASSERT(reporter, SkGetPackedR32(centerPMColor) == 0); |
235 } | 257 } |
236 | 258 |
237 DEF_TEST(Gradient, reporter) { | 259 DEF_TEST(Gradient, reporter) { |
238 TestGradientShaders(reporter); | 260 TestGradientShaders(reporter); |
239 TestConstantGradient(reporter); | 261 TestConstantGradient(reporter); |
240 test_big_grad(reporter); | 262 test_big_grad(reporter); |
241 test_nearly_vertical(reporter); | 263 test_nearly_vertical(reporter); |
242 test_linear_fuzz(reporter); | 264 test_linear_fuzz(reporter); |
243 test_two_point_conical_zero_radius(reporter); | 265 test_two_point_conical_zero_radius(reporter); |
244 } | 266 } |
OLD | NEW |