我正在尝试使用 Core Text 函数绘制文本,其行距尽可能接近使用 NSTextView 时的行距。
以这个字体为例:
NSFont *font = [NSFont fontWithName:@"Times New Roman" size:96.0];
如果我在 NSTextView 中使用,这种字体的行高是 111.0。
NSLayoutManager *lm = [[NSLayoutManager alloc] init];
NSLog(@"%f", [lm defaultLineHeightForFont:font]); // this is 111.0
现在,如果我对 Core Text 做同样的事情,结果是 110.4(假设你可以通过添加上升、下降和前导来计算行高)。
CTFontRef cFont = CTFontCreateWithName(CFSTR("Times New Roman"), 96.0, NULL);
NSLog(@"%f", CTFontGetDescent(cFont) + CTFontGetAscent(cFont) +
CTFontGetLeading(cFont)); // this is 110.390625
这非常接近 111.0,但对于某些字体,差异要大得多。例如对于 Helvetica,NSLayoutManager 给出 115.0 而 CTFont ascent + descent +leading = 96.0。显然,对于 Helvetica,我无法使用上升 + 下降 + 引导来计算行间距。
所以我想我会使用 CTFrame 和 CTFramesetter 来布局几行并从中获取行间距。但这也给出了不同的值。
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
所以现在的行间距与我在 NSTextView 中使用的 111.0 更加不同,而且并不是每一行都是相等的。似乎换行符增加了一些额外的空间(即使默认值为paragraphSpacingBefore
0.0)。
我现在正在通过 NSLayoutManager 获取行高然后单独绘制每个 CTLine 来解决这个问题,但我想知道是否有更好的方法来做到这一点。