For clipping tasks like this, NSBezierPath is a very poor cousin to Apple's old technology for this - Regions. With regions one could trivially obtain union, intersection, difference and xor of complex shapes using the built-in APIs. Neither NSBezierPath nor the underlying Quartz routines it calls upon have the equivalent operations. OK, Regions were intrinsically pixel-oriented (scanline) entities and maybe it's just too hard to offer this sort of thing generically with bezier paths, but I for one feel this is a glaring hole in the functionality of Quartz (and, since the rasterizing code *already* has to search for self-intersections and so on, in fact the private code must be very close to having an implementation of this right there - they just need to clean it up, flesh it out and make a public API for it).

For the case of excluding an area from the clip region you can eventually force it to do the job by combinations of winding rules, path reversals and appends, but for other graphics work these are a very blunt instrument. The "append" terminology is the only one NSBezierPath has because that's all it can do - append more paths. It cannot subtract ("remove") one path from another. If the paths intersect you can get an xor or a union effect depending on the winding rule, but never a subtraction. It's a royal PITA.

Here's one method I have in a category on NSBezierPath that *might* address the clipping situation that you have. However, since there's no public method to GET the current context's clip path, this works using the bounding box of that path instead, which may not be applicable in every case. Once again, I know there's a private API for this but for some inexplicable reason, Apple do not expose it in the public headers, even though without it this sort of thing is downright awkward, yet commonly required.

- (void)        addInverseClip
{
// this is similar to -addClip, except that it excludes the area bounded by the path instead of includes it. It works by combining this path // with the existing clip area using the E/O winding rule, then setting the result as the clip area. This should be called between
        // calls to save and restore the gstate, as for addClip.
        
CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
        CGRect cbbox = CGContextGetClipBoundingBox( context );
        
        NSBezierPath*   cp = [NSBezierPath bezierPathWithRect:*(NSRect*)&cbbox];
        [cp appendBezierPath:self];
        [cp setWindingRule:NSEvenOddWindingRule];
        [cp setClip];
}


G.

On 19 May 2008, at 3:03 pm, Peter Duniho wrote:

As an example, I found myself wanting to exclude an area from my clipping region. Nothing complicated: I had a rectangular area, and I wanted to draw everywhere _except_ a specific sub-rectangle. The docs were quite prideful as to how, since Cocoa clipping uses the NSBezierPath, you have practically infinite control over clipped. No doubt this boasting was reasonably accurate (*). And yet, even as it hints tantalizingly at the idea that there's a way to do this (see "Modifying the Current Graphics State"), it doesn't quite get you there.


I was finally able to, after reading documentation in three different places that discuss NSBezierPath, connect the dots so to speak and figure out how the heck to get NSBezierPath to do what the docs hinted it could do.

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [EMAIL PROTECTED]

Reply via email to