Note that there are some explanatory texts on larger screens.

plurals
  1. POHow does line spacing work in Core Text? (and why is it different from NSLayoutManager?)
    primarykey
    data
    text
    <p>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.</p> <p>Take this font as an example:</p> <pre><code>NSFont *font = [NSFont fontWithName:@"Times New Roman" size:96.0]; </code></pre> <p>The line height of this font, if I would use it in an NSTextView is 111.0.</p> <pre><code>NSLayoutManager *lm = [[NSLayoutManager alloc] init]; NSLog(@"%f", [lm defaultLineHeightForFont:font]); // this is 111.0 </code></pre> <p>Now, if I do the same thing with Core Text, the result is 110.4 (assuming you can calculate the line height by adding the ascent, descent and leading).</p> <pre><code>CTFontRef cFont = CTFontCreateWithName(CFSTR("Times New Roman"), 96.0, NULL); NSLog(@"%f", CTFontGetDescent(cFont) + CTFontGetAscent(cFont) + CTFontGetLeading(cFont)); // this is 110.390625 </code></pre> <p>This is very close to 111.0, but for some fonts the difference is much bigger. E.g. for Helvetica, NSLayoutManager gives 115.0 whereas CTFont ascent + descent + leading = 96.0. Clearly, for Helvetica, I wouldn't be able to use ascent + descent + leading to calculate the spacing between lines.</p> <p>So I thought I'd use CTFrame and CTFramesetter to layout a few lines and get the linespacing from that. But that also gives different values.</p> <pre><code>CTFontRef cFont = CTFontCreateWithName(CFSTR("Times New Roman"), 96.0, NULL); NSDictionary *attrs = [NSDictionary dictionaryWithObject:(id)cFont forKey:(id)kCTFontAttributeName]; NSAttributedString *threeLines = [[NSAttributedString alloc] initWithString:@"abcdefg\nabcdefg\nabcdefg" attributes:attrs]; CTFramesetterRef threeLineFramesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)threeLines); CGMutablePathRef path = CGPathCreateMutable(); CGPathAddRect(path, NULL, CGRectMake(0.0, 0.0, 600.0, 600.0)); CTFrameRef threeLineFrame = CTFramesetterCreateFrame(threeLineFramesetter, CFRangeMake(0, 0), path, NULL); CGPoint lineOrigins[3]; CTFrameGetLineOrigins(threeLineFrame, CFRangeMake(0, 0), lineOrigins); NSLog(@"space between line 1 and 2: %f", lineOrigins[0].y - lineOrigins[1].y); // result: 119.278125 NSLog(@"space between line 2 and 3: %f", lineOrigins[1].y - lineOrigins[2].y); // result: 113.625000 </code></pre> <p>So the line spacing is now even more different from the 111.0 that was used in my NSTextView, and not every line is equal. It seems that the line breaks add some extra space (even though the default value for <code>paragraphSpacingBefore</code> is 0.0).</p> <p>I'm working around this problem now by getting the line height via NSLayoutManager and then individually drawing each CTLine, but I wonder if there's a better way to do this.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload