@shopify/react-native-skia 2.6.9 → 2.8.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 +10 -1
- 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/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/JsiSkParagraph.h +114 -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/external/reanimated/useVideoLoading.js +11 -2
- package/lib/commonjs/external/reanimated/useVideoLoading.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/core/SVG.web.js +4 -5
- package/lib/commonjs/skia/core/SVG.web.js.map +1 -1
- package/lib/commonjs/skia/types/Paragraph/Paragraph.d.ts +62 -0
- package/lib/commonjs/skia/types/Paragraph/Paragraph.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/Host.js +7 -0
- package/lib/commonjs/skia/web/Host.js.map +1 -1
- package/lib/commonjs/skia/web/JsiSkPaint.js +5 -0
- package/lib/commonjs/skia/web/JsiSkPaint.js.map +1 -1
- package/lib/commonjs/skia/web/JsiSkParagraph.d.ts +3 -1
- package/lib/commonjs/skia/web/JsiSkParagraph.js +6 -0
- package/lib/commonjs/skia/web/JsiSkParagraph.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 +45 -3
- package/lib/commonjs/sksg/Container.web.js.map +1 -1
- package/lib/commonjs/sksg/Recorder/DrawingContext.d.ts +2 -0
- package/lib/commonjs/sksg/Recorder/DrawingContext.js +22 -6
- package/lib/commonjs/sksg/Recorder/DrawingContext.js.map +1 -1
- package/lib/commonjs/sksg/Recorder/FrameScope.d.ts +18 -0
- package/lib/commonjs/sksg/Recorder/FrameScope.js +66 -0
- package/lib/commonjs/sksg/Recorder/FrameScope.js.map +1 -0
- package/lib/commonjs/sksg/Recorder/FrameScope.native.d.ts +10 -0
- package/lib/commonjs/sksg/Recorder/FrameScope.native.js +26 -0
- package/lib/commonjs/sksg/Recorder/FrameScope.native.js.map +1 -0
- package/lib/commonjs/sksg/Recorder/Player.js +1 -2
- package/lib/commonjs/sksg/Recorder/Player.js.map +1 -1
- package/lib/commonjs/sksg/Recorder/Recorder.d.ts +3 -1
- package/lib/commonjs/sksg/Recorder/Recorder.js +12 -1
- package/lib/commonjs/sksg/Recorder/Recorder.js.map +1 -1
- package/lib/commonjs/sksg/Recorder/commands/Drawing.js +3 -3
- package/lib/commonjs/sksg/Recorder/commands/Drawing.js.map +1 -1
- package/lib/commonjs/sksg/Recorder/commands/Shaders.js +3 -3
- package/lib/commonjs/sksg/Recorder/commands/Shaders.js.map +1 -1
- package/lib/commonjs/sksg/StaticContainer.d.ts +1 -0
- package/lib/commonjs/sksg/StaticContainer.js +27 -1
- package/lib/commonjs/sksg/StaticContainer.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/external/reanimated/useVideoLoading.js +12 -2
- package/lib/module/external/reanimated/useVideoLoading.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/core/SVG.web.js +4 -5
- package/lib/module/skia/core/SVG.web.js.map +1 -1
- package/lib/module/skia/types/Paragraph/Paragraph.d.ts +62 -0
- package/lib/module/skia/types/Paragraph/Paragraph.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/Host.js +7 -0
- package/lib/module/skia/web/Host.js.map +1 -1
- package/lib/module/skia/web/JsiSkPaint.js +5 -0
- package/lib/module/skia/web/JsiSkPaint.js.map +1 -1
- package/lib/module/skia/web/JsiSkParagraph.d.ts +3 -1
- package/lib/module/skia/web/JsiSkParagraph.js +7 -1
- package/lib/module/skia/web/JsiSkParagraph.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 +46 -4
- package/lib/module/sksg/Container.web.js.map +1 -1
- package/lib/module/sksg/Recorder/DrawingContext.d.ts +2 -0
- package/lib/module/sksg/Recorder/DrawingContext.js +22 -6
- package/lib/module/sksg/Recorder/DrawingContext.js.map +1 -1
- package/lib/module/sksg/Recorder/FrameScope.d.ts +18 -0
- package/lib/module/sksg/Recorder/FrameScope.js +59 -0
- package/lib/module/sksg/Recorder/FrameScope.js.map +1 -0
- package/lib/module/sksg/Recorder/FrameScope.native.d.ts +10 -0
- package/lib/module/sksg/Recorder/FrameScope.native.js +19 -0
- package/lib/module/sksg/Recorder/FrameScope.native.js.map +1 -0
- package/lib/module/sksg/Recorder/Player.js +1 -2
- package/lib/module/sksg/Recorder/Player.js.map +1 -1
- package/lib/module/sksg/Recorder/Recorder.d.ts +3 -1
- package/lib/module/sksg/Recorder/Recorder.js +10 -0
- package/lib/module/sksg/Recorder/Recorder.js.map +1 -1
- package/lib/module/sksg/Recorder/commands/Drawing.js +3 -3
- package/lib/module/sksg/Recorder/commands/Drawing.js.map +1 -1
- package/lib/module/sksg/Recorder/commands/Shaders.js +3 -3
- package/lib/module/sksg/Recorder/commands/Shaders.js.map +1 -1
- package/lib/module/sksg/StaticContainer.d.ts +1 -0
- package/lib/module/sksg/StaticContainer.js +28 -2
- package/lib/module/sksg/StaticContainer.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/JsiSkParagraph.d.ts +2 -0
- 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 +3 -3
- package/lib/typescript/lib/commonjs/sksg/Recorder/DrawingContext.d.ts +2 -0
- package/lib/typescript/lib/commonjs/sksg/Recorder/FrameScope.d.ts +17 -0
- package/lib/typescript/lib/commonjs/sksg/Recorder/FrameScope.native.d.ts +13 -0
- package/lib/typescript/lib/commonjs/sksg/Recorder/Recorder.d.ts +1 -0
- package/lib/typescript/lib/commonjs/sksg/StaticContainer.d.ts +2 -2
- 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/JsiSkParagraph.d.ts +2 -0
- 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 +3 -3
- package/lib/typescript/lib/module/sksg/Recorder/DrawingContext.d.ts +2 -0
- package/lib/typescript/lib/module/sksg/Recorder/FrameScope.d.ts +5 -0
- package/lib/typescript/lib/module/sksg/Recorder/FrameScope.native.d.ts +5 -0
- package/lib/typescript/lib/module/sksg/Recorder/Recorder.d.ts +1 -0
- package/lib/typescript/lib/module/sksg/StaticContainer.d.ts +2 -2
- 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/Paragraph/Paragraph.d.ts +62 -0
- package/lib/typescript/src/skia/types/Surface/Surface.d.ts +5 -1
- package/lib/typescript/src/skia/web/JsiSkParagraph.d.ts +3 -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/sksg/Recorder/DrawingContext.d.ts +2 -0
- package/lib/typescript/src/sksg/Recorder/FrameScope.d.ts +18 -0
- package/lib/typescript/src/sksg/Recorder/FrameScope.native.d.ts +10 -0
- package/lib/typescript/src/sksg/Recorder/Recorder.d.ts +3 -1
- package/lib/typescript/src/sksg/StaticContainer.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/external/reanimated/useVideoLoading.ts +12 -2
- package/src/mock/index.ts +1 -0
- package/src/renderer/Canvas.tsx +11 -0
- package/src/skia/core/SVG.web.ts +5 -14
- package/src/skia/types/Paragraph/Paragraph.ts +67 -0
- package/src/skia/types/Surface/Surface.ts +5 -1
- package/src/skia/web/Host.ts +7 -0
- package/src/skia/web/JsiSkPaint.ts +5 -0
- package/src/skia/web/JsiSkParagraph.ts +9 -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 +43 -4
- package/src/sksg/Recorder/DrawingContext.ts +19 -6
- package/src/sksg/Recorder/FrameScope.native.ts +21 -0
- package/src/sksg/Recorder/FrameScope.ts +69 -0
- package/src/sksg/Recorder/Player.ts +1 -2
- package/src/sksg/Recorder/Recorder.ts +15 -1
- package/src/sksg/Recorder/commands/Drawing.ts +3 -3
- package/src/sksg/Recorder/commands/Shaders.ts +22 -16
- package/src/sksg/StaticContainer.ts +29 -2
- 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
|
@@ -4,10 +4,12 @@ import type {
|
|
|
4
4
|
SkRect,
|
|
5
5
|
SkRectWithDirection,
|
|
6
6
|
SkParagraph,
|
|
7
|
+
SkPath,
|
|
7
8
|
LineMetrics,
|
|
9
|
+
ParagraphExtendedVisitor,
|
|
8
10
|
} from "../types";
|
|
9
11
|
|
|
10
|
-
import { HostObject } from "./Host";
|
|
12
|
+
import { HostObject, throwNotImplementedOnRNWeb } from "./Host";
|
|
11
13
|
import type { JsiSkCanvas } from "./JsiSkCanvas";
|
|
12
14
|
import { JsiSkRect } from "./JsiSkRect";
|
|
13
15
|
|
|
@@ -64,4 +66,10 @@ export class JsiSkParagraph
|
|
|
64
66
|
getLineMetrics(): LineMetrics[] {
|
|
65
67
|
return this.ref.getLineMetrics();
|
|
66
68
|
}
|
|
69
|
+
getPath(_lineNumber: number): SkPath | null {
|
|
70
|
+
return throwNotImplementedOnRNWeb<SkPath | null>();
|
|
71
|
+
}
|
|
72
|
+
extendedVisit(_visitor: ParagraphExtendedVisitor): void {
|
|
73
|
+
return throwNotImplementedOnRNWeb<void>();
|
|
74
|
+
}
|
|
67
75
|
}
|
|
@@ -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;
|
|
@@ -3,7 +3,7 @@ import type { Skia } from "../skia/types";
|
|
|
3
3
|
import { HAS_REANIMATED_3 } from "../external/reanimated/renderHelpers";
|
|
4
4
|
|
|
5
5
|
import type { Recording } from "./Recorder/Recorder";
|
|
6
|
-
import { Recorder } from "./Recorder/Recorder";
|
|
6
|
+
import { Recorder, disposeRecording } from "./Recorder/Recorder";
|
|
7
7
|
import { visit } from "./Recorder/Visitor";
|
|
8
8
|
import { replay } from "./Recorder/Player";
|
|
9
9
|
import { createDrawingContext } from "./Recorder/DrawingContext";
|
|
@@ -22,12 +22,24 @@ const drawOnscreen = (Skia: Skia, nativeId: number, recording: Recording) => {
|
|
|
22
22
|
//const start = performance.now();
|
|
23
23
|
|
|
24
24
|
const ctx = createDrawingContext(Skia, recording.paintPool, canvas);
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
let picture;
|
|
26
|
+
try {
|
|
27
|
+
replay(ctx, recording.commands);
|
|
28
|
+
picture = rec.finishRecordingAsPicture();
|
|
29
|
+
} finally {
|
|
30
|
+
// Frame-scoped objects (shaders, filters, paint copies, ...) are
|
|
31
|
+
// referenced by the picture once it is finished — delete the JS handles,
|
|
32
|
+
// otherwise they leak on Web where the GC cannot see WASM memory.
|
|
33
|
+
ctx.dispose();
|
|
34
|
+
rec.dispose();
|
|
35
|
+
}
|
|
28
36
|
//const end = performance.now();
|
|
29
37
|
//console.log("Recording time: ", end - start);
|
|
30
38
|
SkiaViewApi.setJsiProperty(nativeId, "picture", picture);
|
|
39
|
+
// The view now references the new picture; the previous one is ours to
|
|
40
|
+
// delete.
|
|
41
|
+
recording.lastPicture?.dispose();
|
|
42
|
+
recording.lastPicture = picture;
|
|
31
43
|
};
|
|
32
44
|
|
|
33
45
|
class ReanimatedContainer extends Container {
|
|
@@ -40,13 +52,36 @@ class ReanimatedContainer extends Container {
|
|
|
40
52
|
super(Skia);
|
|
41
53
|
}
|
|
42
54
|
|
|
55
|
+
unmount() {
|
|
56
|
+
super.unmount();
|
|
57
|
+
if (this.mapperId !== null) {
|
|
58
|
+
// The mapper closure retains the recording and keeps updating the
|
|
59
|
+
// picture of an unmounted view — stop it or it leaks for the
|
|
60
|
+
// lifetime of the app.
|
|
61
|
+
Rea.stopMapper(this.mapperId);
|
|
62
|
+
this.mapperId = null;
|
|
63
|
+
}
|
|
64
|
+
const { recording } = this;
|
|
65
|
+
if (recording) {
|
|
66
|
+
this.recording = null;
|
|
67
|
+
// Deferred through the same channel as the draw calls so it runs after
|
|
68
|
+
// any of them that are still queued.
|
|
69
|
+
Rea.runOnUI(() => {
|
|
70
|
+
"worklet";
|
|
71
|
+
disposeRecording(recording);
|
|
72
|
+
})();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
43
76
|
redraw() {
|
|
44
77
|
if (this.mapperId !== null) {
|
|
45
78
|
Rea.stopMapper(this.mapperId);
|
|
79
|
+
this.mapperId = null;
|
|
46
80
|
}
|
|
47
81
|
if (this.unmounted) {
|
|
48
82
|
return;
|
|
49
83
|
}
|
|
84
|
+
const previousRecording = this.recording;
|
|
50
85
|
const recorder = new Recorder();
|
|
51
86
|
visit(recorder, this.root);
|
|
52
87
|
const record = recorder.getRecording();
|
|
@@ -64,6 +99,10 @@ class ReanimatedContainer extends Container {
|
|
|
64
99
|
}
|
|
65
100
|
Rea.runOnUI(() => {
|
|
66
101
|
"worklet";
|
|
102
|
+
if (previousRecording) {
|
|
103
|
+
// Runs after any still-queued draw of the previous recording.
|
|
104
|
+
disposeRecording(previousRecording);
|
|
105
|
+
}
|
|
67
106
|
drawOnscreen(Skia, nativeId, recording!);
|
|
68
107
|
})();
|
|
69
108
|
}
|
|
@@ -8,6 +8,8 @@ import type {
|
|
|
8
8
|
SkPathEffect,
|
|
9
9
|
} from "../../skia/types";
|
|
10
10
|
|
|
11
|
+
import { createFrameScope } from "./FrameScope";
|
|
12
|
+
|
|
11
13
|
export const createDrawingContext = (
|
|
12
14
|
Skia: Skia,
|
|
13
15
|
paintPool: SkPaint[],
|
|
@@ -15,6 +17,11 @@ export const createDrawingContext = (
|
|
|
15
17
|
) => {
|
|
16
18
|
"worklet";
|
|
17
19
|
|
|
20
|
+
// Everything the renderer creates through frameSkia is frame-scoped and
|
|
21
|
+
// deleted by dispose() once the frame has been recorded. The paint pool is
|
|
22
|
+
// recording-scoped and deliberately allocated with the raw Skia instance.
|
|
23
|
+
const { Skia: frameSkia, track, dispose } = createFrameScope(Skia);
|
|
24
|
+
|
|
18
25
|
// State (formerly class fields)
|
|
19
26
|
const paints: SkPaint[] = [];
|
|
20
27
|
const colorFilters: SkColorFilter[] = [];
|
|
@@ -27,7 +34,11 @@ export const createDrawingContext = (
|
|
|
27
34
|
let nextPaintIndex = 1;
|
|
28
35
|
|
|
29
36
|
// Initialize first paint and opacity
|
|
30
|
-
paintPool
|
|
37
|
+
if (paintPool.length === 0) {
|
|
38
|
+
paintPool.push(Skia.Paint());
|
|
39
|
+
} else {
|
|
40
|
+
paintPool[0].reset();
|
|
41
|
+
}
|
|
31
42
|
paints.push(paintPool[0]);
|
|
32
43
|
opacities.push(1);
|
|
33
44
|
|
|
@@ -61,7 +72,7 @@ export const createDrawingContext = (
|
|
|
61
72
|
} else {
|
|
62
73
|
const cf = colorFilters.pop();
|
|
63
74
|
if (cf) {
|
|
64
|
-
imageFilter =
|
|
75
|
+
imageFilter = frameSkia.ImageFilter.MakeColorFilter(cf, null);
|
|
65
76
|
}
|
|
66
77
|
}
|
|
67
78
|
canvas.saveLayer(undefined, null, imageFilter);
|
|
@@ -83,7 +94,7 @@ export const createDrawingContext = (
|
|
|
83
94
|
if (colorFilters.length > 0) {
|
|
84
95
|
getCurrentPaint().setColorFilter(
|
|
85
96
|
colorFilters.reduceRight((inner, outer) =>
|
|
86
|
-
inner ?
|
|
97
|
+
inner ? frameSkia.ColorFilter.MakeCompose(outer, inner) : outer
|
|
87
98
|
)
|
|
88
99
|
);
|
|
89
100
|
}
|
|
@@ -95,7 +106,7 @@ export const createDrawingContext = (
|
|
|
95
106
|
if (imageFilters.length > 0) {
|
|
96
107
|
getCurrentPaint().setImageFilter(
|
|
97
108
|
imageFilters.reduceRight((inner, outer) =>
|
|
98
|
-
inner ?
|
|
109
|
+
inner ? frameSkia.ImageFilter.MakeCompose(outer, inner) : outer
|
|
99
110
|
)
|
|
100
111
|
);
|
|
101
112
|
}
|
|
@@ -104,7 +115,7 @@ export const createDrawingContext = (
|
|
|
104
115
|
if (pathEffects.length > 0) {
|
|
105
116
|
getCurrentPaint().setPathEffect(
|
|
106
117
|
pathEffects.reduceRight((inner, outer) =>
|
|
107
|
-
inner ?
|
|
118
|
+
inner ? frameSkia.PathEffect.MakeCompose(outer, inner) : outer
|
|
108
119
|
)
|
|
109
120
|
);
|
|
110
121
|
}
|
|
@@ -119,8 +130,10 @@ export const createDrawingContext = (
|
|
|
119
130
|
// Return an object containing the Skia reference, the canvas, and the methods
|
|
120
131
|
return {
|
|
121
132
|
// Public fields
|
|
122
|
-
Skia,
|
|
133
|
+
Skia: frameSkia,
|
|
123
134
|
canvas,
|
|
135
|
+
track,
|
|
136
|
+
dispose,
|
|
124
137
|
paints,
|
|
125
138
|
colorFilters,
|
|
126
139
|
shaders,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Skia } from "../../skia/types";
|
|
2
|
+
|
|
3
|
+
import type { FrameScope } from "./FrameScope";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* No-op on native. The JSI wrappers report the size of the native objects
|
|
7
|
+
* they hold to the garbage collector (setExternalMemoryPressure), so the GC
|
|
8
|
+
* is aware of the real cost of the objects the renderer creates and reclaims
|
|
9
|
+
* them on its own. The tracking scope is only needed on Web, where CanvasKit
|
|
10
|
+
* objects live in WASM memory the GC cannot see (see FrameScope.ts).
|
|
11
|
+
*/
|
|
12
|
+
export const createFrameScope = (Skia: Skia): FrameScope => {
|
|
13
|
+
"worklet";
|
|
14
|
+
return {
|
|
15
|
+
Skia,
|
|
16
|
+
track: <T>(value: T): T => value,
|
|
17
|
+
dispose: () => {
|
|
18
|
+
// nothing to dispose: no objects are tracked on native
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { Skia } from "../../skia/types";
|
|
2
|
+
|
|
3
|
+
interface Disposable {
|
|
4
|
+
dispose: () => void;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
const isDisposable = (value: unknown): value is Disposable => {
|
|
8
|
+
"worklet";
|
|
9
|
+
return (
|
|
10
|
+
value !== null &&
|
|
11
|
+
typeof value === "object" &&
|
|
12
|
+
typeof (value as Disposable).dispose === "function"
|
|
13
|
+
);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export interface FrameScope {
|
|
17
|
+
Skia: Skia;
|
|
18
|
+
track: <T>(value: T) => T;
|
|
19
|
+
dispose: () => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Wraps a Skia instance so that every object created through its factories is
|
|
24
|
+
* collected and deleted when the scope is disposed. The renderer only keeps
|
|
25
|
+
* the objects it creates alive for the duration of a frame: once the frame
|
|
26
|
+
* has been recorded they can be deleted. This is required on Web where
|
|
27
|
+
* CanvasKit objects live in WASM memory that the JS garbage collector does
|
|
28
|
+
* not perceive, so it (almost) never reclaims them on its own.
|
|
29
|
+
*
|
|
30
|
+
* Objects passed in via props are user-owned: they are not created through
|
|
31
|
+
* this facade and are therefore never tracked nor disposed.
|
|
32
|
+
*/
|
|
33
|
+
export const createFrameScope = (Skia: Skia): FrameScope => {
|
|
34
|
+
"worklet";
|
|
35
|
+
const disposables: Disposable[] = [];
|
|
36
|
+
const track = <T>(value: T): T => {
|
|
37
|
+
if (isDisposable(value)) {
|
|
38
|
+
disposables.push(value);
|
|
39
|
+
}
|
|
40
|
+
return value;
|
|
41
|
+
};
|
|
42
|
+
const wrap = <T extends object>(obj: T): T => {
|
|
43
|
+
const cache = new Map<PropertyKey, unknown>();
|
|
44
|
+
return new Proxy(obj, {
|
|
45
|
+
get(target, prop) {
|
|
46
|
+
if (cache.has(prop)) {
|
|
47
|
+
return cache.get(prop);
|
|
48
|
+
}
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
50
|
+
const value = (target as any)[prop];
|
|
51
|
+
let wrapped: unknown = value;
|
|
52
|
+
if (typeof value === "function") {
|
|
53
|
+
wrapped = (...args: unknown[]) => track(value.apply(target, args));
|
|
54
|
+
} else if (value !== null && typeof value === "object") {
|
|
55
|
+
wrapped = wrap(value);
|
|
56
|
+
}
|
|
57
|
+
cache.set(prop, wrapped);
|
|
58
|
+
return wrapped;
|
|
59
|
+
},
|
|
60
|
+
}) as T;
|
|
61
|
+
};
|
|
62
|
+
const dispose = () => {
|
|
63
|
+
for (let i = 0; i < disposables.length; i++) {
|
|
64
|
+
disposables[i].dispose();
|
|
65
|
+
}
|
|
66
|
+
disposables.length = 0;
|
|
67
|
+
};
|
|
68
|
+
return { Skia: wrap(Skia), track, dispose };
|
|
69
|
+
};
|
|
@@ -166,9 +166,8 @@ const play = (ctx: DrawingContext, _command: Command) => {
|
|
|
166
166
|
} else if (isCommand(command, CommandType.RestoreCTM)) {
|
|
167
167
|
ctx.canvas.restore();
|
|
168
168
|
} else {
|
|
169
|
-
// TODO: is a copy needed here?
|
|
170
169
|
// apply opacity to the current paint.
|
|
171
|
-
const paint = ctx.paint.copy();
|
|
170
|
+
const paint = ctx.track(ctx.paint.copy());
|
|
172
171
|
paint.setAlphaf(paint.getAlphaf() * ctx.getOpacity());
|
|
173
172
|
const paints = [paint, ...ctx.paintDeclarations];
|
|
174
173
|
ctx.paintDeclarations = [];
|
|
@@ -32,7 +32,7 @@ import type {
|
|
|
32
32
|
import type { AnimatedProps } from "../../renderer";
|
|
33
33
|
import { isSharedValue } from "../utils";
|
|
34
34
|
import { isColorFilter, isImageFilter, isPathEffect, isShader } from "../Node";
|
|
35
|
-
import type { SkPaint, BaseRecorder } from "../../skia/types";
|
|
35
|
+
import type { SkPaint, SkPicture, BaseRecorder } from "../../skia/types";
|
|
36
36
|
|
|
37
37
|
import { CommandType } from "./Core";
|
|
38
38
|
import type { Command } from "./Core";
|
|
@@ -40,8 +40,22 @@ import type { Command } from "./Core";
|
|
|
40
40
|
export interface Recording {
|
|
41
41
|
commands: Command[];
|
|
42
42
|
paintPool: SkPaint[];
|
|
43
|
+
// Last picture produced from this recording. The view keeps its own
|
|
44
|
+
// reference to the picture it displays, so the renderer owns this one and
|
|
45
|
+
// disposes it when the next frame replaces it or the recording is disposed.
|
|
46
|
+
lastPicture?: SkPicture | null;
|
|
43
47
|
}
|
|
44
48
|
|
|
49
|
+
export const disposeRecording = (recording: Recording) => {
|
|
50
|
+
"worklet";
|
|
51
|
+
recording.paintPool.forEach((paint) => paint.dispose());
|
|
52
|
+
recording.paintPool.length = 0;
|
|
53
|
+
if (recording.lastPicture) {
|
|
54
|
+
recording.lastPicture.dispose();
|
|
55
|
+
recording.lastPicture = null;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
|
|
45
59
|
interface AnimationValues {
|
|
46
60
|
animationValues: Set<SharedValue<unknown>>;
|
|
47
61
|
}
|
|
@@ -131,14 +131,14 @@ export const drawTextPath = (ctx: DrawingContext, props: TextPathProps) => {
|
|
|
131
131
|
const widths = font.getGlyphWidths(ids);
|
|
132
132
|
const rsx: SkRSXform[] = [];
|
|
133
133
|
const meas = ctx.Skia.ContourMeasureIter(path, false, 1);
|
|
134
|
-
let cont = meas.next();
|
|
134
|
+
let cont = ctx.track(meas.next());
|
|
135
135
|
let dist = initialOffset;
|
|
136
136
|
for (let i = 0; i < text.length && cont; i++) {
|
|
137
137
|
const width = widths[i];
|
|
138
138
|
dist += width / 2;
|
|
139
139
|
if (dist > cont.length()) {
|
|
140
140
|
// jump to next contour
|
|
141
|
-
cont = meas.next();
|
|
141
|
+
cont = ctx.track(meas.next());
|
|
142
142
|
if (!cont) {
|
|
143
143
|
// We have come to the end of the path - terminate the string
|
|
144
144
|
// right here.
|
|
@@ -221,7 +221,7 @@ export const drawPath = (ctx: DrawingContext, props: PathProps) => {
|
|
|
221
221
|
if (hasFillType) {
|
|
222
222
|
const builder = ctx.Skia.PathBuilder.MakeFromPath(path);
|
|
223
223
|
builder.setFillType(FillType[enumKey(fillType)]);
|
|
224
|
-
path = builder.build();
|
|
224
|
+
path = ctx.track(builder.build());
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
// Apply stroke using static Path.Stroke
|
|
@@ -43,10 +43,12 @@ const declareShader = (
|
|
|
43
43
|
const { source, uniforms, ...transform } = props;
|
|
44
44
|
const m3 = ctx.Skia.Matrix();
|
|
45
45
|
processTransformProps(m3, transform);
|
|
46
|
-
const shader =
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
46
|
+
const shader = ctx.track(
|
|
47
|
+
source.makeShaderWithChildren(
|
|
48
|
+
processUniforms(source, uniforms),
|
|
49
|
+
ctx.shaders.splice(0, children),
|
|
50
|
+
m3
|
|
51
|
+
)
|
|
50
52
|
);
|
|
51
53
|
ctx.shaders.push(shader);
|
|
52
54
|
};
|
|
@@ -208,20 +210,24 @@ const declareImageShader = (ctx: DrawingContext, props: ImageShaderProps) => {
|
|
|
208
210
|
processTransformProps(lm, imageShaderProps);
|
|
209
211
|
let shader: SkShader;
|
|
210
212
|
if (sampling && isCubicSampling(sampling)) {
|
|
211
|
-
shader =
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
213
|
+
shader = ctx.track(
|
|
214
|
+
image.makeShaderCubic(
|
|
215
|
+
TileMode[enumKey(tx)],
|
|
216
|
+
TileMode[enumKey(ty)],
|
|
217
|
+
sampling.B,
|
|
218
|
+
sampling.C,
|
|
219
|
+
lm
|
|
220
|
+
)
|
|
217
221
|
);
|
|
218
222
|
} else {
|
|
219
|
-
shader =
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
223
|
+
shader = ctx.track(
|
|
224
|
+
image.makeShaderCubic(
|
|
225
|
+
TileMode[enumKey(tx)],
|
|
226
|
+
TileMode[enumKey(ty)],
|
|
227
|
+
sampling?.filter ?? FilterMode.Linear,
|
|
228
|
+
sampling?.mipmap ?? MipmapMode.None,
|
|
229
|
+
lm
|
|
230
|
+
)
|
|
225
231
|
);
|
|
226
232
|
}
|
|
227
233
|
ctx.shaders.push(shader);
|
|
@@ -2,7 +2,7 @@ import type { Skia, SkCanvas } from "../skia/types";
|
|
|
2
2
|
|
|
3
3
|
import type { Node } from "./Node";
|
|
4
4
|
import type { Recording } from "./Recorder/Recorder";
|
|
5
|
-
import { Recorder } from "./Recorder/Recorder";
|
|
5
|
+
import { Recorder, disposeRecording } from "./Recorder/Recorder";
|
|
6
6
|
import { visit } from "./Recorder/Visitor";
|
|
7
7
|
import { replay } from "./Recorder/Player";
|
|
8
8
|
import { createDrawingContext } from "./Recorder/DrawingContext";
|
|
@@ -41,7 +41,14 @@ export abstract class Container {
|
|
|
41
41
|
this.recording.paintPool,
|
|
42
42
|
canvas
|
|
43
43
|
);
|
|
44
|
-
|
|
44
|
+
try {
|
|
45
|
+
replay(ctx, this.recording.commands);
|
|
46
|
+
} finally {
|
|
47
|
+
// Frame-scoped objects created during the replay are no longer needed
|
|
48
|
+
// once drawn — delete them, otherwise they leak on Web where the GC
|
|
49
|
+
// cannot see WASM memory.
|
|
50
|
+
ctx.dispose();
|
|
51
|
+
}
|
|
45
52
|
}
|
|
46
53
|
|
|
47
54
|
abstract redraw(): void;
|
|
@@ -55,7 +62,24 @@ export class StaticContainer extends Container {
|
|
|
55
62
|
super(Skia);
|
|
56
63
|
}
|
|
57
64
|
|
|
65
|
+
unmount() {
|
|
66
|
+
super.unmount();
|
|
67
|
+
if (this.recording) {
|
|
68
|
+
disposeRecording(this.recording);
|
|
69
|
+
this.recording = null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
58
73
|
redraw() {
|
|
74
|
+
if (this.unmounted) {
|
|
75
|
+
// The unmount commit triggers a last redraw — recording it would
|
|
76
|
+
// resurrect a recording for a container that has just disposed it.
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (this.recording) {
|
|
80
|
+
disposeRecording(this.recording);
|
|
81
|
+
this.recording = null;
|
|
82
|
+
}
|
|
59
83
|
const recorder = new Recorder();
|
|
60
84
|
visit(recorder, this.root);
|
|
61
85
|
this.recording = recorder.getRecording();
|
|
@@ -67,6 +91,9 @@ export class StaticContainer extends Container {
|
|
|
67
91
|
const picture = rec.finishRecordingAsPicture();
|
|
68
92
|
rec.dispose();
|
|
69
93
|
SkiaViewApi.setJsiProperty(this.nativeId, "picture", picture);
|
|
94
|
+
// The view keeps its own reference to the picture it displays; this
|
|
95
|
+
// one is renderer-owned and disposed with the recording.
|
|
96
|
+
this.recording.lastPicture = picture;
|
|
70
97
|
}
|
|
71
98
|
}
|
|
72
99
|
}
|
|
@@ -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
|
/>
|