neevek
neevek

Reputation: 12128

Space between the last 2 lines of a paragraph is larger?

I draw the text using CTFramesetter, I have set kCTParagraphStyleSpecifierParagraphSpacing, kCTParagraphStyleSpecifierLineSpacing, kCTParagraphStyleSpecifierParagraphSpacingBefore all to 0.0.

As you can see in the image, the space between the last 2 lines of a paragraph is much larger than others'.

There're in total 15 lines in this image, I pasted their ascent, descent, leading, origin.y in the following, we can see that the ascent and descent on the 5th and 10th line are larger than others', I couldn't find any specifier to set to avoid this weird layout.

Any ideas?

1  ascent=20.639999, descent=3.360000, leading=0.720000, origin.y: 399.000000
2  ascent=20.639999, descent=3.360000, leading=0.720000, origin.y: 374.000000
3  ascent=20.639999, descent=3.360000, leading=0.720000, origin.y: 349.000000
4  ascent=20.639999, descent=3.360000, leading=0.720000, origin.y: 324.000000
5  ascent=25.722656, desecent=13.699219, leading=0.720000, origin.y: 294.000000
6  ascent=20.639999, descent=3.360000, leading=0.720000, origin.y: 258.000000
7  ascent=20.639999, descent=3.360000, leading=0.720000, origin.y: 233.000000
8  ascent=20.639999, descent=3.360000, leading=0.720000, origin.y: 208.000000
9  ascent=20.639999, descent=3.360000, leading=0.720000, origin.y: 183.000000
10 ascent=25.722656, descent=13.699219, leading=0.720000, origin.y: 153.000000
11 ascent=20.639999, descent=3.360000, leading=0.720000, origin.y: 117.000000
12 ascent=20.639999, descent=3.360000, leading=0.720000, origin.y: 92.000000
13 ascent=20.639999, descent=3.360000, leading=0.720000, origin.y: 67.000000
14 ascent=20.639999, descent=3.360000, leading=0.720000, origin.y: 42.000000
15 ascent=20.639999, descent=3.360000, leading=0.720000, origin.y: 17.000000 

enter image description here

Upvotes: 2

Views: 641

Answers (2)

Saykho
Saykho

Reputation: 11

If you use NSMutableAttributeString for text layout, you can set a CTRunDelegate attribute to set the \n metrics to 0. For me this worked:

        CTRunDelegateCallbacks callbacks;
        callbacks.version = kCTRunDelegateVersion1;
        callbacks.getAscent = lineBreakCallback;
        callbacks.getDescent = lineBreakCallback;
        callbacks.getWidth = lineBreakCallback;

        CTFontRef fontRef = CTFontCreateWithName((CFStringRef)@"System", 1.0f, NULL);

        CTRunDelegateRef delegate = CTRunDelegateCreate(&callbacks, NULL); //3
        NSDictionary *attrDictionaryDelegate = [NSDictionary dictionaryWithObjectsAndKeys:
                                                //set the delegate
                                                (__bridge id)delegate, (NSString*)kCTRunDelegateAttributeName,
                                                (__bridge id)fontRef, kCTFontAttributeName,
                                                nil];
        stringLength++;
        [attString appendAttributedString:[[NSAttributedString alloc] initWithString:@"\n" attributes:attrDictionaryDelegate]];

        CFRelease(delegate);
        CFRelease(fontRef);

and

static CGFloat lineBreakCallback( void* ref )
{
    return 0;
}

EDIT:

  • following comments I fixed memory management part (I hope that correctly)
  • I added a font attribute with font of size 1. This is because when the font size of a run (default font size is about 16) is bigger than the rest of line, it changes the line metrics even if the run metrics are smaller (which is quite annoying if you really want to set a bigger font size to a part of a line without for example changing the line's descent - I haven't found a solution for this problem yet).

Upvotes: 1

neevek
neevek

Reputation: 12128

Damit, it's a bug. DTCoreText works around this by repositioning the baseline origins of those affected lines.

see http://www.cocoanetics.com/2012/02/radar-coretext-line-spacing-bug/

Upvotes: 0

Related Questions