Question

When using non-standard fonts in Cocoa, they are sometimes misplaced compared to standard system fonts. I've created a sample OS X Cocoa Application which illustrates the issue: http://www.fileconvoy.com/dfl.php?id=g2bff79a0dcf64cc4999493513da42fd8dbb9294e1.

It looks like this:

Custom font is misplaced inside label and button

The label and button on left is the default system font, whereas on the right, the font is changed to Al Bayan (shipped with OS X).

I'm developing an application, where the font has to be changed dynamically. If the user changes the font to one with similar behavior like this, I need some technique to change the margin/padding inside the controls, in this case like:

  • Button: +5px top margin/padding
  • Label: -5px top margin/padding

How can this be done?

Was it helpful?

Solution

This is especially worse with "Helvetica Neue" which is kinda standard font (in iOS) and likely to play a bigger role in future OS X versions. I'm not aware of a way to adjust individual controls other than changing the font, but I found a way to render text correctly with own computations. Key is here not to use the string height (e.g. for centering or placing the string), but to take the ascender and xHeight into account.

The following code draws the title of an NSTextFieldCell vertically centered, regardless of the font used:

- (NSRect)titleRectForBounds: (NSRect)theRect
{
    NSRect titleFrame = [super titleRectForBounds: theRect];
    CGRect rect = [self.attributedStringValue boundingRectWithSize: NSMakeSize(FLT_MAX, NSHeight(titleFrame))
                                                           options: 0];
    titleFrame.origin.y -= NSHeight(rect) - floor(self.font.ascender);
    titleFrame.origin.y += floor((titleFrame.size.height - self.font.xHeight) / 2);
    return titleFrame;
}

- (void)drawInteriorWithFrame: (NSRect)cellFrame inView: (NSView *)controlView
{
    NSRect titleRect = [self titleRectForBounds: cellFrame];
    [self.attributedStringValue drawInRect: titleRect];
}

The cell is part of an NSOutlineView and hence flipped. For non-flipped content the solution is probably a bit simpler (haven't tested that).

OTHER TIPS

Use setAttributedTitle: of the NSButtonCell class. Supply it an NSAttributedString See the Attributed String Programming Guide for guidance. The font will be part of an NSMutableParagraphStyle defining the text styling. The standard buttons are doing all of this with predefined styling.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top