Skip to content

Commit 60f5f50

Browse files
authored
fix(📏): improve onSize infrastructure to rely on Reanimated (#3500)
1 parent 706cf97 commit 60f5f50

File tree

7 files changed

+26
-94
lines changed

7 files changed

+26
-94
lines changed

packages/skia/cpp/api/JsiSkAnimatedImage.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,9 @@ class JsiSkAnimatedImage
106106
if (bytesPerPixel == 0) {
107107
bytesPerPixel = 4;
108108
}
109-
frameBytes =
110-
safeMul(safeMul(static_cast<size_t>(frame->width()),
111-
static_cast<size_t>(frame->height())),
112-
bytesPerPixel);
109+
frameBytes = safeMul(safeMul(static_cast<size_t>(frame->width()),
110+
static_cast<size_t>(frame->height())),
111+
bytesPerPixel);
113112
}
114113
}
115114

packages/skia/cpp/api/JsiSkSurface.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -152,14 +152,15 @@ class JsiSkSurface : public JsiSkWrappingSkPtrHostObject<SkSurface> {
152152

153153
auto canvas = surface->getCanvas();
154154
const bool isGpuBacked =
155-
surface->recordingContext() != nullptr || surface->recorder() != nullptr ||
155+
surface->recordingContext() != nullptr ||
156+
surface->recorder() != nullptr ||
156157
(canvas && (canvas->recordingContext() != nullptr ||
157158
canvas->recorder() != nullptr));
158159

159160
if (isGpuBacked) {
160161
// Account for a resolved texture and depth/stencil attachments.
161-
estimated = safeAdd(estimated, pixelBytes); // resolve/texture copy
162-
estimated = safeAdd(estimated, pixelBytes / 2); // depth-stencil buffers
162+
estimated = safeAdd(estimated, pixelBytes); // resolve/texture copy
163+
estimated = safeAdd(estimated, pixelBytes / 2); // depth-stencil buffers
163164
}
164165

165166
// Add a small overhead buffer for bookkeeping allocations.

packages/skia/cpp/jsi/ViewProperty.h

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -53,47 +53,13 @@ class ViewProperty {
5353

5454
template <typename PlatformContext>
5555
ViewProperty(jsi::Runtime &runtime, const jsi::Value &value,
56-
PlatformContext platformContext, size_t nativeId) {
57-
// Set the onSize callback with all the necessary context
58-
auto runtimeGuard = std::make_shared<RuntimeAwareRuntimeGuard>(runtime);
59-
_value = std::function<void(int, int)>(
60-
[runtimeGuard, platformContext, nativeId](int width, int height) {
61-
auto runtimePtr = runtimeGuard->getRuntime();
62-
if (runtimePtr == nullptr) {
63-
return;
64-
}
65-
66-
jsi::Runtime &runtime = *runtimePtr;
67-
jsi::Object size(runtime);
68-
auto pd = platformContext->getPixelDensity();
69-
size.setProperty(runtime, "width", jsi::Value(width / pd));
70-
size.setProperty(runtime, "height", jsi::Value(height / pd));
71-
72-
// Get the stored shared value from global
73-
std::string globalKey =
74-
"__onSize_" + std::to_string(static_cast<int>(nativeId));
75-
auto globalProp =
76-
runtime.global().getProperty(runtime, globalKey.c_str());
77-
if (!globalProp.isUndefined()) {
78-
globalProp.asObject(runtime).setProperty(runtime, "value", size);
79-
}
80-
});
81-
}
56+
PlatformContext platformContext, size_t nativeId) {}
8257

8358
bool isNull() { return std::holds_alternative<std::nullptr_t>(_value); }
8459

8560
sk_sp<SkPicture> getPicture() { return std::get<sk_sp<SkPicture>>(_value); }
8661

87-
std::variant<std::nullptr_t, std::function<void(int, int)>>
88-
getOnSize() const {
89-
if (std::holds_alternative<std::function<void(int, int)>>(_value)) {
90-
return std::get<std::function<void(int, int)>>(_value);
91-
}
92-
return nullptr;
93-
}
94-
9562
private:
96-
std::variant<std::nullptr_t, sk_sp<SkPicture>, std::function<void(int, int)>>
97-
_value = nullptr;
63+
std::variant<std::nullptr_t, sk_sp<SkPicture>> _value = nullptr;
9864
};
9965
} // namespace RNJsi

packages/skia/cpp/rnskia/RNSkJsiViewApi.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,6 @@ class RNSkJsiViewApi : public RNJsi::JsiHostObject,
106106
info->props.insert_or_assign(
107107
arguments[1].asString(runtime).utf8(runtime),
108108
RNJsi::ViewProperty(runtime, arguments[2]));
109-
if (info->props.find("onSize") == info->props.end()) {
110-
info->props.insert_or_assign(
111-
"onSize", RNJsi::ViewProperty(runtime, arguments[2],
112-
_platformContext, nativeId));
113-
}
114109
// Now let's see if we have a view that we can update
115110
if (info->view != nullptr) {
116111
// Update view!

packages/skia/cpp/rnskia/RNSkPictureView.h

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -56,25 +56,8 @@ class RNSkPictureRenderer
5656
_requestRedraw();
5757
}
5858

