react-native-windows 0.78.5 → 0.78.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/Directory.Build.props +6 -4
  2. package/Folly/Folly.vcxproj +46 -6
  3. package/Folly/Folly.vcxproj.filters +16 -4
  4. package/Folly/TEMP_UntilFollyUpdate/ConstexprMath.h +26 -18
  5. package/Folly/TEMP_UntilFollyUpdate/Conv.cpp +1205 -0
  6. package/Folly/TEMP_UntilFollyUpdate/chrono/Hardware.h +155 -0
  7. package/Folly/TEMP_UntilFollyUpdate/concurrency/CacheLocality.cpp +633 -0
  8. package/Folly/TEMP_UntilFollyUpdate/{dynamic-inl.h → json/dynamic-inl.h} +3 -4
  9. package/Folly/TEMP_UntilFollyUpdate/{json.cpp → json/json.cpp} +14 -10
  10. package/Folly/TEMP_UntilFollyUpdate/lang/SafeAssert.h +7 -14
  11. package/Folly/TEMP_UntilFollyUpdate/lang/ToAscii.h +6 -6
  12. package/Folly/ThreadNameStub.cpp +10 -0
  13. package/Folly/cgmanifest.json +11 -1
  14. package/Libraries/Components/View/View.windows.js +107 -56
  15. package/Libraries/Components/View/ViewAccessibility.d.ts +60 -1
  16. package/Libraries/Image/Image.windows.js +42 -21
  17. package/Libraries/Modal/Modal.d.ts +7 -0
  18. package/Libraries/Modal/Modal.windows.js +7 -1
  19. package/Libraries/NativeComponent/BaseViewConfig.windows.js +3 -0
  20. package/Libraries/Text/Text.d.ts +18 -0
  21. package/Microsoft.ReactNative/AsynchronousEventBeat.cpp +4 -25
  22. package/Microsoft.ReactNative/AsynchronousEventBeat.h +0 -3
  23. package/Microsoft.ReactNative/Base/FollyIncludes.h +1 -0
  24. package/Microsoft.ReactNative/CallInvoker.cpp +42 -0
  25. package/Microsoft.ReactNative/CallInvoker.h +34 -0
  26. package/Microsoft.ReactNative/{JSDispatcherWriter.cpp → CallInvokerWriter.cpp} +35 -47
  27. package/Microsoft.ReactNative/CallInvokerWriter.h +74 -0
  28. package/Microsoft.ReactNative/CompositionComponentView.idl +0 -5
  29. package/Microsoft.ReactNative/CompositionSwitcher.idl +7 -0
  30. package/Microsoft.ReactNative/Fabric/AbiViewProps.cpp +8 -10
  31. package/Microsoft.ReactNative/Fabric/ComponentView.cpp +4 -1
  32. package/Microsoft.ReactNative/Fabric/Composition/ActivityIndicatorComponentView.cpp +12 -2
  33. package/Microsoft.ReactNative/Fabric/Composition/ActivityIndicatorComponentView.h +2 -0
  34. package/Microsoft.ReactNative/Fabric/Composition/CompositionAnnotationProvider.cpp +100 -0
  35. package/Microsoft.ReactNative/Fabric/Composition/CompositionAnnotationProvider.h +31 -0
  36. package/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp +77 -11
  37. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +43 -1
  38. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h +7 -0
  39. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +86 -56
  40. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h +5 -1
  41. package/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.cpp +0 -4
  42. package/Microsoft.ReactNative/Fabric/Composition/CompositionUIService.cpp +0 -2
  43. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +118 -63
  44. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +2 -0
  45. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp +133 -8
  46. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h +16 -2
  47. package/Microsoft.ReactNative/Fabric/Composition/FocusManager.cpp +4 -2
  48. package/Microsoft.ReactNative/Fabric/Composition/FocusManager.h +9 -1
  49. package/Microsoft.ReactNative/Fabric/Composition/ImageComponentView.cpp +34 -11
  50. package/Microsoft.ReactNative/Fabric/Composition/ImageComponentView.h +3 -0
  51. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +133 -135
  52. package/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.cpp +9 -6
  53. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +46 -49
  54. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +6 -1
  55. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp +13 -8
  56. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h +5 -2
  57. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +146 -25
  58. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h +14 -0
  59. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +160 -12
  60. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +6 -0
  61. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputEventEmitter.cpp +47 -0
  62. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputEventEmitter.h +15 -1
  63. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputProps.cpp +6 -2
  64. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputProps.h +4 -1
  65. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputShadowNode.cpp +7 -9
  66. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputShadowNode.h +4 -1
  67. package/Microsoft.ReactNative/Fabric/Composition/Theme.cpp +5 -0
  68. package/Microsoft.ReactNative/Fabric/Composition/TooltipService.cpp +40 -36
  69. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +68 -0
  70. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h +11 -0
  71. package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp +70 -13
  72. package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.h +10 -2
  73. package/Microsoft.ReactNative/Fabric/ImageManager.cpp +5 -5
  74. package/Microsoft.ReactNative/Fabric/ImageRequestParams.cpp +26 -0
  75. package/Microsoft.ReactNative/Fabric/WindowsImageManager.cpp +47 -8
  76. package/Microsoft.ReactNative/Fabric/WindowsImageManager.h +10 -1
  77. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/CompositionAccessibilityProps.h +67 -0
  78. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.cpp +22 -4
  79. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.h +15 -2
  80. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.cpp +20 -0
  81. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.h +5 -0
  82. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/MouseEvent.h +20 -0
  83. package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/HostPlatformColor.h +5 -8
  84. package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/PlatformColorParser.h +1 -2
  85. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.cpp +247 -45
  86. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.h +15 -0
  87. package/Microsoft.ReactNative/Fabric/platform/react/threading/MessageQueueThreadImpl.cpp +39 -0
  88. package/Microsoft.ReactNative/Fabric/platform/react/threading/MessageQueueThreadImpl.h +54 -0
  89. package/Microsoft.ReactNative/Fabric/platform/react/threading/TaskDispatchThread.cpp +126 -0
  90. package/Microsoft.ReactNative/Fabric/platform/react/threading/TaskDispatchThread.h +73 -0
  91. package/Microsoft.ReactNative/IReactContext.cpp +17 -0
  92. package/Microsoft.ReactNative/IReactContext.h +1 -0
  93. package/Microsoft.ReactNative/IReactContext.idl +18 -1
  94. package/Microsoft.ReactNative/IReactDispatcher.idl +1 -0
  95. package/Microsoft.ReactNative/IReactModuleBuilder.cpp +12 -0
  96. package/Microsoft.ReactNative/IReactModuleBuilder.h +2 -0
  97. package/Microsoft.ReactNative/IReactModuleBuilder.idl +8 -0
  98. package/Microsoft.ReactNative/JsiApi.cpp +10 -2
  99. package/Microsoft.ReactNative/JsiApi.h +1 -0
  100. package/Microsoft.ReactNative/JsiApi.idl +1 -0
  101. package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +0 -3
  102. package/Microsoft.ReactNative/Modules/AccessibilityInfoModule.cpp +2 -3
  103. package/Microsoft.ReactNative/Modules/AlertModule.cpp +7 -12
  104. package/Microsoft.ReactNative/Modules/Animated/AnimationDriver.cpp +2 -1
  105. package/Microsoft.ReactNative/Modules/Animated/NativeAnimatedModule.cpp +4 -8
  106. package/Microsoft.ReactNative/Modules/AppStateModule.cpp +2 -2
  107. package/Microsoft.ReactNative/Modules/ClipboardModule.cpp +6 -8
  108. package/Microsoft.ReactNative/Modules/ClipboardModule.h +1 -1
  109. package/Microsoft.ReactNative/Modules/ImageViewManagerModule.cpp +6 -15
  110. package/Microsoft.ReactNative/Modules/NativeUIManager.cpp +13 -24
  111. package/Microsoft.ReactNative/QuirkSettings.cpp +0 -16
  112. package/Microsoft.ReactNative/QuirkSettings.h +0 -3
  113. package/Microsoft.ReactNative/ReactHost/ReactHost.cpp +11 -1
  114. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +78 -68
  115. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h +1 -2
  116. package/Microsoft.ReactNative/ReactInstanceSettings.cpp +12 -0
  117. package/Microsoft.ReactNative/ReactInstanceSettings.h +2 -0
  118. package/Microsoft.ReactNative/ReactInstanceSettings.idl +6 -0
  119. package/Microsoft.ReactNative/ReactNativeIsland.idl +3 -0
  120. package/Microsoft.ReactNative/ReactSupport.cpp +44 -11
  121. package/Microsoft.ReactNative/RedBox.cpp +30 -1
  122. package/Microsoft.ReactNative/SchedulerSettings.cpp +4 -4
  123. package/Microsoft.ReactNative/SchedulerSettings.h +1 -1
  124. package/Microsoft.ReactNative/TurboModulesProvider.cpp +30 -12
  125. package/Microsoft.ReactNative/Utils/ImageUtils.h +1 -0
  126. package/Microsoft.ReactNative/Utils/LocalBundleReader.cpp +37 -31
  127. package/Microsoft.ReactNative.Cxx/ApiLoaders/JSRuntimeApi.cpp +1 -0
  128. package/Microsoft.ReactNative.Cxx/ApiLoaders/JSRuntimeApi.inc +2 -0
  129. package/Microsoft.ReactNative.Cxx/ApiLoaders/NodeApi_posix.cpp +1 -1
  130. package/Microsoft.ReactNative.Cxx/JSI/JsiAbiApi.cpp +94 -27
  131. package/Microsoft.ReactNative.Cxx/JSI/JsiAbiApi.h +27 -6
  132. package/Microsoft.ReactNative.Cxx/JSI/JsiApiContext.cpp +45 -11
  133. package/Microsoft.ReactNative.Cxx/JSI/JsiApiContext.h +6 -0
  134. package/Microsoft.ReactNative.Cxx/JSI/decorator.h +220 -0
  135. package/Microsoft.ReactNative.Cxx/JSI/instrumentation.h +28 -0
  136. package/Microsoft.ReactNative.Cxx/JSI/jsi-inl.h +6 -0
  137. package/Microsoft.ReactNative.Cxx/JSI/jsi.cpp +241 -4
  138. package/Microsoft.ReactNative.Cxx/JSI/jsi.h +207 -19
  139. package/Microsoft.ReactNative.Cxx/JSValue.cpp +19 -3
  140. package/Microsoft.ReactNative.Cxx/JSValue.h +15 -7
  141. package/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems +2 -2
  142. package/Microsoft.ReactNative.Cxx/NativeModules.h +60 -2
  143. package/Microsoft.ReactNative.Cxx/NodeApiJsiRuntime.cpp +1267 -614
  144. package/Microsoft.ReactNative.Cxx/NodeApiJsiRuntime.h +4 -2
  145. package/Microsoft.ReactNative.Cxx/ReactContext.h +7 -0
  146. package/Microsoft.ReactNative.Cxx/TurboModuleProvider.cpp +11 -13
  147. package/Microsoft.ReactNative.Cxx/TurboModuleProvider.h +2 -3
  148. package/Microsoft.ReactNative.Cxx/node-api/js_native_api.h +81 -20
  149. package/Microsoft.ReactNative.Cxx/node-api/js_native_api_types.h +47 -2
  150. package/Microsoft.ReactNative.Cxx/node-api/js_runtime_api.h +13 -0
  151. package/Microsoft.ReactNative.Cxx/stubs/glog/logging.h +1 -1
  152. package/Microsoft.ReactNative.Managed/ReactContext.cs +3 -1
  153. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  154. package/PropertySheets/JSEngine.props +1 -1
  155. package/PropertySheets/React.Cpp.props +2 -1
  156. package/PropertySheets/WebView2.props +1 -1
  157. package/PropertySheets/WinUI.props +2 -2
  158. package/ReactCommon/TEMP_UntilReactCommonUpdate/jserrorhandler/JsErrorHandler.cpp +429 -0
  159. package/ReactCommon/cgmanifest.json +1 -1
  160. package/Shared/HermesRuntimeHolder.cpp +6 -0
  161. package/Shared/JSI/ChakraRuntime.cpp +4 -0
  162. package/Shared/JSI/ChakraRuntime.h +2 -0
  163. package/Shared/Modules/BlobModule.cpp +14 -16
  164. package/Shared/Modules/BlobModule.h +3 -1
  165. package/Shared/Shared.vcxitems +11 -7
  166. package/Shared/Shared.vcxitems.filters +6 -1
  167. package/Shared/TurboModuleManager.cpp +0 -15
  168. package/codegen/react/components/rnwcore/ActivityIndicatorView.g.h +6 -6
  169. package/codegen/react/components/rnwcore/AndroidDrawerLayout.g.h +6 -6
  170. package/codegen/react/components/rnwcore/AndroidHorizontalScrollContentView.g.h +6 -6
  171. package/codegen/react/components/rnwcore/AndroidProgressBar.g.h +6 -6
  172. package/codegen/react/components/rnwcore/AndroidSwipeRefreshLayout.g.h +6 -6
  173. package/codegen/react/components/rnwcore/AndroidSwitch.g.h +6 -6
  174. package/codegen/react/components/rnwcore/DebuggingOverlay.g.h +6 -6
  175. package/codegen/react/components/rnwcore/InputAccessory.g.h +6 -6
  176. package/codegen/react/components/rnwcore/ModalHostView.g.h +11 -7
  177. package/codegen/react/components/rnwcore/Props.cpp +2 -1
  178. package/codegen/react/components/rnwcore/Props.h +1 -0
  179. package/codegen/react/components/rnwcore/PullToRefreshView.g.h +6 -6
  180. package/codegen/react/components/rnwcore/SafeAreaView.g.h +6 -6
  181. package/codegen/react/components/rnwcore/Switch.g.h +6 -6
  182. package/codegen/react/components/rnwcore/UnimplementedNativeView.g.h +6 -6
  183. package/index.windows.js +4 -2
  184. package/package.json +3 -4
  185. package/src/private/specs/components/RCTModalHostViewNativeComponent.js +8 -0
  186. package/stubs/glog/logging.h +1 -1
  187. package/Microsoft.ReactNative/JSDispatcherWriter.h +0 -47
  188. package/Microsoft.ReactNative/SynchronousEventBeat.cpp +0 -51
  189. package/Microsoft.ReactNative/SynchronousEventBeat.h +0 -31
