Test perf effect of reverting D3269333

Reviewed By: javache

Differential Revision: D3346235

fbshipit-source-id: 2008f8fb9df5d61da59bb0067b25acd5a71f256f
This commit is contained in:
Nick Lockwood
2016-05-27 09:49:15 -07:00
committed by Facebook Github Bot 8
parent 60e0d2c676
commit a4b5f1bf10
16 changed files with 225 additions and 202 deletions

View File

@@ -13,12 +13,12 @@
#import "RCTUIManager.h"
#import "RCTBridge.h"
#import "RCTConvert.h"
#import "RCTImageComponent.h"
#import "RCTLog.h"
#import "RCTShadowRawText.h"
#import "RCTText.h"
#import "RCTUtils.h"
NSString *const RCTShadowViewAttributeName = @"RCTShadowViewAttributeName";
NSString *const RCTIsHighlightedAttributeName = @"IsHighlightedAttributeName";
NSString *const RCTReactTagAttributeName = @"ReactTagAttributeName";
@@ -114,45 +114,6 @@ static css_dim_t RCTMeasure(void *context, float width, css_measure_mode_t width
[self dirtyPropagation];
}
- (void)applyLayoutToChildren:(css_node_t *)node
viewsWithNewFrame:(NSMutableSet<RCTShadowView *> *)viewsWithNewFrame
absolutePosition:(CGPoint)absolutePosition
{
// Run layout on subviews.
NSTextStorage *textStorage = [self buildTextStorageForWidth:self.frame.size.width widthMode:CSS_MEASURE_MODE_EXACTLY];
NSLayoutManager *layoutManager = textStorage.layoutManagers.firstObject;
NSTextContainer *textContainer = layoutManager.textContainers.firstObject;
NSRange glyphRange = [layoutManager glyphRangeForTextContainer:textContainer];
NSRange characterRange = [layoutManager characterRangeForGlyphRange:glyphRange actualGlyphRange:NULL];
[layoutManager.textStorage enumerateAttribute:RCTShadowViewAttributeName inRange:characterRange options:0 usingBlock:^(RCTShadowView *child, NSRange range, BOOL *_) {
if (child != nil) {
css_node_t *childNode = child.cssNode;
float width = childNode->style.dimensions[CSS_WIDTH];
float height = childNode->style.dimensions[CSS_HEIGHT];
if (isUndefined(width) || isUndefined(height)) {
RCTLogError(@"Views nested within a <Text> must have a width and height");
}
UIFont *font = [textStorage attribute:NSFontAttributeName atIndex:range.location effectiveRange:nil];
CGRect glyphRect = [layoutManager boundingRectForGlyphRange:range inTextContainer:textContainer];
CGRect childFrame = {{
RCTRoundPixelValue(glyphRect.origin.x),
RCTRoundPixelValue(glyphRect.origin.y + glyphRect.size.height - height + font.descender)
}, {
RCTRoundPixelValue(width),
RCTRoundPixelValue(height)
}};
NSRange truncatedGlyphRange = [layoutManager truncatedGlyphRangeInLineFragmentForGlyphAtIndex:range.location];
BOOL childIsTruncated = NSIntersectionRange(range, truncatedGlyphRange).length != 0;
[child collectUpdatedFrames:viewsWithNewFrame
withFrame:childFrame
hidden:childIsTruncated
absolutePosition:absolutePosition];
}
}];
}
- (NSTextStorage *)buildTextStorageForWidth:(CGFloat)width widthMode:(css_measure_mode_t)widthMode
{
if (_cachedTextStorage && width == _cachedTextStorageWidth && widthMode == _cachedTextStorageWidthMode) {
@@ -238,48 +199,33 @@ static css_dim_t RCTMeasure(void *context, float width, css_measure_mode_t width
_effectiveLetterSpacing = letterSpacing.doubleValue;
UIFont *font = [RCTConvert UIFont:nil withFamily:fontFamily
size:fontSize weight:fontWeight style:fontStyle
scaleMultiplier:_allowFontScaling ? _fontSizeMultiplier : 1.0];
CGFloat heightOfTallestSubview = 0.0;
NSMutableAttributedString *attributedString = [NSMutableAttributedString new];
for (RCTShadowView *child in [self reactSubviews]) {
if ([child isKindOfClass:[RCTShadowText class]]) {
RCTShadowText *shadowText = (RCTShadowText *)child;
[attributedString appendAttributedString:
[shadowText _attributedStringWithFontFamily:fontFamily
fontSize:fontSize
fontWeight:fontWeight
fontStyle:fontStyle
letterSpacing:letterSpacing
useBackgroundColor:YES
foregroundColor:shadowText.color ?: foregroundColor
backgroundColor:shadowText.backgroundColor ?: backgroundColor
opacity:opacity * shadowText.opacity]];
[child setTextComputed];
[shadowText _attributedStringWithFontFamily:fontFamily
fontSize:fontSize
fontWeight:fontWeight
fontStyle:fontStyle
letterSpacing:letterSpacing
useBackgroundColor:YES
foregroundColor:shadowText.color ?: foregroundColor
backgroundColor:shadowText.backgroundColor ?: backgroundColor
opacity:opacity * shadowText.opacity]];
} else if ([child isKindOfClass:[RCTShadowRawText class]]) {
RCTShadowRawText *shadowRawText = (RCTShadowRawText *)child;
[attributedString appendAttributedString:[[NSAttributedString alloc] initWithString:shadowRawText.text ?: @""]];
[child setTextComputed];
} else if ([child conformsToProtocol:@protocol(RCTImageComponent)]) {
NSTextAttachment *imageAttachment = [NSTextAttachment new];
imageAttachment.image = ((id<RCTImageComponent>)child).image;
imageAttachment.bounds = (CGRect){CGPointZero, {RCTZeroIfNaN(child.width), RCTZeroIfNaN(child.height)}};
[attributedString appendAttributedString:[NSAttributedString attributedStringWithAttachment:imageAttachment]];
} else {
float width = child.cssNode->style.dimensions[CSS_WIDTH];
float height = child.cssNode->style.dimensions[CSS_HEIGHT];
if (isUndefined(width) || isUndefined(height)) {
RCTLogError(@"Views nested within a <Text> must have a width and height");
}
NSTextAttachment *attachment = [NSTextAttachment new];
attachment.bounds = (CGRect){CGPointZero, {width, height}};
NSMutableAttributedString *attachmentString = [NSMutableAttributedString new];
[attachmentString appendAttributedString:[NSAttributedString attributedStringWithAttachment:attachment]];
[attachmentString addAttribute:RCTShadowViewAttributeName value:child range:(NSRange){0, attachmentString.length}];
[attributedString appendAttributedString:attachmentString];
if (height > heightOfTallestSubview) {
heightOfTallestSubview = height;
}
// Don't call setTextComputed on this child. RCTTextManager takes care of
// processing inline UIViews.
RCTLogError(@"<Text> can't have any children except <Text>, <Image> or raw strings");
}
[child setTextComputed];
}
[self _addAttribute:NSForegroundColorAttributeName
@@ -295,10 +241,13 @@ static css_dim_t RCTMeasure(void *context, float width, css_measure_mode_t width
toAttributedString:attributedString];
}
UIFont *font = [RCTConvert UIFont:nil withFamily:fontFamily
size:fontSize weight:fontWeight style:fontStyle
scaleMultiplier:_allowFontScaling ? _fontSizeMultiplier : 1.0];
[self _addAttribute:NSFontAttributeName withValue:font toAttributedString:attributedString];
[self _addAttribute:NSKernAttributeName withValue:letterSpacing toAttributedString:attributedString];
[self _addAttribute:RCTReactTagAttributeName withValue:self.reactTag toAttributedString:attributedString];
[self _setParagraphStyleOnAttributedString:attributedString heightOfTallestSubview:heightOfTallestSubview];
[self _setParagraphStyleOnAttributedString:attributedString];
// create a non-mutable attributedString for use by the Text system which avoids copies down the line
_cachedAttributedString = [[NSAttributedString alloc] initWithAttributedString:attributedString];
@@ -321,7 +270,6 @@ static css_dim_t RCTMeasure(void *context, float width, css_measure_mode_t width
* varying lineHeights, we simply take the max.
*/
- (void)_setParagraphStyleOnAttributedString:(NSMutableAttributedString *)attributedString
heightOfTallestSubview:(CGFloat)heightOfTallestSubview
{
// check if we have lineHeight set on self
__block BOOL hasParagraphStyle = NO;
@@ -329,7 +277,9 @@ static css_dim_t RCTMeasure(void *context, float width, css_measure_mode_t width
hasParagraphStyle = YES;
}
__block float newLineHeight = _lineHeight ?: 0.0;
if (!_lineHeight) {
self.lineHeight = 0.0;
}
CGFloat fontSizeMultiplier = _allowFontScaling ? _fontSizeMultiplier : 1.0;
@@ -338,25 +288,15 @@ static css_dim_t RCTMeasure(void *context, float width, css_measure_mode_t width
if (value) {
NSParagraphStyle *paragraphStyle = (NSParagraphStyle *)value;
CGFloat maximumLineHeight = round(paragraphStyle.maximumLineHeight / fontSizeMultiplier);
if (maximumLineHeight > newLineHeight) {
newLineHeight = maximumLineHeight;
if (maximumLineHeight > self.lineHeight) {
self.lineHeight = maximumLineHeight;
}
hasParagraphStyle = YES;
}
}];
if (self.lineHeight != newLineHeight) {
self.lineHeight = newLineHeight;
}
NSTextAlignment newTextAlign = _textAlign ?: NSTextAlignmentNatural;
if (self.textAlign != newTextAlign) {
self.textAlign = newTextAlign;
}
NSWritingDirection newWritingDirection = _writingDirection ?: NSWritingDirectionNatural;
if (self.writingDirection != newWritingDirection) {
self.writingDirection = newWritingDirection;
}
self.textAlign = _textAlign ?: NSTextAlignmentNatural;
self.writingDirection = _writingDirection ?: NSWritingDirectionNatural;
// if we found anything, set it :D
if (hasParagraphStyle) {
@@ -364,9 +304,6 @@ static css_dim_t RCTMeasure(void *context, float width, css_measure_mode_t width
paragraphStyle.alignment = _textAlign;
paragraphStyle.baseWritingDirection = _writingDirection;
CGFloat lineHeight = round(_lineHeight * fontSizeMultiplier);
if (heightOfTallestSubview > lineHeight) {
lineHeight = ceilf(heightOfTallestSubview);
}
paragraphStyle.minimumLineHeight = lineHeight;
paragraphStyle.maximumLineHeight = lineHeight;
[attributedString addAttribute:NSParagraphStyleAttributeName

View File

@@ -13,17 +13,6 @@
#import "RCTUtils.h"
#import "UIView+React.h"
static void collectNonTextDescendants(RCTText *view, NSMutableArray *nonTextDescendants)
{
for (UIView *child in view.reactSubviews) {
if ([child isKindOfClass:[RCTText class]]) {
collectNonTextDescendants((RCTText *)child, nonTextDescendants);
} else {
[nonTextDescendants addObject:child];
}
}
}
@implementation RCTText
{
NSTextStorage *_textStorage;
@@ -130,15 +119,6 @@ static void collectNonTextDescendants(RCTText *view, NSMutableArray *nonTextDesc
[_highlightLayer removeFromSuperlayer];
_highlightLayer = nil;
}
for (UIView *child in [self subviews]) {
[child removeFromSuperview];
}
NSMutableArray *nonTextDescendants = [NSMutableArray new];
collectNonTextDescendants(self, nonTextDescendants);
for (UIView *child in nonTextDescendants) {
[self addSubview:child];
}
}
- (NSNumber *)reactTagAtPoint:(CGPoint)point

View File

@@ -20,18 +20,6 @@
#import "RCTTextView.h"
#import "UIView+React.h"
static void collectDirtyNonTextDescendants(RCTShadowText *shadowView, NSMutableArray *nonTextDescendants) {
for (RCTShadowView *child in shadowView.reactSubviews) {
if ([child isKindOfClass:[RCTShadowText class]]) {
collectDirtyNonTextDescendants((RCTShadowText *)child, nonTextDescendants);
} else if ([child isKindOfClass:[RCTShadowRawText class]]) {
// no-op
} else if ([child isTextDirty]) {
[nonTextDescendants addObject:child];
}
}
}
@interface RCTShadowText (Private)
- (NSTextStorage *)buildTextStorageForWidth:(CGFloat)width widthMode:(css_measure_mode_t)widthMode;
@@ -97,7 +85,6 @@ RCT_EXPORT_SHADOW_PROPERTY(textShadowColor, UIColor)
if ([shadowView isKindOfClass:[RCTShadowText class]]) {
((RCTShadowText *)shadowView).fontSizeMultiplier = self.bridge.accessibilityManager.multiplier;
[(RCTShadowText *)shadowView recomputeText];
collectDirtyNonTextDescendants((RCTShadowText *)shadowView, queue);
} else if ([shadowView isKindOfClass:[RCTShadowRawText class]]) {
RCTLogError(@"Raw text cannot be used outside of a <Text> tag. Not rendering string: '%@'",
[(RCTShadowRawText *)shadowView text]);