UNPKG

@shopify/react-native-skia

Version:

High-performance React Native Graphics using Skia

75 lines (65 loc) 1.95 kB
import type { DrawingContext, DrawingNodeProps, Node, NodeType, RenderNode, } from "../types"; import type { NodeContext } from "./Node"; import { JsiDeclarationNode } from "./Node"; import { PaintNode } from "./PaintNode"; import { JsiRenderNode } from "./RenderNode"; export abstract class JsiDrawingNode<P extends DrawingNodeProps, C> extends JsiRenderNode<P> implements RenderNode<P> { protected derived?: C; constructor(ctx: NodeContext, type: NodeType, props: P) { super(ctx, type, props); this.derived = this.deriveProps(); } setProps(props: P) { super.setProps(props); this.derived = this.deriveProps(); } setProp<K extends keyof P>(name: K, value: P[K]) { const hasChanged = super.setProp(name, value); if (hasChanged) { this.derived = this.deriveProps(); } return hasChanged; } addChild(child: Node<unknown>): void { if (!(child instanceof JsiDeclarationNode)) { throw new Error(`Cannot add ${child.type} to ${this.type}`); } super.addChild(child); this.derived = this.deriveProps(); } insertChildBefore(child: Node<unknown>, before: Node<unknown>): void { if (!(child instanceof JsiDeclarationNode)) { throw new Error(`Cannot add ${child.type} to ${this.type}`); } super.insertChildBefore(child, before); this.derived = this.deriveProps(); } renderNode(ctx: DrawingContext): void { if (this.props.paint) { this.draw({ ...ctx, paint: this.props.paint }); } else { this.draw(ctx); } this.children().map((child) => { if (child instanceof PaintNode) { const declCtx = ctx.declarationCtx; declCtx.save(); child.decorate(declCtx); const paint = declCtx.paints.pop()!; declCtx.restore(); this.draw({ ...ctx, paint }); } }); } protected abstract draw(ctx: DrawingContext): void; protected abstract deriveProps(): C; }