//
//  The MIT License (MIT)
//  Copyright (c) 2016 Wayne Liu <liuweiself@126.com>
//
//  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//銆€銆€The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//
//
//  LWTextLayout.m
//  LWAsyncLayerDemo
//
//  Created by 鍒樺井 on 16/2/1.
//  Copyright 漏 2016骞?Wayne Liu. All rights reserved.
//  https://github.com/waynezxcv/LWAsyncDisplayView
//  See LICENSE for this sample鈥檚 licensing information
//

#import "LWTextLayout.h"


static CGFloat descentCallback(void *ref){
    return 0;
}

static CGFloat ascentCallback(void *ref){
    NSString* callback = (__bridge NSString *)(ref);
    NSData* jsonData = [callback dataUsingEncoding:NSUTF8StringEncoding];
    NSError* err;
    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData
                                                        options:NSJSONReadingMutableContainers
                                                          error:&err];
    return [[dic objectForKey:@"height"] floatValue];
}

static CGFloat widthCallback(void* ref){
    NSString* callback = (__bridge NSString *)(ref);
    NSData* jsonData = [callback dataUsingEncoding:NSUTF8StringEncoding];
    NSError* err;
    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData
                                                        options:NSJSONReadingMutableContainers
                                                          error:&err];
    return [[dic objectForKey:@"width"] floatValue];
}


@interface LWTextLayout ()


@end

@implementation LWTextLayout

#pragma mark - Initialization

- (NSUInteger)hash {
    NSUInteger value = 0;
    value ^= [_attributedText hash];
    return value;
}

- (BOOL)isEqual:(id)object {
    if (self == object) return YES;
    if (![object isMemberOfClass:self.class]) return NO;
    id selfValue = _attributedText;
    LWTextLayout* other = (LWTextLayout *)object;
    id modelValue = other.attributedText;
    BOOL valuesEqual = ((selfValue == nil && modelValue == nil) || [selfValue isEqual:modelValue]);
    if (!valuesEqual) return NO;
    return YES;
}


- (id)init {
    self = [super init];
    if (self) {
        self.text = nil;
        self.attributedText = nil;
        self.textColor = [UIColor blackColor];
        self.font = [UIFont systemFontOfSize:14.0f];
        self.textAlignment = NSTextAlignmentLeft;
        self.veriticalAlignment = LWVerticalAlignmentCenter;
        self.lineBreakMode = NSLineBreakByWordWrapping;
        self.boundsRect = CGRectZero;
        self.linespace = 2.0f;
        self.characterSpacing = 1.0f;
        self.underlineStyle = NSUnderlineStyleNone;
        self.widthToFit = YES;
    }
    return self;
}

- (void)creatCTFrameRef {
    if (_attributedText == nil) {
        return ;
    }
    if (_textHeight > 0) {
        return ;
    }
    CTFramesetterRef ctFrameSetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)_attributedText);
    CGSize suggestSize = CTFramesetterSuggestFrameSizeWithConstraints(ctFrameSetter,
                                                                      CFRangeMake(0, _attributedText.length),
                                                                      NULL,
                                                                      CGSizeMake(self.boundsRect.size.width, CGFLOAT_MAX),
                                                                      NULL);
    _textHeight = suggestSize.height;
    _textWidth = suggestSize.width;
    if (self.isWidthToFit) {
        self.boundsRect = CGRectMake(self.boundsRect.origin.x, self.boundsRect.origin.y, suggestSize.width, suggestSize.height);
    } else {
        self.boundsRect = CGRectMake(self.boundsRect.origin.x, self.boundsRect.origin.y, self.boundsRect.size.width, suggestSize.height);
    }
    CGMutablePathRef textPath = CGPathCreateMutable();
    CGPathAddRect(textPath, NULL, self.boundsRect);
    _frame = CTFramesetterCreateFrame(ctFrameSetter, CFRangeMake(0, 0), textPath, NULL);
    CFRelease(ctFrameSetter);
    CFRelease(textPath);
}

