I have a certain amount of text that fill some CTFrame
(more than one). To create all frames (one for each page), I'm filling one frame, getting the text that didn't fitted the frame using CTFrameGetVisibleStringRange
and repeating this process until all text is processed.
On all frames, except the last, the text occupies the same height of page. On last frame I'd like to know the real height the text occupies, to know where I could start drawing more text.
Is there any way to do this?
UPDATE
As requested on comments, here's my solution using @omz 's suggestion:
I'm using ARC on my project:
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);
+ (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);
}
You could either get the line origin of the last line in the frame with CTFrameGetLineOrigins
or use the CTFramesetterSuggestFrameSizeWithConstraints
function to get the size of a rectangular frame for a given range. The latter wouldn't work if you use non-rectangular paths for setting the actual frames though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With