Chromium Code Reviews| 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" | |
| 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 an SkPoint to an NSPoint. | |
| 15 NSPoint GetNSPointFromSkPoint(const SkPoint& point) { | |
| 16 return NSMakePoint(point.x(), point.y()); | |
| 17 } | |
| 18 | |
| 19 // Convert a quadratic bezier curve to a cubic bezier curve. | |
|
tapted
2016/02/10 02:28:02
nit: mention that this is based on the implementat
karandeepb
2016/02/11 00:30:09
Done.
| |
| 20 void ConvertQuadToCubicBezier(NSPoint quad[3], NSPoint cubic[4]) { | |
| 21 // The resultant cubic will have the same endpoints. | |
| 22 cubic[0] = quad[0]; | |
| 23 cubic[3] = quad[2]; | |
| 24 | |
| 25 const double scale = 2.0 / 3.0; | |
| 26 | |
| 27 cubic[1].x = quad[0].x + scale * (quad[1].x - quad[0].x); | |
| 28 cubic[1].y = quad[0].y + scale * (quad[1].y - quad[0].y); | |
| 29 | |
| 30 cubic[2].x = quad[2].x + scale * (quad[1].x - quad[2].x); | |
| 31 cubic[2].y = quad[2].y + scale * (quad[1].y - quad[2].y); | |
| 32 } | |
| 33 | |
| 34 } // namespace | |
| 35 | |
| 36 namespace gfx { | |
| 37 | |
| 38 NSBezierPath* CreateNSBezierPathFromSkRegion(const SkRegion& region) { | |
| 39 NSBezierPath* result = [NSBezierPath bezierPath]; | |
| 40 for (SkRegion::Iterator i(region); !i.done(); i.next()) { | |
| 41 const SkIRect& rect = i.rect(); | |
| 42 [result appendBezierPathWithRect:NSMakeRect(rect.x(), rect.y(), | |
| 43 rect.width(), rect.height())]; | |
| 44 } | |
| 45 return result; | |
| 46 } | |
| 47 | |
| 48 NSBezierPath* CreateNSBezierPathFromSkPath(const SkPath& path) { | |
| 49 NSBezierPath* result = [NSBezierPath bezierPath]; | |
| 50 SkPath::RawIter iter(path); | |
| 51 SkPoint points[4]; | |
| 52 SkPath::Verb verb; | |
| 53 while ((verb = iter.next(points)) != SkPath::kDone_Verb) { | |
| 54 NSPoint ns_points[4]; | |
| 55 for (size_t i = 0; i < 4; i++) | |
| 56 ns_points[i] = GetNSPointFromSkPoint(points[i]); | |
|
tapted
2016/02/10 02:28:01
I think this can read from uninitialized memory in
karandeepb
2016/02/11 00:30:09
Done.
| |
| 57 | |
| 58 switch (verb) { | |
| 59 case SkPath::kMove_Verb: { | |
| 60 [result moveToPoint:ns_points[0]]; | |
| 61 break; | |
| 62 } | |
| 63 case SkPath::kLine_Verb: { | |
| 64 DCHECK(NSEqualPoints([result currentPoint], ns_points[0])); | |
| 65 [result lineToPoint:ns_points[1]]; | |
| 66 break; | |
| 67 } | |
| 68 case SkPath::kQuad_Verb: { | |
| 69 DCHECK(NSEqualPoints([result currentPoint], ns_points[0])); | |
| 70 NSPoint quad[] = {ns_points[0], ns_points[1], ns_points[2]}; | |
| 71 // NSBezierPath does not support quadratic bezier curves. Hence convert | |
| 72 // to cubic bezier curve. | |
| 73 ConvertQuadToCubicBezier(quad, ns_points); | |
| 74 [result curveToPoint:ns_points[3] | |
| 75 controlPoint1:ns_points[1] | |
| 76 controlPoint2:ns_points[2]]; | |
| 77 break; | |
| 78 } | |
| 79 case SkPath::kCubic_Verb: { | |
| 80 DCHECK(NSEqualPoints([result currentPoint], ns_points[0])); | |
| 81 [result curveToPoint:ns_points[3] | |
| 82 controlPoint1:ns_points[1] | |
| 83 controlPoint2:ns_points[2]]; | |
| 84 break; | |
| 85 } | |
| 86 case SkPath::kConic_Verb: { | |
| 87 DCHECK(NSEqualPoints([result currentPoint], ns_points[0])); | |
| 88 // Approximate with quads. Use two for now, increase if more precision | |
| 89 // is needed. | |
| 90 const size_t kSubdivisionLevels = 1; | |
| 91 const size_t kQuadCount = 1 << kSubdivisionLevels; | |
| 92 // The quads will share endpoints, so we need one more point than twice | |
| 93 // the number of quads. | |
| 94 const size_t kPointCount = 1 + 2 * kQuadCount; | |
| 95 SkPoint quads[kPointCount]; | |
| 96 SkPath::ConvertConicToQuads(points[0], points[1], points[2], | |
| 97 iter.conicWeight(), quads, | |
| 98 kSubdivisionLevels); | |
| 99 NSPoint ns_quads[kPointCount]; | |
| 100 for (size_t i = 0; i < kPointCount; i++) | |
| 101 ns_quads[i] = GetNSPointFromSkPoint(quads[i]); | |
| 102 | |
| 103 for (size_t i = 0; i < kQuadCount; i++) { | |
| 104 NSPoint quad[] = {ns_quads[2 * i], ns_quads[2 * i + 1], | |
| 105 ns_quads[2 * i + 2]}; | |
| 106 ConvertQuadToCubicBezier(quad, ns_points); | |
| 107 [result curveToPoint:ns_points[3] | |
| 108 controlPoint1:ns_points[1] | |
| 109 controlPoint2:ns_points[2]]; | |
| 110 } | |
| 111 break; | |
| 112 } | |
| 113 case SkPath::kClose_Verb: { | |
| 114 [result closePath]; | |
| 115 break; | |
| 116 } | |
| 117 default: { NOTREACHED(); } | |
| 118 } | |
| 119 } | |
| 120 | |
| 121 // Set up the fill type. | |
| 122 switch (path.getFillType()) { | |
| 123 case SkPath::kWinding_FillType: | |
| 124 [result setWindingRule:NSNonZeroWindingRule]; | |
| 125 break; | |
| 126 case SkPath::kEvenOdd_FillType: | |
| 127 [result setWindingRule:NSEvenOddWindingRule]; | |
| 128 break; | |
| 129 case SkPath::kInverseWinding_FillType: | |
| 130 case SkPath::kInverseEvenOdd_FillType: | |
| 131 NOTREACHED() << "NSBezierCurve does not support inverse fill types."; | |
| 132 break; | |
| 133 default: | |
| 134 NOTREACHED(); | |
| 135 } | |
| 136 | |
| 137 return result; | |
| 138 } | |
| 139 | |
| 140 } // namespace gfx | |
| OLD | NEW |