@shopify/react-native-skia 0.1.116 → 0.1.120

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 (213) hide show
  1. package/cpp/api/JsiSkApi.h +13 -9
  2. package/cpp/api/JsiSkCanvas.h +9 -1
  3. package/cpp/api/JsiSkPicture.h +71 -0
  4. package/cpp/api/JsiSkPictureFactory.h +50 -0
  5. package/cpp/api/JsiSkPictureRecorder.h +53 -0
  6. package/ios/RNSkia-iOS/RNSkDrawViewImpl.h +3 -6
  7. package/ios/RNSkia-iOS/RNSkDrawViewImpl.mm +2 -4
  8. package/ios/RNSkia-iOS/SkiaDrawView.mm +3 -2
  9. package/lib/commonjs/renderer/Canvas.js +22 -36
  10. package/lib/commonjs/renderer/Canvas.js.map +1 -1
  11. package/lib/commonjs/renderer/HostConfig.js +3 -25
  12. package/lib/commonjs/renderer/HostConfig.js.map +1 -1
  13. package/lib/commonjs/renderer/components/{Defs.js → Drawing.js} +13 -12
  14. package/lib/commonjs/renderer/components/Drawing.js.map +1 -0
  15. package/lib/commonjs/renderer/components/Group.js +7 -4
  16. package/lib/commonjs/renderer/components/Group.js.map +1 -1
  17. package/lib/commonjs/renderer/components/Paint.js +1 -21
  18. package/lib/commonjs/renderer/components/Paint.js.map +1 -1
  19. package/lib/commonjs/renderer/components/Picture.js +35 -0
  20. package/lib/commonjs/renderer/components/Picture.js.map +1 -0
  21. package/lib/commonjs/renderer/components/imageFilters/InnerShadow.js +5 -34
  22. package/lib/commonjs/renderer/components/imageFilters/InnerShadow.js.map +1 -1
  23. package/lib/commonjs/renderer/components/imageFilters/{DropShadow.js → Shadow.js} +19 -8
  24. package/lib/commonjs/renderer/components/imageFilters/Shadow.js.map +1 -0
  25. package/lib/commonjs/renderer/components/imageFilters/index.js +4 -17
  26. package/lib/commonjs/renderer/components/imageFilters/index.js.map +1 -1
  27. package/lib/commonjs/renderer/components/index.js +17 -4
  28. package/lib/commonjs/renderer/components/index.js.map +1 -1
  29. package/lib/commonjs/renderer/components/maskFilters/Blur.js +1 -1
  30. package/lib/commonjs/renderer/components/maskFilters/Blur.js.map +1 -1
  31. package/lib/commonjs/renderer/components/shapes/Box.js +126 -0
  32. package/lib/commonjs/renderer/components/shapes/Box.js.map +1 -0
  33. package/lib/commonjs/renderer/components/shapes/index.js +13 -0
  34. package/lib/commonjs/renderer/components/shapes/index.js.map +1 -1
  35. package/lib/commonjs/renderer/index.js +13 -0
  36. package/lib/commonjs/renderer/index.js.map +1 -1
  37. package/lib/commonjs/renderer/nodes/Declaration.js +12 -1
  38. package/lib/commonjs/renderer/nodes/Declaration.js.map +1 -1
  39. package/lib/commonjs/renderer/nodes/Drawing.js +9 -24
  40. package/lib/commonjs/renderer/nodes/Drawing.js.map +1 -1
  41. package/lib/commonjs/renderer/nodes/Node.js +9 -16
  42. package/lib/commonjs/renderer/nodes/Node.js.map +1 -1
  43. package/lib/commonjs/renderer/processors/Paint.js +24 -26
  44. package/lib/commonjs/renderer/processors/Paint.js.map +1 -1
  45. package/lib/commonjs/renderer/processors/math/Math.js +19 -1
  46. package/lib/commonjs/renderer/processors/math/Math.js.map +1 -1
  47. package/lib/commonjs/renderer/processors/math/Matrix3.js +11 -5
  48. package/lib/commonjs/renderer/processors/math/Matrix3.js.map +1 -1
  49. package/lib/commonjs/renderer/typeddash.js +26 -2
  50. package/lib/commonjs/renderer/typeddash.js.map +1 -1
  51. package/lib/commonjs/renderer/useContextBridge.js +35 -0
  52. package/lib/commonjs/renderer/useContextBridge.js.map +1 -0
  53. package/lib/commonjs/skia/Canvas.js.map +1 -1
  54. package/lib/commonjs/skia/Picture/Picture.js +6 -0
  55. package/lib/commonjs/skia/Picture/Picture.js.map +1 -0
  56. package/lib/commonjs/skia/Picture/PictureFactory.js +6 -0
  57. package/lib/commonjs/skia/Picture/PictureFactory.js.map +1 -0
  58. package/lib/commonjs/skia/Picture/PictureRecorder.js +6 -0
  59. package/lib/commonjs/skia/Picture/PictureRecorder.js.map +1 -0
  60. package/lib/commonjs/skia/Picture/index.js +58 -0
  61. package/lib/commonjs/skia/Picture/index.js.map +1 -0
  62. package/lib/commonjs/skia/Picture/usePicture.js +30 -0
  63. package/lib/commonjs/skia/Picture/usePicture.js.map +1 -0
  64. package/lib/commonjs/skia/Skia.js +2 -0
  65. package/lib/commonjs/skia/Skia.js.map +1 -1
  66. package/lib/commonjs/skia/index.js +14 -0
  67. package/lib/commonjs/skia/index.js.map +1 -1
  68. package/lib/commonjs/values/hooks/useDerivedValue.js +2 -2
  69. package/lib/commonjs/values/hooks/useDerivedValue.js.map +1 -1
  70. package/lib/commonjs/views/SkiaView.js +6 -5
  71. package/lib/commonjs/views/SkiaView.js.map +1 -1
  72. package/lib/commonjs/views/types.js.map +1 -1
  73. package/lib/module/renderer/Canvas.js +20 -32
  74. package/lib/module/renderer/Canvas.js.map +1 -1
  75. package/lib/module/renderer/HostConfig.js +2 -24
  76. package/lib/module/renderer/HostConfig.js.map +1 -1
  77. package/lib/module/renderer/components/Drawing.js +17 -0
  78. package/lib/module/renderer/components/Drawing.js.map +1 -0
  79. package/lib/module/renderer/components/Group.js +8 -6
  80. package/lib/module/renderer/components/Group.js.map +1 -1
  81. package/lib/module/renderer/components/Paint.js +2 -22
  82. package/lib/module/renderer/components/Paint.js.map +1 -1
  83. package/lib/module/renderer/components/Picture.js +21 -0
  84. package/lib/module/renderer/components/Picture.js.map +1 -0
  85. package/lib/module/renderer/components/imageFilters/InnerShadow.js +4 -26
  86. package/lib/module/renderer/components/imageFilters/InnerShadow.js.map +1 -1
  87. package/lib/module/renderer/components/imageFilters/{DropShadow.js → Shadow.js} +16 -6
  88. package/lib/module/renderer/components/imageFilters/Shadow.js.map +1 -0
  89. package/lib/module/renderer/components/imageFilters/index.js +1 -2
  90. package/lib/module/renderer/components/imageFilters/index.js.map +1 -1
  91. package/lib/module/renderer/components/index.js +2 -1
  92. package/lib/module/renderer/components/index.js.map +1 -1
  93. package/lib/module/renderer/components/maskFilters/Blur.js +1 -1
  94. package/lib/module/renderer/components/maskFilters/Blur.js.map +1 -1
  95. package/lib/module/renderer/components/shapes/Box.js +102 -0
  96. package/lib/module/renderer/components/shapes/Box.js.map +1 -0
  97. package/lib/module/renderer/components/shapes/index.js +1 -0
  98. package/lib/module/renderer/components/shapes/index.js.map +1 -1
  99. package/lib/module/renderer/index.js +1 -0
  100. package/lib/module/renderer/index.js.map +1 -1
  101. package/lib/module/renderer/nodes/Declaration.js +4 -0
  102. package/lib/module/renderer/nodes/Declaration.js.map +1 -1
  103. package/lib/module/renderer/nodes/Drawing.js +8 -21
  104. package/lib/module/renderer/nodes/Drawing.js.map +1 -1
  105. package/lib/module/renderer/nodes/Node.js +9 -15
  106. package/lib/module/renderer/nodes/Node.js.map +1 -1
  107. package/lib/module/renderer/processors/Paint.js +22 -21
  108. package/lib/module/renderer/processors/Paint.js.map +1 -1
  109. package/lib/module/renderer/processors/math/Math.js +15 -0
  110. package/lib/module/renderer/processors/math/Math.js.map +1 -1
  111. package/lib/module/renderer/processors/math/Matrix3.js +6 -2
  112. package/lib/module/renderer/processors/math/Matrix3.js.map +1 -1
  113. package/lib/module/renderer/typeddash.js +21 -0
  114. package/lib/module/renderer/typeddash.js.map +1 -1
  115. package/lib/module/renderer/useContextBridge.js +21 -0
  116. package/lib/module/renderer/useContextBridge.js.map +1 -0
  117. package/lib/module/skia/Canvas.js.map +1 -1
  118. package/lib/module/skia/Picture/Picture.js +2 -0
  119. package/lib/module/skia/Picture/Picture.js.map +1 -0
  120. package/lib/module/skia/Picture/PictureFactory.js +2 -0
  121. package/lib/module/skia/Picture/PictureFactory.js.map +1 -0
  122. package/lib/module/skia/Picture/PictureRecorder.js +2 -0
  123. package/lib/module/skia/Picture/PictureRecorder.js.map +1 -0
  124. package/lib/module/skia/Picture/index.js +5 -0
  125. package/lib/module/skia/Picture/index.js.map +1 -0
  126. package/lib/module/skia/Picture/usePicture.js +19 -0
  127. package/lib/module/skia/Picture/usePicture.js.map +1 -0
  128. package/lib/module/skia/Skia.js +2 -0
  129. package/lib/module/skia/Skia.js.map +1 -1
  130. package/lib/module/skia/index.js +1 -0
  131. package/lib/module/skia/index.js.map +1 -1
  132. package/lib/module/values/hooks/useDerivedValue.js +1 -1
  133. package/lib/module/values/hooks/useDerivedValue.js.map +1 -1
  134. package/lib/module/views/SkiaView.js +6 -5
  135. package/lib/module/views/SkiaView.js.map +1 -1
  136. package/lib/module/views/types.js.map +1 -1
  137. package/lib/typescript/src/renderer/Canvas.d.ts +5 -10
  138. package/lib/typescript/src/renderer/components/Drawing.d.ts +7 -0
  139. package/lib/typescript/src/renderer/components/Picture.d.ts +6 -0
  140. package/lib/typescript/src/renderer/components/imageFilters/InnerShadow.d.ts +3 -12
  141. package/lib/typescript/src/renderer/components/imageFilters/{DropShadow.d.ts → Shadow.d.ts} +3 -2
  142. package/lib/typescript/src/renderer/components/imageFilters/index.d.ts +1 -2
  143. package/lib/typescript/src/renderer/components/index.d.ts +2 -1
  144. package/lib/typescript/src/renderer/components/shapes/Box.d.ts +23 -0
  145. package/lib/typescript/src/renderer/components/shapes/index.d.ts +1 -0
  146. package/lib/typescript/src/renderer/index.d.ts +1 -0
  147. package/lib/typescript/src/renderer/nodes/Declaration.d.ts +3 -0
  148. package/lib/typescript/src/renderer/nodes/Drawing.d.ts +2 -2
  149. package/lib/typescript/src/renderer/nodes/Node.d.ts +2 -2
  150. package/lib/typescript/src/renderer/processors/Paint.d.ts +2 -2
  151. package/lib/typescript/src/renderer/processors/math/Math.d.ts +14 -0
  152. package/lib/typescript/src/renderer/processors/math/Matrix3.d.ts +1 -0
  153. package/lib/typescript/src/renderer/typeddash.d.ts +1 -0
  154. package/lib/typescript/src/renderer/useContextBridge.d.ts +5 -0
  155. package/lib/typescript/src/skia/Canvas.d.ts +6 -0
  156. package/lib/typescript/src/skia/Picture/Picture.d.ts +26 -0
  157. package/lib/typescript/src/skia/Picture/PictureFactory.d.ts +8 -0
  158. package/lib/typescript/src/skia/Picture/PictureRecorder.d.ts +15 -0
  159. package/lib/typescript/src/skia/Picture/index.d.ts +4 -0
  160. package/lib/typescript/src/skia/Picture/usePicture.d.ts +11 -0
  161. package/lib/typescript/src/skia/Skia.d.ts +5 -0
  162. package/lib/typescript/src/skia/index.d.ts +1 -0
  163. package/lib/typescript/src/views/SkiaView.d.ts +25 -1
  164. package/lib/typescript/src/views/types.d.ts +0 -24
  165. package/libs/ios/libskia.xcframework/ios-arm64_arm64e/libskia.a +0 -0
  166. package/libs/ios/libskia.xcframework/ios-arm64_arm64e_x86_64-simulator/libskia.a +0 -0
  167. package/libs/ios/libskshaper.xcframework/ios-arm64_arm64e/libskshaper.a +0 -0
  168. package/libs/ios/libskshaper.xcframework/ios-arm64_arm64e_x86_64-simulator/libskshaper.a +0 -0
  169. package/libs/ios/libsvg.xcframework/Info.plist +5 -5
  170. package/libs/ios/libsvg.xcframework/ios-arm64_arm64e/libsvg.a +0 -0
  171. package/libs/ios/libsvg.xcframework/ios-arm64_arm64e_x86_64-simulator/libsvg.a +0 -0
  172. package/package.json +1 -1
  173. package/src/renderer/Canvas.tsx +14 -30
  174. package/src/renderer/HostConfig.ts +2 -20
  175. package/src/renderer/components/Drawing.tsx +16 -0
  176. package/src/renderer/components/Group.tsx +25 -15
  177. package/src/renderer/components/Paint.tsx +5 -35
  178. package/src/renderer/components/Picture.tsx +17 -0
  179. package/src/renderer/components/imageFilters/InnerShadow.tsx +33 -47
  180. package/src/renderer/components/imageFilters/Shadow.tsx +39 -0
  181. package/src/renderer/components/imageFilters/index.ts +1 -2
  182. package/src/renderer/components/index.ts +2 -1
  183. package/src/renderer/components/maskFilters/Blur.tsx +1 -1
  184. package/src/renderer/components/shapes/Box.tsx +98 -0
  185. package/src/renderer/components/shapes/index.ts +1 -0
  186. package/src/renderer/index.ts +1 -0
  187. package/src/renderer/nodes/Declaration.tsx +14 -0
  188. package/src/renderer/nodes/Drawing.tsx +16 -26
  189. package/src/renderer/nodes/Node.ts +9 -12
  190. package/src/renderer/processors/Paint.ts +34 -31
  191. package/src/renderer/processors/math/Math.ts +16 -0
  192. package/src/renderer/processors/math/Matrix3.ts +35 -31
  193. package/src/renderer/typeddash.ts +18 -0
  194. package/src/renderer/useContextBridge.tsx +21 -0
  195. package/src/skia/Canvas.ts +7 -0
  196. package/src/skia/Picture/Picture.ts +34 -0
  197. package/src/skia/Picture/PictureFactory.ts +9 -0
  198. package/src/skia/Picture/PictureRecorder.ts +18 -0
  199. package/src/skia/Picture/index.ts +4 -0
  200. package/src/skia/Picture/usePicture.ts +28 -0
  201. package/src/skia/Skia.ts +5 -0
  202. package/src/skia/index.ts +1 -0
  203. package/src/values/hooks/useDerivedValue.ts +1 -1
  204. package/src/views/SkiaView.tsx +27 -3
  205. package/src/views/types.ts +0 -25
  206. package/lib/commonjs/renderer/components/Defs.js.map +0 -1
  207. package/lib/commonjs/renderer/components/imageFilters/DropShadow.js.map +0 -1
  208. package/lib/module/renderer/components/Defs.js +0 -16
  209. package/lib/module/renderer/components/Defs.js.map +0 -1
  210. package/lib/module/renderer/components/imageFilters/DropShadow.js.map +0 -1
  211. package/lib/typescript/src/renderer/components/Defs.d.ts +0 -5
  212. package/src/renderer/components/Defs.tsx +0 -19
  213. package/src/renderer/components/imageFilters/DropShadow.tsx +0 -31