#pragma mark - Draw
- (void)drawInContext:(CGContextRef)context {
    @autoreleasepool {
        CGContextSaveGState(context);
        CGContextSetTextMatrix(context,CGAffineTransformIdentity);
        CGContextTranslateCTM(context, self.boundsRect.origin.x, self.boundsRect.origin.y);
        CGContextTranslateCTM(context, 0, self.boundsRect.size.height);
        CGContextScaleCTM(context, 1.0, -1.0);
        CGContextTranslateCTM(context, - self.boundsRect.origin.x, -self.boundsRect.origin.y);
        CTFrameDraw(self.frame, context);
        CGContextRestoreGState(context);
        if (self.attachs.count == 0) {
            return;
        }
        for (NSInteger i = 0; i < self.attachs.count; i ++) {
            LWTextAttach* attach = self.attachs[i];
            CGContextSaveGState(context);
            CGContextTranslateCTM(context, self.boundsRect.origin.x, self.boundsRect.origin.y);
            CGContextTranslateCTM(context, 0, self.boundsRect.size.height);
            CGContextScaleCTM(context, 1.0, -1.0);
            CGContextTranslateCTM(context, - self.boundsRect.origin.x, -self.boundsRect.origin.y);
            CGContextDrawImage(context,attach.imagePosition,attach.image.CGImage);
            CGContextRestoreGState(context);
        }
    }
}

#pragma mark - Add Link

- (void)addLinkWithData:(id)data
                inRange:(NSRange)range
              linkColor:(UIColor *)linkColor
         highLightColor:(UIColor *)highLightColor
         UnderLineStyle:(NSUnderlineStyle)underlineStyle {
    if (_attributedText == nil || _attributedText.length == 0) {
        return;
    }
    [self _resetFrameRef];
    if (linkColor != nil) {
        [self _mutableAttributedString:_attributedText addAttributesWithTextColor:linkColor
                               inRange:range];
    }
    if (underlineStyle != NSUnderlineStyleNone) {
        [self _mutableAttributedString:_attributedText addAttributesWithUnderlineStyle:underlineStyle
                               inRange:range];
    }
    if (data != nil) {
        [self _mutableAttributedString:_attributedText addLinkAttributesNameWithValue:data inRange:range];
    }
    [self creatCTFrameRef];
}

#pragma mark - Add Image

- (void)replaceTextWithImage:(UIImage *)image
                     inRange:(NSRange)range {
    if (_attributedText == nil || _attributedText.length == 0) {
        return;
    }
    [self _resetFrameRef];
    CGFloat width = image.size.width;
    CGFloat height = image.size.height;
    NSAttributedString* placeholder = [self _placeHolderStringWithJson:[self _jsonWithImageWith:width
                                                                                    imageHeight:height]];
    [_attributedText replaceCharactersInRange:range withAttributedString:placeholder];
    [self creatCTFrameRef];
    LWTextAttach* attach = [[LWTextAttach alloc] init];
    attach.image = image;
    [self _setupImageAttachPositionWithAttach:attach];
    [self.attachs addObject:attach];
}

- (void)replaceTextWithImageURL:(NSURL *)URL inRange:(NSRange)range {

}

