mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Platform specific TextLayoutManager Headers (#50889)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/50889 This effectively reverts D67064488 We are trying to smash together functions, variables, virtual or non-virtual, all required by different platforms, into a single header, often using #ifdefs that are not what we want (apart from a bad editor experience, `#ifdef ANDROID` may or may not be compiled into the react-native-cxx platform, and we cannot use it for the Android platform reliably). For Facsimile, we are going to be introducing more potential divergence, with the idea of `PreparedText`, where we can generate intermediate products as part of the layout process to be reused later. I'm planning to design that in a way which can be eventually reused across platforms, but not everywhere. I think the best path for this is going to be to allow each platform to have their own headers, instead of the current messiness, then allow shared code (e.g. in `ParagraphShadowNode`) to pick how to interact at compile time. I added an example of this as part of `TextLayoutManagerExtended`, to customize how we act if a `TextLayoutManager` chooses not to implement `measureLines`. Changelog: [Internal] Reviewed By: rshest Differential Revision: D73557126 fbshipit-source-id: 9851ebba691b0d123f6a355126f2d5b003aceba0
This commit is contained in:
committed by
Facebook GitHub Bot
parent
2efe8094c0
commit
2e42eab6df
+21
-5
@@ -17,6 +17,7 @@
|
||||
#include <react/renderer/graphics/rounding.h>
|
||||
#include <react/renderer/telemetry/TransactionTelemetry.h>
|
||||
#include <react/renderer/textlayoutmanager/TextLayoutContext.h>
|
||||
#include <react/renderer/textlayoutmanager/TextLayoutManagerExtended.h>
|
||||
|
||||
#include "ParagraphState.h"
|
||||
|
||||
@@ -215,8 +216,17 @@ Float ParagraphShadowNode::baseline(
|
||||
|
||||
AttributedStringBox attributedStringBox{attributedString};
|
||||
|
||||
return LineMeasurement::baseline(textLayoutManager_->measureLines(
|
||||
attributedStringBox, getConcreteProps().paragraphAttributes, size));
|
||||
if constexpr (TextLayoutManagerExtended::supportsLineMeasurement()) {
|
||||
auto lines =
|
||||
TextLayoutManagerExtended(*textLayoutManager_)
|
||||
.measureLines(
|
||||
attributedStringBox, content.paragraphAttributes, size);
|
||||
return LineMeasurement::baseline(lines);
|
||||
} else {
|
||||
LOG(WARNING)
|
||||
<< "Baseline alignment is not supported by the current platform";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ParagraphShadowNode::layout(LayoutContext layoutContext) {
|
||||
@@ -239,9 +249,15 @@ void ParagraphShadowNode::layout(LayoutContext layoutContext) {
|
||||
AttributedStringBox attributedStringBox{content.attributedString};
|
||||
|
||||
if (getConcreteProps().onTextLayout) {
|
||||
auto linesMeasurements = textLayoutManager_->measureLines(
|
||||
attributedStringBox, content.paragraphAttributes, size);
|
||||
getConcreteEventEmitter().onTextLayout(linesMeasurements);
|
||||
if constexpr (TextLayoutManagerExtended::supportsLineMeasurement()) {
|
||||
auto linesMeasurements =
|
||||
TextLayoutManagerExtended(*textLayoutManager_)
|
||||
.measureLines(
|
||||
attributedStringBox, content.paragraphAttributes, size);
|
||||
getConcreteEventEmitter().onTextLayout(linesMeasurements);
|
||||
} else {
|
||||
LOG(WARNING) << "onTextLayout is not supported by the current platform";
|
||||
}
|
||||
}
|
||||
|
||||
if (content.attachments.empty()) {
|
||||
|
||||
+15
-3
@@ -7,6 +7,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glog/logging.h>
|
||||
|
||||
#include <react/renderer/attributedstring/AttributedString.h>
|
||||
#include <react/renderer/attributedstring/AttributedStringBox.h>
|
||||
#include <react/renderer/components/text/BaseTextShadowNode.h>
|
||||
@@ -18,6 +20,7 @@
|
||||
#include <react/renderer/core/LayoutContext.h>
|
||||
#include <react/renderer/textlayoutmanager/TextLayoutContext.h>
|
||||
#include <react/renderer/textlayoutmanager/TextLayoutManager.h>
|
||||
#include <react/renderer/textlayoutmanager/TextLayoutManagerExtended.h>
|
||||
#include <react/utils/ContextContainer.h>
|
||||
|
||||
namespace facebook::react {
|
||||
@@ -106,9 +109,18 @@ class BaseTextInputShadowNode : public ConcreteViewShadowNode<
|
||||
&(YogaLayoutableShadowNode::yogaNode_), YGEdgeTop);
|
||||
|
||||
AttributedStringBox attributedStringBox{attributedString};
|
||||
return LineMeasurement::baseline(textLayoutManager_->measureLines(
|
||||
attributedStringBox, props.paragraphAttributes, size)) +
|
||||
top;
|
||||
|
||||
if constexpr (TextLayoutManagerExtended::supportsLineMeasurement()) {
|
||||
auto lines =
|
||||
TextLayoutManagerExtended(*textLayoutManager_)
|
||||
.measureLines(
|
||||
attributedStringBox, props.paragraphAttributes, size);
|
||||
return LineMeasurement::baseline(lines) + top;
|
||||
} else {
|
||||
LOG(WARNING)
|
||||
<< "Baseline alignment is not supported by the current platform";
|
||||
return top;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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 <glog/logging.h>
|
||||
|
||||
#include <react/renderer/attributedstring/AttributedStringBox.h>
|
||||
#include <react/renderer/attributedstring/ParagraphAttributes.h>
|
||||
#include <react/renderer/graphics/Size.h>
|
||||
#include <react/renderer/textlayoutmanager/TextLayoutManager.h>
|
||||
#include <react/renderer/textlayoutmanager/TextMeasureCache.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
namespace detail {
|
||||
/**
|
||||
* TextLayoutManagerExtended acts as an adapter for TextLayoutManager methods
|
||||
* which may not exist for a specific platform. Callers can check at
|
||||
* compile-time whether a method is supported, and calling if it is not will
|
||||
* terminate.
|
||||
*/
|
||||
template <typename TextLayoutManagerT>
|
||||
class TextLayoutManagerExtended {
|
||||
public:
|
||||
static constexpr bool supportsLineMeasurement() {
|
||||
return requires(TextLayoutManagerT textLayoutManager) {
|
||||
{
|
||||
textLayoutManager.measureLines(
|
||||
AttributedStringBox{}, ParagraphAttributes{}, Size{})
|
||||
} -> std::same_as<LinesMeasurements>;
|
||||
};
|
||||
}
|
||||
|
||||
TextLayoutManagerExtended(const TextLayoutManagerT& textLayoutManager)
|
||||
: textLayoutManager_(textLayoutManager) {}
|
||||
|
||||
LinesMeasurements measureLines(
|
||||
const AttributedStringBox& attributedStringBox,
|
||||
const ParagraphAttributes& paragraphAttributes,
|
||||
const Size& size) {
|
||||
if constexpr (supportsLineMeasurement()) {
|
||||
return textLayoutManager_.measureLines(
|
||||
attributedStringBox, paragraphAttributes, size);
|
||||
}
|
||||
LOG(FATAL) << "Platform TextLayoutManager does not support measureLines";
|
||||
}
|
||||
|
||||
private:
|
||||
const TextLayoutManagerT& textLayoutManager_;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
using TextLayoutManagerExtended =
|
||||
detail::TextLayoutManagerExtended<TextLayoutManager>;
|
||||
|
||||
} // namespace facebook::react
|
||||
+3
-17
@@ -26,7 +26,6 @@ class TextLayoutManager;
|
||||
class TextLayoutManager {
|
||||
public:
|
||||
TextLayoutManager(const ContextContainer::Shared& contextContainer);
|
||||
virtual ~TextLayoutManager() = default;
|
||||
|
||||
/*
|
||||
* Not copyable.
|
||||
@@ -43,13 +42,12 @@ class TextLayoutManager {
|
||||
/*
|
||||
* Measures `attributedString` using native text rendering infrastructure.
|
||||
*/
|
||||
virtual TextMeasurement measure(
|
||||
TextMeasurement measure(
|
||||
const AttributedStringBox& attributedStringBox,
|
||||
const ParagraphAttributes& paragraphAttributes,
|
||||
const TextLayoutContext& layoutContext,
|
||||
const LayoutConstraints& layoutConstraints) const;
|
||||
|
||||
#ifdef ANDROID
|
||||
/**
|
||||
* Measures an AttributedString on the platform, as identified by some
|
||||
* opaque cache ID.
|
||||
@@ -58,30 +56,18 @@ class TextLayoutManager {
|
||||
int64_t cacheId,
|
||||
const ParagraphAttributes& paragraphAttributes,
|
||||
const LayoutConstraints& layoutConstraints) const;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Measures lines of `attributedString` using native text rendering
|
||||
* infrastructure.
|
||||
*/
|
||||
virtual LinesMeasurements measureLines(
|
||||
LinesMeasurements measureLines(
|
||||
const AttributedStringBox& attributedStringBox,
|
||||
const ParagraphAttributes& paragraphAttributes,
|
||||
const Size& size) const;
|
||||
|
||||
#ifdef __APPLE__
|
||||
/*
|
||||
* Returns an opaque pointer to platform-specific TextLayoutManager.
|
||||
* Is used on a native views layer to delegate text rendering to the manager.
|
||||
*/
|
||||
std::shared_ptr<void> getNativeTextLayoutManager() const;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
private:
|
||||
std::shared_ptr<const ContextContainer> contextContainer_;
|
||||
#ifdef __APPLE__
|
||||
std::shared_ptr<void> nativeTextLayoutManager_;
|
||||
#endif
|
||||
TextMeasureCache textMeasureCache_;
|
||||
LineMeasureCache lineMeasureCache_;
|
||||
};
|
||||
+1
-18
@@ -11,8 +11,7 @@ namespace facebook::react {
|
||||
|
||||
TextLayoutManager::TextLayoutManager(
|
||||
const ContextContainer::Shared& /*contextContainer*/)
|
||||
: textMeasureCache_(kSimpleThreadSafeCacheSizeCap),
|
||||
lineMeasureCache_(kSimpleThreadSafeCacheSizeCap) {}
|
||||
: textMeasureCache_(kSimpleThreadSafeCacheSizeCap) {}
|
||||
|
||||
TextMeasurement TextLayoutManager::measure(
|
||||
const AttributedStringBox& attributedStringBox,
|
||||
@@ -29,20 +28,4 @@ TextMeasurement TextLayoutManager::measure(
|
||||
return TextMeasurement{{0, 0}, attachments};
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
TextMeasurement TextLayoutManager::measureCachedSpannableById(
|
||||
int64_t /*cacheId*/,
|
||||
const ParagraphAttributes& /*paragraphAttributes*/,
|
||||
const LayoutConstraints& /*layoutConstraints*/) const {
|
||||
return {};
|
||||
}
|
||||
#endif
|
||||
|
||||
LinesMeasurements TextLayoutManager::measureLines(
|
||||
const AttributedStringBox& /*attributedStringBox*/,
|
||||
const ParagraphAttributes& /*paragraphAttributes*/,
|
||||
const Size& /*size*/) const {
|
||||
return {};
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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 <react/renderer/attributedstring/AttributedStringBox.h>
|
||||
#include <react/renderer/attributedstring/ParagraphAttributes.h>
|
||||
#include <react/renderer/core/LayoutConstraints.h>
|
||||
#include <react/renderer/textlayoutmanager/TextLayoutContext.h>
|
||||
#include <react/renderer/textlayoutmanager/TextMeasureCache.h>
|
||||
#include <react/utils/ContextContainer.h>
|
||||
#include <memory>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
class TextLayoutManager;
|
||||
|
||||
/*
|
||||
* Cross platform facade for text measurement (e.g. Android-specific
|
||||
* TextLayoutManager)
|
||||
*/
|
||||
class TextLayoutManager {
|
||||
public:
|
||||
TextLayoutManager(const ContextContainer::Shared& contextContainer);
|
||||
virtual ~TextLayoutManager() = default;
|
||||
|
||||
/*
|
||||
* Not copyable.
|
||||
*/
|
||||
TextLayoutManager(const TextLayoutManager&) = delete;
|
||||
TextLayoutManager& operator=(const TextLayoutManager&) = delete;
|
||||
|
||||
/*
|
||||
* Not movable.
|
||||
*/
|
||||
TextLayoutManager(TextLayoutManager&&) = delete;
|
||||
TextLayoutManager& operator=(TextLayoutManager&&) = delete;
|
||||
|
||||
/*
|
||||
* Measures `attributedString` using native text rendering infrastructure.
|
||||
*/
|
||||
virtual TextMeasurement measure(
|
||||
const AttributedStringBox& attributedStringBox,
|
||||
const ParagraphAttributes& paragraphAttributes,
|
||||
const TextLayoutContext& layoutContext,
|
||||
const LayoutConstraints& layoutConstraints) const;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<const ContextContainer> contextContainer_;
|
||||
TextMeasureCache textMeasureCache_;
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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 <react/renderer/attributedstring/AttributedStringBox.h>
|
||||
#include <react/renderer/attributedstring/ParagraphAttributes.h>
|
||||
#include <react/renderer/core/LayoutConstraints.h>
|
||||
#include <react/renderer/textlayoutmanager/TextLayoutContext.h>
|
||||
#include <react/renderer/textlayoutmanager/TextMeasureCache.h>
|
||||
#include <react/utils/ContextContainer.h>
|
||||
#include <memory>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
/*
|
||||
* Cross platform facade for text measurement (e.g. Android-specific
|
||||
* TextLayoutManager)
|
||||
*/
|
||||
class TextLayoutManager {
|
||||
public:
|
||||
TextLayoutManager(const ContextContainer::Shared& contextContainer);
|
||||
|
||||
/*
|
||||
* Not copyable.
|
||||
*/
|
||||
TextLayoutManager(const TextLayoutManager&) = delete;
|
||||
TextLayoutManager& operator=(const TextLayoutManager&) = delete;
|
||||
|
||||
/*
|
||||
* Not movable.
|
||||
*/
|
||||
TextLayoutManager(TextLayoutManager&&) = delete;
|
||||
TextLayoutManager& operator=(TextLayoutManager&&) = delete;
|
||||
|
||||
/*
|
||||
* Measures `attributedString` using native text rendering infrastructure.
|
||||
*/
|
||||
TextMeasurement measure(
|
||||
const AttributedStringBox& attributedStringBox,
|
||||
const ParagraphAttributes& paragraphAttributes,
|
||||
const TextLayoutContext& layoutContext,
|
||||
const LayoutConstraints& layoutConstraints) const;
|
||||
|
||||
/*
|
||||
* Measures lines of `attributedString` using native text rendering
|
||||
* infrastructure.
|
||||
*/
|
||||
LinesMeasurements measureLines(
|
||||
const AttributedStringBox& attributedStringBox,
|
||||
const ParagraphAttributes& paragraphAttributes,
|
||||
const Size& size) const;
|
||||
|
||||
/*
|
||||
* Returns an opaque pointer to platform-specific TextLayoutManager.
|
||||
* Is used on a native views layer to delegate text rendering to the manager.
|
||||
*/
|
||||
std::shared_ptr<void> getNativeTextLayoutManager() const;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<const ContextContainer> contextContainer_;
|
||||
std::shared_ptr<void> nativeTextLayoutManager_;
|
||||
TextMeasureCache textMeasureCache_;
|
||||
LineMeasureCache lineMeasureCache_;
|
||||
};
|
||||
|
||||
} // namespace facebook::react
|
||||
Reference in New Issue
Block a user