• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "GrStrokeInfo.h"
9 #include "GrTestUtils.h"
10 #include "SkMatrix.h"
11 #include "SkPathEffect.h"
12 #include "SkPath.h"
13 #include "SkRRect.h"
14 
15 #ifdef GR_TEST_UTILS
16 
test_matrix(SkRandom * random,bool includePerspective)17 static const SkMatrix& test_matrix(SkRandom* random, bool includePerspective) {
18     static SkMatrix gMatrices[5];
19     static const int kPerspectiveCount = 1;
20     static bool gOnce;
21     if (!gOnce) {
22         gOnce = true;
23         gMatrices[0].reset();
24         gMatrices[1].setTranslate(SkIntToScalar(-100), SkIntToScalar(100));
25         gMatrices[2].setRotate(SkIntToScalar(17));
26         gMatrices[3].setRotate(SkIntToScalar(185));
27         gMatrices[3].postTranslate(SkIntToScalar(66), SkIntToScalar(-33));
28         gMatrices[3].postScale(SkIntToScalar(2), SK_ScalarHalf);
29 
30         // Perspective matrices
31         gMatrices[4].setRotate(SkIntToScalar(215));
32         gMatrices[4].set(SkMatrix::kMPersp0, 0.00013f);
33         gMatrices[4].set(SkMatrix::kMPersp1, -0.000039f);
34     }
35 
36     uint32_t count = static_cast<uint32_t>(SK_ARRAY_COUNT(gMatrices));
37     if (includePerspective) {
38         return gMatrices[random->nextULessThan(count)];
39     } else {
40         return gMatrices[random->nextULessThan(count - kPerspectiveCount)];
41     }
42 }
43 
44 namespace GrTest {
TestMatrix(SkRandom * random)45 const SkMatrix& TestMatrix(SkRandom* random) { return test_matrix(random, true); }
46 
TestMatrixPreservesRightAngles(SkRandom * random)47 const SkMatrix& TestMatrixPreservesRightAngles(SkRandom* random) {
48     static SkMatrix gMatrices[5];
49     static bool gOnce;
50     if (!gOnce) {
51         gOnce = true;
52         // identity
53         gMatrices[0].reset();
54         // translation
55         gMatrices[1].setTranslate(SkIntToScalar(-100), SkIntToScalar(100));
56         // scale
57         gMatrices[2].setScale(SkIntToScalar(17), SkIntToScalar(17));
58         // scale + translation
59         gMatrices[3].setScale(SkIntToScalar(-17), SkIntToScalar(-17));
60         gMatrices[3].postTranslate(SkIntToScalar(66), SkIntToScalar(-33));
61         // orthogonal basis vectors
62         gMatrices[4].reset();
63         gMatrices[4].setScale(SkIntToScalar(-1), SkIntToScalar(-1));
64         gMatrices[4].setRotate(47);
65 
66         for (size_t i = 0; i < SK_ARRAY_COUNT(gMatrices); i++) {
67             SkASSERT(gMatrices[i].preservesRightAngles());
68         }
69     }
70     return gMatrices[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gMatrices)))];
71 }
72 
TestMatrixRectStaysRect(SkRandom * random)73 const SkMatrix& TestMatrixRectStaysRect(SkRandom* random) {
74     static SkMatrix gMatrices[6];
75     static bool gOnce;
76     if (!gOnce) {
77         gOnce = true;
78         // identity
79         gMatrices[0].reset();
80         // translation
81         gMatrices[1].setTranslate(SkIntToScalar(-100), SkIntToScalar(100));
82         // scale
83         gMatrices[2].setScale(SkIntToScalar(17), SkIntToScalar(17));
84         // scale + translation
85         gMatrices[3].setScale(SkIntToScalar(-17), SkIntToScalar(-17));
86         gMatrices[3].postTranslate(SkIntToScalar(66), SkIntToScalar(-33));
87         // reflection
88         gMatrices[4].setScale(SkIntToScalar(-1), SkIntToScalar(-1));
89         // 90 degress rotation
90         gMatrices[5].setRotate(90);
91 
92         for (size_t i = 0; i < SK_ARRAY_COUNT(gMatrices); i++) {
93             SkASSERT(gMatrices[i].rectStaysRect());
94         }
95     }
96     return gMatrices[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gMatrices)))];
97 }
98 
TestMatrixInvertible(SkRandom * random)99 const SkMatrix& TestMatrixInvertible(SkRandom* random) { return test_matrix(random, false); }
100 
TestRect(SkRandom * random)101 const SkRect& TestRect(SkRandom* random) {
102     static SkRect gRects[7];
103     static bool gOnce;
104     if (!gOnce) {
105         gOnce = true;
106         gRects[0] = SkRect::MakeWH(1.f, 1.f);
107         gRects[1] = SkRect::MakeWH(1.0f, 256.0f);
108         gRects[2] = SkRect::MakeWH(256.0f, 1.0f);
109         gRects[3] = SkRect::MakeLargest();
110         gRects[4] = SkRect::MakeLTRB(-65535.0f, -65535.0f, 65535.0f, 65535.0f);
111         gRects[5] = SkRect::MakeLTRB(-10.0f, -10.0f, 10.0f, 10.0f);
112     }
113     return gRects[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gRects)))];
114 }
115 
116 // Just some simple rects for code which expects its input very sanitized
TestSquare(SkRandom * random)117 const SkRect& TestSquare(SkRandom* random) {
118     static SkRect gRects[2];
119     static bool gOnce;
120     if (!gOnce) {
121         gOnce = true;
122         gRects[0] = SkRect::MakeWH(128.f, 128.f);
123         gRects[1] = SkRect::MakeWH(256.0f, 256.0f);
124     }
125     return gRects[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gRects)))];
126 }
127 
TestRRectSimple(SkRandom * random)128 const SkRRect& TestRRectSimple(SkRandom* random) {
129     static SkRRect gRRect[2];
130     static bool gOnce;
131     if (!gOnce) {
132         gOnce = true;
133         SkRect rectangle = SkRect::MakeWH(10.f, 20.f);
134         // true round rect with circular corners
135         gRRect[0].setRectXY(rectangle, 1.f, 1.f);
136         // true round rect with elliptical corners
137         gRRect[1].setRectXY(rectangle, 2.0f, 1.0f);
138 
139         for (size_t i = 0; i < SK_ARRAY_COUNT(gRRect); i++) {
140             SkASSERT(gRRect[i].isSimple());
141         }
142     }
143     return gRRect[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gRRect)))];
144 }
145 
TestPath(SkRandom * random)146 const SkPath& TestPath(SkRandom* random) {
147     static SkPath gPath[7];
148     static bool gOnce;
149     if (!gOnce) {
150         gOnce = true;
151         // line
152         gPath[0].moveTo(0.f, 0.f);
153         gPath[0].lineTo(10.f, 10.f);
154         // quad
155         gPath[1].moveTo(0.f, 0.f);
156         gPath[1].quadTo(10.f, 10.f, 20.f, 20.f);
157         // conic
158         gPath[2].moveTo(0.f, 0.f);
159         gPath[2].conicTo(10.f, 10.f, 20.f, 20.f, 1.f);
160         // cubic
161         gPath[3].moveTo(0.f, 0.f);
162         gPath[3].cubicTo(10.f, 10.f, 20.f, 20.f, 30.f, 30.f);
163         // all three
164         gPath[4].moveTo(0.f, 0.f);
165         gPath[4].lineTo(10.f, 10.f);
166         gPath[4].quadTo(10.f, 10.f, 20.f, 20.f);
167         gPath[4].conicTo(10.f, 10.f, 20.f, 20.f, 1.f);
168         gPath[4].cubicTo(10.f, 10.f, 20.f, 20.f, 30.f, 30.f);
169         // convex
170         gPath[5].moveTo(0.0f, 0.0f);
171         gPath[5].lineTo(10.0f, 0.0f);
172         gPath[5].lineTo(10.0f, 10.0f);
173         gPath[5].lineTo(0.0f, 10.0f);
174         gPath[5].close();
175         // concave
176         gPath[6].moveTo(0.0f, 0.0f);
177         gPath[6].lineTo(5.0f, 5.0f);
178         gPath[6].lineTo(10.0f, 0.0f);
179         gPath[6].lineTo(10.0f, 10.0f);
180         gPath[6].lineTo(0.0f, 10.0f);
181         gPath[6].close();
182     }
183 
184     return gPath[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gPath)))];
185 }
186 
TestPathConvex(SkRandom * random)187 const SkPath& TestPathConvex(SkRandom* random) {
188     static SkPath gPath[3];
189     static bool gOnce;
190     if (!gOnce) {
191         gOnce = true;
192         // narrow rect
193         gPath[0].moveTo(-1.5f, -50.0f);
194         gPath[0].lineTo(-1.5f, -50.0f);
195         gPath[0].lineTo( 1.5f, -50.0f);
196         gPath[0].lineTo( 1.5f,  50.0f);
197         gPath[0].lineTo(-1.5f,  50.0f);
198         // degenerate
199         gPath[1].moveTo(-0.025f, -0.025f);
200         gPath[1].lineTo(-0.025f, -0.025f);
201         gPath[1].lineTo( 0.025f, -0.025f);
202         gPath[1].lineTo( 0.025f,  0.025f);
203         gPath[1].lineTo(-0.025f,  0.025f);
204         // clipped triangle
205         gPath[2].moveTo(-10.0f, -50.0f);
206         gPath[2].lineTo(-10.0f, -50.0f);
207         gPath[2].lineTo( 10.0f, -50.0f);
208         gPath[2].lineTo( 50.0f,  31.0f);
209         gPath[2].lineTo( 40.0f,  50.0f);
210         gPath[2].lineTo(-40.0f,  50.0f);
211         gPath[2].lineTo(-50.0f,  31.0f);
212 
213         for (size_t i = 0; i < SK_ARRAY_COUNT(gPath); i++) {
214             SkASSERT(SkPath::kConvex_Convexity == gPath[i].getConvexity());
215         }
216     }
217 
218     return gPath[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gPath)))];
219 }
220 
randomize_stroke_rec(SkStrokeRec * rec,SkRandom * random)221 static void randomize_stroke_rec(SkStrokeRec* rec, SkRandom* random) {
222     bool strokeAndFill = random->nextBool();
223     SkScalar strokeWidth = random->nextBool() ? 0.f : 1.f;
224     rec->setStrokeStyle(strokeWidth, strokeAndFill);
225 
226     SkPaint::Cap cap = SkPaint::Cap(random->nextULessThan(SkPaint::kCapCount));
227     SkPaint::Join join = SkPaint::Join(random->nextULessThan(SkPaint::kJoinCount));
228     SkScalar miterLimit = random->nextRangeScalar(1.f, 5.f);
229     rec->setStrokeParams(cap, join, miterLimit);
230 }
231 
TestStrokeRec(SkRandom * random)232 SkStrokeRec TestStrokeRec(SkRandom* random) {
233     SkStrokeRec::InitStyle style =
234             SkStrokeRec::InitStyle(random->nextULessThan(SkStrokeRec::kFill_InitStyle + 1));
235     SkStrokeRec rec(style);
236     randomize_stroke_rec(&rec, random);
237     return rec;
238 }
239 
TestStrokeInfo(SkRandom * random)240 GrStrokeInfo TestStrokeInfo(SkRandom* random) {
241     SkStrokeRec::InitStyle style =
242             SkStrokeRec::InitStyle(random->nextULessThan(SkStrokeRec::kFill_InitStyle + 1));
243     GrStrokeInfo strokeInfo(style);
244     randomize_stroke_rec(&strokeInfo, random);
245     SkPathEffect::DashInfo dashInfo;
246     dashInfo.fCount = random->nextRangeU(1, 50) * 2;
247     dashInfo.fIntervals = new SkScalar[dashInfo.fCount];
248     SkScalar sum = 0;
249     for (int i = 0; i < dashInfo.fCount; i++) {
250         dashInfo.fIntervals[i] = random->nextRangeScalar(SkDoubleToScalar(0.01),
251                                                          SkDoubleToScalar(10.0));
252         sum += dashInfo.fIntervals[i];
253     }
254     dashInfo.fPhase = random->nextRangeScalar(0, sum);
255     strokeInfo.setDashInfo(dashInfo);
256     delete[] dashInfo.fIntervals;
257     return strokeInfo;
258 }
259 
260 };
261 
262 #endif
263