From 08dda02347a28ad8abe4c7d458ceb6cfcd260ee2 Mon Sep 17 00:00:00 2001 From: Samuel Susla Date: Tue, 3 Mar 2020 04:10:31 -0800 Subject: [PATCH] Font size in Text now respects preferredContentSizeCategory Summary: Changelog: [Internal] Use LayoutContext to pass `fontSizeMultiplier` down to ParagrapShadowNode. Reviewed By: shergin Differential Revision: D20184596 fbshipit-source-id: 3965a127069a21328ed19cb3f9732f0a2d1c4d58 --- React/Base/RCTUtils.h | 2 ++ React/Base/RCTUtils.m | 24 +++++++++++++++++++ React/Fabric/RCTSurfacePresenter.mm | 1 + .../text/paragraph/ParagraphShadowNode.cpp | 12 ++++++---- .../text/paragraph/ParagraphShadowNode.h | 4 ++-- .../fabric/core/layout/LayoutContext.h | 5 ++++ 6 files changed, 41 insertions(+), 7 deletions(-) diff --git a/React/Base/RCTUtils.h b/React/Base/RCTUtils.h index 9159d3d820e..fba47a7fe15 100644 --- a/React/Base/RCTUtils.h +++ b/React/Base/RCTUtils.h @@ -44,6 +44,8 @@ RCT_EXTERN void RCTUnsafeExecuteOnMainQueueSync(dispatch_block_t block); RCT_EXTERN CGFloat RCTScreenScale(void); RCT_EXTERN CGSize RCTScreenSize(void); +RCT_EXTERN CGFloat RCTFontSizeMultiplier(void); + // Round float coordinates to nearest whole screen pixel (not point) RCT_EXTERN CGFloat RCTRoundPixelValue(CGFloat value); RCT_EXTERN CGFloat RCTCeilPixelValue(CGFloat value); diff --git a/React/Base/RCTUtils.m b/React/Base/RCTUtils.m index c5fd2d8e1ce..2e8bc82f4c4 100644 --- a/React/Base/RCTUtils.m +++ b/React/Base/RCTUtils.m @@ -301,6 +301,30 @@ CGFloat RCTScreenScale() return scale; } +CGFloat RCTFontSizeMultiplier() +{ + static NSDictionary *mapping; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + mapping = @{ + UIContentSizeCategoryExtraSmall: @0.823, + UIContentSizeCategorySmall: @0.882, + UIContentSizeCategoryMedium: @0.941, + UIContentSizeCategoryLarge: @1.0, + UIContentSizeCategoryExtraLarge: @1.118, + UIContentSizeCategoryExtraExtraLarge: @1.235, + UIContentSizeCategoryExtraExtraExtraLarge: @1.353, + UIContentSizeCategoryAccessibilityMedium: @1.786, + UIContentSizeCategoryAccessibilityLarge: @2.143, + UIContentSizeCategoryAccessibilityExtraLarge: @2.643, + UIContentSizeCategoryAccessibilityExtraExtraLarge: @3.143, + UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: @3.571 + }; + }); + + return mapping[RCTSharedApplication().preferredContentSizeCategory].floatValue; +} + CGSize RCTScreenSize() { // FIXME: this caches the bounds at app start, whatever those were, and then diff --git a/React/Fabric/RCTSurfacePresenter.mm b/React/Fabric/RCTSurfacePresenter.mm index c96763a3928..1ef905f9d84 100644 --- a/React/Fabric/RCTSurfacePresenter.mm +++ b/React/Fabric/RCTSurfacePresenter.mm @@ -39,6 +39,7 @@ using namespace facebook::react; static LayoutContext RCTCurrentLayoutContext() { return { .pointScaleFactor = RCTScreenScale(), + .fontSizeMultiplier = RCTFontSizeMultiplier() }; } diff --git a/ReactCommon/fabric/components/text/paragraph/ParagraphShadowNode.cpp b/ReactCommon/fabric/components/text/paragraph/ParagraphShadowNode.cpp index 04b64d81289..a4edcacb91f 100644 --- a/ReactCommon/fabric/components/text/paragraph/ParagraphShadowNode.cpp +++ b/ReactCommon/fabric/components/text/paragraph/ParagraphShadowNode.cpp @@ -15,9 +15,10 @@ namespace react { char const ParagraphComponentName[] = "Paragraph"; -AttributedString ParagraphShadowNode::getAttributedString() const { +AttributedString ParagraphShadowNode::getAttributedString(Float fontSizeMultiplier) const { if (!cachedAttributedString_.has_value()) { auto textAttributes = TextAttributes::defaultTextAttributes(); + textAttributes.fontSizeMultiplier = fontSizeMultiplier; textAttributes.apply(getConcreteProps().textAttributes); cachedAttributedString_ = @@ -33,10 +34,10 @@ void ParagraphShadowNode::setTextLayoutManager( textLayoutManager_ = textLayoutManager; } -void ParagraphShadowNode::updateStateIfNeeded() { +void ParagraphShadowNode::updateStateIfNeeded(LayoutContext layoutContext) { ensureUnsealed(); - auto attributedString = getAttributedString(); + auto attributedString = getAttributedString(layoutContext.fontSizeMultiplier); auto const &state = getStateData(); assert(textLayoutManager_); @@ -57,7 +58,8 @@ void ParagraphShadowNode::updateStateIfNeeded() { #pragma mark - LayoutableShadowNode Size ParagraphShadowNode::measureContent(LayoutConstraints layoutConstraints, LayoutContext layoutContext) const { - AttributedString attributedString = getAttributedString(); + AttributedString attributedString = getAttributedString(layoutContext.fontSizeMultiplier); + if (attributedString.isEmpty()) { return layoutConstraints.clamp({0, 0}); } @@ -69,7 +71,7 @@ Size ParagraphShadowNode::measureContent(LayoutConstraints layoutConstraints, La } void ParagraphShadowNode::layout(LayoutContext layoutContext) { - updateStateIfNeeded(); + updateStateIfNeeded(layoutContext); ConcreteViewShadowNode::layout(layoutContext); } diff --git a/ReactCommon/fabric/components/text/paragraph/ParagraphShadowNode.h b/ReactCommon/fabric/components/text/paragraph/ParagraphShadowNode.h index 4c28dc820e1..fa427600e13 100644 --- a/ReactCommon/fabric/components/text/paragraph/ParagraphShadowNode.h +++ b/ReactCommon/fabric/components/text/paragraph/ParagraphShadowNode.h @@ -47,7 +47,7 @@ class ParagraphShadowNode : public ConcreteViewShadowNode< /* * Returns a `AttributedString` which represents text content of the node. */ - AttributedString getAttributedString() const; + AttributedString getAttributedString(Float fontSizeMultiplier) const; /* * Associates a shared TextLayoutManager with the node. @@ -66,7 +66,7 @@ class ParagraphShadowNode : public ConcreteViewShadowNode< * Creates a `State` object (with `AttributedText` and * `TextLayoutManager`) if needed. */ - void updateStateIfNeeded(); + void updateStateIfNeeded(LayoutContext layoutContext); SharedTextLayoutManager textLayoutManager_; diff --git a/ReactCommon/fabric/core/layout/LayoutContext.h b/ReactCommon/fabric/core/layout/LayoutContext.h index b37bd26231d..3b9fd1f429f 100644 --- a/ReactCommon/fabric/core/layout/LayoutContext.h +++ b/ReactCommon/fabric/core/layout/LayoutContext.h @@ -33,6 +33,11 @@ struct LayoutContext { */ Float pointScaleFactor{1.0}; + /* + * Multiplier used to change size of the font in surface. + */ + Float fontSizeMultiplier{1.0}; + /* * A raw pointer to list of raw pointers to `LayoutableShadowNode`s that were * affected by the re-layout pass. If the field is not `nullptr`, a particular