- (void)_setupImageAttachPositionWithAttach:(LWTextAttach *)attach {
    NSArray* lines = (NSArray *)CTFrameGetLines(_frame);
    NSUInteger lineCount = [lines count];
    CGPoint lineOrigins[lineCount];
    CTFrameGetLineOrigins(_frame, CFRangeMake(0, 0), lineOrigins);
    for (int i = 0; i < lineCount; i++) {
        if (attach == nil) {
            break;
        }
        CTLineRef line = (__bridge CTLineRef)lines[i];
        NSArray* runObjArray = (NSArray *)CTLineGetGlyphRuns(line);
        for (id runObj in runObjArray) {
            CTRunRef run = (__bridge CTRunRef)runObj;
            NSDictionary* runAttributes = (NSDictionary *)CTRunGetAttributes(run);
            CTRunDelegateRef delegate = (__bridge CTRunDelegateRef)[runAttributes valueForKey:(id)kCTRunDelegateAttributeName];
            if (delegate == nil) {
                continue;
            }

            CGRect runBounds;
            CGFloat ascent;
            CGFloat descent;
            runBounds.size.width = CTRunGetTypographicBounds(run, CFRangeMake(0, 0), &ascent, &descent, NULL);
            runBounds.size.height = ascent + descent;

            CGFloat xOffset = CTLineGetOffsetForStringIndex(line, CTRunGetStringRange(run).location, NULL);
            runBounds.origin.x = lineOrigins[i].x + xOffset;
            runBounds.origin.y = lineOrigins[i].y - descent;

            CGPathRef pathRef = CTFrameGetPath(_frame);
            CGRect colRect = CGPathGetBoundingBox(pathRef);
            CGRect delegateRect = CGRectMake(runBounds.origin.x + colRect.origin.x,
                                             runBounds.origin.y + colRect.origin.y,
                                             runBounds.size.width,
                                             runBounds.size.height);
            attach.imagePosition = delegateRect;
        }
    }
}

- (NSString *)_jsonWithImageWith:(CGFloat)width
                     imageHeight:(CGFloat)height {
    NSString* jsonString = [NSString stringWithFormat:@"{\"width\":\"%f\",\"height\":\"%f\"}",width,height];
    return jsonString;
}

- (NSAttributedString *)_placeHolderStringWithJson:(NSString *)json {
    CTRunDelegateCallbacks callbacks;
    memset(&callbacks, 0, sizeof(CTRunDelegateCallbacks));
    callbacks.version = kCTRunDelegateVersion1;
    callbacks.getAscent = ascentCallback;
    callbacks.getDescent = descentCallback;
    callbacks.getWidth = widthCallback;
    CTRunDelegateRef delegate = CTRunDelegateCreate(&callbacks, (__bridge void *)(json));
    unichar objectReplacementChar = 0xFFFC;
    NSString* content = [NSString stringWithCharacters:&objectReplacementChar length:1];
    NSMutableAttributedString* space = [[NSMutableAttributedString alloc] initWithString:content];
    //涓篘SAttributedString璁剧疆key涓簁CTRunDelegateAttributeName鍊间负delegate鐨勫睘鎬?    CFAttributedStringSetAttribute((CFMutableAttributedStringRef)space, CFRangeMake(0, content.length),
                                   kCTRunDelegateAttributeName, delegate);
    CFRelease(delegate);
    return space;
}


#pragma mark - Reset
- (void)_resetAttachs {
    [self.attachs removeAllObjects];
}

- (void)_resetFrameRef {
    if (_frame) {
        CFRelease(_frame);
        _frame = nil;
    }
    _textHeight = 0;
}

#pragma mark - Getter

- (NSMutableArray *)attachs {
    if (!_attachs) {
        _attachs = [[NSMutableArray alloc] init];
    }
    return _attachs;
}

- (NSString *)text {
    return _attributedText.string;
}

#pragma mark - Setter

- (void)setText:(NSString *)text {
    [self _resetAttachs];
    [self _resetFrameRef];
    _attributedText = [self _createAttributedStringWithText:text];

}

- (void)setAttributedText:(NSAttributedString *)attributedText {
    [self _resetAttachs];
    [self _resetFrameRef];
    if (attributedText == nil) {
        _attributedText = [[NSMutableAttributedString alloc]init];
    }else if ([attributedText isKindOfClass:[NSMutableAttributedString class]]) {
        _attributedText = (NSMutableAttributedString *)attributedText;
    }else {
        _attributedText = [[NSMutableAttributedString alloc]initWithAttributedString:attributedText];
    }
    [self creatCTFrameRef];
}

- (void)setTextColor:(UIColor *)textColor {
    if (textColor && _textColor != textColor){
        _textColor = textColor;
        [self _mutableAttributedString:_attributedText
            addAttributesWithTextColor:_textColor
                               inRange:NSMakeRange(0, _attributedText.length)];
        [self _resetFrameRef];
    }
}

