I want to apply a CIFilter
to a CALayer
except for an area which is an union of rectangles.
I post my not working code, it does exactly the opposite, i.e. the filter is applied only in the rectangles and not outside!
func refreshTheFrameWithEffect() {
self.layer!.masksToBounds = true
self.layerUsesCoreImageFilters = true
self.layer!.needsDisplayOnBoundsChange = true
let filter = CIFilter(name: "CICircleSplashDistortion")
filter!.setDefaults()
self.layer!.backgroundFilters = [filter!]
var excludedRects: [CGRect] = [] //INITIALISE THEM HOW YOU PREFER
let maskLayer = CAShapeLayer()
maskLayer.frame = self.bounds
self.layer!.fillMode = kCAFillRuleEvenOdd
var maskPath = NSBezierPath()
for rect in excludedRects {
maskPath.append(NSBezierPath(rect: rect))
}
maskLayer.path = maskPath.CGPath
self.layer!.mask = maskLayer
self.layer!.needsDisplay()
}
and then the following code from the Internet since NSBezierPath does not have the attribute CGPath, unlike UIBezierPath.
public var CGPath: CGPath {
let path = CGMutablePath()
var points = [CGPoint](repeating: .zero, count: 3)
for i in 0 ..< self.elementCount {
let type = self.element(at: i, associatedPoints: &points)
switch type {
case .moveToBezierPathElement: path.move(to: CGPoint(x: points[0].x, y: points[0].y) )
case .lineToBezierPathElement: path.addLine(to: CGPoint(x: points[0].x, y: points[0].y) )
case .curveToBezierPathElement: path.addCurve( to: CGPoint(x: points[2].x, y: points[2].y),
control1: CGPoint(x: points[0].x, y: points[0].y),
control2: CGPoint(x: points[1].x, y: points[1].y) )
case .closePathBezierPathElement: path.closeSubpath()
}
}
return path
}