Repository: flutter
Issue: `RoundedRectangleBorder` + `borderRadius.circular(double.infinity)` makes a squared shape
Labels: framework,c: proposal,P3,team-framework,triaged-framework

Related PR: https://github.com/flutter/flutter/pull/123077

Due to how Skia works, a rectangle with `borderRadius.circular(double.infinity)` becomes a square. Upon further inspection, we discovered the maximum supported value there is float32, which is 3.402823e+38. Out of worry to add random constants in the framework, @dnfield recommended against this approach (maximum: double.infinity -> maximum: 3.402823e+38).

When a `borderRadius` is circular (not elliptical), its maximum value is *always* `math.min(rect.width, rect.height) / 2`. When it is elliptical, well.. chaos.

Upon a lot of inspection, even with GPT-4 help, I haven't being able to get to something that works.

GPT-4 suggested:

Input:
> Consider the following in Flutter.
> 1. For w: 20, h:20, borderRadius.circular(20) is acceptable.
> 2. For w: 20, h:20, borderRadius.circular(40) is not acceptable, can be reduced to borderRadius.circular(20).
> 
> The same can't be said for BorderRadius.elliptical.
> For w: 400, h: 50, Radius.elliptical(100000000, 1000) still shows a value that can be seen visually.
> 
> Generalize a math formula that allows to find the "minimum necessary Radius for a given width, height, radiusX and radiusY".

Output:
> Let w and h be the width and height of a rectangle, respectively. Let r_x and r_y be the horizontal and vertical radii of an elliptical border, respectively. Our goal is to find the minimum necessary radius r_min_x and r_min_y for a given width, height, r_x, and r_y.
> 
> We know, by definition, that the elliptical border must satisfy the equation:
>
> (x/w)^2 + (y/h)^2 = 1
> 
> The top-right corner of the rectangle is at the point (w/2, h/2). After substituting these values into the equation, we get:
> 
> ((w/2)/w)^2 + ((h/2)/h)^2 = 1
> (1/2)^2 + (1/2)^2 = 1
> 1/4 + 1/4 = 1
> 1/2 = 1
> 
> Now, we will scale the radii to find the minimum necessary radii r_min_x and r_min_y that satisfy the equation:
> 
> (r_min_x/w)^2 + (r_min_y/h)^2 = 1
> 
> Since we have already established that 1/2 is the maximum value for both terms on the left-hand side of this equation, we can set r_min_x and r_min_y as follows:
> 
> r_min_x = w / (2 * sqrt(2))
> r_min_y = h / (2 * sqrt(2))
> 
> Consequently, if given r_x and r_y values are greater than these r_min_x and r_min_y values, we can use these new minimum radii to create a visually acceptable elliptical border. If r_x or r_y is smaller than these minimum radii, you should use the provided values. So, given any r_x and r_y:
> 
> r_final_x = min(r_x, w / (2 * sqrt(2)))
> r_final_y = min(r_y, h / (2 * sqrt(2)))
> 
> In summary, we can use the above formulas to find the minimum necessary radii r_final_x and r_final_y for a given width, height, r_x, and r_y.

This lead to this:
```dart
Radius clampedEllipseRadius(double w, double h) {
  const double r_x = 100000000;
  const double r_y = 1000;
  const sqrt2 = 1.4142135623730951;

  final r_final_x = math.min(r_x, w / (2 * sqrt2));
  final r_final_y = math.min(r_y, h / (2 * sqrt2));
  
  return Radius.elliptical(r_final_x, r_final_y);
}
```
Which also didn't seem to work.

The issues are many. Take this with a grain of salt, these were my observations but I might have been wrong:
- Elliptical corners seem to interact with each other. We can't limit topLeft individually without knowing what bottomLeft does.
- Ellipitcal seems to do some division, multiplication (or even sqrt2 as GPT-4 suggested) behind the scenes, which is complex.
- A value I found that makes Elliptical "indistinguishable" was BorderRadius.elliptical(100000000, 1000) for width of 400 and height of 50. It is a really big value. I'm not sure I can apply `math.min()` here. `BorderRadius.elliptical(450, 50)` can behave very similar to that super large value, but not exactly. I don't know why.
- As an example, it is possible to "overflow" the border: if we eventually reach a super-high value (say a 11000, 1000), it starts "going-back" (which is probably unwanted). The "max true real value" would be ~9000, 1000. How do we find this? I have no idea.

An image of the odd behaviors:
![image](https://user-images.githubusercontent.com/351125/230953909-17e94566-ab6b-40e0-966e-29fe8a6d8a43.png)

IMO we should be able to somehow find these limits (or just bound to max-width/height and ignore the odd artefacts), but I need  more research. I would like to see with my own eyes the Skia code that produces an elliptical shape. I couldn't find even going into `canvas.cc` or some deep files.

Ultimately, fixing for `BorderRadius.circular` solves the issue for 98% of users and doesn't require any heavy or complex calculation, it will always behave the same. Fixing for `BorderRadius.elliptical` requires a bit more knowledge than I have and maybe the help of someone from Skia/Impeller to say what's "possible", what shouldn't be allowed and what's a bug. Someone with this knowlodge should be able to fix the issue a lot faster than myself when I unsuccessfully tried.