Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(98)

Side by Side Diff: ui/gfx/path_mac_unittest.mm

Issue 1633403002: MacViews: Add native drop shadow to dialogs on OSX < 10.10. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed review comments. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/gfx/path_mac.mm ('k') | ui/views/bubble/bubble_border.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #import "ui/gfx/path_mac.h"
6
7 #include <cmath>
8 #include <vector>
9
10 #import <Cocoa/Cocoa.h>
11
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/skia/include/core/SkRegion.h"
14 #include "ui/gfx/geometry/rect.h"
15 #include "ui/gfx/geometry/rect_conversions.h"
16 #include "ui/gfx/path.h"
17
18 namespace gfx {
19
20 namespace {
21
22 // Returns the point at a distance of |radius| from the point (|centre_x|,
23 // |centre_y|), and angle |degrees| from the positive horizontal axis, measured
24 // anti-clockwise.
25 NSPoint GetRadialPoint(double radius,
26 double degrees,
27 double centre_x,
28 double centre_y) {
29 const double radian = (degrees * SK_ScalarPI) / 180;
30 return NSMakePoint(centre_x + radius * std::cos(radian),
31 centre_y + radius * std::sin(radian));
32 }
33
34 // Returns the area of a circle with the given |radius|.
35 double CalculateCircleArea(double radius) {
36 return SK_ScalarPI * radius * radius;
37 }
38
39 // Returns the area of a simple polygon. |path| should represent a simple
40 // polygon.
41 double CalculatePolygonArea(NSBezierPath* path) {
42 // If path represents a single polygon, it will have MoveTo, followed by
43 // multiple LineTo, followed By ClosePath, followed by another MoveTo
44 // NSBezierPathElement.
45 const size_t element_count = [path elementCount];
46 NSPoint points[3];
47 std::vector<NSPoint> poly;
48
49 for (size_t i = 0; i < element_count - 1; i++) {
50 NSBezierPathElement element =
51 [path elementAtIndex:i associatedPoints:points];
52 poly.push_back(points[0]);
53 DCHECK_EQ(element,
54 i ? (i == element_count - 2 ? NSClosePathBezierPathElement
55 : NSLineToBezierPathElement)
56 : NSMoveToBezierPathElement);
57 }
58 DCHECK_EQ([path elementAtIndex:element_count - 1], NSMoveToBezierPathElement);
59
60 // Shoelace Algorithm to find the area of a simple polygon.
61 DCHECK(NSEqualPoints(poly.front(), poly.back()));
62 double area = 0;
63 for (size_t i = 0; i < poly.size() - 1; i++)
64 area += poly[i].x * poly[i + 1].y - poly[i].y * poly[i + 1].x;
65
66 return std::fabs(area) / 2.0;
67 }
68
69 // Returns the area of a rounded rectangle with the given |width|, |height| and
70 // |radius|.
71 double CalculateRoundedRectangleArea(double width,
72 double height,
73 double radius) {
74 const double inside_width = width - 2 * radius;
75 const double inside_height = height - 2 * radius;
76 return inside_width * inside_height +
77 2 * radius * (inside_width + inside_height) +
78 CalculateCircleArea(radius);
79 }
80
81 // Returns the bounding box of |path| as a Rect.
82 Rect GetBoundingBox(NSBezierPath* path) {
83 const NSRect bounds = [path bounds];
84 return ToNearestRect(RectF(bounds.origin.x, bounds.origin.y,
85 bounds.size.width, bounds.size.height));
86 }
87
88 } // namespace
89
90 // Check that empty NSBezierPath is returned for empty SkPath.
91 TEST(CreateNSBezierPathFromSkPathTest, EmptyPath) {
92 NSBezierPath* result = CreateNSBezierPathFromSkPath(SkPath());
93 EXPECT_TRUE([result isEmpty]);
94 }
95
96 // Check that the returned NSBezierPath has the correct winding rule.
97 TEST(CreateNSBezierPathFromSkPathTest, FillType) {
98 SkPath path;
99 path.setFillType(SkPath::kWinding_FillType);
100 NSBezierPath* result = CreateNSBezierPathFromSkPath(path);
101 EXPECT_EQ(NSNonZeroWindingRule, [result windingRule]);
102
103 path.setFillType(SkPath::kEvenOdd_FillType);
104 result = CreateNSBezierPathFromSkPath(path);
105 EXPECT_EQ(NSEvenOddWindingRule, [result windingRule]);
106 }
107
108 // Check that a path containing multiple subpaths, in this case two rectangles,
109 // is correctly converted to a NSBezierPath.
110 TEST(CreateNSBezierPathFromSkPathTest, TwoRectanglesPath) {
111 const SkRect rects[] = {
112 {0, 0, 50, 50}, {100, 100, 150, 150},
113 };
114 const NSPoint inside_points[] = {
115 {1, 1}, {1, 49}, {49, 49}, {49, 1}, {25, 25},
116 {101, 101}, {101, 149}, {149, 149}, {149, 101}, {125, 125}};
117 const NSPoint outside_points[] = {{-1, -1}, {-1, 51}, {51, 51}, {51, -1},
118 {99, 99}, {99, 151}, {151, 151}, {151, 99},
119 {75, 75}, {-5, -5}};
120 ASSERT_EQ(arraysize(inside_points), arraysize(outside_points));
121 const Rect expected_bounds(0, 0, 150, 150);
122
123 SkPath path;
124 path.addRect(rects[0]);
125 path.addRect(rects[1]);
126 NSBezierPath* result = CreateNSBezierPathFromSkPath(path);
127
128 // Check points near the boundary of the path and verify that they are
129 // reported correctly as being inside/outside the path.
130 for (size_t i = 0; i < arraysize(inside_points); i++) {
131 EXPECT_TRUE([result containsPoint:inside_points[i]]);
132 EXPECT_FALSE([result containsPoint:outside_points[i]]);
133 }
134
135 // Check that the returned result has the correct bounding box. GetBoundingBox
136 // rounds the coordinates to nearest integer values.
137 EXPECT_EQ(expected_bounds, GetBoundingBox(result));
138 }
139
140 // Test that an SKPath containing a circle is converted correctly to a
141 // NSBezierPath.
142 TEST(CreateNSBezierPathFromSkPathTest, CirclePath) {
143 const int kRadius = 5;
144 const int kCentreX = 10;
145 const int kCentreY = 15;
146 const double kCushion = 0.1;
147 // Expected bounding box of the circle.
148 const Rect expected_bounds(kCentreX - kRadius, kCentreY - kRadius,
149 2 * kRadius, 2 * kRadius);
150
151 SkPath path;
152 path.addCircle(SkIntToScalar(kCentreX), SkIntToScalar(kCentreY),
153 SkIntToScalar(kRadius));
154 NSBezierPath* result = CreateNSBezierPathFromSkPath(path);
155
156 // Check points near the boundary of the circle and verify that they are
157 // reported correctly as being inside/outside the path.
158 for (size_t deg = 0; deg < 360; deg++) {
159 NSPoint inside_point =
160 GetRadialPoint(kRadius - kCushion, deg, kCentreX, kCentreY);
161 NSPoint outside_point =
162 GetRadialPoint(kRadius + kCushion, deg, kCentreX, kCentreY);
163 EXPECT_TRUE([result containsPoint:inside_point]);
164 EXPECT_FALSE([result containsPoint:outside_point]);
165 }
166
167 // Check that the returned result has the correct bounding box. GetBoundingBox
168 // rounds the coordinates to nearest integer values.
169 EXPECT_EQ(expected_bounds, GetBoundingBox(result));
170
171 // Check area of converted path is correct up to a certain tolerance value. To
172 // find the area of the NSBezierPath returned, flatten it i.e. convert it to a
173 // polygon.
174 [NSBezierPath setDefaultFlatness:0.01];
175 NSBezierPath* polygon = [result bezierPathByFlatteningPath];
176 const double kTolerance = 0.14;
177 EXPECT_NEAR(CalculateCircleArea(kRadius), CalculatePolygonArea(polygon),
178 kTolerance);
179 }
180
181 // Test that an SKPath containing a rounded rectangle is converted correctly to
182 // a NSBezierPath.
183 TEST(CreateNSBezierPathFromSkPathTest, RoundedRectanglePath) {
184 const int kRectangleWidth = 50;
185 const int kRectangleHeight = 100;
186 const int kCornerRadius = 5;
187 const double kCushion = 0.1;
188 // Expected bounding box of the rounded rectangle.
189 const Rect expected_bounds(kRectangleWidth, kRectangleHeight);
190
191 SkRRect rrect;
192 rrect.setRectXY(SkRect::MakeWH(kRectangleWidth, kRectangleHeight),
193 kCornerRadius, kCornerRadius);
194
195 const NSPoint inside_points[] = {
196 // Bottom left corner.
197 {kCornerRadius / 2.0, kCornerRadius / 2.0},
198 // Bottom right corner.
199 {kRectangleWidth - kCornerRadius / 2.0, kCornerRadius / 2.0},
200 // Top Right corner.
201 {kRectangleWidth - kCornerRadius / 2.0,
202 kRectangleHeight - kCornerRadius / 2.0},
203 // Top left corner.
204 {kCornerRadius / 2.0, kRectangleHeight - kCornerRadius / 2.0},
205 // Bottom middle.
206 {kRectangleWidth / 2.0, kCushion},
207 // Right middle.
208 {kRectangleWidth - kCushion, kRectangleHeight / 2.0},
209 // Top middle.
210 {kRectangleWidth / 2.0, kRectangleHeight - kCushion},
211 // Left middle.
212 {kCushion, kRectangleHeight / 2.0}};
213 const NSPoint outside_points[] = {
214 // Bottom left corner.
215 {0, 0},
216 // Bottom right corner.
217 {kRectangleWidth, 0},
218 // Top right corner.
219 {kRectangleWidth, kRectangleHeight},
220 // Top left corner.
221 {0, kRectangleHeight},
222 // Bottom middle.
223 {kRectangleWidth / 2.0, -kCushion},
224 // Right middle.
225 {kRectangleWidth + kCushion, kRectangleHeight / 2.0},
226 // Top middle.
227 {kRectangleWidth / 2.0, kRectangleHeight + kCushion},
228 // Left middle.
229 {-kCushion, kRectangleHeight / 2.0}};
230 ASSERT_EQ(arraysize(inside_points), arraysize(outside_points));
231
232 SkPath path;
233 path.addRRect(rrect);
234 NSBezierPath* result = CreateNSBezierPathFromSkPath(path);
235
236 // Check points near the boundary of the path and verify that they are
237 // reported correctly as being inside/outside the path.
238 for (size_t i = 0; i < arraysize(inside_points); i++) {
239 EXPECT_TRUE([result containsPoint:inside_points[i]]);
240 EXPECT_FALSE([result containsPoint:outside_points[i]]);
241 }
242
243 // Check that the returned result has the correct bounding box. GetBoundingBox
244 // rounds the coordinates to nearest integer values.
245 EXPECT_EQ(expected_bounds, GetBoundingBox(result));
246
247 // Check area of converted path is correct up to a certain tolerance value. To
248 // find the area of the NSBezierPath returned, flatten it i.e. convert it to a
249 // polygon.
250 [NSBezierPath setDefaultFlatness:0.01];
251 NSBezierPath* polygon = [result bezierPathByFlatteningPath];
252 const double kTolerance = 0.14;
253 EXPECT_NEAR(CalculateRoundedRectangleArea(kRectangleWidth, kRectangleHeight,
254 kCornerRadius),
255 CalculatePolygonArea(polygon), kTolerance);
256 }
257
258 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/path_mac.mm ('k') | ui/views/bubble/bubble_border.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698