Search code examples
macosnsstringappkitnsfont

sizeWithAttributes gives the wrong height with NSFont on a mac when the point size is very small


I am working on a mac app that lets the user zoom pretty far in on the content. I need to measure the size of text that I render. When I scale the font for the zoom the point size of the font is very small (i.e. 0.001). When I use [NSString sizeWithAttributes:] to get the size of a string I get the correct width and I always get 1.0 for the height. I also have an iOS app and this rendering class is used on both iOS and Mac. On iOS when I use a UIFont with a point size of .001 I get the correct height when I call sizeWithAttributes.


Solution

  • I've got the same problem. The following sample code

    #if TARGET_OS_IOS == 0
    #define UIFont NSFont
    #define NSStringFromCGSize NSStringFromSize
    #endif
    
    UIFont *uiFont = [UIFont fontWithName:@"Courier" size:19];
    CGSize boxSize = [@"1" sizeWithAttributes:@{NSFontAttributeName:uiFont}];
    NSLog(@"boxSize %@", NSStringFromCGSize(boxSize));
    

    yields on iOS boxSize {11.40185546875, 19}, on macOS boxSize {11.40185546875, 24}.

    My workaround: Use CTFont.

    CTFontRef _contentFont = CTFontCreateWithName((__bridge CFStringRef)@"Courier", 19, NULL);
    CGGlyph glyphs[1];
    UniChar chars[1];
    chars[0] = '1';
    bool rc = CTFontGetGlyphsForCharacters(_contentFont, chars, glyphs, 1);
    if (rc) {
      double advance = CTFontGetAdvancesForGlyphs(_contentFont, kCTFontOrientationDefault, glyphs, NULL, 1);
      boxSize.width = advance;
      boxSize.height = CTFontGetAscent(_contentFont) + CTFontGetDescent(_contentFont);    
    }