@shopify/react-native-skia 2.0.0 → 2.0.2
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.
- package/android/CMakeLists.txt +47 -21
- package/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h +8 -5
- package/apple/MetalWindowContext.mm +12 -1
- package/apple/RNSkApplePlatformContext.h +7 -5
- package/apple/RNSkApplePlatformContext.mm +30 -29
- package/apple/SkiaCVPixelBufferUtils.mm +4 -8
- package/cpp/api/JsiSkImageFactory.h +14 -1
- package/cpp/api/JsiSkSurface.h +7 -1
- package/cpp/api/recorder/DrawingCtx.h +19 -2
- package/cpp/api/recorder/Paint.h +1 -3
- package/cpp/api/recorder/RNRecorder.h +5 -13
- package/cpp/rnskia/DawnContext.h +11 -2
- package/cpp/rnskia/DawnUtils.h +97 -6
- package/cpp/rnskia/DawnWindowContext.h +18 -11
- package/cpp/rnskia/RNSkPlatformContext.h +22 -5
- package/lib/commonjs/skia/types/Image/ImageFactory.d.ts +2 -1
- package/lib/commonjs/skia/types/Image/ImageFactory.js.map +1 -1
- package/lib/commonjs/skia/types/Surface/Surface.d.ts +1 -1
- package/lib/commonjs/skia/types/Surface/Surface.js.map +1 -1
- package/lib/commonjs/skia/web/JsiSkImageFactory.d.ts +1 -0
- package/lib/commonjs/skia/web/JsiSkImageFactory.js +3 -0
- package/lib/commonjs/skia/web/JsiSkImageFactory.js.map +1 -1
- package/lib/commonjs/skia/web/JsiSkSurface.d.ts +2 -1
- package/lib/commonjs/skia/web/JsiSkSurface.js +4 -1
- package/lib/commonjs/skia/web/JsiSkSurface.js.map +1 -1
- package/lib/commonjs/sksg/HostConfig.js +1 -1
- package/lib/commonjs/sksg/HostConfig.js.map +1 -1
- package/lib/commonjs/sksg/Recorder/DrawingContext.d.ts +2 -0
- package/lib/commonjs/sksg/Recorder/DrawingContext.js +14 -2
- package/lib/commonjs/sksg/Recorder/DrawingContext.js.map +1 -1
- package/lib/commonjs/sksg/Recorder/Player.js +6 -2
- package/lib/commonjs/sksg/Recorder/Player.js.map +1 -1
- package/lib/commonjs/sksg/Recorder/commands/Paint.d.ts +3 -2
- package/lib/commonjs/sksg/Recorder/commands/Paint.js +5 -4
- package/lib/commonjs/sksg/Recorder/commands/Paint.js.map +1 -1
- package/lib/commonjs/views/SkiaBaseWebView.js +4 -0
- package/lib/commonjs/views/SkiaBaseWebView.js.map +1 -1
- package/lib/module/skia/types/Image/ImageFactory.d.ts +2 -1
- package/lib/module/skia/types/Image/ImageFactory.js.map +1 -1
- package/lib/module/skia/types/Surface/Surface.d.ts +1 -1
- package/lib/module/skia/types/Surface/Surface.js.map +1 -1
- package/lib/module/skia/web/JsiSkImageFactory.d.ts +1 -0
- package/lib/module/skia/web/JsiSkImageFactory.js +3 -0
- package/lib/module/skia/web/JsiSkImageFactory.js.map +1 -1
- package/lib/module/skia/web/JsiSkSurface.d.ts +2 -1
- package/lib/module/skia/web/JsiSkSurface.js +4 -1
- package/lib/module/skia/web/JsiSkSurface.js.map +1 -1
- package/lib/module/sksg/HostConfig.js +1 -1
- package/lib/module/sksg/HostConfig.js.map +1 -1
- package/lib/module/sksg/Recorder/DrawingContext.d.ts +2 -0
- package/lib/module/sksg/Recorder/DrawingContext.js +14 -2
- package/lib/module/sksg/Recorder/DrawingContext.js.map +1 -1
- package/lib/module/sksg/Recorder/Player.js +6 -2
- package/lib/module/sksg/Recorder/Player.js.map +1 -1
- package/lib/module/sksg/Recorder/commands/Paint.d.ts +3 -2
- package/lib/module/sksg/Recorder/commands/Paint.js +5 -4
- package/lib/module/sksg/Recorder/commands/Paint.js.map +1 -1
- package/lib/module/views/SkiaBaseWebView.js +4 -0
- package/lib/module/views/SkiaBaseWebView.js.map +1 -1
- package/lib/typescript/lib/commonjs/skia/web/JsiSkImageFactory.d.ts +1 -0
- package/lib/typescript/lib/commonjs/skia/web/JsiSkSurface.d.ts +1 -1
- package/lib/typescript/lib/commonjs/sksg/HostConfig.d.ts +1 -1
- package/lib/typescript/lib/commonjs/sksg/Recorder/DrawingContext.d.ts +2 -0
- package/lib/typescript/lib/commonjs/sksg/Recorder/commands/Paint.d.ts +1 -1
- package/lib/typescript/lib/module/skia/web/JsiSkImageFactory.d.ts +1 -0
- package/lib/typescript/lib/module/skia/web/JsiSkSurface.d.ts +1 -1
- package/lib/typescript/lib/module/sksg/HostConfig.d.ts +1 -1
- package/lib/typescript/lib/module/sksg/Recorder/DrawingContext.d.ts +2 -0
- package/lib/typescript/lib/module/sksg/Recorder/commands/Paint.d.ts +1 -1
- package/lib/typescript/src/skia/types/Image/ImageFactory.d.ts +2 -1
- package/lib/typescript/src/skia/types/Surface/Surface.d.ts +1 -1
- package/lib/typescript/src/skia/web/JsiSkImageFactory.d.ts +1 -0
- package/lib/typescript/src/skia/web/JsiSkSurface.d.ts +2 -1
- package/lib/typescript/src/sksg/Recorder/DrawingContext.d.ts +2 -0
- package/lib/typescript/src/sksg/Recorder/commands/Paint.d.ts +3 -2
- package/package.json +1 -1
- package/react-native-skia.podspec +43 -12
- package/src/renderer/__tests__/e2e/DataEncoding.spec.tsx +6 -2
- package/src/renderer/__tests__/e2e/Paint.spec.tsx +44 -1
- package/src/skia/types/Image/ImageFactory.ts +3 -1
- package/src/skia/types/Surface/Surface.ts +1 -1
- package/src/skia/web/JsiSkImageFactory.ts +4 -0
- package/src/skia/web/JsiSkSurface.ts +4 -1
- package/src/sksg/HostConfig.ts +2 -4
- package/src/sksg/Recorder/DrawingContext.ts +15 -1
- package/src/sksg/Recorder/Player.ts +6 -2
- package/src/sksg/Recorder/commands/Paint.ts +6 -5
- package/src/views/SkiaBaseWebView.tsx +4 -0
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"names":["React","JsiSkSurface","Platform","pd","PixelRatio","SkiaBaseWebView","Component","constructor","props","_defineProperty","createRef","onLayoutEvent","bind","unsubscribeAll","_unsubscriptions","forEach","u","evt","CanvasKit","global","canvas","_canvasRef","current","width","clientWidth","height","clientHeight","surface","MakeWebGLCanvasSurface","Error","_surface","_canvas","getCanvas","redraw","onLayout","getSize","componentDidMount","tick","componentDidUpdate","componentWillUnmount","cancelAnimationFrame","requestId","_this$_canvasRef$curr","
|
1
|
+
{"version":3,"names":["React","JsiSkSurface","Platform","pd","PixelRatio","SkiaBaseWebView","Component","constructor","props","_defineProperty","createRef","onLayoutEvent","bind","unsubscribeAll","_unsubscriptions","forEach","u","evt","CanvasKit","global","canvas","_canvasRef","current","width","clientWidth","height","clientHeight","surface","MakeWebGLCanvasSurface","ctx","getContext","drawingBufferColorSpace","Error","_surface","_canvas","getCanvas","redraw","onLayout","getSize","componentDidMount","tick","componentDidUpdate","componentWillUnmount","cancelAnimationFrame","requestId","_this$_canvasRef$curr","getExtension","loseContext","makeImageSnapshot","rect","_this$_surface","_this$_surface2","clear","TRANSPARENT","renderInCanvas","ref","flush","_redrawRequests","_this$_surface3","Float32Array","of","save","scale","restore","requestAnimationFrame","render","debug","viewProps","createElement","View","_extends","style","display","flex"],"sources":["SkiaBaseWebView.tsx"],"sourcesContent":["/* global HTMLCanvasElement */\nimport React from \"react\";\nimport type { LayoutChangeEvent } from \"react-native\";\n\nimport type { SkRect, SkCanvas } from \"../skia/types\";\nimport { JsiSkSurface } from \"../skia/web/JsiSkSurface\";\nimport { Platform } from \"../Platform\";\n\nimport type { SkiaBaseViewProps } from \"./types\";\n\nconst pd = Platform.PixelRatio;\n\nexport abstract class SkiaBaseWebView<\n TProps extends SkiaBaseViewProps\n> extends React.Component<TProps> {\n constructor(props: TProps) {\n super(props);\n }\n\n private _surface: JsiSkSurface | null = null;\n private _unsubscriptions: Array<() => void> = [];\n private _canvas: SkCanvas | null = null;\n private _canvasRef = React.createRef<HTMLCanvasElement>();\n private _redrawRequests = 0;\n private requestId = 0;\n\n protected width = 0;\n protected height = 0;\n\n private unsubscribeAll() {\n this._unsubscriptions.forEach((u) => u());\n this._unsubscriptions = [];\n }\n\n private onLayoutEvent(evt: LayoutChangeEvent) {\n const { CanvasKit } = global;\n // Reset canvas / surface on layout change\n const canvas = this._canvasRef.current;\n if (canvas) {\n this.width = canvas.clientWidth;\n this.height = canvas.clientHeight;\n canvas.width = this.width * pd;\n canvas.height = this.height * pd;\n const surface = CanvasKit.MakeWebGLCanvasSurface(canvas);\n const ctx = canvas.getContext(\"webgl2\");\n if (ctx) {\n ctx.drawingBufferColorSpace = \"display-p3\";\n }\n if (!surface) {\n throw new Error(\"Could not create surface\");\n }\n this._surface = new JsiSkSurface(CanvasKit, surface);\n this._canvas = this._surface.getCanvas();\n this.redraw();\n }\n // Call onLayout callback if it exists\n if (this.props.onLayout) {\n this.props.onLayout(evt);\n }\n }\n\n protected getSize() {\n return { width: this.width, height: this.height };\n }\n\n componentDidMount() {\n // Start render loop\n this.tick();\n }\n\n componentDidUpdate() {\n this.redraw();\n }\n\n componentWillUnmount() {\n this.unsubscribeAll();\n cancelAnimationFrame(this.requestId);\n // eslint-disable-next-line max-len\n // https://stackoverflow.com/questions/23598471/how-do-i-clean-up-and-unload-a-webgl-canvas-context-from-gpu-after-use\n // https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_lose_context\n // We delete the context, only if the context has been intialized\n if (this._surface) {\n this._canvasRef.current\n ?.getContext(\"webgl2\")\n ?.getExtension(\"WEBGL_lose_context\")\n ?.loseContext();\n }\n }\n\n /**\n * Creates a snapshot from the canvas in the surface\n * @param rect Rect to use as bounds. Optional.\n * @returns An Image object.\n */\n public makeImageSnapshot(rect?: SkRect) {\n this._canvas!.clear(CanvasKit.TRANSPARENT);\n this.renderInCanvas(this._canvas!);\n this._surface?.ref.flush();\n return this._surface?.makeImageSnapshot(rect);\n }\n\n /**\n * Override to render\n */\n protected abstract renderInCanvas(canvas: SkCanvas): void;\n\n /**\n * Sends a redraw request to the native SkiaView.\n */\n private tick() {\n if (this._redrawRequests > 0) {\n this._redrawRequests = 0;\n if (this._canvas) {\n const canvas = this._canvas!;\n canvas.clear(Float32Array.of(0, 0, 0, 0));\n canvas.save();\n canvas.scale(pd, pd);\n this.renderInCanvas(canvas);\n canvas.restore();\n this._surface?.ref.flush();\n }\n }\n this.requestId = requestAnimationFrame(this.tick.bind(this));\n }\n\n public redraw() {\n this._redrawRequests++;\n }\n\n private onLayout = this.onLayoutEvent.bind(this);\n\n render() {\n const { debug = false, ...viewProps } = this.props;\n return (\n <Platform.View {...viewProps} onLayout={this.onLayout}>\n <canvas ref={this._canvasRef} style={{ display: \"flex\", flex: 1 }} />\n </Platform.View>\n );\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
@@ -1,5 +1,6 @@
|
|
1
1
|
export const __esModule: boolean;
|
2
2
|
export class JsiSkImageFactory extends _Host.Host {
|
3
|
+
MakeNull(): _JsiSkImage.JsiSkImage;
|
3
4
|
MakeImageFromViewTag(viewTag: any): Promise<null>;
|
4
5
|
MakeImageFromNativeBuffer(buffer: any, surface: any, image: any): _JsiSkImage.JsiSkImage;
|
5
6
|
MakeImageFromEncoded(encoded: any): _JsiSkImage.JsiSkImage | null;
|
@@ -5,7 +5,7 @@ export class JsiSkSurface extends _Host.HostObject {
|
|
5
5
|
width(): any;
|
6
6
|
height(): any;
|
7
7
|
getCanvas(): _JsiSkCanvas.JsiSkCanvas;
|
8
|
-
makeImageSnapshot(bounds: any): _JsiSkImage.JsiSkImage;
|
8
|
+
makeImageSnapshot(bounds: any, outputImage: any): _JsiSkImage.JsiSkImage;
|
9
9
|
getNativeTextureUnstable(): null;
|
10
10
|
}
|
11
11
|
import _Host = require("./Host");
|
@@ -26,7 +26,7 @@ export namespace sksgHostConfig {
|
|
26
26
|
function clearContainer(_container: any): void;
|
27
27
|
function prepareUpdate(_instance: any, _type: any, oldProps: any, newProps: any, container: any, _hostContext: any): any;
|
28
28
|
function preparePortalMount(): void;
|
29
|
-
function cloneInstance(instance: any, _type: any, _oldProps: any, newProps: any,
|
29
|
+
function cloneInstance(instance: any, _type: any, _oldProps: any, newProps: any, keepChildren: any, _newChildSet: any): {
|
30
30
|
type: any;
|
31
31
|
props: any;
|
32
32
|
children: any[];
|
@@ -1,5 +1,5 @@
|
|
1
1
|
export const __esModule: boolean;
|
2
|
-
export function setPaintProperties(Skia: any,
|
2
|
+
export function setPaintProperties(Skia: any, ctx: any, { opacity, color, blendMode, strokeWidth, style, strokeJoin, strokeCap, strokeMiter, antiAlias, dither }: {
|
3
3
|
opacity: any;
|
4
4
|
color: any;
|
5
5
|
blendMode: any;
|
@@ -4,7 +4,7 @@ export class JsiSkSurface extends HostObject {
|
|
4
4
|
width(): any;
|
5
5
|
height(): any;
|
6
6
|
getCanvas(): JsiSkCanvas;
|
7
|
-
makeImageSnapshot(bounds: any): JsiSkImage;
|
7
|
+
makeImageSnapshot(bounds: any, outputImage: any): JsiSkImage;
|
8
8
|
getNativeTextureUnstable(): null;
|
9
9
|
}
|
10
10
|
import { HostObject } from "./Host";
|
@@ -26,7 +26,7 @@ export namespace sksgHostConfig {
|
|
26
26
|
function clearContainer(_container: any): void;
|
27
27
|
function prepareUpdate(_instance: any, _type: any, oldProps: any, newProps: any, container: any, _hostContext: any): any;
|
28
28
|
function preparePortalMount(): void;
|
29
|
-
function cloneInstance(instance: any, _type: any, _oldProps: any, newProps: any,
|
29
|
+
function cloneInstance(instance: any, _type: any, _oldProps: any, newProps: any, keepChildren: any, _newChildSet: any): {
|
30
30
|
type: any;
|
31
31
|
props: any;
|
32
32
|
children: any[];
|
@@ -1,4 +1,4 @@
|
|
1
|
-
export function setPaintProperties(Skia: any,
|
1
|
+
export function setPaintProperties(Skia: any, ctx: any, { opacity, color, blendMode, strokeWidth, style, strokeJoin, strokeCap, strokeMiter, antiAlias, dither }: {
|
2
2
|
opacity: any;
|
3
3
|
color: any;
|
4
4
|
blendMode: any;
|
@@ -15,6 +15,7 @@ export interface ImageInfo {
|
|
15
15
|
width: number;
|
16
16
|
}
|
17
17
|
export interface ImageFactory {
|
18
|
+
MakeNull: () => SkImage;
|
18
19
|
/**
|
19
20
|
* Return an Image backed by the encoded data, but attempt to defer decoding until the image
|
20
21
|
* is actually used/drawn. This deferral allows the system to cache the result, either on the
|
@@ -58,7 +59,7 @@ export interface ImageFactory {
|
|
58
59
|
*
|
59
60
|
* @returns Returns a valid SkImage, if the texture is invalid, an error is thrown.
|
60
61
|
*/
|
61
|
-
MakeImageFromNativeTextureUnstable: (texture: unknown, width: number, height: number, mipmapped?: boolean) => SkImage;
|
62
|
+
MakeImageFromNativeTextureUnstable: (texture: unknown, width: number, height: number, mipmapped?: boolean, outputImage?: SkImage) => SkImage;
|
62
63
|
/**
|
63
64
|
* Returns an image that will be a screenshot of the view represented by
|
64
65
|
* the view tag
|
@@ -32,7 +32,7 @@ export interface SkSurface extends SkJSIInstance<"Surface"> {
|
|
32
32
|
|
33
33
|
example: https://fiddle.skia.org/c/@Surface_makeImageSnapshot
|
34
34
|
*/
|
35
|
-
makeImageSnapshot(bounds?: SkRect): SkImage;
|
35
|
+
makeImageSnapshot(bounds?: SkRect, outputImage?: SkImage): SkImage;
|
36
36
|
/**
|
37
37
|
* Make sure any queued draws are sent to the screen or the GPU.
|
38
38
|
*/
|
@@ -5,6 +5,7 @@ import { JsiSkImage } from "./JsiSkImage";
|
|
5
5
|
import type { JsiSkSurface } from "./JsiSkSurface";
|
6
6
|
export declare class JsiSkImageFactory extends Host implements ImageFactory {
|
7
7
|
constructor(CanvasKit: CanvasKit);
|
8
|
+
MakeNull(): JsiSkImage;
|
8
9
|
MakeImageFromViewTag(viewTag: number): Promise<SkImage | null>;
|
9
10
|
MakeImageFromNativeBuffer(buffer: NativeBuffer, surface?: JsiSkSurface, image?: JsiSkImage): JsiSkImage;
|
10
11
|
MakeImageFromEncoded(encoded: SkData): JsiSkImage | null;
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import type { CanvasKit, Surface } from "canvaskit-wasm";
|
2
2
|
import type { SkCanvas, SkImage, SkRect, SkSurface } from "../types";
|
3
3
|
import { HostObject } from "./Host";
|
4
|
+
import { JsiSkImage } from "./JsiSkImage";
|
4
5
|
export declare class JsiSkSurface extends HostObject<Surface, "Surface"> implements SkSurface {
|
5
6
|
constructor(CanvasKit: CanvasKit, ref: Surface);
|
6
7
|
dispose: () => void;
|
@@ -8,6 +9,6 @@ export declare class JsiSkSurface extends HostObject<Surface, "Surface"> impleme
|
|
8
9
|
width(): number;
|
9
10
|
height(): number;
|
10
11
|
getCanvas(): SkCanvas;
|
11
|
-
makeImageSnapshot(bounds?: SkRect): SkImage;
|
12
|
+
makeImageSnapshot(bounds?: SkRect, outputImage?: JsiSkImage): SkImage;
|
12
13
|
getNativeTextureUnstable(): unknown;
|
13
14
|
}
|
@@ -14,5 +14,7 @@ export declare const createDrawingContext: (Skia: Skia, paintPool: SkPaint[], ca
|
|
14
14
|
readonly paint: SkPaint;
|
15
15
|
restorePaint: () => SkPaint | undefined;
|
16
16
|
materializePaint: () => void;
|
17
|
+
getOpacity: () => number;
|
18
|
+
setOpacity: (newOpacity: number) => void;
|
17
19
|
};
|
18
20
|
export type DrawingContext = ReturnType<typeof createDrawingContext>;
|
@@ -1,3 +1,4 @@
|
|
1
1
|
import type { PaintProps } from "../../../dom/types";
|
2
|
-
import type {
|
3
|
-
|
2
|
+
import type { Skia } from "../../../skia/types";
|
3
|
+
import type { DrawingContext } from "../DrawingContext";
|
4
|
+
export declare const setPaintProperties: (Skia: Skia, ctx: DrawingContext, { opacity, color, blendMode, strokeWidth, style, strokeJoin, strokeCap, strokeMiter, antiAlias, dither, }: PaintProps) => void;
|
package/package.json
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
"setup-skia-web": "scripts/setup-canvaskit.js"
|
9
9
|
},
|
10
10
|
"title": "React Native Skia",
|
11
|
-
"version": "2.0.
|
11
|
+
"version": "2.0.2",
|
12
12
|
"description": "High-performance React Native Graphics using Skia",
|
13
13
|
"main": "lib/module/index.js",
|
14
14
|
"react-native": "src/index.ts",
|
@@ -4,8 +4,48 @@ require "json"
|
|
4
4
|
|
5
5
|
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
6
6
|
|
7
|
-
# Check
|
8
|
-
|
7
|
+
# Check if Graphite symbols are available in libskia
|
8
|
+
libskia_path = File.join(__dir__, "libs/apple/libskia.xcframework")
|
9
|
+
use_graphite = false
|
10
|
+
|
11
|
+
if File.exist?(libskia_path)
|
12
|
+
# Look for any arm64 or x86_64 framework inside the xcframework
|
13
|
+
framework_paths = Dir.glob(File.join(libskia_path, "**/libskia.framework/libskia"))
|
14
|
+
|
15
|
+
# Also try looking for static libraries if frameworks aren't found
|
16
|
+
if framework_paths.empty?
|
17
|
+
framework_paths = Dir.glob(File.join(libskia_path, "**/libskia.a"))
|
18
|
+
end
|
19
|
+
|
20
|
+
framework_paths.each do |framework_path|
|
21
|
+
if File.exist?(framework_path)
|
22
|
+
# Look for specific Dawn function symbols that indicate Graphite support
|
23
|
+
dawn_symbols = [
|
24
|
+
'dawn::',
|
25
|
+
'wgpu',
|
26
|
+
'_ZN4dawn',
|
27
|
+
'DawnDevice',
|
28
|
+
'dawn_native'
|
29
|
+
]
|
30
|
+
|
31
|
+
dawn_symbols.each do |symbol|
|
32
|
+
nm_output = `nm "#{framework_path}" 2>/dev/null | grep "#{symbol}"`
|
33
|
+
if $?.success? && !nm_output.empty?
|
34
|
+
use_graphite = true
|
35
|
+
break
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
break if use_graphite
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
if use_graphite
|
45
|
+
puts "SK_GRAPHITE: ON (Graphite symbols found in libskia)"
|
46
|
+
else
|
47
|
+
puts "SK_GRAPHITE: OFF (Graphite symbols not found in libskia)"
|
48
|
+
end
|
9
49
|
|
10
50
|
# Set preprocessor definitions based on GRAPHITE flag
|
11
51
|
preprocessor_defs = use_graphite ?
|
@@ -20,13 +60,6 @@ base_frameworks = ['libs/apple/libskia.xcframework',
|
|
20
60
|
'libs/apple/libskunicode_core.xcframework',
|
21
61
|
'libs/apple/libskunicode_libgrapheme.xcframework',]
|
22
62
|
|
23
|
-
# Add Graphite frameworks if enabled
|
24
|
-
graphite_frameworks = [
|
25
|
-
'libs/apple/libdawn_native_static.xcframework',
|
26
|
-
'libs/apple/libdawn_platform_static.xcframework',
|
27
|
-
'libs/apple/libdawn_proc_static.xcframework'
|
28
|
-
]
|
29
|
-
|
30
63
|
Pod::Spec.new do |s|
|
31
64
|
s.name = "react-native-skia"
|
32
65
|
s.version = package["version"]
|
@@ -54,9 +87,7 @@ Pod::Spec.new do |s|
|
|
54
87
|
|
55
88
|
s.frameworks = ['MetalKit', 'AVFoundation', 'AVKit', 'CoreMedia']
|
56
89
|
|
57
|
-
s.vendored_frameworks =
|
58
|
-
base_frameworks + graphite_frameworks :
|
59
|
-
base_frameworks
|
90
|
+
s.vendored_frameworks = base_frameworks
|
60
91
|
|
61
92
|
# All iOS cpp/h files
|
62
93
|
s.source_files = [
|
@@ -52,7 +52,9 @@ describe("Data Encoding", () => {
|
|
52
52
|
const offscreen = Skia.Surface.MakeOffscreen(1, 1)!;
|
53
53
|
const canvas = offscreen.getCanvas();
|
54
54
|
canvas.drawImage(img, 0, 0);
|
55
|
-
|
55
|
+
const snapshotImage = Skia.Image.MakeNull();
|
56
|
+
offscreen.makeImageSnapshot(undefined, snapshotImage);
|
57
|
+
return Array.from(snapshotImage.encodeToBytes());
|
56
58
|
});
|
57
59
|
expect(result.length).toBeGreaterThan(0);
|
58
60
|
});
|
@@ -68,7 +70,9 @@ describe("Data Encoding", () => {
|
|
68
70
|
const offscreen = Skia.Surface.MakeOffscreen(1, 1)!;
|
69
71
|
const canvas = offscreen.getCanvas();
|
70
72
|
canvas.drawImage(img, 0, 0);
|
71
|
-
|
73
|
+
const snapshotImage = Skia.Image.MakeNull();
|
74
|
+
offscreen.makeImageSnapshot(undefined, snapshotImage);
|
75
|
+
return snapshotImage.encodeToBase64();
|
72
76
|
});
|
73
77
|
expect(result.length).toBeGreaterThan(0);
|
74
78
|
});
|
@@ -10,7 +10,7 @@ import {
|
|
10
10
|
Paint,
|
11
11
|
Path,
|
12
12
|
} from "../../components";
|
13
|
-
import { checkImage } from "../../../__tests__/setup";
|
13
|
+
import { checkImage, docPath } from "../../../__tests__/setup";
|
14
14
|
import { fitbox } from "../../components/shapes/FitBox";
|
15
15
|
|
16
16
|
const blendModes = [
|
@@ -167,4 +167,47 @@ describe("Paint", () => {
|
|
167
167
|
threshold: 0,
|
168
168
|
});
|
169
169
|
});
|
170
|
+
it("should override colors", async () => {
|
171
|
+
const { vec } = importSkia();
|
172
|
+
const strokeWidth = 10;
|
173
|
+
const { width, height } = surface;
|
174
|
+
const c = vec(width / 2, height / 2);
|
175
|
+
const r = (width - strokeWidth) / 2;
|
176
|
+
const result = await surface.draw(
|
177
|
+
<>
|
178
|
+
<Circle c={c} r={r} color="transparent">
|
179
|
+
<Paint color="lightblue" />
|
180
|
+
<Paint color="#adbce6" style="stroke" strokeWidth={strokeWidth} />
|
181
|
+
<Paint color="#ade6d8" style="stroke" strokeWidth={strokeWidth / 2} />
|
182
|
+
</Circle>
|
183
|
+
</>
|
184
|
+
);
|
185
|
+
checkImage(result, docPath("paint/stroke.png"));
|
186
|
+
});
|
187
|
+
it("colors don't influence opacity (1)", async () => {
|
188
|
+
const { vec } = importSkia();
|
189
|
+
const strokeWidth = 10;
|
190
|
+
const { width, height } = surface;
|
191
|
+
const c = vec(width / 2, height / 2);
|
192
|
+
const r = (width - strokeWidth) / 2;
|
193
|
+
const result = await surface.draw(
|
194
|
+
<Group color="rgba(0,0,0,0.5)">
|
195
|
+
<Circle c={c} r={r} color="lightblue" />
|
196
|
+
</Group>
|
197
|
+
);
|
198
|
+
checkImage(result, docPath("paint/opaque-circle.png"));
|
199
|
+
});
|
200
|
+
it("colors don't influence opacity (2)", async () => {
|
201
|
+
const { vec } = importSkia();
|
202
|
+
const strokeWidth = 10;
|
203
|
+
const { width, height } = surface;
|
204
|
+
const c = vec(width / 2, height / 2);
|
205
|
+
const r = (width - strokeWidth) / 2;
|
206
|
+
const result = await surface.draw(
|
207
|
+
<Group opacity={0.5}>
|
208
|
+
<Circle c={c} r={r} color="lightblue" />
|
209
|
+
</Group>
|
210
|
+
);
|
211
|
+
checkImage(result, docPath("paint/semi-transparent-circle.png"));
|
212
|
+
});
|
170
213
|
});
|
@@ -21,6 +21,7 @@ export interface ImageInfo {
|
|
21
21
|
}
|
22
22
|
|
23
23
|
export interface ImageFactory {
|
24
|
+
MakeNull: () => SkImage;
|
24
25
|
/**
|
25
26
|
* Return an Image backed by the encoded data, but attempt to defer decoding until the image
|
26
27
|
* is actually used/drawn. This deferral allows the system to cache the result, either on the
|
@@ -70,7 +71,8 @@ export interface ImageFactory {
|
|
70
71
|
texture: unknown,
|
71
72
|
width: number,
|
72
73
|
height: number,
|
73
|
-
mipmapped?: boolean
|
74
|
+
mipmapped?: boolean,
|
75
|
+
outputImage?: SkImage
|
74
76
|
) => SkImage;
|
75
77
|
|
76
78
|
/**
|
@@ -35,7 +35,7 @@ export interface SkSurface extends SkJSIInstance<"Surface"> {
|
|
35
35
|
|
36
36
|
example: https://fiddle.skia.org/c/@Surface_makeImageSnapshot
|
37
37
|
*/
|
38
|
-
makeImageSnapshot(bounds?: SkRect): SkImage;
|
38
|
+
makeImageSnapshot(bounds?: SkRect, outputImage?: SkImage): SkImage;
|
39
39
|
|
40
40
|
/**
|
41
41
|
* Make sure any queued draws are sent to the screen or the GPU.
|
@@ -20,6 +20,10 @@ export class JsiSkImageFactory extends Host implements ImageFactory {
|
|
20
20
|
super(CanvasKit);
|
21
21
|
}
|
22
22
|
|
23
|
+
MakeNull() {
|
24
|
+
return new JsiSkImage(this.CanvasKit, null as unknown as Image);
|
25
|
+
}
|
26
|
+
|
23
27
|
MakeImageFromViewTag(viewTag: number): Promise<SkImage | null> {
|
24
28
|
const view = viewTag as unknown as HTMLElement;
|
25
29
|
// TODO: Implement screenshot from view in React JS
|
@@ -35,12 +35,15 @@ export class JsiSkSurface
|
|
35
35
|
return new JsiSkCanvas(this.CanvasKit, this.ref.getCanvas());
|
36
36
|
}
|
37
37
|
|
38
|
-
makeImageSnapshot(bounds?: SkRect): SkImage {
|
38
|
+
makeImageSnapshot(bounds?: SkRect, outputImage?: JsiSkImage): SkImage {
|
39
39
|
const image = this.ref.makeImageSnapshot(
|
40
40
|
bounds
|
41
41
|
? Array.from(JsiSkRect.fromValue(this.CanvasKit, bounds))
|
42
42
|
: undefined
|
43
43
|
);
|
44
|
+
if (outputImage) {
|
45
|
+
outputImage.ref = image;
|
46
|
+
}
|
44
47
|
return new JsiSkImage(this.CanvasKit, image);
|
45
48
|
}
|
46
49
|
|
package/src/sksg/HostConfig.ts
CHANGED
@@ -177,10 +177,8 @@ export const sksgHostConfig: SkiaHostConfig = {
|
|
177
177
|
_type,
|
178
178
|
_oldProps,
|
179
179
|
newProps,
|
180
|
-
|
181
|
-
|
182
|
-
keepChildren: boolean,
|
183
|
-
_recyclableInstance: null | Instance
|
180
|
+
keepChildren,
|
181
|
+
_newChildSet
|
184
182
|
) {
|
185
183
|
debug("cloneInstance");
|
186
184
|
return {
|
@@ -22,12 +22,14 @@ export const createDrawingContext = (
|
|
22
22
|
const imageFilters: SkImageFilter[] = [];
|
23
23
|
const pathEffects: SkPathEffect[] = [];
|
24
24
|
const paintDeclarations: SkPaint[] = [];
|
25
|
+
const opacities: number[] = [];
|
25
26
|
|
26
27
|
let nextPaintIndex = 1;
|
27
28
|
|
28
|
-
// Initialize first paint
|
29
|
+
// Initialize first paint and opacity
|
29
30
|
paintPool[0] = Skia.Paint();
|
30
31
|
paints.push(paintPool[0]);
|
32
|
+
opacities.push(1);
|
31
33
|
|
32
34
|
// Methods (formerly class methods)
|
33
35
|
const savePaint = () => {
|
@@ -39,9 +41,18 @@ export const createDrawingContext = (
|
|
39
41
|
const nextPaint = paintPool[nextPaintIndex];
|
40
42
|
nextPaint.assign(getCurrentPaint()); // Reuse allocation by copying properties
|
41
43
|
paints.push(nextPaint);
|
44
|
+
opacities.push(opacities[opacities.length - 1]);
|
42
45
|
nextPaintIndex++;
|
43
46
|
};
|
44
47
|
|
48
|
+
const getOpacity = () => {
|
49
|
+
return opacities[opacities.length - 1];
|
50
|
+
};
|
51
|
+
|
52
|
+
const setOpacity = (newOpacity: number) => {
|
53
|
+
opacities[opacities.length - 1] = Math.max(0, Math.min(1, newOpacity));
|
54
|
+
};
|
55
|
+
|
45
56
|
const saveBackdropFilter = () => {
|
46
57
|
let imageFilter: SkImageFilter | null = null;
|
47
58
|
const imgf = imageFilters.pop();
|
@@ -63,6 +74,7 @@ export const createDrawingContext = (
|
|
63
74
|
};
|
64
75
|
|
65
76
|
const restorePaint = () => {
|
77
|
+
opacities.pop();
|
66
78
|
return paints.pop();
|
67
79
|
};
|
68
80
|
|
@@ -125,6 +137,8 @@ export const createDrawingContext = (
|
|
125
137
|
}, // the "getter" for the current paint
|
126
138
|
restorePaint,
|
127
139
|
materializePaint,
|
140
|
+
getOpacity,
|
141
|
+
setOpacity,
|
128
142
|
};
|
129
143
|
};
|
130
144
|
|
@@ -67,7 +67,7 @@ function play(ctx: DrawingContext, _command: Command) {
|
|
67
67
|
ctx.paints.push(command.props.paint);
|
68
68
|
} else {
|
69
69
|
ctx.savePaint();
|
70
|
-
setPaintProperties(ctx.Skia, ctx
|
70
|
+
setPaintProperties(ctx.Skia, ctx, command.props);
|
71
71
|
}
|
72
72
|
} else if (isCommand(command, CommandType.RestorePaint)) {
|
73
73
|
ctx.restorePaint();
|
@@ -101,7 +101,11 @@ function play(ctx: DrawingContext, _command: Command) {
|
|
101
101
|
} else if (isCommand(command, CommandType.RestoreCTM)) {
|
102
102
|
ctx.canvas.restore();
|
103
103
|
} else {
|
104
|
-
|
104
|
+
// TODO: is a copy needed here?
|
105
|
+
// apply opacity to the current paint.
|
106
|
+
const paint = ctx.paint.copy();
|
107
|
+
paint.setAlphaf(paint.getAlphaf() * ctx.getOpacity());
|
108
|
+
const paints = [paint, ...ctx.paintDeclarations];
|
105
109
|
ctx.paintDeclarations = [];
|
106
110
|
paints.forEach((p) => {
|
107
111
|
ctx.paints.push(p);
|
@@ -6,11 +6,12 @@ import {
|
|
6
6
|
StrokeCap,
|
7
7
|
StrokeJoin,
|
8
8
|
} from "../../../skia/types";
|
9
|
-
import type {
|
9
|
+
import type { Skia } from "../../../skia/types";
|
10
|
+
import type { DrawingContext } from "../DrawingContext";
|
10
11
|
|
11
12
|
export const setPaintProperties = (
|
12
13
|
Skia: Skia,
|
13
|
-
|
14
|
+
ctx: DrawingContext,
|
14
15
|
{
|
15
16
|
opacity,
|
16
17
|
color,
|
@@ -25,14 +26,14 @@ export const setPaintProperties = (
|
|
25
26
|
}: PaintProps
|
26
27
|
) => {
|
27
28
|
"worklet";
|
29
|
+
const { paint } = ctx;
|
30
|
+
|
28
31
|
if (opacity !== undefined) {
|
29
|
-
|
32
|
+
ctx.setOpacity(ctx.getOpacity() * opacity);
|
30
33
|
}
|
31
34
|
if (color !== undefined) {
|
32
|
-
const currentOpacity = paint.getAlphaf();
|
33
35
|
paint.setShader(null);
|
34
36
|
paint.setColor(processColor(Skia, color));
|
35
|
-
paint.setAlphaf(currentOpacity * paint.getAlphaf());
|
36
37
|
}
|
37
38
|
if (blendMode !== undefined) {
|
38
39
|
paint.setBlendMode(BlendMode[enumKey(blendMode)]);
|
@@ -42,6 +42,10 @@ export abstract class SkiaBaseWebView<
|
|
42
42
|
canvas.width = this.width * pd;
|
43
43
|
canvas.height = this.height * pd;
|
44
44
|
const surface = CanvasKit.MakeWebGLCanvasSurface(canvas);
|
45
|
+
const ctx = canvas.getContext("webgl2");
|
46
|
+
if (ctx) {
|
47
|
+
ctx.drawingBufferColorSpace = "display-p3";
|
48
|
+
}
|
45
49
|
if (!surface) {
|
46
50
|
throw new Error("Could not create surface");
|
47
51
|
}
|