1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2015 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/core/SkMatrix.h"
9cb93a386Sopenharmony_ci#include "include/core/SkPath.h"
10cb93a386Sopenharmony_ci#include "include/core/SkRRect.h"
11cb93a386Sopenharmony_ci#include "src/core/SkPathPriv.h"
12cb93a386Sopenharmony_ci#include "tests/Test.h"
13cb93a386Sopenharmony_ci
14cb93a386Sopenharmony_cistatic SkRRect path_contains_rrect(skiatest::Reporter* reporter, const SkPath& path,
15cb93a386Sopenharmony_ci                                   SkPathDirection* dir, unsigned* start) {
16cb93a386Sopenharmony_ci    SkRRect out;
17cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, SkPathPriv::IsRRect(path, &out, dir, start));
18cb93a386Sopenharmony_ci    SkPath recreatedPath;
19cb93a386Sopenharmony_ci    recreatedPath.addRRect(out, *dir, *start);
20cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, path == recreatedPath);
21cb93a386Sopenharmony_ci    // Test that rotations/mirrors of the rrect path are still rrect paths and the returned
22cb93a386Sopenharmony_ci    // parameters for the transformed paths are correct.
23cb93a386Sopenharmony_ci    static const SkMatrix kMatrices[] = {
24cb93a386Sopenharmony_ci        SkMatrix::Scale( 1,  1),
25cb93a386Sopenharmony_ci        SkMatrix::Scale(-1,  1),
26cb93a386Sopenharmony_ci        SkMatrix::Scale( 1, -1),
27cb93a386Sopenharmony_ci        SkMatrix::Scale(-1, -1),
28cb93a386Sopenharmony_ci    };
29cb93a386Sopenharmony_ci    for (auto& m : kMatrices) {
30cb93a386Sopenharmony_ci        SkPath xformed;
31cb93a386Sopenharmony_ci        path.transform(m, &xformed);
32cb93a386Sopenharmony_ci        SkRRect xrr = SkRRect::MakeRect(SkRect::MakeEmpty());
33cb93a386Sopenharmony_ci        SkPathDirection xd = SkPathDirection::kCCW;
34cb93a386Sopenharmony_ci        unsigned xs = ~0U;
35cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, SkPathPriv::IsRRect(xformed, &xrr, &xd, &xs));
36cb93a386Sopenharmony_ci        recreatedPath.reset();
37cb93a386Sopenharmony_ci        recreatedPath.addRRect(xrr, xd, xs);
38cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, recreatedPath == xformed);
39cb93a386Sopenharmony_ci    }
40cb93a386Sopenharmony_ci    return out;
41cb93a386Sopenharmony_ci}
42cb93a386Sopenharmony_ci
43cb93a386Sopenharmony_cistatic SkRRect inner_path_contains_rrect(skiatest::Reporter* reporter, const SkRRect& in,
44cb93a386Sopenharmony_ci                                         SkPathDirection dir, unsigned start) {
45cb93a386Sopenharmony_ci    switch (in.getType()) {
46cb93a386Sopenharmony_ci        case SkRRect::kEmpty_Type:
47cb93a386Sopenharmony_ci        case SkRRect::kRect_Type:
48cb93a386Sopenharmony_ci        case SkRRect::kOval_Type:
49cb93a386Sopenharmony_ci            return in;
50cb93a386Sopenharmony_ci        default:
51cb93a386Sopenharmony_ci            break;
52cb93a386Sopenharmony_ci    }
53cb93a386Sopenharmony_ci    SkPath path;
54cb93a386Sopenharmony_ci    path.addRRect(in, dir, start);
55cb93a386Sopenharmony_ci    SkPathDirection outDir;
56cb93a386Sopenharmony_ci    unsigned outStart;
57cb93a386Sopenharmony_ci    SkRRect rrect = path_contains_rrect(reporter, path, &outDir, &outStart);
58cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, outDir == dir && outStart == start);
59cb93a386Sopenharmony_ci    return rrect;
60cb93a386Sopenharmony_ci}
61cb93a386Sopenharmony_ci
62cb93a386Sopenharmony_cistatic void path_contains_rrect_check(skiatest::Reporter* reporter, const SkRRect& in,
63cb93a386Sopenharmony_ci                                      SkPathDirection dir, unsigned start) {
64cb93a386Sopenharmony_ci    SkRRect out = inner_path_contains_rrect(reporter, in, dir, start);
65cb93a386Sopenharmony_ci    if (in != out) {
66cb93a386Sopenharmony_ci        SkDebugf("%s", "");
67cb93a386Sopenharmony_ci    }
68cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, in == out);
69cb93a386Sopenharmony_ci}
70cb93a386Sopenharmony_ci
71cb93a386Sopenharmony_cistatic void path_contains_rrect_nocheck(skiatest::Reporter* reporter, const SkRRect& in,
72cb93a386Sopenharmony_ci                                        SkPathDirection dir, unsigned start) {
73cb93a386Sopenharmony_ci    SkRRect out = inner_path_contains_rrect(reporter, in, dir, start);
74cb93a386Sopenharmony_ci    if (in == out) {
75cb93a386Sopenharmony_ci        SkDebugf("%s", "");
76cb93a386Sopenharmony_ci    }
77cb93a386Sopenharmony_ci}
78cb93a386Sopenharmony_ci
79cb93a386Sopenharmony_cistatic void path_contains_rrect_check(skiatest::Reporter* reporter, const SkRect& r,
80cb93a386Sopenharmony_ci        SkVector v[4], SkPathDirection dir, unsigned start) {
81cb93a386Sopenharmony_ci    SkRRect rrect;
82cb93a386Sopenharmony_ci    rrect.setRectRadii(r, v);
83cb93a386Sopenharmony_ci    path_contains_rrect_check(reporter, rrect, dir, start);
84cb93a386Sopenharmony_ci}
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_ciclass ForceIsRRect_Private {
87cb93a386Sopenharmony_cipublic:
88cb93a386Sopenharmony_ci    ForceIsRRect_Private(SkPath* path, SkPathDirection dir, unsigned start) {
89cb93a386Sopenharmony_ci        path->fPathRef->setIsRRect(true, dir == SkPathDirection::kCCW, start);
90cb93a386Sopenharmony_ci    }
91cb93a386Sopenharmony_ci};
92cb93a386Sopenharmony_ci
93cb93a386Sopenharmony_cistatic void force_path_contains_rrect(skiatest::Reporter* reporter, SkPath& path,
94cb93a386Sopenharmony_ci                                      SkPathDirection dir, unsigned start) {
95cb93a386Sopenharmony_ci    ForceIsRRect_Private force_rrect(&path, dir, start);
96cb93a386Sopenharmony_ci    SkPathDirection outDir;
97cb93a386Sopenharmony_ci    unsigned outStart;
98cb93a386Sopenharmony_ci    path_contains_rrect(reporter, path, &outDir, &outStart);
99cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, outDir == dir && outStart == start);
100cb93a386Sopenharmony_ci}
101cb93a386Sopenharmony_ci
102cb93a386Sopenharmony_cistatic void test_undetected_paths(skiatest::Reporter* reporter) {
103cb93a386Sopenharmony_ci    // We first get the exact conic weight used by SkPath for a circular arc. This
104cb93a386Sopenharmony_ci    // allows our local, hand-crafted, artisanal round rect paths below to exactly match the
105cb93a386Sopenharmony_ci    // factory made corporate paths produced by SkPath.
106cb93a386Sopenharmony_ci    SkPath exactPath;
107cb93a386Sopenharmony_ci    exactPath.addCircle(0, 0, 10);
108cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, SkPath::kMove_Verb == SkPathPriv::VerbData(exactPath)[0]);
109cb93a386Sopenharmony_ci    REPORTER_ASSERT(reporter, SkPath::kConic_Verb == SkPathPriv::VerbData(exactPath)[1]);
110cb93a386Sopenharmony_ci    const SkScalar weight = SkPathPriv::ConicWeightData(exactPath)[0];
111cb93a386Sopenharmony_ci
112cb93a386Sopenharmony_ci    SkPath path;
113cb93a386Sopenharmony_ci    path.moveTo(0, 62.5f);
114cb93a386Sopenharmony_ci    path.lineTo(0, 3.5f);
115cb93a386Sopenharmony_ci    path.conicTo(0, 0, 3.5f, 0, weight);
116cb93a386Sopenharmony_ci    path.lineTo(196.5f, 0);
117cb93a386Sopenharmony_ci    path.conicTo(200, 0, 200, 3.5f, weight);
118cb93a386Sopenharmony_ci    path.lineTo(200, 62.5f);
119cb93a386Sopenharmony_ci    path.conicTo(200, 66, 196.5f, 66, weight);
120cb93a386Sopenharmony_ci    path.lineTo(3.5f, 66);
121cb93a386Sopenharmony_ci    path.conicTo(0, 66, 0, 62.5, weight);
122cb93a386Sopenharmony_ci    path.close();
123cb93a386Sopenharmony_ci    force_path_contains_rrect(reporter, path, SkPathDirection::kCW, 6);
124cb93a386Sopenharmony_ci
125cb93a386Sopenharmony_ci    path.reset();
126cb93a386Sopenharmony_ci    path.moveTo(0, 81.5f);
127cb93a386Sopenharmony_ci    path.lineTo(0, 3.5f);
128cb93a386Sopenharmony_ci    path.conicTo(0, 0, 3.5f, 0, weight);
129cb93a386Sopenharmony_ci    path.lineTo(149.5, 0);
130cb93a386Sopenharmony_ci    path.conicTo(153, 0, 153, 3.5f, weight);
131cb93a386Sopenharmony_ci    path.lineTo(153, 81.5f);
132cb93a386Sopenharmony_ci    path.conicTo(153, 85, 149.5f, 85, weight);
133cb93a386Sopenharmony_ci    path.lineTo(3.5f, 85);
134cb93a386Sopenharmony_ci    path.conicTo(0, 85, 0, 81.5f, weight);
135cb93a386Sopenharmony_ci    path.close();
136cb93a386Sopenharmony_ci    force_path_contains_rrect(reporter, path, SkPathDirection::kCW, 6);
137cb93a386Sopenharmony_ci
138cb93a386Sopenharmony_ci    path.reset();
139cb93a386Sopenharmony_ci    path.moveTo(14, 1189);
140cb93a386Sopenharmony_ci    path.lineTo(14, 21);
141cb93a386Sopenharmony_ci    path.conicTo(14, 14, 21, 14, weight);
142cb93a386Sopenharmony_ci    path.lineTo(1363, 14);
143cb93a386Sopenharmony_ci    path.conicTo(1370, 14, 1370, 21, weight);
144cb93a386Sopenharmony_ci    path.lineTo(1370, 1189);
145cb93a386Sopenharmony_ci    path.conicTo(1370, 1196, 1363, 1196, weight);
146cb93a386Sopenharmony_ci    path.lineTo(21, 1196);
147cb93a386Sopenharmony_ci    path.conicTo(14, 1196, 14, 1189, weight);
148cb93a386Sopenharmony_ci    path.close();
149cb93a386Sopenharmony_ci    force_path_contains_rrect(reporter, path, SkPathDirection::kCW, 6);
150cb93a386Sopenharmony_ci
151cb93a386Sopenharmony_ci    path.reset();
152cb93a386Sopenharmony_ci    path.moveTo(14, 1743);
153cb93a386Sopenharmony_ci    path.lineTo(14, 21);
154cb93a386Sopenharmony_ci    path.conicTo(14, 14, 21, 14, weight);
155cb93a386Sopenharmony_ci    path.lineTo(1363, 14);
156cb93a386Sopenharmony_ci    path.conicTo(1370, 14, 1370, 21, weight);
157cb93a386Sopenharmony_ci    path.lineTo(1370, 1743);
158cb93a386Sopenharmony_ci    path.conicTo(1370, 1750, 1363, 1750, weight);
159cb93a386Sopenharmony_ci    path.lineTo(21, 1750);
160cb93a386Sopenharmony_ci    path.conicTo(14, 1750, 14, 1743, weight);
161cb93a386Sopenharmony_ci    path.close();
162cb93a386Sopenharmony_ci    force_path_contains_rrect(reporter, path, SkPathDirection::kCW, 6);
163cb93a386Sopenharmony_ci}
164cb93a386Sopenharmony_ci
165cb93a386Sopenharmony_cistatic const SkScalar kWidth = 100.0f;
166cb93a386Sopenharmony_cistatic const SkScalar kHeight = 100.0f;
167cb93a386Sopenharmony_ci
168cb93a386Sopenharmony_cistatic void test_tricky_radii(skiatest::Reporter* reporter) {
169cb93a386Sopenharmony_ci    for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
170cb93a386Sopenharmony_ci        for (int start = 0; start < 8; ++start) {
171cb93a386Sopenharmony_ci            {
172cb93a386Sopenharmony_ci                // crbug.com/458522
173cb93a386Sopenharmony_ci                SkRRect rr;
174cb93a386Sopenharmony_ci                const SkRect bounds = { 3709, 3709, 3709 + 7402, 3709 + 29825 };
175cb93a386Sopenharmony_ci                const SkScalar rad = 12814;
176cb93a386Sopenharmony_ci                const SkVector vec[] = { { rad, rad }, { 0, rad }, { rad, rad }, { 0, rad } };
177cb93a386Sopenharmony_ci                rr.setRectRadii(bounds, vec);
178cb93a386Sopenharmony_ci                path_contains_rrect_check(reporter, rr, dir, start);
179cb93a386Sopenharmony_ci            }
180cb93a386Sopenharmony_ci
181cb93a386Sopenharmony_ci            {
182cb93a386Sopenharmony_ci                // crbug.com//463920
183cb93a386Sopenharmony_ci                SkRect r = SkRect::MakeLTRB(0, 0, 1009, 33554432.0);
184cb93a386Sopenharmony_ci                SkVector radii[4] = {
185cb93a386Sopenharmony_ci                    { 13.0f, 8.0f }, { 170.0f, 2.0 }, { 256.0f, 33554432.0 }, { 110.0f, 5.0f }
186cb93a386Sopenharmony_ci                };
187cb93a386Sopenharmony_ci                SkRRect rr;
188cb93a386Sopenharmony_ci                rr.setRectRadii(r, radii);
189cb93a386Sopenharmony_ci                path_contains_rrect_nocheck(reporter, rr, dir, start);
190cb93a386Sopenharmony_ci            }
191cb93a386Sopenharmony_ci        }
192cb93a386Sopenharmony_ci    }
193cb93a386Sopenharmony_ci}
194cb93a386Sopenharmony_ci
195cb93a386Sopenharmony_cistatic void test_empty_crbug_458524(skiatest::Reporter* reporter) {
196cb93a386Sopenharmony_ci    for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
197cb93a386Sopenharmony_ci        for (int start = 0; start < 8; ++start) {
198cb93a386Sopenharmony_ci            SkRRect rr;
199cb93a386Sopenharmony_ci            const SkRect bounds = { 3709, 3709, 3709 + 7402, 3709 + 29825 };
200cb93a386Sopenharmony_ci            const SkScalar rad = 40;
201cb93a386Sopenharmony_ci            rr.setRectXY(bounds, rad, rad);
202cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr, dir, start);
203cb93a386Sopenharmony_ci
204cb93a386Sopenharmony_ci            SkRRect other;
205cb93a386Sopenharmony_ci            SkMatrix matrix;
206cb93a386Sopenharmony_ci            matrix.setScale(0, 1);
207cb93a386Sopenharmony_ci            rr.transform(matrix, &other);
208cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr, dir, start);
209cb93a386Sopenharmony_ci        }
210cb93a386Sopenharmony_ci    }
211cb93a386Sopenharmony_ci}
212cb93a386Sopenharmony_ci
213cb93a386Sopenharmony_cistatic void test_inset(skiatest::Reporter* reporter) {
214cb93a386Sopenharmony_ci    for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
215cb93a386Sopenharmony_ci        for (int start = 0; start < 8; ++start) {
216cb93a386Sopenharmony_ci            SkRRect rr, rr2;
217cb93a386Sopenharmony_ci            SkRect r = { 0, 0, 100, 100 };
218cb93a386Sopenharmony_ci
219cb93a386Sopenharmony_ci            rr.setRect(r);
220cb93a386Sopenharmony_ci            rr.inset(-20, -20, &rr2);
221cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr, dir, start);
222cb93a386Sopenharmony_ci
223cb93a386Sopenharmony_ci            rr.inset(20, 20, &rr2);
224cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr, dir, start);
225cb93a386Sopenharmony_ci
226cb93a386Sopenharmony_ci            rr.inset(r.width()/2, r.height()/2, &rr2);
227cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr, dir, start);
228cb93a386Sopenharmony_ci
229cb93a386Sopenharmony_ci            rr.setRectXY(r, 20, 20);
230cb93a386Sopenharmony_ci            rr.inset(19, 19, &rr2);
231cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr, dir, start);
232cb93a386Sopenharmony_ci            rr.inset(20, 20, &rr2);
233cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr, dir, start);
234cb93a386Sopenharmony_ci        }
235cb93a386Sopenharmony_ci    }
236cb93a386Sopenharmony_ci}
237cb93a386Sopenharmony_ci
238cb93a386Sopenharmony_ci
239cb93a386Sopenharmony_cistatic void test_9patch_rrect(skiatest::Reporter* reporter,
240cb93a386Sopenharmony_ci                              const SkRect& rect,
241cb93a386Sopenharmony_ci                              SkScalar l, SkScalar t, SkScalar r, SkScalar b,
242cb93a386Sopenharmony_ci                              bool checkRadii) {
243cb93a386Sopenharmony_ci    for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
244cb93a386Sopenharmony_ci        for (int start = 0; start < 8; ++start) {
245cb93a386Sopenharmony_ci            SkRRect rr;
246cb93a386Sopenharmony_ci            rr.setNinePatch(rect, l, t, r, b);
247cb93a386Sopenharmony_ci            if (checkRadii) {
248cb93a386Sopenharmony_ci                path_contains_rrect_check(reporter, rr, dir, start);
249cb93a386Sopenharmony_ci            } else {
250cb93a386Sopenharmony_ci                path_contains_rrect_nocheck(reporter, rr, dir, start);
251cb93a386Sopenharmony_ci            }
252cb93a386Sopenharmony_ci
253cb93a386Sopenharmony_ci            SkRRect rr2; // construct the same RR using the most general set function
254cb93a386Sopenharmony_ci            SkVector radii[4] = { { l, t }, { r, t }, { r, b }, { l, b } };
255cb93a386Sopenharmony_ci            rr2.setRectRadii(rect, radii);
256cb93a386Sopenharmony_ci            if (checkRadii) {
257cb93a386Sopenharmony_ci                path_contains_rrect_check(reporter, rr, dir, start);
258cb93a386Sopenharmony_ci            } else {
259cb93a386Sopenharmony_ci                path_contains_rrect_nocheck(reporter, rr, dir, start);
260cb93a386Sopenharmony_ci            }
261cb93a386Sopenharmony_ci        }
262cb93a386Sopenharmony_ci    }
263cb93a386Sopenharmony_ci}
264cb93a386Sopenharmony_ci
265cb93a386Sopenharmony_ci// Test out the basic API entry points
266cb93a386Sopenharmony_cistatic void test_round_rect_basic(skiatest::Reporter* reporter) {
267cb93a386Sopenharmony_ci    for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
268cb93a386Sopenharmony_ci        for (int start = 0; start < 8; ++start) {
269cb93a386Sopenharmony_ci            //----
270cb93a386Sopenharmony_ci            SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
271cb93a386Sopenharmony_ci
272cb93a386Sopenharmony_ci            SkRRect rr1;
273cb93a386Sopenharmony_ci            rr1.setRect(rect);
274cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr1, dir, start);
275cb93a386Sopenharmony_ci
276cb93a386Sopenharmony_ci            SkRRect rr1_2; // construct the same RR using the most general set function
277cb93a386Sopenharmony_ci            SkVector rr1_2_radii[4] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };
278cb93a386Sopenharmony_ci            rr1_2.setRectRadii(rect, rr1_2_radii);
279cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr1_2, dir, start);
280cb93a386Sopenharmony_ci            SkRRect rr1_3;  // construct the same RR using the nine patch set function
281cb93a386Sopenharmony_ci            rr1_3.setNinePatch(rect, 0, 0, 0, 0);
282cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr1_2, dir, start);
283cb93a386Sopenharmony_ci
284cb93a386Sopenharmony_ci            //----
285cb93a386Sopenharmony_ci            SkPoint halfPoint = { SkScalarHalf(kWidth), SkScalarHalf(kHeight) };
286cb93a386Sopenharmony_ci            SkRRect rr2;
287cb93a386Sopenharmony_ci            rr2.setOval(rect);
288cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr2, dir, start);
289cb93a386Sopenharmony_ci
290cb93a386Sopenharmony_ci            SkRRect rr2_2;  // construct the same RR using the most general set function
291cb93a386Sopenharmony_ci            SkVector rr2_2_radii[4] = { { halfPoint.fX, halfPoint.fY },
292cb93a386Sopenharmony_ci                                        { halfPoint.fX, halfPoint.fY },
293cb93a386Sopenharmony_ci                                        { halfPoint.fX, halfPoint.fY },
294cb93a386Sopenharmony_ci                                        { halfPoint.fX, halfPoint.fY } };
295cb93a386Sopenharmony_ci            rr2_2.setRectRadii(rect, rr2_2_radii);
296cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr2_2, dir, start);
297cb93a386Sopenharmony_ci            SkRRect rr2_3;  // construct the same RR using the nine patch set function
298cb93a386Sopenharmony_ci            rr2_3.setNinePatch(rect, halfPoint.fX, halfPoint.fY, halfPoint.fX, halfPoint.fY);
299cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr2_3, dir, start);
300cb93a386Sopenharmony_ci
301cb93a386Sopenharmony_ci            //----
302cb93a386Sopenharmony_ci            SkPoint p = { 5, 5 };
303cb93a386Sopenharmony_ci            SkRRect rr3;
304cb93a386Sopenharmony_ci            rr3.setRectXY(rect, p.fX, p.fY);
305cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr3, dir, start);
306cb93a386Sopenharmony_ci
307cb93a386Sopenharmony_ci            SkRRect rr3_2; // construct the same RR using the most general set function
308cb93a386Sopenharmony_ci            SkVector rr3_2_radii[4] = { { 5, 5 }, { 5, 5 }, { 5, 5 }, { 5, 5 } };
309cb93a386Sopenharmony_ci            rr3_2.setRectRadii(rect, rr3_2_radii);
310cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr3_2, dir, start);
311cb93a386Sopenharmony_ci            SkRRect rr3_3;  // construct the same RR using the nine patch set function
312cb93a386Sopenharmony_ci            rr3_3.setNinePatch(rect, 5, 5, 5, 5);
313cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr3_3, dir, start);
314cb93a386Sopenharmony_ci
315cb93a386Sopenharmony_ci            //----
316cb93a386Sopenharmony_ci            test_9patch_rrect(reporter, rect, 10, 9, 8, 7, true);
317cb93a386Sopenharmony_ci
318cb93a386Sopenharmony_ci            {
319cb93a386Sopenharmony_ci                // Test out the rrect from skia:3466
320cb93a386Sopenharmony_ci                SkRect rect2 = SkRect::MakeLTRB(0.358211994f, 0.755430222f, 0.872866154f,
321cb93a386Sopenharmony_ci                                                0.806214333f);
322cb93a386Sopenharmony_ci
323cb93a386Sopenharmony_ci                test_9patch_rrect(reporter,
324cb93a386Sopenharmony_ci                                  rect2,
325cb93a386Sopenharmony_ci                                  0.926942348f, 0.642850280f, 0.529063463f, 0.587844372f,
326cb93a386Sopenharmony_ci                                  false);
327cb93a386Sopenharmony_ci            }
328cb93a386Sopenharmony_ci
329cb93a386Sopenharmony_ci            //----
330cb93a386Sopenharmony_ci            SkPoint radii2[4] = { { 0, 0 }, { 0, 0 }, { 50, 50 }, { 20, 50 } };
331cb93a386Sopenharmony_ci
332cb93a386Sopenharmony_ci            SkRRect rr5;
333cb93a386Sopenharmony_ci            rr5.setRectRadii(rect, radii2);
334cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr5, dir, start);
335cb93a386Sopenharmony_ci        }
336cb93a386Sopenharmony_ci    }
337cb93a386Sopenharmony_ci}
338cb93a386Sopenharmony_ci
339cb93a386Sopenharmony_ci// Test out the cases when the RR degenerates to a rect
340cb93a386Sopenharmony_cistatic void test_round_rect_rects(skiatest::Reporter* reporter) {
341cb93a386Sopenharmony_ci    for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
342cb93a386Sopenharmony_ci        for (int start = 0; start < 8; ++start) {
343cb93a386Sopenharmony_ci            //----
344cb93a386Sopenharmony_ci            SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
345cb93a386Sopenharmony_ci            SkRRect rr1;
346cb93a386Sopenharmony_ci            rr1.setRectXY(rect, 0, 0);
347cb93a386Sopenharmony_ci
348cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr1, dir, start);
349cb93a386Sopenharmony_ci
350cb93a386Sopenharmony_ci            //----
351cb93a386Sopenharmony_ci            SkPoint radii[4] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } };
352cb93a386Sopenharmony_ci
353cb93a386Sopenharmony_ci            SkRRect rr2;
354cb93a386Sopenharmony_ci            rr2.setRectRadii(rect, radii);
355cb93a386Sopenharmony_ci
356cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr2, dir, start);
357cb93a386Sopenharmony_ci
358cb93a386Sopenharmony_ci            //----
359cb93a386Sopenharmony_ci            SkPoint radii2[4] = { { 0, 0 }, { 20, 20 }, { 50, 50 }, { 20, 50 } };
360cb93a386Sopenharmony_ci
361cb93a386Sopenharmony_ci            SkRRect rr3;
362cb93a386Sopenharmony_ci            rr3.setRectRadii(rect, radii2);
363cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr3, dir, start);
364cb93a386Sopenharmony_ci        }
365cb93a386Sopenharmony_ci    }
366cb93a386Sopenharmony_ci}
367cb93a386Sopenharmony_ci
368cb93a386Sopenharmony_ci// Test out the cases when the RR degenerates to an oval
369cb93a386Sopenharmony_cistatic void test_round_rect_ovals(skiatest::Reporter* reporter) {
370cb93a386Sopenharmony_ci    for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
371cb93a386Sopenharmony_ci        for (int start = 0; start < 8; ++start) {
372cb93a386Sopenharmony_ci            //----
373cb93a386Sopenharmony_ci            SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
374cb93a386Sopenharmony_ci            SkRRect rr1;
375cb93a386Sopenharmony_ci            rr1.setRectXY(rect, SkScalarHalf(kWidth), SkScalarHalf(kHeight));
376cb93a386Sopenharmony_ci
377cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr1, dir, start);
378cb93a386Sopenharmony_ci        }
379cb93a386Sopenharmony_ci    }
380cb93a386Sopenharmony_ci}
381cb93a386Sopenharmony_ci
382cb93a386Sopenharmony_ci// Test out the non-degenerate RR cases
383cb93a386Sopenharmony_cistatic void test_round_rect_general(skiatest::Reporter* reporter) {
384cb93a386Sopenharmony_ci    for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
385cb93a386Sopenharmony_ci        for (int start = 0; start < 8; ++start) {
386cb93a386Sopenharmony_ci            //----
387cb93a386Sopenharmony_ci            SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
388cb93a386Sopenharmony_ci            SkRRect rr1;
389cb93a386Sopenharmony_ci            rr1.setRectXY(rect, 20, 20);
390cb93a386Sopenharmony_ci
391cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr1, dir, start);
392cb93a386Sopenharmony_ci
393cb93a386Sopenharmony_ci            //----
394cb93a386Sopenharmony_ci            SkPoint radii[4] = { { 0, 0 }, { 20, 20 }, { 50, 50 }, { 20, 50 } };
395cb93a386Sopenharmony_ci
396cb93a386Sopenharmony_ci            SkRRect rr2;
397cb93a386Sopenharmony_ci            rr2.setRectRadii(rect, radii);
398cb93a386Sopenharmony_ci
399cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr2, dir, start);
400cb93a386Sopenharmony_ci        }
401cb93a386Sopenharmony_ci    }
402cb93a386Sopenharmony_ci}
403cb93a386Sopenharmony_ci
404cb93a386Sopenharmony_cistatic void test_round_rect_iffy_parameters(skiatest::Reporter* reporter) {
405cb93a386Sopenharmony_ci    for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
406cb93a386Sopenharmony_ci        for (int start = 0; start < 8; ++start) {
407cb93a386Sopenharmony_ci            SkRect rect = SkRect::MakeLTRB(0, 0, kWidth, kHeight);
408cb93a386Sopenharmony_ci            SkPoint radii[4] = { { 50, 100 }, { 100, 50 }, { 50, 100 }, { 100, 50 } };
409cb93a386Sopenharmony_ci            SkRRect rr1;
410cb93a386Sopenharmony_ci            rr1.setRectRadii(rect, radii);
411cb93a386Sopenharmony_ci            path_contains_rrect_nocheck(reporter, rr1, dir, start);
412cb93a386Sopenharmony_ci        }
413cb93a386Sopenharmony_ci    }
414cb93a386Sopenharmony_ci}
415cb93a386Sopenharmony_ci
416cb93a386Sopenharmony_cistatic void set_radii(SkVector radii[4], int index, float rad) {
417cb93a386Sopenharmony_ci    sk_bzero(radii, sizeof(SkVector) * 4);
418cb93a386Sopenharmony_ci    radii[index].set(rad, rad);
419cb93a386Sopenharmony_ci}
420cb93a386Sopenharmony_ci
421cb93a386Sopenharmony_cistatic void test_skbug_3239(skiatest::Reporter* reporter) {
422cb93a386Sopenharmony_ci    const float min = SkBits2Float(0xcb7f16c8); /* -16717512.000000 */
423cb93a386Sopenharmony_ci    const float max = SkBits2Float(0x4b7f1c1d); /*  16718877.000000 */
424cb93a386Sopenharmony_ci    const float big = SkBits2Float(0x4b7f1bd7); /*  16718807.000000 */
425cb93a386Sopenharmony_ci
426cb93a386Sopenharmony_ci    const float rad = 33436320;
427cb93a386Sopenharmony_ci
428cb93a386Sopenharmony_ci    const SkRect rectx = SkRect::MakeLTRB(min, min, max, big);
429cb93a386Sopenharmony_ci    const SkRect recty = SkRect::MakeLTRB(min, min, big, max);
430cb93a386Sopenharmony_ci
431cb93a386Sopenharmony_ci    for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
432cb93a386Sopenharmony_ci        for (int start = 0; start < 8; ++start) {
433cb93a386Sopenharmony_ci            SkVector radii[4];
434cb93a386Sopenharmony_ci            for (int i = 0; i < 4; ++i) {
435cb93a386Sopenharmony_ci                set_radii(radii, i, rad);
436cb93a386Sopenharmony_ci                path_contains_rrect_check(reporter, rectx, radii, dir, start);
437cb93a386Sopenharmony_ci                path_contains_rrect_check(reporter, recty, radii, dir, start);
438cb93a386Sopenharmony_ci            }
439cb93a386Sopenharmony_ci        }
440cb93a386Sopenharmony_ci    }
441cb93a386Sopenharmony_ci}
442cb93a386Sopenharmony_ci
443cb93a386Sopenharmony_cistatic void test_mix(skiatest::Reporter* reporter) {
444cb93a386Sopenharmony_ci    for (auto dir : {SkPathDirection::kCW, SkPathDirection::kCCW}) {
445cb93a386Sopenharmony_ci        for (int start = 0; start < 8; ++start) {
446cb93a386Sopenharmony_ci            // Test out mixed degenerate and non-degenerate geometry with Conics
447cb93a386Sopenharmony_ci            const SkVector radii[4] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 100, 100 } };
448cb93a386Sopenharmony_ci            SkRect r = SkRect::MakeWH(100, 100);
449cb93a386Sopenharmony_ci            SkRRect rr;
450cb93a386Sopenharmony_ci            rr.setRectRadii(r, radii);
451cb93a386Sopenharmony_ci            path_contains_rrect_check(reporter, rr, dir, start);
452cb93a386Sopenharmony_ci        }
453cb93a386Sopenharmony_ci    }
454cb93a386Sopenharmony_ci}
455cb93a386Sopenharmony_ci
456cb93a386Sopenharmony_ciDEF_TEST(RoundRectInPath, reporter) {
457cb93a386Sopenharmony_ci    test_tricky_radii(reporter);
458cb93a386Sopenharmony_ci    test_empty_crbug_458524(reporter);
459cb93a386Sopenharmony_ci    test_inset(reporter);
460cb93a386Sopenharmony_ci    test_round_rect_basic(reporter);
461cb93a386Sopenharmony_ci    test_round_rect_rects(reporter);
462cb93a386Sopenharmony_ci    test_round_rect_ovals(reporter);
463cb93a386Sopenharmony_ci    test_round_rect_general(reporter);
464cb93a386Sopenharmony_ci    test_undetected_paths(reporter);
465cb93a386Sopenharmony_ci    test_round_rect_iffy_parameters(reporter);
466cb93a386Sopenharmony_ci    test_skbug_3239(reporter);
467cb93a386Sopenharmony_ci    test_mix(reporter);
468cb93a386Sopenharmony_ci}
469cb93a386Sopenharmony_ci
470cb93a386Sopenharmony_ciDEF_TEST(RRect_fragile, reporter) {
471cb93a386Sopenharmony_ci    SkRect rect = {
472cb93a386Sopenharmony_ci        SkBits2Float(0x1f800000),  // 0x003F0000 was the starter value that also fails
473cb93a386Sopenharmony_ci        SkBits2Float(0x1400001C),
474cb93a386Sopenharmony_ci        SkBits2Float(0x3F000004),
475cb93a386Sopenharmony_ci        SkBits2Float(0x3F000004),
476cb93a386Sopenharmony_ci    };
477cb93a386Sopenharmony_ci
478cb93a386Sopenharmony_ci    SkPoint radii[] = {
479cb93a386Sopenharmony_ci        { SkBits2Float(0x00000001), SkBits2Float(0x00000001) },
480cb93a386Sopenharmony_ci        { SkBits2Float(0x00000020), SkBits2Float(0x00000001) },
481cb93a386Sopenharmony_ci        { SkBits2Float(0x00000000), SkBits2Float(0x00000000) },
482cb93a386Sopenharmony_ci        { SkBits2Float(0x3F000004), SkBits2Float(0x3F000004) },
483cb93a386Sopenharmony_ci    };
484cb93a386Sopenharmony_ci
485cb93a386Sopenharmony_ci    SkRRect rr;
486cb93a386Sopenharmony_ci    // please don't assert
487cb93a386Sopenharmony_ci    if (false) {    // disable until we fix this
488cb93a386Sopenharmony_ci        SkDebugf("%g 0x%08X\n", rect.fLeft, SkFloat2Bits(rect.fLeft));
489cb93a386Sopenharmony_ci        rr.setRectRadii(rect, radii);
490cb93a386Sopenharmony_ci    }
491cb93a386Sopenharmony_ci}
492cb93a386Sopenharmony_ci
493