Search code examples
iosswiftcore-graphicsquartz-2d

Core Graphics Clipping


I am trying to understand clipping in IOS Core Graphics but i cant figure out some strange behaviour.

What i want to do is to clip out a small triangle. I made a child view from UIView and i override the draw(_ rect) function.

With this code i draw the triangle:

    let con = UIGraphicsGetCurrentContext()!

    con.setFillColor(UIColor.red.cgColor)
    con.move(to: CGPoint(x: rect.midX - 10, y: rect.maxY - 10))
    con.addLine(to: CGPoint(x: rect.midX, y: rect.maxY - 20 ))
    con.addLine(to: CGPoint(x: rect.midX + 10, y: rect.maxY - 10 ))
    con.closePath()

After that i took the path's surrounding rectangle and i clipped the triangle:

    con.addRect(con.boundingBoxOfPath)
    con.clip(using: .evenOdd)

Now if i try to fill the path nothing appears. Moreover if i try to add to the current path the whole subview rectangle and fill it with the red color i would expect the whole area to be red except the triangle but the result is this:

enter image description here

I cant draw anywhere else!

Any ideas?


Solution

  • The bug in your code is: con.addRect(con.boundingBoxOfPath). The rectangle boundingBoxOfPath is not relevant to this task. If you want to be able to draw anywhere in the view except for the triangle, you need to add the full view rectangle to your clipping path. In other words, change that line to: con.addRect(rect)

    The following code worked for me:

    guard let ctx = UIGraphicsGetCurrentContext() else { return }
    
    ctx.beginPath()
    ctx.move(to: CGPoint(x: rect.midX - 10, y: rect.midY - 10))
    ctx.addLine(to: CGPoint(x: rect.midX, y: rect.midY - 20 ))
    ctx.addLine(to: CGPoint(x: rect.midX + 10, y: rect.midY - 10 ))
    ctx.closePath()
    
    ctx.addRect(rect)
    ctx.clip(using: .evenOdd)
    
    // Test filling the view (except triangle) with red:
    ctx.setFillColor(UIColor.red.cgColor)
    ctx.fill(rect)