@shopify/react-native-skia 0.1.116 → 0.1.118
Sign up to get free protection for your applications and to get access to all the features.
- package/cpp/api/JsiSkApi.h +13 -9
- package/cpp/api/JsiSkCanvas.h +9 -1
- package/cpp/api/JsiSkPicture.h +71 -0
- package/cpp/api/JsiSkPictureFactory.h +50 -0
- package/cpp/api/JsiSkPictureRecorder.h +53 -0
- package/lib/commonjs/renderer/Canvas.js +22 -36
- package/lib/commonjs/renderer/Canvas.js.map +1 -1
- package/lib/commonjs/renderer/HostConfig.js +2 -24
- package/lib/commonjs/renderer/HostConfig.js.map +1 -1
- package/lib/commonjs/renderer/components/Drawing.js +31 -0
- package/lib/commonjs/renderer/components/Drawing.js.map +1 -0
- package/lib/commonjs/renderer/components/Group.js +1 -1
- package/lib/commonjs/renderer/components/Group.js.map +1 -1
- package/lib/commonjs/renderer/components/Picture.js +35 -0
- package/lib/commonjs/renderer/components/Picture.js.map +1 -0
- package/lib/commonjs/renderer/components/imageFilters/InnerShadow.js +5 -34
- package/lib/commonjs/renderer/components/imageFilters/InnerShadow.js.map +1 -1
- package/lib/commonjs/renderer/components/imageFilters/{DropShadow.js → Shadow.js} +19 -8
- package/lib/commonjs/renderer/components/imageFilters/Shadow.js.map +1 -0
- package/lib/commonjs/renderer/components/imageFilters/index.js +4 -17
- package/lib/commonjs/renderer/components/imageFilters/index.js.map +1 -1
- package/lib/commonjs/renderer/components/index.js +26 -0
- package/lib/commonjs/renderer/components/index.js.map +1 -1
- package/lib/commonjs/renderer/components/maskFilters/Blur.js +1 -1
- package/lib/commonjs/renderer/components/maskFilters/Blur.js.map +1 -1
- package/lib/commonjs/renderer/components/shapes/Box.js +126 -0
- package/lib/commonjs/renderer/components/shapes/Box.js.map +1 -0
- package/lib/commonjs/renderer/components/shapes/index.js +13 -0
- package/lib/commonjs/renderer/components/shapes/index.js.map +1 -1
- package/lib/commonjs/renderer/index.js +13 -0
- package/lib/commonjs/renderer/index.js.map +1 -1
- package/lib/commonjs/renderer/nodes/Declaration.js +8 -1
- package/lib/commonjs/renderer/nodes/Declaration.js.map +1 -1
- package/lib/commonjs/renderer/nodes/Drawing.js +5 -8
- package/lib/commonjs/renderer/nodes/Drawing.js.map +1 -1
- package/lib/commonjs/renderer/processors/math/Math.js +19 -1
- package/lib/commonjs/renderer/processors/math/Math.js.map +1 -1
- package/lib/commonjs/renderer/processors/math/Matrix3.js +11 -5
- package/lib/commonjs/renderer/processors/math/Matrix3.js.map +1 -1
- package/lib/commonjs/renderer/typeddash.js +26 -2
- package/lib/commonjs/renderer/typeddash.js.map +1 -1
- package/lib/commonjs/renderer/useContextBridge.js +35 -0
- package/lib/commonjs/renderer/useContextBridge.js.map +1 -0
- package/lib/commonjs/skia/Canvas.js.map +1 -1
- package/lib/commonjs/skia/Picture/Picture.js +6 -0
- package/lib/commonjs/skia/Picture/Picture.js.map +1 -0
- package/lib/commonjs/skia/Picture/PictureFactory.js +6 -0
- package/lib/commonjs/skia/Picture/PictureFactory.js.map +1 -0
- package/lib/commonjs/skia/Picture/PictureRecorder.js +6 -0
- package/lib/commonjs/skia/Picture/PictureRecorder.js.map +1 -0
- package/lib/commonjs/skia/Picture/index.js +58 -0
- package/lib/commonjs/skia/Picture/index.js.map +1 -0
- package/lib/commonjs/skia/Picture/usePicture.js +30 -0
- package/lib/commonjs/skia/Picture/usePicture.js.map +1 -0
- package/lib/commonjs/skia/Skia.js +2 -0
- package/lib/commonjs/skia/Skia.js.map +1 -1
- package/lib/commonjs/skia/index.js +14 -0
- package/lib/commonjs/skia/index.js.map +1 -1
- package/lib/commonjs/values/hooks/useDerivedValue.js +2 -2
- package/lib/commonjs/values/hooks/useDerivedValue.js.map +1 -1
- package/lib/commonjs/views/SkiaView.js +6 -5
- package/lib/commonjs/views/SkiaView.js.map +1 -1
- package/lib/commonjs/views/types.js.map +1 -1
- package/lib/module/renderer/Canvas.js +20 -32
- package/lib/module/renderer/Canvas.js.map +1 -1
- package/lib/module/renderer/HostConfig.js +1 -23
- package/lib/module/renderer/HostConfig.js.map +1 -1
- package/lib/module/renderer/components/Drawing.js +17 -0
- package/lib/module/renderer/components/Drawing.js.map +1 -0
- package/lib/module/renderer/components/Group.js +1 -1
- package/lib/module/renderer/components/Group.js.map +1 -1
- package/lib/module/renderer/components/Picture.js +21 -0
- package/lib/module/renderer/components/Picture.js.map +1 -0
- package/lib/module/renderer/components/imageFilters/InnerShadow.js +4 -26
- package/lib/module/renderer/components/imageFilters/InnerShadow.js.map +1 -1
- package/lib/module/renderer/components/imageFilters/{DropShadow.js → Shadow.js} +16 -6
- package/lib/module/renderer/components/imageFilters/Shadow.js.map +1 -0
- package/lib/module/renderer/components/imageFilters/index.js +1 -2
- package/lib/module/renderer/components/imageFilters/index.js.map +1 -1
- package/lib/module/renderer/components/index.js +2 -0
- package/lib/module/renderer/components/index.js.map +1 -1
- package/lib/module/renderer/components/maskFilters/Blur.js +1 -1
- package/lib/module/renderer/components/maskFilters/Blur.js.map +1 -1
- package/lib/module/renderer/components/shapes/Box.js +102 -0
- package/lib/module/renderer/components/shapes/Box.js.map +1 -0
- package/lib/module/renderer/components/shapes/index.js +1 -0
- package/lib/module/renderer/components/shapes/index.js.map +1 -1
- package/lib/module/renderer/index.js +1 -0
- package/lib/module/renderer/index.js.map +1 -1
- package/lib/module/renderer/nodes/Declaration.js +3 -0
- package/lib/module/renderer/nodes/Declaration.js.map +1 -1
- package/lib/module/renderer/nodes/Drawing.js +3 -4
- package/lib/module/renderer/nodes/Drawing.js.map +1 -1
- package/lib/module/renderer/processors/math/Math.js +15 -0
- package/lib/module/renderer/processors/math/Math.js.map +1 -1
- package/lib/module/renderer/processors/math/Matrix3.js +6 -2
- package/lib/module/renderer/processors/math/Matrix3.js.map +1 -1
- package/lib/module/renderer/typeddash.js +21 -0
- package/lib/module/renderer/typeddash.js.map +1 -1
- package/lib/module/renderer/useContextBridge.js +21 -0
- package/lib/module/renderer/useContextBridge.js.map +1 -0
- package/lib/module/skia/Canvas.js.map +1 -1
- package/lib/module/skia/Picture/Picture.js +2 -0
- package/lib/module/skia/Picture/Picture.js.map +1 -0
- package/lib/module/skia/Picture/PictureFactory.js +2 -0
- package/lib/module/skia/Picture/PictureFactory.js.map +1 -0
- package/lib/module/skia/Picture/PictureRecorder.js +2 -0
- package/lib/module/skia/Picture/PictureRecorder.js.map +1 -0
- package/lib/module/skia/Picture/index.js +5 -0
- package/lib/module/skia/Picture/index.js.map +1 -0
- package/lib/module/skia/Picture/usePicture.js +19 -0
- package/lib/module/skia/Picture/usePicture.js.map +1 -0
- package/lib/module/skia/Skia.js +2 -0
- package/lib/module/skia/Skia.js.map +1 -1
- package/lib/module/skia/index.js +1 -0
- package/lib/module/skia/index.js.map +1 -1
- package/lib/module/values/hooks/useDerivedValue.js +1 -1
- package/lib/module/values/hooks/useDerivedValue.js.map +1 -1
- package/lib/module/views/SkiaView.js +6 -5
- package/lib/module/views/SkiaView.js.map +1 -1
- package/lib/module/views/types.js.map +1 -1
- package/lib/typescript/src/renderer/Canvas.d.ts +5 -10
- package/lib/typescript/src/renderer/components/Drawing.d.ts +7 -0
- package/lib/typescript/src/renderer/components/Picture.d.ts +6 -0
- package/lib/typescript/src/renderer/components/imageFilters/InnerShadow.d.ts +3 -12
- package/lib/typescript/src/renderer/components/imageFilters/{DropShadow.d.ts → Shadow.d.ts} +3 -2
- package/lib/typescript/src/renderer/components/imageFilters/index.d.ts +1 -2
- package/lib/typescript/src/renderer/components/index.d.ts +2 -0
- package/lib/typescript/src/renderer/components/shapes/Box.d.ts +23 -0
- package/lib/typescript/src/renderer/components/shapes/index.d.ts +1 -0
- package/lib/typescript/src/renderer/index.d.ts +1 -0
- package/lib/typescript/src/renderer/nodes/Declaration.d.ts +2 -0
- package/lib/typescript/src/renderer/nodes/Drawing.d.ts +2 -2
- package/lib/typescript/src/renderer/processors/math/Math.d.ts +14 -0
- package/lib/typescript/src/renderer/processors/math/Matrix3.d.ts +1 -0
- package/lib/typescript/src/renderer/typeddash.d.ts +1 -0
- package/lib/typescript/src/renderer/useContextBridge.d.ts +5 -0
- package/lib/typescript/src/skia/Canvas.d.ts +6 -0
- package/lib/typescript/src/skia/Picture/Picture.d.ts +26 -0
- package/lib/typescript/src/skia/Picture/PictureFactory.d.ts +8 -0
- package/lib/typescript/src/skia/Picture/PictureRecorder.d.ts +15 -0
- package/lib/typescript/src/skia/Picture/index.d.ts +4 -0
- package/lib/typescript/src/skia/Picture/usePicture.d.ts +11 -0
- package/lib/typescript/src/skia/Skia.d.ts +5 -0
- package/lib/typescript/src/skia/index.d.ts +1 -0
- package/lib/typescript/src/views/SkiaView.d.ts +25 -1
- package/lib/typescript/src/views/types.d.ts +0 -24
- package/libs/ios/libskia.xcframework/ios-arm64_arm64e/libskia.a +0 -0
- package/libs/ios/libskia.xcframework/ios-arm64_arm64e_x86_64-simulator/libskia.a +0 -0
- package/libs/ios/libskshaper.xcframework/ios-arm64_arm64e/libskshaper.a +0 -0
- package/libs/ios/libskshaper.xcframework/ios-arm64_arm64e_x86_64-simulator/libskshaper.a +0 -0
- package/libs/ios/libsvg.xcframework/Info.plist +5 -5
- package/libs/ios/libsvg.xcframework/ios-arm64_arm64e/libsvg.a +0 -0
- package/libs/ios/libsvg.xcframework/ios-arm64_arm64e_x86_64-simulator/libsvg.a +0 -0
- package/package.json +1 -1
- package/src/renderer/Canvas.tsx +14 -30
- package/src/renderer/HostConfig.ts +1 -19
- package/src/renderer/components/Drawing.tsx +16 -0
- package/src/renderer/components/Group.tsx +1 -1
- package/src/renderer/components/Picture.tsx +17 -0
- package/src/renderer/components/imageFilters/InnerShadow.tsx +33 -47
- package/src/renderer/components/imageFilters/Shadow.tsx +39 -0
- package/src/renderer/components/imageFilters/index.ts +1 -2
- package/src/renderer/components/index.ts +2 -0
- package/src/renderer/components/maskFilters/Blur.tsx +1 -1
- package/src/renderer/components/shapes/Box.tsx +98 -0
- package/src/renderer/components/shapes/index.ts +1 -0
- package/src/renderer/index.ts +1 -0
- package/src/renderer/nodes/Declaration.tsx +10 -0
- package/src/renderer/nodes/Drawing.tsx +6 -6
- package/src/renderer/processors/math/Math.ts +16 -0
- package/src/renderer/processors/math/Matrix3.ts +35 -31
- package/src/renderer/typeddash.ts +18 -0
- package/src/renderer/useContextBridge.tsx +21 -0
- package/src/skia/Canvas.ts +7 -0
- package/src/skia/Picture/Picture.ts +34 -0
- package/src/skia/Picture/PictureFactory.ts +9 -0
- package/src/skia/Picture/PictureRecorder.ts +18 -0
- package/src/skia/Picture/index.ts +4 -0
- package/src/skia/Picture/usePicture.ts +28 -0
- package/src/skia/Skia.ts +5 -0
- package/src/skia/index.ts +1 -0
- package/src/values/hooks/useDerivedValue.ts +1 -1
- package/src/views/SkiaView.tsx +27 -3
- package/src/views/types.ts +0 -25
- package/lib/commonjs/renderer/components/imageFilters/DropShadow.js.map +0 -1
- package/lib/module/renderer/components/imageFilters/DropShadow.js.map +0 -1
- package/src/renderer/components/imageFilters/DropShadow.tsx +0 -31
package/src/renderer/Canvas.tsx
CHANGED
@@ -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
|
-
|
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
|
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
|
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,
|
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;
|
@@ -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
|
+
};
|
@@ -33,7 +33,7 @@ const onDraw = createDrawing<GroupProps>(
|
|
33
33
|
processPaint(paint, opacity, groupProps);
|
34
34
|
const hasTransform = !!groupProps.transform || !!groupProps.matrix;
|
35
35
|
const hasClip = !!clip;
|
36
|
-
const shouldSave = hasTransform || hasClip;
|
36
|
+
const shouldSave = hasTransform || hasClip || !!layer;
|
37
37
|
if (shouldSave) {
|
38
38
|
if (layer) {
|
39
39
|
if (typeof layer === "boolean") {
|
@@ -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
|
1
|
+
import type { SkColor } from "../../../skia";
|
2
|
+
import { BlendMode, Skia, TileMode } from "../../../skia";
|
3
|
+
import type { SkImageFilter } from "../../../skia/ImageFilter/ImageFilter";
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
-
|
49
|
-
|
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
|
+
};
|
@@ -8,6 +8,7 @@ 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";
|
@@ -15,3 +16,4 @@ export * from "./Paint";
|
|
15
16
|
export * from "./Compose";
|
16
17
|
export * from "./Blend";
|
17
18
|
export * from "./Defs";
|
19
|
+
export * from "./Drawing";
|
@@ -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
|
+
};
|
package/src/renderer/index.ts
CHANGED
@@ -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,13 @@ 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
|
+
|
21
31
|
export interface DeclarationProps<P> {
|
22
32
|
onDeclare: DeclarationCallback<P>;
|
23
33
|
}
|
@@ -1,5 +1,5 @@
|
|
1
|
-
import type { ReactNode } from "react";
|
2
|
-
import
|
1
|
+
import type { DependencyList, ReactNode } from "react";
|
2
|
+
import { useCallback } from "react";
|
3
3
|
|
4
4
|
import type { DrawingContext } from "../DrawingContext";
|
5
5
|
import { processPaint, selectPaint } from "../processors";
|
@@ -21,16 +21,16 @@ type OnDrawCallback<P> = (ctx: DrawingContext, props: P, node: Node<P>) => void;
|
|
21
21
|
export const createDrawing = <P,>(cb: OnDrawCallback<P>): DrawingCallback<P> =>
|
22
22
|
cb;
|
23
23
|
|
24
|
+
export const useDrawing = <P,>(cb: OnDrawCallback<P>, deps?: DependencyList) =>
|
25
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
26
|
+
useCallback(cb, deps ?? []);
|
27
|
+
|
24
28
|
export type DrawingProps<T> = {
|
25
29
|
onDraw: DrawingCallback<T>;
|
26
30
|
skipProcessing?: boolean;
|
27
31
|
children?: ReactNode | ReactNode[];
|
28
32
|
};
|
29
33
|
|
30
|
-
export const Drawing = <P,>(props: DrawingProps<P>) => {
|
31
|
-
return <skDrawing {...props} />;
|
32
|
-
};
|
33
|
-
|
34
34
|
export class DrawingNode<P> extends Node<P> {
|
35
35
|
onDraw: DrawingCallback<P>;
|
36
36
|
skipProcessing: boolean;
|
@@ -1,2 +1,18 @@
|
|
1
|
+
/**
|
2
|
+
* Linear interpolation
|
3
|
+
* @param value
|
4
|
+
* @param x
|
5
|
+
* @param y
|
6
|
+
*/
|
1
7
|
export const mix = (value: number, x: number, y: number) =>
|
2
8
|
x * (1 - value) + y * value;
|
9
|
+
|
10
|
+
/**
|
11
|
+
* @summary Clamps a node with a lower and upper bound.
|
12
|
+
* @example
|
13
|
+
clamp(-1, 0, 100); // 0
|
14
|
+
clamp(1, 0, 100); // 1
|
15
|
+
clamp(101, 0, 100); // 100
|
16
|
+
*/
|
17
|
+
export const clamp = (value: number, lowerBound: number, upperBound: number) =>
|
18
|
+
Math.min(Math.max(lowerBound, value), upperBound);
|
@@ -102,6 +102,9 @@ const multiply3 = (m1: Matrix3, m2: Matrix3) => {
|
|
102
102
|
] as const;
|
103
103
|
};
|
104
104
|
|
105
|
+
export const matrixVecMul3 = (m: Matrix3, v: Vec3) =>
|
106
|
+
[dot3(m[0], v), dot3(m[1], v), dot3(m[2], v)] as const;
|
107
|
+
|
105
108
|
const skiaMatrix3 = (m: Matrix3): SkMatrix => {
|
106
109
|
return [
|
107
110
|
m[0][0],
|
@@ -117,34 +120,35 @@ const skiaMatrix3 = (m: Matrix3): SkMatrix => {
|
|
117
120
|
};
|
118
121
|
|
119
122
|
export const processTransform2d = (transforms: Transforms2d) =>
|
120
|
-
skiaMatrix3(
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
return
|
149
|
-
}
|
150
|
-
|
123
|
+
skiaMatrix3(processTransform(transforms));
|
124
|
+
|
125
|
+
const processTransform = (transforms: Transforms2d) =>
|
126
|
+
transforms.reduce((acc, transform) => {
|
127
|
+
const key = Object.keys(transform)[0] as Transform2dName;
|
128
|
+
const value = (transform as Pick<Transformations, typeof key>)[key];
|
129
|
+
if (key === "translateX") {
|
130
|
+
return multiply3(acc, translateXMatrix(value));
|
131
|
+
}
|
132
|
+
if (key === "translateY") {
|
133
|
+
return multiply3(acc, translateYMatrix(value));
|
134
|
+
}
|
135
|
+
if (key === "scale") {
|
136
|
+
return multiply3(acc, scaleMatrix(value));
|
137
|
+
}
|
138
|
+
if (key === "scaleX") {
|
139
|
+
return multiply3(acc, scaleXMatrix(value));
|
140
|
+
}
|
141
|
+
if (key === "scaleY") {
|
142
|
+
return multiply3(acc, scaleYMatrix(value));
|
143
|
+
}
|
144
|
+
if (key === "skewX") {
|
145
|
+
return multiply3(acc, skewXMatrix(value));
|
146
|
+
}
|
147
|
+
if (key === "skewY") {
|
148
|
+
return multiply3(acc, skewYMatrix(value));
|
149
|
+
}
|
150
|
+
if (key === "rotate" || key === "rotateZ") {
|
151
|
+
return multiply3(acc, rotateZMatrix(value));
|
152
|
+
}
|
153
|
+
return exhaustiveCheck(key);
|
154
|
+
}, identityMatrix);
|
@@ -3,3 +3,21 @@ export const mapKeys = <T>(obj: T) => Object.keys(obj) as (keyof T)[];
|
|
3
3
|
export const exhaustiveCheck = (a: never): never => {
|
4
4
|
throw new Error(`Unexhaustive handling for ${a}`);
|
5
5
|
};
|
6
|
+
|
7
|
+
// Shallow eq on props (without children)
|
8
|
+
export const shallowEq = <P>(p1: P, p2: P): boolean => {
|
9
|
+
const keys1 = mapKeys(p1);
|
10
|
+
const keys2 = mapKeys(p2);
|
11
|
+
if (keys1.length !== keys2.length) {
|
12
|
+
return false;
|
13
|
+
}
|
14
|
+
for (const key of keys1) {
|
15
|
+
if (key === "children") {
|
16
|
+
continue;
|
17
|
+
}
|
18
|
+
if (p1[key] !== p2[key]) {
|
19
|
+
return false;
|
20
|
+
}
|
21
|
+
}
|
22
|
+
return true;
|
23
|
+
};
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import React, { useMemo, useContext } from "react";
|
2
|
+
import type { ReactNode, Context, ReactElement } from "react";
|
3
|
+
|
4
|
+
// useContextBridge() is taken from https://github.com/pmndrs/drei#usecontextbridge
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
6
|
+
export const useContextBridge = (...contexts: Context<any>[]) => {
|
7
|
+
const values =
|
8
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
9
|
+
contexts.map((context) => useContext(context));
|
10
|
+
return useMemo(
|
11
|
+
() =>
|
12
|
+
({ children }: { children: ReactNode }) =>
|
13
|
+
contexts.reduceRight(
|
14
|
+
(acc, Context, i) => (
|
15
|
+
<Context.Provider value={values[i]} children={acc} />
|
16
|
+
),
|
17
|
+
children
|
18
|
+
) as ReactElement,
|
19
|
+
[contexts, values]
|
20
|
+
);
|
21
|
+
};
|
package/src/skia/Canvas.ts
CHANGED
@@ -12,6 +12,7 @@ import type { SkMatrix } from "./Matrix";
|
|
12
12
|
import type { SkImageFilter } from "./ImageFilter";
|
13
13
|
import type { SkVertices } from "./Vertices";
|
14
14
|
import type { SkTextBlob } from "./TextBlob";
|
15
|
+
import type { SkPicture } from "./Picture";
|
15
16
|
|
16
17
|
export enum ClipOp {
|
17
18
|
Difference,
|
@@ -485,4 +486,10 @@ export interface SkCanvas {
|
|
485
486
|
* @param m
|
486
487
|
*/
|
487
488
|
concat(m: SkMatrix): void;
|
489
|
+
|
490
|
+
/**
|
491
|
+
* Draws the given picture using the current clip, current matrix, and the provided paint.
|
492
|
+
* @param skp
|
493
|
+
*/
|
494
|
+
drawPicture(skp: SkPicture): void;
|
488
495
|
}
|