mirror of
https://github.com/react/react-native.git
synced 2026-09-28 05:13:06 +08:00
Summary: Fabric's `ParagraphAttributes` carries a `maximumFontSize` field, but it is not exposed by the `<Text>` or `<TextInput>` APIs, so normal JS usage leaves it as `NaN`. On iOS, `RCTTextLayoutManager` falls back to a 96pt maximum when it is `NaN`. On Android, the C++ side serializes it into MapBuffer key 7, but `TextLayoutManager` never reads that key. This PR removes the attribute: the `ParagraphAttributes` field, its raw-prop parsing in `conversions.h`, the paragraph and text input prop entries, and MapBuffer key 7 on both the C++ and Kotlin sides. - **iOS**: `RCTTextLayoutManager` now passes the largest font size in the attributed string to `scaleFontSizeToFitSize:` as the maximum instead of 96pt. `scaleFontSizeToFitSize:` returns early when the text already fits; otherwise `scaleFontSizeWithRatio:` applies `MIN(pointSize * ratio, maximumFontSize)` on each pass of a bisection over the ratio. With 96pt, fonts above 96pt were clamped to 96pt on every pass, and when that clamp alone made the text fit, the search went on to ratios above 1.0 and grew the remaining fonts up to 96pt. With the largest font size as the maximum the clamp is a no-op, the ratio-1.0 pass reproduces the original text, which is known not to fit, and every later pass shrinks. Fonts above 96pt are now scaled proportionally rather than capped, and text is never grown. Text at 96pt or smaller is unaffected. - **Android**: `PA_KEY_MAXIMUM_FONT_SIZE` is removed. Nothing reads it, so there is no behavior change. Split out of https://github.com/react/react-native/issues/58492. https://github.com/react/react-native/issues/58492 builds on this and reuses the largest-font-size helper for `minimumFontScale`. ## Changelog: [GENERAL] [REMOVED] - Remove the unused `maximumFontSize` paragraph attribute Pull Request resolved: https://github.com/react/react-native/pull/58529 Test Plan: **Unit tests** - Updated `ParagraphAttributesTest.cpp` for the removed field. - Regenerated the C++ API snapshots (`yarn cxx-api-build`). ```sh ./gradlew :packages:react-native:ReactAndroid:testDebugUnitTest --tests 'com.facebook.react.views.text.*' ``` All 38 `com.facebook.react.views.text` tests pass. Reviewed By: cipolleschi Differential Revision: D120127100 Pulled By: javache fbshipit-source-id: 44e7de2c21c95500e721d5c6f4b4e207da369713
249 lines
7.5 KiB
C++
249 lines
7.5 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.
|
|
*/
|
|
|
|
#include "BaseTextInputProps.h"
|
|
#include <react/renderer/attributedstring/TextAttributes.h>
|
|
#include <react/renderer/attributedstring/conversions.h>
|
|
#include <react/renderer/components/image/conversions.h>
|
|
#include <react/renderer/components/textinput/baseConversions.h>
|
|
#include <react/renderer/core/Props.h>
|
|
#include <react/renderer/core/PropsMacros.h>
|
|
#include <react/renderer/core/PropsParserContext.h>
|
|
#include <react/renderer/core/graphicsConversions.h>
|
|
#include <react/renderer/core/propsConversions.h>
|
|
#include <react/renderer/graphics/Color.h>
|
|
#include <react/renderer/imagemanager/primitives.h>
|
|
#include <limits>
|
|
|
|
namespace facebook::react {
|
|
|
|
BaseTextInputProps::BaseTextInputProps(
|
|
const PropsParserContext& context,
|
|
const BaseTextInputProps& sourceProps,
|
|
const RawProps& rawProps)
|
|
: ViewProps(context, sourceProps, rawProps),
|
|
BaseTextProps(context, sourceProps, rawProps),
|
|
paragraphAttributes(convertRawProp(
|
|
context,
|
|
rawProps,
|
|
sourceProps.paragraphAttributes,
|
|
{})),
|
|
defaultValue(convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"defaultValue",
|
|
sourceProps.defaultValue,
|
|
{})),
|
|
placeholder(convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"placeholder",
|
|
sourceProps.placeholder,
|
|
{})),
|
|
placeholderTextColor(convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"placeholderTextColor",
|
|
sourceProps.placeholderTextColor,
|
|
{})),
|
|
cursorColor(convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"cursorColor",
|
|
sourceProps.cursorColor,
|
|
{})),
|
|
selectionColor(convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"selectionColor",
|
|
sourceProps.selectionColor,
|
|
{})),
|
|
selectionHandleColor(convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"selectionHandleColor",
|
|
sourceProps.selectionHandleColor,
|
|
{})),
|
|
underlineColorAndroid(convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"underlineColorAndroid",
|
|
sourceProps.underlineColorAndroid,
|
|
{})),
|
|
maxLength(convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"maxLength",
|
|
sourceProps.maxLength,
|
|
{std::numeric_limits<int>::max()})),
|
|
text(convertRawProp(context, rawProps, "text", sourceProps.text, {})),
|
|
mostRecentEventCount(convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"mostRecentEventCount",
|
|
sourceProps.mostRecentEventCount,
|
|
{})),
|
|
autoFocus(convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"autoFocus",
|
|
sourceProps.autoFocus,
|
|
{})),
|
|
autoCapitalize(convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"autoCapitalize",
|
|
sourceProps.autoCapitalize,
|
|
{})),
|
|
editable(convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"editable",
|
|
sourceProps.editable,
|
|
{})),
|
|
readOnly(convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"readOnly",
|
|
sourceProps.readOnly,
|
|
{})),
|
|
submitBehavior(convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"submitBehavior",
|
|
sourceProps.submitBehavior,
|
|
{})),
|
|
multiline(convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"multiline",
|
|
sourceProps.multiline,
|
|
{false})),
|
|
disableKeyboardShortcuts(convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"disableKeyboardShortcuts",
|
|
sourceProps.disableKeyboardShortcuts,
|
|
{false})),
|
|
acceptDragAndDropTypes(convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"acceptDragAndDropTypes",
|
|
sourceProps.acceptDragAndDropTypes,
|
|
{})) {}
|
|
|
|
void BaseTextInputProps::setProp(
|
|
const PropsParserContext& context,
|
|
RawPropsPropNameHash hash,
|
|
const char* propName,
|
|
const RawValue& value) {
|
|
ViewProps::setProp(context, hash, propName, value);
|
|
BaseTextProps::setProp(context, hash, propName, value);
|
|
|
|
static auto defaults = BaseTextInputProps{};
|
|
|
|
// ParagraphAttributes has its own switch statement - to keep all
|
|
// of these fields together, and because there are some collisions between
|
|
// propnames parsed here and outside of ParagraphAttributes. For example,
|
|
// textBreakStrategy is duplicated.
|
|
// This code is also duplicated in ParagraphProps.
|
|
static auto paDefaults = ParagraphAttributes{};
|
|
switch (hash) {
|
|
REBUILD_FIELD_SWITCH_CASE(
|
|
paDefaults,
|
|
value,
|
|
paragraphAttributes,
|
|
maximumNumberOfLines,
|
|
"numberOfLines");
|
|
REBUILD_FIELD_SWITCH_CASE(
|
|
paDefaults, value, paragraphAttributes, ellipsizeMode, "ellipsizeMode");
|
|
REBUILD_FIELD_SWITCH_CASE(
|
|
paDefaults,
|
|
value,
|
|
paragraphAttributes,
|
|
textBreakStrategy,
|
|
"textBreakStrategy");
|
|
REBUILD_FIELD_SWITCH_CASE(
|
|
paDefaults,
|
|
value,
|
|
paragraphAttributes,
|
|
adjustsFontSizeToFit,
|
|
"adjustsFontSizeToFit");
|
|
REBUILD_FIELD_SWITCH_CASE(
|
|
paDefaults,
|
|
value,
|
|
paragraphAttributes,
|
|
minimumFontSize,
|
|
"minimumFontSize");
|
|
REBUILD_FIELD_SWITCH_CASE(
|
|
paDefaults,
|
|
value,
|
|
paragraphAttributes,
|
|
includeFontPadding,
|
|
"includeFontPadding");
|
|
REBUILD_FIELD_SWITCH_CASE(
|
|
paDefaults,
|
|
value,
|
|
paragraphAttributes,
|
|
android_hyphenationFrequency,
|
|
"android_hyphenationFrequency");
|
|
REBUILD_FIELD_SWITCH_CASE(
|
|
paDefaults,
|
|
value,
|
|
paragraphAttributes,
|
|
textAlignVertical,
|
|
"textAlignVertical");
|
|
}
|
|
|
|
switch (hash) {
|
|
RAW_SET_PROP_SWITCH_CASE_BASIC(underlineColorAndroid);
|
|
RAW_SET_PROP_SWITCH_CASE_BASIC(autoFocus);
|
|
RAW_SET_PROP_SWITCH_CASE_BASIC(maxLength);
|
|
RAW_SET_PROP_SWITCH_CASE_BASIC(placeholder);
|
|
RAW_SET_PROP_SWITCH_CASE_BASIC(placeholderTextColor);
|
|
RAW_SET_PROP_SWITCH_CASE_BASIC(selectionColor);
|
|
RAW_SET_PROP_SWITCH_CASE_BASIC(selectionHandleColor);
|
|
RAW_SET_PROP_SWITCH_CASE_BASIC(defaultValue);
|
|
RAW_SET_PROP_SWITCH_CASE_BASIC(cursorColor);
|
|
RAW_SET_PROP_SWITCH_CASE_BASIC(text);
|
|
RAW_SET_PROP_SWITCH_CASE_BASIC(mostRecentEventCount);
|
|
RAW_SET_PROP_SWITCH_CASE_BASIC(autoCapitalize);
|
|
RAW_SET_PROP_SWITCH_CASE_BASIC(editable);
|
|
RAW_SET_PROP_SWITCH_CASE_BASIC(readOnly);
|
|
RAW_SET_PROP_SWITCH_CASE_BASIC(submitBehavior);
|
|
RAW_SET_PROP_SWITCH_CASE_BASIC(multiline);
|
|
RAW_SET_PROP_SWITCH_CASE_BASIC(disableKeyboardShortcuts);
|
|
RAW_SET_PROP_SWITCH_CASE_BASIC(acceptDragAndDropTypes);
|
|
}
|
|
}
|
|
|
|
TextAttributes BaseTextInputProps::getEffectiveTextAttributes(
|
|
Float fontSizeMultiplier) const {
|
|
auto result = TextAttributes::defaultTextAttributes();
|
|
result.fontSizeMultiplier = fontSizeMultiplier;
|
|
result.apply(textAttributes);
|
|
|
|
/*
|
|
* These props are applied to `View`, therefore they must not be a part of
|
|
* base text attributes.
|
|
*/
|
|
result.backgroundColor = clearColor();
|
|
result.opacity = 1;
|
|
|
|
return result;
|
|
}
|
|
|
|
SubmitBehavior BaseTextInputProps::getNonDefaultSubmitBehavior() const {
|
|
if (submitBehavior == SubmitBehavior::Default) {
|
|
return multiline ? SubmitBehavior::Newline : SubmitBehavior::BlurAndSubmit;
|
|
}
|
|
|
|
return submitBehavior;
|
|
}
|
|
|
|
} // namespace facebook::react
|