@shopify/react-native-skia
Version:
High-performance React Native Graphics using Skia
73 lines (70 loc) • 1.83 kB
text/typescript
import {
isPathDef,
processPath,
processTransformProps2,
} from "../../../dom/nodes";
import type { ClipDef, CTMProps } from "../../../dom/types";
import type { Skia, SkPath, SkRect, SkRRect } from "../../../skia/types";
import { ClipOp, isRRect } from "../../../skia/types";
import type { DrawingContext } from "../DrawingContext";
const computeClip = (
Skia: Skia,
clip: ClipDef | undefined
):
| undefined
| { clipPath: SkPath }
| { clipRect: SkRect }
| { clipRRect: SkRRect } => {
"worklet";
if (clip) {
if (isPathDef(clip)) {
return { clipPath: processPath(Skia, clip) };
} else if (isRRect(clip)) {
return { clipRRect: clip };
} else {
return { clipRect: clip };
}
}
return undefined;
};
export const saveCTM = (ctx: DrawingContext, props: CTMProps) => {
"worklet";
const { canvas, Skia } = ctx;
const {
clip: rawClip,
invertClip,
matrix,
transform,
origin,
layer,
} = props as CTMProps;
const hasTransform = matrix !== undefined || transform !== undefined;
const clip = computeClip(Skia, rawClip);
const hasClip = clip !== undefined;
const op = invertClip ? ClipOp.Difference : ClipOp.Intersect;
const m3 = processTransformProps2(Skia, { matrix, transform, origin });
const shouldSave = hasTransform || hasClip || !!layer;
if (shouldSave) {
if (layer) {
if (typeof layer === "boolean") {
canvas.saveLayer();
} else {
canvas.saveLayer(layer);
}
} else {
canvas.save();
}
}
if (m3) {
canvas.concat(m3);
}
if (clip) {
if ("clipRect" in clip) {
canvas.clipRect(clip.clipRect, op, true);
} else if ("clipRRect" in clip) {
canvas.clipRRect(clip.clipRRect, op, true);
} else {
canvas.clipPath(clip.clipPath, op, true);
}
}
};