지난 번에 CTFramesetterSuggestFrameSizeWithConstraints 를 이용하여 드로잉 된 사이즈를 계산하는 방법을 포스팅 하였습니다.

(http://dptablo.tistory.com/213)


이번에는 CTParagraphStyle 이 적용된 CTFrameRef 의 드로잉 될 사이즈를 계산 하는 소스코드를 포스팅 합니다. 



아래와 같이 CTParagraphStyle 을 설정하여 최종적으로 CTFrameRef 를 생성하였습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
CTFontRef sysUIFont = CTFontCreateUIFontForLanguage(kCTFontSystemFontType, 폰트크기, NULL);
 
CGColorRef color = /* 컬러 */ ;
 
CTTextAlignment alignment = [self getCTTextAlignment:font.horizontalAlign];
 
CGFloat lineSpacing = 0;
 
CTParagraphStyleSetting settings[] = {
    {kCTParagraphStyleSpecifierAlignment, sizeof(alignment), &alignment}
    , {kCTParagraphStyleSpecifierLineSpacing, sizeof(lineSpacing), &lineSpacing}
};
 
CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(settings, sizeof(settings) / sizeof(settings[0]));
 
NSDictionary *attributesDict = [NSDictionary dictionaryWithObjectsAndKeys:
                                (__bridge id)paragraphStyle, kCTParagraphStyleAttributeName,
                                color, (id)kCTForegroundColorAttributeName,
                                sysUIFont, (id)kCTFontAttributeName,
                                nil];
 
 
NSAttributedString *stringToDraw = [[NSAttributedString alloc] initWithString:text
                                                                   attributes:attributesDict];
 
 
CGContextSetTextMatrix(ctx, CGAffineTransformIdentity);
CGContextTranslateCTM(ctx, 0, documentSize.height.value);
CGContextScaleCTM(ctx, 1.0, -1.0);
 
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)stringToDraw);
 
struct CGPath *p = CGPathCreateMutable();
CGPathAddRect(p, NULL, drawRect);
 
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), p, NULL);
 




이후 아래처럼 CTFrameRef 의 드로잉 될 영역의 크기를 계산하였습니다.


CTLineGetTypographicBounds   CTFrameGetLineOrigins   두가지 api를 이용하여 


드로잉 위치와 ascent, descent, leading 값을 이용하여 계산하였습니다. 



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
+(CGSize)measureFrame:(CTFrameRef)frame
{    
    // 1. Width 계산
    CFArrayRef  lines       = CTFrameGetLines(frame);
    CFIndex     numLines    = CFArrayGetCount(lines);
    CGFloat     maxWidth    = 0;
 
    for(CFIndex index = 0; index < numLines; index++)
    {
        CTLineRef   line = (CTLineRef) CFArrayGetValueAtIndex(lines, index);
        CGFloat     ascent, descent, leading, width;
        
        width = CTLineGetTypographicBounds(line, &ascent,  &descent, &leading);
        
        if(width > maxWidth)
            maxWidth = width;
    }
 
    // 2. Height 계산
    CGFloat ascent, descent, leading;
 
    CTLineGetTypographicBounds((CTLineRef) CFArrayGetValueAtIndex(lines, 0), &ascent,  &descent, &leading);
 
    CTLineGetTypographicBounds((CTLineRef) CFArrayGetValueAtIndex(lines, numLines - 1), &ascent,  &descent, &leading);
    CGFloat lastLineHeight  = ascent + descent + leading;
 
    CGPoint firstLineOrigin;
    CTFrameGetLineOrigins(frame, CFRangeMake(0, 1), &firstLineOrigin);
 
    CGPoint lastLineOrigin;
    CTFrameGetLineOrigins(frame, CFRangeMake(numLines - 1, 1), &lastLineOrigin);
 
    CGFloat textHeight = ceil(ABS(firstLineOrigin.y - lastLineOrigin.y) + lastLineHeight);
 
    return CGSizeMake(maxWidth, textHeight);
}


블로그 이미지

Tablo@

leeyw2355@gmail.com