Skip to content

Commit 2f6c744

Browse files
NickGerlemanmeta-codesync[bot]
authored andcommitted
Reland: Wire native CSS parsing for fontVariant (#55881)
Summary: Pull Request resolved: #55881 ## Reland No changes. This was on the same stack as D95032494 which was backed out due to bug. ## Original Gate `processFontVariant` behind `enableNativeCSSParsing()`. When the flag is on, CSS font-variant strings like `"small-caps oldstyle-nums"` are parsed natively using the existing CSS font-variant parser instead of being preprocessed in JS. Also removes `react_native_expect(false)` hard error on unknown font variant values, replacing it with a graceful skip. Changelog: [Internal] Reviewed By: fkgozali Differential Revision: D95021048 fbshipit-source-id: e75ce199565c7de3b883a95c61e5e534c2018cba
1 parent fecd8e3 commit 2f6c744

File tree

3 files changed

+135
-3
lines changed

3 files changed

+135
-3
lines changed

packages/react-native/Libraries/Components/View/ReactNativeStyleAttributes.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ export const transformOriginAttribute: AnyAttributeType = nativeCSSParsing
6767
? true
6868
: {process: processTransformOrigin};
6969

70+
export const fontVariantAttribute: AnyAttributeType = nativeCSSParsing
71+
? true
72+
: {process: processFontVariant};
73+
7074
const ReactNativeStyleAttributes: {[string]: AnyAttributeType, ...} = {
7175
/**
7276
* Layout
@@ -248,7 +252,7 @@ const ReactNativeStyleAttributes: {[string]: AnyAttributeType, ...} = {
248252
fontFamily: true,
249253
fontSize: true,
250254
fontStyle: true,
251-
fontVariant: {process: processFontVariant},
255+
fontVariant: fontVariantAttribute,
252256
fontWeight: true,
253257
includeFontPadding: true,
254258
letterSpacing: true,

packages/react-native/ReactCommon/react/renderer/attributedstring/conversions.h

Lines changed: 104 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include <folly/dynamic.h>
1111
#include <react/debug/react_native_expect.h>
12+
#include <react/featureflags/ReactNativeFeatureFlags.h>
1213
#include <react/renderer/attributedstring/AttributedString.h>
1314
#include <react/renderer/attributedstring/ParagraphAttributes.h>
1415
#include <react/renderer/attributedstring/TextAttributes.h>
@@ -21,6 +22,8 @@
2122
#include <react/renderer/core/conversions.h>
2223
#include <react/renderer/core/graphicsConversions.h>
2324
#include <react/renderer/core/propsConversions.h>
25+
#include <react/renderer/css/CSSFontVariant.h>
26+
#include <react/renderer/css/CSSValueParser.h>
2427
#include <unordered_map>
2528

2629
#ifdef RN_SERIALIZABLE_STATE
@@ -317,7 +320,73 @@ inline std::string toString(const FontStyle &fontStyle)
317320
return "normal";
318321
}
319322

320-
inline void fromRawValue(const PropsParserContext &context, const RawValue &value, FontVariant &result)
323+
inline std::optional<FontVariant> fontVariantFromCSSFontVariant(CSSFontVariant cssVariant)
324+
{
325+
switch (cssVariant) {
326+
case CSSFontVariant::SmallCaps:
327+
return FontVariant::SmallCaps;
328+
case CSSFontVariant::OldstyleNums:
329+
return FontVariant::OldstyleNums;
330+
case CSSFontVariant::LiningNums:
331+
return FontVariant::LiningNums;
332+
case CSSFontVariant::TabularNums:
333+
return FontVariant::TabularNums;
334+
case CSSFontVariant::ProportionalNums:
335+
return FontVariant::ProportionalNums;
336+
case CSSFontVariant::StylisticOne:
337+
return FontVariant::StylisticOne;
338+
case CSSFontVariant::StylisticTwo:
339+
return FontVariant::StylisticTwo;
340+
case CSSFontVariant::StylisticThree:
341+
return FontVariant::StylisticThree;
342+
case CSSFontVariant::StylisticFour:
343+
return FontVariant::StylisticFour;
344+
case CSSFontVariant::StylisticFive:
345+
return FontVariant::StylisticFive;
346+
case CSSFontVariant::StylisticSix:
347+
return FontVariant::StylisticSix;
348+
case CSSFontVariant::StylisticSeven:
349+
return FontVariant::StylisticSeven;
350+
case CSSFontVariant::StylisticEight:
351+
return FontVariant::StylisticEight;
352+
case CSSFontVariant::StylisticNine:
353+
return FontVariant::StylisticNine;
354+
case CSSFontVariant::StylisticTen:
355+
return FontVariant::StylisticTen;
356+
case CSSFontVariant::StylisticEleven:
357+
return FontVariant::StylisticEleven;
358+
case CSSFontVariant::StylisticTwelve:
359+
return FontVariant::StylisticTwelve;
360+
case CSSFontVariant::StylisticThirteen:
361+
return FontVariant::StylisticThirteen;
362+
case CSSFontVariant::StylisticFourteen:
363+
return FontVariant::StylisticFourteen;
364+
case CSSFontVariant::StylisticFifteen:
365+
return FontVariant::StylisticFifteen;
366+
case CSSFontVariant::StylisticSixteen:
367+
return FontVariant::StylisticSixteen;
368+
case CSSFontVariant::StylisticSeventeen:
369+
return FontVariant::StylisticSeventeen;
370+
case CSSFontVariant::StylisticEighteen:
371+
return FontVariant::StylisticEighteen;
372+
case CSSFontVariant::StylisticNineteen:
373+
return FontVariant::StylisticNineteen;
374+
case CSSFontVariant::StylisticTwenty:
375+
return FontVariant::StylisticTwenty;
376+
case CSSFontVariant::CommonLigatures:
377+
case CSSFontVariant::NoCommonLigatures:
378+
case CSSFontVariant::DiscretionaryLigatures:
379+
case CSSFontVariant::NoDiscretionaryLigatures:
380+
case CSSFontVariant::HistoricalLigatures:
381+
case CSSFontVariant::NoHistoricalLigatures:
382+
case CSSFontVariant::Contextual:
383+
case CSSFontVariant::NoContextual:
384+
return std::nullopt;
385+
}
386+
}
387+
388+
inline void
389+
parseProcessedFontVariant(const PropsParserContext & /*context*/, const RawValue &value, FontVariant &result)
321390
{
322391
result = FontVariant::Default;
323392
react_native_expect(value.hasType<std::vector<std::string>>());
@@ -376,14 +445,47 @@ inline void fromRawValue(const PropsParserContext &context, const RawValue &valu
376445
result = (FontVariant)((int)result | (int)FontVariant::StylisticTwenty);
377446
} else {
378447
LOG(ERROR) << "Unsupported FontVariant value: " << item;
379-
react_native_expect(false);
380448
}
381449
}
382450
} else {
383451
LOG(ERROR) << "Unsupported FontVariant type";
384452
}
385453
}
386454

