From 17cb6a8aebb34b640d633ef40badca48b7fb2712 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Sun, 3 Mar 2019 12:04:03 -0800 Subject: [PATCH] Fabric: Caching for `NSAttributedString`s in RCTTextLayoutManager Summary: Creation NSAttributedString from attributedString is not so cheap process, so with this simple cache we hopefully can save a couple milliseconds. The same string is used at least two times: first time for measuring and second for drawing. Reviewed By: mdvacca Differential Revision: D14296514 fbshipit-source-id: 6313aa2c6e9f63d873868131750f61c02d64d2de --- .../platform/ios/RCTTextLayoutManager.mm | 43 ++++++++++++------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/ReactCommon/fabric/textlayoutmanager/platform/ios/RCTTextLayoutManager.mm b/ReactCommon/fabric/textlayoutmanager/platform/ios/RCTTextLayoutManager.mm index 0e885b26037..94fed1a895d 100644 --- a/ReactCommon/fabric/textlayoutmanager/platform/ios/RCTTextLayoutManager.mm +++ b/ReactCommon/fabric/textlayoutmanager/platform/ios/RCTTextLayoutManager.mm @@ -10,9 +10,13 @@ #import "NSTextStorage+FontScaling.h" #import "RCTAttributedTextUtils.h" +#import + using namespace facebook::react; -@implementation RCTTextLayoutManager +@implementation RCTTextLayoutManager { + SimpleThreadSafeCache, 256> _cache; +} static NSLineBreakMode RCTNSLineBreakModeFromWritingDirection( EllipsizeMode ellipsizeMode) { @@ -34,11 +38,10 @@ static NSLineBreakMode RCTNSLineBreakModeFromWritingDirection( layoutConstraints:(LayoutConstraints)layoutConstraints { CGSize maximumSize = CGSize{layoutConstraints.maximumSize.width, layoutConstraints.maximumSize.height}; - NSTextStorage *textStorage = - [self _textStorageAndLayoutManagerWithAttributesString: - RCTNSAttributedStringFromAttributedString(attributedString) - paragraphAttributes:paragraphAttributes - size:maximumSize]; + NSTextStorage *textStorage = [self + _textStorageAndLayoutManagerWithAttributesString:[self _nsAttributedStringFromAttributedString:attributedString] + paragraphAttributes:paragraphAttributes + size:maximumSize]; NSLayoutManager *layoutManager = textStorage.layoutManagers.firstObject; NSTextContainer *textContainer = layoutManager.textContainers.firstObject; @@ -55,11 +58,10 @@ static NSLineBreakMode RCTNSLineBreakModeFromWritingDirection( - (void)drawAttributedString:(AttributedString)attributedString paragraphAttributes:(ParagraphAttributes)paragraphAttributes frame:(CGRect)frame { - NSTextStorage *textStorage = - [self _textStorageAndLayoutManagerWithAttributesString: - RCTNSAttributedStringFromAttributedString(attributedString) - paragraphAttributes:paragraphAttributes - size:frame.size]; + NSTextStorage *textStorage = [self + _textStorageAndLayoutManagerWithAttributesString:[self _nsAttributedStringFromAttributedString:attributedString] + paragraphAttributes:paragraphAttributes + size:frame.size]; NSLayoutManager *layoutManager = textStorage.layoutManagers.firstObject; NSTextContainer *textContainer = layoutManager.textContainers.firstObject; @@ -111,11 +113,10 @@ static NSLineBreakMode RCTNSLineBreakModeFromWritingDirection( paragraphAttributes:(ParagraphAttributes)paragraphAttributes frame:(CGRect)frame atPoint:(CGPoint)point { - NSTextStorage *textStorage = - [self _textStorageAndLayoutManagerWithAttributesString: - RCTNSAttributedStringFromAttributedString(attributedString) - paragraphAttributes:paragraphAttributes - size:frame.size]; + NSTextStorage *textStorage = [self + _textStorageAndLayoutManagerWithAttributesString:[self _nsAttributedStringFromAttributedString:attributedString] + paragraphAttributes:paragraphAttributes + size:frame.size]; NSLayoutManager *layoutManager = textStorage.layoutManagers.firstObject; NSTextContainer *textContainer = layoutManager.textContainers.firstObject; @@ -140,4 +141,14 @@ static NSLineBreakMode RCTNSLineBreakModeFromWritingDirection( return nil; } +- (NSAttributedString *)_nsAttributedStringFromAttributedString:(AttributedString)attributedString +{ + auto sharedNSAttributedString = _cache.get(attributedString, [](const AttributedString attributedString) { + return std::shared_ptr( + (__bridge_retained void *)RCTNSAttributedStringFromAttributedString(attributedString), CFRelease); + }); + + return (__bridge NSAttributedString *)sharedNSAttributedString.get(); +} + @end