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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:math' as math;
import 'dart:ui' as ui show Shadow, lerpDouble;
import 'package:flutter/foundation.dart';
import 'basic_types.dart';
import 'debug.dart';
/// A shadow cast by a box.
///
/// [BoxShadow] can cast non-rectangular shadows if the box is non-rectangular
/// (e.g., has a border radius or a circular shape).
///
/// This class is similar to CSS box-shadow.
///
/// See also:
///
/// * [Canvas.drawShadow], which is a more efficient way to draw shadows.
/// * [PhysicalModel], a widget for showing shadows.
/// * [kElevationToShadow], for some predefined shadows used in Material
/// Design.
/// * [Shadow], which is the parent class that lacks [spreadRadius].
@immutable
class BoxShadow extends ui.Shadow {
/// Creates a box shadow.
///
/// By default, the shadow is solid black with zero [offset], [blurRadius],
/// and [spreadRadius].
const BoxShadow({
Color color = const Color(0xFF000000),
Offset offset = Offset.zero,
double blurRadius = 0.0,
this.spreadRadius = 0.0,
}) : super(color: color, offset: offset, blurRadius: blurRadius);
/// The amount the box should be inflated prior to applying the blur.
final double spreadRadius;
/// Create the [Paint] object that corresponds to this shadow description.
///
/// The [offset] and [spreadRadius] are not represented in the [Paint] object.
/// To honor those as well, the shape should be inflated by [spreadRadius] pixels
/// in every direction and then translated by [offset] before being filled using
/// this [Paint].
@override
Paint toPaint() {
final Paint result = Paint()
..color = color
..maskFilter = MaskFilter.blur(BlurStyle.normal, blurSigma);
assert(() {
if (debugDisableShadows)
result.maskFilter = null;
return true;
}());
return result;
}
/// Returns a new box shadow with its offset, blurRadius, and spreadRadius scaled by the given factor.
@override
BoxShadow scale(double factor) {
return BoxShadow(
color: color,
offset: offset * factor,
blurRadius: blurRadius * factor,
spreadRadius: spreadRadius * factor,
);
}
/// Linearly interpolate between two box shadows.
///
/// If either box shadow is null, this function linearly interpolates from a
/// a box shadow that matches the other box shadow in color but has a zero
/// offset and a zero blurRadius.
///
/// {@macro dart.ui.shadow.lerp}
static BoxShadow? lerp(BoxShadow? a, BoxShadow? b, double t) {
assert(t != null);
if (a == null && b == null)
return null;
if (a == null)
return b!.scale(t);
if (b == null)
return a.scale(1.0 - t);
return BoxShadow(
color: Color.lerp(a.color, b.color, t)!,
offset: Offset.lerp(a.offset, b.offset, t)!,
blurRadius: ui.lerpDouble(a.blurRadius, b.blurRadius, t)!,
spreadRadius: ui.lerpDouble(a.spreadRadius, b.spreadRadius, t)!,
);
}
/// Linearly interpolate between two lists of box shadows.
///
/// If the lists differ in length, excess items are lerped with null.
///
/// {@macro dart.ui.shadow.lerp}
static List<BoxShadow>? lerpList(List<BoxShadow>? a, List<BoxShadow>? b, double t) {
assert(t != null);
if (a == null && b == null)
return null;
a ??= <BoxShadow>[];
b ??= <BoxShadow>[];
final int commonLength = math.min(a.length, b.length);
return <BoxShadow>[
for (int i = 0; i < commonLength; i += 1) BoxShadow.lerp(a[i], b[i], t)!,
for (int i = commonLength; i < a.length; i += 1) a[i].scale(1.0 - t),
for (int i = commonLength; i < b.length; i += 1) b[i].scale(t),
];
}
@override
bool operator ==(Object other) {
if (identical(this, other))
return true;
if (other.runtimeType != runtimeType)
return false;
return other is BoxShadow
&& other.color == color
&& other.offset == offset
&& other.blurRadius == blurRadius
&& other.spreadRadius == spreadRadius;
}
@override
int get hashCode => hashValues(color, offset, blurRadius, spreadRadius);
@override
String toString() => 'BoxShadow($color, $offset, ${debugFormatDouble(blurRadius)}, ${debugFormatDouble(spreadRadius)})';
}