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" |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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&, const Gr
adRec&) { |
71 sk_sp<SkShader> s(SkShader::MakeEmptyShader()); | 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, con
st GradRec&) { |
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& buildRe
c, |
87 sk_sp<SkShader> s(SkGradientShader::MakeLinear(rec.fPoint, rec.fColors, rec.
fPos, | 87 const GradRec& checkRec) { |
88 rec.fColorCount, rec.fTileMod
e)); | 88 sk_sp<SkShader> s(SkGradientShader::MakeLinear(buildRec.fPoint, buildRec.fCo
lors, buildRec.fPos, |
| 89 buildRec.fColorCount, buildRe
c.fTileMode)); |
89 | 90 |
90 SkShader::GradientInfo info; | 91 SkShader::GradientInfo info; |
91 rec.gradCheck(reporter, s, &info, SkShader::kLinear_GradientType); | 92 checkRec.gradCheck(reporter, s, &info, SkShader::kLinear_GradientType); |
92 REPORTER_ASSERT(reporter, !memcmp(info.fPoint, rec.fPoint, 2 * sizeof(SkPoin
t))); | 93 REPORTER_ASSERT(reporter, !memcmp(info.fPoint, checkRec.fPoint, 2 * sizeof(S
kPoint))); |
93 } | 94 } |
94 | 95 |
95 static void radial_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { | 96 static void radial_gradproc(skiatest::Reporter* reporter, const GradRec& buildRe
c, |
96 sk_sp<SkShader> s(SkGradientShader::MakeRadial(rec.fPoint[0], rec.fRadius[0]
, rec.fColors, | 97 const GradRec& checkRec) { |
97 rec.fPos, rec.fColorCount, re
c.fTileMode)); | 98 sk_sp<SkShader> s(SkGradientShader::MakeRadial(buildRec.fPoint[0], buildRec.
fRadius[0], |
| 99 buildRec.fColors, buildRec.fP
os, |
| 100 buildRec.fColorCount, buildRe
c.fTileMode)); |
98 | 101 |
99 SkShader::GradientInfo info; | 102 SkShader::GradientInfo info; |
100 rec.gradCheck(reporter, s, &info, SkShader::kRadial_GradientType); | 103 checkRec.gradCheck(reporter, s, &info, SkShader::kRadial_GradientType); |
101 REPORTER_ASSERT(reporter, info.fPoint[0] == rec.fPoint[0]); | 104 REPORTER_ASSERT(reporter, info.fPoint[0] == checkRec.fPoint[0]); |
102 REPORTER_ASSERT(reporter, info.fRadius[0] == rec.fRadius[0]); | 105 REPORTER_ASSERT(reporter, info.fRadius[0] == checkRec.fRadius[0]); |
103 } | 106 } |
104 | 107 |
105 static void sweep_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { | 108 static void sweep_gradproc(skiatest::Reporter* reporter, const GradRec& buildRec
, |
106 sk_sp<SkShader> s(SkGradientShader::MakeSweep(rec.fPoint[0].fX, rec.fPoint[0
].fY, rec.fColors, | 109 const GradRec& checkRec) { |
107 rec.fPos, rec.fColorCount)); | 110 sk_sp<SkShader> s(SkGradientShader::MakeSweep(buildRec.fPoint[0].fX, buildRe
c.fPoint[0].fY, |
| 111 buildRec.fColors, buildRec.fPo
s, |
| 112 buildRec.fColorCount)); |
108 | 113 |
109 SkShader::GradientInfo info; | 114 SkShader::GradientInfo info; |
110 rec.gradCheck(reporter, s, &info, SkShader::kSweep_GradientType); | 115 checkRec.gradCheck(reporter, s, &info, SkShader::kSweep_GradientType); |
111 REPORTER_ASSERT(reporter, info.fPoint[0] == rec.fPoint[0]); | 116 REPORTER_ASSERT(reporter, info.fPoint[0] == checkRec.fPoint[0]); |
112 } | 117 } |
113 | 118 |
114 static void conical_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { | 119 static void conical_gradproc(skiatest::Reporter* reporter, const GradRec& buildR
ec, |
115 sk_sp<SkShader> s(SkGradientShader::MakeTwoPointConical(rec.fPoint[0], | 120 const GradRec& checkRec) { |
116 rec.fRadius[0], | 121 sk_sp<SkShader> s(SkGradientShader::MakeTwoPointConical(buildRec.fPoint[0], |
117 rec.fPoint[1], | 122 buildRec.fRadius[0], |
118 rec.fRadius[1], | 123 buildRec.fPoint[1], |
119 rec.fColors, | 124 buildRec.fRadius[1], |
120 rec.fPos, | 125 buildRec.fColors, |
121 rec.fColorCount, | 126 buildRec.fPos, |
122 rec.fTileMode)); | 127 buildRec.fColorCount
, |
| 128 buildRec.fTileMode))
; |
123 | 129 |
124 SkShader::GradientInfo info; | 130 SkShader::GradientInfo info; |
125 rec.gradCheck(reporter, s, &info, SkShader::kConical_GradientType); | 131 checkRec.gradCheck(reporter, s, &info, SkShader::kConical_GradientType); |
126 REPORTER_ASSERT(reporter, !memcmp(info.fPoint, rec.fPoint, 2 * sizeof(SkPoin
t))); | 132 REPORTER_ASSERT(reporter, !memcmp(info.fPoint, checkRec.fPoint, 2 * sizeof(S
kPoint))); |
127 REPORTER_ASSERT(reporter, !memcmp(info.fRadius, rec.fRadius, 2 * sizeof(SkSc
alar))); | 133 REPORTER_ASSERT(reporter, !memcmp(info.fRadius, checkRec.fRadius, 2 * sizeof
(SkScalar))); |
128 } | 134 } |
129 | 135 |
130 // Ensure that repeated color gradients behave like drawing a single color | 136 // Ensure that repeated color gradients behave like drawing a single color |
131 static void TestConstantGradient(skiatest::Reporter*) { | 137 static void TestConstantGradient(skiatest::Reporter*) { |
132 const SkPoint pts[] = { | 138 const SkPoint pts[] = { |
133 { 0, 0 }, | 139 { 0, 0 }, |
134 { SkIntToScalar(10), 0 } | 140 { SkIntToScalar(10), 0 } |
135 }; | 141 }; |
136 SkColor colors[] = { SK_ColorBLUE, SK_ColorBLUE }; | 142 SkColor colors[] = { SK_ColorBLUE, SK_ColorBLUE }; |
137 const SkScalar pos[] = { 0, SK_Scalar1 }; | 143 const SkScalar pos[] = { 0, SK_Scalar1 }; |
138 SkPaint paint; | 144 SkPaint paint; |
139 paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 2, SkShader::
kClamp_TileMode)); | 145 paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 2, SkShader::
kClamp_TileMode)); |
140 SkBitmap outBitmap; | 146 SkBitmap outBitmap; |
141 outBitmap.allocN32Pixels(10, 1); | 147 outBitmap.allocN32Pixels(10, 1); |
142 SkCanvas canvas(outBitmap); | 148 SkCanvas canvas(outBitmap); |
143 canvas.drawPaint(paint); | 149 canvas.drawPaint(paint); |
144 SkAutoLockPixels alp(outBitmap); | 150 SkAutoLockPixels alp(outBitmap); |
145 for (int i = 0; i < 10; i++) { | 151 for (int i = 0; i < 10; i++) { |
146 // The following is commented out because it currently fails | 152 // The following is commented out because it currently fails |
147 // Related bug: https://code.google.com/p/skia/issues/detail?id=1098 | 153 // Related bug: https://code.google.com/p/skia/issues/detail?id=1098 |
148 | 154 |
149 // REPORTER_ASSERT(reporter, SK_ColorBLUE == outBitmap.getColor(i, 0)); | 155 // REPORTER_ASSERT(reporter, SK_ColorBLUE == outBitmap.getColor(i, 0)); |
150 } | 156 } |
151 } | 157 } |
152 | 158 |
153 typedef void (*GradProc)(skiatest::Reporter* reporter, const GradRec&); | 159 typedef void (*GradProc)(skiatest::Reporter* reporter, const GradRec&, const Gra
dRec&); |
154 | 160 |
155 static void TestGradientShaders(skiatest::Reporter* reporter) { | 161 static void TestGradientShaders(skiatest::Reporter* reporter) { |
156 static const SkColor gColors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE
}; | 162 static const SkColor gColors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE
}; |
157 static const SkScalar gPos[] = { 0, SK_ScalarHalf, SK_Scalar1 }; | 163 static const SkScalar gPos[] = { 0, SK_ScalarHalf, SK_Scalar1 }; |
158 static const SkPoint gPts[] = { | 164 static const SkPoint gPts[] = { |
159 { 0, 0 }, | 165 { 0, 0 }, |
160 { SkIntToScalar(10), SkIntToScalar(20) } | 166 { SkIntToScalar(10), SkIntToScalar(20) } |
161 }; | 167 }; |
162 static const SkScalar gRad[] = { SkIntToScalar(1), SkIntToScalar(2) }; | 168 static const SkScalar gRad[] = { SkIntToScalar(1), SkIntToScalar(2) }; |
163 | 169 |
164 GradRec rec; | 170 GradRec rec; |
165 rec.fColorCount = SK_ARRAY_COUNT(gColors); | 171 rec.fColorCount = SK_ARRAY_COUNT(gColors); |
166 rec.fColors = gColors; | 172 rec.fColors = gColors; |
167 rec.fPos = gPos; | 173 rec.fPos = gPos; |
168 rec.fPoint = gPts; | 174 rec.fPoint = gPts; |
169 rec.fRadius = gRad; | 175 rec.fRadius = gRad; |
170 rec.fTileMode = SkShader::kClamp_TileMode; | 176 rec.fTileMode = SkShader::kClamp_TileMode; |
171 | 177 |
172 static const GradProc gProcs[] = { | 178 static const GradProc gProcs[] = { |
173 none_gradproc, | 179 none_gradproc, |
174 color_gradproc, | 180 color_gradproc, |
175 linear_gradproc, | 181 linear_gradproc, |
176 radial_gradproc, | 182 radial_gradproc, |
177 sweep_gradproc, | 183 sweep_gradproc, |
178 conical_gradproc, | 184 conical_gradproc, |
179 }; | 185 }; |
180 | 186 |
181 for (size_t i = 0; i < SK_ARRAY_COUNT(gProcs); ++i) { | 187 for (size_t i = 0; i < SK_ARRAY_COUNT(gProcs); ++i) { |
182 gProcs[i](reporter, rec); | 188 gProcs[i](reporter, rec, rec); |
183 } | 189 } |
184 } | 190 } |
185 | 191 |
| 192 static void TestGradientOptimization(skiatest::Reporter* reporter) { |
| 193 static const struct { |
| 194 GradProc fProc; |
| 195 bool fIsClampRestricted; |
| 196 } gProcInfo[] = { |
| 197 { linear_gradproc , false }, |
| 198 { radial_gradproc , false }, |
| 199 { sweep_gradproc , true }, // sweep is funky in that it always pretend
s to be kClamp. |
| 200 { conical_gradproc, false }, |
| 201 }; |
| 202 |
| 203 static const SkColor gC_00[] = { 0xff000000, 0xff000000 }; |
| 204 static const SkColor gC_01[] = { 0xff000000, 0xffffffff }; |
| 205 static const SkColor gC_11[] = { 0xffffffff, 0xffffffff }; |
| 206 static const SkColor gC_001[] = { 0xff000000, 0xff000000, 0xffffffff }; |
| 207 static const SkColor gC_011[] = { 0xff000000, 0xffffffff, 0xffffffff }; |
| 208 static const SkColor gC_0011[] = { 0xff000000, 0xff000000, 0xffffffff, 0xfff
fffff }; |
| 209 |
| 210 static const SkScalar gP_01[] = { 0, 1 }; |
| 211 static const SkScalar gP_001[] = { 0, 0, 1 }; |
| 212 static const SkScalar gP_011[] = { 0, 1, 1 }; |
| 213 static const SkScalar gP_0x1[] = { 0, .5f, 1 }; |
| 214 static const SkScalar gP_0011[] = { 0, 0, 1, 1 }; |
| 215 |
| 216 static const SkPoint gPts[] = { {0, 0}, {1, 1} }; |
| 217 static const SkScalar gRadii[] = { 1, 2 }; |
| 218 |
| 219 static const struct { |
| 220 const SkColor* fCol; |
| 221 const SkScalar* fPos; |
| 222 int fCount; |
| 223 |
| 224 const SkColor* fExpectedCol; |
| 225 const SkScalar* fExpectedPos; |
| 226 int fExpectedCount; |
| 227 bool fRequiresNonClamp; |
| 228 } gTests[] = { |
| 229 { gC_001, gP_001, 3, gC_01, gP_01, 2, false }, |
| 230 { gC_001, gP_011, 3, gC_00, gP_01, 2, true }, |
| 231 { gC_001, gP_0x1, 3, gC_001, gP_0x1, 3, false }, |
| 232 { gC_001, nullptr, 3, gC_001, gP_0x1, 3, false }, |
| 233 |
| 234 { gC_011, gP_001, 3, gC_11, gP_01, 2, true }, |
| 235 { gC_011, gP_011, 3, gC_01, gP_01, 2, false }, |
| 236 { gC_011, gP_0x1, 3, gC_011, gP_0x1, 3, false }, |
| 237 { gC_011, nullptr, 3, gC_011, gP_0x1, 3, false }, |
| 238 |
| 239 { gC_0011, gP_0011, 4, gC_0011, gP_0011, 4, false }, |
| 240 }; |
| 241 |
| 242 for (size_t i = 0; i < SK_ARRAY_COUNT(gProcInfo); ++i) { |
| 243 for (int mode = 0; mode < SkShader::kTileModeCount; ++mode) { |
| 244 if (gProcInfo[i].fIsClampRestricted && mode != SkShader::kClamp_Tile
Mode) { |
| 245 continue; |
| 246 } |
| 247 |
| 248 for (size_t t = 0; t < SK_ARRAY_COUNT(gTests); ++t) { |
| 249 GradRec rec; |
| 250 rec.fColorCount = gTests[t].fCount; |
| 251 rec.fColors = gTests[t].fCol; |
| 252 rec.fPos = gTests[t].fPos; |
| 253 rec.fTileMode = static_cast<SkShader::TileMode>(mode); |
| 254 rec.fPoint = gPts; |
| 255 rec.fRadius = gRadii; |
| 256 |
| 257 GradRec expected = rec; |
| 258 if (!gTests[t].fRequiresNonClamp || mode != SkShader::kClamp_Til
eMode) { |
| 259 expected.fColorCount = gTests[t].fExpectedCount; |
| 260 expected.fColors = gTests[t].fExpectedCol; |
| 261 expected.fPos = gTests[t].fExpectedPos; |
| 262 } |
| 263 |
| 264 gProcInfo[i].fProc(reporter, rec, expected); |
| 265 } |
| 266 } |
| 267 } |
| 268 } |
| 269 |
186 static void test_nearly_vertical(skiatest::Reporter* reporter) { | 270 static void test_nearly_vertical(skiatest::Reporter* reporter) { |
187 auto surface(SkSurface::MakeRasterN32Premul(200, 200)); | 271 auto surface(SkSurface::MakeRasterN32Premul(200, 200)); |
188 | 272 |
189 const SkPoint pts[] = {{ 100, 50 }, { 100.0001f, 50000 }}; | 273 const SkPoint pts[] = {{ 100, 50 }, { 100.0001f, 50000 }}; |
190 const SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE }; | 274 const SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE }; |
191 const SkScalar pos[] = { 0, 1 }; | 275 const SkScalar pos[] = { 0, 1 }; |
192 SkPaint paint; | 276 SkPaint paint; |
193 paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 2, SkShader::
kClamp_TileMode)); | 277 paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 2, SkShader::
kClamp_TileMode)); |
194 | 278 |
195 surface->getCanvas()->drawPaint(paint); | 279 surface->getCanvas()->drawPaint(paint); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 | 348 |
265 p.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkShader::
kClamp_TileMode)); | 349 p.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkShader::
kClamp_TileMode)); |
266 sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50)); | 350 sk_sp<SkSurface> surface(SkSurface::MakeRasterN32Premul(50, 50)); |
267 surface->getCanvas()->drawPaint(p); | 351 surface->getCanvas()->drawPaint(p); |
268 | 352 |
269 // Passes if we don't trigger asserts. | 353 // Passes if we don't trigger asserts. |
270 } | 354 } |
271 | 355 |
272 DEF_TEST(Gradient, reporter) { | 356 DEF_TEST(Gradient, reporter) { |
273 TestGradientShaders(reporter); | 357 TestGradientShaders(reporter); |
| 358 TestGradientOptimization(reporter); |
274 TestConstantGradient(reporter); | 359 TestConstantGradient(reporter); |
275 test_big_grad(reporter); | 360 test_big_grad(reporter); |
276 test_nearly_vertical(reporter); | 361 test_nearly_vertical(reporter); |
277 test_linear_fuzz(reporter); | 362 test_linear_fuzz(reporter); |
278 test_two_point_conical_zero_radius(reporter); | 363 test_two_point_conical_zero_radius(reporter); |
279 test_clamping_overflow(reporter); | 364 test_clamping_overflow(reporter); |
280 text_degenerate_linear(reporter); | 365 text_degenerate_linear(reporter); |
281 } | 366 } |
OLD | NEW |