@@ -6,32 +6,32 @@
6
6
  <array>
7
7
  <dict>
8
8
  <key>LibraryIdentifier</key>
9
- <string>ios-arm64_arm64e_x86_64-simulator</string>
9
+ <string>ios-arm64_arm64e</string>
10
10
  <key>LibraryPath</key>
11
11
  <string>libsvg.a</string>
12
12
  <key>SupportedArchitectures</key>
13
13
  <array>
14
14
  <string>arm64</string>
15
15
  <string>arm64e</string>
16
- <string>x86_64</string>
17
16
  </array>
18
17
  <key>SupportedPlatform</key>
19
18
  <string>ios</string>
20
- <key>SupportedPlatformVariant</key>
21
- <string>simulator</string>
22
19
  </dict>
23
20
  <dict>
24
21
  <key>LibraryIdentifier</key>
25
- <string>ios-arm64_arm64e</string>
22
+ <string>ios-arm64_arm64e_x86_64-simulator</string>
26
23
  <key>LibraryPath</key>
27
24
  <string>libsvg.a</string>
28
25
  <key>SupportedArchitectures</key>
29
26
  <array>
30
27
  <string>arm64</string>
31
28
  <string>arm64e</string>
29
+ <string>x86_64</string>
32
30
  </array>
33
31
  <key>SupportedPlatform</key>
