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); | |
24 SkPaint paint; | 23 SkPaint paint; |
25 paint.setShader(s)->unref(); | 24 paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, 2, |
| 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, SkShader* shader, | 49 void gradCheck(skiatest::Reporter* reporter, const sk_sp<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 SkAutoTUnref<SkShader> s(SkShader::CreateEmptyShader()); | 71 sk_sp<SkShader> s(SkShader::MakeEmptyShader()); |
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 SkAutoTUnref<SkShader> s(SkGradientShader::CreateLinear(rec.fPoint, | 87 sk_sp<SkShader> s(SkGradientShader::MakeLinear(rec.fPoint, rec.fColors, rec.
fPos, |
88 rec.fColors, | 88 rec.fColorCount, rec.fTileMod
e)); |
89 rec.fPos, | |
90 rec.fColorCount, | |
91 rec.fTileMode)); | |
92 | 89 |
93 SkShader::GradientInfo info; | 90 SkShader::GradientInfo info; |
94 rec.gradCheck(reporter, s, &info, SkShader::kLinear_GradientType); | 91 rec.gradCheck(reporter, s, &info, SkShader::kLinear_GradientType); |
95 REPORTER_ASSERT(reporter, !memcmp(info.fPoint, rec.fPoint, 2 * sizeof(SkPoin
t))); | 92 REPORTER_ASSERT(reporter, !memcmp(info.fPoint, rec.fPoint, 2 * sizeof(SkPoin
t))); |
96 } | 93 } |
97 | 94 |
98 static void radial_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { | 95 static void radial_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { |
99 SkAutoTUnref<SkShader> s(SkGradientShader::CreateRadial(rec.fPoint[0], | 96 sk_sp<SkShader> s(SkGradientShader::MakeRadial(rec.fPoint[0], rec.fRadius[0]
, rec.fColors, |
100 rec.fRadius[0], | 97 rec.fPos, rec.fColorCount, re
c.fTileMode)); |
101 rec.fColors, | |
102 rec.fPos, | |
103 rec.fColorCount, | |
104 rec.fTileMode)); | |
105 | 98 |
106 SkShader::GradientInfo info; | 99 SkShader::GradientInfo info; |
107 rec.gradCheck(reporter, s, &info, SkShader::kRadial_GradientType); | 100 rec.gradCheck(reporter, s, &info, SkShader::kRadial_GradientType); |
108 REPORTER_ASSERT(reporter, info.fPoint[0] == rec.fPoint[0]); | 101 REPORTER_ASSERT(reporter, info.fPoint[0] == rec.fPoint[0]); |
109 REPORTER_ASSERT(reporter, info.fRadius[0] == rec.fRadius[0]); | 102 REPORTER_ASSERT(reporter, info.fRadius[0] == rec.fRadius[0]); |
110 } | 103 } |
111 | 104 |
112 static void sweep_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { | 105 static void sweep_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { |
113 SkAutoTUnref<SkShader> s(SkGradientShader::CreateSweep(rec.fPoint[0].fX, | 106 sk_sp<SkShader> s(SkGradientShader::MakeSweep(rec.fPoint[0].fX, rec.fPoint[0
].fY, rec.fColors, |
114 rec.fPoint[0].fY, | 107 rec.fPos, rec.fColorCount)); |
115 rec.fColors, | |
116 rec.fPos, | |
117 rec.fColorCount)); | |
118 | 108 |
119 SkShader::GradientInfo info; | 109 SkShader::GradientInfo info; |
120 rec.gradCheck(reporter, s, &info, SkShader::kSweep_GradientType); | 110 rec.gradCheck(reporter, s, &info, SkShader::kSweep_GradientType); |
121 REPORTER_ASSERT(reporter, info.fPoint[0] == rec.fPoint[0]); | 111 REPORTER_ASSERT(reporter, info.fPoint[0] == rec.fPoint[0]); |
122 } | 112 } |
123 | 113 |
124 static void conical_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { | 114 static void conical_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { |
125 SkAutoTUnref<SkShader> s(SkGradientShader::CreateTwoPointConical(rec.fPoint[
0], | 115 sk_sp<SkShader> s(SkGradientShader::MakeTwoPointConical(rec.fPoint[0], |
126 rec.fRadius[0], | 116 rec.fRadius[0], |
127 rec.fPoint[1], | 117 rec.fPoint[1], |
128 rec.fRadius[1], | 118 rec.fRadius[1], |
129 rec.fColors, | 119 rec.fColors, |
130 rec.fPos, | 120 rec.fPos, |
131 rec.fColorCount, | 121 rec.fColorCount, |
132 rec.fTileMode)); | 122 rec.fTileMode)); |
133 | 123 |
134 SkShader::GradientInfo info; | 124 SkShader::GradientInfo info; |
135 rec.gradCheck(reporter, s, &info, SkShader::kConical_GradientType); | 125 rec.gradCheck(reporter, s, &info, SkShader::kConical_GradientType); |
136 REPORTER_ASSERT(reporter, !memcmp(info.fPoint, rec.fPoint, 2 * sizeof(SkPoin
t))); | 126 REPORTER_ASSERT(reporter, !memcmp(info.fPoint, rec.fPoint, 2 * sizeof(SkPoin
t))); |
137 REPORTER_ASSERT(reporter, !memcmp(info.fRadius, rec.fRadius, 2 * sizeof(SkSc
alar))); | 127 REPORTER_ASSERT(reporter, !memcmp(info.fRadius, rec.fRadius, 2 * sizeof(SkSc
alar))); |
138 } | 128 } |
139 | 129 |
140 // Ensure that repeated color gradients behave like drawing a single color | 130 // Ensure that repeated color gradients behave like drawing a single color |
141 static void TestConstantGradient(skiatest::Reporter*) { | 131 static void TestConstantGradient(skiatest::Reporter*) { |
142 const SkPoint pts[] = { | 132 const SkPoint pts[] = { |
143 { 0, 0 }, | 133 { 0, 0 }, |
144 { SkIntToScalar(10), 0 } | 134 { SkIntToScalar(10), 0 } |
145 }; | 135 }; |
146 SkColor colors[] = { SK_ColorBLUE, SK_ColorBLUE }; | 136 SkColor colors[] = { SK_ColorBLUE, SK_ColorBLUE }; |
147 const SkScalar pos[] = { 0, SK_Scalar1 }; | 137 const SkScalar pos[] = { 0, SK_Scalar1 }; |
148 SkAutoTUnref<SkShader> s(SkGradientShader::CreateLinear(pts, | 138 SkPaint paint; |
149 colors, | 139 paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 2, SkShader::
kClamp_TileMode)); |
150 pos, | |
151 2, | |
152 SkShader::kClamp_Til
eMode)); | |
153 SkBitmap outBitmap; | 140 SkBitmap outBitmap; |
154 outBitmap.allocN32Pixels(10, 1); | 141 outBitmap.allocN32Pixels(10, 1); |
155 SkPaint paint; | |
156 paint.setShader(s.get()); | |
157 SkCanvas canvas(outBitmap); | 142 SkCanvas canvas(outBitmap); |
158 canvas.drawPaint(paint); | 143 canvas.drawPaint(paint); |
159 SkAutoLockPixels alp(outBitmap); | 144 SkAutoLockPixels alp(outBitmap); |
160 for (int i = 0; i < 10; i++) { | 145 for (int i = 0; i < 10; i++) { |
161 // The following is commented out because it currently fails | 146 // The following is commented out because it currently fails |
162 // Related bug: https://code.google.com/p/skia/issues/detail?id=1098 | 147 // Related bug: https://code.google.com/p/skia/issues/detail?id=1098 |
163 | 148 |
164 // REPORTER_ASSERT(reporter, SK_ColorBLUE == outBitmap.getColor(i, 0)); | 149 // REPORTER_ASSERT(reporter, SK_ColorBLUE == outBitmap.getColor(i, 0)); |
165 } | 150 } |
166 } | 151 } |
(...skipping 30 matching lines...) Expand all Loading... |
197 gProcs[i](reporter, rec); | 182 gProcs[i](reporter, rec); |
198 } | 183 } |
199 } | 184 } |
200 | 185 |
201 static void test_nearly_vertical(skiatest::Reporter* reporter) { | 186 static void test_nearly_vertical(skiatest::Reporter* reporter) { |
202 SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(200, 200)); | 187 SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(200, 200)); |
203 | 188 |
204 const SkPoint pts[] = {{ 100, 50 }, { 100.0001f, 50000 }}; | 189 const SkPoint pts[] = {{ 100, 50 }, { 100.0001f, 50000 }}; |
205 const SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE }; | 190 const SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE }; |
206 const SkScalar pos[] = { 0, 1 }; | 191 const SkScalar pos[] = { 0, 1 }; |
207 SkAutoTUnref<SkShader> gradient( | |
208 SkGradientShader::CreateLinear(pts, colors, pos, 2, SkShader::kClamp_Til
eMode)); | |
209 | |
210 SkPaint paint; | 192 SkPaint paint; |
211 paint.setShader(gradient); | 193 paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 2, SkShader::
kClamp_TileMode)); |
212 | 194 |
213 surface->getCanvas()->drawPaint(paint); | 195 surface->getCanvas()->drawPaint(paint); |
214 } | 196 } |
215 | 197 |
216 // A linear gradient interval can, due to numerical imprecision (likely in the d
ivide) | 198 // A linear gradient interval can, due to numerical imprecision (likely in the d
ivide) |
217 // finish an interval with the final fx not landing outside of [p0...p1]. | 199 // finish an interval with the final fx not landing outside of [p0...p1]. |
218 // The old code had an assert which this test triggered. | 200 // The old code had an assert which this test triggered. |
219 // We now explicitly clamp the resulting fx value. | 201 // We now explicitly clamp the resulting fx value. |
220 static void test_linear_fuzz(skiatest::Reporter* reporter) { | 202 static void test_linear_fuzz(skiatest::Reporter* reporter) { |
221 SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(1300, 630)); | 203 SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(1300, 630)); |
222 | 204 |
223 const SkPoint pts[] = {{ 179.5f, -179.5f }, { 1074.5f, 715.5f }}; | 205 const SkPoint pts[] = {{ 179.5f, -179.5f }, { 1074.5f, 715.5f }}; |
224 const SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_C
olorWHITE }; | 206 const SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_C
olorWHITE }; |
225 const SkScalar pos[] = {0, 0.200000003f, 0.800000012f, 1 }; | 207 const SkScalar pos[] = {0, 0.200000003f, 0.800000012f, 1 }; |
226 | 208 |
| 209 SkPaint paint; |
| 210 paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 4, SkShader::
kClamp_TileMode)); |
227 | 211 |
228 SkAutoTUnref<SkShader> gradient( | |
229 SkGradientShader::CreateLinear(pts, colors, pos, 4, SkShader:
:kClamp_TileMode)); | |
230 | |
231 SkPaint paint; | |
232 paint.setShader(gradient); | |
233 SkRect r = {0, 83, 1254, 620}; | 212 SkRect r = {0, 83, 1254, 620}; |
234 surface->getCanvas()->drawRect(r, paint); | 213 surface->getCanvas()->drawRect(r, paint); |
235 } | 214 } |
236 | 215 |
237 // https://bugs.chromium.org/p/skia/issues/detail?id=5023 | 216 // https://bugs.chromium.org/p/skia/issues/detail?id=5023 |
238 // We should still shade pixels for which the radius is exactly 0. | 217 // We should still shade pixels for which the radius is exactly 0. |
239 static void test_two_point_conical_zero_radius(skiatest::Reporter* reporter) { | 218 static void test_two_point_conical_zero_radius(skiatest::Reporter* reporter) { |
240 SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(5, 5)); | 219 SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(5, 5)); |
241 surface->getCanvas()->clear(SK_ColorRED); | 220 surface->getCanvas()->clear(SK_ColorRED); |
242 | 221 |
243 const SkColor colors[] = { SK_ColorGREEN, SK_ColorBLUE }; | 222 const SkColor colors[] = { SK_ColorGREEN, SK_ColorBLUE }; |
244 SkAutoTUnref<SkShader> shader(SkGradientShader::CreateTwoPointConical( | 223 SkPaint p; |
| 224 p.setShader(SkGradientShader::MakeTwoPointConical( |
245 SkPoint::Make(2.5f, 2.5f), 0, | 225 SkPoint::Make(2.5f, 2.5f), 0, |
246 SkPoint::Make(3.0f, 3.0f), 10, | 226 SkPoint::Make(3.0f, 3.0f), 10, |
247 colors, nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode)); | 227 colors, nullptr, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode)); |
248 SkPaint p; | |
249 p.setShader(shader); | |
250 surface->getCanvas()->drawPaint(p); | 228 surface->getCanvas()->drawPaint(p); |
251 | 229 |
252 // r == 0 for the center pixel. | 230 // r == 0 for the center pixel. |
253 // verify that we draw it (no red bleed) | 231 // verify that we draw it (no red bleed) |
254 SkPMColor centerPMColor; | 232 SkPMColor centerPMColor; |
255 surface->readPixels(SkImageInfo::MakeN32Premul(1, 1), ¢erPMColor, sizeof
(SkPMColor), 2, 2); | 233 surface->readPixels(SkImageInfo::MakeN32Premul(1, 1), ¢erPMColor, sizeof
(SkPMColor), 2, 2); |
256 REPORTER_ASSERT(reporter, SkGetPackedR32(centerPMColor) == 0); | 234 REPORTER_ASSERT(reporter, SkGetPackedR32(centerPMColor) == 0); |
257 } | 235 } |
258 | 236 |
259 DEF_TEST(Gradient, reporter) { | 237 DEF_TEST(Gradient, reporter) { |
260 TestGradientShaders(reporter); | 238 TestGradientShaders(reporter); |
261 TestConstantGradient(reporter); | 239 TestConstantGradient(reporter); |
262 test_big_grad(reporter); | 240 test_big_grad(reporter); |
263 test_nearly_vertical(reporter); | 241 test_nearly_vertical(reporter); |
264 test_linear_fuzz(reporter); | 242 test_linear_fuzz(reporter); |
265 test_two_point_conical_zero_radius(reporter); | 243 test_two_point_conical_zero_radius(reporter); |
266 } | 244 } |
OLD | NEW |