react-native-windows 0.0.0-canary.487 → 0.0.0-canary.490
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.
- package/Chakra/ChakraHelpers.cpp +0 -1
- package/Libraries/Components/Button.windows.js +1 -0
- package/Libraries/Pressability/Pressability.windows.js +13 -2
- package/Libraries/StyleSheet/processTransform.windows.js +272 -0
- package/Microsoft.ReactNative/DynamicReader.cpp +3 -3
- package/Microsoft.ReactNative/Fabric/DWriteHelpers.cpp +19 -0
- package/Microsoft.ReactNative/Fabric/DWriteHelpers.h +13 -0
- package/Microsoft.ReactNative/Fabric/ParagraphComponentView.cpp +36 -10
- package/Microsoft.ReactNative/Fabric/SliderComponentView.h +1 -1
- package/Microsoft.ReactNative/Fabric/SwitchComponentView.h +1 -1
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.cpp +107 -57
- package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.h +8 -2
- package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +1 -0
- package/Microsoft.ReactNative/Modules/CreateModules.cpp +3 -3
- package/Microsoft.ReactNative/ReactHost/ReactNativeHeaders.h +1 -1
- package/Microsoft.ReactNative/Views/ControlViewManager.cpp +32 -0
- package/Microsoft.ReactNative/Views/ControlViewManager.h +11 -0
- package/Microsoft.ReactNative/Views/DevMenu.cpp +2 -2
- package/Microsoft.ReactNative/Views/FrameworkElementViewManager.cpp +149 -22
- package/Microsoft.ReactNative/Views/Image/Microsoft.UI.Composition.Effects_Impl.h +5 -11
- package/Microsoft.ReactNative/Views/Image/ReactImage.cpp +2 -1
- package/Microsoft.ReactNative/Views/ViewViewManager.cpp +21 -0
- package/Microsoft.ReactNative.Cxx/DesktopWindowBridge.h +1 -1
- package/Microsoft.ReactNative.Cxx/JSI/JsiAbiApi.cpp +1 -1
- package/Microsoft.ReactNative.Cxx/JSI/NodeApiJsiRuntime.cpp +1 -1
- package/Microsoft.ReactNative.Cxx/JSValueReader.h +2 -2
- package/Microsoft.ReactNative.Cxx/JSValueWriter.h +5 -5
- package/Microsoft.ReactNative.Cxx/NativeModules.h +1 -1
- package/Microsoft.ReactNative.Cxx/ReactContext.h +3 -3
- package/Microsoft.ReactNative.Cxx/ReactNonAbiValue.h +3 -3
- package/Microsoft.ReactNative.Managed/packages.lock.json +1 -1
- package/Mso/activeObject/activeObject.h +2 -2
- package/Mso/compilerAdapters/cppMacros.h +3 -5
- package/Mso/errorCode/errorProvider.h +2 -2
- package/Mso/errorCode/maybe.h +4 -4
- package/Mso/functional/functor.h +6 -6
- package/Mso/functional/functorRef.h +2 -2
- package/Mso/future/details/executor.h +2 -2
- package/Mso/future/details/futureFuncInl.h +4 -4
- package/Mso/future/details/ifuture.h +3 -3
- package/Mso/future/details/maybeInvoker.h +6 -6
- package/Mso/future/details/promiseGroupInl.h +4 -4
- package/Mso/future/details/promiseInl.h +4 -4
- package/Mso/future/details/resultTraits.h +4 -4
- package/Mso/future/details/whenAllInl.h +1 -1
- package/Mso/future/future.h +13 -13
- package/Mso/guid/msoGuidDetails.h +1 -1
- package/Mso/memoryApi/memoryApi.h +13 -7
- package/Mso/motifCpp/gTestAdapter.h +1 -1
- package/Mso/motifCpp/testInfo.h +7 -9
- package/Mso/object/make.h +8 -8
- package/Mso/object/objectRefCount.h +3 -5
- package/Mso/object/objectWithWeakRef.h +10 -14
- package/Mso/object/queryCast.h +4 -4
- package/Mso/object/refCountedObject.h +4 -4
- package/Mso/object/unknownObject.h +7 -7
- package/Mso/platformAdapters/windowsFirst.h +1 -1
- package/Mso/smartPtr/cntPtr.h +8 -8
- package/Mso/src/future/futureImpl.h +1 -1
- package/Mso/src/memoryApi/memoryApi.cpp +4 -4
- package/PropertySheets/Generated/PackageVersion.g.props +1 -1
- package/ReactCommon/ReactCommon.vcxproj +0 -3
- package/Scripts/OfficeReact.Win32.nuspec +1 -1
- package/Shared/AbiSafe.h +3 -3
- package/Shared/BaseScriptStoreImpl.cpp +1 -1
- package/Shared/CppRuntimeOptions.h +50 -0
- package/Shared/InspectorPackagerConnection.cpp +7 -5
- package/Shared/InspectorPackagerConnection.h +2 -2
- package/Shared/JSI/ChakraApi.cpp +0 -1
- package/Shared/JSI/ChakraRuntime.cpp +1 -2
- package/Shared/Modules/HttpModule.cpp +1 -1
- package/Shared/Modules/HttpModule.h +2 -2
- package/Shared/Modules/WebSocketModule.cpp +1 -1
- package/Shared/Modules/WebSocketModule.h +8 -5
- package/Shared/{IHttpResource.h → Networking/IHttpResource.h} +4 -4
- package/Shared/{IWebSocketResource.h → Networking/IWebSocketResource.h} +3 -3
- package/Shared/Networking/OriginPolicy.h +15 -0
- package/Shared/Networking/OriginPolicyHttpFilter.cpp +746 -0
- package/Shared/Networking/OriginPolicyHttpFilter.h +112 -0
- package/Shared/{WinRTHttpResource.cpp → Networking/WinRTHttpResource.cpp} +129 -99
- package/Shared/{WinRTHttpResource.h → Networking/WinRTHttpResource.h} +8 -12
- package/Shared/Networking/WinRTTypes.h +30 -0
- package/Shared/{WinRTWebSocketResource.cpp → Networking/WinRTWebSocketResource.cpp} +18 -3
- package/Shared/{WinRTWebSocketResource.h → Networking/WinRTWebSocketResource.h} +3 -3
- package/Shared/OInstance.cpp +1 -1
- package/Shared/RuntimeOptions.cpp +93 -15
- package/Shared/RuntimeOptions.h +22 -9
- package/Shared/Shared.vcxitems +11 -7
- package/Shared/Shared.vcxitems.filters +39 -21
- package/Shared/Threading/BatchingQueueThread.cpp +1 -1
- package/Shared/tracing/fbsystrace.h +2 -2
- package/include/Shared/cdebug.h +9 -9
- package/package.json +4 -4
- package/Shared/cdebug.cpp +0 -6
package/Chakra/ChakraHelpers.cpp
CHANGED
|
@@ -342,6 +342,7 @@ class Button extends React.Component<
|
|
|
342
342
|
if (Platform.OS === 'windows') {
|
|
343
343
|
return (
|
|
344
344
|
<Touchable
|
|
345
|
+
accessible={accessible}
|
|
345
346
|
accessibilityLabel={accessibilityLabel}
|
|
346
347
|
accessibilityHint={accessibilityHint}
|
|
347
348
|
accessibilityLanguage={accessibilityLanguage}
|
|
@@ -721,6 +721,11 @@ export default class Pressability {
|
|
|
721
721
|
}
|
|
722
722
|
}
|
|
723
723
|
|
|
724
|
+
// [Windows]
|
|
725
|
+
_isDefaultPressButton(button) {
|
|
726
|
+
return !button; // Treat 0 or undefined as default press
|
|
727
|
+
}
|
|
728
|
+
|
|
724
729
|
/**
|
|
725
730
|
* Performs a transition between touchable states and identify any activations
|
|
726
731
|
* or deactivations (and callback invocations).
|
|
@@ -771,7 +776,10 @@ export default class Pressability {
|
|
|
771
776
|
}
|
|
772
777
|
const {onLongPress, onPress, android_disableSound} = this._config;
|
|
773
778
|
|
|
774
|
-
if (
|
|
779
|
+
if (
|
|
780
|
+
onPress != null &&
|
|
781
|
+
this._isDefaultPressButton(getTouchFromPressEvent(event).button)
|
|
782
|
+
) {
|
|
775
783
|
const isPressCanceledByLongPress =
|
|
776
784
|
onLongPress != null &&
|
|
777
785
|
prevState === 'RESPONDER_ACTIVE_LONG_PRESS_IN' &&
|
|
@@ -800,7 +808,10 @@ export default class Pressability {
|
|
|
800
808
|
|
|
801
809
|
_deactivate(event: PressEvent): void {
|
|
802
810
|
const {onPressOut} = this._config;
|
|
803
|
-
if (
|
|
811
|
+
if (
|
|
812
|
+
onPressOut != null &&
|
|
813
|
+
this._isDefaultPressButton(getTouchFromPressEvent(event).button)
|
|
814
|
+
) {
|
|
804
815
|
const minPressDuration = normalizeDelay(
|
|
805
816
|
this._config.minPressDuration,
|
|
806
817
|
0,
|
|
@@ -0,0 +1,272 @@
|
|
|
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
|
+
* @format
|
|
8
|
+
* @flow
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
'use strict';
|
|
12
|
+
|
|
13
|
+
const MatrixMath = require('../Utilities/MatrixMath');
|
|
14
|
+
const Platform = require('../Utilities/Platform');
|
|
15
|
+
|
|
16
|
+
const invariant = require('invariant');
|
|
17
|
+
const stringifySafe = require('../Utilities/stringifySafe').default;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Generate a transform matrix based on the provided transforms, and use that
|
|
21
|
+
* within the style object instead.
|
|
22
|
+
*
|
|
23
|
+
* This allows us to provide an API that is similar to CSS, where transforms may
|
|
24
|
+
* be applied in an arbitrary order, and yet have a universal, singular
|
|
25
|
+
* interface to native code.
|
|
26
|
+
*/
|
|
27
|
+
function processTransform(
|
|
28
|
+
transform: Array<Object>,
|
|
29
|
+
): Array<Object> | Array<number> {
|
|
30
|
+
if (__DEV__) {
|
|
31
|
+
_validateTransforms(transform);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Android & iOS implementations of transform property accept the list of
|
|
35
|
+
// transform properties as opposed to a transform Matrix. This is necessary
|
|
36
|
+
// to control transform property updates completely on the native thread.
|
|
37
|
+
if (
|
|
38
|
+
Platform.OS === 'android' ||
|
|
39
|
+
Platform.OS === 'ios' ||
|
|
40
|
+
Platform.OS === 'windows'
|
|
41
|
+
) {
|
|
42
|
+
return transform;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const result = MatrixMath.createIdentityMatrix();
|
|
46
|
+
|
|
47
|
+
transform.forEach(transformation => {
|
|
48
|
+
const key = Object.keys(transformation)[0];
|
|
49
|
+
const value = transformation[key];
|
|
50
|
+
|
|
51
|
+
switch (key) {
|
|
52
|
+
case 'matrix':
|
|
53
|
+
MatrixMath.multiplyInto(result, result, value);
|
|
54
|
+
break;
|
|
55
|
+
case 'perspective':
|
|
56
|
+
_multiplyTransform(result, MatrixMath.reusePerspectiveCommand, [value]);
|
|
57
|
+
break;
|
|
58
|
+
case 'rotateX':
|
|
59
|
+
_multiplyTransform(result, MatrixMath.reuseRotateXCommand, [
|
|
60
|
+
_convertToRadians(value),
|
|
61
|
+
]);
|
|
62
|
+
break;
|
|
63
|
+
case 'rotateY':
|
|
64
|
+
_multiplyTransform(result, MatrixMath.reuseRotateYCommand, [
|
|
65
|
+
_convertToRadians(value),
|
|
66
|
+
]);
|
|
67
|
+
break;
|
|
68
|
+
case 'rotate':
|
|
69
|
+
case 'rotateZ':
|
|
70
|
+
_multiplyTransform(result, MatrixMath.reuseRotateZCommand, [
|
|
71
|
+
_convertToRadians(value),
|
|
72
|
+
]);
|
|
73
|
+
break;
|
|
74
|
+
case 'scale':
|
|
75
|
+
_multiplyTransform(result, MatrixMath.reuseScaleCommand, [value]);
|
|
76
|
+
break;
|
|
77
|
+
case 'scaleX':
|
|
78
|
+
_multiplyTransform(result, MatrixMath.reuseScaleXCommand, [value]);
|
|
79
|
+
break;
|
|
80
|
+
case 'scaleY':
|
|
81
|
+
_multiplyTransform(result, MatrixMath.reuseScaleYCommand, [value]);
|
|
82
|
+
break;
|
|
83
|
+
case 'translate':
|
|
84
|
+
_multiplyTransform(result, MatrixMath.reuseTranslate3dCommand, [
|
|
85
|
+
value[0],
|
|
86
|
+
value[1],
|
|
87
|
+
value[2] || 0,
|
|
88
|
+
]);
|
|
89
|
+
break;
|
|
90
|
+
case 'translateX':
|
|
91
|
+
_multiplyTransform(result, MatrixMath.reuseTranslate2dCommand, [
|
|
92
|
+
value,
|
|
93
|
+
0,
|
|
94
|
+
]);
|
|
95
|
+
break;
|
|
96
|
+
case 'translateY':
|
|
97
|
+
_multiplyTransform(result, MatrixMath.reuseTranslate2dCommand, [
|
|
98
|
+
0,
|
|
99
|
+
value,
|
|
100
|
+
]);
|
|
101
|
+
break;
|
|
102
|
+
case 'skewX':
|
|
103
|
+
_multiplyTransform(result, MatrixMath.reuseSkewXCommand, [
|
|
104
|
+
_convertToRadians(value),
|
|
105
|
+
]);
|
|
106
|
+
break;
|
|
107
|
+
case 'skewY':
|
|
108
|
+
_multiplyTransform(result, MatrixMath.reuseSkewYCommand, [
|
|
109
|
+
_convertToRadians(value),
|
|
110
|
+
]);
|
|
111
|
+
break;
|
|
112
|
+
default:
|
|
113
|
+
throw new Error('Invalid transform name: ' + key);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Performs a destructive operation on a transform matrix.
|
|
122
|
+
*/
|
|
123
|
+
function _multiplyTransform(
|
|
124
|
+
result: Array<number>,
|
|
125
|
+
matrixMathFunction: Function,
|
|
126
|
+
args: Array<number>,
|
|
127
|
+
): void {
|
|
128
|
+
const matrixToApply = MatrixMath.createIdentityMatrix();
|
|
129
|
+
const argsWithIdentity = [matrixToApply].concat(args);
|
|
130
|
+
matrixMathFunction.apply(this, argsWithIdentity);
|
|
131
|
+
MatrixMath.multiplyInto(result, result, matrixToApply);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Parses a string like '0.5rad' or '60deg' into radians expressed in a float.
|
|
136
|
+
* Note that validation on the string is done in `_validateTransform()`.
|
|
137
|
+
*/
|
|
138
|
+
function _convertToRadians(value: string): number {
|
|
139
|
+
const floatValue = parseFloat(value);
|
|
140
|
+
return value.indexOf('rad') > -1 ? floatValue : (floatValue * Math.PI) / 180;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function _validateTransforms(transform: Array<Object>): void {
|
|
144
|
+
transform.forEach(transformation => {
|
|
145
|
+
const keys = Object.keys(transformation);
|
|
146
|
+
invariant(
|
|
147
|
+
keys.length === 1,
|
|
148
|
+
'You must specify exactly one property per transform object. Passed properties: %s',
|
|
149
|
+
stringifySafe(transformation),
|
|
150
|
+
);
|
|
151
|
+
const key = keys[0];
|
|
152
|
+
const value = transformation[key];
|
|
153
|
+
_validateTransform(key, value, transformation);
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function _validateTransform(
|
|
158
|
+
key:
|
|
159
|
+
| string
|
|
160
|
+
| $TEMPORARY$string<'matrix'>
|
|
161
|
+
| $TEMPORARY$string<'perspective'>
|
|
162
|
+
| $TEMPORARY$string<'rotate'>
|
|
163
|
+
| $TEMPORARY$string<'rotateX'>
|
|
164
|
+
| $TEMPORARY$string<'rotateY'>
|
|
165
|
+
| $TEMPORARY$string<'rotateZ'>
|
|
166
|
+
| $TEMPORARY$string<'scale'>
|
|
167
|
+
| $TEMPORARY$string<'scaleX'>
|
|
168
|
+
| $TEMPORARY$string<'scaleY'>
|
|
169
|
+
| $TEMPORARY$string<'skewX'>
|
|
170
|
+
| $TEMPORARY$string<'skewY'>
|
|
171
|
+
| $TEMPORARY$string<'translate'>
|
|
172
|
+
| $TEMPORARY$string<'translateX'>
|
|
173
|
+
| $TEMPORARY$string<'translateY'>,
|
|
174
|
+
value: any | number | string,
|
|
175
|
+
transformation: any,
|
|
176
|
+
) {
|
|
177
|
+
invariant(
|
|
178
|
+
!value.getValue,
|
|
179
|
+
'You passed an Animated.Value to a normal component. ' +
|
|
180
|
+
'You need to wrap that component in an Animated. For example, ' +
|
|
181
|
+
'replace <View /> by <Animated.View />.',
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
const multivalueTransforms = ['matrix', 'translate'];
|
|
185
|
+
if (multivalueTransforms.indexOf(key) !== -1) {
|
|
186
|
+
invariant(
|
|
187
|
+
Array.isArray(value),
|
|
188
|
+
'Transform with key of %s must have an array as the value: %s',
|
|
189
|
+
key,
|
|
190
|
+
stringifySafe(transformation),
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
switch (key) {
|
|
194
|
+
case 'matrix':
|
|
195
|
+
invariant(
|
|
196
|
+
value.length === 9 || value.length === 16,
|
|
197
|
+
'Matrix transform must have a length of 9 (2d) or 16 (3d). ' +
|
|
198
|
+
'Provided matrix has a length of %s: %s',
|
|
199
|
+
/* $FlowFixMe[prop-missing] (>=0.84.0 site=react_native_fb) This
|
|
200
|
+
* comment suppresses an error found when Flow v0.84 was deployed. To
|
|
201
|
+
* see the error, delete this comment and run Flow. */
|
|
202
|
+
value.length,
|
|
203
|
+
stringifySafe(transformation),
|
|
204
|
+
);
|
|
205
|
+
break;
|
|
206
|
+
case 'translate':
|
|
207
|
+
invariant(
|
|
208
|
+
value.length === 2 || value.length === 3,
|
|
209
|
+
'Transform with key translate must be an array of length 2 or 3, found %s: %s',
|
|
210
|
+
/* $FlowFixMe[prop-missing] (>=0.84.0 site=react_native_fb) This
|
|
211
|
+
* comment suppresses an error found when Flow v0.84 was deployed. To
|
|
212
|
+
* see the error, delete this comment and run Flow. */
|
|
213
|
+
value.length,
|
|
214
|
+
stringifySafe(transformation),
|
|
215
|
+
);
|
|
216
|
+
break;
|
|
217
|
+
case 'rotateX':
|
|
218
|
+
case 'rotateY':
|
|
219
|
+
case 'rotateZ':
|
|
220
|
+
case 'rotate':
|
|
221
|
+
case 'skewX':
|
|
222
|
+
case 'skewY':
|
|
223
|
+
invariant(
|
|
224
|
+
typeof value === 'string',
|
|
225
|
+
'Transform with key of "%s" must be a string: %s',
|
|
226
|
+
key,
|
|
227
|
+
stringifySafe(transformation),
|
|
228
|
+
);
|
|
229
|
+
invariant(
|
|
230
|
+
value.indexOf('deg') > -1 || value.indexOf('rad') > -1,
|
|
231
|
+
'Rotate transform must be expressed in degrees (deg) or radians ' +
|
|
232
|
+
'(rad): %s',
|
|
233
|
+
stringifySafe(transformation),
|
|
234
|
+
);
|
|
235
|
+
break;
|
|
236
|
+
case 'perspective':
|
|
237
|
+
invariant(
|
|
238
|
+
typeof value === 'number',
|
|
239
|
+
'Transform with key of "%s" must be a number: %s',
|
|
240
|
+
key,
|
|
241
|
+
stringifySafe(transformation),
|
|
242
|
+
);
|
|
243
|
+
invariant(
|
|
244
|
+
value !== 0,
|
|
245
|
+
'Transform with key of "%s" cannot be zero: %s',
|
|
246
|
+
key,
|
|
247
|
+
stringifySafe(transformation),
|
|
248
|
+
);
|
|
249
|
+
break;
|
|
250
|
+
case 'translateX':
|
|
251
|
+
case 'translateY':
|
|
252
|
+
case 'scale':
|
|
253
|
+
case 'scaleX':
|
|
254
|
+
case 'scaleY':
|
|
255
|
+
invariant(
|
|
256
|
+
typeof value === 'number',
|
|
257
|
+
'Transform with key of "%s" must be a number: %s',
|
|
258
|
+
key,
|
|
259
|
+
stringifySafe(transformation),
|
|
260
|
+
);
|
|
261
|
+
break;
|
|
262
|
+
default:
|
|
263
|
+
invariant(
|
|
264
|
+
false,
|
|
265
|
+
'Invalid transform %s: %s',
|
|
266
|
+
key,
|
|
267
|
+
stringifySafe(transformation),
|
|
268
|
+
);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
module.exports = processTransform;
|
|
@@ -140,9 +140,9 @@ bool DynamicReader::GetBoolean() noexcept {
|
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
int64_t DynamicReader::GetInt64() noexcept {
|
|
143
|
-
return (m_current->type() == folly::dynamic::Type::INT64)
|
|
144
|
-
? m_current->
|
|
145
|
-
|
|
143
|
+
return (m_current->type() == folly::dynamic::Type::INT64) ? m_current->getInt()
|
|
144
|
+
: (m_current->type() == folly::dynamic::Type::DOUBLE) ? static_cast<int64_t>(m_current->getDouble())
|
|
145
|
+
: 0;
|
|
146
146
|
}
|
|
147
147
|
|
|
148
148
|
double DynamicReader::GetDouble() noexcept {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
// Copyright (c) Microsoft Corporation.
|
|
2
|
+
// Licensed under the MIT License.
|
|
3
|
+
|
|
4
|
+
#pragma once
|
|
5
|
+
|
|
6
|
+
#include "DWriteHelpers.h"
|
|
7
|
+
|
|
8
|
+
namespace Microsoft::ReactNative {
|
|
9
|
+
|
|
10
|
+
winrt::com_ptr<::IDWriteFactory> DWriteFactory() noexcept {
|
|
11
|
+
static winrt::com_ptr<::IDWriteFactory> s_dwriteFactory;
|
|
12
|
+
if (!s_dwriteFactory) {
|
|
13
|
+
winrt::check_hresult(::DWriteCreateFactory(
|
|
14
|
+
DWRITE_FACTORY_TYPE_SHARED, __uuidof(s_dwriteFactory), reinterpret_cast<::IUnknown **>(s_dwriteFactory.put())));
|
|
15
|
+
}
|
|
16
|
+
return s_dwriteFactory;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
} // namespace Microsoft::ReactNative
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
|
|
2
|
+
// Copyright (c) Microsoft Corporation.
|
|
3
|
+
// Licensed under the MIT License.
|
|
4
|
+
|
|
5
|
+
#pragma once
|
|
6
|
+
|
|
7
|
+
#include <dwrite.h>
|
|
8
|
+
|
|
9
|
+
namespace Microsoft::ReactNative {
|
|
10
|
+
|
|
11
|
+
winrt::com_ptr<::IDWriteFactory> DWriteFactory() noexcept;
|
|
12
|
+
|
|
13
|
+
} // namespace Microsoft::ReactNative
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
#include "ParagraphComponentView.h"
|
|
8
8
|
|
|
9
9
|
#include <UI.Xaml.Controls.h>
|
|
10
|
+
#include <UI.Xaml.Documents.h>
|
|
10
11
|
#include <Utils/ValueUtils.h>
|
|
11
12
|
#include <dwrite.h>
|
|
12
13
|
#include <react/renderer/components/text/ParagraphShadowNode.h>
|
|
@@ -30,14 +31,12 @@ void ParagraphComponentView::mountChildComponentView(
|
|
|
30
31
|
uint32_t index) noexcept {
|
|
31
32
|
auto v = static_cast<const ParagraphComponentView &>(childComponentView);
|
|
32
33
|
assert(false);
|
|
33
|
-
// m_element.Children().InsertAt(index, v.Element());
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
void ParagraphComponentView::unmountChildComponentView(
|
|
37
37
|
const IComponentView &childComponentView,
|
|
38
38
|
uint32_t index) noexcept {
|
|
39
39
|
assert(false);
|
|
40
|
-
// m_element.Children().RemoveAt(index);
|
|
41
40
|
}
|
|
42
41
|
|
|
43
42
|
void ParagraphComponentView::updateProps(
|
|
@@ -99,11 +98,40 @@ void ParagraphComponentView::updateState(
|
|
|
99
98
|
facebook::react::State::Shared const &oldState) noexcept {
|
|
100
99
|
const auto &newState = *std::static_pointer_cast<facebook::react::ParagraphShadowNode::ConcreteState const>(state);
|
|
101
100
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
101
|
+
m_element.Inlines().Clear();
|
|
102
|
+
|
|
103
|
+
for (const auto &fragment : newState.getData().attributedString.getFragments()) {
|
|
104
|
+
auto inlines = m_element.Inlines();
|
|
105
|
+
|
|
106
|
+
if (auto tdlt = fragment.textAttributes.textDecorationLineType; tdlt &&
|
|
107
|
+
(*tdlt == facebook::react::TextDecorationLineType::Underline ||
|
|
108
|
+
*tdlt == facebook::react::TextDecorationLineType::UnderlineStrikethrough)) {
|
|
109
|
+
auto underline = xaml::Documents::Underline();
|
|
110
|
+
inlines.Append(underline);
|
|
111
|
+
inlines = underline.Inlines();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (fragment.textAttributes.fontStyle == facebook::react::FontStyle::Italic ||
|
|
115
|
+
fragment.textAttributes.fontStyle == facebook::react::FontStyle::Oblique) {
|
|
116
|
+
auto italic = xaml::Documents::Italic();
|
|
117
|
+
inlines.Append(italic);
|
|
118
|
+
inlines = italic.Inlines();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
auto run = xaml::Documents::Run();
|
|
122
|
+
run.Text(winrt::to_hstring(fragment.string));
|
|
123
|
+
run.FontFamily(xaml::Media::FontFamily(
|
|
124
|
+
fragment.textAttributes.fontFamily.empty() ? L"Segoe UI"
|
|
125
|
+
: winrt::to_hstring(fragment.textAttributes.fontFamily)));
|
|
126
|
+
|
|
127
|
+
run.FontWeight(
|
|
128
|
+
winrt::Windows::UI::Text::FontWeight{static_cast<uint16_t>(fragment.textAttributes.fontWeight.value_or(
|
|
129
|
+
static_cast<facebook::react::FontWeight>(DWRITE_FONT_WEIGHT_REGULAR)))});
|
|
130
|
+
|
|
131
|
+
run.FontSize(fragment.textAttributes.fontSize);
|
|
132
|
+
run.Foreground(fragment.textAttributes.foregroundColor.AsWindowsBrush());
|
|
133
|
+
inlines.Append(run);
|
|
134
|
+
}
|
|
107
135
|
}
|
|
108
136
|
void ParagraphComponentView::updateLayoutMetrics(
|
|
109
137
|
facebook::react::LayoutMetrics const &layoutMetrics,
|
|
@@ -118,9 +146,7 @@ void ParagraphComponentView::updateLayoutMetrics(
|
|
|
118
146
|
m_element.Width(layoutMetrics.frame.size.width);
|
|
119
147
|
m_element.Height(layoutMetrics.frame.size.height);
|
|
120
148
|
}
|
|
121
|
-
void ParagraphComponentView::finalizeUpdates(RNComponentViewUpdateMask updateMask) noexcept {
|
|
122
|
-
// m_element.FinalizeProperties();
|
|
123
|
-
}
|
|
149
|
+
void ParagraphComponentView::finalizeUpdates(RNComponentViewUpdateMask updateMask) noexcept {}
|
|
124
150
|
void ParagraphComponentView::prepareForRecycle() noexcept {}
|
|
125
151
|
facebook::react::SharedProps ParagraphComponentView::props() noexcept {
|
|
126
152
|
assert(false);
|
package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.cpp
CHANGED
|
@@ -5,72 +5,125 @@
|
|
|
5
5
|
|
|
6
6
|
#include "pch.h"
|
|
7
7
|
|
|
8
|
+
#include <Fabric/DWriteHelpers.h>
|
|
9
|
+
#include <dwrite.h>
|
|
8
10
|
#include "TextLayoutManager.h"
|
|
9
11
|
|
|
10
12
|
#include <unicode.h>
|
|
11
13
|
|
|
12
14
|
namespace facebook::react {
|
|
13
15
|
|
|
14
|
-
TextLayoutManager
|
|
16
|
+
void TextLayoutManager::GetTextLayout(
|
|
17
|
+
AttributedStringBox attributedStringBox,
|
|
18
|
+
ParagraphAttributes paragraphAttributes,
|
|
19
|
+
LayoutConstraints layoutConstraints,
|
|
20
|
+
const std::optional<TextAlignment> &textAlignment,
|
|
21
|
+
winrt::com_ptr<IDWriteTextLayout> &spTextLayout) noexcept {
|
|
22
|
+
if (attributedStringBox.getValue().isEmpty())
|
|
23
|
+
return;
|
|
24
|
+
|
|
25
|
+
auto fragments = attributedStringBox.getValue().getFragments();
|
|
26
|
+
auto outerFragment = fragments[0];
|
|
27
|
+
|
|
28
|
+
DWRITE_FONT_STYLE style = DWRITE_FONT_STYLE_NORMAL;
|
|
29
|
+
if (outerFragment.textAttributes.fontStyle == facebook::react::FontStyle::Italic)
|
|
30
|
+
style = DWRITE_FONT_STYLE_ITALIC;
|
|
31
|
+
else if (outerFragment.textAttributes.fontStyle == facebook::react::FontStyle::Oblique)
|
|
32
|
+
style = DWRITE_FONT_STYLE_OBLIQUE;
|
|
33
|
+
|
|
34
|
+
winrt::com_ptr<IDWriteTextFormat> spTextFormat;
|
|
35
|
+
winrt::check_hresult(Microsoft::ReactNative::DWriteFactory()->CreateTextFormat(
|
|
36
|
+
outerFragment.textAttributes.fontFamily.empty()
|
|
37
|
+
? L"Segoe UI"
|
|
38
|
+
: Microsoft::Common::Unicode::Utf8ToUtf16(outerFragment.textAttributes.fontFamily).c_str(),
|
|
39
|
+
nullptr, // Font collection (nullptr sets it to use the system font collection).
|
|
40
|
+
static_cast<DWRITE_FONT_WEIGHT>(outerFragment.textAttributes.fontWeight.value_or(
|
|
41
|
+
static_cast<facebook::react::FontWeight>(DWRITE_FONT_WEIGHT_REGULAR))),
|
|
42
|
+
style,
|
|
43
|
+
DWRITE_FONT_STRETCH_NORMAL,
|
|
44
|
+
outerFragment.textAttributes.fontSize,
|
|
45
|
+
L"",
|
|
46
|
+
spTextFormat.put()));
|
|
47
|
+
|
|
48
|
+
DWRITE_TEXT_ALIGNMENT alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
|
|
49
|
+
if (textAlignment) {
|
|
50
|
+
switch (*textAlignment) {
|
|
51
|
+
case facebook::react::TextAlignment::Center:
|
|
52
|
+
alignment = DWRITE_TEXT_ALIGNMENT_CENTER;
|
|
53
|
+
break;
|
|
54
|
+
case facebook::react::TextAlignment::Justified:
|
|
55
|
+
alignment = DWRITE_TEXT_ALIGNMENT_JUSTIFIED;
|
|
56
|
+
break;
|
|
57
|
+
case facebook::react::TextAlignment::Left:
|
|
58
|
+
alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
|
|
59
|
+
break;
|
|
60
|
+
case facebook::react::TextAlignment::Right:
|
|
61
|
+
alignment = DWRITE_TEXT_ALIGNMENT_TRAILING;
|
|
62
|
+
break;
|
|
63
|
+
// TODO use LTR values
|
|
64
|
+
case facebook::react::TextAlignment::Natural:
|
|
65
|
+
alignment = DWRITE_TEXT_ALIGNMENT_LEADING;
|
|
66
|
+
break;
|
|
67
|
+
default:
|
|
68
|
+
assert(false);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
winrt::check_hresult(spTextFormat->SetTextAlignment(alignment));
|
|
72
|
+
|
|
73
|
+
auto str = Microsoft::Common::Unicode::Utf8ToUtf16(attributedStringBox.getValue().getString());
|
|
74
|
+
|
|
75
|
+
winrt::check_hresult(Microsoft::ReactNative::DWriteFactory()->CreateTextLayout(
|
|
76
|
+
str.c_str(), // The string to be laid out and formatted.
|
|
77
|
+
static_cast<UINT32>(str.length()), // The length of the string.
|
|
78
|
+
spTextFormat.get(), // The text format to apply to the string (contains font information, etc).
|
|
79
|
+
layoutConstraints.maximumSize.width, // The width of the layout box.
|
|
80
|
+
layoutConstraints.maximumSize.height, // The height of the layout box.
|
|
81
|
+
spTextLayout.put() // The IDWriteTextLayout interface pointer.
|
|
82
|
+
));
|
|
83
|
+
|
|
84
|
+
unsigned int position = 0;
|
|
85
|
+
unsigned int length = 0;
|
|
86
|
+
for (const auto &fragment : fragments) {
|
|
87
|
+
length = static_cast<UINT32>(fragment.string.length());
|
|
88
|
+
DWRITE_TEXT_RANGE range = {position, length};
|
|
89
|
+
TextAttributes attributes = fragment.textAttributes;
|
|
90
|
+
DWRITE_FONT_STYLE fragmentStyle = DWRITE_FONT_STYLE_NORMAL;
|
|
91
|
+
if (attributes.fontStyle == facebook::react::FontStyle::Italic)
|
|
92
|
+
fragmentStyle = DWRITE_FONT_STYLE_ITALIC;
|
|
93
|
+
else if (attributes.fontStyle == facebook::react::FontStyle::Oblique)
|
|
94
|
+
fragmentStyle = DWRITE_FONT_STYLE_OBLIQUE;
|
|
95
|
+
|
|
96
|
+
winrt::check_hresult(spTextLayout->SetFontFamilyName(
|
|
97
|
+
attributes.fontFamily.empty() ? L"Segoe UI"
|
|
98
|
+
: Microsoft::Common::Unicode::Utf8ToUtf16(attributes.fontFamily).c_str(),
|
|
99
|
+
range));
|
|
100
|
+
winrt::check_hresult(spTextLayout->SetFontWeight(
|
|
101
|
+
static_cast<DWRITE_FONT_WEIGHT>(
|
|
102
|
+
attributes.fontWeight.value_or(static_cast<facebook::react::FontWeight>(DWRITE_FONT_WEIGHT_REGULAR))),
|
|
103
|
+
range));
|
|
104
|
+
winrt::check_hresult(spTextLayout->SetFontStyle(fragmentStyle, range));
|
|
105
|
+
winrt::check_hresult(spTextLayout->SetFontSize(attributes.fontSize, range));
|
|
106
|
+
|
|
107
|
+
position += length;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
15
110
|
|
|
16
111
|
TextMeasurement TextLayoutManager::measure(
|
|
17
112
|
AttributedStringBox attributedStringBox,
|
|
18
113
|
ParagraphAttributes paragraphAttributes,
|
|
19
114
|
LayoutConstraints layoutConstraints) const {
|
|
20
|
-
winrt::com_ptr<
|
|
115
|
+
winrt::com_ptr<IDWriteTextLayout> spTextLayout;
|
|
21
116
|
|
|
22
|
-
|
|
23
|
-
DWriteCreateFactory(
|
|
24
|
-
DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), reinterpret_cast<IUnknown **>(m_spDWriteFactory.put()));
|
|
25
|
-
}
|
|
117
|
+
GetTextLayout(attributedStringBox, paragraphAttributes, layoutConstraints, TextAlignment::Left, spTextLayout);
|
|
26
118
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
style = DWRITE_FONT_STYLE_OBLIQUE;
|
|
33
|
-
|
|
34
|
-
winrt::com_ptr<IDWriteTextFormat> spTextFormat;
|
|
35
|
-
m_spDWriteFactory->CreateTextFormat(
|
|
36
|
-
fragment.textAttributes.fontFamily.empty()
|
|
37
|
-
? L"Segoe UI"
|
|
38
|
-
: Microsoft::Common::Unicode::Utf8ToUtf16(fragment.textAttributes.fontFamily).c_str(),
|
|
39
|
-
nullptr, // Font collection (nullptr sets it to use the system font collection).
|
|
40
|
-
static_cast<DWRITE_FONT_WEIGHT>(fragment.textAttributes.fontWeight.value_or(
|
|
41
|
-
static_cast<facebook::react::FontWeight>(DWRITE_FONT_WEIGHT_REGULAR))),
|
|
42
|
-
style,
|
|
43
|
-
DWRITE_FONT_STRETCH_NORMAL,
|
|
44
|
-
fragment.textAttributes.fontSize * fragment.textAttributes.fontSizeMultiplier,
|
|
45
|
-
L"en-us",
|
|
46
|
-
spTextFormat.put());
|
|
47
|
-
|
|
48
|
-
auto str = Microsoft::Common::Unicode::Utf8ToUtf16(fragment.string);
|
|
49
|
-
|
|
50
|
-
winrt::com_ptr<IDWriteTextLayout> spTextLayout;
|
|
51
|
-
// TODO - For now assuming fragment.textAttributes.fontSizeMultiplier is the same as the pointScaleFactor
|
|
52
|
-
m_spDWriteFactory->CreateTextLayout(
|
|
53
|
-
str.c_str(), // The string to be laid out and formatted.
|
|
54
|
-
static_cast<UINT32>(str.length()), // The length of the string.
|
|
55
|
-
spTextFormat.get(), // The text format to apply to the string (contains font information, etc).
|
|
56
|
-
layoutConstraints.maximumSize.width *
|
|
57
|
-
fragment.textAttributes.fontSizeMultiplier, // The width of the layout box.
|
|
58
|
-
layoutConstraints.maximumSize.height *
|
|
59
|
-
fragment.textAttributes.fontSizeMultiplier, // The height of the layout box.
|
|
60
|
-
spTextLayout.put() // The IDWriteTextLayout interface pointer.
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
TextMeasurement tm;
|
|
64
|
-
DWRITE_TEXT_METRICS dtm;
|
|
65
|
-
spTextLayout->GetMetrics(&dtm);
|
|
66
|
-
tm.size = {
|
|
67
|
-
dtm.width / fragment.textAttributes.fontSizeMultiplier,
|
|
68
|
-
dtm.height / fragment.textAttributes.fontSizeMultiplier};
|
|
69
|
-
return tm;
|
|
119
|
+
TextMeasurement tm{};
|
|
120
|
+
if (spTextLayout) {
|
|
121
|
+
DWRITE_TEXT_METRICS dtm{};
|
|
122
|
+
winrt::check_hresult(spTextLayout->GetMetrics(&dtm));
|
|
123
|
+
tm.size = {dtm.width, dtm.height};
|
|
70
124
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
};
|
|
125
|
+
return tm;
|
|
126
|
+
}
|
|
74
127
|
|
|
75
128
|
/**
|
|
76
129
|
* Measures an AttributedString on the platform, as identified by some
|
|
@@ -81,8 +134,7 @@ TextMeasurement TextLayoutManager::measureCachedSpannableById(
|
|
|
81
134
|
ParagraphAttributes const ¶graphAttributes,
|
|
82
135
|
LayoutConstraints layoutConstraints) const {
|
|
83
136
|
assert(false);
|
|
84
|
-
|
|
85
|
-
return tm;
|
|
137
|
+
return {};
|
|
86
138
|
}
|
|
87
139
|
|
|
88
140
|
LinesMeasurements TextLayoutManager::measureLines(
|
|
@@ -90,9 +142,7 @@ LinesMeasurements TextLayoutManager::measureLines(
|
|
|
90
142
|
ParagraphAttributes paragraphAttributes,
|
|
91
143
|
Size size) const {
|
|
92
144
|
assert(false);
|
|
93
|
-
|
|
94
|
-
std::vector<LineMeasurement> paragraphLines{};
|
|
95
|
-
return paragraphLines;
|
|
145
|
+
return {};
|
|
96
146
|
}
|
|
97
147
|
|
|
98
148
|
void *TextLayoutManager::getNativeTextLayoutManager() const {
|