/
Box.ts
110 lines (100 loc) · 3.17 KB
/
Box.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import type { SkRRect, Skia } from "../../../skia/types";
import { BlurStyle, ClipOp, isRRect } from "../../../skia/types";
import type { DrawingContext } from "../../types";
import { DeclarationType, NodeType } from "../../types";
import type { BoxShadowProps, BoxProps } from "../../types/Drawings";
import type { NodeContext } from "../Node";
import { JsiDeclarationNode } from "../Node";
import { JsiRenderNode } from "../RenderNode";
import type { DeclarationContext } from "../../types/DeclarationContext";
const inflate = (
Skia: Skia,
box: SkRRect,
dx: number,
dy: number,
tx = 0,
ty = 0
) =>
Skia.RRectXY(
Skia.XYWHRect(
box.rect.x - dx + tx,
box.rect.y - dy + ty,
box.rect.width + 2 * dx,
box.rect.height + 2 * dy
),
box.rx + dx,
box.ry + dy
);
const deflate = (
Skia: Skia,
box: SkRRect,
dx: number,
dy: number,
tx = 0,
ty = 0
) => inflate(Skia, box, -dx, -dy, tx, ty);
export class BoxShadowNode extends JsiDeclarationNode<BoxShadowProps> {
constructor(ctx: NodeContext, props: BoxShadowProps) {
super(ctx, DeclarationType.Unknown, NodeType.BoxShadow, props);
}
decorate(_ctx: DeclarationContext) {
// do nothing
}
materialize() {
return this.props;
}
}
export class BoxNode extends JsiRenderNode<BoxProps> {
constructor(ctx: NodeContext, props: BoxProps) {
super(ctx, NodeType.Box, props);
}
renderNode({ canvas, paint }: DrawingContext) {
const { box: defaultBox } = this.props;
const opacity = paint.getAlphaf();
const box = isRRect(defaultBox)
? defaultBox
: this.Skia.RRectXY(defaultBox, 0, 0);
const shadows = this._children
.map((node) => {
if (node instanceof BoxShadowNode) {
return node.materialize();
}
return null;
})
.filter((n): n is BoxShadowProps => n !== null);
shadows
.filter((shadow) => !shadow.inner)
.map((shadow) => {
const { color = "black", blur, spread = 0, dx = 0, dy = 0 } = shadow;
const lPaint = this.Skia.Paint();
lPaint.setColor(this.Skia.Color(color));
lPaint.setAlphaf(paint.getAlphaf() * opacity);
lPaint.setMaskFilter(
this.Skia.MaskFilter.MakeBlur(BlurStyle.Normal, blur, true)
);
canvas.drawRRect(
inflate(this.Skia, box, spread, spread, dx, dy),
lPaint
);
});
canvas.drawRRect(box, paint);
shadows
.filter((shadow) => shadow.inner)
.map((shadow) => {
const { color = "black", blur, spread = 0, dx = 0, dy = 0 } = shadow;
const delta = this.Skia.Point(10 + Math.abs(dx), 10 + Math.abs(dy));
canvas.save();
canvas.clipRRect(box, ClipOp.Intersect, false);
const lPaint = this.Skia.Paint();
lPaint.setColor(this.Skia.Color(color));
lPaint.setAlphaf(paint.getAlphaf() * opacity);
lPaint.setMaskFilter(
this.Skia.MaskFilter.MakeBlur(BlurStyle.Normal, blur, true)
);
const inner = deflate(this.Skia, box, spread, spread, dx, dy);
const outer = inflate(this.Skia, box, delta.x, delta.y);
canvas.drawDRRect(outer, inner, lPaint);
canvas.restore();
});
}
}