mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Remove folly::dynamic AttributedString storage (#44512)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/44512 We only ever go through MapBuffer now, so we can remove the code related to storing text fragments in folly::dynamic. Changelog: [Internal] Reviewed By: rshest Differential Revision: D56963463 fbshipit-source-id: 98bce8aa4ccad134ce18bf35028e1b7b5082c3ca
This commit is contained in:
committed by
Facebook GitHub Bot
parent
082e29ed4e
commit
fd8f1f5274
@@ -813,176 +813,6 @@ inline std::string toString(const AttributedString::Range& range) {
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
inline folly::dynamic toDynamic(
|
||||
const ParagraphAttributes& paragraphAttributes) {
|
||||
auto values = folly::dynamic::object();
|
||||
values("maximumNumberOfLines", paragraphAttributes.maximumNumberOfLines);
|
||||
values("ellipsizeMode", toString(paragraphAttributes.ellipsizeMode));
|
||||
values("textBreakStrategy", toString(paragraphAttributes.textBreakStrategy));
|
||||
values("adjustsFontSizeToFit", paragraphAttributes.adjustsFontSizeToFit);
|
||||
values("includeFontPadding", paragraphAttributes.includeFontPadding);
|
||||
values(
|
||||
"android_hyphenationFrequency",
|
||||
toString(paragraphAttributes.android_hyphenationFrequency));
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
inline folly::dynamic toDynamic(const FontVariant& fontVariant) {
|
||||
auto result = folly::dynamic::array();
|
||||
if ((int)fontVariant & (int)FontVariant::SmallCaps) {
|
||||
result.push_back("small-caps");
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::OldstyleNums) {
|
||||
result.push_back("oldstyle-nums");
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::LiningNums) {
|
||||
result.push_back("lining-nums");
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::TabularNums) {
|
||||
result.push_back("tabular-nums");
|
||||
}
|
||||
if ((int)fontVariant & (int)FontVariant::ProportionalNums) {
|
||||
result.push_back("proportional-nums");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
inline folly::dynamic toDynamic(const TextAttributes& textAttributes) {
|
||||
auto _textAttributes = folly::dynamic::object();
|
||||
if (textAttributes.foregroundColor) {
|
||||
_textAttributes(
|
||||
"foregroundColor", toAndroidRepr(textAttributes.foregroundColor));
|
||||
}
|
||||
if (textAttributes.backgroundColor) {
|
||||
_textAttributes(
|
||||
"backgroundColor", toAndroidRepr(textAttributes.backgroundColor));
|
||||
}
|
||||
if (!std::isnan(textAttributes.opacity)) {
|
||||
_textAttributes("opacity", textAttributes.opacity);
|
||||
}
|
||||
if (!textAttributes.fontFamily.empty()) {
|
||||
_textAttributes("fontFamily", textAttributes.fontFamily);
|
||||
}
|
||||
if (!std::isnan(textAttributes.fontSize)) {
|
||||
_textAttributes("fontSize", textAttributes.fontSize);
|
||||
}
|
||||
if (!std::isnan(textAttributes.fontSizeMultiplier)) {
|
||||
_textAttributes("fontSizeMultiplier", textAttributes.fontSizeMultiplier);
|
||||
}
|
||||
if (textAttributes.fontWeight.has_value()) {
|
||||
_textAttributes("fontWeight", toString(*textAttributes.fontWeight));
|
||||
}
|
||||
if (textAttributes.fontStyle.has_value()) {
|
||||
_textAttributes("fontStyle", toString(*textAttributes.fontStyle));
|
||||
}
|
||||
if (textAttributes.fontVariant.has_value()) {
|
||||
_textAttributes("fontVariant", toDynamic(*textAttributes.fontVariant));
|
||||
}
|
||||
if (textAttributes.allowFontScaling.has_value()) {
|
||||
_textAttributes("allowFontScaling", *textAttributes.allowFontScaling);
|
||||
}
|
||||
if (!std::isnan(textAttributes.letterSpacing)) {
|
||||
_textAttributes("letterSpacing", textAttributes.letterSpacing);
|
||||
}
|
||||
if (textAttributes.textTransform.has_value()) {
|
||||
_textAttributes("textTransform", toString(*textAttributes.textTransform));
|
||||
}
|
||||
if (!std::isnan(textAttributes.lineHeight)) {
|
||||
_textAttributes("lineHeight", textAttributes.lineHeight);
|
||||
}
|
||||
if (textAttributes.alignment.has_value()) {
|
||||
_textAttributes("alignment", toString(*textAttributes.alignment));
|
||||
}
|
||||
if (textAttributes.baseWritingDirection.has_value()) {
|
||||
_textAttributes(
|
||||
"baseWritingDirection", toString(*textAttributes.baseWritingDirection));
|
||||
}
|
||||
if (textAttributes.lineBreakStrategy.has_value()) {
|
||||
_textAttributes(
|
||||
"lineBreakStrategyIOS", toString(*textAttributes.lineBreakStrategy));
|
||||
}
|
||||
// Decoration
|
||||
if (textAttributes.textDecorationColor) {
|
||||
_textAttributes(
|
||||
"textDecorationColor",
|
||||
toAndroidRepr(textAttributes.textDecorationColor));
|
||||
}
|
||||
if (textAttributes.textDecorationLineType.has_value()) {
|
||||
_textAttributes(
|
||||
"textDecorationLine", toString(*textAttributes.textDecorationLineType));
|
||||
}
|
||||
if (textAttributes.textDecorationStyle.has_value()) {
|
||||
_textAttributes(
|
||||
"textDecorationStyle", toString(*textAttributes.textDecorationStyle));
|
||||
}
|
||||
// Shadow
|
||||
// textShadowOffset = textAttributes.textShadowOffset.has_value() ?
|
||||
// textAttributes.textShadowOffset.value() : textShadowOffset;
|
||||
if (!std::isnan(textAttributes.textShadowRadius)) {
|
||||
_textAttributes("textShadowRadius", textAttributes.textShadowRadius);
|
||||
}
|
||||
if (textAttributes.textShadowColor) {
|
||||
_textAttributes(
|
||||
"textShadowColor", toAndroidRepr(textAttributes.textShadowColor));
|
||||
}
|
||||
// Special
|
||||
if (textAttributes.isHighlighted.has_value()) {
|
||||
_textAttributes("isHighlighted", *textAttributes.isHighlighted);
|
||||
}
|
||||
if (textAttributes.layoutDirection.has_value()) {
|
||||
_textAttributes(
|
||||
"layoutDirection", toString(*textAttributes.layoutDirection));
|
||||
}
|
||||
if (textAttributes.accessibilityRole.has_value()) {
|
||||
_textAttributes(
|
||||
"accessibilityRole", toString(*textAttributes.accessibilityRole));
|
||||
}
|
||||
if (textAttributes.textAlignVertical.has_value()) {
|
||||
_textAttributes(
|
||||
"textAlignVertical", toString(*textAttributes.textAlignVertical));
|
||||
}
|
||||
return _textAttributes;
|
||||
}
|
||||
|
||||
inline folly::dynamic toDynamic(const AttributedString::Fragment& fragment) {
|
||||
folly::dynamic value = folly::dynamic::object();
|
||||
|
||||
value["string"] = fragment.string;
|
||||
if (fragment.parentShadowView.componentHandle) {
|
||||
value["reactTag"] = fragment.parentShadowView.tag;
|
||||
}
|
||||
if (fragment.isAttachment()) {
|
||||
value["isAttachment"] = true;
|
||||
value["width"] = fragment.parentShadowView.layoutMetrics.frame.size.width;
|
||||
value["height"] = fragment.parentShadowView.layoutMetrics.frame.size.height;
|
||||
}
|
||||
value["textAttributes"] = toDynamic(fragment.textAttributes);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
inline folly::dynamic toDynamic(const AttributedString& attributedString) {
|
||||
auto value = folly::dynamic::object();
|
||||
auto fragments = folly::dynamic::array();
|
||||
for (auto fragment : attributedString.getFragments()) {
|
||||
fragments.push_back(toDynamic(fragment));
|
||||
}
|
||||
value("fragments", fragments);
|
||||
value(
|
||||
"hash", std::hash<facebook::react::AttributedString>{}(attributedString));
|
||||
value("string", attributedString.getString());
|
||||
return value;
|
||||
}
|
||||
|
||||
inline folly::dynamic toDynamic(const AttributedString::Range& range) {
|
||||
folly::dynamic dynamicValue = folly::dynamic::object();
|
||||
dynamicValue["location"] = range.location;
|
||||
dynamicValue["length"] = range.length;
|
||||
return dynamicValue;
|
||||
}
|
||||
|
||||
// constants for AttributedString serialization
|
||||
constexpr static MapBuffer::Key AS_KEY_HASH = 0;
|
||||
constexpr static MapBuffer::Key AS_KEY_STRING = 1;
|
||||
|
||||
-45
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <react/renderer/attributedstring/TextAttributes.h>
|
||||
#include <react/renderer/attributedstring/conversions.h>
|
||||
#include <react/renderer/attributedstring/primitives.h>
|
||||
#include <react/renderer/core/graphicsConversions.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
TEST(AttributedStringTest, testToDynamic) {
|
||||
auto attributedString = AttributedString{};
|
||||
auto fragment = AttributedString::Fragment{};
|
||||
fragment.string = "test";
|
||||
|
||||
auto text = TextAttributes{};
|
||||
text.foregroundColor = {
|
||||
colorFromComponents({100 / 255.0, 153 / 255.0, 200 / 255.0, 1.0})};
|
||||
text.opacity = 0.5;
|
||||
text.fontStyle = FontStyle::Italic;
|
||||
text.fontWeight = FontWeight::Thin;
|
||||
text.fontVariant = FontVariant::TabularNums;
|
||||
fragment.textAttributes = text;
|
||||
|
||||
attributedString.appendFragment(fragment);
|
||||
|
||||
auto result = toDynamic(attributedString);
|
||||
EXPECT_EQ(result["string"], fragment.string);
|
||||
auto textAttribute = result["fragments"][0]["textAttributes"];
|
||||
EXPECT_EQ(textAttribute["foregroundColor"], toDynamic(text.foregroundColor));
|
||||
EXPECT_EQ(textAttribute["opacity"], text.opacity);
|
||||
EXPECT_EQ(textAttribute["fontStyle"], toString(text.fontStyle.value()));
|
||||
EXPECT_EQ(textAttribute["fontWeight"], toString(text.fontWeight.value()));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace facebook::react
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <react/renderer/attributedstring/ParagraphAttributes.h>
|
||||
#include <react/renderer/attributedstring/conversions.h>
|
||||
#include <react/renderer/attributedstring/primitives.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
TEST(ParagraphAttributesTest, testToDynamic) {
|
||||
auto paragraphAttributes = ParagraphAttributes{};
|
||||
paragraphAttributes.maximumNumberOfLines = 2;
|
||||
paragraphAttributes.adjustsFontSizeToFit = false;
|
||||
paragraphAttributes.ellipsizeMode = EllipsizeMode::Middle;
|
||||
|
||||
auto result = toDynamic(paragraphAttributes);
|
||||
EXPECT_EQ(
|
||||
result["maximumNumberOfLines"], paragraphAttributes.maximumNumberOfLines);
|
||||
EXPECT_EQ(
|
||||
result["adjustsFontSizeToFit"], paragraphAttributes.adjustsFontSizeToFit);
|
||||
EXPECT_EQ(
|
||||
result["ellipsizeMode"], toString(paragraphAttributes.ellipsizeMode));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace facebook::react
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <react/renderer/attributedstring/TextAttributes.h>
|
||||
#include <react/renderer/attributedstring/conversions.h>
|
||||
#include <react/renderer/attributedstring/primitives.h>
|
||||
#include <react/renderer/core/graphicsConversions.h>
|
||||
|
||||
namespace facebook::react {
|
||||
|
||||
#ifdef ANDROID
|
||||
|
||||
TEST(TextAttributesTest, testToDynamic) {
|
||||
auto textAttributes = TextAttributes{};
|
||||
textAttributes.foregroundColor = {
|
||||
colorFromComponents({200 / 255.0, 153 / 255.0, 100 / 255.0, 1.0})};
|
||||
textAttributes.opacity = 0.5;
|
||||
textAttributes.fontStyle = FontStyle::Italic;
|
||||
textAttributes.fontWeight = FontWeight::Thin;
|
||||
textAttributes.fontVariant = FontVariant::TabularNums;
|
||||
|
||||
auto result = toDynamic(textAttributes);
|
||||
EXPECT_EQ(
|
||||
result["foregroundColor"], toDynamic(textAttributes.foregroundColor));
|
||||
EXPECT_EQ(result["opacity"], textAttributes.opacity);
|
||||
EXPECT_EQ(result["fontStyle"], toString(textAttributes.fontStyle.value()));
|
||||
EXPECT_EQ(result["fontWeight"], toString(textAttributes.fontWeight.value()));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace facebook::react
|
||||
@@ -14,7 +14,7 @@ namespace facebook::react {
|
||||
|
||||
#ifdef ANDROID
|
||||
folly::dynamic ParagraphState::getDynamic() const {
|
||||
return toDynamic(*this);
|
||||
LOG(FATAL) << "ParagraphState may only be serialized to MapBuffer";
|
||||
}
|
||||
|
||||
MapBuffer ParagraphState::getMapBuffer() const {
|
||||
|
||||
@@ -18,15 +18,6 @@
|
||||
namespace facebook::react {
|
||||
|
||||
#ifdef ANDROID
|
||||
inline folly::dynamic toDynamic(const ParagraphState& paragraphState) {
|
||||
folly::dynamic newState = folly::dynamic::object();
|
||||
newState["attributedString"] = toDynamic(paragraphState.attributedString);
|
||||
newState["paragraphAttributes"] =
|
||||
toDynamic(paragraphState.paragraphAttributes);
|
||||
newState["hash"] = newState["attributedString"]["hash"];
|
||||
return newState;
|
||||
}
|
||||
|
||||
inline MapBuffer toMapBuffer(const ParagraphState& paragraphState) {
|
||||
auto builder = MapBufferBuilder();
|
||||
auto attStringMapBuffer = toMapBuffer(paragraphState.attributedString);
|
||||
|
||||
+4
-15
@@ -66,27 +66,16 @@ AndroidTextInputState::AndroidTextInputState(
|
||||
.getDouble()){};
|
||||
|
||||
folly::dynamic AndroidTextInputState::getDynamic() const {
|
||||
// Java doesn't need all fields, so we don't pass them all along.
|
||||
folly::dynamic newState = folly::dynamic::object();
|
||||
LOG(FATAL) << "Android TextInput state should only be read using MapBuffer";
|
||||
}
|
||||
|
||||
MapBuffer AndroidTextInputState::getMapBuffer() const {
|
||||
auto builder = MapBufferBuilder();
|
||||
// If we have a `cachedAttributedStringId` we know that we're (1) not trying
|
||||
// to set a new string, so we don't need to pass it along; (2) setState was
|
||||
// called from Java to trigger a relayout with a `cachedAttributedStringId`,
|
||||
// so Java has all up-to-date information and we should pass an empty map
|
||||
// through.
|
||||
if (cachedAttributedStringId == 0) {
|
||||
newState["mostRecentEventCount"] = mostRecentEventCount;
|
||||
newState["attributedString"] = toDynamic(attributedString);
|
||||
newState["hash"] = newState["attributedString"]["hash"];
|
||||
newState["paragraphAttributes"] =
|
||||
toDynamic(paragraphAttributes); // TODO: can we memoize this in Java?
|
||||
}
|
||||
return newState;
|
||||
}
|
||||
|
||||
MapBuffer AndroidTextInputState::getMapBuffer() const {
|
||||
auto builder = MapBufferBuilder();
|
||||
// See comment in getDynamic block.
|
||||
if (cachedAttributedStringId == 0) {
|
||||
// TODO truncation
|
||||
builder.putInt(
|
||||
|
||||
Reference in New Issue
Block a user