- (void)setFont:(UIFont *)font {
    if (font && _font != font){
        _font = font;
        [self _mutableAttributedString:_attributedText
                 addAttributesWithFont:_font
                               inRange:NSMakeRange(0, _attributedText.length)];
        [self _resetFrameRef];
    }
}

- (void)setCharacterSpacing:(unichar)characterSpacing {
    if (characterSpacing >= 0 && _characterSpacing != characterSpacing) {
        _characterSpacing = characterSpacing;
        [self _mutableAttributedString:_attributedText
     addAttributesWithCharacterSpacing:characterSpacing
                               inRange:NSMakeRange(0, _attributedText.length)];
        [self _resetFrameRef];
    }
}

- (void)setLinespace:(CGFloat)linespace {
    if (_linespace != linespace) {
        _linespace = linespace;
        [self _mutableAttributedString:_attributedText
          addAttributesWithLineSpacing:_linespace
                         textAlignment:_textAlignment
                         lineBreakMode:_lineBreakMode
                               inRange:NSMakeRange(0, _attributedText.length)];
        [self _resetFrameRef];
    }
}

- (void)setTextAlignment:(NSTextAlignment)textAlignment {
    if (_textAlignment != textAlignment) {
        _textAlignment = textAlignment;
        self.widthToFit = NO;
        [self _mutableAttributedString:_attributedText
          addAttributesWithLineSpacing:_linespace
                         textAlignment:_textAlignment
                         lineBreakMode:_lineBreakMode
                               inRange:NSMakeRange(0, _attributedText.length)];
        [self _resetFrameRef];
    }
}

- (void)setLineBreakMode:(NSLineBreakMode)lineBreakMode {
    if (_lineBreakMode != lineBreakMode) {
        _lineBreakMode = lineBreakMode;
        [self _mutableAttributedString:_attributedText
          addAttributesWithLineSpacing:_linespace
                         textAlignment:_textAlignment
                         lineBreakMode:_lineBreakMode
                               inRange:NSMakeRange(0, _attributedText.length)];
        [self _resetFrameRef];
    }
}

- (void)dealloc {
    if (self.frame) {
        CFRelease(self.frame);
    }
}

#pragma mark - Attributes

/**
 *  鍒涘缓灞炴€у瓧绗︿覆
 *
 */
- (NSMutableAttributedString *)_createAttributedStringWithText:(NSString *)text {
    if (text.length <= 0) {
        return [[NSMutableAttributedString alloc]init];
    }
    // 鍒涘缓灞炴€ф枃鏈?    NSMutableAttributedString* attbutedString = [[NSMutableAttributedString alloc]initWithString:text];
    // 娣诲姞棰滆壊灞炴€?    [self _mutableAttributedString:attbutedString
        addAttributesWithTextColor:_textColor
                           inRange:NSMakeRange(0, text.length)];
    // 娣诲姞瀛椾綋灞炴€?    [self _mutableAttributedString:attbutedString
             addAttributesWithFont:_font
                           inRange:NSMakeRange(0, text.length)];
    // 娣诲姞鏂囨湰娈佃惤鏍峰紡
    [self _mutableAttributedString:attbutedString addAttributesWithLineSpacing:_linespace
                     textAlignment:_textAlignment
                     lineBreakMode:_lineBreakMode
                           inRange:NSMakeRange(0, text.length)];
    //娣诲姞涓嬪垝绾垮紡鏍?    [self _mutableAttributedString:attbutedString addAttributesWithUnderlineStyle:_underlineStyle
                           inRange:NSMakeRange(0, text.length)];
    return attbutedString;
}


/**
 *  娣诲姞Link灞炴€? *
 */

- (void)_mutableAttributedString:(NSMutableAttributedString *)attributedString
  addLinkAttributesNameWithValue:(id)value
                         inRange:(NSRange)range {

    if (attributedString == nil) {
        return;
    }
    if (value != nil) {
        [attributedString addAttribute:kLWTextLinkAttributedName
                                 value:value
                                 range:range];
    }
}

