1

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.

fatihyildizhan
8,8207 gold badges68 silver badges92 bronze badges
asked Jan 4, 2023 at 19:25
5
  • 4
    Your code doesn't do any actual drawing. There are no calls to drawPath, fillPath, or strokePath, or any other calls that actually modify pixels. You need to show us more code. Commented Jan 4, 2023 at 19:59
  • For my use case I don't need to. I am passing a CGPath into this function and getting the stroked path as a CGPath. (see updated code) Commented Jan 5, 2023 at 8:54
  • Please add the code that actually draws the stroked path. Commented Jan 5, 2023 at 9:18
  • Drawing the path in swiftUI using Path(getPreviewPath(path:input, strokeWidth: 20)) Commented Jan 5, 2023 at 9:29
  • Since this is obviously about SwiftUI, why don't you use the stroke method of SwiftUI's Path class? See developer.apple.com/documentation/swiftui/path/stroke(style:) Also note that your current code creates path the includes both the stroked and non-stroked path. Commented Jan 5, 2023 at 10:21

1 Answer 1

0

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:

Screenshot path stroking

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)
 }
}
answered Jan 5, 2023 at 18:47
Sign up to request clarification or add additional context in comments.

4 Comments

Did try this earlier. It works well with paths with no fill(unclosed paths). The issue I ran into with this is that, when getting the stroked 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.
I don't understand what you are actually trying to achieve and why you want to use 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.
I still don't understand why you need to do it this particular way. Obviously, you are not willing to share what you are actually trying to achieve. But making another shot guessing what might help you, I've added additional code that first creates a path containing a stroked path.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.