@shopify/react-native-skia 2.2.8 → 2.2.10

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.
Files changed (67) hide show
  1. package/android/build.gradle +0 -11
  2. package/cpp/api/JsiSkParagraph.h +40 -8
  3. package/lib/commonjs/renderer/Canvas.d.ts +1 -0
  4. package/lib/commonjs/renderer/Canvas.js.map +1 -1
  5. package/lib/commonjs/renderer/__tests__/e2e/ParagraphMethods.spec.d.ts +1 -0
  6. package/lib/commonjs/renderer/__tests__/e2e/setup/Paragraph.d.ts +1 -1
  7. package/lib/commonjs/skia/types/Paragraph/Paragraph.d.ts +31 -1
  8. package/lib/commonjs/skia/types/Paragraph/Paragraph.js.map +1 -1
  9. package/lib/commonjs/skia/web/JsiSkParagraph.d.ts +2 -2
  10. package/lib/commonjs/skia/web/JsiSkParagraph.js +4 -18
  11. package/lib/commonjs/skia/web/JsiSkParagraph.js.map +1 -1
  12. package/lib/commonjs/specs/NativeSkiaModule.web.d.ts +3 -3
  13. package/lib/commonjs/specs/NativeSkiaModule.web.js.map +1 -1
  14. package/lib/commonjs/specs/SkiaPictureViewNativeComponent.web.d.ts +1 -2
  15. package/lib/commonjs/views/SkiaPictureView.web.d.ts +10 -6
  16. package/lib/commonjs/views/SkiaPictureView.web.js +253 -20
  17. package/lib/commonjs/views/SkiaPictureView.web.js.map +1 -1
  18. package/lib/commonjs/views/types.d.ts +1 -0
  19. package/lib/commonjs/views/types.js.map +1 -1
  20. package/lib/module/renderer/Canvas.d.ts +1 -0
  21. package/lib/module/renderer/Canvas.js.map +1 -1
  22. package/lib/module/renderer/__tests__/e2e/ParagraphMethods.spec.d.ts +1 -0
  23. package/lib/module/renderer/__tests__/e2e/setup/Paragraph.d.ts +1 -1
  24. package/lib/module/skia/types/Paragraph/Paragraph.d.ts +31 -1
  25. package/lib/module/skia/types/Paragraph/Paragraph.js.map +1 -1
  26. package/lib/module/skia/web/JsiSkParagraph.d.ts +2 -2
  27. package/lib/module/skia/web/JsiSkParagraph.js +4 -18
  28. package/lib/module/skia/web/JsiSkParagraph.js.map +1 -1
  29. package/lib/module/specs/NativeSkiaModule.web.d.ts +3 -3
  30. package/lib/module/specs/NativeSkiaModule.web.js.map +1 -1
  31. package/lib/module/specs/SkiaPictureViewNativeComponent.web.d.ts +1 -2
  32. package/lib/module/views/SkiaPictureView.web.d.ts +10 -6
  33. package/lib/module/views/SkiaPictureView.web.js +251 -18
  34. package/lib/module/views/SkiaPictureView.web.js.map +1 -1
  35. package/lib/module/views/types.d.ts +1 -0
  36. package/lib/module/views/types.js.map +1 -1
  37. package/lib/typescript/lib/commonjs/specs/SkiaPictureViewNativeComponent.web.d.ts +11 -1
  38. package/lib/typescript/lib/commonjs/views/SkiaPictureView.web.d.ts +1 -6
  39. package/lib/typescript/lib/module/specs/SkiaPictureViewNativeComponent.web.d.ts +1 -2
  40. package/lib/typescript/lib/module/views/SkiaPictureView.web.d.ts +2 -6
  41. package/lib/typescript/src/renderer/Canvas.d.ts +1 -0
  42. package/lib/typescript/src/renderer/__tests__/e2e/ParagraphMethods.spec.d.ts +1 -0
  43. package/lib/typescript/src/renderer/__tests__/e2e/setup/Paragraph.d.ts +1 -1
  44. package/lib/typescript/src/skia/types/Paragraph/Paragraph.d.ts +31 -1
  45. package/lib/typescript/src/skia/web/JsiSkParagraph.d.ts +2 -2
  46. package/lib/typescript/src/specs/NativeSkiaModule.web.d.ts +3 -3
  47. package/lib/typescript/src/specs/SkiaPictureViewNativeComponent.web.d.ts +1 -2
  48. package/lib/typescript/src/views/SkiaPictureView.web.d.ts +10 -6
  49. package/lib/typescript/src/views/types.d.ts +1 -0
  50. package/package.json +1 -1
  51. package/src/renderer/Canvas.tsx +1 -0
  52. package/src/renderer/__tests__/e2e/ParagraphMethods.spec.tsx +388 -0
  53. package/src/skia/types/Paragraph/Paragraph.ts +32 -1
  54. package/src/skia/web/JsiSkParagraph.ts +19 -28
  55. package/src/specs/NativeSkiaModule.web.ts +4 -4
  56. package/src/views/SkiaPictureView.web.tsx +312 -18
  57. package/src/views/types.ts +4 -0
  58. package/lib/commonjs/views/SkiaBaseWebView.d.ts +0 -40
  59. package/lib/commonjs/views/SkiaBaseWebView.js +0 -143
  60. package/lib/commonjs/views/SkiaBaseWebView.js.map +0 -1
  61. package/lib/module/views/SkiaBaseWebView.d.ts +0 -40
  62. package/lib/module/views/SkiaBaseWebView.js +0 -136
  63. package/lib/module/views/SkiaBaseWebView.js.map +0 -1
  64. package/lib/typescript/lib/commonjs/views/SkiaBaseWebView.d.ts +0 -39
  65. package/lib/typescript/lib/module/views/SkiaBaseWebView.d.ts +0 -36
  66. package/lib/typescript/src/views/SkiaBaseWebView.d.ts +0 -40
  67. package/src/views/SkiaBaseWebView.tsx +0 -140
