Skip to content

Platform specific TextLayoutManager Headers #50889

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -215,8 +216,18 @@ Float ParagraphShadowNode::baseline(

AttributedStringBox attributedStringBox{attributedString};

return LineMeasurement::baseline(textLayoutManager_->measureLines(
attributedStringBox, getConcreteProps().paragraphAttributes, size));
if constexpr (TextLayoutManagerExtended<
TextLayoutManager>::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) {
Expand All @@ -239,9 +250,16 @@ 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<
TextLayoutManager>::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()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand All @@ -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 {
Expand Down Expand Up @@ -106,9 +109,19 @@ class BaseTextInputShadowNode : public ConcreteViewShadowNode<
&(YogaLayoutableShadowNode::yogaNode_), YGEdgeTop);

AttributedStringBox attributedStringBox{attributedString};
return LineMeasurement::baseline(textLayoutManager_->measureLines(
attributedStringBox, props.paragraphAttributes, size)) +
top;

if constexpr (TextLayoutManagerExtended<
TextLayoutManager>::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;
}
}

/*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* 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 <type_traits>

#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 {

/**
* 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>
requires(std::is_same_v<TextLayoutManager, std::decay_t<TextLayoutManagerT>>)
class TextLayoutManagerExtended {
public:
static constexpr bool supportsLineMeasurement() {
return requires(TextLayoutManagerT textLayoutManager) {
{
textLayoutManager.measureLines(
AttributedStringBox{}, ParagraphAttributes{}, Size{})
} -> std::same_as<LinesMeasurements>;
};
}

TextLayoutManagerExtended(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:
TextLayoutManagerT& textLayoutManager_;
};

} // namespace facebook::react
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ class TextLayoutManager;
class TextLayoutManager {
public:
TextLayoutManager(const ContextContainer::Shared& contextContainer);
virtual ~TextLayoutManager() = default;

/*
* Not copyable.
Expand All @@ -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.
Expand All @@ -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_;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Loading