OLD | NEW |
---|---|
(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" | |
msw
2016/02/11 23:57:37
I'm not the most capable reviewer here, but I thin
| |
6 | |
7 #import <Cocoa/Cocoa.h> | |
8 | |
9 #include "third_party/skia/include/core/SkRegion.h" | |
10 #include "ui/gfx/path.h" | |
11 | |
12 namespace { | |
13 | |
14 // Convert a quadratic bezier curve to a cubic bezier curve. Based on the | |
15 // implementation of the private SkConvertQuadToCubic method inside Skia. | |
msw
2016/02/11 23:57:37
q: Can/should we expose SkConvertQuadToCubic inste
karandeepb
2016/02/12 03:45:51
Tried doing this - https://codereview.chromium.org
msw
2016/02/12 19:26:55
Acknowledged.
| |
16 void ConvertQuadToCubicBezier(NSPoint quad[3], NSPoint cubic[4]) { | |
17 // The resultant cubic will have the same endpoints. | |
18 cubic[0] = quad[0]; | |
19 cubic[3] = quad[2]; | |
20 | |
21 const double scale = 2.0 / 3.0; | |
22 | |
23 cubic[1].x = quad[0].x + scale * (quad[1].x - quad[0].x); | |
24 cubic[1].y = quad[0].y + scale * (quad[1].y - quad[0].y); | |
25 | |
26 cubic[2].x = quad[2].x + scale * (quad[1].x - quad[2].x); | |
27 cubic[2].y = quad[2].y + scale * (quad[1].y - quad[2].y); | |
28 } | |
29 | |
30 } // namespace | |
31 | |
32 namespace gfx { | |
33 | |
34 NSBezierPath* CreateNSBezierPathFromSkPath(const SkPath& path) { | |
35 NSBezierPath* result = [NSBezierPath bezierPath]; | |
36 SkPath::RawIter iter(path); | |
37 SkPoint sk_points[4] = {{0.0}}; | |
38 SkPath::Verb verb; | |
39 while ((verb = iter.next(sk_points)) != SkPath::kDone_Verb) { | |
40 NSPoint points[4]; | |
msw
2016/02/11 23:57:37
nit: declare outside loop?
karandeepb
2016/02/12 03:45:51
Done.
| |
41 for (size_t i = 0; i < 4; i++) | |
msw
2016/02/11 23:57:37
nit: maybe use arraysize(points)?
karandeepb
2016/02/12 03:45:51
Done.
| |
42 points[i] = NSMakePoint(sk_points[i].x(), sk_points[i].y()); | |
43 | |
44 switch (verb) { | |
45 case SkPath::kMove_Verb: { | |
46 [result moveToPoint:points[0]]; | |
47 break; | |
48 } | |
49 case SkPath::kLine_Verb: { | |
50 DCHECK(NSEqualPoints([result currentPoint], points[0])); | |
51 [result lineToPoint:points[1]]; | |
52 break; | |
53 } | |
54 case SkPath::kQuad_Verb: { | |
55 DCHECK(NSEqualPoints([result currentPoint], points[0])); | |
56 NSPoint quad[] = {points[0], points[1], points[2]}; | |
57 // NSBezierPath does not support quadratic bezier curves. Hence convert | |
58 // to cubic bezier curve. | |
59 ConvertQuadToCubicBezier(quad, points); | |
60 [result curveToPoint:points[3] | |
61 controlPoint1:points[1] | |
62 controlPoint2:points[2]]; | |
63 break; | |
64 } | |
65 case SkPath::kCubic_Verb: { | |
66 DCHECK(NSEqualPoints([result currentPoint], points[0])); | |
67 [result curveToPoint:points[3] | |
68 controlPoint1:points[1] | |
69 controlPoint2:points[2]]; | |
70 break; | |
71 } | |
72 case SkPath::kConic_Verb: { | |
msw
2016/02/11 23:57:37
nit: match decl order (move above cubic, after qua
karandeepb
2016/02/12 03:45:51
Done.
| |
73 DCHECK(NSEqualPoints([result currentPoint], points[0])); | |
74 // Approximate with quads. Use two for now, increase if more precision | |
75 // is needed. | |
76 const size_t kSubdivisionLevels = 1; | |
77 const size_t kQuadCount = 1 << kSubdivisionLevels; | |
78 // The quads will share endpoints, so we need one more point than twice | |
79 // the number of quads. | |
80 const size_t kPointCount = 1 + 2 * kQuadCount; | |
81 SkPoint quads[kPointCount]; | |
82 SkPath::ConvertConicToQuads(sk_points[0], sk_points[1], sk_points[2], | |
83 iter.conicWeight(), quads, | |
84 kSubdivisionLevels); | |
85 NSPoint ns_quads[kPointCount]; | |
86 for (size_t i = 0; i < kPointCount; i++) | |
87 ns_quads[i] = NSMakePoint(quads[i].x(), quads[i].y()); | |
88 | |
89 for (size_t i = 0; i < kQuadCount; i++) { | |
90 NSPoint quad[] = {ns_quads[2 * i], ns_quads[2 * i + 1], | |
91 ns_quads[2 * i + 2]}; | |
92 ConvertQuadToCubicBezier(quad, points); | |
msw
2016/02/11 23:57:37
nit: DCHECK(NSEqualPoints([result currentPoint], p
karandeepb
2016/02/12 03:45:51
Done.
| |
93 [result curveToPoint:points[3] | |
94 controlPoint1:points[1] | |
95 controlPoint2:points[2]]; | |
96 } | |
97 break; | |
98 } | |
99 case SkPath::kClose_Verb: { | |
msw
2016/02/11 23:57:37
Should this use (or at least check) the returned "
karandeepb
2016/02/12 03:45:51
I don't think that the Skia behaviour here is as p
msw
2016/02/12 19:26:55
Acknowledged.
| |
100 [result closePath]; | |
101 break; | |
102 } | |
103 default: { NOTREACHED(); } | |
104 } | |
105 } | |
106 | |
107 // Set up the fill type. | |
108 switch (path.getFillType()) { | |
109 case SkPath::kWinding_FillType: | |
110 [result setWindingRule:NSNonZeroWindingRule]; | |
111 break; | |
112 case SkPath::kEvenOdd_FillType: | |
113 [result setWindingRule:NSEvenOddWindingRule]; | |
114 break; | |
115 case SkPath::kInverseWinding_FillType: | |
116 case SkPath::kInverseEvenOdd_FillType: | |
117 NOTREACHED() << "NSBezierCurve does not support inverse fill types."; | |
118 break; | |
119 default: | |
msw
2016/02/11 23:57:37
nit: I think you can omit default to get compile e
karandeepb
2016/02/12 03:45:51
Done.
| |
120 NOTREACHED(); | |
121 } | |
122 | |
123 return result; | |
124 } | |
125 | |
126 } // namespace gfx | |
OLD | NEW |