1 /* 2 * Copyright 2015 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 "GrTestUtils.h" 9 #include "GrColorSpaceInfo.h" 10 #include "GrProcessorUnitTest.h" 11 #include "GrStyle.h" 12 #include "SkDashPathPriv.h" 13 #include "SkMakeUnique.h" 14 #include "SkMatrix.h" 15 #include "SkPath.h" 16 #include "SkRectPriv.h" 17 #include "SkRRect.h" 18 19 #if GR_TEST_UTILS 20 21 static const SkMatrix& test_matrix(SkRandom* random, 22 bool includeNonPerspective, 23 bool includePerspective) { 24 static SkMatrix gMatrices[5]; 25 static const int kPerspectiveCount = 1; 26 static bool gOnce; 27 if (!gOnce) { 28 gOnce = true; 29 gMatrices[0].reset(); 30 gMatrices[1].setTranslate(SkIntToScalar(-100), SkIntToScalar(100)); 31 gMatrices[2].setRotate(SkIntToScalar(17)); 32 gMatrices[3].setRotate(SkIntToScalar(185)); 33 gMatrices[3].postTranslate(SkIntToScalar(66), SkIntToScalar(-33)); 34 gMatrices[3].postScale(SkIntToScalar(2), SK_ScalarHalf); 35 36 // Perspective matrices 37 gMatrices[4].setRotate(SkIntToScalar(215)); 38 gMatrices[4].set(SkMatrix::kMPersp0, 0.00013f); 39 gMatrices[4].set(SkMatrix::kMPersp1, -0.000039f); 40 } 41 42 uint32_t count = static_cast<uint32_t>(SK_ARRAY_COUNT(gMatrices)); 43 if (includeNonPerspective && includePerspective) { 44 return gMatrices[random->nextULessThan(count)]; 45 } else if (!includeNonPerspective) { 46 return gMatrices[count - 1 - random->nextULessThan(kPerspectiveCount)]; 47 } else { 48 SkASSERT(includeNonPerspective && !includePerspective); 49 return gMatrices[random->nextULessThan(count - kPerspectiveCount)]; 50 } 51 } 52 53 namespace GrTest { 54 const SkMatrix& TestMatrix(SkRandom* random) { return test_matrix(random, true, true); } 55 56 const SkMatrix& TestMatrixPreservesRightAngles(SkRandom* random) { 57 static SkMatrix gMatrices[5]; 58 static bool gOnce; 59 if (!gOnce) { 60 gOnce = true; 61 // identity 62 gMatrices[0].reset(); 63 // translation 64 gMatrices[1].setTranslate(SkIntToScalar(-100), SkIntToScalar(100)); 65 // scale 66 gMatrices[2].setScale(SkIntToScalar(17), SkIntToScalar(17)); 67 // scale + translation 68 gMatrices[3].setScale(SkIntToScalar(-17), SkIntToScalar(-17)); 69 gMatrices[3].postTranslate(SkIntToScalar(66), SkIntToScalar(-33)); 70 // orthogonal basis vectors 71 gMatrices[4].reset(); 72 gMatrices[4].setScale(SkIntToScalar(-1), SkIntToScalar(-1)); 73 gMatrices[4].setRotate(47); 74 75 for (size_t i = 0; i < SK_ARRAY_COUNT(gMatrices); i++) { 76 SkASSERT(gMatrices[i].preservesRightAngles()); 77 } 78 } 79 return gMatrices[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gMatrices)))]; 80 } 81 82 const SkMatrix& TestMatrixRectStaysRect(SkRandom* random) { 83 static SkMatrix gMatrices[6]; 84 static bool gOnce; 85 if (!gOnce) { 86 gOnce = true; 87 // identity 88 gMatrices[0].reset(); 89 // translation 90 gMatrices[1].setTranslate(SkIntToScalar(-100), SkIntToScalar(100)); 91 // scale 92 gMatrices[2].setScale(SkIntToScalar(17), SkIntToScalar(17)); 93 // scale + translation 94 gMatrices[3].setScale(SkIntToScalar(-17), SkIntToScalar(-17)); 95 gMatrices[3].postTranslate(SkIntToScalar(66), SkIntToScalar(-33)); 96 // reflection 97 gMatrices[4].setScale(SkIntToScalar(-1), SkIntToScalar(-1)); 98 // 90 degress rotation 99 gMatrices[5].setRotate(90); 100 101 for (size_t i = 0; i < SK_ARRAY_COUNT(gMatrices); i++) { 102 SkASSERT(gMatrices[i].rectStaysRect()); 103 } 104 } 105 return gMatrices[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gMatrices)))]; 106 } 107 108 const SkMatrix& TestMatrixInvertible(SkRandom* random) { return test_matrix(random, true, false); } 109 const SkMatrix& TestMatrixPerspective(SkRandom* random) { return test_matrix(random, false, true); } 110 111 void TestWrapModes(SkRandom* random, GrSamplerState::WrapMode wrapModes[2]) { 112 static const GrSamplerState::WrapMode kWrapModes[] = { 113 GrSamplerState::WrapMode::kClamp, 114 GrSamplerState::WrapMode::kRepeat, 115 GrSamplerState::WrapMode::kMirrorRepeat, 116 }; 117 wrapModes[0] = kWrapModes[random->nextULessThan(SK_ARRAY_COUNT(kWrapModes))]; 118 wrapModes[1] = kWrapModes[random->nextULessThan(SK_ARRAY_COUNT(kWrapModes))]; 119 } 120 const SkRect& TestRect(SkRandom* random) { 121 static SkRect gRects[7]; 122 static bool gOnce; 123 if (!gOnce) { 124 gOnce = true; 125 gRects[0] = SkRect::MakeWH(1.f, 1.f); 126 gRects[1] = SkRect::MakeWH(1.0f, 256.0f); 127 gRects[2] = SkRect::MakeWH(256.0f, 1.0f); 128 gRects[3] = SkRectPriv::MakeLargest(); 129 gRects[4] = SkRect::MakeLTRB(-65535.0f, -65535.0f, 65535.0f, 65535.0f); 130 gRects[5] = SkRect::MakeLTRB(-10.0f, -10.0f, 10.0f, 10.0f); 131 } 132 return gRects[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gRects)))]; 133 } 134 135 // Just some simple rects for code which expects its input very sanitized 136 const SkRect& TestSquare(SkRandom* random) { 137 static SkRect gRects[2]; 138 static bool gOnce; 139 if (!gOnce) { 140 gOnce = true; 141 gRects[0] = SkRect::MakeWH(128.f, 128.f); 142 gRects[1] = SkRect::MakeWH(256.0f, 256.0f); 143 } 144 return gRects[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gRects)))]; 145 } 146 147 const SkRRect& TestRRectSimple(SkRandom* random) { 148 static SkRRect gRRect[2]; 149 static bool gOnce; 150 if (!gOnce) { 151 gOnce = true; 152 SkRect rectangle = SkRect::MakeWH(10.f, 20.f); 153 // true round rect with circular corners 154 gRRect[0].setRectXY(rectangle, 1.f, 1.f); 155 // true round rect with elliptical corners 156 gRRect[1].setRectXY(rectangle, 2.0f, 1.0f); 157 158 for (size_t i = 0; i < SK_ARRAY_COUNT(gRRect); i++) { 159 SkASSERT(gRRect[i].isSimple()); 160 } 161 } 162 return gRRect[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gRRect)))]; 163 } 164 165 const SkPath& TestPath(SkRandom* random) { 166 static SkPath gPath[7]; 167 static bool gOnce; 168 if (!gOnce) { 169 gOnce = true; 170 // line 171 gPath[0].moveTo(0.f, 0.f); 172 gPath[0].lineTo(10.f, 10.f); 173 // quad 174 gPath[1].moveTo(0.f, 0.f); 175 gPath[1].quadTo(10.f, 10.f, 20.f, 20.f); 176 // conic 177 gPath[2].moveTo(0.f, 0.f); 178 gPath[2].conicTo(10.f, 10.f, 20.f, 20.f, 1.f); 179 // cubic 180 gPath[3].moveTo(0.f, 0.f); 181 gPath[3].cubicTo(10.f, 10.f, 20.f, 20.f, 30.f, 30.f); 182 // all three 183 gPath[4].moveTo(0.f, 0.f); 184 gPath[4].lineTo(10.f, 10.f); 185 gPath[4].quadTo(10.f, 10.f, 20.f, 20.f); 186 gPath[4].conicTo(10.f, 10.f, 20.f, 20.f, 1.f); 187 gPath[4].cubicTo(10.f, 10.f, 20.f, 20.f, 30.f, 30.f); 188 // convex 189 gPath[5].moveTo(0.0f, 0.0f); 190 gPath[5].lineTo(10.0f, 0.0f); 191 gPath[5].lineTo(10.0f, 10.0f); 192 gPath[5].lineTo(0.0f, 10.0f); 193 gPath[5].close(); 194 // concave 195 gPath[6].moveTo(0.0f, 0.0f); 196 gPath[6].lineTo(5.0f, 5.0f); 197 gPath[6].lineTo(10.0f, 0.0f); 198 gPath[6].lineTo(10.0f, 10.0f); 199 gPath[6].lineTo(0.0f, 10.0f); 200 gPath[6].close(); 201 } 202 203 return gPath[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gPath)))]; 204 } 205 206 const SkPath& TestPathConvex(SkRandom* random) { 207 static SkPath gPath[3]; 208 static bool gOnce; 209 if (!gOnce) { 210 gOnce = true; 211 // narrow rect 212 gPath[0].moveTo(-1.5f, -50.0f); 213 gPath[0].lineTo(-1.5f, -50.0f); 214 gPath[0].lineTo( 1.5f, -50.0f); 215 gPath[0].lineTo( 1.5f, 50.0f); 216 gPath[0].lineTo(-1.5f, 50.0f); 217 // degenerate 218 gPath[1].moveTo(-0.025f, -0.025f); 219 gPath[1].lineTo(-0.025f, -0.025f); 220 gPath[1].lineTo( 0.025f, -0.025f); 221 gPath[1].lineTo( 0.025f, 0.025f); 222 gPath[1].lineTo(-0.025f, 0.025f); 223 // clipped triangle 224 gPath[2].moveTo(-10.0f, -50.0f); 225 gPath[2].lineTo(-10.0f, -50.0f); 226 gPath[2].lineTo( 10.0f, -50.0f); 227 gPath[2].lineTo( 50.0f, 31.0f); 228 gPath[2].lineTo( 40.0f, 50.0f); 229 gPath[2].lineTo(-40.0f, 50.0f); 230 gPath[2].lineTo(-50.0f, 31.0f); 231 232 for (size_t i = 0; i < SK_ARRAY_COUNT(gPath); i++) { 233 SkASSERT(SkPath::kConvex_Convexity == gPath[i].getConvexity()); 234 } 235 } 236 237 return gPath[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gPath)))]; 238 } 239 240 static void randomize_stroke_rec(SkStrokeRec* rec, SkRandom* random) { 241 bool strokeAndFill = random->nextBool(); 242 SkScalar strokeWidth = random->nextBool() ? 0.f : 1.f; 243 rec->setStrokeStyle(strokeWidth, strokeAndFill); 244 245 SkPaint::Cap cap = SkPaint::Cap(random->nextULessThan(SkPaint::kCapCount)); 246 SkPaint::Join join = SkPaint::Join(random->nextULessThan(SkPaint::kJoinCount)); 247 SkScalar miterLimit = random->nextRangeScalar(1.f, 5.f); 248 rec->setStrokeParams(cap, join, miterLimit); 249 } 250 251 SkStrokeRec TestStrokeRec(SkRandom* random) { 252 SkStrokeRec::InitStyle style = 253 SkStrokeRec::InitStyle(random->nextULessThan(SkStrokeRec::kFill_InitStyle + 1)); 254 SkStrokeRec rec(style); 255 randomize_stroke_rec(&rec, random); 256 return rec; 257 } 258 259 void TestStyle(SkRandom* random, GrStyle* style) { 260 SkStrokeRec::InitStyle initStyle = 261 SkStrokeRec::InitStyle(random->nextULessThan(SkStrokeRec::kFill_InitStyle + 1)); 262 SkStrokeRec stroke(initStyle); 263 randomize_stroke_rec(&stroke, random); 264 sk_sp<SkPathEffect> pe; 265 if (random->nextBool()) { 266 int cnt = random->nextRangeU(1, 50) * 2; 267 std::unique_ptr<SkScalar[]> intervals(new SkScalar[cnt]); 268 SkScalar sum = 0; 269 for (int i = 0; i < cnt; i++) { 270 intervals[i] = random->nextRangeScalar(SkDoubleToScalar(0.01), 271 SkDoubleToScalar(10.0)); 272 sum += intervals[i]; 273 } 274 SkScalar phase = random->nextRangeScalar(0, sum); 275 pe = TestDashPathEffect::Make(intervals.get(), cnt, phase); 276 } 277 *style = GrStyle(stroke, std::move(pe)); 278 } 279 280 TestDashPathEffect::TestDashPathEffect(const SkScalar* intervals, int count, SkScalar phase) { 281 fCount = count; 282 fIntervals.reset(count); 283 memcpy(fIntervals.get(), intervals, count * sizeof(SkScalar)); 284 SkDashPath::CalcDashParameters(phase, intervals, count, &fInitialDashLength, 285 &fInitialDashIndex, &fIntervalLength, &fPhase); 286 } 287 288 bool TestDashPathEffect::filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec, 289 const SkRect* cullRect) const { 290 return SkDashPath::InternalFilter(dst, src, rec, cullRect, fIntervals.get(), fCount, 291 fInitialDashLength, fInitialDashIndex, fIntervalLength); 292 } 293 294 SkPathEffect::DashType TestDashPathEffect::asADash(DashInfo* info) const { 295 if (info) { 296 if (info->fCount >= fCount && info->fIntervals) { 297 memcpy(info->fIntervals, fIntervals.get(), fCount * sizeof(SkScalar)); 298 } 299 info->fCount = fCount; 300 info->fPhase = fPhase; 301 } 302 return kDash_DashType; 303 } 304 305 sk_sp<SkColorSpace> TestColorSpace(SkRandom* random) { 306 static sk_sp<SkColorSpace> gColorSpaces[3]; 307 static bool gOnce; 308 if (!gOnce) { 309 gOnce = true; 310 // No color space (legacy mode) 311 gColorSpaces[0] = nullptr; 312 // sRGB or color-spin sRGB 313 gColorSpaces[1] = SkColorSpace::MakeSRGB(); 314 gColorSpaces[2] = SkColorSpace::MakeSRGB()->makeColorSpin(); 315 } 316 return gColorSpaces[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gColorSpaces)))]; 317 } 318 319 sk_sp<GrColorSpaceXform> TestColorXform(SkRandom* random) { 320 static sk_sp<GrColorSpaceXform> gXforms[3]; 321 static bool gOnce; 322 if (!gOnce) { 323 gOnce = true; 324 sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB(); 325 sk_sp<SkColorSpace> spin = SkColorSpace::MakeSRGB()->makeColorSpin(); 326 // No gamut change 327 gXforms[0] = nullptr; 328 // To different gamut (with automatic transfer function) 329 gXforms[1] = GrColorSpaceXform::Make(srgb.get(), kSRGBA_8888_GrPixelConfig, spin.get()); 330 // To different gamut (with manual transfer function) 331 gXforms[2] = GrColorSpaceXform::Make(spin.get(), kRGBA_8888_GrPixelConfig, srgb.get()); 332 } 333 return gXforms[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gXforms)))]; 334 } 335 336 TestAsFPArgs::TestAsFPArgs(GrProcessorTestData* d) 337 : fViewMatrixStorage(TestMatrix(d->fRandom)) 338 , fColorSpaceInfoStorage(skstd::make_unique<GrColorSpaceInfo>(TestColorSpace(d->fRandom), 339 kRGBA_8888_GrPixelConfig)) 340 , fArgs(d->context(), &fViewMatrixStorage, nullptr, kNone_SkFilterQuality, 341 fColorSpaceInfoStorage.get()) 342 {} 343 344 TestAsFPArgs::~TestAsFPArgs() {} 345 346 } // namespace GrTest 347 348 #endif 349