mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/51065 This adds infrastructure to let us start storing cached Android text layouts as part of a `ParagraphShadowNode`. After this, we will clear them out, and propagate them to state. Right now, the flag doesn't do much, apart from extra work. This is done by adding `TextLayoutManagerExtended::supportsPreparedLayout()`, and `TextLayoutManager::PreparedLayout` types, to shim between platforms, then on Android, we add a `PreparedLayout`, which is for now just an Android layout, with extra field (`maxNumberOfLines`, for some reason not exposed on recent versions). Android `TextLayoutManager` java side is split a little bit, so that we reuse all the existing logic for prepared layouts. I tried to set up the boundary, so that we don't reserialize a MapBuffer after preparation, and for simplicity, this means source of truth for attachment count, and attachment sizes, now lives on the layout. This means we need to change boundary a bit, where we are no longer able to pass in a buffer to fill from C++ side of attachment positions. Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D73970149 fbshipit-source-id: ff71c227e062c16fe52a4eb3ba2acbebf3d96e56
125 lines
4.0 KiB
C++
125 lines
4.0 KiB
C++
/*
|
|
* 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 <cstddef>
|
|
|
|
#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 {
|
|
|
|
template <typename TextLayoutManagerT>
|
|
concept TextLayoutManagerWithPreparedLayout = requires(
|
|
TextLayoutManagerT textLayoutManager,
|
|
AttributedString attributedString,
|
|
ParagraphAttributes paragraphAttributes,
|
|
TextLayoutContext layoutContext,
|
|
LayoutConstraints layoutConstraints,
|
|
typename TextLayoutManagerT::PreparedLayout preparedLayout) {
|
|
sizeof(typename TextLayoutManagerT::PreparedLayout);
|
|
{
|
|
textLayoutManager.prepareLayout(
|
|
attributedString, paragraphAttributes, layoutContext, layoutConstraints)
|
|
} -> std::same_as<typename TextLayoutManagerT::PreparedLayout>;
|
|
{
|
|
textLayoutManager.measurePreparedLayout(
|
|
preparedLayout, layoutContext, layoutConstraints)
|
|
} -> std::same_as<TextMeasurement>;
|
|
};
|
|
|
|
namespace detail {
|
|
template <typename T>
|
|
struct PreparedLayoutT {
|
|
using type = std::nullptr_t;
|
|
};
|
|
|
|
template <TextLayoutManagerWithPreparedLayout T>
|
|
struct PreparedLayoutT<T> {
|
|
using type = typename T::PreparedLayout;
|
|
};
|
|
|
|
/**
|
|
* 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>;
|
|
};
|
|
}
|
|
|
|
static constexpr bool supportsPreparedLayout() {
|
|
return TextLayoutManagerWithPreparedLayout<TextLayoutManagerT>;
|
|
}
|
|
|
|
using PreparedLayout = typename PreparedLayoutT<TextLayoutManagerT>::type;
|
|
|
|
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";
|
|
}
|
|
|
|
PreparedLayout prepareLayout(
|
|
const AttributedString& attributedString,
|
|
const ParagraphAttributes& paragraphAttributes,
|
|
const TextLayoutContext& layoutContext,
|
|
const LayoutConstraints& layoutConstraints) const {
|
|
if constexpr (supportsPreparedLayout()) {
|
|
return textLayoutManager_.prepareLayout(
|
|
attributedString,
|
|
paragraphAttributes,
|
|
layoutContext,
|
|
layoutConstraints);
|
|
}
|
|
LOG(FATAL) << "Platform TextLayoutManager does not support prepareLayout";
|
|
}
|
|
|
|
TextMeasurement measurePreparedLayout(
|
|
const PreparedLayout& layout,
|
|
const TextLayoutContext& layoutContext,
|
|
const LayoutConstraints& layoutConstraints) const {
|
|
if constexpr (supportsPreparedLayout()) {
|
|
return textLayoutManager_.measurePreparedLayout(
|
|
layout, layoutContext, layoutConstraints);
|
|
}
|
|
LOG(FATAL)
|
|
<< "Platform TextLayoutManager does not support measurePreparedLayout";
|
|
}
|
|
|
|
private:
|
|
const TextLayoutManagerT& textLayoutManager_;
|
|
};
|
|
} // namespace detail
|
|
|
|
using TextLayoutManagerExtended =
|
|
detail::TextLayoutManagerExtended<TextLayoutManager>;
|
|
|
|
} // namespace facebook::react
|