For laying out a long string into pages, I can use CTFramesetterCreateFrame to create CTFrameRef and then move forward the start index in the string for creating next CTFrameRef. This is easy since the start index is moving forward, and the Core Text APIs support this kind of layout natively.
Now I am stuck in a situation that I want to turn to the previous page.
For example, The length of the long string is 1000, now the start index of the current page(or CTFrameRef) is 500, and I want to turn to the previous page, how do I know what index to start? I can’t cache all the indices for each page or calculate from the start of the string, cause the string can be very very long that won’t fit in memory(I will need to read the string from a file block by block). I have scanned the CT* APIs, there’s no such API that supports laying out text backwards.
Any ideas on this?
The reason that there’s no API for this is that there’s no efficient context-independent way of doing this other than trying to typeset the whole page by trial and error to find the best start index, which as you can imagine would be an intensive operation.
If each page of your text has a set width, and is just a rectangular CTFrame, this how you can do this:
Although this should work, I still recommend you try to find a way of avoiding this if possible. Notice that this breaks down as soon as you have a more complex pagination algorithm, and even in this case it uses 1.5/2x memory. Here are a few suggestions on how you can do this:
Cache the indexes (at least up to the current position.) Each page can probably hold ~1000 characters, so your cache size will be 0.1% the size of the whole text, and you have to do it at least once for the first time you’re showing the text. You can make the cache even smaller by storing indexes for every n page.
If it applies, break your string into logical substrings, for example based on page break or section breaks, Then typeset that each substring as a whole for a range of pages.