455+
inline void parseUnprocessedFontVariantString(const std::string &value, FontVariant &result)
456+
{
457+
auto fontVariantList = parseCSSProperty<CSSFontVariantList>(value);
458+
if (!std::holds_alternative<CSSFontVariantList>(fontVariantList)) {
459+
result = FontVariant::Default;
460+
return;
461+
}
462+
463+
result = FontVariant::Default;
464+
for (const auto &cssVariant : std::get<CSSFontVariantList>(fontVariantList)) {
465+
if (auto fv = fontVariantFromCSSFontVariant(cssVariant)) {
466+
result = (FontVariant)((int)result | (int)*fv);
467+
}
468+
}
469+
}
470+
471+
inline void parseUnprocessedFontVariant(const PropsParserContext &context, const RawValue &value, FontVariant &result)
472+
{
473+
if (value.hasType<std::string>()) {
474+
parseUnprocessedFontVariantString((std::string)value, result);
475+
} else {
476+
parseProcessedFontVariant(context, value, result);
477+
}
478+
}
479+
480+
inline void fromRawValue(const PropsParserContext &context, const RawValue &value, FontVariant &result)
481+
{
482+
if (ReactNativeFeatureFlags::enableNativeCSSParsing()) {
483+
parseUnprocessedFontVariant(context, value, result);
484+
} else {
485+
parseProcessedFontVariant(context, value, result);
486+
}
487+
}
488+
387489
inline std::string toString(const FontVariant &fontVariant)
388490
{
389491
auto result = std::string{};

packages/react-native/ReactCommon/react/renderer/components/view/tests/ConversionsTest.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <gtest/gtest.h>
99

10+
#include <react/renderer/attributedstring/conversions.h>
1011
#include <react/renderer/components/view/BoxShadowPropsConversions.h>
1112
#include <react/renderer/components/view/FilterPropsConversions.h>
1213
#include <react/renderer/components/view/conversions.h>
@@ -454,4 +455,29 @@ TEST(ConversionsTest, unprocessed_transform_origin_rawvalue_string_with_z) {
454455
EXPECT_EQ(result.z, 15.0f);
455456
}
456457

458+
TEST(ConversionsTest, unprocessed_font_variant_string_single) {
459+
FontVariant result{};
460+
parseUnprocessedFontVariantString("small-caps", result);
461+
462+
EXPECT_EQ((int)result, (int)FontVariant::SmallCaps);
463+
}
464+
465+
TEST(ConversionsTest, unprocessed_font_variant_string_multiple) {
466+
FontVariant result{};
467+
parseUnprocessedFontVariantString(
468+
"small-caps oldstyle-nums tabular-nums", result);
469+
470+
EXPECT_EQ(
471+
(int)result,
472+
(int)FontVariant::SmallCaps | (int)FontVariant::OldstyleNums |
473+
(int)FontVariant::TabularNums);
474+
}
475+
476+
TEST(ConversionsTest, unprocessed_font_variant_string_invalid) {
477+
FontVariant result{};
478+
parseUnprocessedFontVariantString("not-a-variant", result);
479+
480+
EXPECT_EQ((int)result, (int)FontVariant::Default);
481+
}
482+
457483
} // namespace facebook::react

0 commit comments

Comments
 (0)