@shopify/react-native-skia 2.12.0 → 2.13.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.
Files changed (103) hide show
  1. package/LICENSE.md +2 -1
  2. package/Package.swift +4 -4
  3. package/android/CMakeLists.txt +22 -177
  4. package/android/build.gradle +40 -209
  5. package/android/cpp/jni/JniSkiaManager.cpp +3 -45
  6. package/android/cpp/jni/include/JniPlatformContext.h +1 -1
  7. package/android/cpp/jni/include/JniSkiaBaseView.h +18 -11
  8. package/android/cpp/jni/include/JniSkiaManager.h +3 -4
  9. package/android/cpp/jni/include/JniSkiaPictureView.h +5 -5
  10. package/android/cpp/rnskia-android/RNSkAndroidView.h +6 -6
  11. package/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp +4 -4
  12. package/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h +2 -2
  13. package/android/src/main/AndroidManifest.xml +1 -1
  14. package/android/src/main/java/com/{shopify/reactnative → reactnative}/skia/PlatformContext.java +1 -1
  15. package/android/src/main/java/com/{shopify/reactnative → reactnative}/skia/RNSkVideo.java +1 -1
  16. package/android/src/main/java/com/{shopify/reactnative → reactnative}/skia/RNSkiaModule.java +1 -8
  17. package/android/src/main/java/com/reactnative/skia/RNSkiaPackage.java +57 -0
  18. package/android/src/main/java/com/reactnative/skia/SkiaBaseView.java +185 -0
  19. package/android/src/main/java/com/{shopify/reactnative → reactnative}/skia/SkiaBaseViewManager.java +20 -1
  20. package/android/src/main/java/com/{shopify/reactnative → reactnative}/skia/SkiaManager.java +11 -6
  21. package/android/src/main/java/com/{shopify/reactnative → reactnative}/skia/SkiaPictureView.java +3 -3
  22. package/android/src/main/java/com/{shopify/reactnative → reactnative}/skia/SkiaPictureViewManager.java +1 -1
  23. package/android/src/main/java/com/{shopify/reactnative → reactnative}/skia/SkiaSurfaceView.java +13 -3
  24. package/android/src/main/java/com/{shopify/reactnative → reactnative}/skia/SkiaTextureView.java +5 -3
  25. package/android/src/main/java/com/{shopify/reactnative → reactnative}/skia/SkiaViewAPI.java +1 -1
  26. package/android/src/main/java/com/{shopify/reactnative → reactnative}/skia/ViewScreenshotService.java +1 -1
  27. package/apple/MetalContext.mm +1 -1
  28. package/apple/RNSkiaModule.h +1 -10
  29. package/apple/RNSkiaModule.mm +2 -10
  30. package/apple/SkiaManager.h +0 -2
  31. package/apple/SkiaManager.mm +4 -6
  32. package/apple/SkiaPictureView.h +2 -2
  33. package/apple/SkiaPictureView.mm +0 -4
  34. package/apple/SkiaUIView.h +3 -18
  35. package/apple/SkiaUIView.mm +0 -30
  36. package/cpp/api/CustomBlendModes.h +17 -0
  37. package/cpp/api/JsiSkCanvas.h +19 -10
  38. package/cpp/jsi/ViewProperty.h +0 -4
  39. package/lib/commonjs/mock/index.js +0 -1
  40. package/lib/commonjs/mock/index.js.map +1 -1
  41. package/lib/commonjs/renderer/Canvas.d.ts +11 -3
  42. package/lib/commonjs/renderer/Canvas.js +8 -6
  43. package/lib/commonjs/renderer/Canvas.js.map +1 -1
  44. package/lib/commonjs/skia/web/JsiSkCanvas.js +9 -4
  45. package/lib/commonjs/skia/web/JsiSkCanvas.js.map +1 -1
  46. package/lib/commonjs/specs/SkiaPictureViewNativeComponent.d.ts +2 -0
  47. package/lib/commonjs/specs/SkiaPictureViewNativeComponent.js.map +1 -1
  48. package/lib/commonjs/specs/SkiaPictureViewNativeComponent.web.d.ts +3 -1
  49. package/lib/commonjs/specs/SkiaPictureViewNativeComponent.web.js +3 -0
  50. package/lib/commonjs/specs/SkiaPictureViewNativeComponent.web.js.map +1 -1
  51. package/lib/commonjs/views/SkiaPictureView.js +2 -12
  52. package/lib/commonjs/views/SkiaPictureView.js.map +1 -1
  53. package/lib/commonjs/views/types.d.ts +19 -8
  54. package/lib/commonjs/views/types.js.map +1 -1
  55. package/lib/module/mock/index.js +0 -1
  56. package/lib/module/mock/index.js.map +1 -1
  57. package/lib/module/renderer/Canvas.d.ts +11 -3
  58. package/lib/module/renderer/Canvas.js +7 -5
  59. package/lib/module/renderer/Canvas.js.map +1 -1
  60. package/lib/module/skia/web/JsiSkCanvas.js +9 -4
  61. package/lib/module/skia/web/JsiSkCanvas.js.map +1 -1
  62. package/lib/module/specs/SkiaPictureViewNativeComponent.d.ts +2 -0
  63. package/lib/module/specs/SkiaPictureViewNativeComponent.js.map +1 -1
  64. package/lib/module/specs/SkiaPictureViewNativeComponent.web.d.ts +3 -1
  65. package/lib/module/specs/SkiaPictureViewNativeComponent.web.js +3 -0
  66. package/lib/module/specs/SkiaPictureViewNativeComponent.web.js.map +1 -1
  67. package/lib/module/views/SkiaPictureView.js +2 -12
  68. package/lib/module/views/SkiaPictureView.js.map +1 -1
  69. package/lib/module/views/types.d.ts +19 -8
  70. package/lib/module/views/types.js.map +1 -1
  71. package/lib/typescript/lib/commonjs/mock/index.d.ts +0 -1
  72. package/lib/typescript/lib/commonjs/renderer/Canvas.d.ts +2 -2
  73. package/lib/typescript/lib/commonjs/specs/SkiaPictureViewNativeComponent.web.d.ts +3 -1
  74. package/lib/typescript/lib/module/mock/index.d.ts +0 -1
  75. package/lib/typescript/lib/module/renderer/Canvas.d.ts +2 -2
  76. package/lib/typescript/lib/module/specs/SkiaPictureViewNativeComponent.web.d.ts +3 -1
  77. package/lib/typescript/src/renderer/Canvas.d.ts +11 -3
  78. package/lib/typescript/src/specs/SkiaPictureViewNativeComponent.d.ts +2 -0
  79. package/lib/typescript/src/specs/SkiaPictureViewNativeComponent.web.d.ts +3 -1
  80. package/lib/typescript/src/views/types.d.ts +19 -8
  81. package/package.json +3 -3
  82. package/react-native-skia.podspec +4 -10
  83. package/src/mock/index.ts +0 -1
  84. package/src/renderer/Canvas.tsx +23 -5
  85. package/src/skia/web/JsiSkCanvas.ts +14 -9
  86. package/src/specs/SkiaPictureViewNativeComponent.ts +5 -0
  87. package/src/specs/SkiaPictureViewNativeComponent.web.ts +5 -0
  88. package/src/views/SkiaPictureView.tsx +2 -10
  89. package/src/views/types.ts +23 -10
  90. package/android/src/latest/java/com/shopify/reactnative/skia/ReactNativeCompatible.java +0 -11
  91. package/android/src/main/java/com/shopify/reactnative/skia/RNSkiaPackage.java +0 -79
  92. package/android/src/main/java/com/shopify/reactnative/skia/SkiaAHBView.java +0 -113
  93. package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java +0 -136
  94. package/android/src/paper/java/com/facebook/react/viewmanagers/SkiaPictureViewManagerDelegate.java +0 -41
  95. package/android/src/paper/java/com/facebook/react/viewmanagers/SkiaPictureViewManagerInterface.java +0 -20
  96. package/android/src/paper/java/com/facebook/react/viewmanagers/SkiaWebGPUViewManagerDelegate.java +0 -35
  97. package/android/src/paper/java/com/facebook/react/viewmanagers/SkiaWebGPUViewManagerInterface.java +0 -17
  98. package/android/src/paper/java/com/shopify/reactnative/skia/NativeSkiaModuleSpec.java +0 -38
  99. package/android/src/reactnative74/java/com/shopify/reactnative/skia/ReactNativeCompatible.java +0 -14
  100. package/apple/SkiaPictureViewManager.h +0 -8
  101. package/apple/SkiaPictureViewManager.mm +0 -60
  102. package/apple/SkiaWebGPUView.h +0 -20
  103. package/apple/WebGPUMetalView.h +0 -12