/**
 *  娣诲姞涓嬪垝绾垮紡鏍? *
 */
- (void)_mutableAttributedString:(NSMutableAttributedString *)attributedString
 addAttributesWithUnderlineStyle:(NSUnderlineStyle)underlineStyle
                         inRange:(NSRange)range {
    if (attributedString == nil) {
        return;
    }
    [attributedString removeAttribute:(NSString *)kCTUnderlineStyleAttributeName range:range];
    CTUnderlineStyle ctUnderlineStyle = _coreTextUnderlineStyleFromNSUnderlineStyle(underlineStyle);
    if (ctUnderlineStyle != kCTUnderlineStyleNone) {
        [attributedString addAttribute:(NSString *)kCTUnderlineStyleAttributeName
                                 value:[NSNumber numberWithInt:(ctUnderlineStyle)]
                                 range:range];
    }
}

/**
 * 娣诲姞娈佃惤鐩稿叧灞炴€? *
 */
- (void)_mutableAttributedString:(NSMutableAttributedString *)attributedString
    addAttributesWithLineSpacing:(CGFloat)linespacing
                   textAlignment:(NSTextAlignment)textAlignment
                   lineBreakMode:(NSLineBreakMode)lineBreakMode
                         inRange:(NSRange)range {
    if (attributedString == nil) {
        return;
    }
    [attributedString removeAttribute:(NSString *)kCTParagraphStyleAttributeName
                                range:range];
    //鏂囧瓧瀵归綈鏂瑰紡
    CTTextAlignment ctTextAlignment = _coreTextAlignmentFromNSTextAlignment(textAlignment);
    //鎹㈣鏂瑰紡
    CTLineBreakMode ctLineBreakMode = _coreTextLineBreakModeFromNSLineBreakModel(lineBreakMode);
    //娈佃惤寮忔牱
    CTParagraphStyleSetting theSettings[] = {
        { kCTParagraphStyleSpecifierLineSpacingAdjustment, sizeof(CGFloat), &linespacing},
        { kCTParagraphStyleSpecifierAlignment, sizeof(ctTextAlignment), &ctTextAlignment },
        { kCTParagraphStyleSpecifierLineBreakMode,sizeof(CTLineBreakMode),&ctLineBreakMode }
    };
    CTParagraphStyleRef paragraphRef = CTParagraphStyleCreate(theSettings, sizeof(theSettings) / sizeof(theSettings[0]));
    if (paragraphRef != nil) {
        [attributedString addAttribute:(id)kCTParagraphStyleAttributeName value:(__bridge id)paragraphRef range:range];
        CFRelease(paragraphRef);
    }
}

/**
 * 娣诲姞瀛椾綋灞炴€? *
 */
- (void)_mutableAttributedString:(NSMutableAttributedString *)attributedString
           addAttributesWithFont:(UIFont *)font
                         inRange:(NSRange)range {
    if (attributedString == nil || font == nil) {
        return;
    }
    [attributedString removeAttribute:(NSString *)kCTFontAttributeName range:range];
    CTFontRef fontRef = CTFontCreateWithName((CFStringRef)font.fontName, font.pointSize, nil);
    if (fontRef != nil) {
        [attributedString addAttribute:(NSString *)kCTFontAttributeName value:(__bridge id)fontRef range:range];
        CFRelease(fontRef);
    }
}

/**
 *  娣诲姞鏂囧瓧棰滆壊灞炴€? *
 */
- (void)_mutableAttributedString:(NSMutableAttributedString *)attributedString
      addAttributesWithTextColor:(UIColor *)textColor
                         inRange:(NSRange)range {
    if (attributedString == nil || textColor == nil) {
        return;
    }
    [attributedString removeAttribute:(NSString *)kCTForegroundColorAttributeName range:range];
    [attributedString addAttribute:(NSString *)kCTForegroundColorAttributeName value:(id)textColor.CGColor range:range];
}


