blob: de720b5cf2245afd2669e0afc2c4f2b2129b5ac8 [file] [log] [blame]
Jim Van Verth4db18ed2018-04-03 10:00:37 -04001/*
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#include "Test.h"
8#include "SkOffsetPolygon.h"
9
10static bool is_convex(const SkTDArray<SkPoint>& poly) {
11 if (poly.count() < 3) {
12 return false;
13 }
14
15 SkVector v0 = poly[0] - poly[poly.count() - 1];
16 SkVector v1 = poly[1] - poly[poly.count() - 1];
17 SkScalar winding = v0.cross(v1);
18
19 for (int i = 0; i < poly.count()-1; ++i) {
20 int j = i + 1;
21 int k = (i + 2) % poly.count();
22
23 SkVector v0 = poly[j] - poly[i];
24 SkVector v1 = poly[k] - poly[i];
25 SkScalar perpDot = v0.cross(v1);
26 if (winding*perpDot < 0) {
27 return false;
28 }
29 }
30
31 return true;
32}
33
34DEF_TEST(OffsetSimplePoly, reporter) {
35 SkTDArray<SkPoint> rrectPoly;
36
37 ///////////////////////////////////////////////////////////////////////
38 // Try convex tests first
39
40 // round rect
41 *rrectPoly.push() = SkPoint::Make(-100, 55);
42 *rrectPoly.push() = SkPoint::Make(100, 55);
43 *rrectPoly.push() = SkPoint::Make(100 + 2.5f, 50 + 4.330127f);
44 *rrectPoly.push() = SkPoint::Make(100 + 3.535534f, 50 + 3.535534f);
45 *rrectPoly.push() = SkPoint::Make(100 + 4.330127f, 50 + 2.5f);
46 *rrectPoly.push() = SkPoint::Make(105, 50);
47 *rrectPoly.push() = SkPoint::Make(105, -50);
48 *rrectPoly.push() = SkPoint::Make(100 + 4.330127f, -50 - 2.5f);
49 *rrectPoly.push() = SkPoint::Make(100 + 3.535534f, -50 - 3.535534f);
50 *rrectPoly.push() = SkPoint::Make(100 + 2.5f, -50 - 4.330127f);
51 *rrectPoly.push() = SkPoint::Make(100, -55);
52 *rrectPoly.push() = SkPoint::Make(-100, -55);
53 *rrectPoly.push() = SkPoint::Make(-100 - 2.5f, -50 - 4.330127f);
54 *rrectPoly.push() = SkPoint::Make(-100 - 3.535534f, -50 - 3.535534f);
55 *rrectPoly.push() = SkPoint::Make(-100 - 4.330127f, -50 - 2.5f);
56 *rrectPoly.push() = SkPoint::Make(-105, -50);
57 *rrectPoly.push() = SkPoint::Make(-105, 50);
58 *rrectPoly.push() = SkPoint::Make(-100 - 4.330127f, 50 + 2.5f);
59 *rrectPoly.push() = SkPoint::Make(-100 - 3.535534f, 50 + 3.535534f);
60 *rrectPoly.push() = SkPoint::Make(-100 - 2.5f, 50 + 4.330127f);
61 REPORTER_ASSERT(reporter, is_convex(rrectPoly));
62
63 // inset a little
64 SkTDArray<SkPoint> offsetPoly;
65 bool result = SkOffsetSimplePolygon(&rrectPoly[0], rrectPoly.count(), 3, &offsetPoly);
66 REPORTER_ASSERT(reporter, result);
67 REPORTER_ASSERT(reporter, is_convex(offsetPoly));
68
69 // inset to rect
70 result = SkOffsetSimplePolygon(&rrectPoly[0], rrectPoly.count(), 10, &offsetPoly);
71 REPORTER_ASSERT(reporter, result);
72 REPORTER_ASSERT(reporter, is_convex(offsetPoly));
73 REPORTER_ASSERT(reporter, offsetPoly.count() == 4);
74 if (offsetPoly.count() == 4) {
75 REPORTER_ASSERT(reporter, offsetPoly[0].equals(-95, 45));
76 REPORTER_ASSERT(reporter, offsetPoly[1].equals(95, 45));
77 REPORTER_ASSERT(reporter, offsetPoly[2].equals(95, -45));
78 REPORTER_ASSERT(reporter, offsetPoly[3].equals(-95, -45));
79 }
80
81 // just to full inset
82 // fails, but outputs a line segment
83 result = SkOffsetSimplePolygon(&rrectPoly[0], rrectPoly.count(), 55, &offsetPoly);
84 REPORTER_ASSERT(reporter, !result);
85 REPORTER_ASSERT(reporter, !is_convex(offsetPoly));
86 REPORTER_ASSERT(reporter, offsetPoly.count() == 2);
87 if (offsetPoly.count() == 2) {
88 REPORTER_ASSERT(reporter, offsetPoly[0].equals(-50, 0));
89 REPORTER_ASSERT(reporter, offsetPoly[1].equals(50, 0));
90 }
91
92 // past full inset
93 result = SkOffsetSimplePolygon(&rrectPoly[0], rrectPoly.count(), 75, &offsetPoly);
94 REPORTER_ASSERT(reporter, !result);
Jim Van Verth4db18ed2018-04-03 10:00:37 -040095
96 // troublesome case
97 SkTDArray<SkPoint> clippedRRectPoly;
98 *clippedRRectPoly.push() = SkPoint::Make(335.928101f, 428.219055f);
99 *clippedRRectPoly.push() = SkPoint::Make(330.414459f, 423.034912f);
100 *clippedRRectPoly.push() = SkPoint::Make(325.749084f, 417.395508f);
101 *clippedRRectPoly.push() = SkPoint::Make(321.931946f, 411.300842f);
102 *clippedRRectPoly.push() = SkPoint::Make(318.963074f, 404.750977f);
103 *clippedRRectPoly.push() = SkPoint::Make(316.842468f, 397.745850f);
104 *clippedRRectPoly.push() = SkPoint::Make(315.570068f, 390.285522f);
105 *clippedRRectPoly.push() = SkPoint::Make(315.145966f, 382.369965f);
106 *clippedRRectPoly.push() = SkPoint::Make(315.570068f, 374.454346f);
107 *clippedRRectPoly.push() = SkPoint::Make(316.842468f, 366.994019f);
108 *clippedRRectPoly.push() = SkPoint::Make(318.963074f, 359.988892f);
109 *clippedRRectPoly.push() = SkPoint::Make(321.931946f, 353.439056f);
110 *clippedRRectPoly.push() = SkPoint::Make(325.749084f, 347.344421f);
111 *clippedRRectPoly.push() = SkPoint::Make(330.414459f, 341.705017f);
112 *clippedRRectPoly.push() = SkPoint::Make(335.928101f, 336.520813f);
113 *clippedRRectPoly.push() = SkPoint::Make(342.289948f, 331.791901f);
114 *clippedRRectPoly.push() = SkPoint::Make(377.312134f, 331.791901f);
115 *clippedRRectPoly.push() = SkPoint::Make(381.195313f, 332.532593f);
116 *clippedRRectPoly.push() = SkPoint::Make(384.464935f, 334.754700f);
117 *clippedRRectPoly.push() = SkPoint::Make(386.687042f, 338.024292f);
118 *clippedRRectPoly.push() = SkPoint::Make(387.427765f, 341.907532f);
119 *clippedRRectPoly.push() = SkPoint::Make(387.427765f, 422.832367f);
120 *clippedRRectPoly.push() = SkPoint::Make(386.687042f, 426.715576f);
121 *clippedRRectPoly.push() = SkPoint::Make(384.464935f, 429.985168f);
122 *clippedRRectPoly.push() = SkPoint::Make(381.195313f, 432.207275f);
123 *clippedRRectPoly.push() = SkPoint::Make(377.312134f, 432.947998f);
124 *clippedRRectPoly.push() = SkPoint::Make(342.289948f, 432.947998f);
125 REPORTER_ASSERT(reporter, is_convex(clippedRRectPoly));
126
127 result = SkOffsetSimplePolygon(&clippedRRectPoly[0], clippedRRectPoly.count(), 32.3699417f,
128 &offsetPoly);
129 REPORTER_ASSERT(reporter, result);
130 REPORTER_ASSERT(reporter, is_convex(offsetPoly));
131
132 ////////////////////////////////////////////////////////////////////////////////
133 // Concave tests
134
135 SkTDArray<SkPoint> starPoly;
136 *starPoly.push() = SkPoint::Make(0.0f, -50.0f);
137 *starPoly.push() = SkPoint::Make(14.43f, -25.0f);
138 *starPoly.push() = SkPoint::Make(43.30f, -25.0f);
139 *starPoly.push() = SkPoint::Make(28.86f, 0.0f);
140 *starPoly.push() = SkPoint::Make(43.30f, 25.0f);
141 *starPoly.push() = SkPoint::Make(14.43f, 25.0f);
142 *starPoly.push() = SkPoint::Make(0.0f, 50.0f);
143 *starPoly.push() = SkPoint::Make(-14.43f, 25.0f);
144 *starPoly.push() = SkPoint::Make(-43.30f, 25.0f);
145 *starPoly.push() = SkPoint::Make(-28.86f, 0.0f);
146 *starPoly.push() = SkPoint::Make(-43.30f, -25.0f);
147 *starPoly.push() = SkPoint::Make(-14.43f, -25.0f);
148
149 // try a variety of distances
150 result = SkOffsetSimplePolygon(&starPoly[0], starPoly.count(), 0.1f,
151 &offsetPoly);
152 REPORTER_ASSERT(reporter, result);
153
154 result = SkOffsetSimplePolygon(&starPoly[0], starPoly.count(), 5.665f,
155 &offsetPoly);
156 REPORTER_ASSERT(reporter, result);
157
158 result = SkOffsetSimplePolygon(&starPoly[0], starPoly.count(), 28,
159 &offsetPoly);
160 REPORTER_ASSERT(reporter, result);
161
162 // down to a point
163 result = SkOffsetSimplePolygon(&starPoly[0], starPoly.count(), 28.866f,
164 &offsetPoly);
165 REPORTER_ASSERT(reporter, !result);
166
167 // and past
168 result = SkOffsetSimplePolygon(&starPoly[0], starPoly.count(), 50.5f,
169 &offsetPoly);
170 REPORTER_ASSERT(reporter, !result);
171
172 // and now out
173 result = SkOffsetSimplePolygon(&starPoly[0], starPoly.count(), -0.1f,
174 &offsetPoly);
175 REPORTER_ASSERT(reporter, result);
176
177 result = SkOffsetSimplePolygon(&starPoly[0], starPoly.count(), -5.6665f,
178 &offsetPoly);
179 REPORTER_ASSERT(reporter, result);
180
181 result = SkOffsetSimplePolygon(&starPoly[0], starPoly.count(), -50,
182 &offsetPoly);
183 REPORTER_ASSERT(reporter, result);
184
185 result = SkOffsetSimplePolygon(&starPoly[0], starPoly.count(), -100,
186 &offsetPoly);
187 REPORTER_ASSERT(reporter, result);
188
189 SkTDArray<SkPoint> intersectingPoly;
190 *intersectingPoly.push() = SkPoint::Make(0.0f, -50.0f);
191 *intersectingPoly.push() = SkPoint::Make(14.43f, -25.0f);
192 *intersectingPoly.push() = SkPoint::Make(43.30f, -25.0f);
193 *intersectingPoly.push() = SkPoint::Make(-28.86f, 0.0f);
194 *intersectingPoly.push() = SkPoint::Make(43.30f, 25.0f);
195 *intersectingPoly.push() = SkPoint::Make(14.43f, 25.0f);
196 *intersectingPoly.push() = SkPoint::Make(0.0f, 50.0f);
197 *intersectingPoly.push() = SkPoint::Make(-14.43f, 25.0f);
198 *intersectingPoly.push() = SkPoint::Make(-43.30f, 25.0f);
199 *intersectingPoly.push() = SkPoint::Make(28.86f, 0.0f);
200 *intersectingPoly.push() = SkPoint::Make(-43.30f, -25.0f);
201 *intersectingPoly.push() = SkPoint::Make(-14.43f, -25.0f);
202
203 result = SkOffsetSimplePolygon(&intersectingPoly[0], intersectingPoly.count(), -100,
204 &offsetPoly);
205 REPORTER_ASSERT(reporter, !result);
206
207
208
209}