You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@weex.apache.org by ac...@apache.org on 2018/04/26 12:39:59 UTC

[07/16] incubator-weex git commit: [WEEX-311] [iOS] use new layoutEngin to replace yoga

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b77b4259/ios/sdk/WeexSDK/Sources/Component/WXTextAreaComponent.mm
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextAreaComponent.mm b/ios/sdk/WeexSDK/Sources/Component/WXTextAreaComponent.mm
new file mode 100644
index 0000000..bb263c8
--- /dev/null
+++ b/ios/sdk/WeexSDK/Sources/Component/WXTextAreaComponent.mm
@@ -0,0 +1,261 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#import "WXTextAreaComponent.h"
+#import "WXUtility.h"
+#import "WXComponent+Layout.h"
+#import "WXComponent_internal.h"
+#import "WXComponent+Layout.h"
+
+#define CorrectX 4 //textview fill text 4 pixel from left. so placeholderlabel have 4 pixel too
+#define CorrectY 8 // textview fill text 8 pixel from top
+typedef UITextView WXTextAreaView;
+
+@interface WXTextAreaComponent()
+
+@property (nonatomic, strong) WXTextAreaView *textView;
+@property (nonatomic) NSUInteger rows;
+
+@end
+
+@implementation WXTextAreaComponent {
+    UIEdgeInsets _border;
+    UIEdgeInsets _padding;
+}
+
+-(void)viewDidLoad
+{
+    _padding = UIEdgeInsetsZero;
+    _border = UIEdgeInsetsZero;
+    if (self.placeholderString) {
+        self.placeHolderLabel = [[UILabel alloc] init];
+        self.placeHolderLabel.numberOfLines = 0;
+        [_textView addSubview:self.placeHolderLabel];
+    }
+    // default placeholder hide from voice over
+    self.placeHolderLabel.isAccessibilityElement = NO;
+    _textView.isAccessibilityElement = YES;
+    _textView.delegate = self;
+    [_textView setNeedsDisplay];
+    [_textView setClipsToBounds:YES];
+    [super viewDidLoad];
+}
+
+- (void)viewWillUnload
+{
+    _textView = nil;
+}
+
+- (UIView *)loadView
+{
+    _textView = [[WXTextAreaView alloc] init];
+    return _textView;
+}
+
+#pragma mark measure frame
+- (CGSize (^)(CGSize))measureBlock
+{
+    __weak typeof(self) weakSelf = self;
+    return ^CGSize (CGSize constrainedSize) {
+        
+        CGSize computedSize = [[[NSString alloc] init]sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:weakSelf.textView.font.pointSize]}];
+        computedSize.height = _rows? computedSize.height *weakSelf.rows + (CorrectY + CorrectY/2):0;
+//#ifndef USE_FLEX
+        
+         if (![WXComponent isUseFlex])
+         {
+             if (!isnan(weakSelf.cssNode->style.minDimensions[CSS_WIDTH])) {
+                 computedSize.width = MAX(computedSize.width, weakSelf.cssNode->style.minDimensions[CSS_WIDTH]);
+             }
+             
+             if (!isnan(weakSelf.cssNode->style.maxDimensions[CSS_WIDTH])) {
+                 computedSize.width = MIN(computedSize.width, weakSelf.cssNode->style.maxDimensions[CSS_WIDTH]);
+             }
+             
+             if (!isnan(weakSelf.cssNode->style.minDimensions[CSS_HEIGHT])) {
+                 computedSize.height = MAX(computedSize.height, weakSelf.cssNode->style.minDimensions[CSS_HEIGHT]);
+             }
+             
+             if (!isnan(weakSelf.cssNode->style.maxDimensions[CSS_HEIGHT])) {
+                 computedSize.height = MIN(computedSize.height, weakSelf.cssNode->style.maxDimensions[CSS_HEIGHT]);
+             }
+         }
+       
+//#else
+        
+        else
+        {
+            if (!isnan(weakSelf.flexCssNode->getMinWidth())) {
+                computedSize.width = MAX(computedSize.width, weakSelf.flexCssNode->getMinWidth());
+            }
+            
+            if (!isnan(weakSelf.flexCssNode->getMaxWidth())) {
+                computedSize.width = MIN(computedSize.width, weakSelf.flexCssNode->getMaxWidth());
+            }
+            
+            if (!isnan(weakSelf.flexCssNode->getMinHeight())) {
+                computedSize.height = MAX(computedSize.height, weakSelf.flexCssNode->getMinHeight());
+            }
+            
+            if (!isnan(weakSelf.flexCssNode->getMaxHeight())) {
+                computedSize.height = MIN(computedSize.height, weakSelf.flexCssNode->getMaxHeight());
+            }
+        }
+        
+//#endif
+        return (CGSize) {
+            WXCeilPixelValue(computedSize.width),
+            WXCeilPixelValue(computedSize.height)
+        };
+    };
+}
+
+#pragma mark -Overwrite method
+-(NSString *)text
+{
+    return _textView.text;
+}
+
+- (void)setText:(NSString *)text
+{
+    _textView.text = text;
+    if ([text length] >0) {
+        self.placeHolderLabel.text = @"";
+    }
+}
+
+-(void)setTextColor:(UIColor *)color
+{
+    [_textView setTextColor:color];
+}
+
+-(void)setTextAlignment:(NSTextAlignment)textAlignForStyle
+{
+    [_textView setTextAlignment:textAlignForStyle];
+}
+
+-(void)setUserInteractionEnabled:(BOOL)userInteractionEnabled
+{
+    [_textView setUserInteractionEnabled:userInteractionEnabled];
+}
+
+-(void)setEnabled:(BOOL)enabled
+{
+    _textView.editable = enabled;
+    _textView.selectable = enabled;
+}
+
+-(void)setReturnKeyType:(UIReturnKeyType)returnKeyType
+{
+    [_textView setReturnKeyType:returnKeyType];
+}
+
+-(void)setInputAccessoryView:(UIView *)inputAccessoryView
+{
+    [_textView setInputAccessoryView:inputAccessoryView];
+}
+
+-(void)setEditSelectionRange:(NSInteger)selectionStart selectionEnd:(NSInteger)selectionEnd
+{
+    [self.textView becomeFirstResponder];
+    UITextPosition *startPos =  [self.textView positionFromPosition:self.textView.beginningOfDocument offset:selectionStart];
+    UITextPosition *endPos = [self.textView positionFromPosition:self.textView.beginningOfDocument offset:selectionEnd];
+    UITextRange *textRange = [self.textView textRangeFromPosition:startPos
+                                                       toPosition:endPos];
+    self.textView.selectedTextRange = textRange;
+}
+
+-(NSDictionary *)getEditSelectionRange
+{
+    NSInteger selectionStart = [self.textView offsetFromPosition:self.textView.beginningOfDocument toPosition:self.textView.selectedTextRange.start];
+    NSInteger selectionEnd = [self.textView offsetFromPosition:self.textView.beginningOfDocument toPosition:self.textView.selectedTextRange.end];
+    NSDictionary *res = @{@"selectionStart":@(selectionStart),@"selectionEnd":@(selectionEnd)};
+    return res;
+}
+
+-(void)setKeyboardType:(UIKeyboardType)keyboardType
+{
+    [_textView setKeyboardType:keyboardType];
+}
+
+-(void)setSecureTextEntry:(BOOL)secureTextEntry
+{
+    [_textView setSecureTextEntry:secureTextEntry];
+}
+
+-(void)setEditPadding:(UIEdgeInsets)padding
+{
+    _padding = padding;
+    [self _updateTextContentInset];
+}
+
+-(void)setEditBorder:(UIEdgeInsets)border
+{
+    _border = border;
+    [self _updateTextContentInset];
+}
+
+-(void)setAttributedPlaceholder:(NSMutableAttributedString *)attributedString font:(UIFont *)font
+{
+    if (self.placeholderColor) {
+        [attributedString addAttribute:NSForegroundColorAttributeName value:self.placeholderColor range:NSMakeRange(0, self.placeholderString.length)];
+        [attributedString addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, self.placeholderString.length)];
+    }
+    self.placeHolderLabel.backgroundColor = [UIColor clearColor];
+    CGRect expectedLabelSize = [attributedString boundingRectWithSize:(CGSize){self.view.frame.size.width, CGFLOAT_MAX}
+                                                              options:NSStringDrawingUsesLineFragmentOrigin
+                                                              context:nil];
+    
+    self.placeHolderLabel.clipsToBounds = NO;
+    CGRect newFrame = self.placeHolderLabel.frame;
+    newFrame.size.height = ceil(expectedLabelSize.size.height);
+    newFrame.size.width = _textView.frame.size.width- CorrectX*2;
+    newFrame.origin.x = CorrectX + _padding.left + _border.left; // the cursor origin.x
+    self.placeHolderLabel.frame = newFrame;
+    self.placeHolderLabel.attributedText = attributedString;
+}
+
+-(void)setFont:(UIFont *)font
+{
+    [_textView setFont:font];
+}
+
+-(void)setRows:(NSUInteger)rows
+{
+    _rows = rows;
+    [self setNeedsLayout];
+}
+
+#pragma mark -Private Method
+- (void)_updateTextContentInset
+{
+    [_textView setTextContainerInset:UIEdgeInsetsMake(_padding.top + _border.top,
+                                                      _padding.left + _border.left,
+                                                      _padding.bottom + _border.bottom,
+                                                      _border.right + _border.right)];
+    
+    //when textview update, placeHolderLabel update too
+    CGRect newFrame = self.placeHolderLabel.frame;
+    newFrame.size.width = self.textView.frame.size.width - (_padding.left + _border.left) -CorrectX*2;
+    newFrame.origin.x = CorrectX + _padding.left + _border.left; // the cursor origin.x
+    newFrame.origin.y = _padding.top + _border.top;
+    self.placeHolderLabel.frame = newFrame;
+}
+
+@end

