diff --git a/lib/web_ui/lib/src/engine/html/path/path_ref.dart b/lib/web_ui/lib/src/engine/html/path/path_ref.dart
index 1cbc082a836a4..7e66e42ee87db 100644
--- a/lib/web_ui/lib/src/engine/html/path/path_ref.dart
+++ b/lib/web_ui/lib/src/engine/html/path/path_ref.dart
@@ -263,15 +263,12 @@ class PathRef {
// The location delta of control point specifies corner radius.
if (vector1_0x != 0.0) {
// For CW : Top right or bottom left corners.
- assert(vector2_1x == 0.0 && vector1_0y == 0.0);
dx = vector1_0x.abs();
dy = vector2_1y.abs();
} else if (vector1_0y != 0.0) {
- assert(vector2_1x == 0.0 || vector2_1y == 0.0);
dx = vector2_1x.abs();
dy = vector1_0y.abs();
} else {
- assert(vector2_1y == 0.0);
dx = vector1_0x.abs();
dy = vector1_0y.abs();
}
@@ -288,9 +285,19 @@ class PathRef {
radii.add(ui.Radius.elliptical(dx, dy));
++cornerIndex;
} else {
- assert((verb == SPath.kLineVerb &&
- ((pts[2] - pts[0]) == 0 || (pts[3] - pts[1]) == 0)) ||
- verb == SPath.kCloseVerb);
+ if (assertionsEnabled) {
+ if (verb == SPath.kLineVerb) {
+ final bool isVerticalOrHorizontal =
+ SPath.nearlyEqual(pts[2], pts[0]) ||
+ SPath.nearlyEqual(pts[3], pts[1]);
+ assert(
+ isVerticalOrHorizontal,
+ 'An RRect path must only contain vertical and horizontal lines.'
+ );
+ } else {
+ assert(verb == SPath.kCloseVerb);
+ }
+ }
}
}
return ui.RRect.fromRectAndCorners(bounds,
diff --git a/lib/web_ui/test/html/path_ref_test.dart b/lib/web_ui/test/html/path_ref_test.dart
new file mode 100644
index 0000000000000..2eaff94dfeab7
--- /dev/null
+++ b/lib/web_ui/test/html/path_ref_test.dart
@@ -0,0 +1,78 @@
+// Copyright 2013 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 'package:test/bootstrap/browser.dart';
+import 'package:test/test.dart';
+import 'package:ui/src/engine.dart';
+import 'package:ui/ui.dart';
+
+// TODO(yjbanov): https://github.com/flutter/flutter/issues/76885
+const bool issue76885Exists = true;
+
+void main() {
+ internalBootstrapBrowserTest(() => testMain);
+}
+
+void testMain() {
+ test('PathRef.getRRect with radius', () {
+ final SurfacePath path = SurfacePath();
+ final RRect rrect = RRect.fromLTRBR(0, 0, 10, 10, const Radius.circular(2));
+ path.addRRect(rrect);
+ expect(path.toRoundedRect(), rrect);
+ });
+
+ test('PathRef.getRRect with radius larger than rect', () {
+ final SurfacePath path = SurfacePath();
+ final RRect rrect = RRect.fromLTRBR(0, 0, 10, 10, const Radius.circular(20));
+ path.addRRect(rrect);
+ expect(
+ path.toRoundedRect(),
+ // Path.addRRect will correct the radius to fit the dimensions, so when
+ // extracting the rrect out of the path we don't get the original.
+ RRect.fromLTRBR(0, 0, 10, 10, const Radius.circular(5)),
+ );
+ });
+
+ test('PathRef.getRRect with zero radius', () {
+ final SurfacePath path = SurfacePath();
+ final RRect rrect = RRect.fromLTRBR(0, 0, 10, 10, const Radius.circular(0));
+ path.addRRect(rrect);
+ expect(path.toRoundedRect(), isNull);
+ expect(path.toRect(), rrect.outerRect);
+ });
+
+ test('PathRef.getRRect elliptical', () {
+ final SurfacePath path = SurfacePath();
+ final RRect rrect = RRect.fromLTRBR(0, 0, 10, 10, const Radius.elliptical(2, 4));
+ path.addRRect(rrect);
+ expect(path.toRoundedRect(), rrect);
+ });
+
+ test('PathRef.getRRect elliptical zero x', () {
+ final SurfacePath path = SurfacePath();
+ final RRect rrect = RRect.fromLTRBR(0, 0, 10, 10, const Radius.elliptical(0, 3));
+ path.addRRect(rrect);
+ expect(path.toRoundedRect(), isNull);
+ expect(path.toRect(), rrect.outerRect);
+ });
+
+ test('PathRef.getRRect elliptical zero y', () {
+ final SurfacePath path = SurfacePath();
+ final RRect rrect = RRect.fromLTRBR(0, 0, 10, 10, const Radius.elliptical(3, 0));
+ path.addRRect(rrect);
+ expect(path.toRoundedRect(), isNull);
+ expect(path.toRect(), rrect.outerRect);
+ });
+
+ // This test demonstrates the issue with attempting to reconstruct an RRect
+ // with imprecision introduced by comparing double values. We should fix this
+ // by removing the need to reconstruct rrects:
+ // https://github.com/flutter/flutter/issues/76885
+ test('PathRef.getRRect with nearly zero corner', () {
+ final SurfacePath path = SurfacePath();
+ final RRect original = RRect.fromLTRBR(0, 0, 10, 10, const Radius.elliptical(0.00000001, 5));
+ path.addRRect(original);
+ expect(path.toRoundedRect(), original);
+ }, skip: issue76885Exists);
+}