Skip to content

Commit

Permalink
Skia DOM (#886)
Browse files Browse the repository at this point in the history
  • Loading branch information
wcandillon authored Sep 14, 2022
1 parent eb37899 commit 5436eb6
Show file tree
Hide file tree
Showing 190 changed files with 5,391 additions and 2,426 deletions.
5 changes: 2 additions & 3 deletions docs/docs/group.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,13 +247,12 @@ const Clip = () => {
return (
<Canvas style={{ flex: 1 }}>
<Paint ref={paint}>
<Blur blur={20} />
<ColorMatrix
matrix={[
1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 18, -7,
]}
>
<Blur blur={20} />
</ColorMatrix>
/>
</Paint>
<Group color="lightblue" layer={paint}>
<Circle cx={0} cy={128} r={128 * 0.95} />
Expand Down
Binary file removed docs/docs/image-filters/assets/color.png
Binary file not shown.
2 changes: 1 addition & 1 deletion docs/docs/image-filters/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,4 @@ const ComposeImageFilter = () => {
};
```

![Clamp Blur](assets/color.png)
<img src={require("/static/img/image-filters/composing.png").default} width="256" height="256" />
Binary file added docs/static/img/blur-backdrop-aurora.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/static/img/box/box-stroke.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/static/img/box/shadows.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/static/img/color-filters/composition.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/static/img/color-filters/lerp.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/static/img/image-filters/composing.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion example/src/Examples/API/BlendModes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import {
BlendMode,
Canvas,
Circle,
enumKey,
Group,
Path,
Skia,
Text,
useFont,
enumKey,
} from "@shopify/react-native-skia";

const r = 50;
Expand Down
56 changes: 6 additions & 50 deletions example/src/Examples/API/Freeze.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,34 @@
import type { ReactNode } from "react";
import React, { useEffect, useState } from "react";
import type { SkPaint, SkRect } from "@shopify/react-native-skia";
import React from "react";
import {
useFont,
FilterMode,
Canvas,
Group,
Rect,
Text,
useClockValue,
useComputedValue,
rect,
createDrawing,
Skia,
TileMode,
} from "@shopify/react-native-skia";

const size = 200;
const n = 99;
const n = 49;

export const FreezeExample = () => {
const font = useFont(require("../../assets/SF-Mono-Semibold.otf"), 32);
const [color, setColor] = useState("black");
const clock = useClockValue();
const transform = useComputedValue(
() => [{ translateY: 100 }, { rotate: (Math.PI * clock.current) / 4000 }],
[clock]
);
useEffect(() => {
const h = setInterval(() => {
setColor("#" + (Math.random().toString(16) + "00000").slice(2, 8));
}, 10000);
return () => clearInterval(h);
}, []);

if (font === null) {
return null;
}
return (
<Canvas style={{ flex: 1, margin: 50 }} debug>
<Canvas style={{ flex: 1, margin: 50 }}>
<Group origin={{ x: size / 2, y: size / 2 }} transform={transform}>
<Freeze key={color} rect={rect(0, 0, 200, 200)}>
<Checkerboard color={color} />
</Freeze>
<Checkerboard color="black" />
</Group>
{font && <Text x={20} y={size + 100} text={`n = ${n}`} font={font} />}
{font && <Text x={20} y={size + 100} text={`n = ${n * n}`} font={font} />}
</Canvas>
);
};
Expand All @@ -65,32 +50,3 @@ const Checkerboard = ({ color }: { color: string }) => {
</>
);
};

interface FreezeProps {
rect: SkRect;
children?: ReactNode | ReactNode[];
}

const onDraw = createDrawing<FreezeProps>(
(ctx, { rect: boundingRect }, node) => {
if (node.memoized === null) {
const recorder = Skia.PictureRecorder();
const canvas = recorder.beginRecording(boundingRect);
node.visit({
...ctx,
canvas,
});
const pic = recorder.finishRecordingAsPicture();
const shaderPaint = Skia.Paint();
shaderPaint.setShader(
pic.makeShader(TileMode.Decal, TileMode.Decal, FilterMode.Nearest)
);
node.memoized = shaderPaint;
}
ctx.canvas.drawRect(boundingRect, node.memoized as SkPaint);
}
);

export const Freeze = (props: FreezeProps) => {
return <skDrawing onDraw={onDraw} skipProcessing {...props} />;
};
4 changes: 2 additions & 2 deletions example/src/Examples/API/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ const examples = [
title: "🖼 Picture",
},
{
screen: "Freeze",
title: "❄️ Freeze",
screen: "Checker",
title: "🏁 Checker",
},
{
screen: "UseCanvas",
Expand Down
2 changes: 1 addition & 1 deletion example/src/Examples/API/Routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export type Routes = {
BlendModes: undefined;
Data: undefined;
Picture: undefined;
Freeze: undefined;
Checker: undefined;
UseCanvas: undefined;
Reanimated: undefined;
};
7 changes: 5 additions & 2 deletions example/src/Examples/API/Touch.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import React, { useCallback, useRef } from "react";
import { StyleSheet, View } from "react-native";
import type { SkColor, TouchInfo } from "@shopify/react-native-skia";
import type {
DrawingContext,
SkColor,
TouchInfo,
} from "@shopify/react-native-skia";
import {
Group,
useMultiTouchHandler,
Expand All @@ -10,7 +14,6 @@ import {
Skia,
TouchType,
} from "@shopify/react-native-skia";
import type { DrawingContext } from "@shopify/react-native-skia/src/renderer/DrawingContext";

import { Title } from "./components/Title";

Expand Down
4 changes: 2 additions & 2 deletions example/src/Examples/API/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,10 @@ export const API = () => {
}}
/>
<Stack.Screen
name="Freeze"
name="Checker"
component={FreezeExample}
options={{
title: "❄️ Freeze",
title: "🏁 Checker",
}}
/>
<Stack.Screen
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ vec4 main(vec2 pos) {

interface BilinearGradientProps {
rect: SkRect;
colors: readonly [Color, Color, Color, Color];
colors: [Color, Color, Color, Color];
}

export const BilinearGradient = ({ rect, colors }: BilinearGradientProps) => {
Expand Down
24 changes: 14 additions & 10 deletions example/src/Examples/Aurora/components/CoonsPatchMeshGradient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { useHandles } from "./useHandles";

const rectToTexture = (
vertices: CubicBezierHandle[],
[tl, tr, br, bl]: readonly [number, number, number, number]
[tl, tr, br, bl]: number[]
) =>
[
vertices[tl].pos,
Expand All @@ -33,15 +33,19 @@ const rectToTexture = (
vertices[bl].pos,
] as const;

const rectToColors = (
colors: string[],
[tl, tr, br, bl]: readonly [number, number, number, number]
) => [colors[tl], colors[tr], colors[br], colors[bl]] as const;
const rectToColors = (colors: string[], [tl, tr, br, bl]: number[]) => [
colors[tl],
colors[tr],
colors[br],
colors[bl],
];

const useRectToPatch = (
mesh: SkiaValue<CubicBezierHandle[]>,
indices: readonly number[]
) =>
indices: number[]
): SkiaValue<
[CubicBezierHandle, CubicBezierHandle, CubicBezierHandle, CubicBezierHandle]
> =>
useComputedValue(() => {
const tl = mesh.current[indices[0]];
const tr = mesh.current[indices[1]];
Expand All @@ -68,7 +72,7 @@ const useRectToPatch = (
c1: bl.c1,
c2: symmetric(bl.c2, bl.pos),
},
] as const;
];
}, [mesh]);

interface CoonsPatchMeshGradientProps {
Expand Down Expand Up @@ -127,7 +131,7 @@ export const CoonsPatchMeshGradient = ({
const tr = tl + 1;
const bl = (row + 1) * l + col;
const br = bl + 1;
return [tl, tr, br, bl] as const;
return [tl, tr, br, bl];
})
)
.flat();
Expand Down Expand Up @@ -203,7 +207,7 @@ export const CoonsPatchMeshGradient = ({
};

interface RectPatchProps {
r: readonly [number, number, number, number];
r: number[];
debug?: boolean;
lines?: boolean;
colors: string[];
Expand Down
10 changes: 7 additions & 3 deletions example/src/Examples/Breathe/Breathe.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,13 @@ const Ring = ({ index, progress }: RingProps) => {
}, [progress]);

return (
<Group origin={center} transform={transform}>
<Circle c={center} r={R} color={index % 2 ? c1 : c2} />
</Group>
<Circle
c={center}
r={R}
color={index % 2 ? c1 : c2}
origin={center}
transform={transform}
/>
);
};

Expand Down
21 changes: 7 additions & 14 deletions example/src/Examples/Performance/PerformanceRects.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import {
Canvas,
Paint,
Rect,
Skia,
SkiaView,
PaintStyle,
usePaintRef,
Group,
useTouchHandler,
useValue,
Expand Down Expand Up @@ -116,9 +114,6 @@ export const PerformanceDrawingTest: React.FC = () => {
[paint1, paint2, rects]
);

const paint1Ref = usePaintRef();
const paint2Ref = usePaintRef();

return (
<View style={styles.container}>
<View style={styles.mode}>
Expand All @@ -145,21 +140,19 @@ export const PerformanceDrawingTest: React.FC = () => {
</View>
{isDeclarative ? (
<Canvas style={styles.container} debug mode="default" onTouch={onTouch}>
<Paint ref={paint1Ref} color="#00ff00" style={"fill"} />
<Paint
ref={paint2Ref}
color="#4060A3"
style="stroke"
strokeWidth={2}
/>
{rects.map((_, i) => (
<Group
key={i}
transform={Selector(rotationTransforms, (v) => v[i])}
origin={rects[i]}
>
<Rect rect={rects[i]} paint={paint1Ref} />
<Rect rect={rects[i]} paint={paint2Ref} />
<Rect rect={rects[i]} color="#00ff00" />
<Rect
rect={rects[i]}
color="#4060A3"
style="stroke"
strokeWidth={2}
/>
</Group>
))}
</Canvas>
Expand Down
1 change: 1 addition & 0 deletions package/src/__tests__/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ export const processResult = (
} else {
fs.writeFileSync(p, png);
}
ckSurface.getCanvas().clear(Float32Array.of(0, 0, 0, 0));
};
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added package/src/__tests__/snapshots/drawings/cyan.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified package/src/__tests__/snapshots/drawings/rrect-no-aa.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 41 additions & 0 deletions package/src/dom/__tests__/Compose.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import {
importSkia,
width,
height,
loadImage,
getSkDOM,
} from "../../renderer/__tests__/setup";
import { setupSkia } from "../../skia/__tests__/setup";
import { docPath, processResult } from "../../__tests__/setup";

describe("Compose", () => {
it("should compose image filters", () => {
const size = width;
const { surface, canvas } = setupSkia(width, height);
const { Skia, rect, vec } = importSkia();
const Sk = getSkDOM();
const image = loadImage("skia/__tests__/assets/oslo.jpg");

const root = Sk.Group();
const img = Sk.Image({
image,
fit: "cover",
rect: rect(0, 0, size, size),
});
root.addChild(img);

const matrix = [
-0.578, 0.99, 0.588, 0, 0, 0.469, 0.535, -0.003, 0, 0, 0.015, 1.69,
-0.703, 0, 0, 0, 0, 0, 1, 0,
];
const cf = Sk.MatrixColorFilter({ matrix });

const blur = Sk.BlurImageFilter({ blur: vec(10, 10), mode: "decal" });
blur.addChild(cf);
root.addChild(blur);

const ctx = { canvas, paint: Skia.Paint(), opacity: 1, Skia };
root.render(ctx);
processResult(surface, docPath("image-filters/composing.png"));
});
});
Loading

0 comments on commit 5436eb6

Please sign in to comment.