1 /*
2 * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer.
11 * 2. Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following
13 * disclaimer in the documentation and/or other materials
14 * provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
27 * OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include "config.h"
31
32 #include "platform/geometry/FloatRoundedRect.h"
33
34 #include <gtest/gtest.h>
35
36 using namespace WebCore;
37
38 namespace WebCore {
39
PrintTo(const FloatSize & size,std::ostream * os)40 void PrintTo(const FloatSize& size, std::ostream* os)
41 {
42 *os << "FloatSize("
43 << size.width() << ", "
44 << size.height() << ")";
45 }
46
PrintTo(const FloatRect & rect,std::ostream * os)47 void PrintTo(const FloatRect& rect, std::ostream* os)
48 {
49 *os << "FloatRect("
50 << rect.x() << ", "
51 << rect.y() << ", "
52 << rect.width() << ", "
53 << rect.height() << ")";
54 }
55
PrintTo(const FloatRoundedRect::Radii & radii,std::ostream * os)56 void PrintTo(const FloatRoundedRect::Radii& radii, std::ostream* os)
57 {
58 *os << "FloatRoundedRect::Radii("
59 << ::testing::PrintToString(radii.topLeft()) << ", "
60 << ::testing::PrintToString(radii.topRight()) << ", "
61 << ::testing::PrintToString(radii.bottomRight()) << ", "
62 << ::testing::PrintToString(radii.bottomLeft()) << ")";
63 }
64
PrintTo(const FloatRoundedRect & roundedRect,std::ostream * os)65 void PrintTo(const FloatRoundedRect& roundedRect, std::ostream* os)
66 {
67 *os << "FloatRoundedRect("
68 << ::testing::PrintToString(roundedRect.rect()) << ", "
69 << ::testing::PrintToString(roundedRect.radii()) << ")";
70 }
71
72 } // namespace WebCore
73
74 namespace {
75
76 #define TEST_INTERCEPTS(roundedRect, yCoordinate, expectedMinXIntercept, expectedMaxXIntercept) \
77 { \
78 float minXIntercept; \
79 float maxXIntercept; \
80 EXPECT_TRUE(roundedRect.xInterceptsAtY(yCoordinate, minXIntercept, maxXIntercept)); \
81 EXPECT_FLOAT_EQ(expectedMinXIntercept, minXIntercept); \
82 EXPECT_FLOAT_EQ(expectedMaxXIntercept, maxXIntercept); \
83 }
84
TEST(FloatRoundedRectTest,zeroRadii)85 TEST(FloatRoundedRectTest, zeroRadii)
86 {
87 FloatRoundedRect r = FloatRoundedRect(1, 2, 3, 4);
88
89 EXPECT_EQ(FloatRect(1, 2, 3, 4), r.rect());
90 EXPECT_EQ(FloatSize(), r.radii().topLeft());
91 EXPECT_EQ(FloatSize(), r.radii().topRight());
92 EXPECT_EQ(FloatSize(), r.radii().bottomLeft());
93 EXPECT_EQ(FloatSize(), r.radii().bottomRight());
94 EXPECT_TRUE(r.radii().isZero());
95 EXPECT_FALSE(r.isRounded());
96 EXPECT_FALSE(r.isEmpty());
97
98 EXPECT_EQ(FloatRect(1, 2, 0, 0), r.topLeftCorner());
99 EXPECT_EQ(FloatRect(4, 2, 0, 0), r.topRightCorner());
100 EXPECT_EQ(FloatRect(4, 6, 0, 0), r.bottomRightCorner());
101 EXPECT_EQ(FloatRect(1, 6, 0, 0), r.bottomLeftCorner());
102
103 TEST_INTERCEPTS(r, 2, r.rect().x(), r.rect().maxX());
104 TEST_INTERCEPTS(r, 4, r.rect().x(), r.rect().maxX());
105 TEST_INTERCEPTS(r, 6, r.rect().x(), r.rect().maxX());
106
107 float minXIntercept;
108 float maxXIntercept;
109
110 EXPECT_FALSE(r.xInterceptsAtY(1, minXIntercept, maxXIntercept));
111 EXPECT_FALSE(r.xInterceptsAtY(7, minXIntercept, maxXIntercept));
112
113 // The FloatRoundedRect::expandRadii() function doesn't change radii FloatSizes that
114 // are <= zero. Same as RoundedRect::expandRadii().
115 r.expandRadii(20);
116 r.shrinkRadii(10);
117 EXPECT_TRUE(r.radii().isZero());
118 }
119
TEST(FloatRoundedRectTest,circle)120 TEST(FloatRoundedRectTest, circle)
121 {
122 FloatSize cornerRadii(50, 50);
123 FloatRoundedRect r(FloatRect(0, 0, 100, 100), cornerRadii, cornerRadii, cornerRadii, cornerRadii);
124
125 EXPECT_EQ(FloatRect(0, 0, 100, 100), r.rect());
126 EXPECT_EQ(cornerRadii, r.radii().topLeft());
127 EXPECT_EQ(cornerRadii, r.radii().topRight());
128 EXPECT_EQ(cornerRadii, r.radii().bottomLeft());
129 EXPECT_EQ(cornerRadii, r.radii().bottomRight());
130 EXPECT_FALSE(r.radii().isZero());
131 EXPECT_TRUE(r.isRounded());
132 EXPECT_FALSE(r.isEmpty());
133
134 EXPECT_EQ(FloatRect(0, 0, 50, 50), r.topLeftCorner());
135 EXPECT_EQ(FloatRect(50, 0, 50, 50), r.topRightCorner());
136 EXPECT_EQ(FloatRect(0, 50, 50, 50), r.bottomLeftCorner());
137 EXPECT_EQ(FloatRect(50, 50, 50, 50), r.bottomRightCorner());
138
139 TEST_INTERCEPTS(r, 0, 50, 50);
140 TEST_INTERCEPTS(r, 25, 6.69873, 93.3013);
141 TEST_INTERCEPTS(r, 50, 0, 100);
142 TEST_INTERCEPTS(r, 75, 6.69873, 93.3013);
143 TEST_INTERCEPTS(r, 100, 50, 50);
144
145 float minXIntercept;
146 float maxXIntercept;
147
148 EXPECT_FALSE(r.xInterceptsAtY(-1, minXIntercept, maxXIntercept));
149 EXPECT_FALSE(r.xInterceptsAtY(101, minXIntercept, maxXIntercept));
150 }
151
152 /*
153 * FloatRoundedRect geometry for this test. Corner radii are in parens, x and y intercepts
154 * for the elliptical corners are noted. The rectangle itself is at 0,0 with width and height 100.
155 *
156 * (10, 15) x=10 x=90 (10, 20)
157 * (--+---------+--)
158 * y=15 +--| |-+ y=20
159 * | |
160 * | |
161 * y=85 + -| |- + y=70
162 * (--+---------+--)
163 * (25, 15) x=25 x=80 (20, 30)
164 */
TEST(FloatRoundedRectTest,ellipticalCorners)165 TEST(FloatRoundedRectTest, ellipticalCorners)
166 {
167 FloatSize cornerSize(10, 20);
168 FloatRoundedRect::Radii cornerRadii;
169 cornerRadii.setTopLeft(FloatSize(10, 15));
170 cornerRadii.setTopRight(FloatSize(10, 20));
171 cornerRadii.setBottomLeft(FloatSize(25, 15));
172 cornerRadii.setBottomRight(FloatSize(20, 30));
173
174 FloatRoundedRect r(FloatRect(0, 0, 100, 100), cornerRadii);
175
176 EXPECT_EQ(r.radii(), FloatRoundedRect::Radii(FloatSize(10, 15), FloatSize(10, 20), FloatSize(25, 15), FloatSize(20, 30)));
177 EXPECT_EQ(r, FloatRoundedRect(FloatRect(0, 0, 100, 100), cornerRadii));
178
179 EXPECT_EQ(FloatRect(0, 0, 10, 15), r.topLeftCorner());
180 EXPECT_EQ(FloatRect(90, 0, 10, 20), r.topRightCorner());
181 EXPECT_EQ(FloatRect(0, 85, 25, 15), r.bottomLeftCorner());
182 EXPECT_EQ(FloatRect(80, 70, 20, 30), r.bottomRightCorner());
183
184 TEST_INTERCEPTS(r, 5, 2.5464401, 96.61438);
185 TEST_INTERCEPTS(r, 15, 0, 99.682457);
186 TEST_INTERCEPTS(r, 20, 0, 100);
187 TEST_INTERCEPTS(r, 50, 0, 100);
188 TEST_INTERCEPTS(r, 70, 0, 100);
189 TEST_INTERCEPTS(r, 85, 0, 97.320511);
190 TEST_INTERCEPTS(r, 95, 6.3661003, 91.05542);
191
192 float minXIntercept;
193 float maxXIntercept;
194
195 EXPECT_FALSE(r.xInterceptsAtY(-1, minXIntercept, maxXIntercept));
196 EXPECT_FALSE(r.xInterceptsAtY(101, minXIntercept, maxXIntercept));
197 }
198
199 } // namespace
200
201