http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/b77b4259/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m
----------------------------------------------------------------------
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m
deleted file mode 100644
index 2a948e2..0000000
--- a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m
+++ /dev/null
@@ -1,1076 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-#import "WXTextComponent.h"
-#import "WXSDKInstance_private.h"
-#import "WXComponent_internal.h"
-#import "WXLayer.h"
-#import "WXUtility.h"
-#import "WXConvert.h"
-#import "WXRuleManager.h"
-#import "WXDefine.h"
-#import "WXView.h"
-#import <pthread/pthread.h>
-#import <CoreText/CoreText.h>
-
-// WXText is a non-public is not permitted
-@interface WXTextView : WXView
-@property (nonatomic, strong) NSTextStorage *textStorage;
-@end
-
-@implementation WXTextView
-
-- (instancetype)initWithFrame:(CGRect)frame
-{
-    if ((self = [super initWithFrame:frame])) {
-        self.accessibilityTraits |= UIAccessibilityTraitStaticText;
-        
-        self.opaque = NO;
-        self.contentMode = UIViewContentModeRedraw;
-        self.textStorage = [NSTextStorage new];
-    }
-    return self;
-}
-
-+ (Class)layerClass
-{
-    return [WXLayer class];
-}
-
-- (void)copy:(id)sender
-{
-    [[UIPasteboard generalPasteboard] setString:((WXTextComponent*)self.wx_component).text];
-}
-
-- (void)setTextStorage:(NSTextStorage *)textStorage
-{
-    if (_textStorage != textStorage) {
-        _textStorage = textStorage;
-        [self.wx_component setNeedsDisplay];
-    }
-}
-
-- (BOOL)canBecomeFirstResponder
-{
-    return YES;
-}
-
-- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
-{
-    if (action == @selector(copy:)) {
-        return [[self.wx_component valueForKey:@"_enableCopy"] boolValue];
-    }
-    return [super canPerformAction:action withSender:sender];
-}
-
-- (NSString *)description
-{
-    NSString *superDescription = super.description;
-    NSRange semicolonRange = [superDescription rangeOfString:@";"];
-    NSString * content = _textStorage.string;
-    if ([(WXTextComponent*)self.wx_component useCoreText]) {
-        content = ((WXTextComponent*)self.wx_component).text;
-    }
-    NSString *replacement = [NSString stringWithFormat:@"; text: %@; frame:%f,%f,%f,%f", content, self.frame.origin.x, self.frame.origin.y, self.frame.size.width, self.frame.size.height];
-    return [superDescription stringByReplacingCharactersInRange:semicolonRange withString:replacement];
-}
-
-- (NSString *)accessibilityValue
-{
-    if (self.wx_component && self.wx_component->_ariaLabel) {
-        return [super accessibilityValue];
-    }
-    if (![(WXTextComponent*)self.wx_component useCoreText]) {
-        return _textStorage.string;
-    }
-    return ((WXTextComponent*)self.wx_component).text;
-}
-
-- (NSString *)accessibilityLabel
-{
-    if (self.wx_component) {
-        if (self.wx_component->_ariaLabel) {
-            return self.wx_component->_ariaLabel;
-        }
-    }
-    return [super accessibilityLabel];
-}
-
-@end
-
-static BOOL textRenderUsingCoreText = YES;
-
-NSString *const WXTextTruncationToken = @"\u2026";
-CGFloat WXTextDefaultLineThroughWidth = 1.2;
-
-@interface WXTextComponent()
-@property (nonatomic, strong) NSString *useCoreTextAttr;
-@end
-
-@implementation WXTextComponent
-{
-    UIEdgeInsets _border;
-    UIEdgeInsets _padding;
-    NSTextStorage *_textStorage;
-    CGFloat _textStorageWidth;
-    
-    UIColor *_color;
-    NSString *_fontFamily;
-    CGFloat _fontSize;
-    CGFloat _fontWeight;
-    WXTextStyle _fontStyle;
-    NSUInteger _lines;
-    NSTextAlignment _textAlign;
-    NSString *_direction;
-    WXTextDecoration _textDecoration;
-    NSString *_textOverflow;
-    CGFloat _lineHeight;
-    CGFloat _letterSpacing;
-    BOOL _truncationLine; // support trunk tail
-    
-    NSAttributedString * _ctAttributedString;
-    NSString *_wordWrap;
-    
-    pthread_mutex_t _ctAttributedStringMutex;
-    pthread_mutexattr_t _propertMutexAttr;
-    BOOL _observerIconfont;
-    BOOL _enableCopy;
-}
-
-+ (void)setRenderUsingCoreText:(BOOL)usingCoreText
-{
-    textRenderUsingCoreText = usingCoreText;
-}
-
-+ (BOOL)textRenderUsingCoreText
-{
-    return textRenderUsingCoreText;
-}
-
-- (instancetype)initWithRef:(NSString *)ref
-                       type:(NSString *)type
-                     styles:(NSDictionary *)styles
-                 attributes:(NSDictionary *)attributes
-                     events:(NSArray *)events
-               weexInstance:(WXSDKInstance *)weexInstance
-{
-    self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance];
-    if (self) {
-        // just for coretext and textkit render replacement
-        pthread_mutexattr_init(&(_propertMutexAttr));
-        pthread_mutexattr_settype(&(_propertMutexAttr), PTHREAD_MUTEX_RECURSIVE);
-        pthread_mutex_init(&(_ctAttributedStringMutex), &(_propertMutexAttr));
-        
-        if ([attributes objectForKey:@"coretext"]) {
-            _useCoreTextAttr = [WXConvert NSString:attributes[@"coretext"]];
-        } else {
-            _useCoreTextAttr = nil;
-        }
-        
-        [self fillCSSStyles:styles];
-        [self fillAttributes:attributes];
-    }
-    
-    return self;
-}
-
-- (BOOL)useCoreText
-{
-    if ([_useCoreTextAttr isEqualToString:@"true"]) {
-        return YES;
-    }
-    if ([_useCoreTextAttr isEqualToString:@"false"]) {
-        return NO;
-    }
-    
-    if ([WXTextComponent textRenderUsingCoreText]) {
-        return YES;
-    }
-    return NO;
-}
-
-- (void)dealloc
-{
-    if (_fontFamily && _observerIconfont) {
-        [[NSNotificationCenter defaultCenter] removeObserver:self name:WX_ICONFONT_DOWNLOAD_NOTIFICATION object:nil];
-    }
-    pthread_mutex_destroy(&_ctAttributedStringMutex);
-    pthread_mutexattr_destroy(&_propertMutexAttr);
-}
-
-#define WX_STYLE_FILL_TEXT(key, prop, type, needLayout)\
-do {\
-    id value = styles[@#key];\
-    if (value) {\
-        _##prop = [WXConvert type:value];\
-        [self setNeedsRepaint];\
-        if (needLayout) {\
-            [self setNeedsLayout];\
-        }\
-    }\
-} while(0);
-
-#define WX_STYLE_FILL_TEXT_WITH_DEFAULT_VALUE(key, prop, type, defaultValue,needLayout)\
-do {\
-    id value = styles[@#key];\
-    if (value) {\
-        if([WXUtility isBlankString:value]){\
-            _##prop = defaultValue;\
-        }else {\
-            _##prop = [WXConvert type:value];\
-        }\
-        [self setNeedsRepaint];\
-        if (needLayout) {\
-            [self setNeedsLayout];\
-        }\
-    }\
-} while(0);
-
-
-#define WX_STYLE_FILL_TEXT_PIXEL(key, prop, needLayout)\
-do {\
-    id value = styles[@#key];\
-    if (value) {\
-        _##prop = [WXConvert WXPixelType:value scaleFactor:self.weexInstance.pixelScaleFactor];\
-        [self setNeedsRepaint];\
-    if (needLayout) {\
-        [self setNeedsLayout];\
-    }\
-}\
-} while(0);
-
-- (void)fillCSSStyles:(NSDictionary *)styles
-{
-    WX_STYLE_FILL_TEXT_WITH_DEFAULT_VALUE(color, color, UIColor, [UIColor blackColor], NO)
-    WX_STYLE_FILL_TEXT(fontFamily, fontFamily, NSString, YES)
-    WX_STYLE_FILL_TEXT_PIXEL(fontSize, fontSize, YES)
-    WX_STYLE_FILL_TEXT(fontWeight, fontWeight, WXTextWeight, YES)
-    WX_STYLE_FILL_TEXT(fontStyle, fontStyle, WXTextStyle, YES)
-    WX_STYLE_FILL_TEXT(lines, lines, NSUInteger, YES)
-    WX_STYLE_FILL_TEXT(textAlign, textAlign, NSTextAlignment, NO)
-    WX_STYLE_FILL_TEXT(textDecoration, textDecoration, WXTextDecoration, YES)
-    WX_STYLE_FILL_TEXT(textOverflow, textOverflow, NSString, NO)
-    WX_STYLE_FILL_TEXT_PIXEL(lineHeight, lineHeight, YES)
-    WX_STYLE_FILL_TEXT_PIXEL(letterSpacing, letterSpacing, YES)
-    WX_STYLE_FILL_TEXT(wordWrap, wordWrap, NSString, YES);
-    WX_STYLE_FILL_TEXT(direction, direction, NSString, YES)
-    if (_fontFamily && !_observerIconfont) {
-        // notification received when custom icon font file download finish
-        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(repaintText:) name:WX_ICONFONT_DOWNLOAD_NOTIFICATION object:nil];
-        _observerIconfont = YES;
-    }
-    UIEdgeInsets padding = {
-        WXFloorPixelValue(self.cssNode->style.padding[CSS_TOP] + self.cssNode->style.border[CSS_TOP]),
-        WXFloorPixelValue(self.cssNode->style.padding[CSS_LEFT] + self.cssNode->style.border[CSS_LEFT]),
-        WXFloorPixelValue(self.cssNode->style.padding[CSS_BOTTOM] + self.cssNode->style.border[CSS_BOTTOM]),
-        WXFloorPixelValue(self.cssNode->style.padding[CSS_RIGHT] + self.cssNode->style.border[CSS_RIGHT])
-    };
-    
-    if (!UIEdgeInsetsEqualToEdgeInsets(padding, _padding)) {
-        _padding = padding;
-        [self setNeedsRepaint];
-    }
-}
-
-- (void)fillAttributes:(NSDictionary *)attributes
-{
-    id text = [WXConvert NSString:attributes[@"value"]];
-    if (text && ![self.text isEqualToString:text]) {
-        self.text = text;
-        [self setNeedsRepaint];
-        [self setNeedsLayout];
-    }
-    if (attributes[@"enableCopy"]) {
-        _enableCopy = [WXConvert BOOL:attributes[@"enableCopy"]];
-    }
-}
-
-- (void)setNeedsRepaint
-{
-    _textStorage = nil;
-    
-    pthread_mutex_lock(&(_ctAttributedStringMutex));
-    _ctAttributedString = nil;
-    pthread_mutex_unlock(&(_ctAttributedStringMutex));
-    
-}
-
-#pragma mark - Subclass
-
-- (void)setNeedsLayout
-{
-    [super setNeedsLayout];
-}
-
-- (void)viewDidLoad
-{
-    [super viewDidLoad];
-    BOOL useCoreText = NO;
-    if ([self.view.wx_component isKindOfClass:NSClassFromString(@"WXTextComponent")] && [self.view.wx_component respondsToSelector:@selector(useCoreText)]) {
-        useCoreText = [(WXTextComponent*)self.view.wx_component useCoreText];
-    }
-    if (!useCoreText) {
-        ((WXTextView *)self.view).textStorage = _textStorage;
-    }
-    if (_enableCopy) {
-        UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(displayMenuController:)];
-        [self.view addGestureRecognizer:longPress];
-    }
-    self.view.isAccessibilityElement = YES;
-    
-    [self setNeedsDisplay];
-}
-
-- (void)displayMenuController:(id)sender
-{
-    if ([self.view becomeFirstResponder] && ((UILongPressGestureRecognizer*)sender).state == UIGestureRecognizerStateBegan) {
-        UIMenuController *theMenu = [UIMenuController sharedMenuController];
-        CGSize size = [self ctAttributedString].size;
-        CGRect selectionRect = CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y, size.width, size.height);
-        [theMenu setTargetRect:selectionRect inView:self.view.superview];
-        [theMenu setMenuVisible:YES animated:YES];
-    }
-}
-
-- (UIView *)loadView
-{
-    return [[WXTextView alloc] init];
-}
-
-- (BOOL)needsDrawRect
-{
-    return YES;
-}
-
-- (UIImage *)drawRect:(CGRect)rect;
-{
-    CGContextRef context = UIGraphicsGetCurrentContext();
-    if (_isCompositingChild) {
-        [self drawTextWithContext:context bounds:rect padding:_padding view:nil];
-    } else {
-        WXTextView *textView = (WXTextView *)_view;
-        [self drawTextWithContext:context bounds:rect padding:_padding view:textView];
-    }
-    
-    return nil;
-}
-
-- (CGSize (^)(CGSize))measureBlock
-{
-    __weak typeof(self) weakSelf = self;
-    return ^CGSize (CGSize constrainedSize) {
-        CGSize computedSize = CGSizeZero;
-        NSTextStorage *textStorage = nil;
-        
-        //TODO:more elegant way to use max and min constrained size
-        if (!isnan(weakSelf.cssNode->style.minDimensions[CSS_WIDTH])) {
-            constrainedSize.width = MAX(constrainedSize.width, weakSelf.cssNode->style.minDimensions[CSS_WIDTH]);
-        }
-        
-        if (!isnan(weakSelf.cssNode->style.maxDimensions[CSS_WIDTH])) {
-            constrainedSize.width = MIN(constrainedSize.width, weakSelf.cssNode->style.maxDimensions[CSS_WIDTH]);
-        }
-        
-        if (![self useCoreText]) {
-            textStorage = [weakSelf textStorageWithWidth:constrainedSize.width];
-            NSLayoutManager *layoutManager = textStorage.layoutManagers.firstObject;
-            NSTextContainer *textContainer = layoutManager.textContainers.firstObject;
-            computedSize = [layoutManager usedRectForTextContainer:textContainer].size;
-        } else {
-            computedSize = [weakSelf calculateTextHeightWithWidth:constrainedSize.width];
-        }
-        
-        if (!isnan(weakSelf.cssNode->style.minDimensions[CSS_HEIGHT])) {
-            computedSize.height = MAX(computedSize.height, weakSelf.cssNode->style.minDimensions[CSS_HEIGHT]);
-        }
-        
-        if (!isnan(weakSelf.cssNode->style.maxDimensions[CSS_HEIGHT])) {
-            computedSize.height = MIN(computedSize.height, weakSelf.cssNode->style.maxDimensions[CSS_HEIGHT]);
-        }
-        if (textStorage && [WXUtility isBlankString:textStorage.string]) {
-            //  if the text value is empty or nil, then set the height is 0.
-            computedSize.height = 0;
-        }
-        
-        return (CGSize) {
-            WXCeilPixelValue(computedSize.width),
-            WXCeilPixelValue(computedSize.height)
-        };
-    };
-}
-
-#pragma mark Text Building
-
-- (NSAttributedString *)ctAttributedString
-{
-    if (!self.text) {
-        return nil;
-    }
-    NSAttributedString * attributedString = nil;
-    pthread_mutex_lock(&(_ctAttributedStringMutex));
-    if (!_ctAttributedString) {
-        _ctAttributedString = [self buildCTAttributeString];
-        WXPerformBlockOnComponentThread(^{
-            [self.weexInstance.componentManager startComponentTasks];
-        });
-    }
-    attributedString = [_ctAttributedString copy];
-    pthread_mutex_unlock(&(_ctAttributedStringMutex));
-    return attributedString;
-}
-
-- (void)repaintText:(NSNotification *)notification
-{
-    if (![_fontFamily isEqualToString:notification.userInfo[@"fontFamily"]]) {
-        return;
-    }
-    [self setNeedsRepaint];
-    WXPerformBlockOnComponentThread(^{
-        [self.weexInstance.componentManager startComponentTasks];
-        WXPerformBlockOnMainThread(^{
-            [self setNeedsLayout];
-            [self setNeedsDisplay];
-        });
-    });
-}
-
-- (NSMutableAttributedString *)buildCTAttributeString
-{
-    NSString * string = self.text;
-    if (![string isKindOfClass:[NSString class]]) {
-        WXLogError(@"text %@ is invalid", self.text);
-        string = @"";
-    }
-    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString: string];
-    if (_color) {
-        [attributedString addAttribute:NSForegroundColorAttributeName value:_color range:NSMakeRange(0, string.length)];
-    }
-    
-    // set font
-    UIFont *font = [WXUtility fontWithSize:_fontSize textWeight:_fontWeight textStyle:_fontStyle fontFamily:_fontFamily scaleFactor:self.weexInstance.pixelScaleFactor useCoreText:[self useCoreText]];
-    CTFontRef ctFont = CTFontCreateWithName((__bridge CFStringRef)font.fontName,
-                                           font.pointSize,
-                                           NULL);
-    if (ctFont) {
-        [attributedString addAttribute:(id)kCTFontAttributeName value:(__bridge id)(ctFont) range:NSMakeRange(0, string.length)];
-        CFRelease(ctFont);
-    }
-    
-    if(_textDecoration == WXTextDecorationUnderline){
-        [attributedString addAttribute:(id)kCTUnderlineStyleAttributeName value:@(kCTUnderlinePatternSolid | kCTUnderlineStyleSingle) range:NSMakeRange(0, string.length)];
-    } else if(_textDecoration == WXTextDecorationLineThrough){
-        [attributedString addAttribute:NSStrikethroughStyleAttributeName value:@(NSUnderlinePatternSolid | NSUnderlineStyleSingle) range:NSMakeRange(0, string.length)];
-    }
-    
-    NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
-    
-    // handle text direction style, default ltr
-    if (_cssNode->layout.direction == CSS_DIRECTION_RTL) {
-        if (0 == _textAlign) {
-            //force text right-align if don't specified any align.
-            _textAlign = NSTextAlignmentRight;
-        }
-        paragraphStyle.baseWritingDirection = NSWritingDirectionRightToLeft;
-    } else {
-        //if you specify NSWritingDirectionNaturalDirection, the receiver resolves the writing
-        //directionto eitherNSWritingDirectionLeftToRight or NSWritingDirectionRightToLeft,
-        //depending on the direction for the user’s language preference setting.
-        paragraphStyle.baseWritingDirection =  NSWritingDirectionNatural;
-    }
-    
-    if (_textAlign) {
-        paragraphStyle.alignment = _textAlign;
-    }
-    
-    if ([[_wordWrap lowercaseString] isEqualToString:@"break-word"]) {
-        paragraphStyle.lineBreakMode = NSLineBreakByWordWrapping;
-    } else if ([[_wordWrap lowercaseString] isEqualToString:@"normal"]){
-        paragraphStyle.lineBreakMode = NSLineBreakByClipping;
-    } else {
-         // set default lineBreakMode
-        paragraphStyle.lineBreakMode = NSLineBreakByCharWrapping;
-    }
-    _truncationLine = NO;
-    if (_textOverflow && [_textOverflow length] > 0) {
-        if (_lines && [_textOverflow isEqualToString:@"ellipsis"])
-            _truncationLine = YES;
-    }
-    
-    if (_lineHeight) {
-        paragraphStyle.maximumLineHeight = _lineHeight;
-        paragraphStyle.minimumLineHeight = _lineHeight;
-    }
-    if (_lineHeight || _textAlign || [_textOverflow length] > 0) {
-        [attributedString addAttribute:NSParagraphStyleAttributeName
-                                 value:paragraphStyle
-                                 range:(NSRange){0, attributedString.length}];
-    }
-    
-    if (_letterSpacing) {
-        [attributedString addAttribute:NSKernAttributeName value:@(_letterSpacing) range:(NSRange){0, attributedString.length}];
-    }
-    
-    if ([self adjustLineHeight]) {
-        if (_lineHeight > font.lineHeight) {
-            [attributedString addAttribute:NSBaselineOffsetAttributeName
-                                     value:@((_lineHeight - font.lineHeight)/ 2)
-                                     range:(NSRange){0, attributedString.length}];
-        }
-    }
-    
-    return attributedString;
-}
-
-- (NSAttributedString *)buildAttributeString
-{
-    NSString *string = self.text ?: @"";
-    
-    NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:string];
-    
-    // set textColor
-    if(_color) {
-        [attributedString addAttribute:NSForegroundColorAttributeName value:_color range:NSMakeRange(0, string.length)];
-    }
-    
-    // set font
-    UIFont *font = [WXUtility fontWithSize:_fontSize textWeight:_fontWeight textStyle:_fontStyle fontFamily:_fontFamily scaleFactor:self.weexInstance.pixelScaleFactor];
-    if (font) {
-        [attributedString addAttribute:NSFontAttributeName value:font range:NSMakeRange(0, string.length)];
-    }
-    
-    if(_textDecoration == WXTextDecorationUnderline){
-        [attributedString addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlinePatternSolid | NSUnderlineStyleSingle) range:NSMakeRange(0, string.length)];
-    } else if(_textDecoration == WXTextDecorationLineThrough){
-        [attributedString addAttribute:NSStrikethroughStyleAttributeName value:@(NSUnderlinePatternSolid | NSUnderlineStyleSingle) range:NSMakeRange(0, string.length)];
-    }
-    
-    NSMutableParagraphStyle *paragraphStyle = [NSMutableParagraphStyle new];
-
-    // handle text direction style, default ltr
-    if (_cssNode->layout.direction == CSS_DIRECTION_RTL) {
-        if (0 == _textAlign) {
-            //force text right-align if don't specified any align.
-            _textAlign = NSTextAlignmentRight;
-        }
-        paragraphStyle.baseWritingDirection = NSWritingDirectionRightToLeft;
-    } else {
-        //if you specify NSWritingDirectionNaturalDirection, the receiver resolves the writing
-        //directionto eitherNSWritingDirectionLeftToRight or NSWritingDirectionRightToLeft,
-        //depending on the direction for the user’s language preference setting.
-        paragraphStyle.baseWritingDirection =  NSWritingDirectionNatural;
-    }
-    
-    if (_textAlign) {
-        paragraphStyle.alignment = _textAlign;
-    }
-    
-    if (_lineHeight) {
-        paragraphStyle.maximumLineHeight = _lineHeight;
-        paragraphStyle.minimumLineHeight = _lineHeight;
-    }
-    
-    if (_lineHeight || _textAlign) {
-        [attributedString addAttribute:NSParagraphStyleAttributeName
-                                 value:paragraphStyle
-                                 range:(NSRange){0, attributedString.length}];
-    }
-    if ([self adjustLineHeight]) {
-        if (_lineHeight > font.lineHeight) {
-            [attributedString addAttribute:NSBaselineOffsetAttributeName
-                                     value:@((_lineHeight - font.lineHeight)/ 2)
-                                     range:(NSRange){0, attributedString.length}];
-        }
-    }
-
-    return attributedString;
-}
-
-- (BOOL)adjustLineHeight
-{
-    if (WX_SYS_VERSION_LESS_THAN(@"10.0")) {
-        return true;
-    }
-    return ![self useCoreText];
-}
-
-- (NSTextStorage *)textStorageWithWidth:(CGFloat)width
-{
-    if (_textStorage && width == _textStorageWidth) {
-        return _textStorage;
-    }
-    
-    NSLayoutManager *layoutManager = [NSLayoutManager new];
-    
-    // build AttributeString
-    NSAttributedString *attributedString = [self buildAttributeString];
-    
-    NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedString];
-    [textStorage addLayoutManager:layoutManager];
-    
-    NSTextContainer *textContainer = [NSTextContainer new];
-    textContainer.lineFragmentPadding = 0.0;
-    
-    if ([[_wordWrap lowercaseString] isEqualToString:@"break-word"]) {
-        textContainer.lineBreakMode = NSLineBreakByWordWrapping;
-    } else if ([[_wordWrap lowercaseString] isEqualToString:@"normal"]){
-        textContainer.lineBreakMode = NSLineBreakByClipping;
-    } else {
-        // set default lineBreakMode
-        textContainer.lineBreakMode = NSLineBreakByCharWrapping;
-    }
-    
-    if (_textOverflow && [_textOverflow length] > 0) {
-        if ([_textOverflow isEqualToString:@"ellipsis"])
-            textContainer.lineBreakMode = NSLineBreakByTruncatingTail;
-    }
-    textContainer.maximumNumberOfLines = _lines > 0 ? _lines : 0;
-    textContainer.size = (CGSize){isnan(width) ? CGFLOAT_MAX : width, CGFLOAT_MAX};
-
-    [layoutManager addTextContainer:textContainer];
-    [layoutManager ensureLayoutForTextContainer:textContainer];
-    
-    _textStorageWidth = width;
-    _textStorage = textStorage;
-    
-    return textStorage;
-}
-
-- (void)syncTextStorageForView
-{
-    CGFloat width = self.calculatedFrame.size.width - (_padding.left + _padding.right);
-    NSTextStorage *textStorage = nil;
-    if (![self useCoreText]) {
-        textStorage = [self textStorageWithWidth:width];
-    }
-    [self.weexInstance.componentManager  _addUITask:^{
-        if ([self isViewLoaded]) {
-            if (![self useCoreText]) {
-                ((WXTextView *)self.view).textStorage = textStorage;
-            }
-            [self readyToRender]; // notify super component
-            [self setNeedsDisplay];
-        }
-    }];
-}
-
-- (void)_frameDidCalculated:(BOOL)isChanged
-{
-    [super _frameDidCalculated:isChanged];
-    [self syncTextStorageForView];
-}
-
-- (void)_updateStylesOnComponentThread:(NSDictionary *)styles resetStyles:(NSMutableArray *)resetStyles isUpdateStyles:(BOOL)isUpdateStyles
-{
-    [super _updateStylesOnComponentThread:styles resetStyles:(NSMutableArray *)resetStyles isUpdateStyles:isUpdateStyles];
-    NSMutableDictionary * newStyles = [styles mutableCopy];
-    for (NSString * key in [resetStyles copy]) {
-        [newStyles setObject:@"" forKey:key];
-    }
-    [self fillCSSStyles:newStyles];
-    
-    [self syncTextStorageForView];
-}
-
-- (void)_updateAttributesOnComponentThread:(NSDictionary *)attributes
-{
-    [super _updateAttributesOnComponentThread:attributes];
-    
-    [self fillAttributes:attributes];
-    
-    [self syncTextStorageForView];
-}
-
-- (void)drawTextWithContext:(CGContextRef)context bounds:(CGRect)bounds padding:(UIEdgeInsets)padding view:(WXTextView *)view
-{
-    if (bounds.size.width <= 0 || bounds.size.height <= 0) {
-        return;
-    }
-    
-    if ([self _needsDrawBorder]) {
-        [self _drawBorderWithContext:context size:bounds.size];
-    } else {
-        WXPerformBlockOnMainThread(^{
-            [self _resetNativeBorderRadius];
-        });
-    }
-    if (![self useCoreText]) {
-        NSLayoutManager *layoutManager = _textStorage.layoutManagers.firstObject;
-        NSTextContainer *textContainer = layoutManager.textContainers.firstObject;
-        
-        CGRect textFrame = UIEdgeInsetsInsetRect(bounds, padding);
-        NSRange glyphRange = [layoutManager glyphRangeForTextContainer:textContainer];
-        
-        [layoutManager drawBackgroundForGlyphRange:glyphRange atPoint:textFrame.origin];
-        [layoutManager drawGlyphsForGlyphRange:glyphRange atPoint:textFrame.origin];
-    } else {
-        CGRect textFrame = UIEdgeInsetsInsetRect(bounds, padding);
-        // sufficient height for text to draw, or frame lines will be empty
-        textFrame.size.height = bounds.size.height * 2;
-        CGContextSaveGState(context);
-        //flip the coordinate system
-        CGContextSetTextMatrix(context, CGAffineTransformIdentity);
-        CGContextTranslateCTM(context, 0, textFrame.size.height);
-        CGContextScaleCTM(context, 1.0, -1.0);
-        
-        NSAttributedString * attributedStringCopy = [self ctAttributedString];
-        //add path
-        CGPathRef cgPath = NULL;
-        cgPath = CGPathCreateWithRect(textFrame, NULL);
-        CTFrameRef _coreTextFrameRef = NULL;
-        if (_coreTextFrameRef) {
-            CFRelease(_coreTextFrameRef);
-            _coreTextFrameRef = NULL;
-        }
-        if(!attributedStringCopy) {
-            return;
-        }
-        CTFramesetterRef ctframesetterRef = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)(attributedStringCopy));
-        _coreTextFrameRef = CTFramesetterCreateFrame(ctframesetterRef, CFRangeMake(0, attributedStringCopy.length), cgPath, NULL);
-        CFArrayRef ctLines = NULL;
-        if (NULL == _coreTextFrameRef) {
-            // try to protect crash from frame is NULL
-            return;
-        }
-        CFRelease(ctframesetterRef);
-        ctframesetterRef = NULL;
-        ctLines = CTFrameGetLines(_coreTextFrameRef);
-        CFIndex lineCount = CFArrayGetCount(ctLines);
-        NSMutableArray * mutableLines = [NSMutableArray new];
-        CGPoint lineOrigins[lineCount];
-        NSUInteger rowCount = 0;
-        BOOL needTruncation = NO;
-        CTLineRef ctTruncatedLine = NULL;
-        CTFrameGetLineOrigins(_coreTextFrameRef, CFRangeMake(0, 0), lineOrigins);
-        for (CFIndex lineIndex = 0;(!_lines || _lines > lineIndex) && lineIndex < lineCount; lineIndex ++) {
-            CTLineRef lineRef = NULL;
-            lineRef = CFArrayGetValueAtIndex(ctLines, lineIndex);
-            if (!lineRef) {
-                break;
-            }
-            CGPoint lineOrigin = lineOrigins[lineIndex];
-            lineOrigin.x += padding.left;
-            lineOrigin.y -= padding.top;
-            CFArrayRef runs = CTLineGetGlyphRuns(lineRef);
-            [mutableLines addObject:(__bridge id _Nonnull)(lineRef)];
-            // lineIndex base 0
-            rowCount = lineIndex + 1;
-            if (_lines > 0 && _truncationLine) {
-                if (_truncationLine && rowCount > _lines) {
-                    needTruncation = YES;
-                    do {
-                        NSUInteger lastRow = [mutableLines count];
-                        if (lastRow < rowCount) {
-                           break;
-                        }
-                        [mutableLines removeLastObject];
-                    } while (1);
-
-                }
-            }
-            if (_lines > 0 && _truncationLine) {
-                if (rowCount >= _lines &&!needTruncation && (CTLineGetStringRange(lineRef).length + CTLineGetStringRange(lineRef).location) < attributedStringCopy.length) {
-                    needTruncation = YES;
-                }
-            }
-            
-            if (needTruncation) {
-                CGContextSetTextPosition(context, lineOrigin.x, lineOrigin.y);
-                ctTruncatedLine = [self buildTruncatedLineWithRuns:runs lines:mutableLines path:cgPath];
-                if (ctTruncatedLine) {
-                    CFArrayRef truncatedRuns = CTLineGetGlyphRuns(ctTruncatedLine);
-                    [self drawTextWithRuns:truncatedRuns context:context lineOrigin:lineOrigin];
-                    CFRelease(ctTruncatedLine);
-                    ctTruncatedLine = NULL;
-                    continue;
-                }
-            }else {
-                [self drawTextWithRuns:runs context:context lineOrigin:lineOrigin];
-            }
-        }
-        
-        [mutableLines removeAllObjects];
-        CGPathRelease(cgPath);
-        CFRelease(_coreTextFrameRef);
-        _coreTextFrameRef = NULL;
-        cgPath = NULL;
-        CGContextRestoreGState(context);
-    }
-}
-
-- (void)drawTextWithRuns:(CFArrayRef)runs context:(CGContextRef)context lineOrigin:(CGPoint)lineOrigin
-{
-    for (CFIndex runIndex = 0; runIndex < CFArrayGetCount(runs); runIndex ++) {
-        CTRunRef run = NULL;
-        run = CFArrayGetValueAtIndex(runs, runIndex);
-        CFDictionaryRef attr = NULL;
-        attr = CTRunGetAttributes(run);
-        if (0 == runIndex) {
-            NSNumber *baselineOffset = (NSNumber*)CFDictionaryGetValue(attr, NSBaselineOffsetAttributeName);
-            if (baselineOffset) {
-                lineOrigin.y += [baselineOffset doubleValue];
-            }
-        }
-        CGContextSetTextPosition(context, lineOrigin.x, lineOrigin.y);
-        CTRunDraw(run, context, CFRangeMake(0, 0));
-        CFIndex glyphCount = CTRunGetGlyphCount(run);
-        if (glyphCount <= 0) continue;
-        
-        NSUnderlineStyle strikethrough = (NSUnderlineStyle)CFDictionaryGetValue(attr, NSStrikethroughStyleAttributeName);
-        
-        if (strikethrough) {
-            // draw strikethrough
-            [self drawLineThroughWithRun:runs context:context index:runIndex origin:lineOrigin];
-        }
-    }
-}
-
-- (CTLineRef)buildTruncatedLineWithRuns:(CFArrayRef)runs lines:(NSMutableArray*)mutableLines path:(CGPathRef)cgPath
-{
-    NSAttributedString * truncationToken = nil;
-    CTLineRef ctTruncatedLine = NULL;
-    CTLineRef lastLine = (__bridge CTLineRef)(mutableLines.lastObject);
-   
-    CFArrayRef lastLineRuns = CTLineGetGlyphRuns(lastLine);
-    NSUInteger lastLineRunCount = CFArrayGetCount(lastLineRuns);
-    
-    CTLineRef truncationTokenLine = NULL;
-    NSMutableDictionary *attrs = nil;
-    if (lastLineRunCount > 0) {
-        CTRunRef run = CFArrayGetValueAtIndex(runs, lastLineRunCount - 1);
-        attrs = (id)CTRunGetAttributes(run);
-        attrs = attrs ? attrs.mutableCopy : [NSMutableDictionary new];
-        CTFontRef font = (__bridge CTFontRef)(attrs[(id)kCTFontAttributeName]);
-        CGFloat fontSize = font ? CTFontGetSize(font):32 * self.weexInstance.pixelScaleFactor;
-        UIFont * uiFont = [UIFont systemFontOfSize:fontSize];
-        if (uiFont) {
-            font = CTFontCreateWithName((__bridge CFStringRef)uiFont.fontName, uiFont.pointSize, NULL);
-        }
-        if (font) {
-            attrs[(id)kCTFontAttributeName] = (__bridge id)(font);
-            uiFont = nil;
-            CFRelease(font);
-        }
-        CGColorRef color = (__bridge CGColorRef)(attrs[(id)kCTForegroundColorAttributeName]);
-        if (color && CFGetTypeID(color) == CGColorGetTypeID() && CGColorGetAlpha(color) == 0) {
-            [attrs removeObjectForKey:(id)kCTForegroundColorAttributeName];
-        }
-        
-        attrs = attrs?:[NSMutableDictionary new];
-        truncationToken = [[NSAttributedString alloc] initWithString:WXTextTruncationToken attributes:attrs];
-        truncationTokenLine = CTLineCreateWithAttributedString((CFAttributedStringRef)truncationToken);
-    }
-    
-    if (truncationTokenLine) {
-        // default truncationType is kCTLineTruncationEnd
-        CTLineTruncationType truncationType = kCTLineTruncationEnd;
-        NSAttributedString *attributedString = [self ctAttributedString];
-        NSAttributedString * lastLineText = nil;
-        NSRange lastLineTextRange = WXNSRangeFromCFRange(CTLineGetStringRange(lastLine));
-        NSRange attributeStringRange = NSMakeRange(0, attributedString.string.length);
-        NSRange interSectionRange = NSIntersectionRange(lastLineTextRange, attributeStringRange);
-        if (!NSEqualRanges(interSectionRange, lastLineTextRange)) {
-            // out of bounds
-            lastLineTextRange = interSectionRange;
-        }
-        lastLineText = [attributedString attributedSubstringFromRange: lastLineTextRange];
-        if (!lastLineText) {
-            lastLineText = attributedString;
-        }
-        NSMutableAttributedString *mutableLastLineText = lastLineText.mutableCopy;
-        [mutableLastLineText appendAttributedString:truncationToken];
-        CTLineRef ctLastLineExtend = CTLineCreateWithAttributedString((__bridge CFAttributedStringRef)[mutableLastLineText copy]);
-        if (ctLastLineExtend) {
-            CGRect cgPathRect = CGRectZero;
-            CGFloat truncatedWidth = 0;
-            if (CGPathIsRect(cgPath, &cgPathRect)) {
-                truncatedWidth = cgPathRect.size.width;
-            }
-            ctTruncatedLine = CTLineCreateTruncatedLine(ctLastLineExtend, truncatedWidth, truncationType, truncationTokenLine);
-            CFRelease(ctLastLineExtend);
-            ctLastLineExtend = NULL;
-            CFRelease(truncationTokenLine);
-            truncationTokenLine = NULL;
-        }
-    }
-    
-    return ctTruncatedLine;
-}
-
-- (void)drawLineThroughWithRun:(CFArrayRef)runs context:(CGContextRef)context index:(CFIndex)runIndex origin:(CGPoint)lineOrigin
-{
-    CFRetain(runs);
-    CGContextRetain(context);
-    
-    CGContextSaveGState(context);
-    CGFloat xHeight = 0, underLinePosition = 0, lineThickness = 0;
-    CTRunRef run = CFArrayGetValueAtIndex(runs, runIndex);
-    WXTextGetRunsMaxMetric(runs, &xHeight, &underLinePosition, &lineThickness);
-    
-    CGPoint strikethroughStart;
-    strikethroughStart.x =  lineOrigin.x - underLinePosition;
-    strikethroughStart.y = lineOrigin.y + xHeight/2;
-    CGPoint runPosition = CGPointZero;
-    CTRunGetPositions(run, CFRangeMake(0, 1), &runPosition);
-    strikethroughStart.x = lineOrigin.x + runPosition.x;
-    CGContextSetLineWidth(context, WXTextDefaultLineThroughWidth);
-    double length = CTRunGetTypographicBounds(run, CFRangeMake(0, 0), NULL, NULL, NULL);
-    CGContextMoveToPoint(context, strikethroughStart.x, strikethroughStart.y);
-    CGContextAddLineToPoint(context, strikethroughStart.x + length, strikethroughStart.y);
-    CGContextStrokePath(context);
-    
-    CGContextRestoreGState(context);
-    CFRelease(runs);
-    CGContextRelease(context);
-}
-
-- (CGSize)calculateTextHeightWithWidth:(CGFloat)aWidth
-{
-    CGFloat totalHeight = 0;
-    CGSize suggestSize = CGSizeZero;
-    NSAttributedString * attributedStringCpy = [self ctAttributedString];
-    if (!attributedStringCpy) {
-        return CGSizeZero;
-    }
-    if (isnan(aWidth)) {
-        aWidth = CGFLOAT_MAX;
-    }
-    aWidth = [attributedStringCpy boundingRectWithSize:CGSizeMake(aWidth, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading context:nil].size.width;
-    CTFramesetterRef ctframesetterRef = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)(attributedStringCpy));
-    suggestSize = CTFramesetterSuggestFrameSizeWithConstraints(ctframesetterRef, CFRangeMake(0, 0), NULL, CGSizeMake(aWidth, MAXFLOAT), NULL);
-    
-    CGMutablePathRef path = NULL;
-    path = CGPathCreateMutable();
-        // sufficient height to draw text
-    CGPathAddRect(path, NULL, CGRectMake(0, 0, aWidth, suggestSize.height * 10));
-        
-    CTFrameRef frameRef = NULL;
-    frameRef = CTFramesetterCreateFrame(ctframesetterRef, CFRangeMake(0, attributedStringCpy.length), path, NULL);
-    CGPathRelease(path);
-    
-    CFArrayRef lines = NULL;
-    if (NULL == frameRef) {
-        //try to protect unexpected crash.
-        return suggestSize;
-    }
-    CFRelease(ctframesetterRef);
-    ctframesetterRef = NULL;
-    lines = CTFrameGetLines(frameRef);
-    CFIndex lineCount = CFArrayGetCount(lines);
-    CGFloat ascent = 0;
-    CGFloat descent = 0;
-    CGFloat leading = 0;
-    
-    // height = ascent + descent + lineCount*leading
-    // ignore linespaing
-    NSUInteger actualLineCount = 0;
-    for (CFIndex lineIndex = 0; (!_lines|| lineIndex < _lines) && lineIndex < lineCount; lineIndex ++)
-    {
-        CTLineRef lineRef = NULL;
-        lineRef = CFArrayGetValueAtIndex(lines, lineIndex);
-        CTLineGetTypographicBounds(lineRef, &ascent, &descent, &leading);
-        totalHeight += ascent + descent;
-        actualLineCount ++;
-    }
-    
-    totalHeight = totalHeight + actualLineCount * leading;
-    CFRelease(frameRef);
-    frameRef = NULL;
-    
-    if (WX_SYS_VERSION_LESS_THAN(@"10.0")) {
-        // there is something wrong with coreText drawing text height, trying to fix this with more efficent way.
-        if(actualLineCount && actualLineCount < lineCount) {
-            suggestSize.height = suggestSize.height * actualLineCount / lineCount;
-        }
-        return CGSizeMake(aWidth, suggestSize.height);
-    }
-    return CGSizeMake(aWidth, totalHeight);
-}
-
-static void WXTextGetRunsMaxMetric(CFArrayRef runs, CGFloat *xHeight, CGFloat *underlinePosition, CGFloat *lineThickness)
-{
-    CFRetain(runs);
-    CGFloat maxXHeight = 0;
-    CGFloat maxUnderlinePos = 0;
-    CGFloat maxLineThickness = 0;
-    for (NSUInteger index = 0, runsCount = CFArrayGetCount(runs); index < runsCount; index ++) {
-        CTRunRef run = CFArrayGetValueAtIndex(runs, index);
-        CFDictionaryRef attrs = CTRunGetAttributes(run);
-        if (attrs) {
-            CTFontRef font = CFDictionaryGetValue(attrs, kCTFontAttributeName);
-            if (font) {
-                CGFloat xHeight = CTFontGetXHeight(font);
-                if (xHeight > maxXHeight) {
-                    maxXHeight = xHeight;
-                }
-                
-                CGFloat underlinePos = CTFontGetUnderlinePosition(font);
-                if (underlinePos < maxUnderlinePos) {
-                    maxUnderlinePos = underlinePos;
-                }
-                
-                CGFloat lineThickness = CTFontGetUnderlineThickness(font);
-                if (lineThickness > maxLineThickness) {
-                    maxLineThickness = lineThickness;
-                }
-            }
-        }
-    }
-    
-    if (xHeight) {
-        *xHeight = maxXHeight;
-    }
-    
-    if (underlinePosition) {
-        *underlinePosition = maxUnderlinePos;
-    }
-    
-    if (lineThickness) {
-        *lineThickness = maxLineThickness;
-    }
-    
-    CFRelease(runs);
-}
-                                                                                                                                       
-NS_INLINE NSRange WXNSRangeFromCFRange(CFRange range) {
-    return NSMakeRange(range.location, range.length);
-}
-
-#ifdef UITEST
-- (NSString *)description
-{
-    return super.description;
-}
-#endif
- 
-- (void)_resetCSSNodeStyles:(NSArray *)styles
-{
-    [super _resetCSSNodeStyles:styles];
-    if ([styles containsObject:@"color"]) {
-        _color = [UIColor blackColor];
-        [self setNeedsRepaint];
-    }
-    if ([styles containsObject:@"fontSize"]) {
-        _fontSize = WX_TEXT_FONT_SIZE;
-        [self setNeedsRepaint];
-        [self setNeedsLayout];
-    }
-}
-
-@end
-