react-native-smooth-clip-view 0.2.9 → 0.3.0
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/README.md +60 -21
- package/android/build.gradle +6 -2
- package/android/proguard-rules.pro +3 -3
- package/android/src/main/cpp/SmoothClipAndroid.h +10 -0
- package/android/src/main/cpp/SmoothClipBindings.cpp +890 -4
- package/android/src/main/cpp/SmoothClipRegistry.cpp +1056 -44
- package/android/src/main/java/com/smoothclipview/ClipGeometryNormalizer.kt +265 -0
- package/android/src/main/java/com/smoothclipview/SmoothClipBindings.kt +21 -0
- package/android/src/main/java/com/smoothclipview/SmoothClipModule.kt +283 -0
- package/android/src/main/java/com/smoothclipview/SmoothClipView.kt +371 -18
- package/android/src/main/java/com/smoothclipview/SmoothClipViewManager.kt +138 -24
- package/cpp/SmoothClipAnimationCurve.h +151 -122
- package/cpp/SmoothClipRegistry.h +95 -3
- package/cpp/SmoothClipSharedGeometry.h +146 -7
- package/cpp/SmoothClipVelocityTracker.h +13 -9
- package/ios/SmoothClipGeometry.h +184 -6
- package/ios/SmoothClipRegistry.mm +1028 -22
- package/ios/SmoothClipRegistrySnapshot.h +13 -0
- package/ios/SmoothClipTurboModule.cpp +857 -2
- package/ios/SmoothClipTurboModule.h +310 -0
- package/ios/SmoothClipView.mm +714 -183
- package/ios/SmoothClipViewRegistry.h +1 -0
- package/ios/reactnativesmoothclipview.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/ios/reactnativesmoothclipview.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/lib/module/NativeSmoothClipModule.js.map +1 -1
- package/lib/module/SmoothClipView.ios.js +22 -6
- package/lib/module/SmoothClipView.ios.js.map +1 -1
- package/lib/module/SmoothClipView.js +1 -46
- package/lib/module/SmoothClipView.js.map +1 -1
- package/lib/module/SmoothClipViewNativeComponent.ts +27 -1
- package/lib/module/capabilities.js +4 -0
- package/lib/module/capabilities.js.map +1 -0
- package/lib/module/capabilities.native.js +36 -0
- package/lib/module/capabilities.native.js.map +1 -0
- package/lib/module/capabilityTypes.js +11 -0
- package/lib/module/capabilityTypes.js.map +1 -0
- package/lib/module/driverState.js +0 -28
- package/lib/module/driverState.js.map +1 -1
- package/lib/module/drivers.js +1 -281
- package/lib/module/drivers.js.map +1 -1
- package/lib/module/drivers.native.js +263 -63
- package/lib/module/drivers.native.js.map +1 -1
- package/lib/module/geometry.js +147 -17
- package/lib/module/geometry.js.map +1 -1
- package/lib/module/groupDriverTypes.js +4 -0
- package/lib/module/groupDriverTypes.js.map +1 -0
- package/lib/module/groupDrivers.android.js +4 -0
- package/lib/module/groupDrivers.android.js.map +1 -0
- package/lib/module/groupDrivers.ios.js +4 -0
- package/lib/module/groupDrivers.ios.js.map +1 -0
- package/lib/module/groupDrivers.js +4 -0
- package/lib/module/groupDrivers.js.map +1 -0
- package/lib/module/groupDrivers.native.js +799 -0
- package/lib/module/groupDrivers.native.js.map +1 -0
- package/lib/module/index.js +3 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/presentationProtocol.js +15 -0
- package/lib/module/presentationProtocol.js.map +1 -0
- package/lib/typescript/src/NativeSmoothClipModule.d.ts +25 -0
- package/lib/typescript/src/NativeSmoothClipModule.d.ts.map +1 -1
- package/lib/typescript/src/SmoothClipView.d.ts +2 -10
- package/lib/typescript/src/SmoothClipView.d.ts.map +1 -1
- package/lib/typescript/src/SmoothClipView.ios.d.ts +133 -2
- package/lib/typescript/src/SmoothClipView.ios.d.ts.map +1 -1
- package/lib/typescript/src/SmoothClipViewNativeComponent.d.ts +8 -0
- package/lib/typescript/src/SmoothClipViewNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/capabilities.d.ts +3 -0
- package/lib/typescript/src/capabilities.d.ts.map +1 -0
- package/lib/typescript/src/capabilities.native.d.ts +3 -0
- package/lib/typescript/src/capabilities.native.d.ts.map +1 -0
- package/lib/typescript/src/capabilityTypes.d.ts +10 -0
- package/lib/typescript/src/capabilityTypes.d.ts.map +1 -0
- package/lib/typescript/src/driverState.d.ts +1 -6
- package/lib/typescript/src/driverState.d.ts.map +1 -1
- package/lib/typescript/src/driverTypes.d.ts +25 -11
- package/lib/typescript/src/driverTypes.d.ts.map +1 -1
- package/lib/typescript/src/drivers.d.ts +2 -4
- package/lib/typescript/src/drivers.d.ts.map +1 -1
- package/lib/typescript/src/drivers.native.d.ts.map +1 -1
- package/lib/typescript/src/geometry.d.ts +36 -2
- package/lib/typescript/src/geometry.d.ts.map +1 -1
- package/lib/typescript/src/groupDriverTypes.d.ts +66 -0
- package/lib/typescript/src/groupDriverTypes.d.ts.map +1 -0
- package/lib/typescript/src/groupDrivers.android.d.ts +2 -0
- package/lib/typescript/src/groupDrivers.android.d.ts.map +1 -0
- package/lib/typescript/src/groupDrivers.d.ts +2 -0
- package/lib/typescript/src/groupDrivers.d.ts.map +1 -0
- package/lib/typescript/src/groupDrivers.ios.d.ts +2 -0
- package/lib/typescript/src/groupDrivers.ios.d.ts.map +1 -0
- package/lib/typescript/src/groupDrivers.native.d.ts +4 -0
- package/lib/typescript/src/groupDrivers.native.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +6 -3
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/presentationProtocol.d.ts +4 -0
- package/lib/typescript/src/presentationProtocol.d.ts.map +1 -0
- package/package.json +10 -11
- package/src/NativeSmoothClipModule.ts +275 -0
- package/src/SmoothClipView.ios.tsx +30 -11
- package/src/SmoothClipView.tsx +2 -76
- package/src/SmoothClipViewNativeComponent.ts +27 -1
- package/src/capabilities.native.ts +69 -0
- package/src/capabilities.ts +2 -0
- package/src/capabilityTypes.ts +17 -0
- package/src/driverState.ts +1 -41
- package/src/driverTypes.ts +42 -11
- package/src/drivers.native.ts +824 -124
- package/src/drivers.ts +2 -423
- package/src/geometry.ts +231 -27
- package/src/groupDriverTypes.ts +117 -0
- package/src/groupDrivers.android.ts +1 -0
- package/src/groupDrivers.ios.ts +1 -0
- package/src/groupDrivers.native.ts +1189 -0
- package/src/groupDrivers.ts +1 -0
- package/src/index.ts +30 -2
- package/src/presentationProtocol.ts +28 -0
- package/lib/module/SmoothClipView.web.js +0 -54
- package/lib/module/SmoothClipView.web.js.map +0 -1
- package/lib/module/index.web.js +0 -8
- package/lib/module/index.web.js.map +0 -1
- package/lib/module/webClipPath.js +0 -25
- package/lib/module/webClipPath.js.map +0 -1
- package/lib/typescript/src/SmoothClipView.web.d.ts +0 -10
- package/lib/typescript/src/SmoothClipView.web.d.ts.map +0 -1
- package/lib/typescript/src/index.web.d.ts +0 -9
- package/lib/typescript/src/index.web.d.ts.map +0 -1
- package/lib/typescript/src/webClipPath.d.ts +0 -7
- package/lib/typescript/src/webClipPath.d.ts.map +0 -1
- package/src/SmoothClipView.web.tsx +0 -66
- package/src/index.web.ts +0 -23
- package/src/webClipPath.ts +0 -30
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
namespace smoothclip {
|
|
7
7
|
|
|
8
8
|
// The two most recent interactive samples used by `initialVelocity: 'inherit'`.
|
|
9
|
-
// Channels are the
|
|
10
|
-
//
|
|
9
|
+
// Channels are the eleven continuous V2 presentation scalars. Scale is stored
|
|
10
|
+
// so histories remain coherent but excluded from velocity projection; each of
|
|
11
|
+
// the four radius channels contributes one quarter of the legacy radius weight.
|
|
11
12
|
// iOS records normalized (host-clamped) geometry, Android raw DIP — the
|
|
12
13
|
// projection only needs both samples and the target in the same space.
|
|
13
14
|
// Shared by ios/SmoothClipView.mm and android/.../SmoothClipRegistry.cpp; a
|
|
@@ -15,8 +16,8 @@ namespace smoothclip {
|
|
|
15
16
|
struct VelocitySampleHistory {
|
|
16
17
|
bool hasPrevious = false;
|
|
17
18
|
bool hasLatest = false;
|
|
18
|
-
std::array<double,
|
|
19
|
-
std::array<double,
|
|
19
|
+
std::array<double, 11> previous{};
|
|
20
|
+
std::array<double, 11> latest{};
|
|
20
21
|
double previousTimeS = 0;
|
|
21
22
|
double latestTimeS = 0;
|
|
22
23
|
};
|
|
@@ -40,7 +41,7 @@ inline constexpr double kVelocityFullCreditS = 1.0 / 60.0;
|
|
|
40
41
|
|
|
41
42
|
inline void recordVelocitySample(
|
|
42
43
|
VelocitySampleHistory &history,
|
|
43
|
-
const std::array<double,
|
|
44
|
+
const std::array<double, 11> &channels,
|
|
44
45
|
double nowS) {
|
|
45
46
|
if (history.hasLatest && channels == history.latest) {
|
|
46
47
|
// Identical re-record (a `from` seed equal to the last interactive
|
|
@@ -97,7 +98,7 @@ inline double velocityStalenessCredit(double holdS) {
|
|
|
97
98
|
// Android seeds each integrator channel with scalar·displacement.
|
|
98
99
|
inline double inheritedVelocity(
|
|
99
100
|
const VelocitySampleHistory &history,
|
|
100
|
-
const std::array<double,
|
|
101
|
+
const std::array<double, 11> &target,
|
|
101
102
|
double nowS) {
|
|
102
103
|
if (!history.hasPrevious || !history.hasLatest) return 0;
|
|
103
104
|
const double elapsed = history.latestTimeS - history.previousTimeS;
|
|
@@ -107,11 +108,14 @@ inline double inheritedVelocity(
|
|
|
107
108
|
}
|
|
108
109
|
double numerator = 0;
|
|
109
110
|
double denominator = 0;
|
|
110
|
-
for (int index = 0; index <
|
|
111
|
+
for (int index = 0; index < 11; index += 1) {
|
|
112
|
+
const double weight = index >= 4 && index <= 7
|
|
113
|
+
? 0.25
|
|
114
|
+
: (index == 10 ? 0.0 : 1.0);
|
|
111
115
|
const double sampleDelta = history.latest[index] - history.previous[index];
|
|
112
116
|
const double destinationDelta = target[index] - history.latest[index];
|
|
113
|
-
numerator += sampleDelta * destinationDelta;
|
|
114
|
-
denominator += destinationDelta * destinationDelta;
|
|
117
|
+
numerator += weight * sampleDelta * destinationDelta;
|
|
118
|
+
denominator += weight * destinationDelta * destinationDelta;
|
|
115
119
|
}
|
|
116
120
|
if (denominator <= 1e-12) return 0;
|
|
117
121
|
const double result = numerator / elapsed / denominator * credit;
|
package/ios/SmoothClipGeometry.h
CHANGED
|
@@ -2,23 +2,77 @@
|
|
|
2
2
|
|
|
3
3
|
#include <math.h>
|
|
4
4
|
|
|
5
|
+
typedef struct {
|
|
6
|
+
CGFloat topLeft;
|
|
7
|
+
CGFloat topRight;
|
|
8
|
+
CGFloat bottomRight;
|
|
9
|
+
CGFloat bottomLeft;
|
|
10
|
+
} SmoothClipCornerRadii;
|
|
11
|
+
|
|
12
|
+
typedef NS_ENUM(NSInteger, SmoothClipCornerCurve) {
|
|
13
|
+
SmoothClipCornerCurveCircular = 0,
|
|
14
|
+
SmoothClipCornerCurveContinuous = 1,
|
|
15
|
+
};
|
|
16
|
+
|
|
5
17
|
typedef struct {
|
|
6
18
|
CGRect rect;
|
|
19
|
+
// Retained for the V1 uniform-radius contract. V2 callers should consume
|
|
20
|
+
// `radii`; this field is zero when the normalized radii are unequal.
|
|
7
21
|
CGFloat radius;
|
|
22
|
+
SmoothClipCornerRadii radii;
|
|
23
|
+
SmoothClipCornerCurve curve;
|
|
8
24
|
} SmoothNormalizedClipGeometry;
|
|
9
25
|
|
|
10
|
-
|
|
11
|
-
|
|
26
|
+
NS_INLINE BOOL SmoothClipCornerRadiiEqual(
|
|
27
|
+
SmoothClipCornerRadii first,
|
|
28
|
+
SmoothClipCornerRadii second) {
|
|
29
|
+
return first.topLeft == second.topLeft &&
|
|
30
|
+
first.topRight == second.topRight &&
|
|
31
|
+
first.bottomRight == second.bottomRight &&
|
|
32
|
+
first.bottomLeft == second.bottomLeft;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
NS_INLINE BOOL SmoothClipCornerRadiiAreUniform(
|
|
36
|
+
SmoothClipCornerRadii radii) {
|
|
37
|
+
return radii.topLeft == radii.topRight &&
|
|
38
|
+
radii.topLeft == radii.bottomRight &&
|
|
39
|
+
radii.topLeft == radii.bottomLeft;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
NS_INLINE CGFloat SmoothClipSafeOverlapFactor(
|
|
43
|
+
CGFloat extent,
|
|
44
|
+
CGFloat firstRadius,
|
|
45
|
+
CGFloat secondRadius) {
|
|
46
|
+
const CGFloat sum = firstRadius + secondRadius;
|
|
47
|
+
return sum > 0 ? extent / sum : 1;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Normalizes the V2 rectangle and four radii without allocating.
|
|
52
|
+
*
|
|
53
|
+
* The proportional overlap rule matches CSS border radii and the shared
|
|
54
|
+
* Android/C++ contract: all corners use one scale factor, preserving their
|
|
55
|
+
* relative shape while no opposing pair exceeds its edge.
|
|
56
|
+
*/
|
|
57
|
+
NS_INLINE BOOL SmoothClipNormalizeGeometryV2(
|
|
12
58
|
CGFloat x,
|
|
13
59
|
CGFloat y,
|
|
14
60
|
CGFloat width,
|
|
15
61
|
CGFloat height,
|
|
16
|
-
CGFloat
|
|
62
|
+
CGFloat topLeftRadius,
|
|
63
|
+
CGFloat topRightRadius,
|
|
64
|
+
CGFloat bottomRightRadius,
|
|
65
|
+
CGFloat bottomLeftRadius,
|
|
66
|
+
NSInteger curveCode,
|
|
17
67
|
CGSize hostSize,
|
|
18
68
|
SmoothNormalizedClipGeometry *result) {
|
|
19
69
|
if (!isfinite(x) || !isfinite(y) || !isfinite(width) ||
|
|
20
|
-
!isfinite(height) || !isfinite(
|
|
21
|
-
!isfinite(
|
|
70
|
+
!isfinite(height) || !isfinite(topLeftRadius) ||
|
|
71
|
+
!isfinite(topRightRadius) || !isfinite(bottomRightRadius) ||
|
|
72
|
+
!isfinite(bottomLeftRadius) || !isfinite(hostSize.width) ||
|
|
73
|
+
!isfinite(hostSize.height) ||
|
|
74
|
+
(curveCode != SmoothClipCornerCurveCircular &&
|
|
75
|
+
curveCode != SmoothClipCornerCurveContinuous)) {
|
|
22
76
|
return NO;
|
|
23
77
|
}
|
|
24
78
|
|
|
@@ -35,7 +89,131 @@ NS_INLINE BOOL SmoothClipNormalizeGeometry(
|
|
|
35
89
|
const CGFloat visibleWidth = MAX(0, right - left);
|
|
36
90
|
const CGFloat visibleHeight = MAX(0, bottom - top);
|
|
37
91
|
|
|
92
|
+
SmoothClipCornerRadii radii = {
|
|
93
|
+
MAX(0, topLeftRadius),
|
|
94
|
+
MAX(0, topRightRadius),
|
|
95
|
+
MAX(0, bottomRightRadius),
|
|
96
|
+
MAX(0, bottomLeftRadius),
|
|
97
|
+
};
|
|
98
|
+
const CGFloat overlapScale = MIN(
|
|
99
|
+
1,
|
|
100
|
+
MIN(
|
|
101
|
+
MIN(
|
|
102
|
+
SmoothClipSafeOverlapFactor(
|
|
103
|
+
visibleWidth, radii.topLeft, radii.topRight),
|
|
104
|
+
SmoothClipSafeOverlapFactor(
|
|
105
|
+
visibleWidth, radii.bottomLeft, radii.bottomRight)),
|
|
106
|
+
MIN(
|
|
107
|
+
SmoothClipSafeOverlapFactor(
|
|
108
|
+
visibleHeight, radii.topLeft, radii.bottomLeft),
|
|
109
|
+
SmoothClipSafeOverlapFactor(
|
|
110
|
+
visibleHeight, radii.topRight, radii.bottomRight))));
|
|
111
|
+
radii.topLeft *= overlapScale;
|
|
112
|
+
radii.topRight *= overlapScale;
|
|
113
|
+
radii.bottomRight *= overlapScale;
|
|
114
|
+
radii.bottomLeft *= overlapScale;
|
|
115
|
+
|
|
38
116
|
result->rect = CGRectMake(left, top, visibleWidth, visibleHeight);
|
|
39
|
-
result->
|
|
117
|
+
result->radii = radii;
|
|
118
|
+
result->radius = SmoothClipCornerRadiiAreUniform(radii)
|
|
119
|
+
? radii.topLeft
|
|
120
|
+
: 0;
|
|
121
|
+
result->curve = (SmoothClipCornerCurve)curveCode;
|
|
40
122
|
return YES;
|
|
41
123
|
}
|
|
124
|
+
|
|
125
|
+
/** Mirrors the Android and JavaScript geometry contract without allocating. */
|
|
126
|
+
NS_INLINE BOOL SmoothClipNormalizeGeometry(
|
|
127
|
+
CGFloat x,
|
|
128
|
+
CGFloat y,
|
|
129
|
+
CGFloat width,
|
|
130
|
+
CGFloat height,
|
|
131
|
+
CGFloat radius,
|
|
132
|
+
CGSize hostSize,
|
|
133
|
+
SmoothNormalizedClipGeometry *result) {
|
|
134
|
+
return SmoothClipNormalizeGeometryV2(
|
|
135
|
+
x,
|
|
136
|
+
y,
|
|
137
|
+
width,
|
|
138
|
+
height,
|
|
139
|
+
radius,
|
|
140
|
+
radius,
|
|
141
|
+
radius,
|
|
142
|
+
radius,
|
|
143
|
+
SmoothClipCornerCurveCircular,
|
|
144
|
+
hostSize,
|
|
145
|
+
result);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Creates the stable nine-segment rounded-rectangle topology used by the
|
|
150
|
+
* unequal-corner CAShapeLayer mask. Every corner is one cubic, including a
|
|
151
|
+
* zero-radius corner, so Core Animation can interpolate paths without a
|
|
152
|
+
* topology change.
|
|
153
|
+
*/
|
|
154
|
+
NS_INLINE CGPathRef SmoothClipCreateRoundedRectPath(
|
|
155
|
+
CGRect rect,
|
|
156
|
+
SmoothClipCornerRadii radii,
|
|
157
|
+
SmoothClipCornerCurve curve) CF_RETURNS_RETAINED {
|
|
158
|
+
const CGFloat minX = CGRectGetMinX(rect);
|
|
159
|
+
const CGFloat minY = CGRectGetMinY(rect);
|
|
160
|
+
const CGFloat maxX = CGRectGetMaxX(rect);
|
|
161
|
+
const CGFloat maxY = CGRectGetMaxY(rect);
|
|
162
|
+
// Circular is the exact cubic-circle coefficient. The portable continuous
|
|
163
|
+
// fallback uses kappa=1 so each cubic joins its straight edges with zero
|
|
164
|
+
// curvature, matching the portable Android path. Hit testing derives
|
|
165
|
+
// from this rendered path rather than maintaining a second curve model.
|
|
166
|
+
// Uniform
|
|
167
|
+
// continuous shapes use CALayer.cornerCurve for Apple's platform-native
|
|
168
|
+
// compositor shape and are intentionally not pixel-identical cross-platform.
|
|
169
|
+
const CGFloat controlFactor =
|
|
170
|
+
curve == SmoothClipCornerCurveContinuous
|
|
171
|
+
? 1.0
|
|
172
|
+
: 0.5522847498307936;
|
|
173
|
+
|
|
174
|
+
CGMutablePathRef path = CGPathCreateMutable();
|
|
175
|
+
CGPathMoveToPoint(path, NULL, minX + radii.topLeft, minY);
|
|
176
|
+
CGPathAddLineToPoint(path, NULL, maxX - radii.topRight, minY);
|
|
177
|
+
CGPathAddCurveToPoint(
|
|
178
|
+
path,
|
|
179
|
+
NULL,
|
|
180
|
+
maxX - radii.topRight + radii.topRight * controlFactor,
|
|
181
|
+
minY,
|
|
182
|
+
maxX,
|
|
183
|
+
minY + radii.topRight - radii.topRight * controlFactor,
|
|
184
|
+
maxX,
|
|
185
|
+
minY + radii.topRight);
|
|
186
|
+
CGPathAddLineToPoint(path, NULL, maxX, maxY - radii.bottomRight);
|
|
187
|
+
CGPathAddCurveToPoint(
|
|
188
|
+
path,
|
|
189
|
+
NULL,
|
|
190
|
+
maxX,
|
|
191
|
+
maxY - radii.bottomRight + radii.bottomRight * controlFactor,
|
|
192
|
+
maxX - radii.bottomRight +
|
|
193
|
+
radii.bottomRight * controlFactor,
|
|
194
|
+
maxY,
|
|
195
|
+
maxX - radii.bottomRight,
|
|
196
|
+
maxY);
|
|
197
|
+
CGPathAddLineToPoint(path, NULL, minX + radii.bottomLeft, maxY);
|
|
198
|
+
CGPathAddCurveToPoint(
|
|
199
|
+
path,
|
|
200
|
+
NULL,
|
|
201
|
+
minX + radii.bottomLeft - radii.bottomLeft * controlFactor,
|
|
202
|
+
maxY,
|
|
203
|
+
minX,
|
|
204
|
+
maxY - radii.bottomLeft + radii.bottomLeft * controlFactor,
|
|
205
|
+
minX,
|
|
206
|
+
maxY - radii.bottomLeft);
|
|
207
|
+
CGPathAddLineToPoint(path, NULL, minX, minY + radii.topLeft);
|
|
208
|
+
CGPathAddCurveToPoint(
|
|
209
|
+
path,
|
|
210
|
+
NULL,
|
|
211
|
+
minX,
|
|
212
|
+
minY + radii.topLeft - radii.topLeft * controlFactor,
|
|
213
|
+
minX + radii.topLeft - radii.topLeft * controlFactor,
|
|
214
|
+
minY,
|
|
215
|
+
minX + radii.topLeft,
|
|
216
|
+
minY);
|
|
217
|
+
CGPathCloseSubpath(path);
|
|
218
|
+
return path;
|
|
219
|
+
}
|