views:

266

answers:

1

I'm trying to produce a clipping area in a UIView that's generated from path objects in its subviews. For example, I might have one subview containing a square and another containing a circle. I want to be able to produce a clip in the parent superview that's the union of both these shapes. Can someone explain how to do this? About all I've been able to figure out so far is that:

1 - the superview's drawRect: method is called before its subviews' drawRects are, and
2 - the ContextRef that's accessible in all three instances is the same.

Other than that I'm stumped. Thanks,
Howard

+1  A: 

In a nutshell, you have to iterate through all the subviews and let each one modify the current context path, then set that path as the clipping path. You could ask for a path from each view or pass the context to each view.

CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState( context );
CGContextBeginPath( context );

for ( view in subviews ) {
  if ( [view respondsToSelector:@selector(pathTranslatedForView:)] ) {
    CGContextAddPath( context , [(MyCustomViewPath *)view pathTranslatedForView:self] );
  }
}

CGContextClip( context );
// do stuff with clipping path
CGContextRestoreGState( context );

Edit:

When calling the subview, you may want to adjust the context so that 0,0 is the origin of the called view, not the superview:

CGRect frame = [view frame];
CGContextTranslateCTM( context , -frame.origin.x , -frame.origin.y );
CGContextAddPath( context , [(MyCustomViewPath *)view path]; 
CGContextTranslateCTM( context , frame.origin.x , frame.origin.y );
drawnonward
Ah, I almost have it I think. I'm presuming that one of the main tasks of each subview's pathTranslatedForView: method is to adjust the path's coordinates to account for the subview's offset relative to its superview, but what's the easiest way of doing that? Setting a translation transform before constructing the path?
hkatz
It mostly depends on the particulars of your implementation. Are you keeping an actual CGPathRef in your views, or the location of a circle and square? Many CGPath operations accept a transform, so each class could build a transform for itself. Or the superview could apply a transform to the context before calling each subview.
drawnonward