379 lines
12 KiB
Objective-C
379 lines
12 KiB
Objective-C
//
|
|
// UMComMutiTextRun.m
|
|
// UMCommunity
|
|
//
|
|
// Created by umeng on 15/8/19.
|
|
// Copyright (c) 2015年 Umeng. All rights reserved.
|
|
//
|
|
|
|
#import "UMComMutiTextRun.h"
|
|
#import <CoreText/CoreText.h>
|
|
#import "UMComResouceDefines.h"
|
|
//#import <UMComDataStorage/UMComUser.h>
|
|
//#import <UMComDataStorage/UMComComment.h>
|
|
//#import <UMComDataStorage/UMComLike.h>
|
|
//#import <UMComDataStorage/UMComTopic.h>
|
|
//#import "UMComSyntaxHighlightTextStorage.h"
|
|
|
|
|
|
NSString * const UMComMutiTextRunAttributedName = @"UMComMutiTextRunAttributedName";
|
|
|
|
@implementation UMComMutiTextRun
|
|
|
|
/**
|
|
* 向字符串中添加相关Run类型属性
|
|
*/
|
|
- (void)decorateToAttributedString:(NSMutableAttributedString *)attributedString range:(NSRange)range
|
|
{
|
|
if (attributedString.length == 0) {
|
|
return;
|
|
}
|
|
[attributedString addAttribute:UMComMutiTextRunAttributedName value:self range:range];
|
|
[attributedString addAttribute:(NSString *)kCTForegroundColorAttributeName value:self.textColor range:range];
|
|
[attributedString addAttribute:(NSString *)kCTFontAttributeName value:self.font range:range];
|
|
// self.font = [attributedString attribute:NSFontAttributeName atIndex:0 longestEffectiveRange:nil inRange:range];
|
|
}
|
|
|
|
/**
|
|
* 绘制Run内容
|
|
*/
|
|
- (void)drawRunWithRect:(CGRect)rect
|
|
{
|
|
|
|
}
|
|
|
|
- (instancetype)initWithText:(NSString *)text
|
|
font:(UIFont *)font
|
|
textColor:(UIColor *)color
|
|
range:(NSRange)range
|
|
{
|
|
self = [self init];
|
|
if (self) {
|
|
self.text = text;
|
|
if ([font isKindOfClass:[UIFont class]]) {
|
|
self.font = font;
|
|
}
|
|
if ([color isKindOfClass:[UIColor class]]) {
|
|
self.textColor = color;
|
|
}
|
|
self.range = range;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (instancetype)init
|
|
{
|
|
self = [super init];
|
|
if (self) {
|
|
self.font = [UIFont systemFontOfSize:15];
|
|
self.textColor = [UIColor blueColor];
|
|
self.drawSelf = NO;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
|
|
@end
|
|
|
|
|
|
@implementation UMComMutiTextRunClickUser
|
|
|
|
- (void)decorateToAttributedString:(NSMutableAttributedString *)attributedString range:(NSRange)range
|
|
{
|
|
[super decorateToAttributedString:attributedString range:range];
|
|
// [attributedString addAttribute:(NSString *)kCTForegroundColorAttributeName value:self.textColor range:range];
|
|
}
|
|
|
|
|
|
+ (NSArray *)runsWithAttributedString:(NSMutableAttributedString *)attributedString
|
|
font:(UIFont *)font
|
|
textColor:(UIColor *)color
|
|
checkWords:(NSArray *)checkWords
|
|
{
|
|
|
|
NSString *string = attributedString.string;
|
|
NSMutableArray *array = [NSMutableArray array];
|
|
|
|
for (NSString *userName in checkWords) {
|
|
NSString *userNameRegulaStr = UserRulerString;
|
|
NSRegularExpression *regular = [NSRegularExpression regularExpressionWithPattern:userNameRegulaStr options:NSRegularExpressionDotMatchesLineSeparators error:nil];
|
|
NSInteger matchCount = [regular numberOfMatchesInString:userName options:0 range:NSMakeRange(0, [userName length])];
|
|
if (matchCount > 0) {
|
|
NSRegularExpression *userNameRegular = [NSRegularExpression regularExpressionWithPattern:userName options:NSRegularExpressionDotMatchesLineSeparators error:nil];
|
|
NSArray *matchs = [userNameRegular matchesInString:string
|
|
options:0
|
|
range:NSMakeRange(0, [string length])];
|
|
for (NSTextCheckingResult *match in matchs) {
|
|
UMComMutiTextRunClickUser *run = [[UMComMutiTextRunClickUser alloc] initWithText:userName font:font textColor:color range:match.range];
|
|
[run decorateToAttributedString:attributedString range:match.range];
|
|
[array addObject:run];
|
|
}
|
|
}
|
|
}
|
|
return array;
|
|
}
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation UMComMutiTextRunTopic
|
|
|
|
/**
|
|
* 向字符串中添加相关Run类型属性
|
|
*/
|
|
- (void)decorateToAttributedString:(NSMutableAttributedString *)attributedString range:(NSRange)range
|
|
{
|
|
if (attributedString.length == 0) {
|
|
return;
|
|
}
|
|
[super decorateToAttributedString:attributedString range:range];
|
|
}
|
|
|
|
|
|
+ (NSArray *)runsWithAttributedString:(NSMutableAttributedString *)attributedString
|
|
font:(UIFont *)font
|
|
textColor:(UIColor *)color
|
|
checkWords:(NSArray *)checkWords
|
|
{
|
|
NSString *string = attributedString.string;
|
|
NSMutableArray *array = [NSMutableArray array];
|
|
|
|
for (NSString *topicName in checkWords) {
|
|
NSString *topicNameRegulaStr = TopicRulerString;
|
|
NSRegularExpression *regular = [NSRegularExpression regularExpressionWithPattern:topicNameRegulaStr options:NSRegularExpressionDotMatchesLineSeparators error:nil];
|
|
NSInteger matchCount = [regular numberOfMatchesInString:topicName options:0 range:NSMakeRange(0, [topicName length])];
|
|
if (matchCount > 0) {
|
|
NSRegularExpression *topicNameRegular = [NSRegularExpression regularExpressionWithPattern:topicName options:NSRegularExpressionDotMatchesLineSeparators error:nil];
|
|
NSArray *matchs = [topicNameRegular matchesInString:string
|
|
options:0
|
|
range:NSMakeRange(0, [string length])];
|
|
for (NSTextCheckingResult *match in matchs) {
|
|
UMComMutiTextRunTopic *run = [[UMComMutiTextRunTopic alloc] initWithText:topicName font:font textColor:color range:match.range];
|
|
[run decorateToAttributedString:attributedString range:match.range];
|
|
[array addObject:run];
|
|
}
|
|
}
|
|
|
|
}
|
|
return array;
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation UMComMutiTextRunURL
|
|
|
|
/**
|
|
* 向字符串中添加相关Run类型属性
|
|
*/
|
|
- (void)decorateToAttributedString:(NSMutableAttributedString *)attributedString range:(NSRange)range
|
|
{
|
|
if (attributedString.length == 0) {
|
|
return;
|
|
}
|
|
[super decorateToAttributedString:attributedString range:range];
|
|
// [attributedString addAttribute:(NSString *)kCTForegroundColorAttributeName value:self.textColor range:range];
|
|
}
|
|
|
|
|
|
+ (NSArray *)runsWithAttributedString:(NSMutableAttributedString *)attributedString
|
|
font:(UIFont *)font
|
|
textColor:(UIColor *)color
|
|
{
|
|
NSString *string = attributedString.string;
|
|
NSMutableArray *array = [NSMutableArray array];
|
|
|
|
NSError *error = nil;
|
|
NSString *regulaStr = @"((http[s]{0,1}|ftp)://[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\,\\.\\-~!@#$%^&*+?:_/=<>]*)?)|(www.[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\,\\.\\-~!@#$%^&*+?:_/=<>]*)?)";
|
|
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regulaStr
|
|
options:NSRegularExpressionCaseInsensitive
|
|
error:&error];
|
|
if (error == nil)
|
|
{
|
|
NSArray *arrayOfAllMatches = [regex matchesInString:string
|
|
options:0
|
|
range:NSMakeRange(0, [string length])];
|
|
|
|
for (NSTextCheckingResult *match in arrayOfAllMatches)
|
|
{
|
|
NSString* substringForMatch = [string substringWithRange:match.range];
|
|
UMComMutiTextRunURL *run = [[UMComMutiTextRunURL alloc] initWithText:substringForMatch font:font textColor:color range:match.range];
|
|
[run decorateToAttributedString:attributedString range:match.range];
|
|
[array addObject:run ];
|
|
}
|
|
}
|
|
return array;
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
|
|
@implementation UMComMutiTextRunDelegate
|
|
|
|
/**
|
|
* 向字符串中添加相关Run类型属性
|
|
*/
|
|
- (void)decorateToAttributedString:(NSMutableAttributedString *)attributedString range:(NSRange)range
|
|
{
|
|
[super decorateToAttributedString:attributedString range:range];
|
|
|
|
CTRunDelegateCallbacks callbacks;
|
|
callbacks.version = kCTRunDelegateVersion1;
|
|
callbacks.dealloc = UMComMutiTextRunDelegateDeallocCallback;
|
|
callbacks.getAscent = UMComMutiTextRunDelegateGetAscentCallback;
|
|
callbacks.getDescent = UMComMutiTextRunDelegateGetDescentCallback;
|
|
callbacks.getWidth = UMComMutiTextRunDelegateGetWidthCallback;
|
|
|
|
CTRunDelegateRef runDelegate = CTRunDelegateCreate(&callbacks, (__bridge void*)self);
|
|
[attributedString addAttribute:(NSString *)kCTRunDelegateAttributeName value:(__bridge id)runDelegate range:range];
|
|
CFRelease(runDelegate);
|
|
|
|
[attributedString addAttribute:(NSString *)kCTForegroundColorAttributeName value:(id)[UIColor clearColor].CGColor range:range];
|
|
}
|
|
|
|
#pragma mark - RunCallback
|
|
|
|
- (void)mutiTextRunDealloc
|
|
{
|
|
|
|
}
|
|
|
|
- (CGFloat)mutiTextRunGetAscent
|
|
{
|
|
return self.font.ascender;
|
|
}
|
|
|
|
- (CGFloat)mutiTextRunGetDescent
|
|
{
|
|
return self.font.descender;
|
|
}
|
|
|
|
- (CGFloat)mutiTextRunGetWidth
|
|
{
|
|
return self.font.ascender - self.font.descender;
|
|
}
|
|
|
|
#pragma mark - RunDelegateCallback
|
|
|
|
void UMComMutiTextRunDelegateDeallocCallback(void *refCon)
|
|
{
|
|
// UMComMutiTextRunDelegate *run =(__bridge UMComMutiTextRunDelegate *) refCon;
|
|
//
|
|
// [run mutiTextRunDealloc];
|
|
}
|
|
|
|
//--上行高度
|
|
CGFloat UMComMutiTextRunDelegateGetAscentCallback(void *refCon)
|
|
{
|
|
UMComMutiTextRunDelegate *run =(__bridge UMComMutiTextRunDelegate *) refCon;
|
|
|
|
return [run mutiTextRunGetAscent];
|
|
}
|
|
|
|
//--下行高度
|
|
CGFloat UMComMutiTextRunDelegateGetDescentCallback(void *refCon)
|
|
{
|
|
UMComMutiTextRunDelegate *run =(__bridge UMComMutiTextRunDelegate *) refCon;
|
|
|
|
return [run mutiTextRunGetDescent];
|
|
}
|
|
|
|
//-- 宽
|
|
CGFloat UMComMutiTextRunDelegateGetWidthCallback(void *refCon)
|
|
{
|
|
UMComMutiTextRunDelegate *run =(__bridge UMComMutiTextRunDelegate *) refCon;
|
|
|
|
return [run mutiTextRunGetWidth];
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation UMComMutiTextRunEmoji
|
|
|
|
/**
|
|
* 返回表情数组
|
|
*/
|
|
+ (NSArray *) emojiStringArray
|
|
{
|
|
return [NSArray arrayWithObjects:@"[smile]",@"[cry]",@"[hei]",nil];
|
|
}
|
|
|
|
+ (NSArray *)runsForAttributedString:(NSMutableAttributedString *)attributedString
|
|
{
|
|
NSString *markL = @"[";
|
|
NSString *markR = @"]";
|
|
NSString *string = attributedString.string;
|
|
NSMutableArray *array = [NSMutableArray array];
|
|
NSMutableArray *stack = [NSMutableArray array];
|
|
|
|
for (int i = 0; i < string.length; i++)
|
|
{
|
|
NSString *s = [string substringWithRange:NSMakeRange(i, 1)];
|
|
|
|
if (([s isEqualToString:markL]) || ((stack.count > 0) && [stack[0] isEqualToString:markL]))
|
|
{
|
|
if (([s isEqualToString:markL]) && ((stack.count > 0) && [stack[0] isEqualToString:markL]))
|
|
{
|
|
[stack removeAllObjects];
|
|
}
|
|
|
|
[stack addObject:s];
|
|
|
|
if ([s isEqualToString:markR] || (i == string.length - 1))
|
|
{
|
|
NSMutableString *emojiStr = [[NSMutableString alloc] init];
|
|
for (NSString *c in stack)
|
|
{
|
|
[emojiStr appendString:c];
|
|
}
|
|
|
|
if ([[UMComMutiTextRunEmoji emojiStringArray] containsObject:emojiStr])
|
|
{
|
|
NSRange range = NSMakeRange(i + 1 - emojiStr.length, emojiStr.length);
|
|
|
|
[attributedString replaceCharactersInRange:range withString:@" "];
|
|
|
|
UMComMutiTextRunEmoji *run = [[UMComMutiTextRunEmoji alloc] init];
|
|
run.range = NSMakeRange(i + 1 - emojiStr.length, 1);
|
|
run.text = emojiStr;
|
|
run.drawSelf = YES;
|
|
[run decorateToAttributedString:attributedString range:run.range];
|
|
[array addObject:run];
|
|
}
|
|
|
|
[stack removeAllObjects];
|
|
}
|
|
}
|
|
}
|
|
|
|
return array;
|
|
}
|
|
|
|
/**
|
|
* 绘制Run内容
|
|
*/
|
|
- (void)drawRunWithRect:(CGRect)rect
|
|
{
|
|
CGContextRef context = UIGraphicsGetCurrentContext();
|
|
|
|
NSString *emojiString = [NSString stringWithFormat:@"%@.png",self.text];
|
|
|
|
UIImage *image = UMComImageWithImageName(emojiString);
|
|
if (image)
|
|
{
|
|
CGContextDrawImage(context, rect, image.CGImage);
|
|
}
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|