NSMutableString * text = @"";
coretext 跟很多底层 API 一样,Core Text 使用 Y翻转坐标系统,而且内容的呈现也是上下翻转的,所以需要通过转换内容将其翻转
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
// 这里你需要创建一个用于绘制文本的路径区域。Mac 上的 Core Text 支持矩形图形等不同形状,但在 iOS 上只支持矩形。在这个示例中,你将通过 self.bounds 使用整个视图矩形区域创建 CGPath 引用。
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, self.bounds);
// 创建字体以及字体大小
CGFloat fontSize = 14.0;
CTFontRef helvetica = CTFontCreateWithName(CFSTR("Helvetica"), fontSize, NULL);
CTFontRef helveticaBold = CTFontCreateWithName(CFSTR("Helvetica-Bold"), fontSize, NULL);
CTFontRef helveticaItalic = CTFontCreateCopyWithSymbolicTraits(helveticaBold, fontSize, NULL,kCTFontItalicTrait, kCTFontBoldTrait | kCTFontItalicTrait); // 根据已有的字体创建其斜体字体
CTFontRef systemFont = CTFontCreateUIFontForLanguage(kCTFontSystemFontType, fontSize, NULL);
// 定义字体颜色
CGColorRef topicColor = [UIColor redColor].CGColor;
CGColorRef linkColor = RGBColor(19, 160, 205).CGColor;
CGColorRef atColor = [UIColor grayColor].CGColor;
// 定义样式
//NSNumber * underline = [NSNumber numberWithInt:kCTUnderlineStyleSingle];
// 创建文本对齐方式
CTTextAlignment alignment = kCTLeftTextAlignment;//左对齐 kCTRightTextAlignment为右对齐
CTParagraphStyleSetting alignmentStyle;
alignmentStyle.spec = kCTParagraphStyleSpecifierAlignment;//指定为对齐属性
alignmentStyle.valueSize = sizeof(alignment);
alignmentStyle.value = &alignment;
// 创建文本行间距
CGFloat lineSpace = 5.0f; //间距数据
CTParagraphStyleSetting lineSpaceStyle;
lineSpaceStyle.spec = kCTParagraphStyleSpecifierLineSpacing;//指定为行间距属性
lineSpaceStyle.valueSize = sizeof(lineSpace);
lineSpaceStyle.value = &lineSpace;
//换行模式
CTParagraphStyleSetting lineBreakStyle;
CTLineBreakMode lineBreak = kCTLineBreakByCharWrapping;
lineBreakStyle.spec = kCTParagraphStyleSpecifierLineBreakMode;
lineBreakStyle.value = &lineBreak;
lineBreakStyle.valueSize = sizeof(CTLineBreakMode);
// 创建样式数组
CTParagraphStyleSetting settings[] = {alignmentStyle, lineSpaceStyle, lineBreakStyle};
CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(settings, sizeof(settings)); // 设置样式
// 在 Core Text 中使用 NSAttributedString 而不是 NSString,NSAttributedString 是一个非常强大的 NSString 派生类,它允许你对文本应用格式化属性。 现在我们还没有用到格式化,这里仅仅使用纯文本。
NSMutableAttributedString * attString = [[[NSMutableAttributedString alloc] initWithString:text] autorelease];
// 给字符串添加样式attribute
[attString addAttribute:(id)kCTFontAttributeName value:(id)helvetica range:NSMakeRange(0, [attString length])];
[attString addAttribute:(id)kCTParagraphStyleAttributeName value:(id)paragraphStyle range:NSMakeRange(0, [attString length])];
// 解析http://短链接
NSString *regex_http = @"[http]+://[[a-zA-Z]*.]*[/[a-zA-Z0-9_]*]*.[a-zA-Z]*"; //http://短链接正则表达式
NSArray *array_http = [text componentsMatchedByRegex:regex_http];
if ([array_http count]) {
NSLog(@"解析http短链接:");
for (NSString *str in array_http) {
NSRange range = [text rangeOfString:str];
// NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithObject:(id)paragraphStyle forKey:(id)kCTParagraphStyleAttributeName];
NSLog(@"\t%@", str);
[attString addAttribute:(id)kCTForegroundColorAttributeName value:(id)linkColor range:range];
}
}
// 解析#话题#
NSString *regex_topic = @"#[\\u4e00-\\u9fa5\\w\\-]*#";
NSArray *array_topic = [text componentsMatchedByRegex:regex_topic];
if ([array_topic count]) {
printf("\n");
NSLog(@"解析#话题#:");
for (NSString *str in array_topic) {
NSLog(@"\t%@", str);
NSRange range = [text rangeOfString:str];
[attString addAttribute:(id)kCTForegroundColorAttributeName value:(id)topicColor range:range];
}
}
// 解析@
NSString *regex_at = @"@[^\\s]+\\s?"; //@的正则表达式
NSArray *array_at = [text componentsMatchedByRegex:regex_at];
if ([array_at count]) {
printf("\n");
NSLog(@"解析@:");
for (NSString *str in array_at) {
NSLog(@"\t%@", str);
NSRange range = [text rangeOfString:str];
[attString addAttribute:(id)kCTForegroundColorAttributeName value:(id)atColor range:range];
}
}
// 解析<加粗>
NSString *regex_bold = @"<[\\u4e00-\\u9fa5\\w\\-]+>";
NSArray *array_bold = [text componentsMatchedByRegex:regex_bold];
if ([array_bold count]) {
printf("\n");
NSLog(@"解析<加粗>:");
for (NSString *str in array_bold) {
NSLog(@"\t%@", str);
NSRange range = [text rangeOfString:str];
[attString addAttribute:(id)kCTFontAttributeName value:(id)helveticaBold range:range];
// 过滤掉 < > 符号
NSString * s = [text substringWithRange:((NSRange){range.location+1, range.length-2})];
[attString replaceCharactersInRange:range withString:s];
[text replaceCharactersInRange:range withString:s];
}
}
//解析表情
NSString * regex_emoji = @"\\[[a-zA-Z0-9\\u4e00-\\u9fa5]+\\]"; // 表情的正则表达式
NSArray * array_emoji = [text componentsMatchedByRegex:regex_emoji];
NSLog(@"text = %@",text);
NSLog(@"array_emo = %@",array_emoji);
if ([array_emoji count]) {
printf("\n");
NSLog(@"解析表情:");
// 加载表情配置文件
NSString * filePath = [[NSBundle mainBundle] pathForResource:@"emotionImage" ofType:@"plist"];
NSDictionary * m_EmojiDic = [[NSDictionary alloc] initWithContentsOfFile:filePath];
for (NSString * str in array_emoji) {
NSLog(@"表情。。。。。。。。\t%@", str);
NSString * imgName = [m_EmojiDic objectForKey:str]; // 图片的名字
NSRange range = [text rangeOfString:str];
// 匹配表情字符串为空格
[attString replaceCharactersInRange:range withString:@" "];
[text replaceCharactersInRange:range withString:@" "];
NSLog(@"tex ===== %@",text);
range = NSMakeRange(range.location, 1);
//为图片设置CTRunDelegate,delegate决定留给图片的空间大小
CTRunDelegateCallbacks imageCallbacks;
imageCallbacks.version = kCTRunDelegateVersion1;
imageCallbacks.dealloc = RunDelegateDeallocCallback;
imageCallbacks.getAscent = RunDelegateGetAscentCallback;
imageCallbacks.getDescent = RunDelegateGetDescentCallback;
imageCallbacks.getWidth = RunDelegateGetWidthCallback;
CTRunDelegateRef runDelegate = CTRunDelegateCreate(&imageCallbacks, imgName);
[attString addAttribute:(NSString *)kCTRunDelegateAttributeName value:(id)runDelegate range:range];
CFRelease(runDelegate);
[attString addAttribute:@"imageName" value:imgName range:range];
}
}
// CTFramesetter 是使用 Core Text 绘制时最重要的类。它管理您的字体引用和文本绘制帧。 目前您需要了解 CTFramesetterCreateWithAttributedString 通过应用属性化文本创建 CTFramesetter。 这里在 framesetter 之后通过一个所选的文本范围(这里我们选择整个文本)与需要绘制到的矩形路径创建一个帧。
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attString);
CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, [attString length]), path, NULL);
CTFrameDraw(frame, context); // CTFrameDraw 将 frame 描述到设备上下文
// 绘制
CFArrayRef lines = CTFrameGetLines(frame);
CGPoint lineOrigins[CFArrayGetCount(lines)];
CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), lineOrigins);
//NSLog(@"line count = %ld",CFArrayGetCount(lines));
for (int i = 0; i < CFArrayGetCount(lines); i++) {
CTLineRef line = CFArrayGetValueAtIndex(lines, i);
CGFloat lineAscent;
CGFloat lineDescent;
CGFloat lineLeading;
CTLineGetTypographicBounds(line, &lineAscent, &lineDescent, &lineLeading);
// NSLog(@"ascent = %f,descent = %f,leading = %f",lineAscent,lineDescent,lineLeading);
CFArrayRef runs = CTLineGetGlyphRuns(line);
// NSLog(@"run count = %ld",CFArrayGetCount(runs));
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);
// NSLog(@"width = %f",runRect.size.width);
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 = CGSizeMake(image.size.width/2.0, image.size.height/2.0); //image.size;
imageDrawRect.origin.x = runRect.origin.x + lineOrigin.x;
imageDrawRect.origin.y = lineOrigin.y;
CGContextDrawImage(context, imageDrawRect, image.CGImage);
}
}
}
}
// 最后,释放所有使用的对象(要牢记:在你引用名字中有 “Create” 的函数时,不要忘记使用 CFRelease)
CFRelease(frame);
CFRelease(path);
CFRelease(framesetter);
CFRelease(helvetica);
CFRelease(helveticaBold);
CFRelease(helveticaItalic);
CFRelease(systemFont);
UIGraphicsPushContext(context);