59-
void setOnSize(
60-
std::variant<std::nullptr_t, std::function<void(int, int)>> onSize) {
61-
_onSize = onSize;
62-
}
63-
6459
private:
6560
bool performDraw(std::shared_ptr<RNSkCanvasProvider> canvasProvider) {
66-
// Call onSize callback only if the size has changed
67-
int currentWidth = canvasProvider->getWidth();
68-
int currentHeight = canvasProvider->getHeight();
69-
70-
if (std::holds_alternative<std::function<void(int, int)>>(_onSize)) {
71-
if (_lastWidth != currentWidth || _lastHeight != currentHeight) {
72-
_lastWidth = currentWidth;
73-
_lastHeight = currentHeight;
74-
std::get<std::function<void(int, int)>>(_onSize)(currentWidth,
75-
currentHeight);
76-
}
77-
}
7861
return canvasProvider->renderToCanvas([=, this](SkCanvas *canvas) {
7962
// Make sure to scale correctly
8063
auto pd = _platformContext->getPixelDensity();
@@ -90,9 +73,6 @@ class RNSkPictureRenderer
9073

9174
std::shared_ptr<RNSkPlatformContext> _platformContext;
9275
sk_sp<SkPicture> _picture;
93-
std::variant<std::nullptr_t, std::function<void(int, int)>> _onSize = nullptr;
94-
int _lastWidth = -1;
95-
int _lastHeight = -1;
9676
};
9777

9878
class RNSkPictureView : public RNSkView {
@@ -109,7 +89,7 @@ class RNSkPictureView : public RNSkView {
10989

11090
void setJsiProperties(
11191
std::unordered_map<std::string, RNJsi::ViewProperty> &props) override {
112-
// Base implementation - no onSize callback
92+
// Base implementation
11393
for (auto &prop : props) {
11494
if (prop.first == "picture") {
11595
if (prop.second.isNull()) {
@@ -121,9 +101,6 @@ class RNSkPictureView : public RNSkView {
121101
// Save picture
122102
std::static_pointer_cast<RNSkPictureRenderer>(getRenderer())
123103
->setPicture(prop.second.getPicture());
124-
} else if (prop.first == "onSize") {
125-
std::static_pointer_cast<RNSkPictureRenderer>(getRenderer())
126-
->setOnSize(prop.second.getOnSize());
127104
}
128105
}
129106
}

packages/skia/cpp/rnskia/RNSkView.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -148,13 +148,6 @@ class RNSkView : public std::enable_shared_from_this<RNSkView> {
148148
virtual void setJsiProperties(
149149
std::unordered_map<std::string, RNJsi::ViewProperty> &props) = 0;
150150

151-
virtual void
152-
setJsiProperties(std::unordered_map<std::string, RNJsi::ViewProperty> &props,
153-
std::function<jsi::Object(int, int)> onSize) {
154-
// Default implementation just calls the base method, ignoring onSize
155-
setJsiProperties(props);
156-
}
157-
158151
void requestRedraw() {
159152
if (!_redrawRequested) {
160153
_redrawRequested = true;

packages/skia/src/renderer/Canvas.tsx

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import type {
1515
View,
1616
ViewProps,
1717
} from "react-native";
18-
import type { SharedValue } from "react-native-reanimated";
18+
import type { AnimatedRef, SharedValue } from "react-native-reanimated";
1919

2020
import Rea from "../external/reanimated/ReanimatedProxy";
2121
import { SkiaViewNativeId } from "../views/SkiaViewNativeId";
@@ -38,6 +38,11 @@ export interface CanvasRef extends FC<CanvasProps> {
3838
export const useCanvasRef = () => useRef<CanvasRef>(null);
3939

4040
const useReanimatedFrame = !HAS_REANIMATED_3 ? () => {} : Rea.useFrameCallback;
41+
const measure = !HAS_REANIMATED_3 ? null : Rea.measure;
42+
43+
const useCanvasRefPriv: typeof useRef<View> = !HAS_REANIMATED_3
44+
? useRef
45+
: Rea.useAnimatedRef;
4146

4247
export const useCanvasSize = (userRef?: RefObject<CanvasRef | null>) => {
4348
const ourRef = useCanvasRef();
@@ -84,7 +89,7 @@ export const Canvas = ({
8489
"<Canvas onLayout={onLayout} /> is not supported on the new architecture, to fix the issue, see: https://shopify.github.io/react-native-skia/docs/canvas/overview/#getting-the-canvas-size"
8590
);
8691
}
87-
const viewRef = useRef<View>(null);
92+
const viewRef = useCanvasRefPriv(null);
8893
// Native ID
8994
const nativeId = useMemo(() => {
9095
return SkiaViewNativeId.current++;
@@ -95,20 +100,16 @@ export const Canvas = ({
95100

96101
useReanimatedFrame(() => {
97102
"worklet";
98-
}, !!onSize);
99-
useEffect(() => {
100-
if (onSize) {
101-
Rea.runOnUI(() => {
102-
(global as Record<string, unknown>)[`__onSize_${nativeId}`] = onSize;
103-
})();
104-
return () => {
105-
Rea.runOnUI(() => {
106-
delete (global as Record<string, unknown>)[`__onSize_${nativeId}`];
107-
})();
108-
};
103+
if (onSize && measure) {
104+
const result = measure(viewRef as AnimatedRef<View>);
105+
if (result) {
106+
const { width, height } = result;
107+
if (onSize.value.width !== width || onSize.value.height !== height) {
108+
onSize.value = { width, height };
109+
}
110+
}
109111
}
110-
return undefined;
111-
}, [onSize, nativeId]);
112+
}, !!onSize);
112113

113114
// Render effects
114115
useLayoutEffect(() => {

0 commit comments

Comments
 (0)