@shopify/react-native-skia 2.6.8 → 2.7.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/android/cpp/jni/include/JniSkiaBaseView.h +6 -4
- package/android/cpp/jni/include/JniSkiaPictureView.h +8 -6
- package/android/cpp/rnskia-android/OpenGLContext.h +20 -5
- package/android/cpp/rnskia-android/RNSkAndroidView.h +8 -8
- package/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp +9 -5
- package/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h +4 -2
- package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java +48 -12
- package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseViewManager.java +5 -0
- package/android/src/main/java/com/shopify/reactnative/skia/SkiaPictureView.java +2 -2
- package/android/src/main/java/com/shopify/reactnative/skia/ViewScreenshotService.java +11 -7
- package/apple/MetalContext.h +7 -6
- package/apple/MetalLayerColorSpace.mm +39 -0
- package/apple/MetalLayerColorSpaceUtils.h +34 -0
- package/apple/MetalWindowContext.h +3 -1
- package/apple/MetalWindowContext.mm +9 -8
- package/apple/RNSkAppleView.h +6 -0
- package/apple/RNSkMetalCanvasProvider.h +2 -0
- package/apple/RNSkMetalCanvasProvider.mm +15 -2
- package/apple/SkiaCVPixelBufferUtils.mm +10 -0
- package/apple/SkiaPictureView.mm +1 -0
- package/apple/SkiaPictureViewManager.mm +5 -0
- package/apple/SkiaUIView.h +1 -0
- package/apple/SkiaUIView.mm +9 -0
- package/cpp/api/JsiSkSurface.h +8 -2
- package/cpp/rnskia/RNDawnContext.h +4 -3
- package/cpp/rnskia/RNDawnUtils.h +25 -6
- package/cpp/rnskia/RNDawnWindowContext.h +44 -10
- package/cpp/rnskia/RNMetalLayerColorSpace.h +16 -0
- package/cpp/rnskia/RNSkJsiViewApi.h +46 -24
- package/cpp/rnwgpu/SurfaceRegistry.h +10 -4
- package/lib/commonjs/Platform/Platform.web.js +2 -90
- package/lib/commonjs/Platform/Platform.web.js.map +1 -1
- package/lib/commonjs/mock/index.js +1 -0
- package/lib/commonjs/mock/index.js.map +1 -1
- package/lib/commonjs/renderer/Canvas.d.ts +10 -1
- package/lib/commonjs/renderer/Canvas.js +2 -0
- package/lib/commonjs/renderer/Canvas.js.map +1 -1
- package/lib/commonjs/skia/types/Surface/Surface.d.ts +5 -1
- package/lib/commonjs/skia/types/Surface/Surface.js.map +1 -1
- package/lib/commonjs/skia/web/JsiSkParagraphStyle.js +14 -3
- package/lib/commonjs/skia/web/JsiSkParagraphStyle.js.map +1 -1
- package/lib/commonjs/skia/web/JsiSkSurface.d.ts +1 -1
- package/lib/commonjs/skia/web/JsiSkSurface.js +2 -1
- package/lib/commonjs/skia/web/JsiSkSurface.js.map +1 -1
- package/lib/commonjs/sksg/Container.native.d.ts +1 -0
- package/lib/commonjs/sksg/Container.native.js +11 -0
- package/lib/commonjs/sksg/Container.native.js.map +1 -1
- package/lib/commonjs/sksg/Container.web.d.ts +1 -0
- package/lib/commonjs/sksg/Container.web.js +11 -0
- package/lib/commonjs/sksg/Container.web.js.map +1 -1
- package/lib/commonjs/specs/NativeSkiaModule.web.d.ts +2 -0
- package/lib/commonjs/specs/NativeSkiaModule.web.js +32 -7
- package/lib/commonjs/specs/NativeSkiaModule.web.js.map +1 -1
- package/lib/commonjs/specs/SkiaPictureViewNativeComponent.d.ts +1 -0
- package/lib/commonjs/specs/SkiaPictureViewNativeComponent.js.map +1 -1
- package/lib/commonjs/views/SkiaPictureView.js +2 -0
- package/lib/commonjs/views/SkiaPictureView.js.map +1 -1
- package/lib/commonjs/views/SkiaPictureView.web.js +279 -94
- package/lib/commonjs/views/SkiaPictureView.web.js.map +1 -1
- package/lib/commonjs/views/formats.d.ts +1 -0
- package/lib/commonjs/views/formats.js +28 -0
- package/lib/commonjs/views/formats.js.map +1 -0
- package/lib/commonjs/views/index.d.ts +1 -0
- package/lib/commonjs/views/index.js +11 -0
- package/lib/commonjs/views/index.js.map +1 -1
- package/lib/commonjs/views/types.d.ts +6 -0
- package/lib/commonjs/views/types.js.map +1 -1
- package/lib/module/Platform/Platform.web.js +3 -91
- package/lib/module/Platform/Platform.web.js.map +1 -1
- package/lib/module/mock/index.js +1 -0
- package/lib/module/mock/index.js.map +1 -1
- package/lib/module/renderer/Canvas.d.ts +10 -1
- package/lib/module/renderer/Canvas.js +2 -0
- package/lib/module/renderer/Canvas.js.map +1 -1
- package/lib/module/skia/types/Surface/Surface.d.ts +5 -1
- package/lib/module/skia/types/Surface/Surface.js.map +1 -1
- package/lib/module/skia/web/JsiSkParagraphStyle.js +14 -3
- package/lib/module/skia/web/JsiSkParagraphStyle.js.map +1 -1
- package/lib/module/skia/web/JsiSkSurface.d.ts +1 -1
- package/lib/module/skia/web/JsiSkSurface.js +2 -1
- package/lib/module/skia/web/JsiSkSurface.js.map +1 -1
- package/lib/module/sksg/Container.native.d.ts +1 -0
- package/lib/module/sksg/Container.native.js +11 -0
- package/lib/module/sksg/Container.native.js.map +1 -1
- package/lib/module/sksg/Container.web.d.ts +1 -0
- package/lib/module/sksg/Container.web.js +11 -0
- package/lib/module/sksg/Container.web.js.map +1 -1
- package/lib/module/specs/NativeSkiaModule.web.d.ts +2 -0
- package/lib/module/specs/NativeSkiaModule.web.js +32 -7
- package/lib/module/specs/NativeSkiaModule.web.js.map +1 -1
- package/lib/module/specs/SkiaPictureViewNativeComponent.d.ts +1 -0
- package/lib/module/specs/SkiaPictureViewNativeComponent.js.map +1 -1
- package/lib/module/views/SkiaPictureView.js +2 -0
- package/lib/module/views/SkiaPictureView.js.map +1 -1
- package/lib/module/views/SkiaPictureView.web.js +280 -95
- package/lib/module/views/SkiaPictureView.web.js.map +1 -1
- package/lib/module/views/formats.d.ts +1 -0
- package/lib/module/views/formats.js +22 -0
- package/lib/module/views/formats.js.map +1 -0
- package/lib/module/views/index.d.ts +1 -0
- package/lib/module/views/index.js +1 -0
- package/lib/module/views/index.js.map +1 -1
- package/lib/module/views/types.d.ts +6 -0
- package/lib/module/views/types.js.map +1 -1
- package/lib/typescript/lib/commonjs/Platform/Platform.web.d.ts +1 -2
- package/lib/typescript/lib/commonjs/mock/index.d.ts +1 -0
- package/lib/typescript/lib/commonjs/renderer/Canvas.d.ts +2 -1
- package/lib/typescript/lib/commonjs/skia/web/JsiSkSurface.d.ts +1 -1
- package/lib/typescript/lib/commonjs/sksg/Container.native.d.ts +1 -1
- package/lib/typescript/lib/commonjs/sksg/Container.web.d.ts +1 -1
- package/lib/typescript/lib/commonjs/views/formats.d.ts +2 -0
- package/lib/typescript/lib/module/Platform/Platform.web.d.ts +1 -3
- package/lib/typescript/lib/module/mock/index.d.ts +2 -2
- package/lib/typescript/lib/module/renderer/Canvas.d.ts +2 -1
- package/lib/typescript/lib/module/skia/web/JsiSkSurface.d.ts +1 -1
- package/lib/typescript/lib/module/sksg/Container.native.d.ts +1 -1
- package/lib/typescript/lib/module/sksg/Container.web.d.ts +1 -1
- package/lib/typescript/lib/module/views/formats.d.ts +1 -0
- package/lib/typescript/lib/module/views/index.d.ts +1 -0
- package/lib/typescript/src/renderer/Canvas.d.ts +10 -1
- package/lib/typescript/src/skia/types/Surface/Surface.d.ts +5 -1
- package/lib/typescript/src/skia/web/JsiSkSurface.d.ts +1 -1
- package/lib/typescript/src/sksg/Container.native.d.ts +1 -0
- package/lib/typescript/src/sksg/Container.web.d.ts +1 -0
- package/lib/typescript/src/specs/NativeSkiaModule.web.d.ts +2 -0
- package/lib/typescript/src/specs/SkiaPictureViewNativeComponent.d.ts +1 -0
- package/lib/typescript/src/views/formats.d.ts +1 -0
- package/lib/typescript/src/views/index.d.ts +1 -0
- package/lib/typescript/src/views/types.d.ts +6 -0
- package/package.json +4 -1
- package/react-native-skia.podspec +1 -0
- package/src/Platform/Platform.web.tsx +7 -99
- package/src/mock/index.ts +1 -0
- package/src/renderer/Canvas.tsx +11 -0
- package/src/skia/types/Surface/Surface.ts +5 -1
- package/src/skia/web/JsiSkParagraphStyle.ts +16 -2
- package/src/skia/web/JsiSkSurface.ts +2 -1
- package/src/sksg/Container.native.ts +12 -0
- package/src/sksg/Container.web.ts +12 -0
- package/src/specs/NativeSkiaModule.web.ts +39 -7
- package/src/specs/SkiaPictureViewNativeComponent.ts +1 -0
- package/src/views/SkiaPictureView.tsx +2 -0
- package/src/views/SkiaPictureView.web.tsx +318 -106
- package/src/views/formats.ts +21 -0
- package/src/views/index.ts +1 -0
- package/src/views/types.ts +7 -0
|
@@ -1,104 +1,16 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import React, {
|
|
3
|
-
import type {
|
|
1
|
+
import type { CSSProperties } from "react";
|
|
2
|
+
import React, { useMemo } from "react";
|
|
3
|
+
import type { ViewComponent, ViewProps } from "react-native";
|
|
4
4
|
|
|
5
5
|
import type { DataModule } from "../skia/types";
|
|
6
6
|
import { isRNModule } from "../skia/types";
|
|
7
7
|
|
|
8
8
|
import type { IPlatform } from "./IPlatform";
|
|
9
9
|
|
|
10
|
-
//
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
type Div = HTMLDivElement & {
|
|
14
|
-
__reactLayoutHandler: OnLayout;
|
|
15
|
-
};
|
|
16
|
-
|
|
17
|
-
let resizeObserver: ResizeObserver | null = null;
|
|
18
|
-
|
|
19
|
-
const getObserver = () => {
|
|
20
|
-
if (resizeObserver == null) {
|
|
21
|
-
resizeObserver = new window.ResizeObserver(function (entries) {
|
|
22
|
-
entries.forEach((entry) => {
|
|
23
|
-
const node = entry.target as Div;
|
|
24
|
-
const { left, top, width, height } = entry.contentRect;
|
|
25
|
-
const onLayout = node[DOM_LAYOUT_HANDLER_NAME];
|
|
26
|
-
if (typeof onLayout === "function") {
|
|
27
|
-
// setTimeout 0 is taken from react-native-web (UIManager)
|
|
28
|
-
setTimeout(
|
|
29
|
-
() =>
|
|
30
|
-
onLayout({
|
|
31
|
-
timeStamp: Date.now(),
|
|
32
|
-
nativeEvent: { layout: { x: left, y: top, width, height } },
|
|
33
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
34
|
-
// @ts-expect-error
|
|
35
|
-
currentTarget: 0,
|
|
36
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
37
|
-
// @ts-expect-error
|
|
38
|
-
target: 0,
|
|
39
|
-
bubbles: false,
|
|
40
|
-
cancelable: false,
|
|
41
|
-
defaultPrevented: false,
|
|
42
|
-
eventPhase: 0,
|
|
43
|
-
isDefaultPrevented() {
|
|
44
|
-
throw new Error("Method not supported on web.");
|
|
45
|
-
},
|
|
46
|
-
isPropagationStopped() {
|
|
47
|
-
throw new Error("Method not supported on web.");
|
|
48
|
-
},
|
|
49
|
-
persist() {
|
|
50
|
-
throw new Error("Method not supported on web.");
|
|
51
|
-
},
|
|
52
|
-
preventDefault() {
|
|
53
|
-
throw new Error("Method not supported on web.");
|
|
54
|
-
},
|
|
55
|
-
stopPropagation() {
|
|
56
|
-
throw new Error("Method not supported on web.");
|
|
57
|
-
},
|
|
58
|
-
isTrusted: true,
|
|
59
|
-
type: "",
|
|
60
|
-
}),
|
|
61
|
-
0
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
return resizeObserver;
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const useElementLayout = (ref: RefObject<Div>, onLayout: OnLayout) => {
|
|
71
|
-
const observer = getObserver();
|
|
72
|
-
|
|
73
|
-
useLayoutEffect(() => {
|
|
74
|
-
const node = ref.current;
|
|
75
|
-
if (node !== null) {
|
|
76
|
-
node[DOM_LAYOUT_HANDLER_NAME] = onLayout;
|
|
77
|
-
}
|
|
78
|
-
}, [ref, onLayout]);
|
|
79
|
-
|
|
80
|
-
useLayoutEffect(() => {
|
|
81
|
-
const node = ref.current;
|
|
82
|
-
if (node != null && observer != null) {
|
|
83
|
-
if (typeof node[DOM_LAYOUT_HANDLER_NAME] === "function") {
|
|
84
|
-
observer.observe(node);
|
|
85
|
-
} else {
|
|
86
|
-
observer.unobserve(node);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
return () => {
|
|
90
|
-
if (node != null && observer != null) {
|
|
91
|
-
observer.unobserve(node);
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
}, [observer, ref]);
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
const View = (({ children, onLayout, style: rawStyle }: ViewProps) => {
|
|
10
|
+
// Layout is observed by the views themselves (see SkiaPictureView.web.tsx):
|
|
11
|
+
// this shim only reproduces react-native-web's default View styling.
|
|
12
|
+
const View = (({ children, style: rawStyle }: ViewProps) => {
|
|
98
13
|
const style = useMemo(() => (rawStyle ?? {}) as CSSProperties, [rawStyle]);
|
|
99
|
-
const ref = useRef<Div>(null);
|
|
100
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
101
|
-
useElementLayout(ref as any, onLayout);
|
|
102
14
|
const cssStyles = useMemo(() => {
|
|
103
15
|
return {
|
|
104
16
|
alignItems: "stretch" as const,
|
|
@@ -121,11 +33,7 @@ const View = (({ children, onLayout, style: rawStyle }: ViewProps) => {
|
|
|
121
33
|
};
|
|
122
34
|
}, [style]);
|
|
123
35
|
|
|
124
|
-
return
|
|
125
|
-
<div ref={ref} style={cssStyles}>
|
|
126
|
-
{children}
|
|
127
|
-
</div>
|
|
128
|
-
);
|
|
36
|
+
return <div style={cssStyles}>{children}</div>;
|
|
129
37
|
}) as unknown as typeof ViewComponent;
|
|
130
38
|
|
|
131
39
|
export const Platform: IPlatform = {
|
package/src/mock/index.ts
CHANGED
|
@@ -24,6 +24,7 @@ export const Mock = (CanvasKit: CanvasKit) => {
|
|
|
24
24
|
...require("../dom/nodes"),
|
|
25
25
|
Canvas: require("react-native").View,
|
|
26
26
|
WebGPUCanvas: require("react-native").View,
|
|
27
|
+
getPreferredHighBitDepthCanvasFormat: () => "rgba16float",
|
|
27
28
|
SkiaPictureView: require("react-native").View,
|
|
28
29
|
JsiSkImage: JsiSkImage,
|
|
29
30
|
drawAsPicture: Noop,
|
package/src/renderer/Canvas.tsx
CHANGED
|
@@ -69,6 +69,15 @@ export interface CanvasProps extends Omit<ViewProps, "onLayout"> {
|
|
|
69
69
|
opaque?: boolean;
|
|
70
70
|
onSize?: SharedValue<SkSize>;
|
|
71
71
|
colorSpace?: "p3" | "srgb";
|
|
72
|
+
/**
|
|
73
|
+
* Renders into a surface with more than 8 bits per channel (16-bit float on
|
|
74
|
+
* iOS, 10-bit on Android) to avoid banding in subtle gradients. Colors are
|
|
75
|
+
* identical to the default 8-bit surface, only with more precision (this is
|
|
76
|
+
* about bit depth, not HDR). On Android the extra precision survives
|
|
77
|
+
* composition only when combined with `opaque`, and the prop must be set
|
|
78
|
+
* before the canvas is mounted.
|
|
79
|
+
*/
|
|
80
|
+
highBitDepth?: boolean;
|
|
72
81
|
ref?: React.Ref<CanvasRef>;
|
|
73
82
|
androidWarmup?: boolean;
|
|
74
83
|
__destroyWebGLContextAfterRender?: boolean;
|
|
@@ -80,6 +89,7 @@ export const Canvas = ({
|
|
|
80
89
|
children,
|
|
81
90
|
onSize,
|
|
82
91
|
colorSpace = "p3",
|
|
92
|
+
highBitDepth = false,
|
|
83
93
|
androidWarmup = false,
|
|
84
94
|
ref,
|
|
85
95
|
onLayout,
|
|
@@ -180,6 +190,7 @@ export const Canvas = ({
|
|
|
180
190
|
debug={debug}
|
|
181
191
|
opaque={opaque}
|
|
182
192
|
colorSpace={colorSpace}
|
|
193
|
+
highBitDepth={highBitDepth}
|
|
183
194
|
androidWarmup={androidWarmup}
|
|
184
195
|
onLayout={
|
|
185
196
|
Platform.OS === "web" && (onSize || onLayout) ? onLayoutWeb : onLayout
|
|
@@ -39,8 +39,12 @@ export interface SkSurface extends SkJSIInstance<"Surface"> {
|
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
41
|
* Make sure any queued draws are sent to the screen or the GPU.
|
|
42
|
+
* @param sync - When true, block until the GPU has finished executing the
|
|
43
|
+
* submitted work. Use this before reading the surface's texture from a native
|
|
44
|
+
* consumer on a different command queue (see {@link getNativeTextureUnstable}).
|
|
45
|
+
* Defaults to false.
|
|
42
46
|
*/
|
|
43
|
-
flush(): void;
|
|
47
|
+
flush(sync?: boolean): void;
|
|
44
48
|
|
|
45
49
|
/**
|
|
46
50
|
* Returns the possibly scaled width of the surface.
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import type { CanvasKit, ParagraphStyle } from "canvaskit-wasm";
|
|
1
|
+
import type { CanvasKit, ParagraphStyle, TextStyle } from "canvaskit-wasm";
|
|
2
2
|
|
|
3
3
|
import { TextDirection } from "../types";
|
|
4
4
|
import type { SkParagraphStyle } from "../types";
|
|
5
5
|
|
|
6
|
+
import { JsiSkTextStyle } from "./JsiSkTextStyle";
|
|
7
|
+
|
|
6
8
|
export class JsiSkParagraphStyle {
|
|
7
9
|
static toParagraphStyle(
|
|
8
10
|
ck: CanvasKit,
|
|
@@ -10,7 +12,19 @@ export class JsiSkParagraphStyle {
|
|
|
10
12
|
): ParagraphStyle {
|
|
11
13
|
// Seems like we need to provide the textStyle.color value, otherwise
|
|
12
14
|
// the constructor crashes.
|
|
13
|
-
const
|
|
15
|
+
const textStyle: TextStyle = { color: ck.BLACK };
|
|
16
|
+
if (value.textStyle) {
|
|
17
|
+
// Only merge the properties that are set; toTextStyle() emits undefined
|
|
18
|
+
// for the others and the ParagraphStyle constructor requires a color.
|
|
19
|
+
Object.entries(JsiSkTextStyle.toTextStyle(value.textStyle)).forEach(
|
|
20
|
+
([key, v]) => {
|
|
21
|
+
if (v !== undefined) {
|
|
22
|
+
(textStyle as Record<string, unknown>)[key] = v;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
const ps = new ck.ParagraphStyle({ textStyle });
|
|
14
28
|
|
|
15
29
|
ps.disableHinting = value.disableHinting ?? ps.disableHinting;
|
|
16
30
|
ps.ellipsis = value.ellipsis ?? ps.ellipsis;
|
|
@@ -39,9 +39,21 @@ class NativeReanimatedContainer extends Container {
|
|
|
39
39
|
this.picture = Skia.Picture.MakePicture(null)!;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
unmount() {
|
|
43
|
+
super.unmount();
|
|
44
|
+
if (this.mapperId !== null) {
|
|
45
|
+
// The mapper closure retains the recorder and its resources (e.g.
|
|
46
|
+
// images) on the UI runtime and keeps updating the picture of an
|
|
47
|
+
// unmounted view — stop it or it leaks for the lifetime of the app.
|
|
48
|
+
Rea.stopMapper(this.mapperId);
|
|
49
|
+
this.mapperId = null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
42
53
|
redraw() {
|
|
43
54
|
if (this.mapperId !== null) {
|
|
44
55
|
Rea.stopMapper(this.mapperId);
|
|
56
|
+
this.mapperId = null;
|
|
45
57
|
}
|
|
46
58
|
if (this.unmounted) {
|
|
47
59
|
return;
|
|
@@ -40,9 +40,21 @@ class ReanimatedContainer extends Container {
|
|
|
40
40
|
super(Skia);
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
unmount() {
|
|
44
|
+
super.unmount();
|
|
45
|
+
if (this.mapperId !== null) {
|
|
46
|
+
// The mapper closure retains the recording and keeps updating the
|
|
47
|
+
// picture of an unmounted view — stop it or it leaks for the
|
|
48
|
+
// lifetime of the app.
|
|
49
|
+
Rea.stopMapper(this.mapperId);
|
|
50
|
+
this.mapperId = null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
43
54
|
redraw() {
|
|
44
55
|
if (this.mapperId !== null) {
|
|
45
56
|
Rea.stopMapper(this.mapperId);
|
|
57
|
+
this.mapperId = null;
|
|
46
58
|
}
|
|
47
59
|
if (this.unmounted) {
|
|
48
60
|
return;
|
|
@@ -6,29 +6,45 @@ import type { SkiaPictureViewHandle } from "../views/SkiaPictureView.web";
|
|
|
6
6
|
export type ISkiaViewApiWeb = ISkiaViewApi & {
|
|
7
7
|
views: Record<string, SkiaPictureViewHandle>;
|
|
8
8
|
deferedPictures: Record<string, SkPicture>;
|
|
9
|
+
unregisteredViews: Set<string>;
|
|
9
10
|
registerView(nativeId: string, view: SkiaPictureViewHandle): void;
|
|
11
|
+
unregisterView(nativeId: string): void;
|
|
10
12
|
};
|
|
11
13
|
|
|
12
14
|
global.SkiaViewApi = {
|
|
13
15
|
views: {},
|
|
14
16
|
deferedPictures: {},
|
|
17
|
+
unregisteredViews: new Set<string>(),
|
|
15
18
|
deferedOnSize: {},
|
|
16
19
|
web: true,
|
|
17
20
|
registerView(nativeId: string, view: SkiaPictureViewHandle) {
|
|
21
|
+
this.unregisteredViews.delete(nativeId);
|
|
18
22
|
// Maybe a picture for this view was already set
|
|
19
23
|
if (this.deferedPictures[nativeId]) {
|
|
20
24
|
view.setPicture(this.deferedPictures[nativeId] as SkPicture);
|
|
25
|
+
delete this.deferedPictures[nativeId];
|
|
21
26
|
}
|
|
22
27
|
this.views[nativeId] = view;
|
|
23
28
|
},
|
|
29
|
+
unregisterView(nativeId: string) {
|
|
30
|
+
// Views must be removed on unmount: the handle's closures capture the
|
|
31
|
+
// canvas element, so a stale entry retains the whole detached DOM tree.
|
|
32
|
+
this.unregisteredViews.add(nativeId);
|
|
33
|
+
delete this.views[nativeId];
|
|
34
|
+
delete this.deferedPictures[nativeId];
|
|
35
|
+
},
|
|
24
36
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
25
37
|
setJsiProperty(nativeId: number, name: string, value: any) {
|
|
26
38
|
if (name === "picture") {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
39
|
+
const id = `${nativeId}`;
|
|
40
|
+
if (this.views[id]) {
|
|
41
|
+
this.views[id].setPicture(value);
|
|
42
|
+
} else if (!this.unregisteredViews.has(id)) {
|
|
43
|
+
this.deferedPictures[id] = value;
|
|
31
44
|
}
|
|
45
|
+
// Otherwise the view has unmounted (e.g. a trailing animation frame):
|
|
46
|
+
// drop the picture instead of deferring it for an id that will never
|
|
47
|
+
// register again, which would retain it forever.
|
|
32
48
|
}
|
|
33
49
|
},
|
|
34
50
|
size(nativeId: number) {
|
|
@@ -39,14 +55,30 @@ global.SkiaViewApi = {
|
|
|
39
55
|
}
|
|
40
56
|
},
|
|
41
57
|
requestRedraw(nativeId: number) {
|
|
42
|
-
|
|
58
|
+
// The view may already have unmounted (e.g. a trailing animation frame).
|
|
59
|
+
this.views[`${nativeId}`]?.redraw();
|
|
43
60
|
},
|
|
44
61
|
makeImageSnapshot(nativeId: number, rect?: SkRect) {
|
|
45
|
-
|
|
62
|
+
const view = this.views[`${nativeId}`];
|
|
63
|
+
if (!view) {
|
|
64
|
+
throw new Error(
|
|
65
|
+
`Cannot make image snapshot: view with nativeID ${nativeId} is not registered (it may have unmounted)`
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
return view.makeImageSnapshot(rect);
|
|
46
69
|
},
|
|
47
70
|
makeImageSnapshotAsync(nativeId: number, rect?: SkRect) {
|
|
48
71
|
return new Promise((resolve, reject) => {
|
|
49
|
-
const
|
|
72
|
+
const view = this.views[`${nativeId}`];
|
|
73
|
+
if (!view) {
|
|
74
|
+
reject(
|
|
75
|
+
new Error(
|
|
76
|
+
`Cannot make image snapshot: view with nativeID ${nativeId} is not registered (it may have unmounted)`
|
|
77
|
+
)
|
|
78
|
+
);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const result = view.makeImageSnapshot(rect);
|
|
50
82
|
if (result) {
|
|
51
83
|
resolve(result);
|
|
52
84
|
} else {
|
|
@@ -87,6 +87,7 @@ export class SkiaPictureView extends React.Component<SkiaPictureViewProps> {
|
|
|
87
87
|
mode,
|
|
88
88
|
debug = false,
|
|
89
89
|
opaque = false,
|
|
90
|
+
highBitDepth = false,
|
|
90
91
|
androidWarmup = false,
|
|
91
92
|
...viewProps
|
|
92
93
|
} = this.props;
|
|
@@ -96,6 +97,7 @@ export class SkiaPictureView extends React.Component<SkiaPictureViewProps> {
|
|
|
96
97
|
nativeID={`${this._nativeId}`}
|
|
97
98
|
debug={debug}
|
|
98
99
|
opaque={opaque}
|
|
100
|
+
highBitDepth={highBitDepth}
|
|
99
101
|
androidWarmup={androidWarmup}
|
|
100
102
|
{...viewProps}
|
|
101
103
|
/>
|