/**
 *  娣诲姞瀛楅棿璺濆睘鎬? *
 */
- (void)_mutableAttributedString:(NSMutableAttributedString *)attributedString
addAttributesWithCharacterSpacing:(unichar)characterSpacing
                         inRange:(NSRange)range {
    if (attributedString == nil) {
        return;
    }
    [attributedString removeAttribute:(NSString *)kCTKernAttributeName range:range];

    CFNumberRef charSpacingNum =  CFNumberCreate(kCFAllocatorDefault,kCFNumberSInt8Type,&characterSpacing);
    if (charSpacingNum != nil) {
        [attributedString addAttribute:(NSString *)kCTKernAttributeName value:(__bridge id)charSpacingNum range:range];
        CFRelease(charSpacingNum);
    }
}

#pragma mark - Private

/*
 kCTParagraphStyleSpecifierAlignment = 0,                 //瀵归綈灞炴€?
 kCTParagraphStyleSpecifierFirstLineHeadIndent = 1,       //棣栬缂╄繘
 kCTParagraphStyleSpecifierHeadIndent = 2,                //娈靛ご缂╄繘
 kCTParagraphStyleSpecifierTailIndent = 3,                //娈靛熬缂╄繘
 kCTParagraphStyleSpecifierTabStops = 4,                  //鍒惰〃绗︽ā寮? kCTParagraphStyleSpecifierDefaultTabInterval = 5,        //榛樿tab闂撮殧
 kCTParagraphStyleSpecifierLineBreakMode = 6,             //鎹㈣妯″紡*
 kCTParagraphStyleSpecifierLineHeightMultiple = 7,        //澶氳楂? kCTParagraphStyleSpecifierMaximumLineHeight = 8,         //鏈€澶ц楂? kCTParagraphStyleSpecifierMinimumLineHeight = 9,         //鏈€灏忚楂? kCTParagraphStyleSpecifierLineSpacing = 10,              //琛岃窛*
 kCTParagraphStyleSpecifierParagraphSpacing = 11,         //娈佃惤闂磋窛鍦ㄦ鐨勬湭灏撅紙Bottom锛夊姞涓婇棿闅旓紝杩欎釜鍊间负璐熸暟銆? kCTParagraphStyleSpecifierParagraphSpacingBefore = 12,   //娈佃惤鍓嶉棿璺?鍦ㄤ竴涓钀界殑鍓嶉潰鍔犱笂闂撮殧銆俆OP
 kCTParagraphStyleSpecifierBaseWritingDirection = 13,     //鍩烘湰涔﹀啓鏂瑰悜
 kCTParagraphStyleSpecifierMaximumLineSpacing = 14,       //鏈€澶ц璺? kCTParagraphStyleSpecifierMinimumLineSpacing = 15,       //鏈€灏忚璺? kCTParagraphStyleSpecifierLineSpacingAdjustment = 16,    //琛岃窛璋冩暣
 kCTParagraphStyleSpecifierCount = 17,
 */
/********************************* ParagraphStyle *********************************************/

/**
 *  灏哊STextAlignment杞崲鎴怌TTextAlignment
 *
 */
static CTTextAlignment _coreTextAlignmentFromNSTextAlignment(NSTextAlignment alignment) {
    switch (alignment) {
        case NSTextAlignmentLeft: return kCTTextAlignmentLeft;
        case NSTextAlignmentCenter: return kCTTextAlignmentCenter;
        case NSTextAlignmentRight: return kCTTextAlignmentRight;
        case NSTextAlignmentJustified : return kCTTextAlignmentJustified;
        case NSTextAlignmentNatural: return kCTTextAlignmentNatural;
        default: return kCTTextAlignmentLeft;
    }
}

