CTRunGetImageBounds renvoyant des résultats inexacts

J'utilise Core Text pour dessiner du text. Je voudrais get les différentes limites d'exécution, mais quand j'appelle CTRunGetImageBounds , le rect qui est returnné est la taille correcte, mais dans le mauvais endroit. Plus précisément, l'origine de la ligne se trouve à la fin du text dans son set.

 - (void)drawRect:(CGRect)rect { CGContextRef context = UIGraphicsGetCurrentContext(); self.transform = CGAffineTransformMakeScale(1.0, -1.0); CGContextSetTextMasortingx(context, CGAffineTransformIdentity); [[UIColor whiteColor] set]; CGContextFillRect(context, self.bounds); NSMutableAtsortingbutedSsortingng* attrSsortingng = [[NSMutableAtsortingbutedSsortingng alloc] initWithSsortingng:@"Blue should be underlined."]; NSRange blueRange = NSMakeRange(0, 4); [attrSsortingng beginEditing]; //make all text size 20.0 [attrSsortingng addAtsortingbute:(NSSsortingng *)kCTFontAtsortingbuteName value:(id)CTFontCreateWithName((CFSsortingngRef)@"Helvetica", 20.0, NULL) range:NSMakeRange(0, [attrSsortingng length])]; //make the text appear in blue [attrSsortingng addAtsortingbute:(NSSsortingng *)kCTForegroundColorAtsortingbuteName value:(id)[[UIColor blueColor] CGColor] range:blueRange]; //next make the text appear with an underline [attrSsortingng addAtsortingbute:(NSSsortingng *)kCTUnderlineStyleAtsortingbuteName value:[NSNumber numberWithInt:1] range:blueRange]; [attrSsortingng endEditing]; CGMutablePathRef path = CGPathCreateMutable(); CGRect bounds = CGRectMake(10.0, 10.0, 200.0, 200.0); [[UIColor redColor] set]; CGContextFillRect(context, bounds); CGPathAddRect(path, NULL, bounds); CTFramesetterRef framesetter = CTFramesetterCreateWithAtsortingbutedSsortingng((CFAtsortingbutedSsortingngRef)attrSsortingng); CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL); CTFrameDraw(frame, context); for (id lineObj in (NSArray *)CTFrameGetLines(frame)) { CTLineRef line = (CTLineRef)lineObj; for (id runObj in (NSArray *)CTLineGetGlyphRuns(line)) { CTRunRef run = (CTRunRef)runObj; CGRect runBounds = CTRunGetImageBounds(run, context, CFRangeMake(0, 0)); NSLog(@"bounds: %@", NSSsortingngFromCGRect(runBounds)); [[UIColor greenColor] set]; CGContextFillRect(context, runBounds); } } CFRelease(framesetter); CFRelease(frame); [attrSsortingng release]; } 

Produit:

résultats

Voici ce que j'ai trouvé. C'est complètement précis.

 CTFrameRef frame = [self _frameWithRect:rect]; NSArray *lines = (NSArray *)CTFrameGetLines(frame); CGPoint origins[[lines count]];//the origins of each line at the baseline CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), origins); NSUInteger lineIndex = 0; for (id lineObj in lines) { CTLineRef line = (CTLineRef)lineObj; for (id runObj in (NSArray *)CTLineGetGlyphRuns(line)) { CTRunRef run = (CTRunRef)runObj; CFRange runRange = CTRunGetSsortingngRange(run); CGRect runBounds; CGFloat ascent;//height above the baseline CGFloat descent;//height below the baseline runBounds.size.width = CTRunGetTypographicBounds(run, CFRangeMake(0, 0), &ascent, &descent, NULL); runBounds.size.height = ascent + descent; CGFloat xOffset = CTLineGetOffsetForSsortingngIndex(line, CTRunGetSsortingngRange(run).location, NULL); runBounds.origin.x = origins[lineIndex].x + rect.origin.x + xOffset; runBounds.origin.y = origins[lineIndex].y + rect.origin.y; runBounds.origin.y -= descent; //do something with runBounds } lineIndex++; } 

Avant de pouvoir utiliser CTRunGetImageBounds () ou CTLineDraw (), vous devez définir la position du text de départ avec un appel à CGContextSetTextPosition () avant de dessiner ou de calculer chaque ligne. La raison est que CTLine n'a aucune idée de l'endroit où commencer à dessiner (ou calculer) seul, il utilise la dernière position du text, vous devez donc lui donner un sharepoint départ XY. Pour get les origines du tableau de lignes d'un cadre, appelez CTFrameGetLineOrigins () avec un tableau de points. Ensuite, avant de dessiner ou de calculer chaque ligne, définissez l'origine de cette ligne via CGContextSetTextPosition ().

 NSArray *lines = (NSArray *)CTFrameGetLines(frame); CGPoint origins[[lines count]]; // the origins of each line at the baseline CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), origins); int i, lineCount; lineCount = [lines count]; for (i = 0; i < lineCount; i++) { CTLineRef line = (CTLineRef)[lines objectAtIndex:i]; CGContextSetTextPosition(context, origins[i].x, origins[i].y); CTLineDraw(line, context); }