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

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
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 {
19
20 // Returns the point at a distance of |radius| from the point (|centre_x|,
21 // |centre_y|), and angle |degrees| from the positive horizontal axis, measured
22 // anti-clockwise.
23 NSPoint GetRadialPoint(double radius,
24 double degrees,
25 double centre_x,
26 double centre_y) {
27 const double radian = (degrees * SK_ScalarPI) / 180;
28 return NSMakePoint(centre_x + radius * std::cos(radian),
29 centre_y + radius * std::sin(radian));
30 }
31
32 // Returns the area of a circle with the given |radius|.
33 double CalculateCircleArea(double radius) {
34 return SK_ScalarPI * radius * radius;
35 }
36
37 // Returns the area of a simple polygon. |path| should represent a simple
38 // polygon.
39 double CalculatePolygonArea(NSBezierPath* path) {
40 // If path represents a single polygon, it will have MoveTo, followed by
41 // multiple LineTo, followed By ClosePath, followed by another MoveTo
42 // NSBezierPathElement.
43 const size_t element_count = [path elementCount];
44 NSPoint points[3];
45 std::vector<NSPoint> poly;
46
47 for (size_t i = 0; i < element_count - 1; i++) {
48 NSBezierPathElement element =
49 [path elementAtIndex:i associatedPoints:points];
50 poly.push_back(points[0]);
51 DCHECK_EQ(element,
52 i ? (i == element_count - 2 ? NSClosePathBezierPathElement
53 : NSLineToBezierPathElement)
54 : NSMoveToBezierPathElement);
55 }
56 DCHECK_EQ([path elementAtIndex:element_count - 1 associatedPoints:points],
msw 2016/02/11 23:57:37 optional nit: you could omit associatedPoints here
karandeepb 2016/02/12 03:45:52 Done.
57 NSMoveToBezierPathElement);
58 DCHECK(NSEqualPoints(points[0], poly.front()));
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;
msw 2016/02/11 23:57:37 q: don't you technically need incldue these terms
karandeepb 2016/02/12 03:45:52 The last point in the poly vector is the same as t
msw 2016/02/12 19:26:55 Acknowledged.
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 gfx::Rect.
msw 2016/02/11 23:57:38 nit: put this anon namespace inside gfx, and then
karandeepb 2016/02/12 03:45:52 Done.
82 gfx::Rect GetBoundingBox(NSBezierPath* path) {
83 const NSRect bounds = [path bounds];
84 return gfx::ToNearestRect(gfx::RectF(bounds.origin.x, bounds.origin.y,
85 bounds.size.width, bounds.size.height));
86 }
87
88 } // namespace
89
90 namespace gfx {
91
92 // Check that empty NSBezierPath is returned for empty SkPath.
93 TEST(CreateNSBezierPathFromSkPathTest, EmptyPath) {
94 NSBezierPath* result = CreateNSBezierPathFromSkPath(SkPath());
msw 2016/02/11 23:57:38 Don't you need to release (CFRelease?) all the pat
karandeepb 2016/02/12 03:45:52 It is autoreleased when it is no longer in scope(a
95 EXPECT_TRUE([result isEmpty]);
96 }
97
98 // Check that the returned NSBezierPath has the correct winding rule.
99 TEST(CreateNSBezierPathFromSkPathTest, FillType) {
100 SkPath path;
101 path.setFillType(SkPath::kWinding_FillType);
102 NSBezierPath* result = CreateNSBezierPathFromSkPath(path);
103 EXPECT_EQ(NSNonZeroWindingRule, [result windingRule]);
104
105 path.setFillType(SkPath::kEvenOdd_FillType);
106 result = CreateNSBezierPathFromSkPath(path);
107 EXPECT_EQ(NSEvenOddWindingRule, [result windingRule]);
108 }
109
110 // Check that a path containing multiple subpaths, in this case two rectangles,
111 // is correctly converted to a NSBezierPath.
112 TEST(CreateNSBezierPathFromSkPathTest, TwoRectanglesPath) {
113 const SkRect rects[] = {
114 {0, 0, 50, 50}, {100, 100, 150, 150},
115 };
116 const NSPoint inside_points[] = {
117 {1, 1}, {1, 49}, {49, 49}, {49, 1}, {101, 101},
118 {101, 149}, {149, 149}, {149, 101}, {25, 25}, {125, 125}};
msw 2016/02/11 23:57:38 nit: put {25, 25} after {49, 1}, bump {101, 101} t
karandeepb 2016/02/12 03:45:51 Done.
119 const NSPoint outside_points[] = {{-1, -1}, {-1, 51}, {51, 51}, {51, -1},
msw 2016/02/11 23:57:38 EXPECT/ASSERT_EQ(arraysize(inside_points), arraysi
karandeepb 2016/02/12 03:45:52 Done.
120 {99, 99}, {99, 151}, {151, 151}, {151, 99},
121 {75, 75}, {-5, -5}};
122 const gfx::Rect expected_bounds(0, 0, 150, 150);
msw 2016/02/11 23:57:38 nit: 'gfx::' not needed
karandeepb 2016/02/12 03:45:52 Done.
123
124 SkPath path;
125 path.addRect(rects[0]);
126 path.addRect(rects[1]);
127 NSBezierPath* result = CreateNSBezierPathFromSkPath(path);
128
129 // Check points near the boundary of the path and verify that they are
130 // reported correctly as being inside/outside the path.
131 for (size_t i = 0; i < arraysize(inside_points); i++) {
132 EXPECT_TRUE([result containsPoint:inside_points[i]]);
133 EXPECT_FALSE([result containsPoint:outside_points[i]]);
134 }
135
136 // Check that the returned result has the correct bounding box. GetBoundingBox
137 // rounds the coordinates to nearest integer values.
138 EXPECT_EQ(expected_bounds, GetBoundingBox(result));
139 }
140
141 // Test that an SKPath containing a circle is converted correctly to a
142 // NSBezierPath.
143 TEST(CreateNSBezierPathFromSkPathTest, CirclePath) {
144 const int kRadius = 5;
145 const int kCentreX = 10;
146 const int kCentreY = 15;
147 const double kCushion = 0.1;
148 // Expected bounding box of the circle.
149 const gfx::Rect expected_bounds(kCentreX - kRadius, kCentreY - kRadius,
msw 2016/02/11 23:57:38 nit: 'gfx::' not needed
karandeepb 2016/02/12 03:45:51 Done.
150 2 * kRadius, 2 * kRadius);
151
152 SkPath path;
153 path.addCircle(SkIntToScalar(kCentreX), SkIntToScalar(kCentreY),
154 SkIntToScalar(kRadius));
155 NSBezierPath* result = CreateNSBezierPathFromSkPath(path);
156
157 // Check points near the boundary of the circle and verify that they are
158 // reported correctly as being inside/outside the path.
159 for (size_t deg = 0; deg < 360; deg++) {
160 NSPoint inside_point =
161 GetRadialPoint(kRadius - kCushion, deg, kCentreX, kCentreY);
162 NSPoint outside_point =
163 GetRadialPoint(kRadius + kCushion, deg, kCentreX, kCentreY);
164 EXPECT_TRUE([result containsPoint:inside_point]);
165 EXPECT_FALSE([result containsPoint:outside_point]);
166 }
167
168 // Check that the returned result has the correct bounding box. GetBoundingBox
169 // rounds the coordinates to nearest integer values.
170 EXPECT_EQ(expected_bounds, GetBoundingBox(result));
171
172 // Check area of converted path is correct upto a certain tolerance value. To
msw 2016/02/11 23:57:38 nit: "up to"
karandeepb 2016/02/12 03:45:52 Done.
173 // find the area of the NSBezierPath returned, flatten it i.e. convert it to a
174 // polygon.
175 [NSBezierPath setDefaultFlatness:0.01];
176 NSBezierPath* polygon = [result bezierPathByFlatteningPath];
msw 2016/02/11 23:57:38 nit: delete this object at some point or use base:
karandeepb 2016/02/12 03:45:51 It is autoreleased when it is no longer in scope(a
177 const double kTolerance = 0.14;
178 EXPECT_NEAR(CalculateCircleArea(kRadius), CalculatePolygonArea(polygon),
179 kTolerance);
180 }
181
182 // Test that an SKPath containing a rounded rectangle is converted correctly to
183 // a NSBezierPath.
184 TEST(CreateNSBezierPathFromSkPathTest, RoundedRectanglePath) {
185 const int kRectangleWidth = 50;
186 const int kRectangleHeight = 100;
187 const int kCornerRadius = 5;
188 const double kCushion = 0.1;
189 // Expected bounding box of the rounded rectangle.
190 const gfx::Rect expected_bounds(kRectangleWidth, kRectangleHeight);
msw 2016/02/11 23:57:38 nit: 'gfx::' not needed
karandeepb 2016/02/12 03:45:52 Done.
191
192 SkRRect rrect;
193 rrect.setRectXY(SkRect::MakeWH(kRectangleWidth, kRectangleHeight),
194 kCornerRadius, kCornerRadius);
195
196 const NSPoint inside_points[] = {
197 // Bottom left corner.
198 {kCornerRadius / 2.0, kCornerRadius / 2.0},
199 // Bottom right corner.
200 {kRectangleWidth - kCornerRadius / 2.0, kCornerRadius / 2.0},
201 // Top Right corner.
202 {kRectangleWidth - kCornerRadius / 2.0,
203 kRectangleHeight - kCornerRadius / 2.0},
204 // Top left corner.
205 {kCornerRadius / 2.0, kRectangleHeight - kCornerRadius / 2.0},
206 // Bottom middle.
207 {kRectangleWidth / 2.0, kCushion},
208 // Right middle.
209 {kRectangleWidth - kCushion, kRectangleHeight / 2.0},
210 // Top middle.
211 {kRectangleWidth / 2.0, kRectangleHeight - kCushion},
212 // Left middle.
213 {kCushion, kRectangleHeight / 2.0}};
214 const NSPoint outside_points[] = {
msw 2016/02/11 23:57:38 EXPECT/ASSERT_EQ(arraysize(inside_points), arraysi
karandeepb 2016/02/12 03:45:52 Done.
215 // Bottom left corner.
216 {0, 0},
217 // Bottom right corner.
218 {kRectangleWidth, 0},
219 // Top right corner.
220 {kRectangleWidth, kRectangleHeight},
221 // Top left corner.
222 {0, kRectangleHeight},
223 // Bottom middle.
224 {kRectangleWidth / 2.0, -kCushion},
225 // Right middle.
226 {kRectangleWidth + kCushion, kRectangleHeight / 2.0},
227 // Top middle.
228 {kRectangleWidth / 2.0, kRectangleHeight + kCushion},
229 // Left middle.
230 {-kCushion, kRectangleHeight / 2.0}};
231 const size_t kNumPoints = arraysize(inside_points);
232
233 SkPath path;
234 path.addRRect(rrect);
235 NSBezierPath* result = CreateNSBezierPathFromSkPath(path);
236
237 // Check points near the boundary of the path and verify that they are
238 // reported correctly as being inside/outside the path.
239 for (size_t i = 0; i < kNumPoints; i++) {
240 EXPECT_TRUE([result containsPoint:inside_points[i]]);
241 EXPECT_FALSE([result containsPoint:outside_points[i]]);
242 }
243
244 // Check that the returned result has the correct bounding box. GetBoundingBox
245 // rounds the coordinates to nearest integer values.
246 EXPECT_EQ(expected_bounds, GetBoundingBox(result));
247
248 // Check area of converted path is correct upto a certain tolerance value. To
msw 2016/02/11 23:57:38 nit: "up to"
karandeepb 2016/02/12 03:45:51 Done.
249 // find the area of the NSBezierPath returned, flatten it i.e. convert it to a
250 // polygon.
251 [NSBezierPath setDefaultFlatness:0.01];
252 NSBezierPath* polygon = [result bezierPathByFlatteningPath];
253 const double kTolerance = 0.14;
254 EXPECT_NEAR(CalculateRoundedRectangleArea(kRectangleWidth, kRectangleHeight,
255 kCornerRadius),
256 CalculatePolygonArea(polygon), kTolerance);
257 }
258
259 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698