Skip to content
Closed
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 @@ -54,17 +54,20 @@ class TextAttributes : public DebugStringConvertible {
Float opacity{std::numeric_limits<Float>::quiet_NaN()};

// Font
// We list 4-byte fields first to mitigate alignment gaps created by smaller
// values. Keep these fields in sync with TextAttributesLayoutTest, which
// checks alignment.
std::string fontFamily{""};
Float fontSize{std::numeric_limits<Float>::quiet_NaN()};
Float fontSizeMultiplier{std::numeric_limits<Float>::quiet_NaN()};
std::optional<FontWeight> fontWeight{};
std::optional<FontStyle> fontStyle{};
Float maxFontSizeMultiplier{std::numeric_limits<Float>::quiet_NaN()};
Float letterSpacing{std::numeric_limits<Float>::quiet_NaN()};
std::optional<FontVariant> fontVariant{};
std::optional<std::string> fontVariationSettings{};
std::optional<FontWeight> fontWeight{};
std::optional<FontStyle> fontStyle{};
std::optional<bool> allowFontScaling{};
Float maxFontSizeMultiplier{std::numeric_limits<Float>::quiet_NaN()};
std::optional<DynamicTypeRamp> dynamicTypeRamp{};
Float letterSpacing{std::numeric_limits<Float>::quiet_NaN()};
std::optional<TextTransform> textTransform{};

// Paragraph Styles
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,18 @@

#include <react/cxxstableapi/FrameworksGuard.h>

#include <cstdint>
#include <functional>
#include <limits>

namespace facebook::react {

enum class FontStyle { Normal, Italic, Oblique };
// We explicitly use the smallest size for each enum type in TextAttributes to
// optimize memory used by each AttributedString fragment and text measurement
// cache key. Usually this is 1 byte but some types have larger enum values.
enum class FontStyle : uint8_t { Normal, Italic, Oblique };

enum class FontWeight : int {
enum class FontWeight : uint16_t {
Weight100 = 100,
UltraLight = 100,
Weight200 = 200,
Expand Down Expand Up @@ -67,7 +71,7 @@ enum class FontVariant : int {
StylisticTwenty = 1 << 25
};

enum class DynamicTypeRamp {
enum class DynamicTypeRamp : uint8_t {
Caption2,
Caption1,
Footnote,
Expand Down Expand Up @@ -99,7 +103,7 @@ enum class TextWidthMode {
LongestLine,
};

enum class TextAlignment {
enum class TextAlignment : uint8_t {
Natural, // Indicates the default alignment for script.
Left, // Visually left aligned.
Center, // Visually centered.
Expand All @@ -116,14 +120,14 @@ enum class TextAlignmentVertical {
Center,
};

enum class WritingDirection {
enum class WritingDirection : uint8_t {
Natural, // Determines direction using the Unicode Bidi Algorithm rules P2 and
// P3.
LeftToRight, // Left to right writing direction.
RightToLeft // Right to left writing direction.
};

enum class LineBreakStrategy {
enum class LineBreakStrategy : uint8_t {
None, // Don't use any line break strategies
PushOut, // Use the push out line break strategy.
HangulWordPriority, // When specified, it prohibits breaking between Hangul
Expand All @@ -132,7 +136,7 @@ enum class LineBreakStrategy {
// system uses for standard UI labels.
};

enum class LineBreakMode {
enum class LineBreakMode : uint8_t {
Word, // Wrap at word boundaries, default
Char, // Wrap at character boundaries
Clip, // Simply clip
Expand All @@ -141,11 +145,11 @@ enum class LineBreakMode {
Tail // Truncate at tail of line: "abcd..."
};

enum class TextDecorationLineType { None, Underline, Strikethrough, UnderlineStrikethrough };
enum class TextDecorationLineType : uint8_t { None, Underline, Strikethrough, UnderlineStrikethrough };

enum class TextDecorationStyle { Solid, Double, Dotted, Dashed, Wavy };
enum class TextDecorationStyle : uint8_t { Solid, Double, Dotted, Dashed, Wavy };

enum class TextTransform {
enum class TextTransform : uint8_t {
None,
Uppercase,
Lowercase,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* 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 <algorithm>
#include <cstddef>
#include <sstream>
#include <vector>

#include <react/renderer/attributedstring/TextAttributes.h>

namespace facebook::react {
namespace {

struct Member {
const char* name;
size_t offset;
size_t size;
};

template <typename T>
size_t offsetWithin(const TextAttributes& attributes, const T& member) {
return static_cast<size_t>(
reinterpret_cast<const char*>(&member) -
reinterpret_cast<const char*>(&attributes));
}

} // namespace

// The Font group of TextAttributes lists its 4-byte fields before its 2-byte
// optionals to mitigate alignment gaps. This checks the span the group's
// fields cover against the sum of their sizes, so it does not depend on the
// order below matching the header's. A field added to the group belongs among
// the fields of its size, and in this list.
TEST(TextAttributesLayoutTest, fontGroupHasNoAlignmentGaps) {
TextAttributes attributes;
#define MEMBER(field) \
Member{ \
#field, \
offsetWithin(attributes, attributes.field), \
sizeof(attributes.field)}
std::vector<Member> fontGroup = {
MEMBER(fontFamily),
MEMBER(fontSize),
MEMBER(fontSizeMultiplier),
MEMBER(maxFontSizeMultiplier),
MEMBER(letterSpacing),
MEMBER(fontVariant),
MEMBER(fontVariationSettings),
MEMBER(fontWeight),
MEMBER(fontStyle),
MEMBER(allowFontScaling),
MEMBER(dynamicTypeRamp),
MEMBER(textTransform),
};
#undef MEMBER

std::sort(
fontGroup.begin(), fontGroup.end(), [](const auto& a, const auto& b) {
return a.offset < b.offset;
});
size_t total = 0;
std::ostringstream gaps;
for (size_t i = 0; i < fontGroup.size(); i++) {
total += fontGroup[i].size;
if (i > 0) {
auto previousEnd = fontGroup[i - 1].offset + fontGroup[i - 1].size;
if (fontGroup[i].offset > previousEnd) {
gaps << " " << (fontGroup[i].offset - previousEnd) << " bytes after "
<< fontGroup[i - 1].name << ",";
}
}
}
auto span = fontGroup.back().offset + fontGroup.back().size -
fontGroup.front().offset;

EXPECT_EQ(span, total)
<< "The Font group of TextAttributes spans " << span
<< " bytes but its fields total " << total << ". Gaps:" << gaps.str()
<< " either a field is out of size order in TextAttributes.h or a Font "
<< "field is missing from this test's list.";
}

} // namespace facebook::react
20 changes: 10 additions & 10 deletions scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api
Original file line number Diff line number Diff line change
Expand Up @@ -6206,7 +6206,7 @@ enum facebook::react::DisplayType {
None,
}

enum facebook::react::DynamicTypeRamp {
enum facebook::react::DynamicTypeRamp : uint8_t {
Body,
Callout,
Caption1,
Expand Down Expand Up @@ -6255,7 +6255,7 @@ enum facebook::react::FocusDirection {
FocusUp,
}

enum facebook::react::FontStyle {
enum facebook::react::FontStyle : uint8_t {
Italic,
Normal,
Oblique,
Expand Down Expand Up @@ -6290,7 +6290,7 @@ enum facebook::react::FontVariant : int {
TabularNums,
}

enum facebook::react::FontWeight : int {
enum facebook::react::FontWeight : uint16_t {
Black,
Bold,
Demibold,
Expand Down Expand Up @@ -6362,7 +6362,7 @@ enum facebook::react::LayoutDirection {
Undefined,
}

enum facebook::react::LineBreakMode {
enum facebook::react::LineBreakMode : uint8_t {
Char,
Clip,
Head,
Expand All @@ -6371,7 +6371,7 @@ enum facebook::react::LineBreakMode {
Word,
}

enum facebook::react::LineBreakStrategy {
enum facebook::react::LineBreakStrategy : uint8_t {
HangulWordPriority,
None,
PushOut,
Expand Down Expand Up @@ -6629,7 +6629,7 @@ enum facebook::react::SubmitBehavior {
Submit,
}

enum facebook::react::TextAlignment {
enum facebook::react::TextAlignment : uint8_t {
Center,
End,
Justified,
Expand All @@ -6652,22 +6652,22 @@ enum facebook::react::TextBreakStrategy {
Simple,
}

enum facebook::react::TextDecorationLineType {
enum facebook::react::TextDecorationLineType : uint8_t {
None,
Strikethrough,
Underline,
UnderlineStrikethrough,
}

enum facebook::react::TextDecorationStyle {
enum facebook::react::TextDecorationStyle : uint8_t {
Dashed,
Dotted,
Double,
Solid,
Wavy,
}

enum facebook::react::TextTransform {
enum facebook::react::TextTransform : uint8_t {
Capitalize,
Lowercase,
None,
Expand Down Expand Up @@ -6715,7 +6715,7 @@ enum facebook::react::UnitType {
Undefined,
}

enum facebook::react::WritingDirection {
enum facebook::react::WritingDirection : uint8_t {
LeftToRight,
Natural,
RightToLeft,
Expand Down
20 changes: 10 additions & 10 deletions scripts/cxx-api/api-snapshots/ReactAndroidNewarchCxx.api
Original file line number Diff line number Diff line change
Expand Up @@ -6016,7 +6016,7 @@ enum facebook::react::DisplayType {
None,
}

enum facebook::react::DynamicTypeRamp {
enum facebook::react::DynamicTypeRamp : uint8_t {
Body,
Callout,
Caption1,
Expand Down Expand Up @@ -6065,7 +6065,7 @@ enum facebook::react::FocusDirection {
FocusUp,
}

enum facebook::react::FontStyle {
enum facebook::react::FontStyle : uint8_t {
Italic,
Normal,
Oblique,
Expand Down Expand Up @@ -6100,7 +6100,7 @@ enum facebook::react::FontVariant : int {
TabularNums,
}

enum facebook::react::FontWeight : int {
enum facebook::react::FontWeight : uint16_t {
Black,
Bold,
Demibold,
Expand Down Expand Up @@ -6172,7 +6172,7 @@ enum facebook::react::LayoutDirection {
Undefined,
}

enum facebook::react::LineBreakMode {
enum facebook::react::LineBreakMode : uint8_t {
Char,
Clip,
Head,
Expand All @@ -6181,7 +6181,7 @@ enum facebook::react::LineBreakMode {
Word,
}

enum facebook::react::LineBreakStrategy {
enum facebook::react::LineBreakStrategy : uint8_t {
HangulWordPriority,
None,
PushOut,
Expand Down Expand Up @@ -6439,7 +6439,7 @@ enum facebook::react::SubmitBehavior {
Submit,
}

enum facebook::react::TextAlignment {
enum facebook::react::TextAlignment : uint8_t {
Center,
End,
Justified,
Expand All @@ -6462,22 +6462,22 @@ enum facebook::react::TextBreakStrategy {
Simple,
}

enum facebook::react::TextDecorationLineType {
enum facebook::react::TextDecorationLineType : uint8_t {
None,
Strikethrough,
Underline,
UnderlineStrikethrough,
}

enum facebook::react::TextDecorationStyle {
enum facebook::react::TextDecorationStyle : uint8_t {
Dashed,
Dotted,
Double,
Solid,
Wavy,
}

enum facebook::react::TextTransform {
enum facebook::react::TextTransform : uint8_t {
Capitalize,
Lowercase,
None,
Expand Down Expand Up @@ -6525,7 +6525,7 @@ enum facebook::react::UnitType {
Undefined,
}

enum facebook::react::WritingDirection {
enum facebook::react::WritingDirection : uint8_t {
LeftToRight,
Natural,
RightToLeft,
Expand Down
Loading
Loading