Line spacing in multi-language layout with Core Text
Asked Answered
C

3

9

The attributed string has only one attribute - 17 point Helvetica NeueUI font - covering the whole string. Line 1~3 are purely English, line 4~6 are mixtures of English and Chinese, line 7~8 are purely Chinese.

It is then layouted with CTFramesetter and resultant frame is drawn with CTFrameDraw.

// UIView subclass
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor whiteColor];
        CTFontRef font = CTFontCreateWithName(CFSTR("Helvetica NeueUI"), 17.f, NULL);
        _text = [[NSAttributedString alloc] initWithString:string attributes:
                 [NSDictionary dictionaryWithObject:(id)font forKey:(id)kCTFontAttributeName]];
        CFRelease(font);
        _framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)_text);
        CGMutablePathRef path = CGPathCreateMutable();
        CGPathAddRect(path, NULL, self.bounds);
        _frame = CTFramesetterCreateFrame(_framesetter, CFRangeMake(0, 0), path, NULL);
        CGPathRelease(path);
    }
    return self;
}

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSaveGState(context);
    // Flip the coordinate system.
    CGContextTranslateCTM(context, 0.f, self.bounds.size.height);
    CGContextScaleCTM(context, 1.f, -1.f);
    
    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    
    CTFrameDraw(_frame, context);
    CGContextRestoreGState(context);
}

The problem is that the space between line 7 and 8 (purely Chinese lines) is much smaller than others.

For contrast, I put a UILabel below it, with the same font and text. Ignoring the rendering difference of single characters, you can see the line spaces in UILabel are uniform including the last one between two Chinese lines.

Screenshot
(source: skitch.com)

Notice: this results above is got on a real device. If you run the same code on the simulator, you'll get very different result for the Core Text view — spaces between lines containing Chinese are much larger than others.

  1. Why is the space between Chinese lines smaller(larger)?
  2. How can I layout multi-language text with uniform line height using Core Text?

PS: here is the sample project you can try yourself.

Choleric answered 16/6, 2011 at 5:54 Comment(0)
C
1

I finally got an official answer from Apple engineer:

CTLine metrics are based on the maximum of each of {ascent, descent, leading}; this has not changed, nor will it. Clients may override the line metrics using paragraph style specifiers or iOS 7 text styles, for example [UIFont preferredFontForTextStyle:UIFontTextStyleBody].

Choleric answered 1/7, 2011 at 2:33 Comment(1)
If you wouldn’t mind, I’d love to see your iOS 5 answer on the developer forums (until you can post it here).Solarize
B
3

Similarly to the space between each letter in European languages, Chinese writing uses a narrow space between characters, though it does not observe the equivalent to the wider space between words, except in rare occasions. (In this respect, it may somewhat resemble a form of scriptio continua.) When space is used, it is also fullwidth. One instance of its usage is as an honorific marker. A modern example in Taiwan, is found in the reference to Chiang Kai-shek as 先總統 蔣公 (Former President, Lord Chiang), in which the preceding space serves as an honorific marker for 蔣公. This use is also still current in very formal letters or other old-style documents. When Chinese is written in transliterated form (as in Hanyu Pinyin), spaces are used to assist in reading. source:http://en.wikipedia.org/wiki/Chinese_punctuation

So its because in chinese as space is used a bit differently than in english.

Billybillycock answered 1/3, 2012 at 20:31 Comment(0)
C
1

I finally got an official answer from Apple engineer:

CTLine metrics are based on the maximum of each of {ascent, descent, leading}; this has not changed, nor will it. Clients may override the line metrics using paragraph style specifiers or iOS 7 text styles, for example [UIFont preferredFontForTextStyle:UIFontTextStyleBody].

Choleric answered 1/7, 2011 at 2:33 Comment(1)
If you wouldn’t mind, I’d love to see your iOS 5 answer on the developer forums (until you can post it here).Solarize
I
1

The reason for the space is depending on the characters, as it could be found when querying parts of the text for its dimension, but this does not declare why a label simply ignores this problem.

However the space is in fact introduced by the FrameSetter in order to achieve even space you could use the FrameSetter to get the line breaks and use a TypeSetter (CTTypesetterCreateWithAttributedString) to produce the lines and point them at a desired line distance, as shown in the Manual Line Break from Apple. This also works for your given sample, as i have briefly checked.

Anyway I could only agree that the behaviour of the label is somehow odd, but not this bad as it looks better.

Indite answered 2/3, 2012 at 16:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.