| 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 |