From 3a3d450592774ae60a8490fa43f91cb90ee59c3f Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 22 Apr 2019 15:18:51 -0700 Subject: [PATCH 1/2] Revert "fix toString (#8688)" This reverts commit 9fa7336784b56ef70fd3580ac54d2939d1faa5a0. --- lib/ui/geometry.dart | 2 +- testing/dart/rect_test.dart | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/ui/geometry.dart b/lib/ui/geometry.dart index b99a01fec44b6..59e5e65c9b03a 100644 --- a/lib/ui/geometry.dart +++ b/lib/ui/geometry.dart @@ -879,7 +879,7 @@ class Rect { int get hashCode => hashValues(left, top, right, bottom); @override - String toString() => 'Rect.fromLTRB(${left.toStringAsFixed(1)}, ${top.toStringAsFixed(1)}, ${right.toStringAsFixed(1)}, ${bottom.toStringAsFixed(1)})'; + String toString() => 'Rect.fromLTRB(${left.toStringAsFixed(1)} ${top.toStringAsFixed(1)}, ${right.toStringAsFixed(1)}, ${bottom.toStringAsFixed(1)})'; } /// A radius for either circular or elliptical shapes. diff --git a/testing/dart/rect_test.dart b/testing/dart/rect_test.dart index 0248ad6241e13..b8b893351c7dd 100644 --- a/testing/dart/rect_test.dart +++ b/testing/dart/rect_test.dart @@ -7,11 +7,6 @@ import 'dart:ui'; import 'package:test/test.dart'; void main() { - test('toString test', () { - const Rect r = Rect.fromLTRB(1.0, 3.0, 5.0, 7.0); - expect(r.toString(), 'Rect.fromLTRB(1.0, 3.0, 5.0, 7.0)'); - }); - test('rect accessors', () { const Rect r = Rect.fromLTRB(1.0, 3.0, 5.0, 7.0); expect(r.left, equals(1.0)); From f2455619615aa2b38165d9abce7ec50542e136cd Mon Sep 17 00:00:00 2001 From: Dan Field Date: Mon, 22 Apr 2019 15:19:04 -0700 Subject: [PATCH 2/2] Revert "Make Rect and RRect use 64 bit doubles, and make them const-able (#8565)" This reverts commit c12315273f6344175dae748ec1f23e15b4e7d59e. --- lib/stub_ui/lib/geometry.dart | 619 ++++++++++++++++------------------ lib/stub_ui/lib/painting.dart | 4 +- lib/ui/compositing.dart | 2 +- lib/ui/geometry.dart | 619 ++++++++++++++++------------------ lib/ui/painting.dart | 16 +- testing/dart/rect_test.dart | 18 +- 6 files changed, 610 insertions(+), 668 deletions(-) diff --git a/lib/stub_ui/lib/geometry.dart b/lib/stub_ui/lib/geometry.dart index 35f04ee070474..e112ef2389a8c 100644 --- a/lib/stub_ui/lib/geometry.dart +++ b/lib/stub_ui/lib/geometry.dart @@ -619,52 +619,65 @@ class Size extends OffsetBase { /// Rect myRect = const Offset(1.0, 2.0) & const Size(3.0, 4.0); /// ``` class Rect { + Rect._(); + /// Construct a rectangle from its left, top, right, and bottom edges. - const Rect.fromLTRB(this.left, this.top, this.right, this.bottom) - : assert(left != null), - assert(top != null), - assert(right != null), - assert(bottom != null); + Rect.fromLTRB(double left, double top, double right, double bottom) { + _value + ..[0] = left + ..[1] = top + ..[2] = right + ..[3] = bottom; + } /// Construct a rectangle from its left and top edges, its width, and its /// height. /// /// To construct a [Rect] from an [Offset] and a [Size], you can use the /// rectangle constructor operator `&`. See [Offset.&]. - const Rect.fromLTWH(double left, double top, double width, double height) : this.fromLTRB(left, top, left + width, top + height); + Rect.fromLTWH(double left, double top, double width, double height) { + _value + ..[0] = left + ..[1] = top + ..[2] = left + width + ..[3] = top + height; + } /// Construct a rectangle that bounds the given circle. /// /// The `center` argument is assumed to be an offset from the origin. - Rect.fromCircle({ Offset center, double radius }) : this.fromLTRB( - center.dx - radius, - center.dy - radius, - center.dx + radius, - center.dy + radius, - ); + Rect.fromCircle({ Offset center, double radius }) { + _value + ..[0] = center.dx - radius + ..[1] = center.dy - radius + ..[2] = center.dx + radius + ..[3] = center.dy + radius; + } /// Construct the smallest rectangle that encloses the given offsets, treating /// them as vectors from the origin. - Rect.fromPoints(Offset a, Offset b) : this.fromLTRB( - math.min(a.dx, b.dx), - math.min(a.dy, b.dy), - math.max(a.dx, b.dx), - math.max(a.dy, b.dy), - ); + Rect.fromPoints(Offset a, Offset b) { + _value + ..[0] = math.min(a.dx, b.dx) + ..[1] = math.min(a.dy, b.dy) + ..[2] = math.max(a.dx, b.dx) + ..[3] = math.max(a.dy, b.dy); + } - Float32List get _value32 => Float32List.fromList([left, top, right, bottom]); + static const int _kDataSize = 4; + final Float32List _value = new Float32List(_kDataSize); /// The offset of the left edge of this rectangle from the x axis. - final double left; + double get left => _value[0]; /// The offset of the top edge of this rectangle from the y axis. - final double top; + double get top => _value[1]; /// The offset of the right edge of this rectangle from the x axis. - final double right; + double get right => _value[2]; /// The offset of the bottom edge of this rectangle from the y axis. - final double bottom; + double get bottom => _value[3]; /// The distance between the left and right edges of this rectangle. double get width => right - left; @@ -676,11 +689,8 @@ class Rect { /// this rectangle. Size get size => new Size(width, height); - /// Whether any of the dimensions are `NaN`. - bool get hasNaN => left.isNaN || top.isNaN || right.isNaN || bottom.isNaN; - /// A rectangle with left, top, right, and bottom edges all at zero. - static const Rect zero = Rect.fromLTRB(0.0, 0.0, 0.0, 0.0); + static final Rect zero = new Rect._(); static const double _giantScalar = 1.0E+9; // matches kGiantRect from layer.h @@ -688,7 +698,7 @@ class Rect { /// /// This covers the space from -1e9,-1e9 to 1e9,1e9. /// This is the space over which graphics operations are valid. - static const Rect largest = Rect.fromLTRB(-_giantScalar, -_giantScalar, _giantScalar, _giantScalar); + static final Rect largest = new Rect.fromLTRB(-_giantScalar, -_giantScalar, _giantScalar, _giantScalar); /// Whether any of the coordinates of this rectangle are equal to positive infinity. // included for consistency with Offset and Size @@ -868,17 +878,18 @@ class Rect { if (runtimeType != other.runtimeType) return false; final Rect typedOther = other; - return left == typedOther.left && - top == typedOther.top && - right == typedOther.right && - bottom == typedOther.bottom; + for (int i = 0; i < _kDataSize; i += 1) { + if (_value[i] != typedOther._value[i]) + return false; + } + return true; } @override - int get hashCode => hashValues(left, top, right, bottom); + int get hashCode => hashList(_value); @override - String toString() => 'Rect.fromLTRB(${left.toStringAsFixed(1)} ${top.toStringAsFixed(1)}, ${right.toStringAsFixed(1)}, ${bottom.toStringAsFixed(1)})'; + String toString() => 'Rect.fromLTRB(${left.toStringAsFixed(1)}, ${top.toStringAsFixed(1)}, ${right.toStringAsFixed(1)}, ${bottom.toStringAsFixed(1)})'; } /// A radius for either circular or elliptical shapes. @@ -1006,78 +1017,81 @@ class Radius { /// An immutable rounded rectangle with the custom radii for all four corners. class RRect { + RRect._(); + /// Construct a rounded rectangle from its left, top, right, and bottom edges, /// and the same radii along its horizontal axis and its vertical axis. - const RRect.fromLTRBXY(double left, double top, double right, double bottom, - double radiusX, double radiusY) : this._raw( - top: top, - left: left, - right: right, - bottom: bottom, - tlRadiusX: radiusX, - tlRadiusY: radiusY, - trRadiusX: radiusX, - trRadiusY: radiusY, - blRadiusX: radiusX, - blRadiusY: radiusY, - brRadiusX: radiusX, - brRadiusY: radiusY, - ); + RRect.fromLTRBXY(double left, double top, double right, double bottom, + double radiusX, double radiusY) { + _value + ..[0] = left + ..[1] = top + ..[2] = right + ..[3] = bottom + ..[4] = radiusX + ..[5] = radiusY + ..[6] = radiusX + ..[7] = radiusY + ..[8] = radiusX + ..[9] = radiusY + ..[10] = radiusX + ..[11] = radiusY; + } /// Construct a rounded rectangle from its left, top, right, and bottom edges, /// and the same radius in each corner. RRect.fromLTRBR(double left, double top, double right, double bottom, - Radius radius) - : this._raw( - top: top, - left: left, - right: right, - bottom: bottom, - tlRadiusX: radius.x, - tlRadiusY: radius.y, - trRadiusX: radius.x, - trRadiusY: radius.y, - blRadiusX: radius.x, - blRadiusY: radius.y, - brRadiusX: radius.x, - brRadiusY: radius.y, - ); + Radius radius) { + _value + ..[0] = left + ..[1] = top + ..[2] = right + ..[3] = bottom + ..[4] = radius.x + ..[5] = radius.y + ..[6] = radius.x + ..[7] = radius.y + ..[8] = radius.x + ..[9] = radius.y + ..[10] = radius.x + ..[11] = radius.y; + } /// Construct a rounded rectangle from its bounding box and the same radii /// along its horizontal axis and its vertical axis. - RRect.fromRectXY(Rect rect, double radiusX, double radiusY) - : this._raw( - top: rect.top, - left: rect.left, - right: rect.right, - bottom: rect.bottom, - tlRadiusX: radiusX, - tlRadiusY: radiusY, - trRadiusX: radiusX, - trRadiusY: radiusY, - blRadiusX: radiusX, - blRadiusY: radiusY, - brRadiusX: radiusX, - brRadiusY: radiusY, - ); + RRect.fromRectXY(Rect rect, double radiusX, double radiusY) { + _value + ..[0] = rect.left + ..[1] = rect.top + ..[2] = rect.right + ..[3] = rect.bottom + ..[4] = radiusX + ..[5] = radiusY + ..[6] = radiusX + ..[7] = radiusY + ..[8] = radiusX + ..[9] = radiusY + ..[10] = radiusX + ..[11] = radiusY; + } /// Construct a rounded rectangle from its bounding box and a radius that is /// the same in each corner. - RRect.fromRectAndRadius(Rect rect, Radius radius) - : this._raw( - top: rect.top, - left: rect.left, - right: rect.right, - bottom: rect.bottom, - tlRadiusX: radius.x, - tlRadiusY: radius.y, - trRadiusX: radius.x, - trRadiusY: radius.y, - blRadiusX: radius.x, - blRadiusY: radius.y, - brRadiusX: radius.x, - brRadiusY: radius.y, - ); + RRect.fromRectAndRadius(Rect rect, Radius radius) { + _value + ..[0] = rect.left + ..[1] = rect.top + ..[2] = rect.right + ..[3] = rect.bottom + ..[4] = radius.x + ..[5] = radius.y + ..[6] = radius.x + ..[7] = radius.y + ..[8] = radius.x + ..[9] = radius.y + ..[10] = radius.x + ..[11] = radius.y; + } /// Construct a rounded rectangle from its left, top, right, and bottom edges, /// and topLeft, topRight, bottomRight, and bottomLeft radii. @@ -1092,20 +1106,21 @@ class RRect { Radius topRight: Radius.zero, Radius bottomRight: Radius.zero, Radius bottomLeft: Radius.zero, - }) : this._raw( - top: top, - left: left, - right: right, - bottom: bottom, - tlRadiusX: topLeft.x, - tlRadiusY: topLeft.y, - trRadiusX: topRight.x, - trRadiusY: topRight.y, - blRadiusX: bottomLeft.x, - blRadiusY: bottomLeft.y, - brRadiusX: bottomRight.x, - brRadiusY: bottomRight.y, - ); + }) { + _value + ..[0] = left + ..[1] = top + ..[2] = right + ..[3] = bottom + ..[4] = topLeft.x + ..[5] = topLeft.y + ..[6] = topRight.x + ..[7] = topRight.y + ..[8] = bottomRight.x + ..[9] = bottomRight.y + ..[10] = bottomLeft.x + ..[11] = bottomLeft.y; + } /// Construct a rounded rectangle from its bounding box and and topLeft, /// topRight, bottomRight, and bottomLeft radii. @@ -1119,147 +1134,132 @@ class RRect { Radius bottomRight: Radius.zero, Radius bottomLeft: Radius.zero } - ) : this._raw( - top: rect.top, - left: rect.left, - right: rect.right, - bottom: rect.bottom, - tlRadiusX: topLeft.x, - tlRadiusY: topLeft.y, - trRadiusX: topRight.x, - trRadiusY: topRight.y, - blRadiusX: bottomLeft.x, - blRadiusY: bottomLeft.y, - brRadiusX: bottomRight.x, - brRadiusY: bottomRight.y, - ); - - const RRect._raw({ - this.left, - this.top, - this.right, - this.bottom, - this.tlRadiusX, - this.tlRadiusY, - this.trRadiusX, - this.trRadiusY, - this.brRadiusX, - this.brRadiusY, - this.blRadiusX, - this.blRadiusY, - }) : assert(left != null), - assert(top != null), - assert(right != null), - assert(bottom != null), - assert(tlRadiusX != null), - assert(tlRadiusY != null), - assert(trRadiusX != null), - assert(trRadiusY != null), - assert(brRadiusX != null), - assert(brRadiusY != null), - assert(blRadiusX != null), - assert(blRadiusY != null); - - Float32List get _value32 => Float32List.fromList([ - left, - top, - right, - bottom, - tlRadiusX, - tlRadiusY, - trRadiusX, - trRadiusY, - brRadiusX, - brRadiusY, - blRadiusX, - blRadiusY, - ]); + ) { + _value + ..[0] = rect.left + ..[1] = rect.top + ..[2] = rect.right + ..[3] = rect.bottom + ..[4] = topLeft.x + ..[5] = topLeft.y + ..[6] = topRight.x + ..[7] = topRight.y + ..[8] = bottomRight.x + ..[9] = bottomRight.y + ..[10] = bottomLeft.x + ..[11] = bottomLeft.y; + } + + RRect._fromList(List list) { + for (int i = 0; i < _kDataSize; i += 1) + _value[i] = list[i]; + } + + static const int _kDataSize = 12; + final Float32List _value = new Float32List(_kDataSize); + RRect _scaled; // same RRect with scaled radii per side /// The offset of the left edge of this rectangle from the x axis. - final double left; + double get left => _value[0]; /// The offset of the top edge of this rectangle from the y axis. - final double top; + double get top => _value[1]; /// The offset of the right edge of this rectangle from the x axis. - final double right; + double get right => _value[2]; /// The offset of the bottom edge of this rectangle from the y axis. - final double bottom; + double get bottom => _value[3]; /// The top-left horizontal radius. - final double tlRadiusX; + double get tlRadiusX => _value[4]; /// The top-left vertical radius. - final double tlRadiusY; + double get tlRadiusY => _value[5]; /// The top-left [Radius]. - Radius get tlRadius => new Radius.elliptical(tlRadiusX, tlRadiusY); + Radius get tlRadius => new Radius.elliptical(_value[4], _value[5]); /// The top-right horizontal radius. - final double trRadiusX; + double get trRadiusX => _value[6]; /// The top-right vertical radius. - final double trRadiusY; + double get trRadiusY => _value[7]; /// The top-right [Radius]. - Radius get trRadius => new Radius.elliptical(trRadiusX, trRadiusY); + Radius get trRadius => new Radius.elliptical(_value[6], _value[7]); /// The bottom-right horizontal radius. - final double brRadiusX; + double get brRadiusX => _value[8]; /// The bottom-right vertical radius. - final double brRadiusY; + double get brRadiusY => _value[9]; /// The bottom-right [Radius]. - Radius get brRadius => new Radius.elliptical(brRadiusX, brRadiusY); + Radius get brRadius => new Radius.elliptical(_value[8], _value[9]); /// The bottom-left horizontal radius. - final double blRadiusX; + double get blRadiusX => _value[10]; /// The bottom-left vertical radius. - final double blRadiusY; + double get blRadiusY => _value[11]; /// The bottom-left [Radius]. - Radius get blRadius => new Radius.elliptical(blRadiusX, blRadiusY); + Radius get blRadius => new Radius.elliptical(_value[10], _value[11]); /// A rounded rectangle with all the values set to zero. - static final RRect zero = new RRect._raw(); + static final RRect zero = new RRect._(); /// Returns a new [RRect] translated by the given offset. RRect shift(Offset offset) { - return new RRect._raw( - left: left + offset.dx, - top: top + offset.dy, - right: right + offset.dx, - bottom: bottom + offset.dy, - tlRadiusX: tlRadiusX, - tlRadiusY: tlRadiusY, - trRadiusX: trRadiusX, - trRadiusY: trRadiusY, - blRadiusX: blRadiusX, - blRadiusY: blRadiusY, - brRadiusX: brRadiusX, - brRadiusY: brRadiusY, + return new RRect.fromLTRBAndCorners( + _value[0] + offset.dx, + _value[1] + offset.dy, + _value[2] + offset.dx, + _value[3] + offset.dy, + topLeft: new Radius.elliptical( + _value[4], + _value[5] + ), + topRight: new Radius.elliptical( + _value[6], + _value[7] + ), + bottomRight: new Radius.elliptical( + _value[8], + _value[9] + ), + bottomLeft: new Radius.elliptical( + _value[10], + _value[11] + ) ); } /// Returns a new [RRect] with edges and radii moved outwards by the given /// delta. RRect inflate(double delta) { - return new RRect._raw( - left: left - delta, - top: top - delta, - right: right + delta, - bottom: bottom + delta, - tlRadiusX: tlRadiusX + delta, - tlRadiusY: tlRadiusY + delta, - trRadiusX: trRadiusX + delta, - trRadiusY: trRadiusY + delta, - blRadiusX: blRadiusX + delta, - blRadiusY: blRadiusY + delta, - brRadiusX: brRadiusX + delta, - brRadiusY: brRadiusY + delta, + return new RRect.fromLTRBAndCorners( + _value[0] - delta, + _value[1] - delta, + _value[2] + delta, + _value[3] + delta, + topLeft: new Radius.elliptical( + _value[4] + delta, + _value[5] + delta + ), + topRight: new Radius.elliptical( + _value[6] + delta, + _value[7] + delta + ), + bottomRight: new Radius.elliptical( + _value[8] + delta, + _value[9] + delta + ), + bottomLeft: new Radius.elliptical( + _value[10] + delta, + _value[11] + delta + ) ); } @@ -1388,10 +1388,6 @@ class RRect { /// rounded rectangle. double get longestSide => math.max(width.abs(), height.abs()); - /// Whether any of the dimensions are `NaN`. - bool get hasNaN => left.isNaN || top.isNaN || right.isNaN || bottom.isNaN || - trRadiusX.isNaN || trRadiusY.isNaN || tlRadiusX.isNaN || tlRadiusY.isNaN || - brRadiusX.isNaN || brRadiusY.isNaN || blRadiusX.isNaN || blRadiusY.isNaN; /// The offset to the point halfway between the left and right and the top and /// bottom edges of this rectangle. @@ -1411,39 +1407,23 @@ class RRect { // // Inspired from: // https://github.com/google/skia/blob/master/src/core/SkRRect.cpp#L164 - RRect _scaleRadii() { - double scale = 1.0; - scale = _getMin(scale, blRadiusY, tlRadiusY, height); - scale = _getMin(scale, tlRadiusX, trRadiusX, width); - scale = _getMin(scale, trRadiusY, brRadiusY, height); - scale = _getMin(scale, brRadiusX, blRadiusX, width); - - double scaledLeft = left; - double scaledTop = top; - double scaledRight = right; - double scaledBottom = bottom; - - if (scale < 1.0) { - scaledTop *= scale; - scaledLeft *= scale; - scaledRight *= scale; - scaledBottom *= scale; + void _scaleRadii() { + if (_scaled == null) { + double scale = 1.0; + final List scaled = new List.from(_value); + + scale = _getMin(scale, scaled[11], scaled[5], height); + scale = _getMin(scale, scaled[4], scaled[6], width); + scale = _getMin(scale, scaled[7], scaled[9], height); + scale = _getMin(scale, scaled[8], scaled[10], width); + + if (scale < 1.0) { + for (int i = 4; i < _kDataSize; i += 1) + scaled[i] *= scale; + } + + _scaled = new RRect._fromList(scaled); } - - return new RRect._raw( - top: scaledTop, - left: scaledLeft, - right: scaledRight, - bottom: scaledBottom, - tlRadiusX: tlRadiusX, - tlRadiusY: tlRadiusY, - trRadiusX: trRadiusX, - trRadiusY: trRadiusY, - blRadiusX: blRadiusX, - blRadiusY: blRadiusY, - brRadiusX: brRadiusX, - brRadiusY: brRadiusY, - ); } /// Whether the point specified by the given offset (which is assumed to be @@ -1457,7 +1437,7 @@ class RRect { if (point.dx < left || point.dx >= right || point.dy < top || point.dy >= bottom) return false; // outside bounding box - final RRect scaled = _scaleRadii(); + _scaleRadii(); double x; double y; @@ -1465,30 +1445,30 @@ class RRect { double radiusY; // check whether point is in one of the rounded corner areas // x, y -> translate to ellipse center - if (point.dx < left + scaled.tlRadiusX && - point.dy < top + scaled.tlRadiusY) { - x = point.dx - left - scaled.tlRadiusX; - y = point.dy - top - scaled.tlRadiusY; - radiusX = scaled.tlRadiusX; - radiusY = scaled.tlRadiusY; - } else if (point.dx > right - scaled.trRadiusX && - point.dy < top + scaled.trRadiusY) { - x = point.dx - right + scaled.trRadiusX; - y = point.dy - top - scaled.trRadiusY; - radiusX = scaled.trRadiusX; - radiusY = scaled.trRadiusY; - } else if (point.dx > right - scaled.brRadiusX && - point.dy > bottom - scaled.brRadiusY) { - x = point.dx - right + scaled.brRadiusX; - y = point.dy - bottom + scaled.brRadiusY; - radiusX = scaled.brRadiusX; - radiusY = scaled.brRadiusY; - } else if (point.dx < left + scaled.blRadiusX && - point.dy > bottom - scaled.blRadiusY) { - x = point.dx - left - scaled.blRadiusX; - y = point.dy - bottom + scaled.blRadiusY; - radiusX = scaled.blRadiusX; - radiusY = scaled.blRadiusY; + if (point.dx < left + _scaled.tlRadiusX && + point.dy < top + _scaled.tlRadiusY) { + x = point.dx - left - _scaled.tlRadiusX; + y = point.dy - top - _scaled.tlRadiusY; + radiusX = _scaled.tlRadiusX; + radiusY = _scaled.tlRadiusY; + } else if (point.dx > right - _scaled.trRadiusX && + point.dy < top + _scaled.trRadiusY) { + x = point.dx - right + _scaled.trRadiusX; + y = point.dy - top - _scaled.trRadiusY; + radiusX = _scaled.trRadiusX; + radiusY = _scaled.trRadiusY; + } else if (point.dx > right - _scaled.brRadiusX && + point.dy > bottom - _scaled.brRadiusY) { + x = point.dx - right + _scaled.brRadiusX; + y = point.dy - bottom + _scaled.brRadiusY; + radiusX = _scaled.brRadiusX; + radiusY = _scaled.brRadiusY; + } else if (point.dx < left + _scaled.blRadiusX && + point.dy > bottom - _scaled.blRadiusY) { + x = point.dx - left - _scaled.blRadiusX; + y = point.dy - bottom + _scaled.blRadiusY; + radiusX = _scaled.blRadiusX; + radiusY = _scaled.blRadiusY; } else { return true; // inside and not within the rounded corner area } @@ -1521,52 +1501,52 @@ class RRect { if (a == null && b == null) return null; if (a == null) { - return new RRect._raw( - left: b.left * t, - top: b.top * t, - right: b.right * t, - bottom: b.bottom * t, - tlRadiusX: b.tlRadiusX * t, - tlRadiusY: b.tlRadiusY * t, - trRadiusX: b.trRadiusX * t, - trRadiusY: b.trRadiusY * t, - brRadiusX: b.brRadiusX * t, - brRadiusY: b.brRadiusY * t, - blRadiusX: b.blRadiusX * t, - blRadiusY: b.blRadiusY * t, - ); + return new RRect._fromList([ + b.left * t, + b.top * t, + b.right * t, + b.bottom * t, + b.tlRadiusX * t, + b.tlRadiusY * t, + b.trRadiusX * t, + b.trRadiusY * t, + b.brRadiusX * t, + b.brRadiusY * t, + b.blRadiusX * t, + b.blRadiusY * t, + ]); } if (b == null) { final double k = 1.0 - t; - return new RRect._raw( - left: a.left * k, - top: a.top * k, - right: a.right * k, - bottom: a.bottom * k, - tlRadiusX: a.tlRadiusX * k, - tlRadiusY: a.tlRadiusY * k, - trRadiusX: a.trRadiusX * k, - trRadiusY: a.trRadiusY * k, - brRadiusX: a.brRadiusX * k, - brRadiusY: a.brRadiusY * k, - blRadiusX: a.blRadiusX * k, - blRadiusY: a.blRadiusY * k, - ); + return new RRect._fromList([ + a.left * k, + a.top * k, + a.right * k, + a.bottom * k, + a.tlRadiusX * k, + a.tlRadiusY * k, + a.trRadiusX * k, + a.trRadiusY * k, + a.brRadiusX * k, + a.brRadiusY * k, + a.blRadiusX * k, + a.blRadiusY * k, + ]); } - return new RRect._raw( - left: lerpDouble(a.left, b.left, t), - top: lerpDouble(a.top, b.top, t), - right: lerpDouble(a.right, b.right, t), - bottom: lerpDouble(a.bottom, b.bottom, t), - tlRadiusX: lerpDouble(a.tlRadiusX, b.tlRadiusX, t), - tlRadiusY: lerpDouble(a.tlRadiusY, b.tlRadiusY, t), - trRadiusX: lerpDouble(a.trRadiusX, b.trRadiusX, t), - trRadiusY: lerpDouble(a.trRadiusY, b.trRadiusY, t), - brRadiusX: lerpDouble(a.brRadiusX, b.brRadiusX, t), - brRadiusY: lerpDouble(a.brRadiusY, b.brRadiusY, t), - blRadiusX: lerpDouble(a.blRadiusX, b.blRadiusX, t), - blRadiusY: lerpDouble(a.blRadiusY, b.blRadiusY, t), - ); + return new RRect._fromList([ + lerpDouble(a.left, b.left, t), + lerpDouble(a.top, b.top, t), + lerpDouble(a.right, b.right, t), + lerpDouble(a.bottom, b.bottom, t), + lerpDouble(a.tlRadiusX, b.tlRadiusX, t), + lerpDouble(a.tlRadiusY, b.tlRadiusY, t), + lerpDouble(a.trRadiusX, b.trRadiusX, t), + lerpDouble(a.trRadiusY, b.trRadiusY, t), + lerpDouble(a.brRadiusX, b.brRadiusX, t), + lerpDouble(a.brRadiusY, b.brRadiusY, t), + lerpDouble(a.blRadiusX, b.blRadiusX, t), + lerpDouble(a.blRadiusY, b.blRadiusY, t), + ]); } @override @@ -1576,24 +1556,15 @@ class RRect { if (runtimeType != other.runtimeType) return false; final RRect typedOther = other; - return left == typedOther.left && - top == typedOther.top && - right == typedOther.right && - bottom == typedOther.bottom && - tlRadiusX == typedOther.tlRadiusX && - tlRadiusY == typedOther.tlRadiusY && - trRadiusX == typedOther.trRadiusX && - trRadiusY == typedOther.trRadiusY && - blRadiusX == typedOther.blRadiusX && - blRadiusY == typedOther.blRadiusY && - brRadiusX == typedOther.brRadiusX && - brRadiusY == typedOther.brRadiusY; + for (int i = 0; i < _kDataSize; i += 1) { + if (_value[i] != typedOther._value[i]) + return false; + } + return true; } @override - int get hashCode => hashValues(left, top, right, bottom, - tlRadiusX, tlRadiusY, trRadiusX, trRadiusY, - blRadiusX, blRadiusY, brRadiusX, brRadiusY); + int get hashCode => hashList(_value); @override String toString() { diff --git a/lib/stub_ui/lib/painting.dart b/lib/stub_ui/lib/painting.dart index 22312ae0281d5..881d2010d2ee6 100644 --- a/lib/stub_ui/lib/painting.dart +++ b/lib/stub_ui/lib/painting.dart @@ -23,13 +23,13 @@ part of ui; bool _rectIsValid(Rect rect) { assert(rect != null, 'Rect argument was null.'); - assert(!rect.hasNaN, 'Rect argument contained a NaN value.'); + assert(!rect._value.any((double value) => value.isNaN), 'Rect argument contained a NaN value.'); return true; } bool _rrectIsValid(RRect rrect) { assert(rrect != null, 'RRect argument was null.'); - assert(!rrect.hasNaN, 'RRect argument contained a NaN value.'); + assert(!rrect._value.any((double value) => value.isNaN), 'RRect argument contained a NaN value.'); return true; } diff --git a/lib/ui/compositing.dart b/lib/ui/compositing.dart index 06906ed50b972..8b3f98c821106 100644 --- a/lib/ui/compositing.dart +++ b/lib/ui/compositing.dart @@ -98,7 +98,7 @@ class SceneBuilder extends NativeFieldWrapperClass2 { EngineLayer pushClipRRect(RRect rrect, {Clip clipBehavior = Clip.antiAlias}) { assert(clipBehavior != null); assert(clipBehavior != Clip.none); - return _pushClipRRect(rrect._value32, clipBehavior.index); + return _pushClipRRect(rrect._value, clipBehavior.index); } EngineLayer _pushClipRRect(Float32List rrect, int clipBehavior) native 'SceneBuilder_pushClipRRect'; diff --git a/lib/ui/geometry.dart b/lib/ui/geometry.dart index 59e5e65c9b03a..2e8a79980c2dc 100644 --- a/lib/ui/geometry.dart +++ b/lib/ui/geometry.dart @@ -619,53 +619,66 @@ class Size extends OffsetBase { /// Rect myRect = const Offset(1.0, 2.0) & const Size(3.0, 4.0); /// ``` class Rect { + Rect._(); + /// Construct a rectangle from its left, top, right, and bottom edges. @pragma('vm:entry-point') - const Rect.fromLTRB(this.left, this.top, this.right, this.bottom) - : assert(left != null), - assert(top != null), - assert(right != null), - assert(bottom != null); + Rect.fromLTRB(double left, double top, double right, double bottom) { + _value + ..[0] = left + ..[1] = top + ..[2] = right + ..[3] = bottom; + } /// Construct a rectangle from its left and top edges, its width, and its /// height. /// /// To construct a [Rect] from an [Offset] and a [Size], you can use the /// rectangle constructor operator `&`. See [Offset.&]. - const Rect.fromLTWH(double left, double top, double width, double height) : this.fromLTRB(left, top, left + width, top + height); + Rect.fromLTWH(double left, double top, double width, double height) { + _value + ..[0] = left + ..[1] = top + ..[2] = left + width + ..[3] = top + height; + } /// Construct a rectangle that bounds the given circle. /// /// The `center` argument is assumed to be an offset from the origin. - Rect.fromCircle({ Offset center, double radius }) : this.fromLTRB( - center.dx - radius, - center.dy - radius, - center.dx + radius, - center.dy + radius, - ); + Rect.fromCircle({ Offset center, double radius }) { + _value + ..[0] = center.dx - radius + ..[1] = center.dy - radius + ..[2] = center.dx + radius + ..[3] = center.dy + radius; + } /// Construct the smallest rectangle that encloses the given offsets, treating /// them as vectors from the origin. - Rect.fromPoints(Offset a, Offset b) : this.fromLTRB( - math.min(a.dx, b.dx), - math.min(a.dy, b.dy), - math.max(a.dx, b.dx), - math.max(a.dy, b.dy), - ); + Rect.fromPoints(Offset a, Offset b) { + _value + ..[0] = math.min(a.dx, b.dx) + ..[1] = math.min(a.dy, b.dy) + ..[2] = math.max(a.dx, b.dx) + ..[3] = math.max(a.dy, b.dy); + } - Float32List get _value32 => Float32List.fromList([left, top, right, bottom]); + static const int _kDataSize = 4; + final Float32List _value = new Float32List(_kDataSize); /// The offset of the left edge of this rectangle from the x axis. - final double left; + double get left => _value[0]; /// The offset of the top edge of this rectangle from the y axis. - final double top; + double get top => _value[1]; /// The offset of the right edge of this rectangle from the x axis. - final double right; + double get right => _value[2]; /// The offset of the bottom edge of this rectangle from the y axis. - final double bottom; + double get bottom => _value[3]; /// The distance between the left and right edges of this rectangle. double get width => right - left; @@ -677,11 +690,8 @@ class Rect { /// this rectangle. Size get size => new Size(width, height); - /// Whether any of the dimensions are `NaN`. - bool get hasNaN => left.isNaN || top.isNaN || right.isNaN || bottom.isNaN; - /// A rectangle with left, top, right, and bottom edges all at zero. - static const Rect zero = Rect.fromLTRB(0.0, 0.0, 0.0, 0.0); + static final Rect zero = new Rect._(); static const double _giantScalar = 1.0E+9; // matches kGiantRect from layer.h @@ -689,7 +699,7 @@ class Rect { /// /// This covers the space from -1e9,-1e9 to 1e9,1e9. /// This is the space over which graphics operations are valid. - static const Rect largest = Rect.fromLTRB(-_giantScalar, -_giantScalar, _giantScalar, _giantScalar); + static final Rect largest = new Rect.fromLTRB(-_giantScalar, -_giantScalar, _giantScalar, _giantScalar); /// Whether any of the coordinates of this rectangle are equal to positive infinity. // included for consistency with Offset and Size @@ -869,17 +879,18 @@ class Rect { if (runtimeType != other.runtimeType) return false; final Rect typedOther = other; - return left == typedOther.left && - top == typedOther.top && - right == typedOther.right && - bottom == typedOther.bottom; + for (int i = 0; i < _kDataSize; i += 1) { + if (_value[i] != typedOther._value[i]) + return false; + } + return true; } @override - int get hashCode => hashValues(left, top, right, bottom); + int get hashCode => hashList(_value); @override - String toString() => 'Rect.fromLTRB(${left.toStringAsFixed(1)} ${top.toStringAsFixed(1)}, ${right.toStringAsFixed(1)}, ${bottom.toStringAsFixed(1)})'; + String toString() => 'Rect.fromLTRB(${left.toStringAsFixed(1)}, ${top.toStringAsFixed(1)}, ${right.toStringAsFixed(1)}, ${bottom.toStringAsFixed(1)})'; } /// A radius for either circular or elliptical shapes. @@ -1007,78 +1018,81 @@ class Radius { /// An immutable rounded rectangle with the custom radii for all four corners. class RRect { + RRect._(); + /// Construct a rounded rectangle from its left, top, right, and bottom edges, /// and the same radii along its horizontal axis and its vertical axis. - const RRect.fromLTRBXY(double left, double top, double right, double bottom, - double radiusX, double radiusY) : this._raw( - top: top, - left: left, - right: right, - bottom: bottom, - tlRadiusX: radiusX, - tlRadiusY: radiusY, - trRadiusX: radiusX, - trRadiusY: radiusY, - blRadiusX: radiusX, - blRadiusY: radiusY, - brRadiusX: radiusX, - brRadiusY: radiusY, - ); + RRect.fromLTRBXY(double left, double top, double right, double bottom, + double radiusX, double radiusY) { + _value + ..[0] = left + ..[1] = top + ..[2] = right + ..[3] = bottom + ..[4] = radiusX + ..[5] = radiusY + ..[6] = radiusX + ..[7] = radiusY + ..[8] = radiusX + ..[9] = radiusY + ..[10] = radiusX + ..[11] = radiusY; + } /// Construct a rounded rectangle from its left, top, right, and bottom edges, /// and the same radius in each corner. RRect.fromLTRBR(double left, double top, double right, double bottom, - Radius radius) - : this._raw( - top: top, - left: left, - right: right, - bottom: bottom, - tlRadiusX: radius.x, - tlRadiusY: radius.y, - trRadiusX: radius.x, - trRadiusY: radius.y, - blRadiusX: radius.x, - blRadiusY: radius.y, - brRadiusX: radius.x, - brRadiusY: radius.y, - ); + Radius radius) { + _value + ..[0] = left + ..[1] = top + ..[2] = right + ..[3] = bottom + ..[4] = radius.x + ..[5] = radius.y + ..[6] = radius.x + ..[7] = radius.y + ..[8] = radius.x + ..[9] = radius.y + ..[10] = radius.x + ..[11] = radius.y; + } /// Construct a rounded rectangle from its bounding box and the same radii /// along its horizontal axis and its vertical axis. - RRect.fromRectXY(Rect rect, double radiusX, double radiusY) - : this._raw( - top: rect.top, - left: rect.left, - right: rect.right, - bottom: rect.bottom, - tlRadiusX: radiusX, - tlRadiusY: radiusY, - trRadiusX: radiusX, - trRadiusY: radiusY, - blRadiusX: radiusX, - blRadiusY: radiusY, - brRadiusX: radiusX, - brRadiusY: radiusY, - ); + RRect.fromRectXY(Rect rect, double radiusX, double radiusY) { + _value + ..[0] = rect.left + ..[1] = rect.top + ..[2] = rect.right + ..[3] = rect.bottom + ..[4] = radiusX + ..[5] = radiusY + ..[6] = radiusX + ..[7] = radiusY + ..[8] = radiusX + ..[9] = radiusY + ..[10] = radiusX + ..[11] = radiusY; + } /// Construct a rounded rectangle from its bounding box and a radius that is /// the same in each corner. - RRect.fromRectAndRadius(Rect rect, Radius radius) - : this._raw( - top: rect.top, - left: rect.left, - right: rect.right, - bottom: rect.bottom, - tlRadiusX: radius.x, - tlRadiusY: radius.y, - trRadiusX: radius.x, - trRadiusY: radius.y, - blRadiusX: radius.x, - blRadiusY: radius.y, - brRadiusX: radius.x, - brRadiusY: radius.y, - ); + RRect.fromRectAndRadius(Rect rect, Radius radius) { + _value + ..[0] = rect.left + ..[1] = rect.top + ..[2] = rect.right + ..[3] = rect.bottom + ..[4] = radius.x + ..[5] = radius.y + ..[6] = radius.x + ..[7] = radius.y + ..[8] = radius.x + ..[9] = radius.y + ..[10] = radius.x + ..[11] = radius.y; + } /// Construct a rounded rectangle from its left, top, right, and bottom edges, /// and topLeft, topRight, bottomRight, and bottomLeft radii. @@ -1093,20 +1107,21 @@ class RRect { Radius topRight: Radius.zero, Radius bottomRight: Radius.zero, Radius bottomLeft: Radius.zero, - }) : this._raw( - top: top, - left: left, - right: right, - bottom: bottom, - tlRadiusX: topLeft.x, - tlRadiusY: topLeft.y, - trRadiusX: topRight.x, - trRadiusY: topRight.y, - blRadiusX: bottomLeft.x, - blRadiusY: bottomLeft.y, - brRadiusX: bottomRight.x, - brRadiusY: bottomRight.y, - ); + }) { + _value + ..[0] = left + ..[1] = top + ..[2] = right + ..[3] = bottom + ..[4] = topLeft.x + ..[5] = topLeft.y + ..[6] = topRight.x + ..[7] = topRight.y + ..[8] = bottomRight.x + ..[9] = bottomRight.y + ..[10] = bottomLeft.x + ..[11] = bottomLeft.y; + } /// Construct a rounded rectangle from its bounding box and and topLeft, /// topRight, bottomRight, and bottomLeft radii. @@ -1120,147 +1135,132 @@ class RRect { Radius bottomRight: Radius.zero, Radius bottomLeft: Radius.zero } - ) : this._raw( - top: rect.top, - left: rect.left, - right: rect.right, - bottom: rect.bottom, - tlRadiusX: topLeft.x, - tlRadiusY: topLeft.y, - trRadiusX: topRight.x, - trRadiusY: topRight.y, - blRadiusX: bottomLeft.x, - blRadiusY: bottomLeft.y, - brRadiusX: bottomRight.x, - brRadiusY: bottomRight.y, - ); - - const RRect._raw({ - this.left = 0.0, - this.top = 0.0, - this.right = 0.0, - this.bottom = 0.0, - this.tlRadiusX = 0.0, - this.tlRadiusY = 0.0, - this.trRadiusX = 0.0, - this.trRadiusY = 0.0, - this.brRadiusX = 0.0, - this.brRadiusY = 0.0, - this.blRadiusX = 0.0, - this.blRadiusY = 0.0, - }) : assert(left != null), - assert(top != null), - assert(right != null), - assert(bottom != null), - assert(tlRadiusX != null), - assert(tlRadiusY != null), - assert(trRadiusX != null), - assert(trRadiusY != null), - assert(brRadiusX != null), - assert(brRadiusY != null), - assert(blRadiusX != null), - assert(blRadiusY != null); - - Float32List get _value32 => Float32List.fromList([ - left, - top, - right, - bottom, - tlRadiusX, - tlRadiusY, - trRadiusX, - trRadiusY, - brRadiusX, - brRadiusY, - blRadiusX, - blRadiusY, - ]); + ) { + _value + ..[0] = rect.left + ..[1] = rect.top + ..[2] = rect.right + ..[3] = rect.bottom + ..[4] = topLeft.x + ..[5] = topLeft.y + ..[6] = topRight.x + ..[7] = topRight.y + ..[8] = bottomRight.x + ..[9] = bottomRight.y + ..[10] = bottomLeft.x + ..[11] = bottomLeft.y; + } + + RRect._fromList(List list) { + for (int i = 0; i < _kDataSize; i += 1) + _value[i] = list[i]; + } + + static const int _kDataSize = 12; + final Float32List _value = new Float32List(_kDataSize); + RRect _scaled; // same RRect with scaled radii per side /// The offset of the left edge of this rectangle from the x axis. - final double left; + double get left => _value[0]; /// The offset of the top edge of this rectangle from the y axis. - final double top; + double get top => _value[1]; /// The offset of the right edge of this rectangle from the x axis. - final double right; + double get right => _value[2]; /// The offset of the bottom edge of this rectangle from the y axis. - final double bottom; + double get bottom => _value[3]; /// The top-left horizontal radius. - final double tlRadiusX; + double get tlRadiusX => _value[4]; /// The top-left vertical radius. - final double tlRadiusY; + double get tlRadiusY => _value[5]; /// The top-left [Radius]. - Radius get tlRadius => new Radius.elliptical(tlRadiusX, tlRadiusY); + Radius get tlRadius => new Radius.elliptical(_value[4], _value[5]); /// The top-right horizontal radius. - final double trRadiusX; + double get trRadiusX => _value[6]; /// The top-right vertical radius. - final double trRadiusY; + double get trRadiusY => _value[7]; /// The top-right [Radius]. - Radius get trRadius => new Radius.elliptical(trRadiusX, trRadiusY); + Radius get trRadius => new Radius.elliptical(_value[6], _value[7]); /// The bottom-right horizontal radius. - final double brRadiusX; + double get brRadiusX => _value[8]; /// The bottom-right vertical radius. - final double brRadiusY; + double get brRadiusY => _value[9]; /// The bottom-right [Radius]. - Radius get brRadius => new Radius.elliptical(brRadiusX, brRadiusY); + Radius get brRadius => new Radius.elliptical(_value[8], _value[9]); /// The bottom-left horizontal radius. - final double blRadiusX; + double get blRadiusX => _value[10]; /// The bottom-left vertical radius. - final double blRadiusY; + double get blRadiusY => _value[11]; /// The bottom-left [Radius]. - Radius get blRadius => new Radius.elliptical(blRadiusX, blRadiusY); + Radius get blRadius => new Radius.elliptical(_value[10], _value[11]); /// A rounded rectangle with all the values set to zero. - static const RRect zero = RRect._raw(); + static final RRect zero = new RRect._(); /// Returns a new [RRect] translated by the given offset. RRect shift(Offset offset) { - return new RRect._raw( - left: left + offset.dx, - top: top + offset.dy, - right: right + offset.dx, - bottom: bottom + offset.dy, - tlRadiusX: tlRadiusX, - tlRadiusY: tlRadiusY, - trRadiusX: trRadiusX, - trRadiusY: trRadiusY, - blRadiusX: blRadiusX, - blRadiusY: blRadiusY, - brRadiusX: brRadiusX, - brRadiusY: brRadiusY, + return new RRect.fromLTRBAndCorners( + _value[0] + offset.dx, + _value[1] + offset.dy, + _value[2] + offset.dx, + _value[3] + offset.dy, + topLeft: new Radius.elliptical( + _value[4], + _value[5] + ), + topRight: new Radius.elliptical( + _value[6], + _value[7] + ), + bottomRight: new Radius.elliptical( + _value[8], + _value[9] + ), + bottomLeft: new Radius.elliptical( + _value[10], + _value[11] + ) ); } /// Returns a new [RRect] with edges and radii moved outwards by the given /// delta. RRect inflate(double delta) { - return new RRect._raw( - left: left - delta, - top: top - delta, - right: right + delta, - bottom: bottom + delta, - tlRadiusX: tlRadiusX + delta, - tlRadiusY: tlRadiusY + delta, - trRadiusX: trRadiusX + delta, - trRadiusY: trRadiusY + delta, - blRadiusX: blRadiusX + delta, - blRadiusY: blRadiusY + delta, - brRadiusX: brRadiusX + delta, - brRadiusY: brRadiusY + delta, + return new RRect.fromLTRBAndCorners( + _value[0] - delta, + _value[1] - delta, + _value[2] + delta, + _value[3] + delta, + topLeft: new Radius.elliptical( + _value[4] + delta, + _value[5] + delta + ), + topRight: new Radius.elliptical( + _value[6] + delta, + _value[7] + delta + ), + bottomRight: new Radius.elliptical( + _value[8] + delta, + _value[9] + delta + ), + bottomLeft: new Radius.elliptical( + _value[10] + delta, + _value[11] + delta + ) ); } @@ -1389,10 +1389,6 @@ class RRect { /// rounded rectangle. double get longestSide => math.max(width.abs(), height.abs()); - /// Whether any of the dimensions are `NaN`. - bool get hasNaN => left.isNaN || top.isNaN || right.isNaN || bottom.isNaN || - trRadiusX.isNaN || trRadiusY.isNaN || tlRadiusX.isNaN || tlRadiusY.isNaN || - brRadiusX.isNaN || brRadiusY.isNaN || blRadiusX.isNaN || blRadiusY.isNaN; /// The offset to the point halfway between the left and right and the top and /// bottom edges of this rectangle. @@ -1412,39 +1408,23 @@ class RRect { // // Inspired from: // https://github.com/google/skia/blob/master/src/core/SkRRect.cpp#L164 - RRect _scaleRadii() { - double scale = 1.0; - scale = _getMin(scale, blRadiusY, tlRadiusY, height); - scale = _getMin(scale, tlRadiusX, trRadiusX, width); - scale = _getMin(scale, trRadiusY, brRadiusY, height); - scale = _getMin(scale, brRadiusX, blRadiusX, width); - - double scaledLeft = left; - double scaledTop = top; - double scaledRight = right; - double scaledBottom = bottom; - - if (scale < 1.0) { - scaledTop *= scale; - scaledLeft *= scale; - scaledRight *= scale; - scaledBottom *= scale; + void _scaleRadii() { + if (_scaled == null) { + double scale = 1.0; + final List scaled = new List.from(_value); + + scale = _getMin(scale, scaled[11], scaled[5], height); + scale = _getMin(scale, scaled[4], scaled[6], width); + scale = _getMin(scale, scaled[7], scaled[9], height); + scale = _getMin(scale, scaled[8], scaled[10], width); + + if (scale < 1.0) { + for (int i = 4; i < _kDataSize; i += 1) + scaled[i] *= scale; + } + + _scaled = new RRect._fromList(scaled); } - - return new RRect._raw( - top: scaledTop, - left: scaledLeft, - right: scaledRight, - bottom: scaledBottom, - tlRadiusX: tlRadiusX, - tlRadiusY: tlRadiusY, - trRadiusX: trRadiusX, - trRadiusY: trRadiusY, - blRadiusX: blRadiusX, - blRadiusY: blRadiusY, - brRadiusX: brRadiusX, - brRadiusY: brRadiusY, - ); } /// Whether the point specified by the given offset (which is assumed to be @@ -1458,7 +1438,7 @@ class RRect { if (point.dx < left || point.dx >= right || point.dy < top || point.dy >= bottom) return false; // outside bounding box - final RRect scaled = _scaleRadii(); + _scaleRadii(); double x; double y; @@ -1466,30 +1446,30 @@ class RRect { double radiusY; // check whether point is in one of the rounded corner areas // x, y -> translate to ellipse center - if (point.dx < left + scaled.tlRadiusX && - point.dy < top + scaled.tlRadiusY) { - x = point.dx - left - scaled.tlRadiusX; - y = point.dy - top - scaled.tlRadiusY; - radiusX = scaled.tlRadiusX; - radiusY = scaled.tlRadiusY; - } else if (point.dx > right - scaled.trRadiusX && - point.dy < top + scaled.trRadiusY) { - x = point.dx - right + scaled.trRadiusX; - y = point.dy - top - scaled.trRadiusY; - radiusX = scaled.trRadiusX; - radiusY = scaled.trRadiusY; - } else if (point.dx > right - scaled.brRadiusX && - point.dy > bottom - scaled.brRadiusY) { - x = point.dx - right + scaled.brRadiusX; - y = point.dy - bottom + scaled.brRadiusY; - radiusX = scaled.brRadiusX; - radiusY = scaled.brRadiusY; - } else if (point.dx < left + scaled.blRadiusX && - point.dy > bottom - scaled.blRadiusY) { - x = point.dx - left - scaled.blRadiusX; - y = point.dy - bottom + scaled.blRadiusY; - radiusX = scaled.blRadiusX; - radiusY = scaled.blRadiusY; + if (point.dx < left + _scaled.tlRadiusX && + point.dy < top + _scaled.tlRadiusY) { + x = point.dx - left - _scaled.tlRadiusX; + y = point.dy - top - _scaled.tlRadiusY; + radiusX = _scaled.tlRadiusX; + radiusY = _scaled.tlRadiusY; + } else if (point.dx > right - _scaled.trRadiusX && + point.dy < top + _scaled.trRadiusY) { + x = point.dx - right + _scaled.trRadiusX; + y = point.dy - top - _scaled.trRadiusY; + radiusX = _scaled.trRadiusX; + radiusY = _scaled.trRadiusY; + } else if (point.dx > right - _scaled.brRadiusX && + point.dy > bottom - _scaled.brRadiusY) { + x = point.dx - right + _scaled.brRadiusX; + y = point.dy - bottom + _scaled.brRadiusY; + radiusX = _scaled.brRadiusX; + radiusY = _scaled.brRadiusY; + } else if (point.dx < left + _scaled.blRadiusX && + point.dy > bottom - _scaled.blRadiusY) { + x = point.dx - left - _scaled.blRadiusX; + y = point.dy - bottom + _scaled.blRadiusY; + radiusX = _scaled.blRadiusX; + radiusY = _scaled.blRadiusY; } else { return true; // inside and not within the rounded corner area } @@ -1522,52 +1502,52 @@ class RRect { if (a == null && b == null) return null; if (a == null) { - return new RRect._raw( - left: b.left * t, - top: b.top * t, - right: b.right * t, - bottom: b.bottom * t, - tlRadiusX: b.tlRadiusX * t, - tlRadiusY: b.tlRadiusY * t, - trRadiusX: b.trRadiusX * t, - trRadiusY: b.trRadiusY * t, - brRadiusX: b.brRadiusX * t, - brRadiusY: b.brRadiusY * t, - blRadiusX: b.blRadiusX * t, - blRadiusY: b.blRadiusY * t, - ); + return new RRect._fromList([ + b.left * t, + b.top * t, + b.right * t, + b.bottom * t, + b.tlRadiusX * t, + b.tlRadiusY * t, + b.trRadiusX * t, + b.trRadiusY * t, + b.brRadiusX * t, + b.brRadiusY * t, + b.blRadiusX * t, + b.blRadiusY * t, + ]); } if (b == null) { final double k = 1.0 - t; - return new RRect._raw( - left: a.left * k, - top: a.top * k, - right: a.right * k, - bottom: a.bottom * k, - tlRadiusX: a.tlRadiusX * k, - tlRadiusY: a.tlRadiusY * k, - trRadiusX: a.trRadiusX * k, - trRadiusY: a.trRadiusY * k, - brRadiusX: a.brRadiusX * k, - brRadiusY: a.brRadiusY * k, - blRadiusX: a.blRadiusX * k, - blRadiusY: a.blRadiusY * k, - ); + return new RRect._fromList([ + a.left * k, + a.top * k, + a.right * k, + a.bottom * k, + a.tlRadiusX * k, + a.tlRadiusY * k, + a.trRadiusX * k, + a.trRadiusY * k, + a.brRadiusX * k, + a.brRadiusY * k, + a.blRadiusX * k, + a.blRadiusY * k, + ]); } - return new RRect._raw( - left: lerpDouble(a.left, b.left, t), - top: lerpDouble(a.top, b.top, t), - right: lerpDouble(a.right, b.right, t), - bottom: lerpDouble(a.bottom, b.bottom, t), - tlRadiusX: lerpDouble(a.tlRadiusX, b.tlRadiusX, t), - tlRadiusY: lerpDouble(a.tlRadiusY, b.tlRadiusY, t), - trRadiusX: lerpDouble(a.trRadiusX, b.trRadiusX, t), - trRadiusY: lerpDouble(a.trRadiusY, b.trRadiusY, t), - brRadiusX: lerpDouble(a.brRadiusX, b.brRadiusX, t), - brRadiusY: lerpDouble(a.brRadiusY, b.brRadiusY, t), - blRadiusX: lerpDouble(a.blRadiusX, b.blRadiusX, t), - blRadiusY: lerpDouble(a.blRadiusY, b.blRadiusY, t), - ); + return new RRect._fromList([ + lerpDouble(a.left, b.left, t), + lerpDouble(a.top, b.top, t), + lerpDouble(a.right, b.right, t), + lerpDouble(a.bottom, b.bottom, t), + lerpDouble(a.tlRadiusX, b.tlRadiusX, t), + lerpDouble(a.tlRadiusY, b.tlRadiusY, t), + lerpDouble(a.trRadiusX, b.trRadiusX, t), + lerpDouble(a.trRadiusY, b.trRadiusY, t), + lerpDouble(a.brRadiusX, b.brRadiusX, t), + lerpDouble(a.brRadiusY, b.brRadiusY, t), + lerpDouble(a.blRadiusX, b.blRadiusX, t), + lerpDouble(a.blRadiusY, b.blRadiusY, t), + ]); } @override @@ -1577,24 +1557,15 @@ class RRect { if (runtimeType != other.runtimeType) return false; final RRect typedOther = other; - return left == typedOther.left && - top == typedOther.top && - right == typedOther.right && - bottom == typedOther.bottom && - tlRadiusX == typedOther.tlRadiusX && - tlRadiusY == typedOther.tlRadiusY && - trRadiusX == typedOther.trRadiusX && - trRadiusY == typedOther.trRadiusY && - blRadiusX == typedOther.blRadiusX && - blRadiusY == typedOther.blRadiusY && - brRadiusX == typedOther.brRadiusX && - brRadiusY == typedOther.brRadiusY; + for (int i = 0; i < _kDataSize; i += 1) { + if (_value[i] != typedOther._value[i]) + return false; + } + return true; } @override - int get hashCode => hashValues(left, top, right, bottom, - tlRadiusX, tlRadiusY, trRadiusX, trRadiusY, - blRadiusX, blRadiusY, brRadiusX, brRadiusY); + int get hashCode => hashList(_value); @override String toString() { diff --git a/lib/ui/painting.dart b/lib/ui/painting.dart index 89cf75099c8a6..6703dfd01083e 100644 --- a/lib/ui/painting.dart +++ b/lib/ui/painting.dart @@ -23,13 +23,13 @@ part of dart.ui; bool _rectIsValid(Rect rect) { assert(rect != null, 'Rect argument was null.'); - assert(!rect.hasNaN, 'Rect argument contained a NaN value.'); + assert(!rect._value.any((double value) => value.isNaN), 'Rect argument contained a NaN value.'); return true; } bool _rrectIsValid(RRect rrect) { assert(rrect != null, 'RRect argument was null.'); - assert(!rrect.hasNaN, 'RRect argument contained a NaN value.'); + assert(!rrect._value.any((double value) => value.isNaN), 'RRect argument contained a NaN value.'); return true; } @@ -2028,7 +2028,7 @@ class Path extends NativeFieldWrapperClass2 { /// argument. void addRRect(RRect rrect) { assert(_rrectIsValid(rrect)); - _addRRect(rrect._value32); + _addRRect(rrect._value); } void _addRRect(Float32List rrect) native 'Path_addRRect'; @@ -3259,7 +3259,7 @@ class Canvas extends NativeFieldWrapperClass2 { void clipRRect(RRect rrect, {bool doAntiAlias = true}) { assert(_rrectIsValid(rrect)); assert(doAntiAlias != null); - _clipRRect(rrect._value32, doAntiAlias); + _clipRRect(rrect._value, doAntiAlias); } void _clipRRect(Float32List rrect, bool doAntiAlias) native 'Canvas_clipRRect'; @@ -3336,7 +3336,7 @@ class Canvas extends NativeFieldWrapperClass2 { void drawRRect(RRect rrect, Paint paint) { assert(_rrectIsValid(rrect)); assert(paint != null); - _drawRRect(rrect._value32, paint._objects, paint._data); + _drawRRect(rrect._value, paint._objects, paint._data); } void _drawRRect(Float32List rrect, List paintObjects, @@ -3351,7 +3351,7 @@ class Canvas extends NativeFieldWrapperClass2 { assert(_rrectIsValid(outer)); assert(_rrectIsValid(inner)); assert(paint != null); - _drawDRRect(outer._value32, inner._value32, paint._objects, paint._data); + _drawDRRect(outer._value, inner._value, paint._objects, paint._data); } void _drawDRRect(Float32List outer, Float32List inner, @@ -3651,7 +3651,7 @@ class Canvas extends NativeFieldWrapperClass2 { } final Int32List colorBuffer = colors.isEmpty ? null : _encodeColorList(colors); - final Float32List cullRectBuffer = cullRect?._value32; + final Float32List cullRectBuffer = cullRect?._value; _drawAtlas( paint._objects, paint._data, atlas, rstTransformBuffer, rectBuffer, @@ -3698,7 +3698,7 @@ class Canvas extends NativeFieldWrapperClass2 { _drawAtlas( paint._objects, paint._data, atlas, rstTransforms, rects, - colors, blendMode.index, cullRect?._value32 + colors, blendMode.index, cullRect?._value ); } diff --git a/testing/dart/rect_test.dart b/testing/dart/rect_test.dart index b8b893351c7dd..b392932c662ea 100644 --- a/testing/dart/rect_test.dart +++ b/testing/dart/rect_test.dart @@ -8,7 +8,7 @@ import 'package:test/test.dart'; void main() { test('rect accessors', () { - const Rect r = Rect.fromLTRB(1.0, 3.0, 5.0, 7.0); + final Rect r = Rect.fromLTRB(1.0, 3.0, 5.0, 7.0); expect(r.left, equals(1.0)); expect(r.top, equals(3.0)); expect(r.right, equals(5.0)); @@ -16,7 +16,7 @@ void main() { }); test('rect created by width and height', () { - const Rect r = Rect.fromLTWH(1.0, 3.0, 5.0, 7.0); + final Rect r = Rect.fromLTWH(1.0, 3.0, 5.0, 7.0); expect(r.left, equals(1.0)); expect(r.top, equals(3.0)); expect(r.right, equals(6.0)); @@ -26,8 +26,8 @@ void main() { }); test('rect intersection', () { - const Rect r1 = Rect.fromLTRB(0.0, 0.0, 100.0, 100.0); - const Rect r2 = Rect.fromLTRB(50.0, 50.0, 200.0, 200.0); + final Rect r1 = Rect.fromLTRB(0.0, 0.0, 100.0, 100.0); + final Rect r2 = Rect.fromLTRB(50.0, 50.0, 200.0, 200.0); final Rect r3 = r1.intersect(r2); expect(r3.left, equals(50.0)); expect(r3.top, equals(50.0)); @@ -38,8 +38,8 @@ void main() { }); test('rect expandToInclude overlapping rects', () { - const Rect r1 = Rect.fromLTRB(0.0, 0.0, 100.0, 100.0); - const Rect r2 = Rect.fromLTRB(50.0, 50.0, 200.0, 200.0); + final Rect r1 = Rect.fromLTRB(0.0, 0.0, 100.0, 100.0); + final Rect r2 = Rect.fromLTRB(50.0, 50.0, 200.0, 200.0); final Rect r3 = r1.expandToInclude(r2); expect(r3.left, equals(0.0)); expect(r3.top, equals(0.0)); @@ -50,8 +50,8 @@ void main() { }); test('rect expandToInclude crossing rects', () { - const Rect r1 = Rect.fromLTRB(50.0, 0.0, 50.0, 200.0); - const Rect r2 = Rect.fromLTRB(0.0, 50.0, 200.0, 50.0); + final Rect r1 = Rect.fromLTRB(50.0, 0.0, 50.0, 200.0); + final Rect r2 = Rect.fromLTRB(0.0, 50.0, 200.0, 50.0); final Rect r3 = r1.expandToInclude(r2); expect(r3.left, equals(0.0)); expect(r3.top, equals(0.0)); @@ -70,7 +70,7 @@ void main() { }); test('rounded rect created from rect and radii', () { - const Rect baseRect = Rect.fromLTWH(1.0, 3.0, 5.0, 7.0); + final Rect baseRect = Rect.fromLTWH(1.0, 3.0, 5.0, 7.0); final RRect r = RRect.fromRectXY(baseRect, 1.0, 1.0); expect(r.left, equals(1.0)); expect(r.top, equals(3.0));