I want to take a filled rectangle and punch a hole in it using a different shape. This is exactly the thing NSBezierPath . You add a rectangular path, then add a sub-item that βpunchesβ it and finally fills it. In my case, the subpath is actually text. No problem, it works fine:

Except when I use Helvetica Neue Bold for my font. When I use this, I just get a solid blue rectangle without any text. But the subpath is really drawn - in fact, if I cut the filled rectangle a bit, you can see some text path:

I get the same behavior with Helvetica Neue Italic. Helvetica Neue Medium works great, like Helvetica Bold, Times New Roman Bold and Arial Bold.
I tried using both NSEvenOddWindingRule and NSNonZeroWindingRule . ( EDIT : Apparently, I really did not try to use the NSEvenOddWinding rule, because it works anyway)
This is the code that I use inside the drawRect method of my NSView subclass.
NSLayoutManager *layoutManger = [[[NSLayoutManager alloc] init] autorelease]; NSTextContainer *textContainer = [[[NSTextContainer alloc] initWithContainerSize:NSMakeSize(300, 100)] autorelease]; NSFont *font = [NSFont fontWithName:@"Helvetica Neue Bold" size:100]; NSDictionary *textAttribs = [NSDictionary dictionaryWithObjectsAndKeys: font, NSFontAttributeName, nil]; NSTextStorage *textStorage = [[[NSTextStorage alloc] initWithString:@"Hello" attributes:textAttribs] autorelease]; [layoutManger addTextContainer:textContainer]; [layoutManger setTextStorage:textStorage]; NSRange glyphRange = [layoutManger glyphRangeForTextContainer:textContainer]; NSGlyph glyphArray[glyphRange.length]; NSUInteger glyphCount = [layoutManger getGlyphs:glyphArray range:glyphRange]; NSBezierPath *path = [NSBezierPath bezierPathWithRect:NSMakeRect(0, 0, 200, 100)]; [path appendBezierPathWithGlyphs:glyphArray count:glyphCount inFont:font]; [[NSColor blueColor] setFill]; [path fill];
So what is going on here? Why do some fonts behave differently than others when it comes to adding glyphs to a path?
EDIT . The solution is to use an NSEvenOddWindingRule . After creating the path add this line:
[path setWindingRule:NSEvenOddWindingRule]
Peter Hawsey's answer provides an explanation of why this is so.
objective-c fonts cocoa core-graphics typography
Ben dolman
source share