From 63079fbd15d851d78191a6439710406e6282a982 Mon Sep 17 00:00:00 2001 From: Eric Rozell Date: Mon, 16 Oct 2023 09:42:33 -0700 Subject: [PATCH] Pass LayoutContext to TextLayoutManager (#40873) Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/40873 Some host platforms may require the LayoutContext for computing the size of text, e.g. to read the pointScaleFactor value. This change passes the LayoutContext to TextLayoutManager so it can be used during text measurement. Please note, for now, this does not wire any fields from LayoutContext through to the TextMeasureCache, TextLayoutManager::getHostTextStorage, or TextLayoutManager::measureCachedSpannableById (on Android). ## Changelog: [General] [Internal] Reviewed By: rshest Differential Revision: D50227592 fbshipit-source-id: 37ec16a4828c6cef4a1c1f01d144a86dd29dec29 --- .../text/ParagraphLayoutManager.cpp | 3 ++ .../components/text/ParagraphLayoutManager.h | 2 + .../components/text/ParagraphShadowNode.cpp | 16 +++++++- .../AndroidTextInputShadowNode.cpp | 6 ++- .../iostextinput/TextInputShadowNode.cpp | 4 ++ .../textlayoutmanager/TextLayoutContext.h | 40 +++++++++++++++++++ .../textlayoutmanager/TextLayoutManager.cpp | 1 + .../textlayoutmanager/TextLayoutManager.h | 2 + .../platform/cxx/TextLayoutManager.cpp | 1 + .../platform/cxx/TextLayoutManager.h | 2 + .../textlayoutmanager/TextLayoutManager.h | 2 + .../textlayoutmanager/TextLayoutManager.mm | 1 + 12 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 packages/react-native/ReactCommon/react/renderer/textlayoutmanager/TextLayoutContext.h diff --git a/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphLayoutManager.cpp b/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphLayoutManager.cpp index 2dfd5dd6bdf94a..ea615b500ab494 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphLayoutManager.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphLayoutManager.cpp @@ -14,6 +14,7 @@ namespace facebook::react { TextMeasurement ParagraphLayoutManager::measure( const AttributedString& attributedString, const ParagraphAttributes& paragraphAttributes, + const TextLayoutContext& layoutContext, LayoutConstraints layoutConstraints) const { if (CoreFeatures::cacheLastTextMeasurement) { bool shouldMeasure = shouldMeasureString( @@ -23,6 +24,7 @@ TextMeasurement ParagraphLayoutManager::measure( cachedTextMeasurement_ = textLayoutManager_->measure( AttributedStringBox(attributedString), paragraphAttributes, + layoutContext, layoutConstraints, hostTextStorage_); lastAvailableWidth_ = layoutConstraints.maximumSize.width; @@ -33,6 +35,7 @@ TextMeasurement ParagraphLayoutManager::measure( return textLayoutManager_->measure( AttributedStringBox(attributedString), paragraphAttributes, + layoutContext, layoutConstraints, nullptr); } diff --git a/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphLayoutManager.h b/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphLayoutManager.h index 5ce955820e55b5..43bd2936abaa59 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphLayoutManager.h +++ b/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphLayoutManager.h @@ -10,6 +10,7 @@ #include #include #include +#include #include namespace facebook::react { @@ -26,6 +27,7 @@ class ParagraphLayoutManager { TextMeasurement measure( const AttributedString& attributedString, const ParagraphAttributes& paragraphAttributes, + const TextLayoutContext& layoutContext, LayoutConstraints layoutConstraints) const; LinesMeasurements measureLines( diff --git a/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphShadowNode.cpp index 9a129bb605dcc1..ca5761652b6171 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/text/ParagraphShadowNode.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "ParagraphState.h" @@ -152,9 +153,15 @@ Size ParagraphShadowNode::measureContent( attributedString.appendFragment({string, textAttributes, {}}); } + TextLayoutContext textLayoutContext{}; + textLayoutContext.pointScaleFactor = layoutContext.pointScaleFactor; return getStateData() .paragraphLayoutManager - .measure(attributedString, content.paragraphAttributes, layoutConstraints) + .measure( + attributedString, + content.paragraphAttributes, + textLayoutContext, + layoutConstraints) .size; } @@ -171,8 +178,13 @@ void ParagraphShadowNode::layout(LayoutContext layoutContext) { updateStateIfNeeded(content); + TextLayoutContext textLayoutContext{}; + textLayoutContext.pointScaleFactor = layoutContext.pointScaleFactor; auto measurement = getStateData().paragraphLayoutManager.measure( - content.attributedString, content.paragraphAttributes, layoutConstraints); + content.attributedString, + content.paragraphAttributes, + textLayoutContext, + layoutConstraints); if (getConcreteProps().onTextLayout) { auto linesMeasurements = getStateData().paragraphLayoutManager.measureLines( diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.cpp index 0c9cc69c673464..3e9e0ad9ed17b1 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/androidtextinput/react/renderer/components/androidtextinput/AndroidTextInputShadowNode.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -157,7 +158,7 @@ void AndroidTextInputShadowNode::updateStateIfNeeded() { #pragma mark - LayoutableShadowNode Size AndroidTextInputShadowNode::measureContent( - const LayoutContext& /*layoutContext*/, + const LayoutContext& layoutContext, const LayoutConstraints& layoutConstraints) const { if (getStateData().cachedAttributedStringId != 0) { return textLayoutManager_ @@ -183,10 +184,13 @@ Size AndroidTextInputShadowNode::measureContent( return {0, 0}; } + TextLayoutContext textLayoutContext; + textLayoutContext.pointScaleFactor = layoutContext.pointScaleFactor; return textLayoutManager_ ->measure( AttributedStringBox{attributedString}, getConcreteProps().paragraphAttributes, + textLayoutContext, layoutConstraints, nullptr) .size; diff --git a/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputShadowNode.cpp b/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputShadowNode.cpp index a23dd665c70e2d..462456335ca725 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputShadowNode.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/textinput/iostextinput/react/renderer/components/iostextinput/TextInputShadowNode.cpp @@ -13,6 +13,7 @@ #include #include #include +#include namespace facebook::react { @@ -106,10 +107,13 @@ void TextInputShadowNode::updateStateIfNeeded( Size TextInputShadowNode::measureContent( const LayoutContext& layoutContext, const LayoutConstraints& layoutConstraints) const { + TextLayoutContext textLayoutContext{}; + textLayoutContext.pointScaleFactor = layoutContext.pointScaleFactor; return textLayoutManager_ ->measure( attributedStringBoxToMeasure(layoutContext), getConcreteProps().getEffectiveParagraphAttributes(), + textLayoutContext, layoutConstraints, nullptr) .size; diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/TextLayoutContext.h b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/TextLayoutContext.h new file mode 100644 index 00000000000000..304cefde8074ad --- /dev/null +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/TextLayoutContext.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +namespace facebook::react { + +/* + * TextLayoutContext: Additional contextual information useful for text + * measurement. + */ +struct TextLayoutContext { + /* + * Reflects the scale factor needed to convert from the logical coordinate + * space into the device coordinate space of the physical screen. + * Some layout systems *might* use this to round layout metric values + * to `pixel value`. + */ + Float pointScaleFactor{1.0}; +}; + +inline bool operator==( + TextLayoutContext const& lhs, + TextLayoutContext const& rhs) { + return std::tie(lhs.pointScaleFactor) == std::tie(rhs.pointScaleFactor); +} + +inline bool operator!=( + TextLayoutContext const& lhs, + TextLayoutContext const& rhs) { + return !(lhs == rhs); +} + +} // namespace facebook::react diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/android/react/renderer/textlayoutmanager/TextLayoutManager.cpp b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/android/react/renderer/textlayoutmanager/TextLayoutManager.cpp index cb5844b2420ba5..1eebf174b2bea5 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/android/react/renderer/textlayoutmanager/TextLayoutManager.cpp +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/android/react/renderer/textlayoutmanager/TextLayoutManager.cpp @@ -159,6 +159,7 @@ void* TextLayoutManager::getNativeTextLayoutManager() const { TextMeasurement TextLayoutManager::measure( const AttributedStringBox& attributedStringBox, const ParagraphAttributes& paragraphAttributes, + const TextLayoutContext& layoutContext, LayoutConstraints layoutConstraints, std::shared_ptr /* hostTextStorage */) const { auto& attributedString = attributedStringBox.getValue(); diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/android/react/renderer/textlayoutmanager/TextLayoutManager.h b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/android/react/renderer/textlayoutmanager/TextLayoutManager.h index 640baaa289ea1b..9f71788b39a766 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/android/react/renderer/textlayoutmanager/TextLayoutManager.h +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/android/react/renderer/textlayoutmanager/TextLayoutManager.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -45,6 +46,7 @@ class TextLayoutManager { TextMeasurement measure( const AttributedStringBox& attributedStringBox, const ParagraphAttributes& paragraphAttributes, + const TextLayoutContext& layoutContext, LayoutConstraints layoutConstraints, std::shared_ptr /* hostTextStorage */) const; diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.cpp b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.cpp index 1a2aed80a69517..6d99a35008fca5 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.cpp +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.cpp @@ -16,6 +16,7 @@ void* TextLayoutManager::getNativeTextLayoutManager() const { TextMeasurement TextLayoutManager::measure( AttributedStringBox attributedStringBox, ParagraphAttributes paragraphAttributes, + const TextLayoutContext& /*layoutContext*/, LayoutConstraints layoutConstraints, std::shared_ptr) const { TextMeasurement::Attachments attachments; diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.h b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.h index 84ffee6bf33bd6..63903786a91b3d 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.h +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/cxx/TextLayoutManager.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -37,6 +38,7 @@ class TextLayoutManager { virtual TextMeasurement measure( AttributedStringBox attributedStringBox, ParagraphAttributes paragraphAttributes, + const TextLayoutContext& layoutContext, LayoutConstraints layoutConstraints, std::shared_ptr) const; diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/TextLayoutManager.h b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/TextLayoutManager.h index 67ca50820f9e81..cfa7abc53eabf1 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/TextLayoutManager.h +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/TextLayoutManager.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -32,6 +33,7 @@ class TextLayoutManager { TextMeasurement measure( AttributedStringBox attributedStringBox, ParagraphAttributes paragraphAttributes, + const TextLayoutContext& layoutContext, LayoutConstraints layoutConstraints, std::shared_ptr hostTextStorage) const; diff --git a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/TextLayoutManager.mm b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/TextLayoutManager.mm index 21742b810e0433..dcce90583805d6 100644 --- a/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/TextLayoutManager.mm +++ b/packages/react-native/ReactCommon/react/renderer/textlayoutmanager/platform/ios/react/renderer/textlayoutmanager/TextLayoutManager.mm @@ -41,6 +41,7 @@ TextMeasurement TextLayoutManager::measure( AttributedStringBox attributedStringBox, ParagraphAttributes paragraphAttributes, + const TextLayoutContext &layoutContext, LayoutConstraints layoutConstraints, std::shared_ptr hostTextStorage) const {