I'm drawing multiple 'pages' of imagery using a CGContext in the iOS. I've used sizeWithFont and drawInRect combinations extensively in my app. What I need to do is split a large chunk of text across multiple pages. I can size it and work out whether or not it needs another page but how do I know where to chop it? Do I have to do an ugly loop to check word by word until I find a string length that perfectly fits the page and then chop the string at that point? Is there a smarter way?
Any ideas?
Thanks.
The NSString additions to UIKit for drawing text, you can pre-determine the exact amount of space required to render a given text for a given font. If splitting the text into pages, you could use this method.
– sizeWithFont:constrainedToSize:lineBreakMode:
Assuming the font and line break mode is known, create a CGSize having the same width as your page, and use a sufficiently number for height. This would be the maximum size that we are constraining the text into.
CGSize maximumSize = CGSizeMake(pageWidth, 999999999);
CGSize expectedSize = [veryLongString sizeWithFont:theFont constrainedToSize:maximumSize lineBreakMode:theLineBreakMode];
expectedSize
will tell us the size that the text will take assuming if it could extend vertically infinitely (well close to). To find the number of pages required, just divide the total height by the height of one page.
NSInteger totalPages = ceil(expectedSize.height / heightOfOnePage);
You would also want to adjust the height of one page to make sure that the last line of text doesn't get clipped. For that to happen, the height of the page should be a multiple of the font's line height. Say the initial page height is 300px
, and the font-height is 16px
, then there will be some clipping as 300/16 = 18.75
which is not a whole number.
NSInteger linesWithoutClipping = floor(initialPageHeight / theFont.lineHeight);
CGFloat optimalPageHeight = linesWithoutClipping * theFont.lineHeight;
Taking the floor value 18
and multiplying with the font line height 16
, we get an optimal page height of 288
to ensure there's no clipping.
Note that lineHeight was introduced in iOS 4.0, but you could calculate it yourselves if needed for older versions.