您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
355 行
13 KiB
355 行
13 KiB
using System;
|
|
using Unity.UIWidgets.ui;
|
|
|
|
namespace Unity.UIWidgets.painting {
|
|
public class RoundedRectangleBorder : ShapeBorder, IEquatable<RoundedRectangleBorder> {
|
|
public RoundedRectangleBorder(
|
|
BorderSide side = null,
|
|
BorderRadius borderRadius = null
|
|
) {
|
|
this.side = side ?? BorderSide.none;
|
|
this.borderRadius = borderRadius ?? BorderRadius.zero;
|
|
}
|
|
|
|
public readonly BorderSide side;
|
|
|
|
public readonly BorderRadius borderRadius;
|
|
|
|
|
|
public override EdgeInsets dimensions {
|
|
get { return EdgeInsets.all(this.side.width); }
|
|
}
|
|
|
|
public override ShapeBorder scale(double t) {
|
|
return new RoundedRectangleBorder(
|
|
side: this.side.scale(t),
|
|
borderRadius: this.borderRadius * t
|
|
);
|
|
}
|
|
|
|
public override ShapeBorder lerpFrom(ShapeBorder a, double t) {
|
|
if (a is RoundedRectangleBorder border) {
|
|
return new RoundedRectangleBorder(
|
|
side: BorderSide.lerp(border.side, this.side, t),
|
|
borderRadius: BorderRadius.lerp(border.borderRadius, this.borderRadius, t)
|
|
);
|
|
}
|
|
|
|
if (a is CircleBorder circleBorder) {
|
|
return new _RoundedRectangleToCircleBorder(
|
|
side: BorderSide.lerp(circleBorder.side, this.side, t),
|
|
borderRadius: this.borderRadius,
|
|
circleness: 1.0 - t
|
|
);
|
|
}
|
|
|
|
return base.lerpFrom(a, t);
|
|
}
|
|
|
|
public override ShapeBorder lerpTo(ShapeBorder b, double t) {
|
|
if (b is RoundedRectangleBorder border) {
|
|
return new RoundedRectangleBorder(
|
|
side: BorderSide.lerp(this.side, border.side, t),
|
|
borderRadius: BorderRadius.lerp(this.borderRadius, border.borderRadius, t)
|
|
);
|
|
}
|
|
|
|
if (b is CircleBorder circleBorder) {
|
|
return new _RoundedRectangleToCircleBorder(
|
|
side: BorderSide.lerp(this.side, circleBorder.side, t),
|
|
borderRadius: this.borderRadius,
|
|
circleness: t
|
|
);
|
|
}
|
|
|
|
return base.lerpTo(b, t);
|
|
}
|
|
|
|
public override Path getInnerPath(Rect rect) {
|
|
var path = new Path();
|
|
path.addRRect(this.borderRadius.toRRect(rect).deflate(this.side.width));
|
|
return path;
|
|
}
|
|
|
|
public override Path getOuterPath(Rect rect) {
|
|
var path = new Path();
|
|
path.addRRect(this.borderRadius.toRRect(rect));
|
|
return path;
|
|
}
|
|
|
|
public override void paint(Canvas canvas, Rect rect) {
|
|
switch (this.side.style) {
|
|
case BorderStyle.none:
|
|
break;
|
|
case BorderStyle.solid:
|
|
double width = this.side.width;
|
|
if (width == 0.0) {
|
|
canvas.drawRRect(this.borderRadius.toRRect(rect), this.side.toPaint());
|
|
}
|
|
else {
|
|
RRect outer = this.borderRadius.toRRect(rect);
|
|
RRect inner = outer.deflate(width);
|
|
Paint paint = new Paint {
|
|
color = this.side.color,
|
|
};
|
|
canvas.drawDRRect(outer, inner, paint);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
public bool Equals(RoundedRectangleBorder other) {
|
|
if (ReferenceEquals(null, other)) {
|
|
return false;
|
|
}
|
|
|
|
if (ReferenceEquals(this, other)) {
|
|
return true;
|
|
}
|
|
|
|
return Equals(this.side, other.side) && Equals(this.borderRadius, other.borderRadius);
|
|
}
|
|
|
|
public override bool Equals(object obj) {
|
|
if (ReferenceEquals(null, obj)) {
|
|
return false;
|
|
}
|
|
|
|
if (ReferenceEquals(this, obj)) {
|
|
return true;
|
|
}
|
|
|
|
if (obj.GetType() != this.GetType()) {
|
|
return false;
|
|
}
|
|
|
|
return this.Equals((RoundedRectangleBorder) obj);
|
|
}
|
|
|
|
public override int GetHashCode() {
|
|
unchecked {
|
|
return ((this.side != null ? this.side.GetHashCode() : 0) * 397) ^
|
|
(this.borderRadius != null ? this.borderRadius.GetHashCode() : 0);
|
|
}
|
|
}
|
|
|
|
public static bool operator ==(RoundedRectangleBorder left, RoundedRectangleBorder right) {
|
|
return Equals(left, right);
|
|
}
|
|
|
|
public static bool operator !=(RoundedRectangleBorder left, RoundedRectangleBorder right) {
|
|
return !Equals(left, right);
|
|
}
|
|
|
|
public override string ToString() {
|
|
return $"{this.GetType()}({this.side}, {this.borderRadius})";
|
|
}
|
|
}
|
|
|
|
class _RoundedRectangleToCircleBorder : ShapeBorder, IEquatable<_RoundedRectangleToCircleBorder> {
|
|
public _RoundedRectangleToCircleBorder(
|
|
BorderSide side = null,
|
|
BorderRadius borderRadius = null,
|
|
double circleness = 0.0
|
|
) {
|
|
this.side = side ?? BorderSide.none;
|
|
this.borderRadius = borderRadius ?? BorderRadius.zero;
|
|
this.circleness = circleness;
|
|
}
|
|
|
|
public readonly BorderSide side;
|
|
|
|
public readonly BorderRadius borderRadius;
|
|
|
|
public readonly double circleness;
|
|
|
|
public override EdgeInsets dimensions {
|
|
get { return EdgeInsets.all(this.side.width); }
|
|
}
|
|
|
|
public override ShapeBorder scale(double t) {
|
|
return new _RoundedRectangleToCircleBorder(
|
|
side: this.side.scale(t),
|
|
borderRadius: this.borderRadius * t,
|
|
circleness: t
|
|
);
|
|
}
|
|
|
|
public override ShapeBorder lerpFrom(ShapeBorder a, double t) {
|
|
if (a is RoundedRectangleBorder rectBorder) {
|
|
return new _RoundedRectangleToCircleBorder(
|
|
side: BorderSide.lerp(rectBorder.side, this.side, t),
|
|
borderRadius: BorderRadius.lerp(rectBorder.borderRadius, this.borderRadius, t),
|
|
circleness: this.circleness * t
|
|
);
|
|
}
|
|
|
|
if (a is CircleBorder circleBorder) {
|
|
return new _RoundedRectangleToCircleBorder(
|
|
side: BorderSide.lerp(circleBorder.side, this.side, t),
|
|
borderRadius: this.borderRadius,
|
|
circleness: this.circleness + (1.0 - this.circleness) * (1.0 - t)
|
|
);
|
|
}
|
|
|
|
if (a is _RoundedRectangleToCircleBorder border) {
|
|
return new _RoundedRectangleToCircleBorder(
|
|
side: BorderSide.lerp(border.side, this.side, t),
|
|
borderRadius: BorderRadius.lerp(border.borderRadius, this.borderRadius, t),
|
|
circleness: MathUtils.lerpDouble(border.circleness, this.circleness, t)
|
|
);
|
|
}
|
|
|
|
return base.lerpFrom(a, t);
|
|
}
|
|
|
|
public override ShapeBorder lerpTo(ShapeBorder b, double t) {
|
|
if (b is RoundedRectangleBorder rectBorder) {
|
|
return new _RoundedRectangleToCircleBorder(
|
|
side: BorderSide.lerp(this.side, rectBorder.side, t),
|
|
borderRadius: BorderRadius.lerp(this.borderRadius, rectBorder.borderRadius, t),
|
|
circleness: this.circleness * (1.0 - t)
|
|
);
|
|
}
|
|
|
|
if (b is CircleBorder circleBorder) {
|
|
return new _RoundedRectangleToCircleBorder(
|
|
side: BorderSide.lerp(this.side, circleBorder.side, t),
|
|
borderRadius: this.borderRadius,
|
|
circleness: this.circleness + (1.0 - this.circleness) * t
|
|
);
|
|
}
|
|
|
|
if (b is _RoundedRectangleToCircleBorder border) {
|
|
return new _RoundedRectangleToCircleBorder(
|
|
side: BorderSide.lerp(this.side, border.side, t),
|
|
borderRadius: BorderRadius.lerp(this.borderRadius, border.borderRadius, t),
|
|
circleness: MathUtils.lerpDouble(this.circleness, border.circleness, t)
|
|
);
|
|
}
|
|
|
|
return base.lerpTo(b, t);
|
|
}
|
|
|
|
Rect _adjustRect(Rect rect) {
|
|
if (this.circleness == 0.0 || rect.width == rect.height) {
|
|
return rect;
|
|
}
|
|
|
|
if (rect.width < rect.height) {
|
|
double delta = this.circleness * (rect.height - rect.width) / 2.0;
|
|
return Rect.fromLTRB(
|
|
rect.left,
|
|
rect.top + delta,
|
|
rect.right,
|
|
rect.bottom - delta
|
|
);
|
|
}
|
|
else {
|
|
double delta = this.circleness * (rect.width - rect.height) / 2.0;
|
|
return Rect.fromLTRB(
|
|
rect.left + delta,
|
|
rect.top,
|
|
rect.right - delta,
|
|
rect.bottom
|
|
);
|
|
}
|
|
}
|
|
|
|
BorderRadius _adjustBorderRadius(Rect rect) {
|
|
BorderRadius resolvedRadius = this.borderRadius;
|
|
if (this.circleness == 0.0) {
|
|
return resolvedRadius;
|
|
}
|
|
|
|
return BorderRadius.lerp(resolvedRadius, BorderRadius.circular(rect.shortestSide / 2.0), this.circleness);
|
|
}
|
|
|
|
public override Path getInnerPath(Rect rect) {
|
|
var path = new Path();
|
|
path.addRRect(this._adjustBorderRadius(rect).toRRect(this._adjustRect(rect)).deflate(this.side.width));
|
|
return path;
|
|
}
|
|
|
|
public override Path getOuterPath(Rect rect) {
|
|
var path = new Path();
|
|
path.addRRect(this._adjustBorderRadius(rect).toRRect(this._adjustRect(rect)));
|
|
return path;
|
|
}
|
|
|
|
public override void paint(Canvas canvas, Rect rect) {
|
|
switch (this.side.style) {
|
|
case BorderStyle.none:
|
|
break;
|
|
case BorderStyle.solid:
|
|
double width = this.side.width;
|
|
if (width == 0.0) {
|
|
canvas.drawRRect(this._adjustBorderRadius(rect).toRRect(this._adjustRect(rect)),
|
|
this.side.toPaint());
|
|
}
|
|
else {
|
|
RRect outer = this._adjustBorderRadius(rect).toRRect(this._adjustRect(rect));
|
|
RRect inner = outer.deflate(width);
|
|
Paint paint = new Paint {
|
|
color = this.side.color,
|
|
};
|
|
canvas.drawDRRect(outer, inner, paint);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
public bool Equals(_RoundedRectangleToCircleBorder other) {
|
|
if (ReferenceEquals(null, other)) {
|
|
return false;
|
|
}
|
|
|
|
if (ReferenceEquals(this, other)) {
|
|
return true;
|
|
}
|
|
|
|
return Equals(this.side, other.side) && Equals(this.borderRadius, other.borderRadius) &&
|
|
this.circleness.Equals(other.circleness);
|
|
}
|
|
|
|
public override bool Equals(object obj) {
|
|
if (ReferenceEquals(null, obj)) {
|
|
return false;
|
|
}
|
|
|
|
if (ReferenceEquals(this, obj)) {
|
|
return true;
|
|
}
|
|
|
|
if (obj.GetType() != this.GetType()) {
|
|
return false;
|
|
}
|
|
|
|
return this.Equals((_RoundedRectangleToCircleBorder) obj);
|
|
}
|
|
|
|
public override int GetHashCode() {
|
|
unchecked {
|
|
var hashCode = (this.side != null ? this.side.GetHashCode() : 0);
|
|
hashCode = (hashCode * 397) ^ (this.borderRadius != null ? this.borderRadius.GetHashCode() : 0);
|
|
hashCode = (hashCode * 397) ^ this.circleness.GetHashCode();
|
|
return hashCode;
|
|
}
|
|
}
|
|
|
|
public static bool operator ==(_RoundedRectangleToCircleBorder left, _RoundedRectangleToCircleBorder right) {
|
|
return Equals(left, right);
|
|
}
|
|
|
|
public static bool operator !=(_RoundedRectangleToCircleBorder left, _RoundedRectangleToCircleBorder right) {
|
|
return !Equals(left, right);
|
|
}
|
|
|
|
public override string ToString() {
|
|
return $"RoundedRectangleBorder({this.side}, {this.borderRadius}, " +
|
|
$"{this.circleness * 100:F1}% of the way to being a CircleBorder)";
|
|
}
|
|
}
|
|
}
|