I'm trying to add a stroke to `CGPath` in a macOS app with the code below. The issue is that the stroked path can't be filled properly. With the current method, I'm adding the original path on top of the stroked path. This causes the overlapping parts to remain unfilled.
func getPreviewPath(path:CGPath, strokeWidth: CGFloat) ->CGPath{
let window = NSWindow()
let context = NSGraphicsContext(window: window).cgContext
context.setLineCap(CGLineCap(rawValue: 0)!)
context.setLineWidth(strokeWidth)
context.setLineJoin(.bevel)
context.addPath(path)
context.replacePathWithStrokedPath()
context.addPath(path)
return context.path!
}
I've read that this is caused by the even-odd fill rule. But there doesn't seem to be a way to change this.
1 Answer 1
Here's a minimal example using the stroke() method:
struct ContentView: View {
var body: some View {
Path { path in
path.move(to: CGPoint(x: 20, y: 20))
path.addLine(to: CGPoint(x: 50, y: 100))
path.addLine(to: CGPoint(x: 80, y: 20))
path.addLine(to: CGPoint(x: 120, y: 20))
}
.stroke(style: StrokeStyle(lineWidth: 12.0, lineCap: .round, lineJoin: .bevel))
.padding()
}
}
And this is the result:
Update
Her is a slightly more complex example. It first creates a path containing a stroked path. This path is then filled. The result is the same.
struct ContentView: View {
var body: some View {
Path(createPath())
.fill(.black)
.padding()
}
func createPath() -> CGPath {
let path = CGMutablePath()
path.move(to: CGPoint(x: 20, y: 20))
path.addLine(to: CGPoint(x: 50, y: 100))
path.addLine(to: CGPoint(x: 80, y: 20))
path.addLine(to: CGPoint(x: 120, y: 20))
return path.copy(strokingWithWidth: 12.0, lineCap: .round, lineJoin: .bevel, miterLimit: 10)
}
}
4 Comments
CGPath from strokedPath.cgPath closed paths are unfilled. When trying to fill back the paths I run into the same issues as described in the initial question.strokedPath instead of directly stroking the path. You might want to add a description of the context and a minimal reproducible example.strokedPath here is Path in your answer as a variable. Ultimately I need a stroked path as a CGPath.
drawPath,fillPath, orstrokePath, or any other calls that actually modify pixels. You need to show us more code.CGPathinto this function and getting the stroked path as aCGPath. (see updated code)Path(getPreviewPath(path:input, strokeWidth: 20))