I\'m trying to draw text using Core Text functions, with a line spacing that\'s as close as possible to what it would be if I used NSTextView.
Take this font as an e
OK, so I took a good look at what goes on in the guts of NSLayoutManager, and it appears, based on my reading of the disassembly, that the code it uses boils down to something like this:
CGFloat ascent = CTFontGetAscent(theFont);
CGFloat descent = CTFontGetDescent(theFont);
CGFloat leading = CTFontGetLeading(theFont);
if (leading < 0)
leading = 0;
leading = floor (leading + 0.5);
lineHeight = floor (ascent + 0.5) + floor (descent + 0.5) + leading;
if (leading > 0)
ascenderDelta = 0;
else
ascenderDelta = floor (0.2 * lineHeight + 0.5);
defaultLineHeight = lineHeight + ascenderDelta;
This will get you the 111.0 and 115.0 values for the two fonts you mention above.
I should add that the correct way, according to the OpenType specification, is just to add the three values (being careful, if you’re using an API that doesn’t make them all positive, to get the sign of the descent value correct).
simple. set up a test string and frame and compare origin of two lines of the font you want. Then if you want to calculate leading just use line height accent descent to do the calculation.
- (float)getLineHeight {
CFMutableAttributedStringRef testAttrString;
testAttrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);
NSString *testString = @"testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest";
CFAttributedStringReplaceString (testAttrString, CFRangeMake(0, 0), (CFStringRef)testString);
CTFontRef myFont1 = CTFontCreateWithName((CFStringRef)@"Helvetica", 30, NULL);
CFRange range = CFRangeMake(0,testString.length);
CFAttributedStringSetAttribute(testAttrString, range, kCTFontAttributeName, myFont1);
CGMutablePathRef path = CGPathCreateMutable();
CGRect bounds;
if ([model isLandscape]) {
bounds = CGRectMake(0, 10, 1024-20, 768);
}
else {
bounds = CGRectMake(0, 10, 768-20, 1024);
}
CGPathAddRect(path, NULL, bounds);
CTFramesetterRef testFramesetter = CTFramesetterCreateWithAttributedString(testAttrString);
CTFrameRef testFrameRef = CTFramesetterCreateFrame(testFramesetter,CFRangeMake(0, 0), path, NULL);
CGPoint origins1,origins2;
CTFrameGetLineOrigins(testFrameRef, CFRangeMake(0, 1), &origins1);
CTFrameGetLineOrigins(testFrameRef, CFRangeMake(1, 1), &origins2);
return origins1.y-origins2.y;
}
Have you looked to see what the sign of the value returned by CTFontGetDescent() is? A common mistake is to assume that descent values are positive, when in fact they tend to be negative (to reflect the fact that they are a descent below the font baseline).
As a result, line spacing should probably be set to
ascent - descent + leading