← Blog

String Drawing and Typesetter Behaviours

· James

I’d like to touch briefly on an issue we recently came across in Ember for Mac where a snap’s text annotations weren’t being drawn correctly after they had been written.

We use an NSTextView to allow the user to add and edit text annotations. When they’ve finished editing we save the annotation model object, remove the text view, and draw the annotation CALayer object. When drawing the layer we use the NSString convenience method drawInRect:.

NSAttributedString *text = [[NSAttributedString alloc] initWithString:[self text] attributes:[self _textAttributes]];
[text drawInRect:(CGRect){.origin = CGPointZero, .size = [self boxSize]}];

However the string being drawn wasn’t appearing the same as the string drawn in the NSTextView when the user was editing it. The line height in particular was very different. The reason was due to the differences in typesetter behaviour. The string-drawing convenience methods supplied by the Application Kit use NSTypesetterBehavior_10_2_WithCompatibility, whereas NSLayoutManager objects use NSTypesetterLatestBehavior.

The typesetter behaviour varies the paragraph spacing, line spacing, and head indent. So if you are measuring, and rending as in our case, the typesetter behaviour will need to be the same if you want the results to be the same. The fix we implemented was to have the NSTextView use the same typesetter behaviour as the string-drawing convenience method.

[[textView layoutManager] setTypesetterBehavior:NSTypesetterBehavior_10_2_WithCompatibility];

Apple goes in to more detail on this behaviour in their Text Layout Programming Guide. The next release of Ember will introduce the highly-requested blur tool and fix some issues, including the one discussed in this article. Download it now on the Mac App Store.

Download

Confirm your email and we'll send your code. Unsubscribe any time. Privacy policy