Body Text: Counting Pages in a Background Stream

Say I'm writing a text viewer for iPhone using Core Text. Each time the user changes the size of the base font, I need to calculate how many pages (CGR) of a fixed size are needed to display the entire NSAttributedString with the given font sizes.

And I would like to do this in a separate NSOperation, so that the user will not experience unnecessary user interface delays.

Unfortunately, for page counting, I need to draw my frames (CTFrameDraw) using invisible text drawing mode, and then use CTFrameGetVisibleStringRange to count characters. But to draw text, I need a CGContext. And here the problems begin ...

I can get the CGContext in my drawRect by calling UIGraphicsGetCurrentContext, but in this case:

  1. I need to call any method that works with CGContext using the performSelectorOnMainThread function, right?
  2. Another thread must CFRetain this context. Is it acceptable to use the drawRect CGContext method outside of the drawRect method?

Any other solutions? Creating a separate CGContext in a workflow? How? CGBitmapContext? How can I be sure that all conditions (I don’t know the resolution? Etc.) will be the same as in drawRect CGContext so that the pages are correctly counted?

+3
source share
3 answers

You do not need CTFrameDraw before getting the result from CTFrameGetVisibleStringRange

0

CTFramesetterSuggestFrameSizeWithConstraints.

: NSString

0

use CTFramesetterSuggestFrameSizeWithConstraints, if you specify fitRange parameter, it will return the actual row range

+ (NSArray*) pagesWithString:(NSString*)string size:(CGSize)size font:(UIFont*)font;
{
  NSMutableArray* result = [[NSMutableArray alloc] initWithCapacity:32];
  CTFontRef fnt = CTFontCreateWithName((CFStringRef)font.fontName, font.pointSize,NULL);
  CFAttributedStringRef str = CFAttributedStringCreate(kCFAllocatorDefault, 
                                                       (CFStringRef)string, 
                                                       (CFDictionaryRef)[NSDictionary dictionaryWithObjectsAndKeys:(id)fnt,kCTFontAttributeName,nil]);
  CTFramesetterRef fs = CTFramesetterCreateWithAttributedString(str);
  CFRange r = {0,0};
  CFRange res = {0,0};
  NSInteger str_len = [string length];
  do {
    CTFramesetterSuggestFrameSizeWithConstraints(fs,r, NULL, size, &res);
    r.location += res.length;
    [result addObject:[NSNumber numberWithInt:res.length]];
  } while(r.location < str_len);

  CFRelease(fs);
  CFRelease(str);
  CFRelease(fnt);
  return result;
}  
0
source

Source: https://habr.com/ru/post/1753877/


All Articles