Core Text 関数を使用して、NSTextView を使用した場合に可能な限り近い行間でテキストを描画しようとしています。
例として、次のフォントを取り上げます。
NSFont *font = [NSFont fontWithName:@"Times New Roman" size:96.0];
NSTextView で使用する場合、このフォントの行の高さは 111.0.0 です。
NSLayoutManager *lm = [[NSLayoutManager alloc] init];
NSLog(@"%f", [lm defaultLineHeightForFont:font]); // this is 111.0
ここで、コア テキストで同じことを行うと、結果は 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 の上昇 + 下降 + 進行 = 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 を個別に描画することで、この問題を回避していますが、これを行うためのより良い方法があるかどうか疑問に思っています。