@shopify/react-native-skia 0.1.116 → 0.1.120

Sign up to get free protection for your applications and to get access to all the features.
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
  }