9

What I want is to take a filled rectangle and punch a hole in it using another shape. This is exactly the kind of thing that NSBezierPath is designed for. You add a rectangular path, then add the subpath that will "punch" through it and finally fill it. In my case the subpath is actually text. No problem, works great:

alt text

Except when I use Helvetica Neue Bold for my font. When I use that, I just end up with a solid blue rectangle without any text at all. But the subpath is indeed drawing--in fact, if I shrink the filled rectangle a bit, you can actually see some of the text path:

alt text

I get the same behavior with Helvetica Neue Italic. Helvetica Neue Medium works fine, as does Helvetica Bold, Times New Roman Bold and Arial Bold.

I've tried using both NSEvenOddWindingRule and NSNonZeroWindingRule. (EDIT: Apparently I didn't really try NSEvenOddWinding rule, because that does turn out to work after all)

This is the code that I'm using 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's 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 NSEvenOddWindingRule. After the creation of path add this line:

[path setWindingRule:NSEvenOddWindingRule];

Peter Hosey's answer provides the explanation of why this is.

4

1 回答 1

4

这可能与字体中路径的方向有关。一种字体可以使用顺时针路径;另一个可能使用逆时针路径。

实现所需效果的更可靠方法是简单地填充矩形,然后在图形上下文的合成模式设置为NSCompositeSourceOut. 如果您只想从填充中剪切文本,您可以使用 Core Graphics 将填充和文本绘制包裹在透明层中。

于 2011-01-20T16:12:28.427 回答