@@ -12,13 +12,10 @@ namespace facebook::react {
12
12
 
13
13
  struct Color {
14
14
  bool operator==(const Color &otherColor) const {
15
- return m_isUndefined && otherColor.m_isUndefined ||
16
- (m_isUndefined == otherColor.m_isUndefined && m_color == otherColor.m_color &&
17
- m_platformColor == otherColor.m_platformColor);
15
+ return m_color == otherColor.m_color && m_platformColor == otherColor.m_platformColor;
18
16
  }
19
17
  bool operator!=(const Color &otherColor) const {
20
- return m_isUndefined != otherColor.m_isUndefined || m_color != otherColor.m_color ||
21
- m_platformColor != otherColor.m_platformColor;
18
+ return m_color != otherColor.m_color || m_platformColor != otherColor.m_platformColor;
22
19
  }
23
20
 
24
21
  winrt::Windows::UI::Color AsWindowsColor() const {
@@ -36,13 +33,14 @@ struct Color {
36
33
  return RGB(m_color.R, m_color.G, m_color.B) | (m_color.A << 24);
37
34
  }
38
35
 
39
- bool m_isUndefined;
40
36
  winrt::Windows::UI::Color m_color;
41
37
  std::vector<std::string> m_platformColor;
42
38
  };
43
39
 
44
40
  namespace HostPlatformColor {
45
- static const facebook::react::Color UndefinedColor{true};
41
+ static const facebook::react::Color UndefinedColor{
42
+ {0, 0, 0, 0} /*Black*/,
43
+ {"__undefinedColor"} /*Empty PlatformColors*/};
46
44
  } // namespace HostPlatformColor
47
45
 
48
46
  inline Color hostPlatformColorFromComponents(ColorComponents components) {
@@ -53,7 +51,6 @@ inline Color hostPlatformColorFromComponents(ColorComponents components) {
53
51
  static_cast<uint8_t>((int)round(components.green * ratio) & 0xff),
54
52
  static_cast<uint8_t>((int)round(components.blue * ratio) & 0xff)};
55
53
  return {
56
- /* .m_isUndefined = */ false,
57
54
  /* .m_color = */ color,
58
55
  /* .m_platformColor = */ {}};
59
56
  }
@@ -15,11 +15,10 @@ namespace facebook::react {
15
15
 
16
16
  inline SharedColor
17
17
  parsePlatformColor(const ContextContainer &contextContainer, int32_t surfaceId, const RawValue &value) {
18
- if (value.hasType<std::unordered_map<std::string, std::string>>()) {
18
+ if (value.hasType<std::unordered_map<std::string, std::vector<std::string>>>()) {
19
19
  auto map = (std::unordered_map<std::string, std::vector<std::string>>)value;
20
20
  if (map.find("windowsbrush") != map.end()) {
21
21
  facebook::react::Color color = {
22
- /* .m_isDefined = */ true,
23
22
  /* .m_color = */ {},
24
23
  /* .m_platformColor = */ std::move(map["windowsbrush"]),
25
24
  };
@@ -14,13 +14,64 @@
14
14
 
15
15
  #include <unicode.h>
16
16
 
17
+ constexpr float cDefaultMaxFontSizeMultiplier = 0.0f;
18
+
17
19
  namespace facebook::react {
18
20
 
21
+ // Creates an empty InlineObject since RN handles actually rendering the Inline object, this just reserves space for it.
22
+ class AttachmentInlineObject : public winrt::implements<AttachmentInlineObject, IDWriteInlineObject> {
23
+ public:
24
+ AttachmentInlineObject(float width, float height) : m_width(width), m_height(height) {}
25
+
26
+ // IDWriteInlineObject methods
27
+ STDMETHOD(Draw)
28
+ (_In_opt_ void *clientDrawingContext,
29
+ _In_ IDWriteTextRenderer *renderer,
30
+ FLOAT originX,
31
+ FLOAT originY,
32
+ BOOL isSideways,
33
+ BOOL isRightToLeft,
34
+ _In_opt_ IUnknown *clientDrawingEffect) override {
35
+ // We don't need to draw anything here since the actual rendering is handled by React Native
36
+ return S_OK;
37
+ }
38
+
39
+ STDMETHOD(GetMetrics)(_Out_ DWRITE_INLINE_OBJECT_METRICS *metrics) override {
40
+ metrics->width = m_width;
41
+ metrics->height = m_height;
42
+ metrics->baseline =
43
+ m_height; // If the baseline is at the bottom, then baseline = height
44
+ // (https://learn.microsoft.com/en-us/windows/win32/api/dwrite/ns-dwrite-dwrite_inline_object_metrics)
45
+ metrics->supportsSideways = true;
46
+ return S_OK;
47
+ }
48
+
49
+ STDMETHOD(GetOverhangMetrics)(_Out_ DWRITE_OVERHANG_METRICS *overhangs) override {
50
+ overhangs->left = 0;
51
+ overhangs->top = 0;
52
+ overhangs->right = 0;
53
+ overhangs->bottom = 0;
54
+ return S_OK;
55
+ }
56
+
57
+ STDMETHOD(GetBreakConditions)
58
+ (_Out_ DWRITE_BREAK_CONDITION *breakConditionBefore, _Out_ DWRITE_BREAK_CONDITION *breakConditionAfter) override {
59
+ *breakConditionBefore = DWRITE_BREAK_CONDITION_NEUTRAL;
60
+ *breakConditionAfter = DWRITE_BREAK_CONDITION_NEUTRAL;
61
+ return S_OK;
62
+ }
63
+
64
+ private:
65
+ float m_width;
66
+ float m_height;
67
+ };
68
+
19
69
  void TextLayoutManager::GetTextLayout(
20
70
  const AttributedStringBox &attributedStringBox,
21
71
  const ParagraphAttributes &paragraphAttributes,
22
72
  Size size,
23
- winrt::com_ptr<IDWriteTextLayout> &spTextLayout) noexcept {
73
+ winrt::com_ptr<IDWriteTextLayout> &spTextLayout,
74
+ TextMeasurement::Attachments &attachments) noexcept {
24
75
  const auto &attributedString = attributedStringBox.getValue();
25
76
  auto fragments = attributedString.getFragments();
26
77
  auto outerFragment = fragments[0];
@@ -32,6 +83,20 @@ void TextLayoutManager::GetTextLayout(
32
83
  style = DWRITE_FONT_STYLE_OBLIQUE;
33
84
 
34
85
  winrt::com_ptr<IDWriteTextFormat> spTextFormat;
86
+
87
+ float fontSizeText = outerFragment.textAttributes.fontSize;
88
+ if (outerFragment.textAttributes.allowFontScaling.value_or(true) &&
89
+ !std::isnan(outerFragment.textAttributes.fontSizeMultiplier)) {
90
+ float maxFontSizeMultiplierText = cDefaultMaxFontSizeMultiplier;
91
+ maxFontSizeMultiplierText =
92
+ (!std::isnan(outerFragment.textAttributes.maxFontSizeMultiplier)
93
+ ? outerFragment.textAttributes.maxFontSizeMultiplier
94
+ : cDefaultMaxFontSizeMultiplier);
95
+ fontSizeText *= (maxFontSizeMultiplierText >= 1.0f)
96
+ ? std::min(maxFontSizeMultiplierText, outerFragment.textAttributes.fontSizeMultiplier)
97
+ : outerFragment.textAttributes.fontSizeMultiplier;
98
+ }
99
+
35
100
  winrt::check_hresult(Microsoft::ReactNative::DWriteFactory()->CreateTextFormat(
36
101
  outerFragment.textAttributes.fontFamily.empty()
37
102
  ? L"Segoe UI"
@@ -41,10 +106,7 @@ void TextLayoutManager::GetTextLayout(
41
106
  static_cast<facebook::react::FontWeight>(DWRITE_FONT_WEIGHT_REGULAR))),
42
107
  style,
43
108
  DWRITE_FONT_STRETCH_NORMAL,
44
- (outerFragment.textAttributes.allowFontScaling.value_or(true) &&
45
- !std::isnan(outerFragment.textAttributes.fontSizeMultiplier))
46
- ? (outerFragment.textAttributes.fontSizeMultiplier * outerFragment.textAttributes.fontSize)
47
- : outerFragment.textAttributes.fontSize,
109
+ fontSizeText,
48
110
  L"",
49
111
  spTextFormat.put()));
50
112
 
@@ -62,6 +124,7 @@ void TextLayoutManager::GetTextLayout(
62
124
  outerFragment.textAttributes.lineHeight * 0.8f));
63
125
  }
64
126
 
127
+ // Set text alignment
65
128
  DWRITE_TEXT_ALIGNMENT alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
66
129
  if (outerFragment.textAttributes.alignment) {
67
130
  switch (*outerFragment.textAttributes.alignment) {
@@ -87,6 +150,7 @@ void TextLayoutManager::GetTextLayout(
87
150
  }
88
151
  winrt::check_hresult(spTextFormat->SetTextAlignment(alignment));
89
152
 
153
+ // Get text with Object Replacement Characters for attachments
90
154
  auto str = GetTransformedText(attributedStringBox);
91
155
 
92
156
  winrt::check_hresult(Microsoft::ReactNative::DWriteFactory()->CreateTextLayout(
@@ -98,39 +162,82 @@ void TextLayoutManager::GetTextLayout(
98
162
  spTextLayout.put() // The IDWriteTextLayout interface pointer.
99
163
  ));
100
164
 
165
+ // Calculate positions for attachments and set inline objects
101
166
  unsigned int position = 0;
102
- unsigned int length = 0;
103
167
  for (const auto &fragment : fragments) {
104
- length = static_cast<UINT32>(fragment.string.length());
105
- DWRITE_TEXT_RANGE range = {position, length};
106
- TextAttributes attributes = fragment.textAttributes;
107
- DWRITE_FONT_STYLE fragmentStyle = DWRITE_FONT_STYLE_NORMAL;
108
- if (attributes.fontStyle == facebook::react::FontStyle::Italic)
109
- fragmentStyle = DWRITE_FONT_STYLE_ITALIC;
110
- else if (attributes.fontStyle == facebook::react::FontStyle::Oblique)
111
- fragmentStyle = DWRITE_FONT_STYLE_OBLIQUE;
112
-
113
- winrt::check_hresult(spTextLayout->SetFontFamilyName(
114
- attributes.fontFamily.empty() ? L"Segoe UI"
115
- : Microsoft::Common::Unicode::Utf8ToUtf16(attributes.fontFamily).c_str(),
116
- range));
117
- winrt::check_hresult(spTextLayout->SetFontWeight(
118
- static_cast<DWRITE_FONT_WEIGHT>(
119
- attributes.fontWeight.value_or(static_cast<facebook::react::FontWeight>(DWRITE_FONT_WEIGHT_REGULAR))),
120
- range));
121
- winrt::check_hresult(spTextLayout->SetFontStyle(fragmentStyle, range));
122
- winrt::check_hresult(spTextLayout->SetFontSize(
123
- (attributes.allowFontScaling.value_or(true) && !std::isnan(attributes.fontSizeMultiplier))
124
- ? (attributes.fontSizeMultiplier * attributes.fontSize)
125
- : attributes.fontSize,
126
- range));
127
-
128
- if (!isnan(attributes.letterSpacing)) {
129
- winrt::check_hresult(
130
- spTextLayout.as<IDWriteTextLayout1>()->SetCharacterSpacing(0, attributes.letterSpacing, 0, range));
131
- }
168
+ if (fragment.isAttachment()) {
169
+ float width = fragment.parentShadowView.layoutMetrics.frame.size.width;
170
+ float height = fragment.parentShadowView.layoutMetrics.frame.size.height;
171
+
172
+ // Get current height to check if attachment needs to be clipped
173
+ DWRITE_TEXT_METRICS dtm{};
174
+ winrt::check_hresult(spTextLayout->GetMetrics(&dtm));
175
+
176
+ // Check if the attachment should be clipped
177
+ // TODO #14443: clipping works on the first-levels view, but any nested view won't be clipped
178
+ bool isClipped = height > dtm.height;
179
+ if (isClipped) {
180
+ height = dtm.height;
181
+ }
182
+
183
+ // Create an inline object (this just reserves space in RichEdit for ReactNative to render the actual attachment)
184
+ auto inlineObject = winrt::make<AttachmentInlineObject>(width, height);
185
+ winrt::check_hresult(spTextLayout->SetInlineObject(inlineObject.get(), {position, 1}));
186
+
187
+ // Get the position of the Object Replacement Character
188
+ DWRITE_HIT_TEST_METRICS hitTestMetrics;
189
+ float x, y;
190
+ winrt::check_hresult(spTextLayout->HitTestTextPosition(position, false, &x, &y, &hitTestMetrics));
191
+
192
+ // Store the attachment position for RN to render later
193
+ TextMeasurement::Attachment attachment;
194
+ attachment.frame = {
195
+ x, // left
196
+ y, // top
197
+ width, // width
198
+ height // height
199
+ };
200
+ attachment.isClipped = isClipped;
201
+ attachments.push_back(attachment);
202
+ position += 1;
203
+ } else {
204
+ unsigned int length = static_cast<UINT32>(fragment.string.length());
205
+ DWRITE_TEXT_RANGE range = {position, length};
206
+ TextAttributes attributes = fragment.textAttributes;
207
+ DWRITE_FONT_STYLE fragmentStyle = DWRITE_FONT_STYLE_NORMAL;
208
+ if (attributes.fontStyle == facebook::react::FontStyle::Italic)
209
+ fragmentStyle = DWRITE_FONT_STYLE_ITALIC;
210
+ else if (attributes.fontStyle == facebook::react::FontStyle::Oblique)
211
+ fragmentStyle = DWRITE_FONT_STYLE_OBLIQUE;
212
+
213
+ winrt::check_hresult(spTextLayout->SetFontFamilyName(
214
+ attributes.fontFamily.empty() ? L"Segoe UI"
215
+ : Microsoft::Common::Unicode::Utf8ToUtf16(attributes.fontFamily).c_str(),
216
+ range));
217
+ winrt::check_hresult(spTextLayout->SetFontWeight(
218
+ static_cast<DWRITE_FONT_WEIGHT>(
219
+ attributes.fontWeight.value_or(static_cast<facebook::react::FontWeight>(DWRITE_FONT_WEIGHT_REGULAR))),
220
+ range));
221
+ winrt::check_hresult(spTextLayout->SetFontStyle(fragmentStyle, range));
222
+
223
+ float maxFontSizeMultiplier = cDefaultMaxFontSizeMultiplier;
224
+ maxFontSizeMultiplier =
225
+ (!std::isnan(attributes.maxFontSizeMultiplier) ? attributes.maxFontSizeMultiplier
226
+ : cDefaultMaxFontSizeMultiplier);
227
+ float fontSize = attributes.fontSize;
228
+ if (attributes.allowFontScaling.value_or(true) && (!std::isnan(attributes.fontSizeMultiplier))) {
229
+ fontSize *= (maxFontSizeMultiplier >= 1.0f) ? std::min(maxFontSizeMultiplier, attributes.fontSizeMultiplier)
230
+ : attributes.fontSizeMultiplier;
231
+ }
132
232
 
133
- position += length;
233
+ winrt::check_hresult(spTextLayout->SetFontSize(fontSize, range));
234
+
235
+ if (!isnan(attributes.letterSpacing)) {
236
+ winrt::check_hresult(
237
+ spTextLayout.as<IDWriteTextLayout1>()->SetCharacterSpacing(0, attributes.letterSpacing, 0, range));
238
+ }
239
+ position += length;
240
+ }
134
241
  }
135
242
  }
136
243
 
@@ -142,9 +249,86 @@ void TextLayoutManager::GetTextLayout(
142
249
  if (attributedStringBox.getValue().isEmpty())
143
250
  return;
144
251
 
145
- GetTextLayout(attributedStringBox, paragraphAttributes, layoutConstraints.maximumSize, spTextLayout);
252
+ TextMeasurement::Attachments attachments;
253
+ if (paragraphAttributes.adjustsFontSizeToFit) {
254
+ auto minimumFontScale = 0.01f;
255
+ // Uncomment below part when minimumFontScale is available in ParagraphAttributes
256
+ // if (paragraphAttributes.minimumFontScale && paragraphAttributes.minimumFontScale >= 0.01f &&
257
+ // paragraphAttributes.minimumFontScale <= 1.0f) {
258
+ // minimumFontScale = paragraphAttributes.minimumFontScale;
259
+ //}
260
+ GetTextLayoutByAdjustingFontSizeToFit(
261
+ attributedStringBox, paragraphAttributes, layoutConstraints, spTextLayout, attachments, minimumFontScale);
262
+ } else {
263
+ GetTextLayout(attributedStringBox, paragraphAttributes, layoutConstraints.maximumSize, spTextLayout, attachments);
264
+ }
265
+ }
266
+
267
+ void TextLayoutManager::GetTextLayoutByAdjustingFontSizeToFit(
268
+ AttributedStringBox attributedStringBox,
269
+ const ParagraphAttributes &paragraphAttributes,
270
+ LayoutConstraints layoutConstraints,
271
+ winrt::com_ptr<IDWriteTextLayout> &spTextLayout,
272
+ TextMeasurement::Attachments &attachments,
273
+ float minimumFontScale) noexcept {
274
+ /* This function constructs a text layout from the given parameters.
275
+ If the generated text layout doesn't fit within the given layout constraints,
276
+ it will reduce the font size and construct a new text layout. This process will
277
+ be repeated until the text layout meets the constraints.*/
278
+
279
+ DWRITE_TEXT_METRICS metrics;
280
+
281
+ // Better Approach should be implemented, this uses O(n)
282
+ constexpr auto fontReduceFactor = 1.0f;
283
+ auto attributedStringToResize = attributedStringBox.getValue();
284
+ auto fragmentsCopyToResize = attributedStringToResize.getFragments();
285
+ if (fragmentsCopyToResize.empty()) {
286
+ return; // No fragments to process
287
+ }
288
+
289
+ float initialFontSize = fragmentsCopyToResize[0].textAttributes.fontSize;
290
+ float currentFontSize = initialFontSize;
291
+
292
+ // Calculate the minimum font size as per Android/IOS
293
+ float minimumFontSize = std::max(minimumFontScale * initialFontSize, 4.0f);
294
+
295
+ // Initial measurement
296
+ GetTextLayout(attributedStringBox, paragraphAttributes, layoutConstraints.maximumSize, spTextLayout, attachments);
297
+ if (spTextLayout) {
298
+ winrt::check_hresult(spTextLayout->GetMetrics(&metrics));
299
+ } else {
300
+ return;
301
+ }
302
+
303
+ // Loop until the font size is reduced to the minimum or the layout fits
304
+ while ((currentFontSize > minimumFontSize) &&
305
+ ((paragraphAttributes.maximumNumberOfLines != 0 &&
306
+ paragraphAttributes.maximumNumberOfLines < static_cast<int>(metrics.lineCount)) ||
307
+ metrics.height > metrics.layoutHeight || metrics.width > metrics.layoutWidth)) {
308
+ // Reduce the font size by 1 point (or a configurable factor)
309
+ currentFontSize = std::max(currentFontSize - fontReduceFactor, minimumFontSize);
310
+
311
+ // Adjust font size for all fragments proportionally
312
+ attributedStringToResize.getFragments().clear();
313
+ for (auto fragment : fragmentsCopyToResize) {
314
+ fragment.textAttributes.fontSize =
315
+ std::max(fragment.textAttributes.fontSize * (currentFontSize / initialFontSize), minimumFontSize);
316
+ attributedStringToResize.appendFragment(std::move(fragment));
317
+ }
318
+
319
+ attributedStringBox = facebook::react::AttributedStringBox(attributedStringToResize);
320
+
321
+ // Re-measure the text layout
322
+ GetTextLayout(attributedStringBox, paragraphAttributes, layoutConstraints.maximumSize, spTextLayout, attachments);
323
+ if (spTextLayout) {
324
+ winrt::check_hresult(spTextLayout->GetMetrics(&metrics));
325
+ } else {
326
+ return;
327
+ }
328
+ }
146
329
  }
147
330
 
331
+ // measure entire text (inluding attachments)
148
332
  TextMeasurement TextLayoutManager::measure(
149
333
  const AttributedStringBox &attributedStringBox,
150
334
  const ParagraphAttributes &paragraphAttributes,
@@ -152,6 +336,7 @@ TextMeasurement TextLayoutManager::measure(
152
336
  LayoutConstraints layoutConstraints) const {
153
337
  TextMeasurement measurement{};
154
338
  auto &attributedString = attributedStringBox.getValue();
339
+
155
340
  measurement = m_measureCache.get(
156
341
  {attributedString, paragraphAttributes, layoutConstraints}, [&](TextMeasureCacheKey const &key) {
157
342
  auto telemetry = TransactionTelemetry::threadLocalTelemetry();
@@ -161,7 +346,9 @@ TextMeasurement TextLayoutManager::measure(
161
346
 
162
347
  winrt::com_ptr<IDWriteTextLayout> spTextLayout;
163
348
 
164
- GetTextLayout(attributedStringBox, paragraphAttributes, layoutConstraints, spTextLayout);
349
+ TextMeasurement::Attachments attachments;
350
+ GetTextLayout(
351
+ attributedStringBox, paragraphAttributes, layoutConstraints.maximumSize, spTextLayout, attachments);
165
352
 
166
353
  if (spTextLayout) {
167
354
  auto maxHeight = std::numeric_limits<float>().max();
@@ -182,6 +369,7 @@ TextMeasurement TextLayoutManager::measure(
182
369
  DWRITE_TEXT_METRICS dtm{};
183
370
  winrt::check_hresult(spTextLayout->GetMetrics(&dtm));
184
371
  measurement.size = {dtm.width, std::min(dtm.height, maxHeight)};
372
+ measurement.attachments = attachments;
185
373
  }
186
374
 
187
375
  if (telemetry) {
@@ -190,7 +378,6 @@ TextMeasurement TextLayoutManager::measure(
190
378
 
191
379
  return measurement;
192
380
  });
193
-
194
381
  return measurement;
195
382
  }
196
383
 
@@ -232,8 +419,8 @@ LinesMeasurements TextLayoutManager::measureLines(
232
419
  LinesMeasurements lineMeasurements{};
233
420
 
234
421
  winrt::com_ptr<IDWriteTextLayout> spTextLayout;
235
-
236
- GetTextLayout(attributedStringBox, paragraphAttributes, size, spTextLayout);
422
+ TextMeasurement::Attachments attachments;
423
+ GetTextLayout(attributedStringBox, paragraphAttributes, size, spTextLayout, attachments);
237
424
 
238
425
  if (spTextLayout) {
239
426
  std::vector<DWRITE_LINE_METRICS> lineMetrics;
@@ -313,17 +500,32 @@ Float TextLayoutManager::baseline(
313
500
  AttributedStringBox attributedStringBox,
314
501
  ParagraphAttributes paragraphAttributes,
315
502
  Size size) const {
316
- return 0;
503
+ winrt::com_ptr<IDWriteTextLayout> spTextLayout;
504
+ TextMeasurement::Attachments attachments;
505
+ GetTextLayout(attributedStringBox, paragraphAttributes, size, spTextLayout, attachments);
506
+ if (!spTextLayout) {
507
+ return 0;
508
+ }
509
+
510
+ DWRITE_TEXT_METRICS metrics;
511
+ winrt::check_hresult(spTextLayout->GetMetrics(&metrics));
512
+ return metrics.height *
513
+ 0.8f; // https://learn.microsoft.com/en-us/windows/win32/api/dwrite/nf-dwrite-idwritetextformat-getlinespacing
317
514
  }
318
515
 
319
516
  winrt::hstring TextLayoutManager::GetTransformedText(const AttributedStringBox &attributedStringBox) {
320
517
  winrt::hstring result{};
321
518
  const auto &attributedString = attributedStringBox.getValue();
519
+
322
520
  for (const auto &fragment : attributedString.getFragments()) {
323
- result = result +
324
- Microsoft::ReactNative::TransformableText::TransformText(
325
- winrt::hstring{Microsoft::Common::Unicode::Utf8ToUtf16(fragment.string)},
326
- ConvertTextTransform(fragment.textAttributes.textTransform));
521
+ if (fragment.isAttachment()) {
522
+ result = result + L"\uFFFC"; // Unicode Object Replacement Character, will be replaced with an inline object
523
+ } else {
524
+ result = result +
525
+ Microsoft::ReactNative::TransformableText::TransformText(
526
+ winrt::hstring{Microsoft::Common::Unicode::Utf8ToUtf16(fragment.string)},
527
+ ConvertTextTransform(fragment.textAttributes.textTransform));
528
+ }
327
529
  }
328
530
  return result;
329
531
  }
@@ -75,12 +75,27 @@ class TextLayoutManager {
75
75
  */
76
76
  void *getNativeTextLayoutManager() const;
77
77
 
78
+ static void GetTextLayout(
79
+ const AttributedStringBox &attributedStringBox,
80
+ const ParagraphAttributes &paragraphAttributes,
81
+ Size size,
82
+ winrt::com_ptr<IDWriteTextLayout> &spTextLayout,
83
+ TextMeasurement::Attachments &attachments) noexcept;
84
+
78
85
  static void GetTextLayout(
79
86
  const AttributedStringBox &attributedStringBox,
80
87
  const ParagraphAttributes &paragraphAttributes,
81
88
  LayoutConstraints layoutConstraints,
82
89
  winrt::com_ptr<IDWriteTextLayout> &spTextLayout) noexcept;
83
90
 
91
+ static void GetTextLayoutByAdjustingFontSizeToFit(
92
+ AttributedStringBox attributedStringBox,
93
+ const ParagraphAttributes &paragraphAttributes,
94
+ LayoutConstraints layoutConstraints,
95
+ winrt::com_ptr<IDWriteTextLayout> &spTextLayout,
96
+ TextMeasurement::Attachments &attachments,
97
+ float minimumFontScale) noexcept;
98
+
84
99
  #pragma endregion
85
100
 
86
101
  private:
@@ -0,0 +1,39 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ // [Windows] Brought forward from react-native - switch to using react-native/ReactCxxPlatform/react/threading version
9
+ // once we integrate that far
10
+
11
+ #include "MessageQueueThreadImpl.h"
12
+
13
+ #include <functional>
14
+
15
+ namespace facebook::react {
16
+
17
+ void MessageQueueThreadImpl::runOnQueue(std::function<void()> &&runnable) {
18
+ if (!taskDispatchThread_.isRunning()) {
19
+ return;
20
+ }
21
+ taskDispatchThread_.runAsync([runnable = std::move(runnable)]() noexcept { runnable(); });
22
+ }
23
+
24
+ void MessageQueueThreadImpl::runOnQueueSync(std::function<void()> &&runnable) {
25
+ if (!taskDispatchThread_.isRunning()) {
26
+ return;
27
+ }
28
+ if (taskDispatchThread_.isOnThread()) {
29
+ runnable();
30
+ } else {
31
+ taskDispatchThread_.runSync([runnable = std::move(runnable)]() noexcept { runnable(); });
32
+ }
33
+ }
34
+
35
+ void MessageQueueThreadImpl::quitSynchronous() {
36
+ taskDispatchThread_.quit();
37
+ }
38
+
39
+ } // namespace facebook::react
@@ -0,0 +1,54 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ // [Windows] Brought forward from react-native - switch to using react-native/ReactCxxPlatform/react/threading version
9
+ // once we integrate that far
10
+
11
+ #pragma once
12
+
13
+ #include <cxxreact/MessageQueueThread.h>
14
+ #include <react/threading/TaskDispatchThread.h>
15
+ #include <memory>
16
+
17
+ namespace facebook::react {
18
+
19
+ using MessageQueueThreadFactory = std::function<std::shared_ptr<MessageQueueThread>()>;
20
+
21
+ constexpr char MessageQueueThreadFactoryKey[] = "MessageQueueThreadFactoryKey";
22
+
23
+ /**
24
+ * MessageQueueThread implementation that uses a TaskDispatchThread for
25
+ * queueing and threading logic
26
+ */
27
+ class MessageQueueThreadImpl : public MessageQueueThread {
28
+ public:
29
+ MessageQueueThreadImpl() noexcept = default;
30
+ explicit MessageQueueThreadImpl(int priorityOffset) noexcept : taskDispatchThread_("MessageQueue", priorityOffset) {}
31
+
32
+ ~MessageQueueThreadImpl() noexcept override = default;
33
+
34
+ /** Add a job to the queue asynchronously */
35
+ void runOnQueue(std::function<void()> &&runnable) override;
36
+
37
+ /**
38
+ * Add a job to the queue synchronously - call won't return until runnable
39
+ * has completed. Will run immediately if called from the looper thread.
40
+ * Should only be used for initialization.
41
+ */
42
+ void runOnQueueSync(std::function<void()> &&runnable) override;
43
+
44
+ /**
45
+ * Stop the message queue thread. Should only be used for cleanup - once it
46
+ * returns, no further work should run on the queue.
47
+ */
48
+ void quitSynchronous() override;
49
+
50
+ private:
51
+ TaskDispatchThread taskDispatchThread_{"MessageQueue"};
52
+ };
53
+
54
+ } // namespace facebook::react