From 0dbe18375ebb712be8bebd3b6592170f90f8b7bc Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Thu, 15 Feb 2018 17:40:14 -0800 Subject: [PATCH] `base-line` metric exposure for Summary: Now (both bersions) exposes base-line metric to Yoga. Before: https://cl.ly/0G1Q29450O0y After: https://cl.ly/2X103V3O0322 Reviewed By: yungsters Differential Revision: D6957054 fbshipit-source-id: d76d96f56720d710a4230c53beafdb0b2521e8a9 --- .../TextInput/RCTBaseTextInputShadowView.m | 44 ++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m b/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m index faaaf775f06742..0d60c3c49d59b6 100644 --- a/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m +++ b/Libraries/Text/TextInput/RCTBaseTextInputShadowView.m @@ -37,6 +37,7 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge _needsUpdateView = YES; YGNodeSetMeasureFunc(self.yogaNode, RCTBaseTextInputShadowViewMeasure); + YGNodeSetBaselineFunc(self.yogaNode, RCTTextInputShadowViewBaseline); } return self; @@ -167,7 +168,7 @@ - (void)uiManagerWillPerformMounting #pragma mark - -- (CGSize)sizeThatFitsMinimumSize:(CGSize)minimumSize maximumSize:(CGSize)maximumSize +- (NSAttributedString *)measurableAttributedText { // Only for the very first render when we don't have `_localAttributedText`, // we use value directly from the property and/or nested content. @@ -187,6 +188,13 @@ - (CGSize)sizeThatFitsMinimumSize:(CGSize)minimumSize maximumSize:(CGSize)maximu attributedText = [[NSAttributedString alloc] initWithString:text attributes:self.textAttributes.effectiveTextAttributes]; } + return attributedText; +} + +- (CGSize)sizeThatFitsMinimumSize:(CGSize)minimumSize maximumSize:(CGSize)maximumSize +{ + NSAttributedString *attributedText = [self measurableAttributedText]; + if (!_textStorage) { _textContainer = [NSTextContainer new]; _textContainer.lineFragmentPadding = 0.0; // Note, the default value is 5. @@ -209,6 +217,26 @@ - (CGSize)sizeThatFitsMinimumSize:(CGSize)minimumSize maximumSize:(CGSize)maximu }; } +- (CGFloat)lastBaselineForSize:(CGSize)size +{ + NSAttributedString *attributedText = [self measurableAttributedText]; + + __block CGFloat maximumDescender = 0.0; + + [attributedText enumerateAttribute:NSFontAttributeName + inRange:NSMakeRange(0, attributedText.length) + options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired + usingBlock: + ^(UIFont *font, NSRange range, __unused BOOL *stop) { + if (maximumDescender > font.descender) { + maximumDescender = font.descender; + } + } + ]; + + return size.height + maximumDescender; +} + static YGSize RCTBaseTextInputShadowViewMeasure(YGNodeRef node, float width, YGMeasureMode widthMode, float height, YGMeasureMode heightMode) { RCTShadowView *shadowView = (__bridge RCTShadowView *)YGNodeGetContext(node); @@ -253,4 +281,18 @@ static YGSize RCTBaseTextInputShadowViewMeasure(YGNodeRef node, float width, YGM }; } +static float RCTTextInputShadowViewBaseline(YGNodeRef node, const float width, const float height) +{ + RCTBaseTextInputShadowView *shadowTextView = (__bridge RCTBaseTextInputShadowView *)YGNodeGetContext(node); + + CGSize size = (CGSize){ + RCTCoreGraphicsFloatFromYogaFloat(width), + RCTCoreGraphicsFloatFromYogaFloat(height) + }; + + CGFloat lastBaseline = [shadowTextView lastBaselineForSize:size]; + + return RCTYogaFloatFromCoreGraphicsFloat(lastBaseline); +} + @end