Clipping the current context so that it's masked by a path

core-graphics, ios, objective-c, quartz-graphics

Solution

I might be inclined to build a path as touches come in (I use `UIBezierPath`), and then your custom view can use that path for both clipping the image, as well as for stroking the path around that clipped image:

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSaveGState(context);

    if (self.isClipped) {
        CGContextAddPath(context, [self.path CGPath]);
        CGContextClip(context);
    }

    [self.image drawInRect:self.bounds];

    CGContextRestoreGState(context);

    [[UIColor blackColor] setStroke];
    self.path.lineWidth = 4.0;
    [self.path stroke];
}

If you want to draw the path as touches come in, I personally would render that via a separate `CAShapeLayer` (to avoid the unnecessary redrawing of the image).

Problem

Given a path which is drawn to the context and then converted to a CGImageRef, how would I clip the context (which has a supplied foreground image drawn) to it so that the said context is masked by the CGImage (that previously was a path)? The code in question below should better illustrate my point if it's not totally clear. Note that all of this is called in a UIView's drawRect: method and that the scaledImageRectangle(UIImage *image, CGRect rect) function merely returns a rectangle. ``` // Close the path CGContextClosePath(context); CGContextDrawPath(context, kCGPathFillStroke); // Mask the image CGImageRef mask = CGBitmapContextCreateImage(context); [foregroundImage drawInRect:scaledImageRectangle(foregroundImage, rect)]; CGContextClipToMask(context, scaledImageRectangle(foregroundImage, rect), mask); // Finally draw the masked image UIImage *maskedImage = [UIImage imageWithCGImage:CGBitmapContextCreateImage(context)]; [maskedImage drawInRect:scaledImageRectangle(foregroundImage, rect)]; ``` For example, here is an image with the black stroke representing the path And here is what the image would look like when masked

Original source