34
32
  <string>ios</string>
33
+ <key>SupportedPlatformVariant</key>
34
+ <string>simulator</string>
35
35
  </dict>
36
36
  </array>
37
37
  <key>CFBundlePackageType</key>
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public"
5
5
  },
6
6
  "title": "React Native Skia",
7
- "version": "0.1.116",
7
+ "version": "0.1.120",
8
8
  "description": "High-performance React Native Graphics using Skia",
9
9
  "main": "lib/module/index.js",
10
10
  "files": [
@@ -11,8 +11,6 @@ import type {
11
11
  RefObject,
12
12
  ReactNode,
13
13
  ComponentProps,
14
- Context,
15
- ReactElement,
16
14
  MutableRefObject,
17
15
  ForwardedRef,
18
16
  } from "react";
@@ -23,6 +21,8 @@ import { SkiaView, useDrawCallback } from "../views";
23
21
  import type { TouchHandler } from "../views";
24
22
  import { Skia } from "../skia";
25
23
  import type { FontMgr } from "../skia/FontMgr/FontMgr";
24
+ import { useValue } from "../values/hooks/useValue";
25
+ import type { SkiaReadonlyValue } from "../values/types";
26
26
 
27
27
  import { debug as hostDebug, skHostConfig } from "./HostConfig";
28
28
  // import { debugTree } from "./nodes";
@@ -30,33 +30,12 @@ import { vec } from "./processors";
30
30
  import { Container } from "./nodes";
31
31
  import { DependencyManager } from "./DependencyManager";
32
32
 
33
- // useContextBridge() is taken from https://github.com/pmndrs/drei#usecontextbridge
34
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
35
- export const useContextBridge = (...contexts: Context<any>[]) => {
36
- const values =
37
- // eslint-disable-next-line react-hooks/rules-of-hooks
38
- contexts.map((context) => useContext(context));
39
- return useMemo(
40
- () =>
41
- ({ children }: { children: ReactNode }) =>
42
- contexts.reduceRight(
43
- (acc, Context, i) => (
44
- <Context.Provider value={values[i]} children={acc} />
45
- ),
46
- children
47
- ) as ReactElement,
48
- [contexts, values]
49
- );
50
- };
51
-
52
- interface CanvasContext {
33
+ const CanvasContext = React.createContext<SkiaReadonlyValue<{
53
34
  width: number;
54
35
  height: number;
55
- }
36
+ }> | null>(null);
56
37
 
57
- const CanvasContext = React.createContext<CanvasContext | null>(null);
58
-
59
- export const useCanvas = () => {
38
+ export const useCanvasSize = () => {
60
39
  const canvas = useContext(CanvasContext);
61
40
  if (!canvas) {
62
41
  throw new Error("Canvas context is not available");
@@ -93,6 +72,7 @@ const defaultFontMgr = Skia.FontMgr.RefDefault();
93
72
 
94
73
  export const Canvas = forwardRef<SkiaView, CanvasProps>(
95
74
  ({ children, style, debug, mode, onTouch, fontMgr }, forwardedRef) => {
75
+ const canvasCtx = useValue({ width: 0, height: 0 });
96
76
  const innerRef = useCanvasRef();
97
77
  const ref = useCombinedRefs(forwardedRef, innerRef);
98
78
  const [tick, setTick] = useState(0);
@@ -103,7 +83,6 @@ export const Canvas = forwardRef<SkiaView, CanvasProps>(
103
83
  [redraw, ref]
104
84
  );
105
85
 
106
- const canvasCtx = useRef({ width: 0, height: 0 });
107
86
  const root = useMemo(
108
87
  () => skiaReconciler.createContainer(container, 0, false, null),
109
88
  [container]
@@ -111,13 +90,13 @@ export const Canvas = forwardRef<SkiaView, CanvasProps>(
111
90
  // Render effect
112
91
  useEffect(() => {
113
92
  render(
114
- <CanvasContext.Provider value={canvasCtx.current}>
93
+ <CanvasContext.Provider value={canvasCtx}>
115
94
  {children}
116
95
  </CanvasContext.Provider>,
117
96
  root,
118
97
  container
119
98
  );
120
- }, [children, root, redraw, container]);
99
+ }, [children, root, redraw, container, canvasCtx]);
121
100
 
122
101
  // Draw callback
123
102
  const onDraw = useDrawCallback(
@@ -127,6 +106,12 @@ export const Canvas = forwardRef<SkiaView, CanvasProps>(
127
106
  if (onTouch) {
128
107
  onTouch(info.touches);
129
108
  }
109
+ if (
110
+ width !== canvasCtx.current.width ||
111
+ height !== canvasCtx.current.height
112
+ ) {
113
+ canvasCtx.current = { width, height };
114
+ }
130
115
  const paint = Skia.Paint();
131
116
  paint.setAntiAlias(true);
132
117
  const ctx = {
@@ -140,7 +125,6 @@ export const Canvas = forwardRef<SkiaView, CanvasProps>(
140
125
  center: vec(width / 2, height / 2),
141
126
  fontMgr: fontMgr ?? defaultFontMgr,
142
127
  };
143
- canvasCtx.current = ctx;
144
128
  container.draw(ctx);
145
129
  },
146
130
  [tick, onTouch]
@@ -3,7 +3,7 @@ import type { HostConfig } from "react-reconciler";
3
3
 
4
4
  import type { Node, Container, DeclarationProps, DrawingProps } from "./nodes";
5
5
  import { DeclarationNode, DrawingNode, NodeType } from "./nodes";
6
- import { exhaustiveCheck, mapKeys } from "./typeddash";
6
+ import { exhaustiveCheck, shallowEq } from "./typeddash";
7
7
 
8
8
  const DEBUG = false;
9
9
  export const debug = (...args: Parameters<typeof console.log>) => {
@@ -53,24 +53,6 @@ type SkiaHostConfig = HostConfig<
53
53
  NoTimeout
54
54
  >;
55
55
 
56
- // Shallow eq on props (without children)
57
- const shallowEq = <P extends Props>(p1: P, p2: P): boolean => {
58
- const keys1 = mapKeys(p1);
59
- const keys2 = mapKeys(p2);
60
- if (keys1.length !== keys2.length) {
61
- return false;
62
- }
63
- for (const key of keys1) {
64
- if (key === "children") {
65
- continue;
66
- }
67
- if (p1[key] !== p2[key]) {
68
- return false;
69
- }
70
- }
71
- return true;
72
- };
73
-
74
56
  const allChildrenAreMemoized = (node: Instance) => {
75
57
  if (!node.memoizable) {
76
58
  return false;
@@ -87,7 +69,7 @@ const bustBranchMemoization = (parent: Node) => {
87
69
  if (parent.memoizable) {
88
70
  let ancestor: Node | undefined = parent;
89
71
  while (ancestor) {
90
- ancestor.memoized = false;
72
+ ancestor.memoized = null;
91
73
  ancestor = ancestor.parent;
92
74
  }
93
75
  }
@@ -0,0 +1,16 @@
1
+ import React from "react";
2
+
3
+ import type { DrawingContext } from "../DrawingContext";
4
+ import { createDrawing } from "../nodes/Drawing";
5
+
6
+ interface DrawingProps {
7
+ drawing: (ctx: DrawingContext) => void;
8
+ }
9
+
10
+ const onDraw = createDrawing<DrawingProps>((ctx, { drawing }) => {
11
+ drawing(ctx);
12
+ });
13
+
14
+ export const Drawing = (props: DrawingProps) => {
15
+ return <skDrawing onDraw={onDraw} skipProcessing {...props} />;
16
+ };
@@ -3,19 +3,15 @@ import type { RefObject } from "react";
3
3
 
4
4
  import type { SkPaint } from "../../skia";
5
5
  import { ClipOp } from "../../skia";
6
- import {
7
- processTransform,
8
- selectPaint,
9
- processPaint,
10
- processClip,
11
- } from "../processors";
6
+ import { processTransform, processPaint, processClip } from "../processors";
12
7
  import type {
13
8
  CustomPaintProps,
14
9
  TransformProps,
15
10
  AnimatedProps,
16
11
  ClipDef,
17
12
  } from "../processors";
18
- import { createDrawing } from "../nodes";
13
+ import { createDrawing, DrawingNode } from "../nodes";
14
+ import { isDeclarationNode } from "../nodes/Declaration";
19
15
 
20
16
  const isSkPaint = (obj: RefObject<SkPaint> | SkPaint): obj is SkPaint =>
21
17
  "__typename__" in obj && obj.__typename__ === "Paint";
@@ -29,11 +25,22 @@ export interface GroupProps extends CustomPaintProps, TransformProps {
29
25
  const onDraw = createDrawing<GroupProps>(
30
26
  (ctx, { layer, clip, invertClip, ...groupProps }, node) => {
31
27
  const { canvas, opacity } = ctx;
32
- const paint = selectPaint(ctx.paint, groupProps);
33
- processPaint(paint, opacity, groupProps);
28
+ const declarations = node.children
29
+ .filter(isDeclarationNode)
30
+ .map((child) => child.draw(ctx));
31
+
32
+ const drawings = node.children.filter(
33
+ (child) => child instanceof DrawingNode
34
+ );
35
+ const paint = processPaint(
36
+ ctx.paint.copy(),
37
+ opacity,
38
+ groupProps,
39
+ declarations
40
+ );
34
41
  const hasTransform = !!groupProps.transform || !!groupProps.matrix;
35
42
  const hasClip = !!clip;
36
- const shouldSave = hasTransform || hasClip;
43
+ const shouldSave = hasTransform || hasClip || !!layer;
37
44
  if (shouldSave) {
38
45
  if (layer) {
39
46
  if (typeof layer === "boolean") {
@@ -52,11 +59,14 @@ const onDraw = createDrawing<GroupProps>(
52
59
  processClip(canvas, clip, op);
53
60
  }
54
61
  }
55
- node.visit({
56
- ...ctx,
57
- paint,
58
- opacity: groupProps.opacity ? groupProps.opacity * opacity : opacity,
59
- });
62
+ node.visit(
63
+ {
64
+ ...ctx,
65
+ paint,
66
+ opacity: groupProps.opacity ? groupProps.opacity * opacity : opacity,
67
+ },
68
+ drawings
69
+ );
60
70
  if (shouldSave) {
61
71
  canvas.restore();
62
72
  }
@@ -1,15 +1,8 @@
1
1
  import type { ReactNode } from "react";
2
2
  import React, { useRef, useMemo, forwardRef, useImperativeHandle } from "react";
3
3
 
4
- import type { SkPaint, SkImageFilter } from "../../skia";
5
- import {
6
- isShader,
7
- isMaskFilter,
8
- isColorFilter,
9
- Skia,
10
- isImageFilter,
11
- isPathEffect,
12
- } from "../../skia";
4
+ import type { SkPaint } from "../../skia";
5
+ import { Skia } from "../../skia";
13
6
  import type { CustomPaintProps, AnimatedProps } from "../processors";
14
7
  import { processPaint } from "../processors";
15
8
  import { createDeclaration } from "../nodes";
@@ -26,32 +19,9 @@ export const Paint = forwardRef<SkPaint, AnimatedProps<PaintProps>>(
26
19
  useImperativeHandle(ref, () => paint, [paint]);
27
20
  const onDeclare = useMemo(
28
21
  () =>
29
- createDeclaration<PaintProps>((paintProps, children, ctx) => {
30
- processPaint(paint, ctx.opacity, paintProps);
31
- children.forEach((child) => {
32
- if (isShader(child)) {
33
- paint.setShader(child);
34
- } else if (isMaskFilter(child)) {
35
- paint.setMaskFilter(child);
36
- } else if (isColorFilter(child)) {
37
- paint.setColorFilter(child);
38
- } else if (isPathEffect(child)) {
39
- paint.setPathEffect(child);
40
- }
41
- });
42
- const filters = children.filter(isImageFilter);
43
- if (filters.length > 0) {
44
- paint.setImageFilter(
45
- filters
46
- .reverse()
47
- .reduce<SkImageFilter | null>(
48
- Skia.ImageFilter.MakeCompose,
49
- null
50
- )
51
- );
52
- }
53
- return paint;
54
- }),
22
+ createDeclaration<PaintProps>((paintProps, children, ctx) =>
23
+ processPaint(paint, ctx.opacity, paintProps, children)
24
+ ),
55
25
  [paint]
56
26
  );
57
27
  return <skDeclaration onDeclare={onDeclare} {...props} />;
@@ -0,0 +1,17 @@
1
+ import React from "react";
2
+
3
+ import type { SkPicture } from "../../skia";
4
+ import { createDrawing } from "../nodes/Drawing";
5
+
6
+ export interface PictureProps {
7
+ picture: SkPicture;
8
+ }
9
+
10
+ const onDraw = createDrawing<PictureProps>((ctx, { picture }) => {
11
+ const { canvas } = ctx;
12
+ canvas.drawPicture(picture);
13
+ });
14
+
15
+ export const Picture = (props: PictureProps) => {
16
+ return <skDrawing onDraw={onDraw} {...props} skipProcessing />;
17
+ };
@@ -1,50 +1,36 @@
1
- import React from "react";
1
+ import type { SkColor } from "../../../skia";
2
+ import { BlendMode, Skia, TileMode } from "../../../skia";
3
+ import type { SkImageFilter } from "../../../skia/ImageFilter/ImageFilter";
2
4
 
3
- import { BlendMode, Skia, TileMode, processColor } from "../../../skia";
4
- import { createDeclaration } from "../../nodes/Declaration";
5
- import type { AnimatedProps } from "../../processors";
6
- import type { Color } from "../../../skia";
7
-
8
- import { getInput } from "./getInput";
9
-
10
- export interface InnerShadowProps {
11
- dx: number;
12
- dy: number;
13
- blur: number;
14
- color: Color;
15
- shadowOnly?: boolean;
16
- inner?: boolean;
17
- }
18
-
19
- const onDeclare = createDeclaration<InnerShadowProps>(
20
- ({ dx, dy, blur, color, shadowOnly }, children, { opacity }) => {
21
- const input = getInput(children);
22
- const cl = processColor(color, opacity);
23
- const sourceGraphic = Skia.ImageFilter.MakeColorFilter(
24
- Skia.ColorFilter.MakeBlend(0xff000000, BlendMode.Dst),
25
- null
26
- );
27
- const sourceAlpha = Skia.ImageFilter.MakeColorFilter(
28
- Skia.ColorFilter.MakeBlend(0xff000000, BlendMode.SrcIn),
29
- null
30
- );
31
- const f1 = Skia.ImageFilter.MakeColorFilter(
32
- Skia.ColorFilter.MakeBlend(cl, BlendMode.SrcOut),
33
- null
34
- );
35
- const f2 = Skia.ImageFilter.MakeOffset(dx, dy, f1);
36
- const f3 = Skia.ImageFilter.MakeBlur(blur, blur, TileMode.Decal, f2);
37
- const f4 = Skia.ImageFilter.MakeBlend(BlendMode.SrcIn, sourceAlpha, f3);
38
- if (shadowOnly) {
39
- return f4;
40
- }
41
- return Skia.ImageFilter.MakeCompose(
42
- input,
43
- Skia.ImageFilter.MakeBlend(BlendMode.SrcOver, sourceGraphic, f4)
44
- );
5
+ export const MakeInnerShadow = (
6
+ shadowOnly: boolean | undefined,
7
+ dx: number,
8
+ dy: number,
9
+ sigmaX: number,
10
+ sigmaY: number,
11
+ color: SkColor,
12
+ input: SkImageFilter | null
13
+ ) => {
14
+ const sourceGraphic = Skia.ImageFilter.MakeColorFilter(
15
+ Skia.ColorFilter.MakeBlend(0xff000000, BlendMode.Dst),
16
+ null
17
+ );
18
+ const sourceAlpha = Skia.ImageFilter.MakeColorFilter(
19
+ Skia.ColorFilter.MakeBlend(0xff000000, BlendMode.SrcIn),
20
+ null
21
+ );
22
+ const f1 = Skia.ImageFilter.MakeColorFilter(
23
+ Skia.ColorFilter.MakeBlend(color, BlendMode.SrcOut),
24
+ null
25
+ );
26
+ const f2 = Skia.ImageFilter.MakeOffset(dx, dy, f1);
27
+ const f3 = Skia.ImageFilter.MakeBlur(sigmaX, sigmaY, TileMode.Decal, f2);
28
+ const f4 = Skia.ImageFilter.MakeBlend(BlendMode.SrcIn, sourceAlpha, f3);
29
+ if (shadowOnly) {
30
+ return f4;
45
31
  }
46
- );
47
-
48
- export const InnerShadow = (props: AnimatedProps<InnerShadowProps>) => {
49
- return <skDeclaration onDeclare={onDeclare} {...props} />;
32
+ return Skia.ImageFilter.MakeCompose(
33
+ input,
34
+ Skia.ImageFilter.MakeBlend(BlendMode.SrcOver, sourceGraphic, f4)
35
+ );
50
36
  };
@@ -0,0 +1,39 @@
1
+ import React from "react";
2
+
3
+ import { Skia } from "../../../skia";
4
+ import { createDeclaration } from "../../nodes/Declaration";
5
+ import type { AnimatedProps } from "../../processors/Animations/Animations";
6
+ import type { Color } from "../../../skia/Color";
7
+ import { processColor } from "../../../skia/Color";
8
+
9
+ import { getInput } from "./getInput";
10
+ import { MakeInnerShadow } from "./InnerShadow";
11
+
12
+ export interface ShadowProps {
13
+ dx: number;
14
+ dy: number;
15
+ blur: number;
16
+ color: Color;
17
+ inner?: boolean;
18
+ shadowOnly?: boolean;
19
+ }
20
+
21
+ const onDeclare = createDeclaration<ShadowProps>(
22
+ ({ dx, dy, blur, color: cl, shadowOnly, inner }, children, { opacity }) => {
23
+ const input = getInput(children);
24
+ const color = processColor(cl, opacity);
25
+ let factory;
26
+ if (inner) {
27
+ factory = MakeInnerShadow.bind(null, shadowOnly);
28
+ } else {
29
+ factory = shadowOnly
30
+ ? Skia.ImageFilter.MakeDropShadowOnly
31
+ : Skia.ImageFilter.MakeDropShadow;
32
+ }
33
+ return factory(dx, dy, blur, blur, color, input);
34
+ }
35
+ );
36
+
37
+ export const Shadow = (props: AnimatedProps<ShadowProps>) => {
38
+ return <skDeclaration onDeclare={onDeclare} {...props} />;
39
+ };
@@ -1,6 +1,5 @@
1
1
  export * from "./Blur";
2
2
  export * from "./Offset";
3
3
  export * from "./DisplacementMap";
4
- export * from "./DropShadow";
5
- export * from "./InnerShadow";
4
+ export * from "./Shadow";
6
5
  export * from "./Morphology";
@@ -8,10 +8,11 @@ export * from "./maskFilters";
8
8
  export * from "./imageFilters";
9
9
  export * from "./pathEffects";
10
10
  export * from "../processors";
11
+ export * from "./Picture";
11
12
 
12
13
  export * from "./Group";
13
14
  export * from "./Mask";
14
15
  export * from "./Paint";
15
16
  export * from "./Compose";
16
17
  export * from "./Blend";
17
- export * from "./Defs";
18
+ export * from "./Drawing";
@@ -29,5 +29,5 @@ export const BlurMask = (props: AnimatedProps<BlurMaskProps>) => {
29
29
 
30
30
  BlurMask.defaultProps = {
31
31
  style: "normal",
32
- respectCTM: false,
32
+ respectCTM: true,
33
33
  };
@@ -0,0 +1,98 @@
1
+ import React from "react";
2
+
3
+ import type { Color, SkRRect } from "../../../skia";
4
+ import { ClipOp, BlurStyle, Skia, processColor } from "../../../skia";
5
+ import { createDrawing } from "../../nodes";
6
+ import type { AnimatedProps, CustomPaintProps } from "../../processors";
7
+ import { add, vec, rrect } from "../../processors";
8
+ import { rect, isRRect } from "../../processors/Rects";
9
+ import { createDeclaration } from "../../nodes/Declaration";
10
+ import type { SkJSIInstance } from "../../../skia/JsiInstance";
11
+ import type { SkRect } from "../../../skia/Rect";
12
+
13
+ const inflate = (box: SkRRect, dx: number, dy: number, tx = 0, ty = 0) =>
14
+ rrect(
15
+ rect(
16
+ box.rect.x - dx + tx,
17
+ box.rect.y - dy + ty,
18
+ box.rect.width + 2 * dx,
19
+ box.rect.height + 2 * dy
20
+ ),
21
+ box.rx + dx,
22
+ box.ry + dy
23
+ );
24
+
25
+ const deflate = (box: SkRRect, dx: number, dy: number, tx = 0, ty = 0) =>
26
+ inflate(box, -dx, -dy, tx, ty);
27
+
28
+ interface BoxShadowProps {
29
+ dx?: number;
30
+ dy?: number;
31
+ spread?: number;
32
+ blur: number;
33
+ color?: Color;
34
+ inner?: boolean;
35
+ }
36
+
37
+ interface BoxShadowDecl extends BoxShadowProps, SkJSIInstance<"BoxShadow"> {}
38
+
39
+ const onDeclare = createDeclaration<BoxShadowProps>(
40
+ ({ dx, dy, spread, blur, color, inner }) => {
41
+ return { dx, dy, spread, blur, color, inner, __typename__: "BoxShadow" };
42
+ }
43
+ );
44
+
45
+ export const BoxShadow = (props: AnimatedProps<BoxShadowProps>) => {
46
+ return <skDeclaration onDeclare={onDeclare} {...props} />;
47
+ };
48
+
49
+ const isBoxShadow = (s: SkJSIInstance<string>): s is BoxShadowDecl =>
50
+ s.__typename__ === "BoxShadow";
51
+
52
+ interface BoxProps extends CustomPaintProps {
53
+ box: SkRRect | SkRect;
54
+ }
55
+
56
+ const onDraw = createDrawing<BoxProps>((ctx, { box: defaultBox }, node) => {
57
+ const box = isRRect(defaultBox) ? defaultBox : rrect(defaultBox, 0, 0);
58
+ const { canvas, paint, opacity } = ctx;
59
+ const shadows = node.visit(ctx).filter<BoxShadowDecl>(isBoxShadow);
60
+ shadows
61
+ .filter((shadow) => !shadow.inner)
62
+ .map((shadow) => {
63
+ const { color = "black", blur, spread = 0, dx = 0, dy = 0 } = shadow;
64
+ const lPaint = Skia.Paint();
65
+ lPaint.setColor(processColor(color, opacity));
66
+ lPaint.setMaskFilter(
67
+ Skia.MaskFilter.MakeBlur(BlurStyle.Normal, blur, true)
68
+ );
69
+ canvas.drawRRect(inflate(box, spread, spread, dx, dy), lPaint);
70
+ });
71
+ canvas.drawRRect(box, paint);
72
+
73
+ shadows
74
+ .filter((shadow) => shadow.inner)
75
+ .map((shadow) => {
76
+ const { color = "black", blur, spread = 0, dx = 0, dy = 0 } = shadow;
77
+ const delta = add(vec(10, 10), vec(Math.abs(dx), Math.abs(dy)));
78
+ canvas.save();
79
+ canvas.clipRRect(box, ClipOp.Intersect, false);
80
+ const lPaint = Skia.Paint();
81
+ lPaint.setColor(processColor(color, opacity));
82
+ lPaint.setMaskFilter(
83
+ Skia.MaskFilter.MakeBlur(BlurStyle.Normal, blur, true)
84
+ );
85
+ const inner = deflate(box, spread, spread, dx, dy);
86
+ const outer = inflate(box, delta.x, delta.y);
87
+ canvas.drawDRRect(outer, inner, lPaint);
88
+ canvas.restore();
89
+ });
90
+ });
91
+
92
+ export const Box = (props: AnimatedProps<BoxProps>) => {
93
+ return <skDrawing onDraw={onDraw} {...props} />;
94
+ };
95
+
96
+ Box.defaultProps = {
97
+ shadows: [],
98
+ };
@@ -10,3 +10,4 @@ export * from "./Patch";
10
10
  export * from "./Vertices";
11
11
  export * from "./Fill";
12
12
  export * from "./FitBox";
13
+ export * from "./Box";
@@ -1,3 +1,4 @@
1
1
  export * from "./Canvas";
2
2
  export * from "./components";
3
3
  export * from "./nodes";
4
+ export * from "./useContextBridge";
@@ -1,3 +1,6 @@
1
+ import type { DependencyList } from "react";
2
+ import { useCallback } from "react";
3
+
1
4
  import type { DrawingContext } from "../DrawingContext";
2
5
  import type { SkJSIInstance } from "../../skia/JsiInstance";
3
6
  import type { AnimatedProps } from "../processors";
@@ -18,6 +21,17 @@ export const createDeclaration = <T,>(
18
21
  cb: DeclarationCallback<T>
19
22
  ): DeclarationCallback<T> => cb;
20
23
 
24
+ export const useDeclaration = <P,>(
25
+ cb: DeclarationCallback<P>,
26
+ deps?: DependencyList
27
+ ) =>
28
+ // eslint-disable-next-line react-hooks/exhaustive-deps
29
+ useCallback(cb, deps ?? []);
30
+
31
+ export const isDeclarationNode = (
32
+ node: Node
33
+ ): node is DeclarationNode<unknown> => node instanceof DeclarationNode;
34
+
21
35
  export interface DeclarationProps<P> {
22
36
  onDeclare: DeclarationCallback<P>;
23
37
  }