How does line spacing work in Core Text? (and why is it different from NSLayoutManager?)

和自甴很熟 提交于 2019-11-28 03:09:29

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
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!