/*
 kCTLineBreakByWordWrapping = 0,        //鍑虹幇鍦ㄥ崟璇嶈竟鐣屾椂璧蜂綔鐢紝濡傛灉璇ュ崟璇嶄笉鍦ㄨ兘鍦ㄤ竴琛岄噷鏄剧ず鏃讹紝鏁翠綋鎹㈣銆傛涓烘鐨勯粯璁ゅ€笺€? kCTLineBreakByCharWrapping = 1,        //褰撲竴琛屼腑鏈€鍚庝竴涓綅缃殑澶у皬涓嶈兘瀹圭撼涓€涓瓧绗︽椂锛屾墠杩涜鎹㈣銆? kCTLineBreakByClipping = 2,            //瓒呭嚭鐢诲竷杈圭紭閮ㄤ唤灏嗚鎴櫎銆? kCTLineBreakByTruncatingHead = 3,      //鎴櫎鍓嶉潰閮ㄤ唤锛屽彧淇濈暀鍚庨潰涓€琛岀殑鏁版嵁銆傚墠閮ㄤ唤浠?..浠f浛銆? kCTLineBreakByTruncatingTail = 4,      //鎴櫎鍚庨潰閮ㄤ唤锛屽彧淇濈暀鍓嶉潰涓€琛岀殑鏁版嵁锛屽悗閮ㄤ唤浠?..浠f浛銆? kCTLineBreakByTruncatingMiddle = 5     //鍦ㄤ竴琛屼腑鏄剧ず娈垫枃瀛楃殑鍓嶉潰鍜屽悗闈㈡枃瀛楋紝涓棿鏂囧瓧浣跨敤...浠f浛銆? */
/**
 *  灏哊SLineBreakMode杞崲鎴怌TLineBreakMode
 *
 */
static CTLineBreakMode _coreTextLineBreakModeFromNSLineBreakModel(NSLineBreakMode lineBreakMode) {
    switch (lineBreakMode) {
        case NSLineBreakByWordWrapping: return kCTLineBreakByWordWrapping;
        case NSLineBreakByCharWrapping: return kCTLineBreakByCharWrapping;
        case NSLineBreakByClipping: return kCTLineBreakByClipping;
        case NSLineBreakByTruncatingHead: return kCTLineBreakByTruncatingHead;
        case NSLineBreakByTruncatingTail: return kCTLineBreakByTruncatingTail;
        case NSLineBreakByTruncatingMiddle: return kCTLineBreakByTruncatingMiddle;
    }
}

//NSUnderlineStyleNone = 0x00,
//NSUnderlineStyleSingle = 0x01,
//NSUnderlineStyleThick NS_ENUM_AVAILABLE(10_0, 7_0) = 0x02,
//NSUnderlineStyleDouble NS_ENUM_AVAILABLE(10_0, 7_0) = 0x09,
//NSUnderlinePatternSolid NS_ENUM_AVAILABLE(10_0, 7_0) = 0x0000,
//NSUnderlinePatternDot NS_ENUM_AVAILABLE(10_0, 7_0) = 0x0100,
//NSUnderlinePatternDash NS_ENUM_AVAILABLE(10_0, 7_0) = 0x0200,
//NSUnderlinePatternDashDot NS_ENUM_AVAILABLE(10_0, 7_0) = 0x0300,
//NSUnderlinePatternDashDotDot NS_ENUM_AVAILABLE(10_0, 7_0) = 0x0400,
//NSUnderlineByWord NS_ENUM_AVAILABLE(10_0, 7_0) = 0x8000

static CTUnderlineStyle _coreTextUnderlineStyleFromNSUnderlineStyle(NSUnderlineStyle underlineStyle) {
    switch (underlineStyle) {
        case NSUnderlineStyleNone: return kCTUnderlineStyleNone;
        case NSUnderlineStyleSingle: return kCTUnderlineStyleSingle;
        case NSUnderlineStyleThick: return kCTUnderlineStyleThick;
        default:return kCTUnderlineStyleNone;
    }
}

@end
// 鐗堟潈灞炰簬鍘熶綔鑰?// http://code4app.com (cn) http://code4app.net (en)
// 鍙戝竷浠g爜浜庢渶涓撲笟鐨勬簮鐮佸垎浜綉绔? Code4App.com