| // Copyright 2015 The Chromium 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 lerpDouble; |
| |
| import 'package:flutter/foundation.dart'; |
| |
| import 'basic_types.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. |
| @immutable |
| class BoxShadow { |
| /// Creates a box shadow. |
| /// |
| /// By default, the shadow is solid black with zero [offset], [blurRadius], |
| /// and [spreadRadius]. |
| const BoxShadow({ |
| this.color: const Color(0xFF000000), |
| this.offset: Offset.zero, |
| this.blurRadius: 0.0, |
| this.spreadRadius: 0.0 |
| }); |
| |
| /// The color of the shadow. |
| final Color color; |
| |
| /// The displacement of the shadow from the box. |
| final Offset offset; |
| |
| /// The standard deviation of the Gaussian to convolve with the box's shape. |
| final double blurRadius; |
| |
| /// The amount the box should be inflated prior to applying the blur. |
| final double spreadRadius; |
| |
| /// Converts a blur radius in pixels to sigmas. |
| /// |
| /// See the sigma argument to [MaskFilter.blur]. |
| // |
| // See SkBlurMask::ConvertRadiusToSigma(). |
| // <https://github.com/google/skia/blob/bb5b77db51d2e149ee66db284903572a5aac09be/src/effects/SkBlurMask.cpp#L23> |
| static double convertRadiusToSigma(double radius) { |
| return radius * 0.57735 + 0.5; |
| } |
| |
| /// The [blurRadius] in sigmas instead of logical pixels. |
| /// |
| /// See the sigma argument to [MaskFilter.blur]. |
| double get blurSigma => convertRadiusToSigma(blurRadius); |
| |
| /// Returns a new box shadow with its offset, blurRadius, and spreadRadius scaled by the given factor. |
| BoxShadow scale(double factor) { |
| return new 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. |
| static BoxShadow lerp(BoxShadow a, BoxShadow b, double t) { |
| if (a == null && b == null) |
| return null; |
| if (a == null) |
| return b.scale(t); |
| if (b == null) |
| return a.scale(1.0 - t); |
| return new 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. |
| static List<BoxShadow> lerpList(List<BoxShadow> a, List<BoxShadow> b, double t) { |
| if (a == null && b == null) |
| return null; |
| a ??= <BoxShadow>[]; |
| b ??= <BoxShadow>[]; |
| final List<BoxShadow> result = <BoxShadow>[]; |
| final int commonLength = math.min(a.length, b.length); |
| for (int i = 0; i < commonLength; ++i) |
| result.add(BoxShadow.lerp(a[i], b[i], t)); |
| for (int i = commonLength; i < a.length; ++i) |
| result.add(a[i].scale(1.0 - t)); |
| for (int i = commonLength; i < b.length; ++i) |
| result.add(b[i].scale(t)); |
| return result; |
| } |
| |
| @override |
| bool operator ==(dynamic other) { |
| if (identical(this, other)) |
| return true; |
| if (runtimeType != other.runtimeType) |
| return false; |
| final BoxShadow typedOther = other; |
| return color == typedOther.color && |
| offset == typedOther.offset && |
| blurRadius == typedOther.blurRadius && |
| spreadRadius == typedOther.spreadRadius; |
| } |
| |
| @override |
| int get hashCode => hashValues(color, offset, blurRadius, spreadRadius); |
| |
| @override |
| String toString() => 'BoxShadow($color, $offset, $blurRadius, $spreadRadius)'; |
| } |