@@ -19,6 +19,7 @@ import type { SharedValue } from "react-native-reanimated";
19
19
 
20
20
  import Rea from "../external/reanimated/ReanimatedProxy";
21
21
  import { SkiaViewNativeId } from "../views/SkiaViewNativeId";
22
+ import type { AndroidCanvasProps, AndroidSurfaceType } from "../views/types";
22
23
  import SkiaPictureViewNativeComponent from "../specs/SkiaPictureViewNativeComponent";
23
24
  import type { SkImage, SkRect, SkSize } from "../skia/types";
24
25
  import { SkiaSGRoot } from "../sksg/Reconciler";
@@ -59,13 +60,16 @@ export const useCanvasSize = (userRef?: RefObject<CanvasRef | null>) => {
59
60
  return { ref, size };
60
61
  };
61
62
 
62
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
63
- export const isFabric = Boolean((global as any)?.nativeFabricUIManager);
64
-
65
63
  export interface CanvasProps extends Omit<ViewProps, "onLayout"> {
66
64
  debug?: boolean;
67
- /** @deprecated Not supported on Fabric. Use `onSize` or `useCanvasSize()` instead. */
65
+ /** @deprecated Not supported on native. Use `onSize` or `useCanvasSize()` instead. */
68
66
  onLayout?: ViewProps["onLayout"];
67
+ /**
68
+ * Declares that the canvas covers every pixel of its bounds, so nothing
69
+ * behind it needs to show through. On Android an opaque canvas is backed by
70
+ * a `SurfaceView` by default, the cheapest path (see `android.surfaceType`).
71
+ * Defaults to false.
72
+ */
69
73
  opaque?: boolean;
70
74
  onSize?: SharedValue<SkSize>;
71
75
  colorSpace?: "p3" | "srgb";
@@ -78,11 +82,22 @@ export interface CanvasProps extends Omit<ViewProps, "onLayout"> {
78
82
  * before the canvas is mounted.
79
83
  */
80
84
  highBitDepth?: boolean;
85
+ /** Android-only rendering options. Ignored on iOS and web. */
86
+ android?: AndroidCanvasProps;
81
87
  ref?: React.Ref<CanvasRef>;
82
88
  androidWarmup?: boolean;
83
89
  __destroyWebGLContextAfterRender?: boolean;
84
90
  }
85
91
 
92
+ // Anything else reaching the native component would hit the generated
93
+ // string-enum parser, which aborts on unknown values.
94
+ const resolveSurfaceType = (
95
+ surfaceType: AndroidSurfaceType | undefined
96
+ ): "auto" | AndroidSurfaceType =>
97
+ surfaceType === "SurfaceView" || surfaceType === "TextureView"
98
+ ? surfaceType
99
+ : "auto";
100
+
86
101
  export const Canvas = ({
87
102
  debug,
88
103
  opaque,
@@ -91,11 +106,12 @@ export const Canvas = ({
91
106
  colorSpace = "p3",
92
107
  highBitDepth = false,
93
108
  androidWarmup = false,
109
+ android,
94
110
  ref,
95
111
  onLayout,
96
112
  ...viewProps
97
113
  }: CanvasProps) => {
98
- if (onLayout && isFabric) {
114
+ if (onLayout && Platform.OS !== "web") {
99
115
  console.error(
100
116
  "<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"
101
117
  );
@@ -192,6 +208,8 @@ export const Canvas = ({
192
208
  colorSpace={colorSpace}
193
209
  highBitDepth={highBitDepth}
194
210
  androidWarmup={androidWarmup}
211
+ androidSurfaceType={resolveSurfaceType(android?.surfaceType)}
212
+ androidZOrderOnTop={!!android?.zOrderOnTop}
195
213
  onLayout={
196
214
  Platform.OS === "web" && (onSize || onLayout) ? onLayoutWeb : onLayout
197
215
  }
@@ -205,15 +205,20 @@ export class JsiSkCanvas
205
205
  mode?: BlendMode | null,
206
206
  paint?: SkPaint
207
207
  ) {
208
- this.ref.drawPatch(
209
- cubics.map(({ x, y }) => [x, y]).flat(),
210
- colors,
211
- texs ? texs.flatMap((p) => Array.from(JsiSkPoint.fromValue(p))) : texs,
212
- mode !== undefined && mode !== null
213
- ? getEnum(this.CanvasKit, "BlendMode", mode)
214
- : null,
215
- paint ? JsiSkPaint.fromValue(paint) : undefined
216
- );
208
+ const defaultPaint = paint ? null : new this.CanvasKit.Paint();
209
+ try {
210
+ this.ref.drawPatch(
211
+ cubics.map(({ x, y }) => [x, y]).flat(),
212
+ colors,
213
+ texs ? texs.flatMap((p) => Array.from(JsiSkPoint.fromValue(p))) : texs,
214
+ mode !== undefined && mode !== null
215
+ ? getEnum(this.CanvasKit, "BlendMode", mode)
216
+ : null,
217
+ paint ? JsiSkPaint.fromValue(paint) : defaultPaint!
218
+ );
219
+ } finally {
220
+ defaultPaint?.delete();
221
+ }
217
222
  }
218
223
 
219
224
  restoreToCount(saveCount: number) {
@@ -9,6 +9,11 @@ export interface NativeProps extends ViewProps {
9
9
  colorSpace?: string;
10
10
  highBitDepth?: boolean;
11
11
  androidWarmup?: boolean;
12
+ androidSurfaceType?: WithDefault<
13
+ "auto" | "SurfaceView" | "TextureView",
14
+ "auto"
15
+ >;
16
+ androidZOrderOnTop?: WithDefault<boolean, false>;
12
17
  pointerEvents?: WithDefault<
13
18
  "auto" | "none" | "box-none" | "box-only",
14
19
  "auto"
@@ -7,6 +7,8 @@ export interface NativeProps extends ViewProps {
7
7
  debug?: boolean;
8
8
  opaque?: boolean;
9
9
  nativeID: string;
10
+ androidSurfaceType?: "auto" | "SurfaceView" | "TextureView";
11
+ androidZOrderOnTop?: boolean;
10
12
  }
11
13
 
12
14
  const SkiaPictureViewNativeComponent = ({
@@ -14,6 +16,9 @@ const SkiaPictureViewNativeComponent = ({
14
16
  debug,
15
17
  opaque,
16
18
  onLayout,
19
+ // Android-only, never reaches the DOM
20
+ androidSurfaceType: _androidSurfaceType,
21
+ androidZOrderOnTop: _androidZOrderOnTop,
17
22
  ...viewProps
18
23
  }: NativeProps) => {
19
24
  return createElement(SkiaPictureView, {
@@ -20,15 +20,11 @@ export class SkiaPictureView extends React.Component<SkiaPictureViewProps> {
20
20
  constructor(props: SkiaPictureViewProps) {
21
21
  super(props);
22
22
  this._nativeId = SkiaViewNativeId.current++;
23
- const { picture, onSize } = props;
23
+ const { picture } = props;
24
24
  if (picture) {
25
25
  assertSkiaViewApi();
26
26
  SkiaViewApi.setJsiProperty(this._nativeId, "picture", picture);
27
27
  }
28
- if (onSize) {
29
- assertSkiaViewApi();
30
- SkiaViewApi.setJsiProperty(this._nativeId, "onSize", onSize);
31
- }
32
28
  this.tick();
33
29
  }
34
30
 
@@ -39,15 +35,11 @@ export class SkiaPictureView extends React.Component<SkiaPictureViewProps> {
39
35
  }
40
36
 
41
37
  componentDidUpdate(prevProps: SkiaPictureViewProps) {
42
- const { picture, onSize } = this.props;
38
+ const { picture } = this.props;
43
39
  if (picture !== prevProps.picture) {
44
40
  assertSkiaViewApi();
45
41
  SkiaViewApi.setJsiProperty(this._nativeId, "picture", picture);
46
42
  }
47
- if (onSize !== prevProps.onSize) {
48
- assertSkiaViewApi();
49
- SkiaViewApi.setJsiProperty(this._nativeId, "onSize", onSize);
50
- }
51
43
  this.tick();
52
44
  }
53
45
 
@@ -1,7 +1,5 @@
1
1
  import type { ViewProps } from "react-native";
2
- import type { SharedValue } from "react-native-reanimated";
3
2
 
4
- import type { Node } from "../dom/types";
5
3
  import type { SkImage, SkPicture, SkRect, SkSize } from "../skia/types";
6
4
 
7
5
  export type NativeSkiaViewProps = ViewProps & {
@@ -9,6 +7,22 @@ export type NativeSkiaViewProps = ViewProps & {
9
7
  opaque?: boolean;
10
8
  };
11
9
 
10
+ export type AndroidSurfaceType = "SurfaceView" | "TextureView";
11
+
12
+ export interface AndroidCanvasProps {
13
+ /**
14
+ * Backing view. Defaults to `SurfaceView` when the canvas is `opaque` and to
15
+ * `TextureView` otherwise; both composite correctly in React Native stacking
16
+ * order without further flags.
17
+ */
18
+ surfaceType?: AndroidSurfaceType;
19
+ /**
20
+ * SurfaceView only: composite above every React Native view in the window,
21
+ * ignoring `zIndex`. Ignored for TextureView. Defaults to false.
22
+ */
23
+ zOrderOnTop?: boolean;
24
+ }
25
+
12
26
  export interface ISkiaViewApi {
13
27
  web?: boolean;
14
28
  setJsiProperty: <T>(nativeId: number, name: string, value: T) => void;
@@ -24,12 +38,12 @@ export interface SkiaBaseViewProps extends ViewProps {
24
38
  * average time it takes to render.
25
39
  */
26
40
  debug?: boolean;
41
+
27
42
  /**
28
- * Pass an animated value to the onSize property to get updates when
29
- * the Skia view is resized.
43
+ * Declares that the canvas covers every pixel of its bounds. On Android an
44
+ * opaque canvas is backed by a `SurfaceView` by default, the cheapest path
45
+ * (see `android.surfaceType`). Defaults to false.
30
46
  */
31
- onSize?: SharedValue<SkSize>;
32
-
33
47
  opaque?: boolean;
34
48
 
35
49
  /**
@@ -39,6 +53,9 @@ export interface SkiaBaseViewProps extends ViewProps {
39
53
  */
40
54
  highBitDepth?: boolean;
41
55
 
56
+ /** Android-only rendering options. Ignored on iOS and web. */
57
+ android?: AndroidCanvasProps;
58
+
42
59
  // On web, only 16 WebGL contextes are allowed. If the drawing is non-animated, set
43
60
  // __destroyWebGLContextAfterRender to true to release the context after each draw.
44
61
  __destroyWebGLContextAfterRender?: boolean;
@@ -48,7 +65,3 @@ export interface SkiaPictureViewNativeProps extends SkiaBaseViewProps {
48
65
  picture?: SkPicture;
49
66
  androidWarmup?: boolean;
50
67
  }
51
-
52
- export interface SkiaDomViewNativeProps extends SkiaBaseViewProps {
53
- root?: Node<unknown>;
54
- }
@@ -1,11 +0,0 @@
1
- package com.shopify.reactnative.skia;
2
-
3
- import com.facebook.react.bridge.ReactContext;
4
- import com.facebook.react.bridge.RuntimeExecutor;
5
-
6
- /* package */ final class ReactNativeCompatible {
7
- public static RuntimeExecutor getRuntimeExecutor(ReactContext context) {
8
- return context.getCatalystInstance().getRuntimeExecutor();
9
- }
10
- }
11
-
@@ -1,79 +0,0 @@
1
- // RnskiaPackage.java
2
-
3
- package com.shopify.reactnative.skia;
4
-
5
- import androidx.annotation.Nullable;
6
-
7
- import java.util.Arrays;
8
- import java.util.HashMap;
9
- import java.util.List;
10
- import java.util.Map;
11
-
12
- import com.facebook.react.TurboReactPackage;
13
- import com.facebook.react.bridge.NativeModule;
14
- import com.facebook.react.bridge.ReactApplicationContext;
15
- import com.facebook.react.module.annotations.ReactModule;
16
- import com.facebook.react.module.annotations.ReactModuleList;
17
- import com.facebook.react.module.model.ReactModuleInfo;
18
- import com.facebook.react.module.model.ReactModuleInfoProvider;
19
- import com.facebook.react.turbomodule.core.interfaces.TurboModule;
20
- import com.facebook.react.uimanager.ViewManager;
21
-
22
- @ReactModuleList(
23
- nativeModules = {
24
- RNSkiaModule.class,
25
- })
26
- public class RNSkiaPackage extends TurboReactPackage {
27
- @Override
28
- public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
29
- return Arrays.<NativeModule>asList(new RNSkiaModule(reactContext));
30
- }
31
-
32
- @Nullable
33
- @Override
34
- public NativeModule getModule(String s, ReactApplicationContext reactApplicationContext) {
35
- switch (s) {
36
- case RNSkiaModule.NAME:
37
- return new RNSkiaModule(reactApplicationContext);
38
- default:
39
- return null;
40
- }
41
- }
42
-
43
- @Override
44
- public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
45
- return Arrays.<ViewManager>asList(
46
- new SkiaPictureViewManager()
47
- );
48
- }
49
-
50
- @Override
51
- public ReactModuleInfoProvider getReactModuleInfoProvider() {
52
- return new ReactModuleInfoProvider() {
53
- @Override
54
- public Map<String, ReactModuleInfo> getReactModuleInfos() {
55
- final Map<String, ReactModuleInfo> reactModuleInfoMap = new HashMap<>();
56
- Class<? extends NativeModule>[] moduleList =
57
- new Class[] {
58
- RNSkiaModule.class,
59
- };
60
-
61
- for (Class<? extends NativeModule> moduleClass : moduleList) {
62
- ReactModule reactModule = moduleClass.getAnnotation(ReactModule.class);
63
-
64
- reactModuleInfoMap.put(
65
- reactModule.name(),
66
- new ReactModuleInfo(
67
- reactModule.name(),
68
- moduleClass.getName(),
69
- reactModule.canOverrideExistingModule(),
70
- reactModule.needsEagerInit(),
71
- reactModule.hasConstants(),
72
- reactModule.isCxxModule(),
73
- TurboModule.class.isAssignableFrom(moduleClass)));
74
- }
75
- return reactModuleInfoMap;
76
- }
77
- };
78
- }
79
- }
@@ -1,113 +0,0 @@
1
- package com.shopify.reactnative.skia;
2
-
3
-
4
- import android.annotation.SuppressLint;
5
- import android.content.Context;
6
- import android.graphics.Bitmap;
7
- import android.graphics.Canvas;
8
- import android.graphics.Matrix;
9
- import android.graphics.PixelFormat;
10
- import android.hardware.HardwareBuffer;
11
- import android.media.Image;
12
- import android.media.ImageReader;
13
- import android.os.Build;
14
- import android.util.Log;
15
- import android.view.View;
16
-
17
- import androidx.annotation.NonNull;
18
- import androidx.annotation.RequiresApi;
19
-
20
- @SuppressLint("ViewConstructor")
21
- @RequiresApi(api = Build.VERSION_CODES.Q)
22
- public class SkiaAHBView extends View implements ImageReader.OnImageAvailableListener {
23
-
24
- private ImageReader mReader;
25
-
26
- private Bitmap mBitmap = null;
27
-
28
- private final Matrix matrix = new Matrix();
29
-
30
- SkiaViewAPI mApi;
31
- boolean mDebug;
32
-
33
- public SkiaAHBView(Context context, SkiaViewAPI api, boolean debug) {
34
- super(context);
35
- mApi = api;
36
- mDebug = debug;
37
- }
38
-
39
- private ImageReader createReader() {
40
- ImageReader reader = ImageReader.newInstance(getWidth(), getHeight(), PixelFormat.RGBA_8888, 2, HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE |
41
- HardwareBuffer.USAGE_GPU_COLOR_OUTPUT);
42
- reader.setOnImageAvailableListener(this, null);
43
- return reader;
44
- }
45
-
46
- @Override
47
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
48
- super.onLayout(changed, left, top, right, bottom);
49
- int width = getWidth();
50
- int height = getHeight();
51
- if (mReader == null) {
52
- mReader = createReader();
53
- mApi.onSurfaceCreated(mReader.getSurface(), width, height);
54
- } else {
55
- mReader = createReader();
56
- mApi.onSurfaceChanged(mReader.getSurface(), width, height);
57
- }
58
- }
59
-
60
- @Override
61
- public void onImageAvailable(ImageReader reader) {
62
- try (Image image = reader.acquireLatestImage()) {
63
- if (image != null) {
64
- HardwareBuffer hb = image.getHardwareBuffer();
65
- if (mDebug) {
66
- textureUpdated(image.getTimestamp());
67
- }
68
- if (hb != null) {
69
- Bitmap bitmap = Bitmap.wrapHardwareBuffer(hb, null);
70
- if (bitmap != null) {
71
- mBitmap = bitmap;
72
- hb.close();
73
- invalidate();
74
- }
75
- }
76
- }
77
- }
78
- }
79
-
80
- @Override
81
- protected void onDraw(@NonNull Canvas canvas) {
82
- super.onDraw(canvas);
83
- if (mBitmap != null) {
84
- float viewWidth = getWidth();
85
- float viewHeight = getHeight();
86
- float bitmapWidth = mBitmap.getWidth();
87
- float bitmapHeight = mBitmap.getHeight();
88
-
89
- // Calculate the scale factors
90
- float scaleX = viewWidth / bitmapWidth;
91
- float scaleY = viewHeight / bitmapHeight;
92
-
93
- // Reset the matrix and apply scaling
94
- matrix.reset();
95
- matrix.setScale(scaleX, scaleY);
96
-
97
- canvas.drawBitmap(mBitmap, matrix, null);
98
- }
99
- }
100
-
101
- private long _prevTimestamp = 0;
102
- public void textureUpdated(long ts) {
103
- long frameDuration = (ts - _prevTimestamp)/1000000;
104
- Log.i("SkiaAHBView", "onSurfaceTextureUpdated "+frameDuration+"ms");
105
- _prevTimestamp = ts;
106
- }
107
-
108
- @Override
109
- protected void onDetachedFromWindow() {
110
- super.onDetachedFromWindow();
111
- mApi.onSurfaceDestroyed();
112
- }
113
- }
@@ -1,136 +0,0 @@
1
- package com.shopify.reactnative.skia;
2
-
3
- import android.content.Context;
4
- import android.graphics.SurfaceTexture;
5
- import android.util.Log;
6
- import android.view.MotionEvent;
7
- import android.view.Surface;
8
- import android.view.View;
9
-
10
- import com.facebook.react.uimanager.PointerEvents;
11
- import com.facebook.react.views.view.ReactViewGroup;
12
-
13
- public abstract class SkiaBaseView extends ReactViewGroup implements SkiaViewAPI {
14
- private View mView;
15
-
16
- private boolean mHighBitDepth = false;
17
-
18
- private final boolean debug = false;
19
- private final String tag = "SkiaView";
20
-
21
- public SkiaBaseView(Context context) {
22
- super(context);
23
- mView = new SkiaTextureView(context, this, debug);
24
- addView(mView);
25
- }
26
-
27
- @Override
28
- public boolean dispatchTouchEvent(MotionEvent ev) {
29
- // When pointerEvents is "none" or "box-none", make this view completely
30
- // transparent to touch dispatch so events pass through to views behind it
31
- if (!PointerEvents.canBeTouchTarget(getPointerEvents())) {
32
- return false;
33
- }
34
- return super.dispatchTouchEvent(ev);
35
- }
36
-
37
- public void setOpaque(boolean value) {
38
- if (value && mView instanceof SkiaTextureView) {
39
- recreateView(true);
40
- } else if (!value && mView instanceof SkiaSurfaceView) {
41
- recreateView(false);
42
- }
43
- }
44
-
45
- public void setHighBitDepth(boolean value) {
46
- if (mHighBitDepth == value) {
47
- return;
48
- }
49
- mHighBitDepth = value;
50
- // The flag only affects the opaque SurfaceView path (see
51
- // highBitDepthIfOpaque), so only that surface needs to be recreated
52
- // with the new buffer format.
53
- if (mView instanceof SkiaSurfaceView) {
54
- recreateView(true);
55
- }
56
- }
57
-
58
- private void recreateView(boolean useSurfaceView) {
59
- removeView(mView);
60
- mView = useSurfaceView
61
- ? new SkiaSurfaceView(getContext(), this, debug)
62
- : new SkiaTextureView(getContext(), this, debug);
63
- addView(mView);
64
- // React Native sizes native children explicitly through onLayout, so
65
- // the requestLayout triggered by addView is ignored; size the new
66
- // child ourselves or it stays 0x0 and never gets a surface.
67
- if (getWidth() > 0 || getHeight() > 0) {
68
- mView.layout(0, 0, getWidth(), getHeight());
69
- }
70
- }
71
-
72
- private boolean highBitDepthIfOpaque(boolean opaque) {
73
- if (mHighBitDepth && !opaque) {
74
- // The 10-bit buffer format only has 2 bits of alpha, which would
75
- // visibly break translucency; the extra precision would also be
76
- // lost in the 8-bit composition pass.
77
- Log.w(tag, "highBitDepth requires the opaque prop on Android, falling back to the 8-bit format");
78
- return false;
79
- }
80
- return mHighBitDepth;
81
- }
82
-
83
- void dropInstance() {
84
- if (!RNSkiaModule.isModuleValid()) {
85
- return;
86
- }
87
- unregisterView();
88
- }
89
-
90
- @Override
91
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
92
- super.onLayout(changed, left, top, right, bottom);
93
- mView.layout(0, 0, right - left, bottom - top);
94
- }
95
-
96
- @Override
97
- public void onSurfaceCreated(Surface surface, int width, int height) {
98
- surfaceAvailable(surface, width, height, true, mHighBitDepth);
99
- }
100
-
101
- @Override
102
- public void onSurfaceChanged(Surface surface, int width, int height) {
103
- Log.i(tag, "onSurfaceTextureSizeChanged " + width + "/" + height);
104
- surfaceSizeChanged(surface, width, height, true, mHighBitDepth);
105
- }
106
-
107
- @Override
108
- public void onSurfaceTextureCreated(SurfaceTexture surface, int width, int height) {
109
- surfaceAvailable(surface, width, height, false, highBitDepthIfOpaque(false));
110
- }
111
-
112
- @Override
113
- public void onSurfaceTextureChanged(SurfaceTexture surface, int width, int height) {
114
- Log.i(tag, "onSurfaceTextureSizeChanged " + width + "/" + height);
115
- surfaceSizeChanged(surface, width, height, false, highBitDepthIfOpaque(false));
116
- }
117
-
118
- @Override
119
- public void onSurfaceDestroyed() {
120
- surfaceDestroyed();
121
- }
122
-
123
- protected abstract void surfaceAvailable(Object surface, int width, int height, boolean opaque, boolean highBitDepth);
124
-
125
- protected abstract void surfaceSizeChanged(Object surface, int width, int height, boolean opaque, boolean highBitDepth);
126
-
127
- protected abstract void surfaceDestroyed();
128
-
129
- protected abstract void setDebugMode(boolean show);
130
-
131
- protected abstract void registerView(int nativeId);
132
-
133
- protected abstract void unregisterView();
134
-
135
- protected abstract int[] getBitmap(int width, int height);
136
- }
@@ -1,41 +0,0 @@
1
- /**
2
- * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
3
- *
4
- * Do not edit this file as changes may cause incorrect behavior and will be lost
5
- * once the code is regenerated.
6
- *
7
- * @generated by codegen project: GeneratePropsJavaDelegate.js
8
- */
9
-
10
- package com.facebook.react.viewmanagers;
11
-
12
- import android.view.View;
13
- import androidx.annotation.Nullable;
14
- import com.facebook.react.uimanager.BaseViewManagerDelegate;
15
- import com.facebook.react.uimanager.BaseViewManager;
16
- import com.facebook.react.uimanager.LayoutShadowNode;
17
-
18
- public class SkiaPictureViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & SkiaPictureViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
19
- public SkiaPictureViewManagerDelegate(U viewManager) {
20
- super(viewManager);
21
- }
22
- @Override
23
- public void setProperty(T view, String propName, @Nullable Object value) {
24
- switch (propName) {
25
- case "debug":
26
- mViewManager.setDebug(view, value != null && (boolean) value);
27
- break;
28
- case "opaque":
29
- mViewManager.setOpaque(view, value != null && (boolean) value);
30
- break;
31
- case "colorSpace":
32
- mViewManager.setColorSpace(view, value == null ? null : (String) value);
33
- break;
34
- case "androidWarmup":
35
- mViewManager.setAndroidWarmup(view, value != null && (boolean) value);
36
- break;
37
- default:
38
- super.setProperty(view, propName, value);
39
- }
40
- }
41
- }
@@ -1,20 +0,0 @@
1
- /**
2
- * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
3
- *
4
- * Do not edit this file as changes may cause incorrect behavior and will be lost
5
- * once the code is regenerated.
6
- *
7
- * @generated by codegen project: GeneratePropsJavaInterface.js
8
- */
9
-
10
- package com.facebook.react.viewmanagers;
11
-
12
- import android.view.View;
13
- import androidx.annotation.Nullable;
14
-
15
- public interface SkiaPictureViewManagerInterface<T extends View> {
16
- void setDebug(T view, boolean value);
17
- void setOpaque(T view, boolean value);
18
- void setColorSpace(T view, @Nullable String value);
19
- void setAndroidWarmup(T view, boolean value);
20
- }
@@ -1,35 +0,0 @@
1
- /**
2
- * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen).
3
- *
4
- * Do not edit this file as changes may cause incorrect behavior and will be lost
5
- * once the code is regenerated.
6
- *
7
- * @generated by codegen project: GeneratePropsJavaDelegate.js
8
- */
9
-
10
- package com.facebook.react.viewmanagers;
11
-
12
- import android.view.View;
13
- import androidx.annotation.Nullable;
14
- import com.facebook.react.uimanager.BaseViewManagerDelegate;
15
- import com.facebook.react.uimanager.BaseViewManager;
16
- import com.facebook.react.uimanager.LayoutShadowNode;
17
-
18
- public class SkiaWebGPUViewManagerDelegate<T extends View, U extends BaseViewManager<T, ? extends LayoutShadowNode> & SkiaWebGPUViewManagerInterface<T>> extends BaseViewManagerDelegate<T, U> {
19
- public SkiaWebGPUViewManagerDelegate(U viewManager) {
20
- super(viewManager);
21
- }
22
- @Override
23
- public void setProperty(T view, String propName, @Nullable Object value) {
24
- switch (propName) {
25
- case "contextId":
26
- mViewManager.setContextId(view, value == null ? 0 : ((Double) value).intValue());
27
- break;
28
- case "transparent":
29
- mViewManager.setTransparent(view, value != null && (boolean) value);
30
- break;
31
- default:
32
- super.setProperty(view, propName, value);
33
- }
34
- }
35
- }