Search code examples
iosmacosquartz-2dcgcontext

Quartz2D: How to convert a clipping rect to an inverted mask at runtime?


Given:

  1. a CGContextRef (ctx) with frame {0,0,100,100}
  2. and a rect (r), with frame {25,25,50,50}

It's easy to clip the context to that rect:

CGContextClipToRect(ctx, r);

to mask out the red area below (red == mask):

enter image description here

But I want to invert this clipping rect to convert it into a clipping mask. The desired outcome is to mask the red portion below (red == mask):

enter image description here

I want to do this programmatically at runtime.

I do not want to manually prepare a bitmap image to ship statically with my app.

Given ctx and r, how can this be done at runtime most easily/straightforwardly?


Solution

  • Read about fill rules in the “Filling a Path” section of the Quartz 2D Programming Guide.

    In your case, the easiest thing to do is use the even-odd fill rule. Create a path consisting of your small rectangle, and a much larger rectangle:

    CGContextBeginPath(ctx);
    CGContextAddRect(ctx, CGRectMake(25,25,50,50));
    CGContextAddRect(ctx, CGRectInfinite);
    

    Then, intersect this path into the clipping path using the even-odd fill rule:

    CGContextEOClip(ctx);