Как получить реальную высоту текста, нарисованного на CTFrame - PullRequest
4 голосов
/ 04 декабря 2011

У меня есть определенное количество текста, который заполняет некоторые CTFrame (более одного). Чтобы создать все фреймы (по одному для каждой страницы), я заполняю один фрейм, получая текст, который не умещается в фрейм, с помощью CTFrameGetVisibleStringRange и повторяю этот процесс, пока весь текст не будет обработан.

На всех фреймах, кроме последнего, текст занимает одинаковую высоту страницы. На последнем кадре я хотел бы знать реальную высоту, занимаемую текстом, чтобы знать, где я мог бы начать рисовать больше текста.

Есть ли способ сделать это?

UPDATE

Как и просили комментарии, вот мое решение, использующее предложение @omz:

Я использую ARC в своем проекте:

CTFrameRef locCTFrame = (__bridge CTFrameRef)ctFrame;

//Save CTLines
lines = (NSArray *) ((__bridge id)CTFrameGetLines(locCTFrame));

//Get line origins
CGPoint lOrigins[MAXLINESPERPAGE];
CTFrameGetLineOrigins(locCTFrame, CFRangeMake(0, 0), lOrigins);
CGFloat colHeight = self.frame.size.height;

//Save the amount of the height used by text
percentFull = ((colHeight - lOrigins[[lines count] - 1].y) / colHeight);

Ответы [ 3 ]

7 голосов
/ 15 октября 2012
+ (CGSize)measureFrame:(CTFrameRef)frame
{
    // 1. measure 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. measure height
    CGFloat ascent, descent, leading;

    CTLineGetTypographicBounds((CTLineRef) CFArrayGetValueAtIndex(lines, 0), &ascent,  &descent, &leading);
    CGFloat firstLineHeight = 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 = ABS(firstLineOrigin.y - lastLineOrigin.y) + firstLineHeight + lastLineHeight;

    return CGSizeMake(maxWidth, textHeight);
}
3 голосов
/ 04 декабря 2011

Вы можете либо получить начало строки последней строки в кадре с помощью CTFrameGetLineOrigins, либо использовать функцию CTFramesetterSuggestFrameSizeWithConstraints, чтобы получить размер прямоугольной рамки для заданного диапазона. Последнее не сработает, если вы используете непрямоугольные пути для установки фактических кадров.

0 голосов
/ 04 декабря 2011

Использование CTLineGetTypographicBounds.

...