Flutter Engine
The Flutter Engine
ShadowTest.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2017 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
10#include "include/core/SkPath.h"
14#include "include/core/SkRect.h"
24#include "tests/Test.h"
25
26#if !defined(SK_ENABLE_OPTIMIZE_SIZE)
27
31};
32
34 ExpectVerts expectVerts, bool expectSuccess) {
35 if (expectSuccess != SkToBool(verts)) {
36 ERRORF(reporter, "Expected shadow tessellation to %s but it did not.",
37 expectSuccess ? "succeed" : "fail");
38 }
39 if (SkToBool(verts)) {
40 if (kDont_ExpectVerts == expectVerts && verts->priv().vertexCount()) {
41 ERRORF(reporter, "Expected shadow tessellation to generate no vertices but it did.");
42 } else if (kDo_ExpectVerts == expectVerts && !verts->priv().vertexCount()) {
43 ERRORF(reporter, "Expected shadow tessellation to generate vertices but it didn't.");
44 }
45 }
46}
47
49 const SkPoint3& heightParams, ExpectVerts expectVerts, bool expectSuccess) {
50
51 auto verts = SkShadowTessellator::MakeAmbient(path, ctm, heightParams, true);
52 check_result(reporter, verts, expectVerts, expectSuccess);
53
54 verts = SkShadowTessellator::MakeAmbient(path, ctm, heightParams, false);
55 check_result(reporter, verts, expectVerts, expectSuccess);
56
57 verts = SkShadowTessellator::MakeSpot(path, ctm, heightParams, {0, 0, 128}, 128.f, true, false);
58 check_result(reporter, verts, expectVerts, expectSuccess);
59
60 verts = SkShadowTessellator::MakeSpot(path, ctm, heightParams, {0, 0, 128}, 128.f, false,
61 false);
62 check_result(reporter, verts, expectVerts, expectSuccess);
63
64 verts = SkShadowTessellator::MakeSpot(path, ctm, heightParams, {0, 0, 128}, 128.f, true, true);
65 check_result(reporter, verts, expectVerts, expectSuccess);
66
67 verts = SkShadowTessellator::MakeSpot(path, ctm, heightParams, {0, 0, 128}, 128.f, false, true);
68 check_result(reporter, verts, expectVerts, expectSuccess);
69}
70
71DEF_TEST(ShadowUtils, reporter) {
72 SkCanvas canvas(100, 100);
73
75 path.cubicTo(100, 50, 20, 100, 0, 0);
76 tessellate_shadow(reporter, path, canvas.getTotalMatrix(), {0, 0, 4}, kDo_ExpectVerts, true);
77 // super high path
78 tessellate_shadow(reporter, path, canvas.getTotalMatrix(), {0, 0, 4.0e+37f},
79 kDo_ExpectVerts, true);
80
81 // This line segment has no area and no shadow.
82 path.reset();
83 path.lineTo(10.f, 10.f);
85
86 // A series of collinear line segments
87 path.reset();
88 for (int i = 0; i < 10; ++i) {
89 path.lineTo((SkScalar)i, (SkScalar)i);
90 }
92
93 // ugly degenerate path
94 path.reset();
95 path.moveTo(-134217728, 2.22265153e+21f);
96 path.cubicTo(-2.33326106e+21f, 7.36298265e-41f, 3.72237738e-22f, 5.99502692e-36f,
97 1.13631943e+22f, 2.0890786e+33f);
98 path.cubicTo(1.03397626e-25f, 5.99502692e-36f, 9.18354962e-41f, 0, 4.6142745e-37f, -213558848);
99 path.lineTo(-134217728, 2.2226515e+21f);
100 tessellate_shadow(reporter, path, canvas.getTotalMatrix(), {0, 0, 9}, kDont_ExpectVerts, true);
101
102 // simple concave path (star of David)
103 path.reset();
104 path.moveTo(0.0f, -50.0f);
105 path.lineTo(14.43f, -25.0f);
106 path.lineTo(43.30f, -25.0f);
107 path.lineTo(28.86f, 0.0f);
108 path.lineTo(43.30f, 25.0f);
109 path.lineTo(14.43f, 25.0f);
110 path.lineTo(0.0f, 50.0f);
111 path.lineTo(-14.43f, 25.0f);
112 path.lineTo(-43.30f, 25.0f);
113 path.lineTo(-28.86f, 0.0f);
114 path.lineTo(-43.30f, -25.0f);
115 path.lineTo(-14.43f, -25.0f);
116// uncomment when transparent concave shadows are working
117// tessellate_shadow(reporter, path, canvas.getTotalMatrix(), {0, 0, 9}, kDo_ExpectVerts, true);
118
119 // complex concave path (bowtie)
120 path.reset();
121 path.moveTo(-50, -50);
122 path.lineTo(-50, 50);
123 path.lineTo(50, -50);
124 path.lineTo(50, 50);
125 path.lineTo(-50, -50);
126 tessellate_shadow(reporter, path, canvas.getTotalMatrix(), {0, 0, 9}, kDont_ExpectVerts, false);
127
128 // multiple contour path
129 path.close();
130 path.moveTo(0, 0);
131 path.lineTo(1, 0);
132 path.lineTo(0, 1);
133 tessellate_shadow(reporter, path, canvas.getTotalMatrix(), {0, 0, 9}, kDont_ExpectVerts, false);
134}
135
137 SkDrawShadowRec rec = {
138 SkPoint3::Make(0, 0, 4),
139 SkPoint3::Make(100, 0, 600),
140 800.f,
141 0x08000000,
142 0x40000000,
143 0
144 };
145 // point light
148 ctm.mapRect(&bounds);
149
150 auto verts = SkShadowTessellator::MakeAmbient(path, ctm, rec.fZPlaneParams, true);
151 if (verts) {
152 REPORTER_ASSERT(reporter, bounds.contains(verts->bounds()));
153 }
154
155 SkPoint mapXY = ctm.mapXY(rec.fLightPos.fX, rec.fLightPos.fY);
156 SkPoint3 devLightPos = SkPoint3::Make(mapXY.fX, mapXY.fY, rec.fLightPos.fZ);
157 verts = SkShadowTessellator::MakeSpot(path, ctm, rec.fZPlaneParams, devLightPos,
158 rec.fLightRadius, false, false);
159 if (verts) {
160 REPORTER_ASSERT(reporter, bounds.contains(verts->bounds()));
161 }
162
163 // directional light
165 rec.fLightRadius = 2.0f;
167 ctm.mapRect(&bounds);
168
169 verts = SkShadowTessellator::MakeAmbient(path, ctm, rec.fZPlaneParams, true);
170 if (verts) {
171 REPORTER_ASSERT(reporter, bounds.contains(verts->bounds()));
172 }
173
174 devLightPos = rec.fLightPos;
175 devLightPos.normalize();
176 verts = SkShadowTessellator::MakeSpot(path, ctm, rec.fZPlaneParams, devLightPos,
177 rec.fLightRadius, false, true);
178 if (verts) {
179 REPORTER_ASSERT(reporter, bounds.contains(verts->bounds()));
180 }
181}
182
184 const bool fixed_shadows_in_perspective = false; // skbug.com/9698
185
186 SkMatrix ctm;
187 ctm.setTranslate(100, 100);
189 ctm.postScale(2, 2);
191 ctm.preRotate(45);
193 ctm.preSkew(40, -20);
195 if (fixed_shadows_in_perspective) {
196 ctm[SkMatrix::kMPersp0] = 0.0001f;
197 ctm[SkMatrix::kMPersp1] = 12.f;
199 ctm[SkMatrix::kMPersp0] = 0.0001f;
200 ctm[SkMatrix::kMPersp1] = -12.f;
202 ctm[SkMatrix::kMPersp0] = 12.f;
203 ctm[SkMatrix::kMPersp1] = 0.0001f;
205 }
206}
207
208DEF_TEST(ShadowBounds, reporter) {
209 SkPath path;
210 path.addRRect(SkRRect::MakeRectXY(SkRect::MakeLTRB(-50, -20, 40, 30), 4, 4));
212
213 path.reset();
214 path.addOval(SkRect::MakeLTRB(300, 300, 900, 900));
216
217 path.reset();
218 path.cubicTo(100, 50, 20, 100, 0, 0);
220}
221
222#endif // !defined(SK_ENABLE_OPTIMIZE_SIZE)
reporter
Definition: FontMgrTest.cpp:39
void check_result(skiatest::Reporter *reporter, sk_sp< SkVertices > verts, ExpectVerts expectVerts, bool expectSuccess)
Definition: ShadowTest.cpp:33
DEF_TEST(ShadowUtils, reporter)
Definition: ShadowTest.cpp:71
void check_xformed_bounds(skiatest::Reporter *reporter, const SkPath &path, const SkMatrix &ctm)
Definition: ShadowTest.cpp:136
ExpectVerts
Definition: ShadowTest.cpp:28
@ kDont_ExpectVerts
Definition: ShadowTest.cpp:29
@ kDo_ExpectVerts
Definition: ShadowTest.cpp:30
void check_bounds(skiatest::Reporter *reporter, const SkPath &path)
Definition: ShadowTest.cpp:183
void tessellate_shadow(skiatest::Reporter *reporter, const SkPath &path, const SkMatrix &ctm, const SkPoint3 &heightParams, ExpectVerts expectVerts, bool expectSuccess)
Definition: ShadowTest.cpp:48
@ kDirectionalLight_ShadowFlag
Definition: SkShadowUtils.h:31
static constexpr bool SkToBool(const T &x)
Definition: SkTo.h:35
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
#define ERRORF(r,...)
Definition: Test.h:293
SkMatrix getTotalMatrix() const
Definition: SkCanvas.cpp:1629
SkMatrix & preSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py)
Definition: SkMatrix.cpp:512
SkMatrix & postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
Definition: SkMatrix.cpp:360
static constexpr int kMPersp1
input y perspective factor
Definition: SkMatrix.h:360
SkMatrix & setTranslate(SkScalar dx, SkScalar dy)
Definition: SkMatrix.cpp:254
void mapXY(SkScalar x, SkScalar y, SkPoint *result) const
Definition: SkMatrix.cpp:777
static constexpr int kMPersp0
input x perspective factor
Definition: SkMatrix.h:359
SkMatrix & preRotate(SkScalar degrees, SkScalar px, SkScalar py)
Definition: SkMatrix.cpp:462
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
Definition: SkMatrix.cpp:1141
Definition: SkPath.h:59
static SkRRect MakeRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
Definition: SkRRect.h:180
int vertexCount() const
SkVerticesPriv priv()
float SkScalar
Definition: extension.cpp:12
void GetLocalBounds(const SkPath &path, const SkDrawShadowRec &rec, const SkMatrix &ctm, SkRect *bounds)
Optional< SkRect > bounds
Definition: SkRecords.h:189
sk_sp< SkVertices > MakeAmbient(const SkPath &path, const SkMatrix &ctm, const SkPoint3 &zPlane, bool transparent)
sk_sp< SkVertices > MakeSpot(const SkPath &path, const SkMatrix &ctm, const SkPoint3 &zPlane, const SkPoint3 &lightPos, SkScalar lightRadius, bool transparent, bool directional)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
SkPoint3 fZPlaneParams
SkScalar fX
Definition: SkPoint3.h:16
static SkPoint3 Make(SkScalar x, SkScalar y, SkScalar z)
Definition: SkPoint3.h:18
SkScalar fZ
Definition: SkPoint3.h:16
bool normalize()
Definition: SkPoint3.cpp:49
SkScalar fY
Definition: SkPoint3.h:16
float fX
x-axis value
Definition: SkPoint_impl.h:164
float fY
y-axis value
Definition: SkPoint_impl.h:165
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition: SkRect.h:646