From be4eb0e7a8e8bd41c893678c60ce6f40d42039e0 Mon Sep 17 00:00:00 2001 From: acton393 Date: Thu, 6 Apr 2017 19:37:03 +0800 Subject: [PATCH 01/16] * [ios] refactor text draw --- .../Sources/Component/WXTextComponent.m | 142 ++++++++++++++++-- 1 file changed, 126 insertions(+), 16 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m index f18ac94589..d226b9a866 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m @@ -15,10 +15,12 @@ #import "WXRuleManager.h" #import "WXDefine.h" #import +#import @interface WXText : UIView @property (nonatomic, strong) NSTextStorage *textStorage; +@property (nonatomic, strong) NSMutableAttributedString * attributedString; @end @@ -57,20 +59,46 @@ - (UIImage *)drawTextWithBounds:(CGRect)bounds padding:(UIEdgeInsets)padding [self.wx_component _resetNativeBorderRadius]; }); } - 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]; - - UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); - - UIGraphicsEndImageContext(); - - return image; + if (![[self.wx_component valueForKey:@"coretext"] boolValue]) { + 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]; + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + return image; + }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; + + //flip the coordinate system + CGContextRetain(context); + CGContextSetTextMatrix(context, CGAffineTransformIdentity); + CGContextTranslateCTM(context, 0, textFrame.size.height); + CGContextScaleCTM(context, 1.0, -1.0); + + //add path + CGMutablePathRef path = CGPathCreateMutable(); + CGPathAddRect(path, NULL, textFrame); + NSMutableAttributedString * attributedStringCopy = [_attributedString mutableCopy]; + CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attributedStringCopy); + CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL); + CTFrameDraw(frame, context); + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); + UIGraphicsEndImageContext(); + + CFRelease(frame); + CFRelease(framesetter); + CGPathRelease(path); + CGContextRelease(context); + + return image; + } } - (void)setTextStorage:(NSTextStorage *)textStorage @@ -81,6 +109,13 @@ - (void)setTextStorage:(NSTextStorage *)textStorage } } +- (void)setAttributedString:(NSMutableAttributedString *)attributedString { + if (_attributedString != attributedString) { + _attributedString = attributedString; + [self.wx_component setNeedsDisplay]; + } +} + - (NSString *)description { NSString *superDescription = super.description; @@ -101,6 +136,10 @@ - (NSString *)accessibilityValue @end +@interface WXTextComponent() +@property (nonatomic, assign)BOOL coretext; +@end + @implementation WXTextComponent { UIEdgeInsets _border; @@ -119,7 +158,6 @@ @implementation WXTextComponent WXTextDecoration _textDecoration; NSString *_textOverflow; CGFloat _lineHeight; - pthread_mutex_t _textStorageMutex; pthread_mutexattr_t _textStorageMutexAttr; @@ -145,7 +183,11 @@ - (instancetype)initWithRef:(NSString *)ref pthread_mutexattr_settype(&_textStorageMutexAttr, PTHREAD_MUTEX_RECURSIVE); pthread_mutex_init(&_textStorageMutex, &_textStorageMutexAttr); } - + if (attributes[@"coretext"]) { + _coretext = [WXConvert BOOL:attributes[@"coretext"]]; + } else { + _coretext = YES; + } [self fillCSSStyles:styles]; [self fillAttributes:attributes]; } @@ -248,6 +290,7 @@ - (void)viewDidLoad pthread_mutex_lock(&_textStorageMutex); } ((WXText *)self.view).textStorage = _textStorage; + ((WXText *)self.view).attributedString = [self buildCTAttributeString]; if (_isUsingTextStorageLock) { pthread_mutex_unlock(&_textStorageMutex); } @@ -339,6 +382,71 @@ - (void)repaintText:(NSNotification *)notification }); } +- (NSMutableAttributedString *)buildCTAttributeString { + + NSString *string = [self text] ?: @""; + + NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:string]; + + if (_color) { + [attributedString addAttribute:(id)kCTForegroundColorAttributeName value:_color range:NSMakeRange(0, string.length)]; + } + + if (_fontFamily) { + NSString * keyPath = [NSString stringWithFormat:@"%@.tempSrc", _fontFamily]; + NSString * fontSrc = [[[WXRuleManager sharedInstance] getRule:@"fontFace"] valueForKeyPath:keyPath]; + keyPath = [NSString stringWithFormat:@"%@.localSrc", _fontFamily]; + NSString * fontLocalSrc = [[[WXRuleManager sharedInstance] getRule:@"fontFace"] valueForKeyPath:keyPath]; + //custom localSrc is cached + if (!fontLocalSrc && fontSrc) { + // if use custom font, when the custom font download finish, refresh text. + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(repaintText:) name:WX_ICONFONT_DOWNLOAD_NOTIFICATION object:nil]; + } + } + + // set font + UIFont *font = [WXUtility fontWithSize:_fontSize textWeight:_fontWeight textStyle:_fontStyle fontFamily:_fontFamily scaleFactor:self.weexInstance.pixelScaleFactor]; + 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)]; + } + + 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]; + + if (_textAlign) { + paragraphStyle.alignment = _textAlign; + } + + if (_lineHeight) { + paragraphStyle.maximumLineHeight = _lineHeight; + paragraphStyle.minimumLineHeight = _lineHeight; + } + if (_lineHeight || _textAlign) { + [attributedString addAttribute:(id)kCTParagraphStyleAttributeName + value:paragraphStyle + range:(NSRange){0, attributedString.length}]; + } + + if ([self adjustLineHeight]) { + if (_lineHeight > font.lineHeight) { + [attributedString addAttribute:(id)kCTBaselineReferenceFont + value:@((_lineHeight - font.lineHeight)/ 2) + range:(NSRange){0, attributedString.length}]; + } + } + + + return attributedString; +} + - (NSAttributedString *)buildAttributeString { NSString *string = [self text] ?: @""; @@ -451,6 +559,7 @@ - (void)syncTextStorageForView { CGFloat width = self.calculatedFrame.size.width - (_padding.left + _padding.right); NSTextStorage *textStorage = [self textStorageWithWidth:width]; + NSMutableAttributedString * attributedString = [self buildCTAttributeString]; [self.weexInstance.componentManager _addUITask:^{ if ([self isViewLoaded]) { @@ -458,6 +567,7 @@ - (void)syncTextStorageForView pthread_mutex_lock(&_textStorageMutex); } ((WXText *)self.view).textStorage = textStorage; + ((WXText *)self.view).attributedString = attributedString; if (_isUsingTextStorageLock) { pthread_mutex_unlock(&_textStorageMutex); } From c94e48b6d1ed5bbe1f9b42bd93c5c226b5008be2 Mon Sep 17 00:00:00 2001 From: acton393 Date: Mon, 10 Apr 2017 12:17:03 +0800 Subject: [PATCH 02/16] * [ios] line by line to draw --- .../Sources/Component/WXTextComponent.m | 50 +++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m index d226b9a866..9f8315fba3 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m @@ -88,7 +88,44 @@ - (UIImage *)drawTextWithBounds:(CGRect)bounds padding:(UIEdgeInsets)padding NSMutableAttributedString * attributedStringCopy = [_attributedString mutableCopy]; CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attributedStringCopy); CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL); - CTFrameDraw(frame, context); + + CFArrayRef lines = CTFrameGetLines(frame); + CFIndex lineCount = CFArrayGetCount(lines); + CGPoint lineOrigins[lineCount]; + CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), lineOrigins); + + CGFloat frameY = 0; + for (CFIndex index = 0; index < lineCount; index ++) { + CTLineRef lineRef = CFArrayGetValueAtIndex(lines, index); + CGFloat lineAscent; + CGFloat lineDescent; + CGFloat lineLeading; + + CTLineGetTypographicBounds(lineRef, &lineAscent, &lineDescent, &lineLeading); + CGPoint lineOrigin = lineOrigins[index]; + + NSLog(@"lineAscent = %f",lineAscent); + NSLog(@"lineDescent = %f",lineDescent); + NSLog(@"lineLeading = %f",lineLeading); + + if (index > 0) { + frameY = frameY - lineAscent; + }else { + frameY = lineOrigin.y; + } + lineOrigin.x += padding.left; + lineOrigin.y -= padding.top; + NSLog(@"lines: %ld origin: %@",index, NSStringFromCGPoint(lineOrigin)); + CGContextSetTextPosition(context, lineOrigin.x, lineOrigin.y); +// CTLineDraw(lineRef, context); + CFArrayRef runs = CTLineGetGlyphRuns(lineRef); + for (CFIndex runIndex = 0; runIndex < CFArrayGetCount(runs); runIndex ++) { + CTRunRef run = CFArrayGetValueAtIndex(runs, runIndex); + CTRunDraw(run, context, CFRangeMake(0, 0)); + } + frameY = frameY - lineDescent; + } + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); @@ -425,11 +462,18 @@ - (NSMutableAttributedString *)buildCTAttributeString { paragraphStyle.alignment = _textAlign; } + // set default lineBreakMode + paragraphStyle.lineBreakMode = NSLineBreakByClipping; + if (_textOverflow && [_textOverflow length] > 0) { + if ([_textOverflow isEqualToString:@"ellipsis"]) + paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail; + } + if (_lineHeight) { paragraphStyle.maximumLineHeight = _lineHeight; paragraphStyle.minimumLineHeight = _lineHeight; } - if (_lineHeight || _textAlign) { + if (_lineHeight || _textAlign || [_textOverflow length] > 0) { [attributedString addAttribute:(id)kCTParagraphStyleAttributeName value:paragraphStyle range:(NSRange){0, attributedString.length}]; @@ -511,7 +555,7 @@ - (NSAttributedString *)buildAttributeString - (BOOL)adjustLineHeight { - return YES; + return !_coretext; } - (NSTextStorage *)textStorageWithWidth:(CGFloat)width From ae6edeebcd9fa549f599b840e9cfc88f52aa64dc Mon Sep 17 00:00:00 2001 From: acton393 Date: Tue, 11 Apr 2017 11:37:15 +0800 Subject: [PATCH 03/16] * [ios] remove unused code --- .../WeexSDK/Sources/Component/WXTextComponent.m | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m index 5c501a9a3e..eb6eb82924 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m @@ -140,8 +140,6 @@ - (void)dealloc [[NSNotificationCenter defaultCenter] removeObserver:self]; } - - #define WX_STYLE_FILL_TEXT(key, prop, type, needLayout)\ do {\ id value = styles[@#key];\ @@ -545,7 +543,6 @@ - (void)drawTextWithContext:(CGContextRef)context bounds:(CGRect)bounds padding: textFrame.size.height = bounds.size.height*2; //flip the coordinate system - CGContextRetain(context); CGContextSetTextMatrix(context, CGAffineTransformIdentity); CGContextTranslateCTM(context, 0, textFrame.size.height); CGContextScaleCTM(context, 1.0, -1.0); @@ -554,6 +551,7 @@ - (void)drawTextWithContext:(CGContextRef)context bounds:(CGRect)bounds padding: CGMutablePathRef path = CGPathCreateMutable(); CGPathAddRect(path, NULL, textFrame); NSMutableAttributedString * attributedStringCopy = [self buildCTAttributeString]; + CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attributedStringCopy); CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL); @@ -562,7 +560,6 @@ - (void)drawTextWithContext:(CGContextRef)context bounds:(CGRect)bounds padding: CGPoint lineOrigins[lineCount]; CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), lineOrigins); - CGFloat frameY = 0; for (CFIndex index = 0; index < lineCount; index ++) { CTLineRef lineRef = CFArrayGetValueAtIndex(lines, index); CGFloat lineAscent; @@ -571,19 +568,8 @@ - (void)drawTextWithContext:(CGContextRef)context bounds:(CGRect)bounds padding: CTLineGetTypographicBounds(lineRef, &lineAscent, &lineDescent, &lineLeading); CGPoint lineOrigin = lineOrigins[index]; - - NSLog(@"lineAscent = %f",lineAscent); - NSLog(@"lineDescent = %f",lineDescent); - NSLog(@"lineLeading = %f",lineLeading); - - if (index > 0) { - frameY = frameY - lineAscent; - }else { - frameY = lineOrigin.y; - } lineOrigin.x += padding.left; lineOrigin.y -= padding.top; - NSLog(@"lines: %ld origin: %@",index, NSStringFromCGPoint(lineOrigin)); CGContextSetTextPosition(context, lineOrigin.x, lineOrigin.y); // CTLineDraw(lineRef, context); CFArrayRef runs = CTLineGetGlyphRuns(lineRef); @@ -591,7 +577,6 @@ - (void)drawTextWithContext:(CGContextRef)context bounds:(CGRect)bounds padding: CTRunRef run = CFArrayGetValueAtIndex(runs, runIndex); CTRunDraw(run, context, CFRangeMake(0, 0)); } - frameY = frameY - lineDescent; } CFRelease(frame); From 395ffc6e4f0de825219eba2276c48fc1b0320696 Mon Sep 17 00:00:00 2001 From: acton393 Date: Tue, 11 Apr 2017 12:45:13 +0800 Subject: [PATCH 04/16] * [ios] protect crash --- ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m index eb6eb82924..e9cc83fa3a 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m @@ -235,7 +235,7 @@ - (UIImage *)drawRect:(CGRect)rect; if (_isCompositingChild) { [self drawTextWithContext:context bounds:rect padding:_padding view:nil]; } else { - WXText *textView = ((WXText *)self.view); + WXText *textView = (WXText *)_view; [self drawTextWithContext:context bounds:rect padding:_padding view:textView]; } From 09d8869e2d1124591ec33cfcf0a776d3a13642d2 Mon Sep 17 00:00:00 2001 From: acton393 Date: Tue, 11 Apr 2017 16:09:16 +0800 Subject: [PATCH 05/16] * [ios] config replacement --- .../Sources/Component/WXTextComponent.m | 25 +++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m index e9cc83fa3a..2a81b9e22e 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m @@ -90,6 +90,8 @@ - (NSString *)accessibilityValue @end +static BOOL textRenderUsingCoreText; + @interface WXTextComponent() @property (nonatomic, assign)BOOL coretext; @end @@ -114,6 +116,16 @@ @implementation WXTextComponent CGFloat _lineHeight; } ++ (void)setRenderUsingCoreText:(BOOL)usingCoreText +{ + textRenderUsingCoreText = usingCoreText; +} + ++ (BOOL)textRenderUsingCoreText +{ + return textRenderUsingCoreText; +} + - (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDictionary *)styles @@ -123,11 +135,18 @@ - (instancetype)initWithRef:(NSString *)ref { self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]; if (self) { + // just for coretext and textkit render replacement if (attributes[@"coretext"]) { _coretext = [WXConvert BOOL:attributes[@"coretext"]]; } else { _coretext = YES; } + BOOL renderUsingCoreText = YES; + if (weexInstance.userInfo[@"renderUsingCoreText"]) { + renderUsingCoreText = [weexInstance.userInfo[@"renderUsingCoreText"] boolValue]; + } + [WXTextComponent setRenderUsingCoreText:renderUsingCoreText]; + [self fillCSSStyles:styles]; [self fillAttributes:attributes]; } @@ -333,6 +352,8 @@ - (NSMutableAttributedString *)buildCTAttributeString { [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){ @@ -438,7 +459,7 @@ - (NSAttributedString *)buildAttributeString - (BOOL)adjustLineHeight { - return !_coretext; + return !(_coretext && [WXTextComponent textRenderUsingCoreText]); } - (NSTextStorage *)textStorageWithWidth:(CGFloat)width @@ -528,7 +549,7 @@ - (void)drawTextWithContext:(CGContextRef)context bounds:(CGRect)bounds padding: [self _resetNativeBorderRadius]; }); } - if (!self.coretext) { + if (![WXTextComponent textRenderUsingCoreText] || !self.coretext) { NSLayoutManager *layoutManager = _textStorage.layoutManagers.firstObject; NSTextContainer *textContainer = layoutManager.textContainers.firstObject; From 2b548d496d93cae0e2c8e3ca7cd0314b2138a9c0 Mon Sep 17 00:00:00 2001 From: acton393 Date: Wed, 12 Apr 2017 01:55:48 +0800 Subject: [PATCH 06/16] * [ios] bugfix use opaque canvas according to whether needs draw border --- ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m b/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m index 918f31309d..dac3c4cc76 100644 --- a/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m +++ b/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m @@ -564,7 +564,7 @@ - (BOOL)_bitmapOpaqueWithSize:(CGSize)size WXRoundedRect *borderRect = [[WXRoundedRect alloc] initWithRect:rect topLeft:_borderTopLeftRadius topRight:_borderTopRightRadius bottomLeft:_borderBottomLeftRadius bottomRight:_borderBottomRightRadius]; WXRadii *radii = borderRect.radii; BOOL hasBorderRadius = [radii hasBorderRadius]; - return (!hasBorderRadius) && _opacity == 1.0 && CGColorGetAlpha(_backgroundColor.CGColor) == 1.0; + return (!hasBorderRadius) && _opacity == 1.0 && CGColorGetAlpha(_backgroundColor.CGColor) == 1.0 && [self _needsDrawBorder]; } #pragma mark - Deprecated From a95a0623f1fb185009b55da27326d3c056bf8b70 Mon Sep 17 00:00:00 2001 From: acton393 Date: Wed, 12 Apr 2017 01:57:22 +0800 Subject: [PATCH 07/16] * [ios] draw line-through --- .../Sources/Component/WXTextComponent.m | 82 +++++++++++++++++-- 1 file changed, 74 insertions(+), 8 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m index 2a81b9e22e..09e61e1780 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m @@ -136,7 +136,7 @@ - (instancetype)initWithRef:(NSString *)ref self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]; if (self) { // just for coretext and textkit render replacement - if (attributes[@"coretext"]) { + if ([attributes objectForKey:@"coretext"]) { _coretext = [WXConvert BOOL:attributes[@"coretext"]]; } else { _coretext = YES; @@ -265,11 +265,15 @@ - (UIImage *)drawRect:(CGRect)rect; { __weak typeof(self) weakSelf = self; return ^CGSize (CGSize constrainedSize) { + CGSize computedSize = CGSizeZero; NSTextStorage *textStorage = [weakSelf textStorageWithWidth:constrainedSize.width]; - - NSLayoutManager *layoutManager = textStorage.layoutManagers.firstObject; - NSTextContainer *textContainer = layoutManager.textContainers.firstObject; - CGSize computedSize = [layoutManager usedRectForTextContainer:textContainer].size; + if (!(weakSelf.coretext && [WXTextComponent textRenderUsingCoreText]) ) { + NSLayoutManager *layoutManager = textStorage.layoutManagers.firstObject; + NSTextContainer *textContainer = layoutManager.textContainers.firstObject; + computedSize = [layoutManager usedRectForTextContainer:textContainer].size; + } else { + computedSize = [[weakSelf buildCTAttributeString] boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin context:nil].size; + } //TODO:more elegant way to use max and min constrained size if (!isnan(weakSelf.cssNode->style.minDimensions[CSS_WIDTH])) { @@ -562,7 +566,7 @@ - (void)drawTextWithContext:(CGContextRef)context bounds:(CGRect)bounds padding: 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); @@ -580,7 +584,6 @@ - (void)drawTextWithContext:(CGContextRef)context bounds:(CGRect)bounds padding: CFIndex lineCount = CFArrayGetCount(lines); CGPoint lineOrigins[lineCount]; CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), lineOrigins); - for (CFIndex index = 0; index < lineCount; index ++) { CTLineRef lineRef = CFArrayGetValueAtIndex(lines, index); CGFloat lineAscent; @@ -592,17 +595,80 @@ - (void)drawTextWithContext:(CGContextRef)context bounds:(CGRect)bounds padding: lineOrigin.x += padding.left; lineOrigin.y -= padding.top; CGContextSetTextPosition(context, lineOrigin.x, lineOrigin.y); - // CTLineDraw(lineRef, context); CFArrayRef runs = CTLineGetGlyphRuns(lineRef); + CGFloat xHeight = 0, underLinePosition = 0, lineThickness = 0 ; + WXTextGetRunsMaxMetric(runs, &xHeight, &underLinePosition, &lineThickness); + CGPoint strikethroughStart; + strikethroughStart.x = lineOrigin.x - underLinePosition; + strikethroughStart.y = lineOrigin.y + xHeight/2; for (CFIndex runIndex = 0; runIndex < CFArrayGetCount(runs); runIndex ++) { CTRunRef run = CFArrayGetValueAtIndex(runs, runIndex); CTRunDraw(run, context, CFRangeMake(0, 0)); + CFDictionaryRef attr = CTRunGetAttributes(run); + NSUnderlineStyle strikethrough = (NSUnderlineStyle)CFDictionaryGetValue(attr, NSStrikethroughStyleAttributeName); + + if (strikethrough) { + // currently draw strikethrough + CGPoint runPosition = CGPointZero; + CTRunGetPositions(run, CFRangeMake(0, 1), &runPosition); + strikethroughStart.x = lineOrigin.x + runPosition.x; + CGContextSetLineWidth(context, 1.5); + 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); + } + } } CFRelease(frame); CFRelease(framesetter); CGPathRelease(path); + + CGContextRestoreGState(context); + } +} + +static void WXTextGetRunsMaxMetric(CFArrayRef runs, CGFloat *xHeight, CGFloat *underlinePosition, CGFloat *lineThickness) { + 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; } } From ade22d61b6db98e1690e0c0b31349bfbae55febf Mon Sep 17 00:00:00 2001 From: acton393 Date: Thu, 13 Apr 2017 02:45:51 +0800 Subject: [PATCH 08/16] * [ios] fix text refactor mutli line bug --- .../Sources/Component/WXTextComponent.m | 96 ++++++++++++------- 1 file changed, 60 insertions(+), 36 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m index 09e61e1780..9df7fef12d 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m @@ -29,10 +29,7 @@ #import @interface WXText : UIView - @property (nonatomic, strong) NSTextStorage *textStorage; -@property (nonatomic, strong) NSMutableAttributedString * attributedString; - @end @implementation WXText @@ -63,13 +60,6 @@ - (void)setTextStorage:(NSTextStorage *)textStorage } } -- (void)setAttributedString:(NSMutableAttributedString *)attributedString { - if (_attributedString != attributedString) { - _attributedString = attributedString; - [self.wx_component setNeedsDisplay]; - } -} - - (NSString *)description { NSString *superDescription = super.description; @@ -114,6 +104,8 @@ @implementation WXTextComponent WXTextDecoration _textDecoration; NSString *_textOverflow; CGFloat _lineHeight; + + CTFrameRef coretextFrameRef; } + (void)setRenderUsingCoreText:(BOOL)usingCoreText @@ -154,9 +146,17 @@ - (instancetype)initWithRef:(NSString *)ref return self; } +- (BOOL)useCoreText +{ + return (_coretext || [WXTextComponent textRenderUsingCoreText]); +} + - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; + if (coretextFrameRef && CFGetRetainCount(coretextFrameRef)) { + CFRelease(coretextFrameRef); + } } #define WX_STYLE_FILL_TEXT(key, prop, type, needLayout)\ @@ -234,7 +234,6 @@ - (void)setNeedsLayout - (void)viewDidLoad { ((WXText *)self.view).textStorage = _textStorage; - ((WXText *)self.view).attributedString = [self buildCTAttributeString]; [self setNeedsDisplay]; } @@ -272,9 +271,9 @@ - (UIImage *)drawRect:(CGRect)rect; NSTextContainer *textContainer = layoutManager.textContainers.firstObject; computedSize = [layoutManager usedRectForTextContainer:textContainer].size; } else { - computedSize = [[weakSelf buildCTAttributeString] boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin context:nil].size; + computedSize = [weakSelf calculateTextHeightWithWidth:constrainedSize.width]; } - + //TODO:more elegant way to use max and min constrained size if (!isnan(weakSelf.cssNode->style.minDimensions[CSS_WIDTH])) { computedSize.width = MAX(computedSize.width, weakSelf.cssNode->style.minDimensions[CSS_WIDTH]); @@ -356,8 +355,6 @@ - (NSMutableAttributedString *)buildCTAttributeString { [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){ @@ -371,9 +368,10 @@ - (NSMutableAttributedString *)buildCTAttributeString { } // set default lineBreakMode - paragraphStyle.lineBreakMode = NSLineBreakByClipping; + // TODO:default clip + paragraphStyle.lineBreakMode = NSLineBreakByCharWrapping; if (_textOverflow && [_textOverflow length] > 0) { - if ([_textOverflow isEqualToString:@"ellipsis"]) + if (_lines && [_textOverflow isEqualToString:@"ellipsis"]) paragraphStyle.lineBreakMode = NSLineBreakByTruncatingTail; } @@ -395,6 +393,7 @@ - (NSMutableAttributedString *)buildCTAttributeString { } } + CFRelease(ctFont); return attributedString; } @@ -463,7 +462,7 @@ - (NSAttributedString *)buildAttributeString - (BOOL)adjustLineHeight { - return !(_coretext && [WXTextComponent textRenderUsingCoreText]); + return ![self useCoreText]; } - (NSTextStorage *)textStorageWithWidth:(CGFloat)width @@ -504,12 +503,9 @@ - (void)syncTextStorageForView { CGFloat width = self.calculatedFrame.size.width - (_padding.left + _padding.right); NSTextStorage *textStorage = [self textStorageWithWidth:width]; - NSMutableAttributedString * attributedString = [self buildCTAttributeString]; - [self.weexInstance.componentManager _addUITask:^{ if ([self isViewLoaded]) { ((WXText *)self.view).textStorage = textStorage; - ((WXText *)self.view).attributedString = attributedString; [self readyToRender]; // notify super component [self setNeedsDisplay]; } @@ -572,26 +568,21 @@ - (void)drawTextWithContext:(CGContextRef)context bounds:(CGRect)bounds padding: CGContextTranslateCTM(context, 0, textFrame.size.height); CGContextScaleCTM(context, 1.0, -1.0); + NSMutableAttributedString * attributedStringCopy = [self buildCTAttributeString]; //add path CGMutablePathRef path = CGPathCreateMutable(); CGPathAddRect(path, NULL, textFrame); - NSMutableAttributedString * attributedStringCopy = [self buildCTAttributeString]; - CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attributedStringCopy); - CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL); + coretextFrameRef = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL); - CFArrayRef lines = CTFrameGetLines(frame); + CFArrayRef lines = CTFrameGetLines(coretextFrameRef); CFIndex lineCount = CFArrayGetCount(lines); CGPoint lineOrigins[lineCount]; - CTFrameGetLineOrigins(frame, CFRangeMake(0, 0), lineOrigins); - for (CFIndex index = 0; index < lineCount; index ++) { - CTLineRef lineRef = CFArrayGetValueAtIndex(lines, index); - CGFloat lineAscent; - CGFloat lineDescent; - CGFloat lineLeading; + CTFrameGetLineOrigins(coretextFrameRef, CFRangeMake(0, 0), lineOrigins); + for (CFIndex lineIndex = 0;(!_lines || _lines > lineIndex) && lineIndex < lineCount; lineIndex ++) { - CTLineGetTypographicBounds(lineRef, &lineAscent, &lineDescent, &lineLeading); - CGPoint lineOrigin = lineOrigins[index]; + CTLineRef lineRef = CFArrayGetValueAtIndex(lines, lineIndex); + CGPoint lineOrigin = lineOrigins[lineIndex]; lineOrigin.x += padding.left; lineOrigin.y -= padding.top; CGContextSetTextPosition(context, lineOrigin.x, lineOrigin.y); @@ -621,15 +612,48 @@ - (void)drawTextWithContext:(CGContextRef)context bounds:(CGRect)bounds padding: } } - - CFRelease(frame); CFRelease(framesetter); CGPathRelease(path); - CGContextRestoreGState(context); } } +- (CGSize)calculateTextHeightWithWidth:(CGFloat)aWidth +{ + if (isnan(aWidth)) { + aWidth = CGFLOAT_MAX; + } + NSAttributedString * attributedStringCpy = [self buildCTAttributeString]; + CTFramesetterRef framesetterRef = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attributedStringCpy); + + CGSize suggestSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetterRef, CFRangeMake(0, attributedStringCpy.length), NULL, CGSizeMake(aWidth, MAXFLOAT), NULL); + + CGMutablePathRef path = CGPathCreateMutable(); + CGPathAddRect(path, NULL, CGRectMake(0, 0, aWidth, suggestSize.height*10)); + + CTFrameRef frameRef = CTFramesetterCreateFrame(framesetterRef, CFRangeMake(0, attributedStringCpy.length), path, NULL); + + CFArrayRef lines = CTFrameGetLines(frameRef); + CFIndex lineCount = CFArrayGetCount(lines); + CGFloat ascent = 0; + CGFloat descent = 0; + CGFloat leading = 0; + CGFloat totalHeight = 0; + // height = ascent + descent + lineCount*leading + // ignore linespaing + NSUInteger actualLineCount = 0; + for (CFIndex lineIndex = 0; (!_lines|| lineIndex < _lines) && lineIndex < lineCount; lineIndex ++) + { + CTLineRef lineRef = CFArrayGetValueAtIndex(lines, lineIndex); + CTLineGetTypographicBounds(lineRef, &ascent, &descent, &leading); + totalHeight += ascent + descent; + actualLineCount ++; + } + + totalHeight = totalHeight + actualLineCount*leading; + return CGSizeMake(suggestSize.width, totalHeight); +} + static void WXTextGetRunsMaxMetric(CFArrayRef runs, CGFloat *xHeight, CGFloat *underlinePosition, CGFloat *lineThickness) { CGFloat maxXHeight = 0; CGFloat maxUnderlinePos = 0; From 6cca6f8a8d7e852830299cf183d91701a159a3d3 Mon Sep 17 00:00:00 2001 From: acton393 Date: Thu, 13 Apr 2017 14:47:57 +0800 Subject: [PATCH 09/16] * [ios] iconfont refactor --- ios/sdk/WeexSDK/Sources/Utility/WXUtility.m | 30 ++++++++++++--------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m index 6cb533475c..466a56382b 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m @@ -455,20 +455,24 @@ + (UIFont *)fontWithSize:(CGFloat)size textWeight:(CGFloat)textWeight textStyle: // if the font file is not the correct font file. it will crash by singal 9 CFURLRef fontURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (__bridge CFStringRef)fpath, kCFURLPOSIXPathStyle, false); if (fontURL) { - CFErrorRef error = nil; - CTFontManagerRegisterFontsForURL(fontURL, kCTFontManagerScopeProcess, &error); - if (error) { - CFRelease(error); - error = nil; - CTFontManagerUnregisterFontsForURL(fontURL, kCTFontManagerScopeProcess, NULL); - CTFontManagerRegisterFontsForURL(fontURL, kCTFontManagerScopeProcess, NULL); + CGDataProviderRef fontDataProvider = CGDataProviderCreateWithURL(fontURL); + if (fontDataProvider) { + CGFontRef newFont = CGFontCreateWithDataProvider(fontDataProvider); + CFErrorRef error = nil; + CTFontManagerRegisterGraphicsFont(newFont, &error); + // the same font family, remove it and register new one. + if (error) { + CTFontManagerUnregisterGraphicsFont(newFont, NULL); + CTFontManagerRegisterGraphicsFont(newFont, NULL); + CFRelease(error); + error = nil; + } + fontFamily = (__bridge_transfer NSString*)CGFontCopyPostScriptName(newFont); + CGFontRelease(newFont); + CFRelease(fontURL); + CFRelease(fontDataProvider); } - NSArray *descriptors = (__bridge_transfer NSArray *)CTFontManagerCreateFontDescriptorsFromURL(fontURL); - // length of descriptors here will be only one. - for (UIFontDescriptor *desc in descriptors) { - font = [UIFont fontWithDescriptor:desc size:fontSize]; - } - CFRelease(fontURL); + } }else { [[WXRuleManager sharedInstance] removeRule:@"fontFace" rule:@{@"fontFamily": fontFamily}]; From dc3e708b97bd763d8ee40706ed09cbc7402f3199 Mon Sep 17 00:00:00 2001 From: acton393 Date: Thu, 13 Apr 2017 14:48:50 +0800 Subject: [PATCH 10/16] * [ios] default use textkit --- ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m index 9df7fef12d..a379c873d4 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m @@ -131,7 +131,7 @@ - (instancetype)initWithRef:(NSString *)ref if ([attributes objectForKey:@"coretext"]) { _coretext = [WXConvert BOOL:attributes[@"coretext"]]; } else { - _coretext = YES; + _coretext = NO; } BOOL renderUsingCoreText = YES; if (weexInstance.userInfo[@"renderUsingCoreText"]) { @@ -265,8 +265,9 @@ - (UIImage *)drawRect:(CGRect)rect; __weak typeof(self) weakSelf = self; return ^CGSize (CGSize constrainedSize) { CGSize computedSize = CGSizeZero; - NSTextStorage *textStorage = [weakSelf textStorageWithWidth:constrainedSize.width]; + NSTextStorage *textStorage = nil; if (!(weakSelf.coretext && [WXTextComponent textRenderUsingCoreText]) ) { + textStorage = [weakSelf textStorageWithWidth:constrainedSize.width]; NSLayoutManager *layoutManager = textStorage.layoutManagers.firstObject; NSTextContainer *textContainer = layoutManager.textContainers.firstObject; computedSize = [layoutManager usedRectForTextContainer:textContainer].size; @@ -290,7 +291,7 @@ - (UIImage *)drawRect:(CGRect)rect; if (!isnan(weakSelf.cssNode->style.maxDimensions[CSS_HEIGHT])) { computedSize.height = MIN(computedSize.height, weakSelf.cssNode->style.maxDimensions[CSS_HEIGHT]); } - if ([WXUtility isBlankString:textStorage.string]) { + if (textStorage && [WXUtility isBlankString:textStorage.string]) { // if the text value is empty or nil, then set the height is 0. computedSize.height = 0; } @@ -549,7 +550,7 @@ - (void)drawTextWithContext:(CGContextRef)context bounds:(CGRect)bounds padding: [self _resetNativeBorderRadius]; }); } - if (![WXTextComponent textRenderUsingCoreText] || !self.coretext) { + if (![self useCoreText]) { NSLayoutManager *layoutManager = _textStorage.layoutManagers.firstObject; NSTextContainer *textContainer = layoutManager.textContainers.firstObject; @@ -629,7 +630,8 @@ - (CGSize)calculateTextHeightWithWidth:(CGFloat)aWidth CGSize suggestSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetterRef, CFRangeMake(0, attributedStringCpy.length), NULL, CGSizeMake(aWidth, MAXFLOAT), NULL); CGMutablePathRef path = CGPathCreateMutable(); - CGPathAddRect(path, NULL, CGRectMake(0, 0, aWidth, suggestSize.height*10)); + // sufficient height to draw text + CGPathAddRect(path, NULL, CGRectMake(0, 0, aWidth, suggestSize.height * 10)); CTFrameRef frameRef = CTFramesetterCreateFrame(framesetterRef, CFRangeMake(0, attributedStringCpy.length), path, NULL); From e443027c1caaf3042995303f412168033b9378f8 Mon Sep 17 00:00:00 2001 From: acton393 Date: Thu, 13 Apr 2017 17:05:13 +0800 Subject: [PATCH 11/16] Revert "* [ios] iconfont refactor" This reverts commit 6cca6f8a8d7e852830299cf183d91701a159a3d3. --- ios/sdk/WeexSDK/Sources/Utility/WXUtility.m | 30 +++++++++------------ 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m index 466a56382b..6cb533475c 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m @@ -455,24 +455,20 @@ + (UIFont *)fontWithSize:(CGFloat)size textWeight:(CGFloat)textWeight textStyle: // if the font file is not the correct font file. it will crash by singal 9 CFURLRef fontURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (__bridge CFStringRef)fpath, kCFURLPOSIXPathStyle, false); if (fontURL) { - CGDataProviderRef fontDataProvider = CGDataProviderCreateWithURL(fontURL); - if (fontDataProvider) { - CGFontRef newFont = CGFontCreateWithDataProvider(fontDataProvider); - CFErrorRef error = nil; - CTFontManagerRegisterGraphicsFont(newFont, &error); - // the same font family, remove it and register new one. - if (error) { - CTFontManagerUnregisterGraphicsFont(newFont, NULL); - CTFontManagerRegisterGraphicsFont(newFont, NULL); - CFRelease(error); - error = nil; - } - fontFamily = (__bridge_transfer NSString*)CGFontCopyPostScriptName(newFont); - CGFontRelease(newFont); - CFRelease(fontURL); - CFRelease(fontDataProvider); + CFErrorRef error = nil; + CTFontManagerRegisterFontsForURL(fontURL, kCTFontManagerScopeProcess, &error); + if (error) { + CFRelease(error); + error = nil; + CTFontManagerUnregisterFontsForURL(fontURL, kCTFontManagerScopeProcess, NULL); + CTFontManagerRegisterFontsForURL(fontURL, kCTFontManagerScopeProcess, NULL); } - + NSArray *descriptors = (__bridge_transfer NSArray *)CTFontManagerCreateFontDescriptorsFromURL(fontURL); + // length of descriptors here will be only one. + for (UIFontDescriptor *desc in descriptors) { + font = [UIFont fontWithDescriptor:desc size:fontSize]; + } + CFRelease(fontURL); } }else { [[WXRuleManager sharedInstance] removeRule:@"fontFace" rule:@{@"fontFamily": fontFamily}]; From 57b37bd45f3fd2238d7f7cb03d5e339f6a584486 Mon Sep 17 00:00:00 2001 From: acton393 Date: Thu, 13 Apr 2017 17:08:46 +0800 Subject: [PATCH 12/16] Revert "Revert "* [ios] iconfont refactor"" This reverts commit e443027c1caaf3042995303f412168033b9378f8. --- ios/sdk/WeexSDK/Sources/Utility/WXUtility.m | 30 ++++++++++++--------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m index 6cb533475c..466a56382b 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m @@ -455,20 +455,24 @@ + (UIFont *)fontWithSize:(CGFloat)size textWeight:(CGFloat)textWeight textStyle: // if the font file is not the correct font file. it will crash by singal 9 CFURLRef fontURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (__bridge CFStringRef)fpath, kCFURLPOSIXPathStyle, false); if (fontURL) { - CFErrorRef error = nil; - CTFontManagerRegisterFontsForURL(fontURL, kCTFontManagerScopeProcess, &error); - if (error) { - CFRelease(error); - error = nil; - CTFontManagerUnregisterFontsForURL(fontURL, kCTFontManagerScopeProcess, NULL); - CTFontManagerRegisterFontsForURL(fontURL, kCTFontManagerScopeProcess, NULL); + CGDataProviderRef fontDataProvider = CGDataProviderCreateWithURL(fontURL); + if (fontDataProvider) { + CGFontRef newFont = CGFontCreateWithDataProvider(fontDataProvider); + CFErrorRef error = nil; + CTFontManagerRegisterGraphicsFont(newFont, &error); + // the same font family, remove it and register new one. + if (error) { + CTFontManagerUnregisterGraphicsFont(newFont, NULL); + CTFontManagerRegisterGraphicsFont(newFont, NULL); + CFRelease(error); + error = nil; + } + fontFamily = (__bridge_transfer NSString*)CGFontCopyPostScriptName(newFont); + CGFontRelease(newFont); + CFRelease(fontURL); + CFRelease(fontDataProvider); } - NSArray *descriptors = (__bridge_transfer NSArray *)CTFontManagerCreateFontDescriptorsFromURL(fontURL); - // length of descriptors here will be only one. - for (UIFontDescriptor *desc in descriptors) { - font = [UIFont fontWithDescriptor:desc size:fontSize]; - } - CFRelease(fontURL); + } }else { [[WXRuleManager sharedInstance] removeRule:@"fontFace" rule:@{@"fontFamily": fontFamily}]; From 155b4e0cf56bb788269f42eba56dcf5d916271c6 Mon Sep 17 00:00:00 2001 From: acton393 Date: Thu, 13 Apr 2017 17:33:49 +0800 Subject: [PATCH 13/16] * [ios] memory leak about coretext --- .../Sources/Component/WXTextComponent.m | 88 +++++++++++-------- 1 file changed, 49 insertions(+), 39 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m index a379c873d4..29f0b24301 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m @@ -80,7 +80,7 @@ - (NSString *)accessibilityValue @end -static BOOL textRenderUsingCoreText; +static BOOL textRenderUsingCoreText = NO; @interface WXTextComponent() @property (nonatomic, assign)BOOL coretext; @@ -104,8 +104,6 @@ @implementation WXTextComponent WXTextDecoration _textDecoration; NSString *_textOverflow; CGFloat _lineHeight; - - CTFrameRef coretextFrameRef; } + (void)setRenderUsingCoreText:(BOOL)usingCoreText @@ -133,11 +131,6 @@ - (instancetype)initWithRef:(NSString *)ref } else { _coretext = NO; } - BOOL renderUsingCoreText = YES; - if (weexInstance.userInfo[@"renderUsingCoreText"]) { - renderUsingCoreText = [weexInstance.userInfo[@"renderUsingCoreText"] boolValue]; - } - [WXTextComponent setRenderUsingCoreText:renderUsingCoreText]; [self fillCSSStyles:styles]; [self fillAttributes:attributes]; @@ -154,9 +147,6 @@ - (BOOL)useCoreText - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; - if (coretextFrameRef && CFGetRetainCount(coretextFrameRef)) { - CFRelease(coretextFrameRef); - } } #define WX_STYLE_FILL_TEXT(key, prop, type, needLayout)\ @@ -332,7 +322,7 @@ - (NSMutableAttributedString *)buildCTAttributeString { NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:string]; if (_color) { - [attributedString addAttribute:(id)kCTForegroundColorAttributeName value:_color range:NSMakeRange(0, string.length)]; + [attributedString addAttribute:NSForegroundColorAttributeName value:_color range:NSMakeRange(0, string.length)]; } if (_fontFamily) { @@ -381,14 +371,14 @@ - (NSMutableAttributedString *)buildCTAttributeString { paragraphStyle.minimumLineHeight = _lineHeight; } if (_lineHeight || _textAlign || [_textOverflow length] > 0) { - [attributedString addAttribute:(id)kCTParagraphStyleAttributeName + [attributedString addAttribute:NSParagraphStyleAttributeName value:paragraphStyle range:(NSRange){0, attributedString.length}]; } if ([self adjustLineHeight]) { if (_lineHeight > font.lineHeight) { - [attributedString addAttribute:(id)kCTBaselineReferenceFont + [attributedString addAttribute:NSBaselineOffsetAttributeName value:@((_lineHeight - font.lineHeight)/ 2) range:(NSRange){0, attributedString.length}]; } @@ -539,7 +529,7 @@ - (void)_updateAttributesOnComponentThread:(NSDictionary *)attributes - (void)drawTextWithContext:(CGContextRef)context bounds:(CGRect)bounds padding:(UIEdgeInsets)padding view:(WXText *)view { - if (bounds.size.width <=0 || bounds.size.height <= 0) { + if (bounds.size.width <= 0 || bounds.size.height <= 0) { return; } @@ -571,18 +561,24 @@ - (void)drawTextWithContext:(CGContextRef)context bounds:(CGRect)bounds padding: NSMutableAttributedString * attributedStringCopy = [self buildCTAttributeString]; //add path - CGMutablePathRef path = CGPathCreateMutable(); - CGPathAddRect(path, NULL, textFrame); - CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)attributedStringCopy); - coretextFrameRef = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL); - - CFArrayRef lines = CTFrameGetLines(coretextFrameRef); + CGPathRef path = NULL; + path = CGPathCreateWithRect(textFrame, NULL); + CTFramesetterRef framesetter = NULL; + framesetter = CTFramesetterCreateWithAttributedString((CFTypeRef)attributedStringCopy); + CTFrameRef coretextFrameRef = NULL; + coretextFrameRef = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL); + CGPathRelease(path); + path = NULL; + CFRelease(framesetter); + framesetter = NULL; + CFArrayRef lines = NULL; + lines = CTFrameGetLines(coretextFrameRef); CFIndex lineCount = CFArrayGetCount(lines); CGPoint lineOrigins[lineCount]; CTFrameGetLineOrigins(coretextFrameRef, CFRangeMake(0, 0), lineOrigins); for (CFIndex lineIndex = 0;(!_lines || _lines > lineIndex) && lineIndex < lineCount; lineIndex ++) { - - CTLineRef lineRef = CFArrayGetValueAtIndex(lines, lineIndex); + CTLineRef lineRef = NULL; + lineRef = CFArrayGetValueAtIndex(lines, lineIndex); CGPoint lineOrigin = lineOrigins[lineIndex]; lineOrigin.x += padding.left; lineOrigin.y -= padding.top; @@ -594,9 +590,11 @@ - (void)drawTextWithContext:(CGContextRef)context bounds:(CGRect)bounds padding: strikethroughStart.x = lineOrigin.x - underLinePosition; strikethroughStart.y = lineOrigin.y + xHeight/2; for (CFIndex runIndex = 0; runIndex < CFArrayGetCount(runs); runIndex ++) { - CTRunRef run = CFArrayGetValueAtIndex(runs, runIndex); + CTRunRef run = NULL; + run = CFArrayGetValueAtIndex(runs, runIndex); CTRunDraw(run, context, CFRangeMake(0, 0)); - CFDictionaryRef attr = CTRunGetAttributes(run); + CFDictionaryRef attr = NULL; + attr = CTRunGetAttributes(run); NSUnderlineStyle strikethrough = (NSUnderlineStyle)CFDictionaryGetValue(attr, NSStrikethroughStyleAttributeName); if (strikethrough) { @@ -610,11 +608,9 @@ - (void)drawTextWithContext:(CGContextRef)context bounds:(CGRect)bounds padding: CGContextAddLineToPoint(context, strikethroughStart.x + length, strikethroughStart.y); CGContextStrokePath(context); } - } } - CFRelease(framesetter); - CGPathRelease(path); + CFRelease(coretextFrameRef); CGContextRestoreGState(context); } } @@ -624,35 +620,49 @@ - (CGSize)calculateTextHeightWithWidth:(CGFloat)aWidth if (isnan(aWidth)) { aWidth = CGFLOAT_MAX; } - NSAttributedString * attributedStringCpy = [self buildCTAttributeString]; - CTFramesetterRef framesetterRef = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attributedStringCpy); - CGSize suggestSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetterRef, CFRangeMake(0, attributedStringCpy.length), NULL, CGSizeMake(aWidth, MAXFLOAT), NULL); - - CGMutablePathRef path = CGPathCreateMutable(); - // sufficient height to draw text + CGFloat totalHeight = 0; + CGSize suggestSize = CGSizeZero; + NSAttributedString * attributedStringCpy = [self buildCTAttributeString]; + CTFramesetterRef framesetterRef = NULL; + framesetterRef = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attributedStringCpy); + + suggestSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetterRef, CFRangeMake(0, attributedStringCpy.length), 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(framesetterRef, CFRangeMake(0, attributedStringCpy.length), path, NULL); + + CFRelease(framesetterRef); + CGPathRelease(path); + framesetterRef = NULL; - CTFrameRef frameRef = CTFramesetterCreateFrame(framesetterRef, CFRangeMake(0, attributedStringCpy.length), path, NULL); - - CFArrayRef lines = CTFrameGetLines(frameRef); + CFArrayRef lines = NULL; + lines = CTFrameGetLines(frameRef); CFIndex lineCount = CFArrayGetCount(lines); CGFloat ascent = 0; CGFloat descent = 0; CGFloat leading = 0; - CGFloat totalHeight = 0; + // height = ascent + descent + lineCount*leading // ignore linespaing NSUInteger actualLineCount = 0; for (CFIndex lineIndex = 0; (!_lines|| lineIndex < _lines) && lineIndex < lineCount; lineIndex ++) { - CTLineRef lineRef = CFArrayGetValueAtIndex(lines, lineIndex); + CTLineRef lineRef = NULL; + lineRef = CFArrayGetValueAtIndex(lines, lineIndex); CTLineGetTypographicBounds(lineRef, &ascent, &descent, &leading); totalHeight += ascent + descent; actualLineCount ++; } totalHeight = totalHeight + actualLineCount*leading; + CFRelease(frameRef); + return CGSizeMake(suggestSize.width, totalHeight); } From e2205bf270b9115b023ce7124ce62fea89888e5b Mon Sep 17 00:00:00 2001 From: acton393 Date: Thu, 13 Apr 2017 17:38:25 +0800 Subject: [PATCH 14/16] * [ios] iconfont accord config draw --- ios/sdk/WeexSDK/Sources/Component/WXTextComponent.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.h b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.h index d9a1269988..800a9094f3 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.h +++ b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.h @@ -21,4 +21,7 @@ @interface WXTextComponent : WXComponent ++ (void)setRenderUsingCoreText:(BOOL)usingCoreText; ++ (BOOL)textRenderUsingCoreText; + @end From efd56009158bca5fac3fea41c2c4c80a775d53cd Mon Sep 17 00:00:00 2001 From: acton393 Date: Thu, 13 Apr 2017 18:18:46 +0800 Subject: [PATCH 15/16] * [ios] adjust configuation --- .../Sources/Component/WXTextComponent.h | 2 +- .../Sources/Component/WXTextComponent.m | 26 ++++++------ ios/sdk/WeexSDK/Sources/Utility/WXUtility.m | 40 ++++++++++++++----- 3 files changed, 43 insertions(+), 25 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.h b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.h index 800a9094f3..7fb8f347e9 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.h +++ b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.h @@ -22,6 +22,6 @@ @interface WXTextComponent : WXComponent + (void)setRenderUsingCoreText:(BOOL)usingCoreText; -+ (BOOL)textRenderUsingCoreText; ++ (BOOL)useCoreText; @end diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m index 29f0b24301..a6d24d9c4b 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m @@ -81,10 +81,7 @@ - (NSString *)accessibilityValue @end static BOOL textRenderUsingCoreText = NO; - -@interface WXTextComponent() -@property (nonatomic, assign)BOOL coretext; -@end +static BOOL useCoreTextAttr = NO; @implementation WXTextComponent { @@ -127,9 +124,9 @@ - (instancetype)initWithRef:(NSString *)ref if (self) { // just for coretext and textkit render replacement if ([attributes objectForKey:@"coretext"]) { - _coretext = [WXConvert BOOL:attributes[@"coretext"]]; + useCoreTextAttr = [WXConvert BOOL:attributes[@"coretext"]]; } else { - _coretext = NO; + _useCoreTextAttr = NO; } [self fillCSSStyles:styles]; @@ -139,9 +136,15 @@ - (instancetype)initWithRef:(NSString *)ref return self; } -- (BOOL)useCoreText ++ (BOOL)useCoreText { - return (_coretext || [WXTextComponent textRenderUsingCoreText]); + if (useCoreTextAttr) { + return YES; + } + if ([WXTextComponent textRenderUsingCoreText]) { + return YES; + } + return NO; } - (void)dealloc @@ -256,7 +259,7 @@ - (UIImage *)drawRect:(CGRect)rect; return ^CGSize (CGSize constrainedSize) { CGSize computedSize = CGSizeZero; NSTextStorage *textStorage = nil; - if (!(weakSelf.coretext && [WXTextComponent textRenderUsingCoreText]) ) { + if (![self useCoreText]) { textStorage = [weakSelf textStorageWithWidth:constrainedSize.width]; NSLayoutManager *layoutManager = textStorage.layoutManagers.firstObject; NSTextContainer *textContainer = layoutManager.textContainers.firstObject; @@ -318,9 +321,7 @@ - (void)repaintText:(NSNotification *)notification - (NSMutableAttributedString *)buildCTAttributeString { NSString *string = [self text] ?: @""; - NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:string]; - if (_color) { [attributedString addAttribute:NSForegroundColorAttributeName value:_color range:NSMakeRange(0, string.length)]; } @@ -552,7 +553,7 @@ - (void)drawTextWithContext:(CGContextRef)context bounds:(CGRect)bounds padding: }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; + textFrame.size.height = bounds.size.height * 2; CGContextSaveGState(context); //flip the coordinate system CGContextSetTextMatrix(context, CGAffineTransformIdentity); @@ -676,7 +677,6 @@ static void WXTextGetRunsMaxMetric(CFArrayRef runs, CGFloat *xHeight, CGFloat *u if (attrs) { CTFontRef font = CFDictionaryGetValue(attrs, kCTFontAttributeName); if (font) { - CGFloat xHeight = CTFontGetXHeight(font); if (xHeight > maxXHeight) { maxXHeight = xHeight; diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m index 466a56382b..22faf0550c 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m @@ -33,6 +33,8 @@ #import #import +#import "WXTextComponent.h" + #define KEY_PASSWORD @"com.taobao.Weex.123456" #define KEY_USERNAME_PASSWORD @"com.taobao.Weex.weex123456" @@ -455,24 +457,40 @@ + (UIFont *)fontWithSize:(CGFloat)size textWeight:(CGFloat)textWeight textStyle: // if the font file is not the correct font file. it will crash by singal 9 CFURLRef fontURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (__bridge CFStringRef)fpath, kCFURLPOSIXPathStyle, false); if (fontURL) { - CGDataProviderRef fontDataProvider = CGDataProviderCreateWithURL(fontURL); - if (fontDataProvider) { - CGFontRef newFont = CGFontCreateWithDataProvider(fontDataProvider); + if ([WXTextComponent useCoreText]) { + CGDataProviderRef fontDataProvider = CGDataProviderCreateWithURL(fontURL); + if (fontDataProvider) { + CGFontRef newFont = CGFontCreateWithDataProvider(fontDataProvider); + CFErrorRef error = nil; + CTFontManagerRegisterGraphicsFont(newFont, &error); + // the same font family, remove it and register new one. + if (error) { + CTFontManagerUnregisterGraphicsFont(newFont, NULL); + CTFontManagerRegisterGraphicsFont(newFont, NULL); + CFRelease(error); + error = nil; + } + fontFamily = (__bridge_transfer NSString*)CGFontCopyPostScriptName(newFont); + CGFontRelease(newFont); + CFRelease(fontURL); + CFRelease(fontDataProvider); + } + } else { CFErrorRef error = nil; - CTFontManagerRegisterGraphicsFont(newFont, &error); - // the same font family, remove it and register new one. + CTFontManagerRegisterFontsForURL(fontURL, kCTFontManagerScopeProcess, &error); if (error) { - CTFontManagerUnregisterGraphicsFont(newFont, NULL); - CTFontManagerRegisterGraphicsFont(newFont, NULL); CFRelease(error); error = nil; + CTFontManagerUnregisterFontsForURL(fontURL, kCTFontManagerScopeProcess, NULL); + CTFontManagerRegisterFontsForURL(fontURL, kCTFontManagerScopeProcess, NULL); + } + NSArray *descriptors = (__bridge_transfer NSArray *)CTFontManagerCreateFontDescriptorsFromURL(fontURL); + // length of descriptors here will be only one. + for (UIFontDescriptor *desc in descriptors) { + font = [UIFont fontWithDescriptor:desc size:fontSize]; } - fontFamily = (__bridge_transfer NSString*)CGFontCopyPostScriptName(newFont); - CGFontRelease(newFont); CFRelease(fontURL); - CFRelease(fontDataProvider); } - } }else { [[WXRuleManager sharedInstance] removeRule:@"fontFace" rule:@{@"fontFamily": fontFamily}]; From 41f524f474f7fc17d637c46166ed57910aa1683e Mon Sep 17 00:00:00 2001 From: acton393 Date: Thu, 13 Apr 2017 18:44:38 +0800 Subject: [PATCH 16/16] * [ios] adjust configuration --- ios/sdk/WeexSDK/Sources/Component/WXTextComponent.h | 2 -- ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m | 13 ++++++++----- ios/sdk/WeexSDK/Sources/Utility/WXUtility.h | 2 ++ ios/sdk/WeexSDK/Sources/Utility/WXUtility.m | 9 +++++++-- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.h b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.h index 7fb8f347e9..8b616f4948 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.h +++ b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.h @@ -22,6 +22,4 @@ @interface WXTextComponent : WXComponent + (void)setRenderUsingCoreText:(BOOL)usingCoreText; -+ (BOOL)useCoreText; - @end diff --git a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m index a6d24d9c4b..d47e3f08fc 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/WXTextComponent.m @@ -81,7 +81,10 @@ - (NSString *)accessibilityValue @end static BOOL textRenderUsingCoreText = NO; -static BOOL useCoreTextAttr = NO; + +@interface WXTextComponent() +@property (nonatomic, assign)BOOL useCoreTextAttr; +@end @implementation WXTextComponent { @@ -124,7 +127,7 @@ - (instancetype)initWithRef:(NSString *)ref if (self) { // just for coretext and textkit render replacement if ([attributes objectForKey:@"coretext"]) { - useCoreTextAttr = [WXConvert BOOL:attributes[@"coretext"]]; + _useCoreTextAttr = [WXConvert BOOL:attributes[@"coretext"]]; } else { _useCoreTextAttr = NO; } @@ -136,9 +139,9 @@ - (instancetype)initWithRef:(NSString *)ref return self; } -+ (BOOL)useCoreText +- (BOOL)useCoreText { - if (useCoreTextAttr) { + if (_useCoreTextAttr) { return YES; } if ([WXTextComponent textRenderUsingCoreText]) { @@ -339,7 +342,7 @@ - (NSMutableAttributedString *)buildCTAttributeString { } // set font - UIFont *font = [WXUtility fontWithSize:_fontSize textWeight:_fontWeight textStyle:_fontStyle fontFamily:_fontFamily scaleFactor:self.weexInstance.pixelScaleFactor]; + 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); diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h index b265b23f94..39c4034614 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h +++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.h @@ -226,6 +226,8 @@ extern _Nonnull SEL WXSwizzledSelectorForSelector(_Nonnull SEL selector); */ + (UIFont *_Nonnull)fontWithSize:(CGFloat)size textWeight:(CGFloat)textWeight textStyle:(WXTextStyle)textStyle fontFamily:(NSString *_Nullable)fontFamily scaleFactor:(CGFloat)scaleFactor; ++ (UIFont *_Nonnull)fontWithSize:(CGFloat)size textWeight:(CGFloat)textWeight textStyle:(WXTextStyle)textStyle fontFamily:(NSString *_Nullable)fontFamily scaleFactor:(CGFloat)scaleFactor useCoreText:(BOOL)useCoreText; + /** * @abstract download remote font from specified url * @param fontURL for remote font diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m index 22faf0550c..048e7bc54d 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXUtility.m @@ -444,7 +444,7 @@ + (UIFont *)fontWithSize:(CGFloat)size textWeight:(CGFloat)textWeight textStyle: return [self fontWithSize:size textWeight:textWeight textStyle:textStyle fontFamily:fontFamily scaleFactor:[self defaultPixelScaleFactor]]; } -+ (UIFont *)fontWithSize:(CGFloat)size textWeight:(CGFloat)textWeight textStyle:(WXTextStyle)textStyle fontFamily:(NSString *)fontFamily scaleFactor:(CGFloat)scaleFactor ++ (UIFont *)fontWithSize:(CGFloat)size textWeight:(CGFloat)textWeight textStyle:(WXTextStyle)textStyle fontFamily:(NSString *)fontFamily scaleFactor:(CGFloat)scaleFactor useCoreText:(BOOL)useCoreText { CGFloat fontSize = (isnan(size) || size == 0) ? 32 * scaleFactor : size; UIFont *font = nil; @@ -457,7 +457,7 @@ + (UIFont *)fontWithSize:(CGFloat)size textWeight:(CGFloat)textWeight textStyle: // if the font file is not the correct font file. it will crash by singal 9 CFURLRef fontURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (__bridge CFStringRef)fpath, kCFURLPOSIXPathStyle, false); if (fontURL) { - if ([WXTextComponent useCoreText]) { + if (useCoreText) { CGDataProviderRef fontDataProvider = CGDataProviderCreateWithURL(fontURL); if (fontDataProvider) { CGFontRef newFont = CGFontCreateWithDataProvider(fontDataProvider); @@ -531,6 +531,11 @@ + (UIFont *)fontWithSize:(CGFloat)size textWeight:(CGFloat)textWeight textStyle: return font; } ++ (UIFont *)fontWithSize:(CGFloat)size textWeight:(CGFloat)textWeight textStyle:(WXTextStyle)textStyle fontFamily:(NSString *)fontFamily scaleFactor:(CGFloat)scaleFactor +{ + return [self fontWithSize:size textWeight:textWeight textStyle:textStyle fontFamily:fontFamily scaleFactor:scaleFactor useCoreText:NO]; +} + + (void)getIconfont:(NSURL *)url completion:(void(^)(NSURL *url, NSError *error))completionBlock { dispatch_async(dispatch_get_global_queue(0, 0), ^{