3

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.

Stephen Johnson
  • 5,293
  • 1
  • 23
  • 37
  • At what point are you calling that in the view lifecycle, and are you using auto-layout? – Jordan Feb 01 '17 at 19:04
  • This is in a layer. I call it in `- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx` which is the layer equivalent of the `drawRect:` on an `NSView`. I do use auto-layout to position the NSView that contain these layers. – Stephen Johnson Feb 01 '17 at 19:24
  • Did you figure this out yet? Can you repro this in a smaller, isolated app (that you could share)? I suspect this is a bug in AppKit. Can you work around by maybe caching the initial width/height ratio & divining the height on your own? – Jordan Feb 10 '17 at 17:03
  • I am currently working around the issue with a bad hack :( I calculate the font point size to pixel ratio for font size 10 and I then multiply that by the really small point size. The size works correctly for everything I have tried so far. – Stephen Johnson Feb 10 '17 at 17:09
  • Yeah, boo. That's too bad. – Jordan Feb 10 '17 at 17:19
  • I haven't created a small stand alone sample project yet that I can post or submit to Apple for a bug. – Stephen Johnson Feb 10 '17 at 17:48

1 Answers1

2

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);    
}
Frank Hintsch
  • 560
  • 8
  • 14