@@ -1,31 +1,325 @@
1
- import type { SkCanvas, SkPicture } from "../skia/types";
1
+ /* global HTMLCanvasElement */
2
+ import React, {
3
+ useRef,
4
+ useEffect,
5
+ useCallback,
6
+ useImperativeHandle,
7
+ forwardRef,
8
+ } from "react";
9
+ import type { LayoutChangeEvent } from "react-native";
10
+
11
+ import type { SkRect, SkPicture, SkImage } from "../skia/types";
12
+ import { JsiSkSurface } from "../skia/web/JsiSkSurface";
13
+ import { Platform } from "../Platform";
2
14
  import type { ISkiaViewApiWeb } from "../specs/NativeSkiaModule.web";
3
15
 
4
16
  import type { SkiaPictureViewNativeProps } from "./types";
5
- import { SkiaBaseWebView } from "./SkiaBaseWebView";
17
+ import { SkiaViewNativeId } from "./SkiaViewNativeId";
18
+
19
+ interface Renderer {
20
+ onResize(): void;
21
+ draw(picture: SkPicture): void;
22
+ makeImageSnapshot(picture: SkPicture, rect?: SkRect): SkImage | null;
23
+ dispose(): void;
24
+ }
25
+
26
+ class WebGLRenderer implements Renderer {
27
+ private surface: JsiSkSurface | null = null;
28
+
29
+ constructor(private canvas: HTMLCanvasElement, private pd: number) {
30
+ this.onResize();
31
+ }
32
+
33
+ makeImageSnapshot(picture: SkPicture, rect?: SkRect): SkImage | null {
34
+ if (!this.surface) {
35
+ return null;
36
+ }
37
+ const canvas = this.surface.getCanvas();
38
+ canvas!.clear(CanvasKit.TRANSPARENT);
39
+ this.draw(picture);
40
+ this.surface.ref.flush();
41
+ return this.surface.makeImageSnapshot(rect);
42
+ }
43
+
44
+ onResize() {
45
+ const { canvas, pd } = this;
46
+ canvas.width = canvas.clientWidth * pd;
47
+ canvas.height = canvas.clientHeight * pd;
48
+ const surface = CanvasKit.MakeWebGLCanvasSurface(canvas);
49
+ const ctx = canvas.getContext("webgl2");
50
+ if (ctx) {
51
+ ctx.drawingBufferColorSpace = "display-p3";
52
+ }
53
+ if (!surface) {
54
+ throw new Error("Could not create surface");
55
+ }
56
+ this.surface = new JsiSkSurface(CanvasKit, surface);
57
+ }
58
+
59
+ draw(picture: SkPicture) {
60
+ if (this.surface) {
61
+ const canvas = this.surface.getCanvas();
62
+ canvas.clear(Float32Array.of(0, 0, 0, 0));
63
+ canvas.save();
64
+ canvas.scale(pd, pd);
65
+ canvas.drawPicture(picture);
66
+ canvas.restore();
67
+ this.surface.ref.flush();
68
+ }
69
+ }
6
70
 
7
- export class SkiaPictureView extends SkiaBaseWebView<SkiaPictureViewNativeProps> {
8
- private picture: SkPicture | null = null;
71
+ dispose(): void {
72
+ if (this.surface) {
73
+ this.canvas
74
+ ?.getContext("webgl2")
75
+ ?.getExtension("WEBGL_lose_context")
76
+ ?.loseContext();
77
+ this.surface.ref.delete();
78
+ this.surface = null;
79
+ }
80
+ }
81
+ }
82
+
83
+ class StaticWebGLRenderer implements Renderer {
84
+ private cachedImage: SkImage | null = null;
85
+
86
+ constructor(private canvas: HTMLCanvasElement, private pd: number) {}
87
+
88
+ onResize(): void {
89
+ this.cachedImage = null;
90
+ }
91
+
92
+ private renderPictureToSurface(
93
+ picture: SkPicture
94
+ ): { surface: JsiSkSurface; tempCanvas: OffscreenCanvas } | null {
95
+ const tempCanvas = new OffscreenCanvas(
96
+ this.canvas.clientWidth * this.pd,
97
+ this.canvas.clientHeight * this.pd
98
+ );
99
+
100
+ let surface: JsiSkSurface | null = null;
101
+
102
+ try {
103
+ const webglSurface = CanvasKit.MakeWebGLCanvasSurface(tempCanvas);
104
+ const ctx = tempCanvas.getContext("webgl2");
105
+ if (ctx) {
106
+ ctx.drawingBufferColorSpace = "display-p3";
107
+ }
108
+
109
+ if (!webglSurface) {
110
+ throw new Error("Could not create WebGL surface");
111
+ }
112
+
113
+ surface = new JsiSkSurface(CanvasKit, webglSurface);
114
+
115
+ const skiaCanvas = surface.getCanvas();
116
+ skiaCanvas.clear(Float32Array.of(0, 0, 0, 0));
117
+ skiaCanvas.save();
118
+ skiaCanvas.scale(this.pd, this.pd);
119
+ skiaCanvas.drawPicture(picture);
120
+ skiaCanvas.restore();
121
+ surface.ref.flush();
122
+
123
+ return { surface, tempCanvas };
124
+ } catch (error) {
125
+ if (surface) {
126
+ surface.ref.delete();
127
+ }
128
+ this.cleanupWebGLContext(tempCanvas);
129
+ return null;
130
+ }
131
+ }
9
132
 
10
- constructor(props: SkiaPictureViewNativeProps) {
11
- super(props);
12
- const { nativeID } = props;
13
- if (!nativeID) {
14
- throw new Error("SkiaPictureView requires a nativeID prop");
133
+ private cleanupWebGLContext(tempCanvas: OffscreenCanvas): void {
134
+ const ctx = tempCanvas.getContext("webgl2");
135
+ if (ctx) {
136
+ const loseContext = ctx.getExtension("WEBGL_lose_context");
137
+ if (loseContext) {
138
+ loseContext.loseContext();
139
+ }
15
140
  }
16
- (global.SkiaViewApi as ISkiaViewApiWeb).registerView(nativeID, this);
17
141
  }
18
142
 
19
- public setPicture(picture: SkPicture) {
20
- this.picture = picture;
21
- this.redraw();
143
+ draw(picture: SkPicture): void {
144
+ const renderResult = this.renderPictureToSurface(picture);
145
+ if (!renderResult) {
146
+ return;
147
+ }
148
+ const { tempCanvas } = renderResult;
149
+ const ctx2d = this.canvas.getContext("2d");
150
+ if (!ctx2d) {
151
+ throw new Error("Could not get 2D context");
152
+ }
153
+
154
+ // Set canvas dimensions to match pixel density
155
+ this.canvas.width = this.canvas.clientWidth * this.pd;
156
+ this.canvas.height = this.canvas.clientHeight * this.pd;
157
+
158
+ // Draw the tempCanvas scaled down to the display size
159
+ ctx2d.drawImage(
160
+ tempCanvas,
161
+ 0,
162
+ 0,
163
+ tempCanvas.width,
164
+ tempCanvas.height,
165
+ 0,
166
+ 0,
167
+ this.canvas.clientWidth * this.pd,
168
+ this.canvas.clientHeight * this.pd
169
+ );
170
+
171
+ this.cleanupWebGLContext(tempCanvas);
22
172
  }
23
173
 
24
- protected renderInCanvas(canvas: SkCanvas): void {
25
- if (this.props.picture) {
26
- canvas.drawPicture(this.props.picture);
27
- } else if (this.picture) {
28
- canvas.drawPicture(this.picture);
174
+ makeImageSnapshot(picture: SkPicture, rect?: SkRect): SkImage | null {
175
+ if (!this.cachedImage) {
176
+ const renderResult = this.renderPictureToSurface(picture);
177
+ if (!renderResult) {
178
+ return null;
179
+ }
180
+
181
+ const { surface, tempCanvas } = renderResult;
182
+
183
+ try {
184
+ this.cachedImage = surface.makeImageSnapshot(rect);
185
+ } catch (error) {
186
+ console.error("Error creating image snapshot:", error);
187
+ } finally {
188
+ surface.ref.delete();
189
+ this.cleanupWebGLContext(tempCanvas);
190
+ }
29
191
  }
192
+
193
+ return this.cachedImage;
194
+ }
195
+
196
+ dispose(): void {
197
+ this.cachedImage?.dispose();
198
+ this.cachedImage = null;
30
199
  }
31
200
  }
201
+
202
+ const pd = Platform.PixelRatio;
203
+
204
+ export interface SkiaPictureViewHandle {
205
+ setPicture(picture: SkPicture): void;
206
+ getSize(): { width: number; height: number };
207
+ redraw(): void;
208
+ makeImageSnapshot(rect?: SkRect): SkImage | null;
209
+ }
210
+
211
+ export const SkiaPictureView = forwardRef<
212
+ SkiaPictureViewHandle,
213
+ SkiaPictureViewNativeProps
214
+ >((props, ref) => {
215
+ const canvasRef = useRef<HTMLCanvasElement | null>(null);
216
+ const renderer = useRef<Renderer | null>(null);
217
+ const redrawRequestsRef = useRef(0);
218
+ const requestIdRef = useRef(0);
219
+ const pictureRef = useRef<SkPicture | null>(null);
220
+
221
+ const { picture, onLayout } = props;
222
+
223
+ const redraw = useCallback(() => {
224
+ redrawRequestsRef.current++;
225
+ }, []);
226
+
227
+ const getSize = useCallback(() => {
228
+ return {
229
+ width: canvasRef.current?.clientWidth || 0,
230
+ height: canvasRef.current?.clientHeight || 0,
231
+ };
232
+ }, []);
233
+
234
+ const setPicture = useCallback(
235
+ (newPicture: SkPicture) => {
236
+ pictureRef.current = newPicture;
237
+ redraw();
238
+ },
239
+ [redraw]
240
+ );
241
+
242
+ const makeImageSnapshot = useCallback((rect?: SkRect) => {
243
+ if (renderer.current && pictureRef.current) {
244
+ return renderer.current.makeImageSnapshot(pictureRef.current, rect);
245
+ }
246
+ return null;
247
+ }, []);
248
+
249
+ const tick = useCallback(() => {
250
+ if (redrawRequestsRef.current > 0) {
251
+ redrawRequestsRef.current = 0;
252
+ if (renderer.current && pictureRef.current) {
253
+ renderer.current.draw(pictureRef.current);
254
+ }
255
+ }
256
+ requestIdRef.current = requestAnimationFrame(tick);
257
+ }, []);
258
+
259
+ const onLayoutEvent = useCallback(
260
+ (evt: LayoutChangeEvent) => {
261
+ const canvas = canvasRef.current;
262
+ if (canvas) {
263
+ renderer.current =
264
+ props.__destroyWebGLContextAfterRender === true
265
+ ? new StaticWebGLRenderer(canvas, pd)
266
+ : new WebGLRenderer(canvas, pd);
267
+ if (pictureRef.current) {
268
+ renderer.current.draw(pictureRef.current);
269
+ }
270
+ }
271
+ if (onLayout) {
272
+ onLayout(evt);
273
+ }
274
+ },
275
+ [onLayout, props.__destroyWebGLContextAfterRender]
276
+ );
277
+
278
+ useImperativeHandle(
279
+ ref,
280
+ () => ({
281
+ setPicture,
282
+ getSize,
283
+ redraw,
284
+ makeImageSnapshot,
285
+ }),
286
+ [setPicture, getSize, redraw, makeImageSnapshot]
287
+ );
288
+
289
+ useEffect(() => {
290
+ const nativeID = props.nativeID ?? `${SkiaViewNativeId.current++}`;
291
+ (global.SkiaViewApi as ISkiaViewApiWeb).registerView(nativeID, {
292
+ setPicture,
293
+ getSize,
294
+ redraw,
295
+ makeImageSnapshot,
296
+ } as SkiaPictureViewHandle);
297
+ if (props.picture) {
298
+ setPicture(props.picture);
299
+ }
300
+ }, [setPicture, getSize, redraw, makeImageSnapshot, props]);
301
+
302
+ useEffect(() => {
303
+ tick();
304
+ return () => {
305
+ cancelAnimationFrame(requestIdRef.current);
306
+ if (renderer.current) {
307
+ renderer.current.dispose();
308
+ renderer.current = null;
309
+ }
310
+ };
311
+ }, [tick]);
312
+
313
+ useEffect(() => {
314
+ if (renderer.current && pictureRef.current) {
315
+ renderer.current.draw(pictureRef.current);
316
+ }
317
+ }, [picture, redraw]);
318
+
319
+ const { debug = false, ...viewProps } = props;
320
+ return (
321
+ <Platform.View {...viewProps} onLayout={onLayoutEvent}>
322
+ <canvas ref={canvasRef} style={{ display: "flex", flex: 1 }} />
323
+ </Platform.View>
324
+ );
325
+ });
@@ -31,6 +31,10 @@ export interface SkiaBaseViewProps extends ViewProps {
31
31
  onSize?: SharedValue<SkSize>;
32
32
 
33
33
  opaque?: boolean;
34
+
35
+ // On web, only 16 WebGL contextes are allowed. If the drawing is non-animated, set
36
+ // __destroyWebGLContextAfterRender to true to release the context after each draw.
37
+ __destroyWebGLContextAfterRender?: boolean;
34
38
  }
35
39
 
36
40
  export interface SkiaPictureViewNativeProps extends SkiaBaseViewProps {
@@ -1,40 +0,0 @@
1
- import React from "react";
2
- import type { SkRect, SkCanvas } from "../skia/types";
3
- import type { SkiaBaseViewProps } from "./types";
4
- export declare abstract class SkiaBaseWebView<TProps extends SkiaBaseViewProps> extends React.Component<TProps> {
5
- constructor(props: TProps);
6
- private _surface;
7
- private _unsubscriptions;
8
- private _canvas;
9
- private _canvasRef;
10
- private _redrawRequests;
11
- private requestId;
12
- protected width: number;
13
- protected height: number;
14
- private unsubscribeAll;
15
- private onLayoutEvent;
16
- getSize(): {
17
- width: number;
18
- height: number;
19
- };
20
- componentDidMount(): void;
21
- componentDidUpdate(): void;
22
- componentWillUnmount(): void;
23
- /**
24
- * Creates a snapshot from the canvas in the surface
25
- * @param rect Rect to use as bounds. Optional.
26
- * @returns An Image object.
27
- */
28
- makeImageSnapshot(rect?: SkRect): import("../skia/types").SkImage | undefined;
29
- /**
30
- * Override to render
31
- */
32
- protected abstract renderInCanvas(canvas: SkCanvas): void;
33
- /**
34
- * Sends a redraw request to the native SkiaView.
35
- */
36
- private tick;
37
- redraw(): void;
38
- private onLayout;
39
- render(): React.JSX.Element;
40
- }
@@ -1,143 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.SkiaBaseWebView = void 0;
7
- var _react = _interopRequireDefault(require("react"));
8
- var _JsiSkSurface = require("../skia/web/JsiSkSurface");
9
- var _Platform = require("../Platform");
10
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
- function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
12
- function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
13
- function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
14
- function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /* global HTMLCanvasElement */
15
- const pd = _Platform.Platform.PixelRatio;
16
- class SkiaBaseWebView extends _react.default.Component {
17
- constructor(props) {
18
- super(props);
19
- _defineProperty(this, "_surface", null);
20
- _defineProperty(this, "_unsubscriptions", []);
21
- _defineProperty(this, "_canvas", null);
22
- _defineProperty(this, "_canvasRef", /*#__PURE__*/_react.default.createRef());
23
- _defineProperty(this, "_redrawRequests", 0);
24
- _defineProperty(this, "requestId", 0);
25
- _defineProperty(this, "width", 0);
26
- _defineProperty(this, "height", 0);
27
- _defineProperty(this, "onLayout", this.onLayoutEvent.bind(this));
28
- }
29
- unsubscribeAll() {
30
- this._unsubscriptions.forEach(u => u());
31
- this._unsubscriptions = [];
32
- }
33
- onLayoutEvent(evt) {
34
- const {
35
- CanvasKit
36
- } = global;
37
- // Reset canvas / surface on layout change
38
- const canvas = this._canvasRef.current;
39
- if (canvas) {
40
- this.width = canvas.clientWidth;
41
- this.height = canvas.clientHeight;
42
- canvas.width = this.width * pd;
43
- canvas.height = this.height * pd;
44
- const surface = CanvasKit.MakeWebGLCanvasSurface(canvas);
45
- const ctx = canvas.getContext("webgl2");
46
- if (ctx) {
47
- ctx.drawingBufferColorSpace = "display-p3";
48
- }
49
- if (!surface) {
50
- throw new Error("Could not create surface");
51
- }
52
- this._surface = new _JsiSkSurface.JsiSkSurface(CanvasKit, surface);
53
- this._canvas = this._surface.getCanvas();
54
- this.redraw();
55
- }
56
- // Call onLayout callback if it exists
57
- if (this.props.onLayout) {
58
- this.props.onLayout(evt);
59
- }
60
- }
61
- getSize() {
62
- return {
63
- width: this.width,
64
- height: this.height
65
- };
66
- }
67
- componentDidMount() {
68
- // Start render loop
69
- this.tick();
70
- }
71
- componentDidUpdate() {
72
- this.redraw();
73
- }
74
- componentWillUnmount() {
75
- this.unsubscribeAll();
76
- cancelAnimationFrame(this.requestId);
77
- // eslint-disable-next-line max-len
78
- // https://stackoverflow.com/questions/23598471/how-do-i-clean-up-and-unload-a-webgl-canvas-context-from-gpu-after-use
79
- // https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_lose_context
80
- // We delete the context, only if the context has been intialized
81
- if (this._surface) {
82
- var _this$_canvasRef$curr;
83
- (_this$_canvasRef$curr = this._canvasRef.current) === null || _this$_canvasRef$curr === void 0 || (_this$_canvasRef$curr = _this$_canvasRef$curr.getContext("webgl2")) === null || _this$_canvasRef$curr === void 0 || (_this$_canvasRef$curr = _this$_canvasRef$curr.getExtension("WEBGL_lose_context")) === null || _this$_canvasRef$curr === void 0 || _this$_canvasRef$curr.loseContext();
84
- }
85
- }
86
-
87
- /**
88
- * Creates a snapshot from the canvas in the surface
89
- * @param rect Rect to use as bounds. Optional.
90
- * @returns An Image object.
91
- */
92
- makeImageSnapshot(rect) {
93
- var _this$_surface, _this$_surface2;
94
- this._canvas.clear(CanvasKit.TRANSPARENT);
95
- this.renderInCanvas(this._canvas);
96
- (_this$_surface = this._surface) === null || _this$_surface === void 0 || _this$_surface.ref.flush();
97
- return (_this$_surface2 = this._surface) === null || _this$_surface2 === void 0 ? void 0 : _this$_surface2.makeImageSnapshot(rect);
98
- }
99
-
100
- /**
101
- * Override to render
102
- */
103
-
104
- /**
105
- * Sends a redraw request to the native SkiaView.
106
- */
107
- tick() {
108
- if (this._redrawRequests > 0) {
109
- this._redrawRequests = 0;
110
- if (this._canvas) {
111
- var _this$_surface3;
112
- const canvas = this._canvas;
113
- canvas.clear(Float32Array.of(0, 0, 0, 0));
114
- canvas.save();
115
- canvas.scale(pd, pd);
116
- this.renderInCanvas(canvas);
117
- canvas.restore();
118
- (_this$_surface3 = this._surface) === null || _this$_surface3 === void 0 || _this$_surface3.ref.flush();
119
- }
120
- }
121
- this.requestId = requestAnimationFrame(this.tick.bind(this));
122
- }
123
- redraw() {
124
- this._redrawRequests++;
125
- }
126
- render() {
127
- const {
128
- debug = false,
129
- ...viewProps
130
- } = this.props;
131
- return /*#__PURE__*/_react.default.createElement(_Platform.Platform.View, _extends({}, viewProps, {
132
- onLayout: this.onLayout
133
- }), /*#__PURE__*/_react.default.createElement("canvas", {
134
- ref: this._canvasRef,
135
- style: {
136
- display: "flex",
137
- flex: 1
138
- }
139
- }));
140
- }
141
- }
142
- exports.SkiaBaseWebView = SkiaBaseWebView;
143
- //# sourceMappingURL=SkiaBaseWebView.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["_react","_interopRequireDefault","require","_JsiSkSurface","_Platform","e","__esModule","default","_extends","Object","assign","bind","n","arguments","length","t","r","hasOwnProperty","call","apply","_defineProperty","_toPropertyKey","defineProperty","value","enumerable","configurable","writable","i","_toPrimitive","Symbol","toPrimitive","TypeError","String","Number","pd","Platform","PixelRatio","SkiaBaseWebView","React","Component","constructor","props","createRef","onLayoutEvent","unsubscribeAll","_unsubscriptions","forEach","u","evt","CanvasKit","global","canvas","_canvasRef","current","width","clientWidth","height","clientHeight","surface","MakeWebGLCanvasSurface","ctx","getContext","drawingBufferColorSpace","Error","_surface","JsiSkSurface","_canvas","getCanvas","redraw","onLayout","getSize","componentDidMount","tick","componentDidUpdate","componentWillUnmount","cancelAnimationFrame","requestId","_this$_canvasRef$curr","getExtension","loseContext","makeImageSnapshot","rect","_this$_surface","_this$_surface2","clear","TRANSPARENT","renderInCanvas","ref","flush","_redrawRequests","_this$_surface3","Float32Array","of","save","scale","restore","requestAnimationFrame","render","debug","viewProps","createElement","View","style","display","flex","exports"],"sources":["SkiaBaseWebView.tsx"],"sourcesContent":["/* global HTMLCanvasElement */\nimport React from \"react\";\nimport type { LayoutChangeEvent } from \"react-native\";\n\nimport type { SkRect, SkCanvas } from \"../skia/types\";\nimport { JsiSkSurface } from \"../skia/web/JsiSkSurface\";\nimport { Platform } from \"../Platform\";\n\nimport type { SkiaBaseViewProps } from \"./types\";\n\nconst pd = Platform.PixelRatio;\n\nexport abstract class SkiaBaseWebView<\n TProps extends SkiaBaseViewProps\n> extends React.Component<TProps> {\n constructor(props: TProps) {\n super(props);\n }\n\n private _surface: JsiSkSurface | null = null;\n private _unsubscriptions: Array<() => void> = [];\n private _canvas: SkCanvas | null = null;\n private _canvasRef = React.createRef<HTMLCanvasElement>();\n private _redrawRequests = 0;\n private requestId = 0;\n\n protected width = 0;\n protected height = 0;\n\n private unsubscribeAll() {\n this._unsubscriptions.forEach((u) => u());\n this._unsubscriptions = [];\n }\n\n private onLayoutEvent(evt: LayoutChangeEvent) {\n const { CanvasKit } = global;\n // Reset canvas / surface on layout change\n const canvas = this._canvasRef.current;\n if (canvas) {\n this.width = canvas.clientWidth;\n this.height = canvas.clientHeight;\n canvas.width = this.width * pd;\n canvas.height = this.height * pd;\n const surface = CanvasKit.MakeWebGLCanvasSurface(canvas);\n const ctx = canvas.getContext(\"webgl2\");\n if (ctx) {\n ctx.drawingBufferColorSpace = \"display-p3\";\n }\n if (!surface) {\n throw new Error(\"Could not create surface\");\n }\n this._surface = new JsiSkSurface(CanvasKit, surface);\n this._canvas = this._surface.getCanvas();\n this.redraw();\n }\n // Call onLayout callback if it exists\n if (this.props.onLayout) {\n this.props.onLayout(evt);\n }\n }\n\n getSize() {\n return { width: this.width, height: this.height };\n }\n\n componentDidMount() {\n // Start render loop\n this.tick();\n }\n\n componentDidUpdate() {\n this.redraw();\n }\n\n componentWillUnmount() {\n this.unsubscribeAll();\n cancelAnimationFrame(this.requestId);\n // eslint-disable-next-line max-len\n // https://stackoverflow.com/questions/23598471/how-do-i-clean-up-and-unload-a-webgl-canvas-context-from-gpu-after-use\n // https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_lose_context\n // We delete the context, only if the context has been intialized\n if (this._surface) {\n this._canvasRef.current\n ?.getContext(\"webgl2\")\n ?.getExtension(\"WEBGL_lose_context\")\n ?.loseContext();\n }\n }\n\n /**\n * Creates a snapshot from the canvas in the surface\n * @param rect Rect to use as bounds. Optional.\n * @returns An Image object.\n */\n public makeImageSnapshot(rect?: SkRect) {\n this._canvas!.clear(CanvasKit.TRANSPARENT);\n this.renderInCanvas(this._canvas!);\n this._surface?.ref.flush();\n return this._surface?.makeImageSnapshot(rect);\n }\n\n /**\n * Override to render\n */\n protected abstract renderInCanvas(canvas: SkCanvas): void;\n\n /**\n * Sends a redraw request to the native SkiaView.\n */\n private tick() {\n if (this._redrawRequests > 0) {\n this._redrawRequests = 0;\n if (this._canvas) {\n const canvas = this._canvas!;\n canvas.clear(Float32Array.of(0, 0, 0, 0));\n canvas.save();\n canvas.scale(pd, pd);\n this.renderInCanvas(canvas);\n canvas.restore();\n this._surface?.ref.flush();\n }\n }\n this.requestId = requestAnimationFrame(this.tick.bind(this));\n }\n\n public redraw() {\n this._redrawRequests++;\n }\n\n private onLayout = this.onLayoutEvent.bind(this);\n\n render() {\n const { debug = false, ...viewProps } = this.props;\n return (\n <Platform.View {...viewProps} onLayout={this.onLayout}>\n <canvas ref={this._canvasRef} style={{ display: \"flex\", flex: 1 }} />\n </Platform.View>\n );\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,40 +0,0 @@
1
- import React from "react";
2
- import type { SkRect, SkCanvas } from "../skia/types";
3
- import type { SkiaBaseViewProps } from "./types";
4
- export declare abstract class SkiaBaseWebView<TProps extends SkiaBaseViewProps> extends React.Component<TProps> {
5
- constructor(props: TProps);
6
- private _surface;
7
- private _unsubscriptions;
8
- private _canvas;
9
- private _canvasRef;
10
- private _redrawRequests;
11
- private requestId;
12
- protected width: number;
13
- protected height: number;
14
- private unsubscribeAll;
15
- private onLayoutEvent;
16
- getSize(): {
17
- width: number;
18
- height: number;
19
- };
20
- componentDidMount(): void;
21
- componentDidUpdate(): void;
22
- componentWillUnmount(): void;
23
- /**
24
- * Creates a snapshot from the canvas in the surface
25
- * @param rect Rect to use as bounds. Optional.
26
- * @returns An Image object.
27
- */
28
- makeImageSnapshot(rect?: SkRect): import("../skia/types").SkImage | undefined;
29
- /**
30
- * Override to render
31
- */
32
- protected abstract renderInCanvas(canvas: SkCanvas): void;
33
- /**
34
- * Sends a redraw request to the native SkiaView.
35
- */
36
- private tick;
37
- redraw(): void;
38
- private onLayout;
39
- render(): React.JSX.Element;
40
- }