UNPKG

@shopify/react-native-skia

Version:

High-performance React Native Graphics using Skia

297 lines (249 loc) 7.25 kB
import type { SharedValue } from "react-native-reanimated"; import type { BaseRecorder, JsiRecorder, Skia } from "../../skia/types"; import type { PaintProps, NodeType, BlurMaskFilterProps, CTMProps, BoxProps, BoxShadowProps, ImageProps, CircleProps, PointsProps, PathProps, RectProps, RoundedRectProps, OvalProps, LineProps, PatchProps, VerticesProps, DiffRectProps, TextProps, TextPathProps, TextBlobProps, GlyphsProps, PictureProps, ImageSVGProps, ParagraphProps, AtlasProps, SkottieProps, DrawingNodeProps, } from "../../dom/types"; import type { AnimatedProps } from "../../renderer"; import { isSharedValue } from "../utils"; /** * Currently the recorder only work if the GPU resources (e.g Images) are owned by the main thread. * It will crash otherwise on Ganesh (iOS/Android). */ export class ReanimatedRecorder implements BaseRecorder { private values = new Set<SharedValue<unknown>>(); private recorder: JsiRecorder; constructor(Skia: Skia) { this.recorder = Skia.Recorder(); } reset() { this.values.clear(); this.recorder.reset(); } private processAnimationValues(props?: Record<string, unknown>) { if (!props) { return; } Object.values(props).forEach((value) => { if (isSharedValue(value) && !this.values.has(value)) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error value.name = `variable${this.values.size}`; this.values.add(value as SharedValue<unknown>); } }); } getRecorder() { return this.recorder; } getSharedValues() { return Array.from(this.values); } saveGroup(props?: AnimatedProps<Pick<DrawingNodeProps, "zIndex">>): void { if (props) { this.processAnimationValues(props); this.recorder.saveGroup(props); } else { this.recorder.saveGroup(); } } restoreGroup(): void { this.recorder.restoreGroup(); } savePaint(props: AnimatedProps<PaintProps>, standalone: boolean): void { this.processAnimationValues(props); this.recorder.savePaint(props, standalone); } restorePaint(): void { this.recorder.restorePaint(); } restorePaintDeclaration(): void { this.recorder.restorePaintDeclaration(); } materializePaint(): void { this.recorder.materializePaint(); } pushPathEffect( pathEffectType: NodeType, props: AnimatedProps<unknown> ): void { this.processAnimationValues(props); this.recorder.pushPathEffect(pathEffectType, props); } pushImageFilter( imageFilterType: NodeType, props: AnimatedProps<unknown> ): void { this.processAnimationValues(props); this.recorder.pushImageFilter(imageFilterType, props); } pushColorFilter( colorFilterType: NodeType, props: AnimatedProps<unknown> ): void { this.processAnimationValues(props); this.recorder.pushColorFilter(colorFilterType, props); } pushShader( shaderType: NodeType, props: AnimatedProps<unknown>, children: number ): void { this.processAnimationValues(props); this.recorder.pushShader(shaderType, props, children); } pushBlurMaskFilter(props: AnimatedProps<BlurMaskFilterProps>): void { this.processAnimationValues(props); this.recorder.pushBlurMaskFilter(props); } composePathEffect(): void { this.recorder.composePathEffect(); } composeColorFilter(): void { this.recorder.composeColorFilter(); } composeImageFilter(): void { this.recorder.composeImageFilter(); } saveCTM(props: AnimatedProps<CTMProps>): void { this.processAnimationValues(props); this.recorder.saveCTM(props); } restoreCTM(): void { this.recorder.restoreCTM(); } drawPaint(): void { this.recorder.drawPaint(); } saveLayer(): void { this.recorder.saveLayer(); } saveBackdropFilter(): void { this.recorder.saveBackdropFilter(); } drawBox( boxProps: AnimatedProps<BoxProps>, shadows: { props: BoxShadowProps; }[] ): void { this.processAnimationValues(boxProps); shadows.forEach((shadow) => { this.processAnimationValues( shadow.props as AnimatedProps<BoxShadowProps> ); }); this.recorder.drawBox( boxProps, // TODO: Fix this type BaseRecorder.drawBox() // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error shadows.map((s) => s.props) ); } drawImage(props: AnimatedProps<ImageProps>): void { this.processAnimationValues(props); this.recorder.drawImage(props); } drawCircle(props: AnimatedProps<CircleProps>): void { this.processAnimationValues(props); this.recorder.drawCircle(props); } drawPoints(props: AnimatedProps<PointsProps>): void { this.processAnimationValues(props); this.recorder.drawPoints(props); } drawPath(props: AnimatedProps<PathProps>): void { this.processAnimationValues(props); this.recorder.drawPath(props); } drawRect(props: AnimatedProps<RectProps>): void { this.processAnimationValues(props); this.recorder.drawRect(props); } drawRRect(props: AnimatedProps<RoundedRectProps>): void { this.processAnimationValues(props); this.recorder.drawRRect(props); } drawOval(props: AnimatedProps<OvalProps>): void { this.processAnimationValues(props); this.recorder.drawOval(props); } drawLine(props: AnimatedProps<LineProps>): void { this.processAnimationValues(props); this.recorder.drawLine(props); } drawPatch(props: AnimatedProps<PatchProps>): void { this.processAnimationValues(props); this.recorder.drawPatch(props); } drawVertices(props: AnimatedProps<VerticesProps>): void { this.processAnimationValues(props); this.recorder.drawVertices(props); } drawDiffRect(props: AnimatedProps<DiffRectProps>): void { this.processAnimationValues(props); this.recorder.drawDiffRect(props); } drawText(props: AnimatedProps<TextProps>): void { this.processAnimationValues(props); this.recorder.drawText(props); } drawTextPath(props: AnimatedProps<TextPathProps>): void { this.processAnimationValues(props); this.recorder.drawTextPath(props); } drawTextBlob(props: AnimatedProps<TextBlobProps>): void { this.processAnimationValues(props); this.recorder.drawTextBlob(props); } drawGlyphs(props: AnimatedProps<GlyphsProps>): void { this.processAnimationValues(props); this.recorder.drawGlyphs(props); } drawPicture(props: AnimatedProps<PictureProps>): void { this.processAnimationValues(props); this.recorder.drawPicture(props); } drawImageSVG(props: AnimatedProps<ImageSVGProps>): void { this.processAnimationValues(props); this.recorder.drawImageSVG(props); } drawParagraph(props: AnimatedProps<ParagraphProps>): void { this.processAnimationValues(props); this.recorder.drawParagraph(props); } drawAtlas(props: AnimatedProps<AtlasProps>): void { this.processAnimationValues(props); this.recorder.drawAtlas(props); } drawSkottie(props: AnimatedProps<SkottieProps>): void { this.processAnimationValues(props); this.recorder.drawSkottie(props); } }