Core Text实战
这里使用Core Text实现一个和之前NSTextView显示类似的图文混排的例子。
直接贴上代码大家体会下:
- void RunDelegateDeallocCallback( void* refCon ){
- }
- CGFloat RunDelegateGetAscentCallback( void *refCon ){
- NSString *imageName = (NSString *)refCon;
- return [UIImage imageNamed:imageName].size.height;
- }
- CGFloat RunDelegateGetDescentCallback(void *refCon){
- return 0;
- }
- CGFloat RunDelegateGetWidthCallback(void *refCon){
- NSString *imageName = (NSString *)refCon;
- return [UIImage imageNamed:imageName].size.width;
- }
- - (void)drawRect:(CGRect)rect
- {
- CGContextRef context = UIGraphicsGetCurrentContext();
- //这四行代码只是简单测试drawRect中context的坐标系
- CGContextSetRGBFillColor (context, 1, 0, 0, 1);
- CGContextFillRect (context, CGRectMake (0, 200, 200, 100 ));
- CGContextSetRGBFillColor (context, 0, 0, 1, .5);
- CGContextFillRect (context, CGRectMake (0, 200, 100, 200));
- CGContextSetTextMatrix(context, CGAffineTransformIdentity);//设置字形变换矩阵为CGAffineTransformIdentity,也就是说每一个字形都不做图形变换
- CGAffineTransform flipVertical = CGAffineTransformMake(1,0,0,-1,0,self.bounds.size.height);
- CGContextConcatCTM(context, flipVertical);//将当前context的坐标系进行flip
- NSMutableAttributedString *attributedString = [[[NSMutableAttributedString alloc] initWithString:@"测试富文本显示"] autorelease];
- //为所有文本设置字体
- //[attributedString addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:24] range:NSMakeRange(0, [attributedString length])]; // 6.0+
- UIFont *font = [UIFont systemFontOfSize:24];
- CTFontRef fontRef = CTFontCreateWithName((CFStringRef)font.fontName, font.pointSize, NULL);
- [attributedString addAttribute:(NSString *)kCTFontAttributeName value:(id)fontRef range:NSMakeRange(0, [attributedString length])];
- //将“测试”两字字体颜色设置为蓝色
- //[attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:NSMakeRange(0, 2)]; //6.0+
- [attributedString addAttribute:(NSString *)kCTForegroundColorAttributeName value:(id)[UIColor blueColor].CGColor range:NSMakeRange(0, 2)];
- //将“富文本”三个字字体颜色设置为红色
- //[attributedString addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(2, 3)]; //6.0+
- [attributedString addAttribute:(NSString *)kCTForegroundColorAttributeName value:(id)[UIColor redColor].CGColor range:NSMakeRange(2, 3)];
- //为图片设置CTRunDelegate,delegate决定留给图片的空间大小
- NSString *taobaoImageName = @"taobao.png";
- CTRunDelegateCallbacks imageCallbacks;
- imageCallbacks.version = kCTRunDelegateVersion1;
- imageCallbacks.dealloc = RunDelegateDeallocCallback;
- imageCallbacks.getAscent = RunDelegateGetAscentCallback;
- imageCallbacks.getDescent = RunDelegateGetDescentCallback;
- imageCallbacks.getWidth = RunDelegateGetWidthCallback;
- CTRunDelegateRef runDelegate = CTRunDelegateCreate(&imageCallbacks, taobaoImageName);
- NSMutableAttributedString *imageAttributedString = [[NSMutableAttributedString alloc] initWithString:@" "];//空格用于给图片留位置
- [imageAttributedString addAttribute:(NSString *)kCTRunDelegateAttributeName value:(id)runDelegate range:NSMakeRange(0, 1)];
- CFRelease(runDelegate);
- [imageAttributedString addAttribute:@"imageName" value:taobaoImageName range:NSMakeRange(0, 1)];
- [attributedString insertAttributedString:imageAttributedString atIndex:1];
- CTFramesetterRef ctFramesetter = CTFramesetterCreateWithAttributedString((CFMutableAttributedStringRef)attributedString);
- CGMutablePathRef path = CGPathCreateMutable();
- CGRect bounds = CGRectMake(0.0, 0.0, self.bounds.size.width, self.bounds.size.height);
- CGPathAddRect(path, NULL, bounds);
- CTFrameRef ctFrame = CTFramesetterCreateFrame(ctFramesetter,CFRangeMake(0, 0), path, NULL);
- CTFrameDraw(ctFrame, context);
- CFArrayRef lines = CTFrameGetLines(ctFrame);
- CGPoint lineOrigins[CFArrayGetCount(lines)];
- CTFrameGetLineOrigins(ctFrame, CFRangeMake(0, 0), lineOrigins);
- for (int i = 0; i < CFArrayGetCount(lines); i++) {
- CTLineRef line = CFArrayGetValueAtIndex(lines, i);
- CGFloat lineAscent;
- CGFloat lineDescent;
- CGFloat lineLeading;
- CTLineGetTypographicBounds(line, &lineAscent, &lineDescent, &lineLeading);
- CFArrayRef runs = CTLineGetGlyphRuns(line);
- for (int j = 0; j < CFArrayGetCount(runs); j++) {
- CGFloat runAscent;
- CGFloat runDescent;
- CGPoint lineOrigin = lineOrigins[i];
- CTRunRef run = CFArrayGetValueAtIndex(runs, j);
- NSDictionary* attributes = (NSDictionary*)CTRunGetAttributes(run);
- CGRect runRect;
- runRect.size.width = CTRunGetTypographicBounds(run, CFRangeMake(0,0), &runAscent, &runDescent, NULL);
- runRect=CGRectMake(lineOrigin.x + CTLineGetOffsetForStringIndex(line, CTRunGetStringRange(run).location, NULL), lineOrigin.y - runDescent, runRect.size.width, runAscent + runDescent);
- NSString *imageName = [attributes objectForKey:@"imageName"];
- //图片渲染逻辑
- if (imageName) {
- UIImage *image = [UIImage imageNamed:imageName];
- if (image) {
- CGRect imageDrawRect;
- imageDrawRect.size = image.size;
- imageDrawRect.origin.x = runRect.origin.x + lineOrigin.x;
- imageDrawRect.origin.y = lineOrigin.y;
- CGContextDrawImage(context, imageDrawRect, image.CGImage);
- }
- }
- }
- }
- CFRelease(ctFrame);
- CFRelease(path);
- CFRelease(ctFramesetter);
- }