CGContextClip() using an inverted path

cocoa, macos, macos-carbon, quartz-graphics

Solution

You could add your entire bounds as a rectangle, then add the rectangles you want to exclude from drawing and use `CGContextEOClip`.

Example:

- (void)drawRect:(NSRect)dirtyRect
    CGContextRef ctx = [[NSGraphicsContext currentContext] graphicsPort];
    //Fill the background with gray:
    CGContextSetRGBFillColor(ctx, 0.5, 0.5, 0.5, 1);
    CGContextFillRect(ctx, NSRectToCGRect(self.bounds));
    CGContextAddRect(ctx, NSRectToCGRect(self.bounds));
    //Add some rectangles:
    CGContextAddRect(ctx, CGRectMake(10, 10, 100, 100));
    CGContextAddRect(ctx, CGRectMake(120, 120, 50, 100));
    //Clip:
    CGContextEOClip(ctx);
    //Fill the entire bounds with red:
    CGContextSetRGBFillColor(ctx, 1.0, 0.0, 0.0, 1.0);
    CGContextFillRect(ctx, NSRectToCGRect(self.bounds));
}

The effect becomes more obvious if you draw an image at the end instead of filling a red rectangle.

Problem

I want to have clipped drawing on my `CGContext` but I need it just the other way round, i.e. I want to add several rectangles to my clipping path using `CGContextAddRect()` and the clipping should be done in the way that all the rectangles that I have added to my clipping path stay unaffected by any drawing operations. Normally, it's just the other way round, i.e. drawing functions draw to the rectangles that have been added to the clipping path and leave the areas that haven't been added to the clipping path unaffected. So I guess what I need is just a way to reverse the clipping path before calling `CGContextClip()`. Back in the QuickDraw days, this could by easily done by using regions and then calling `XorRgn()` for every rectangle. But with Quartz it seems to be more complicated. Does anyone have an easy solution for achieving this or do I need to do all these path reversing calculations on my own?

Original source