Skip to content

Conversation

@bernaferrari
Copy link
Contributor

@bernaferrari bernaferrari commented May 14, 2022

Fix #103829

Flutter supports rectangles and circles, but doesn't support ovals (circles that are not squared). I adjusted two things:

  1. Add BoxShape.oval. There is a comment saying new shapes shouldn't go here. I believe oval could be an exception to that, since BoxShape.oval is basically BoxShape.circle without constraints. It is easier to implement oval than circle. In most places, I just call drawOval instead of calculating the smaller side and drawing a circle. If you disagree, I can remove it, no problem 😀.
  2. Add OvalBorder. Works like CircleBorder, but it is unconstrained. I haven't solved lerp from Oval to Circular or from Oval to others, only it to itself (which lerps do you think are useful?). Stadium lerps to Circular and RoundedRectangle lerps to Circular.

Demo:
image

import 'package:flutter/material.dart';

const Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(
        scaffoldBackgroundColor: darkBlue,
      ),
      debugShowCheckedModeBanner: false,
      home: const Scaffold(
        body: Center(
          child: MyWidget(),
        ),
      ),
    );
  }
}

List<Widget> spaceRow(double gap, Iterable<Widget> children) => children
    .expand((item) sync* {
      yield SizedBox(width: gap);
      yield item;
    })
    .skip(1)
    .toList();

List<Widget> spaceColumn(double gap, Iterable<Widget> children) => children
    .expand((item) sync* {
      yield SizedBox(height: gap);
      yield item;
    })
    .skip(1)
    .toList();

class MyWidget extends StatelessWidget {
  const MyWidget({super.key});

  @override
  Widget build(BuildContext context) {
    const debugStrokeAlign = StrokeAlign.inside;
    return ListView(
      children: [
        const Text("box decoration"),
        Row(
          children: [
            Container(
              width: 60,
              height: 120,
              decoration: const BoxDecoration(
                shape: BoxShape.oval,
                color: Colors.blue,
              ),
            ),
            Container(
              width: 60,
              height: 120,
              decoration: const BoxDecoration(
                shape: BoxShape.oval,
                color: Colors.blue,
                image: DecorationImage(
                  image: NetworkImage(
                      "https://unsplash.it/200/300?image=1&blur=2"),
                ),
              ),
            ),
            Container(
              width: 60,
              height: 120,
              decoration: const BoxDecoration(
                shape: BoxShape.circle,
                color: Colors.blue,
              ),
            ),
            Container(
              width: 60,
              height: 120,
              decoration: const BoxDecoration(
                shape: BoxShape.circle,
                color: Colors.blue,
                image: DecorationImage(
                  image: NetworkImage(
                      "https://unsplash.it/200/300?image=1&blur=2"),
                ),
              ),
            ),
          ],
        ),
        // const SizedBox(height: 16),
        const Text("eccentricity growing"),
        Row(
          children: [
            for (double eccentricity in [0, 0.25, 0.5, 0.75, 1])
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Container(
                  width: 100,
                  height: 160,
                  clipBehavior: Clip.antiAlias,
                  decoration: ShapeDecoration(
                    color: Colors.red,
                    shape: CircleBorder(
                      eccentricity: eccentricity,
                      side: BorderSide(
                        color: Colors.white.withOpacity(0.5),
                        width: 8,
                        strokeAlign: StrokeAlign.inside,
                      ),
                    ),
                  ),
                ),
              ),
          ],
        ),
        Row(
          children: [
            for (double eccentricity in [0, 0.25, 0.5, 0.75, 1])
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Container(
                  width: 100,
                  height: 40,
                  clipBehavior: Clip.antiAlias,
                  decoration: ShapeDecoration(
                    color: Colors.red,
                    shape: CircleBorder(
                      eccentricity: eccentricity,
                      side: BorderSide(
                        color: Colors.white.withOpacity(0.5),
                        width: 8,
                        strokeAlign: StrokeAlign.inside,
                      ),
                    ),
                  ),
                ),
              ),
          ],
        ),
        const SizedBox(height: 32),
        const Text("Lerp CircleBorder not oval -> CircleBorder oval"),
        const SizedBox(height: 16),
        Row(
          children: spaceRow(32, [
            for (double eccentricity in [0, 0.25, 0.5, 0.75, 1])
              Container(
                width: 100,
                height: 40,
                decoration: ShapeDecoration(
                  color: Colors.blue,
                  shape: CircleBorder(
                    eccentricity: 0,
                    side: BorderSide(
                      color: Colors.red.withOpacity(0.5),
                      width: 5,
                      strokeAlign: debugStrokeAlign,
                    ),
                  ).lerpTo(
                    CircleBorder(
                      eccentricity: eccentricity,
                      side: BorderSide(
                        color: Colors.white.withOpacity(0.5),
                        width: 5,
                        strokeAlign: debugStrokeAlign,
                      ),
                    ),
                    eccentricity,
                  )!,
                ),
              ),
          ]),
        ),
        const SizedBox(height: 32),
        const Text("RoundedRectangle -> Circle"),
        const SizedBox(height: 16),
        const RoundedRectangleToCircle(width: 60, height: 120),
        const SizedBox(height: 16),
        const RoundedRectangleToCircle(width: 120, height: 60),
        const SizedBox(height: 64),
        const Text("Stadium -> Circle"),
        const SizedBox(height: 16),
        const StadiumToCircle(width: 60, height: 120),
        const SizedBox(height: 16),
        const StadiumToCircle(width: 120, height: 60),
      ],
    );
  }
}

class StadiumToCircle extends StatelessWidget {
  const StadiumToCircle({
    required this.width,
    required this.height,
    Key? key,
  }) : super(key: key);

  final double width;
  final double height;

  @override
  Widget build(BuildContext context) {
    const debugStrokeAlign = StrokeAlign.inside;

    final stadiumLerp = StadiumBorder(
      side: BorderSide(
        color: Colors.red.withOpacity(0.5),
        width: 5,
        strokeAlign: StrokeAlign.inside,
      ),
    );

    ShapeBorder stadiumToCircleLerp(double t) => stadiumLerp.lerpTo(
        CircleBorder(
          eccentricity: 1,
          side: BorderSide(
            color: Colors.blue.withOpacity(0.5),
            width: 5,
            strokeAlign: StrokeAlign.inside,
          ),
        ),
        t)!;

    ShapeBorder stadiumToPartialCircleLerp(double t) => stadiumLerp.lerpTo(
        CircleBorder(
          eccentricity: 0.5,
          side: BorderSide(
            color: Colors.blue.withOpacity(0.5),
            width: 5,
            strokeAlign: debugStrokeAlign,
          ),
        ),
        t)!;

    ShapeBorder stadiumToCircleLerpFullyRound(double t) => StadiumBorder(
          side: BorderSide(
            color: Colors.blue.withOpacity(0.5),
            width: 5,
            strokeAlign: debugStrokeAlign,
          ),
        ).lerpTo(
            CircleBorder(
              eccentricity: 0.0,
              side: BorderSide(
                color: Colors.purple.withOpacity(0.5),
                width: 5,
                strokeAlign: debugStrokeAlign,
              ),
            ),
            t)!;

    return Column(
      children: [
        Row(
          children: spaceRow(32, [
            for (double t in [0, 0.25, 0.5, 0.75, 1])
              Container(
                width: width,
                height: height,
                decoration: ShapeDecoration(
                  color: Colors.red.withOpacity(0.25),
                  shape: stadiumToCircleLerp(t),
                ),
              ),
            Container(
              width: width,
              height: height,
              decoration: ShapeDecoration(
                color: Colors.white.withOpacity(0.25),
                shape: CircleBorder(
                  eccentricity: 1,
                  side: BorderSide(
                    color: Colors.white.withOpacity(0.5),
                    width: 5,
                    strokeAlign: debugStrokeAlign,
                  ),
                ),
              ),
              child: const Center(child: Text('1.0')),
            ),
          ]),
        ),
        Row(
          children: spaceRow(32, [
            for (double t in [0, 0.25, 0.5, 0.75, 1])
              Container(
                width: width,
                height: height,
                decoration: ShapeDecoration(
                  color: Colors.red.withOpacity(0.25),
                  shape: stadiumToPartialCircleLerp(t),
                ),
              ),
            Container(
              width: width,
              height: height,
              decoration: ShapeDecoration(
                color: Colors.white.withOpacity(0.25),
                shape: CircleBorder(
                  eccentricity: 0.5,
                  side: BorderSide(
                    color: Colors.white.withOpacity(0.5),
                    width: 5,
                    strokeAlign: debugStrokeAlign,
                  ),
                ),
              ),
              child: const Center(child: Text('0.5')),
            ),
          ]),
        ),
        Row(
          children: spaceRow(32, [
            for (double t in [0, 0.25, 0.5, 0.75, 1])
              Container(
                width: width,
                height: height,
                decoration: ShapeDecoration(
                  color: Colors.brown.withOpacity(0.25),
                  shape: stadiumToCircleLerpFullyRound(t),
                ),
              ),
            Container(
              width: width,
              height: height,
              decoration: ShapeDecoration(
                color: Colors.white.withOpacity(0.25),
                shape: CircleBorder(
                  eccentricity: 0.0,
                  side: BorderSide(
                    color: Colors.white.withOpacity(0.5),
                    width: 5,
                    strokeAlign: debugStrokeAlign,
                  ),
                ),
              ),
              child: const Center(child: Text('0.0')),
            ),
          ]),
        ),
      ],
    );
  }
}

class RoundedRectangleToCircle extends StatelessWidget {
  const RoundedRectangleToCircle({
    required this.width,
    required this.height,
    Key? key,
  }) : super(key: key);

  final double width;
  final double height;

  @override
  Widget build(BuildContext context) {
    const debugStrokeAlign = StrokeAlign.inside;

    final roundedLerp = RoundedRectangleBorder(
      side: BorderSide(
        color: Colors.red.withOpacity(0.5),
        width: 5,
        strokeAlign: StrokeAlign.inside,
      ),
    );

    ShapeBorder roundedToOvalLerp(double t) => roundedLerp.lerpTo(
        OvalBorder(
          side: BorderSide(
            color: Colors.blue.withOpacity(0.5),
            width: 5,
            strokeAlign: StrokeAlign.inside,
          ),
        ),
        t)!;

    ShapeBorder roundedToPartialCircleLerp(double t) => roundedLerp.lerpTo(
        CircleBorder(
          eccentricity: 0.5,
          side: BorderSide(
            color: Colors.blue.withOpacity(0.5),
            width: 5,
            strokeAlign: debugStrokeAlign,
          ),
        ),
        t)!;

    ShapeBorder roundedToCircleLerpFullyRound(double t) =>
        RoundedRectangleBorder(
          side: BorderSide(
            color: Colors.blue.withOpacity(0.5),
            width: 5,
            strokeAlign: debugStrokeAlign,
          ),
        ).lerpTo(
            CircleBorder(
              eccentricity: 0.0,
              side: BorderSide(
                color: Colors.purple.withOpacity(0.5),
                width: 5,
                strokeAlign: debugStrokeAlign,
              ),
            ),
            t)!;

    return Column(
      children: [
        Row(
          children: spaceRow(32, [
            for (double t in [0, 0.25, 0.5, 0.75, 1])
              Container(
                width: width,
                height: height,
                decoration: ShapeDecoration(
                  color: Colors.red.withOpacity(0.25),
                  shape: roundedToOvalLerp(t),
                ),
              ),
            Container(
              width: width,
              height: height,
              decoration: ShapeDecoration(
                color: Colors.white.withOpacity(0.25),
                shape: CircleBorder(
                  eccentricity: 1.0,
                  side: BorderSide(
                    color: Colors.white.withOpacity(0.5),
                    width: 5,
                    strokeAlign: debugStrokeAlign,
                  ),
                ),
              ),
              child: const Center(child: Text('1.0')),
            ),
          ]),
        ),
        Row(
          children: spaceRow(32, [
            for (double t in [0, 0.25, 0.5, 0.75, 1])
              Container(
                width: width,
                height: height,
                decoration: ShapeDecoration(
                  color: Colors.red.withOpacity(0.25),
                  shape: roundedToPartialCircleLerp(t),
                ),
              ),
            Container(
              width: width,
              height: height,
              decoration: ShapeDecoration(
                color: Colors.white.withOpacity(0.25),
                shape: CircleBorder(
                  eccentricity: 0.5,
                  side: BorderSide(
                    color: Colors.white.withOpacity(0.5),
                    width: 5,
                    strokeAlign: debugStrokeAlign,
                  ),
                ),
              ),
              child: const Center(child: Text('0.5')),
            ),
          ]),
        ),
        Row(
          children: spaceRow(32, [
            for (double t in [0, 0.25, 0.5, 0.75, 1])
              Container(
                width: width,
                height: height,
                decoration: ShapeDecoration(
                  color: Colors.brown.withOpacity(0.25),
                  shape: roundedToCircleLerpFullyRound(t),
                ),
              ),
            Container(
              width: width,
              height: height,
              decoration: ShapeDecoration(
                color: Colors.white.withOpacity(0.25),
                shape: CircleBorder(
                  eccentricity: 0.0,
                  side: BorderSide(
                    color: Colors.white.withOpacity(0.5),
                    width: 5,
                    strokeAlign: debugStrokeAlign,
                  ),
                ),
              ),
              child: const Center(child: Text('0.0')),
            ),
          ]),
        ),
      ],
    );
  }
}

@flutter-dashboard flutter-dashboard bot added a: tests "flutter test", flutter_test, or one of our tests f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels. labels May 14, 2022
@bernaferrari
Copy link
Contributor Author

Cc @gspencergoog. Kind of related to the PR you just reviewed 😅. This is a lot simpler.

@HansMuller HansMuller requested a review from gspencergoog May 19, 2022 16:26
@gspencergoog
Copy link
Contributor

I think if we're going to add a new shape, then it should support lerping to all the other shapes. The problem is that adding a new shape is exponential in the number of lerps you need to implement, since not only does this have to lerp to, say, rectangle, rectangle needs to lerp to it. For three shapes, you need three lerp functions. For five, you need ten. If we had 32 shapes, we'd need 496 lerp functions. (x = n(n-1)/2). We don't have to support every lerp, but the more the better. I'd say at least oval->rectangle, oval->rounded rect, oval->circle, oval->stadium, and back again.

It also makes the burden of adding a new shape exponentially harder, so we should consider if this is one of the shapes we really want to have. It seems reasonably likely that it is, but we should choose carefully.

@bernaferrari
Copy link
Contributor Author

What do you think if I made it as an attribute to CircleBorder? Like isOval? We would loose lerp between oval = true and oval = false, but it could be easier to update every Circle lerp.

@gspencergoog
Copy link
Contributor

I like that better, since it doesn't increase the cost of adding a new shape. What about making it more "lerpable": instead of a bool, make the parameter a double that goes from 0.0 to 1.0, where 0.0 is an oval, and 1.0 is a circle. The problem is the name of this parameter: circularity? rotundity? ovalness (reverse sense)? I think I'm leaning towards circularity.

@gspencergoog
Copy link
Contributor

Having it be a continuum will make it more useful anyhow: I can imagine wanting a semi-oval circle even when I don't want to lerp it.

@bernaferrari
Copy link
Contributor Author

I'll test that, probably tomorrow. There is already a property like you described used in lerping. It will be kind of weird, but let's see the result. Because we are not lerping from round to square, it is round with min bounds to round without bounds.

@gspencergoog
Copy link
Contributor

Yes, but I think the rect to circle lerp parameter isn't the same as this. They probably need to be combined somehow, which might be complicated. Or it might just be a multiply in the right place, if you're lucky. :-)

@bernaferrari
Copy link
Contributor Author

It should be simple, just the end result might be kind of weird. Let's see tomorrow.

@bernaferrari bernaferrari force-pushed the Oval branch 5 times, most recently from 60f0a7f to 1a24251 Compare May 23, 2022 04:42
@bernaferrari
Copy link
Contributor Author

bernaferrari commented May 23, 2022

Here it goes!

I also updated the sample code with a complex example lerping everything. Test is failing for mysterious reasons, might be something broken in the tree. I'll try to rebase another day.

image

@gspencergoog
Copy link
Contributor

I'll take a look. What about "eccentricity" for the name instead of "ovalness"?
I'm not sure it matches the textbook definition, but it does make some sense: eccentricity of 0.0 is a circle, and 1.0 is a very "eccentric" ellipse.

"The eccentricity of an ellipse is the ratio of the distance from the center to the foci and the distance from the center to the vertices."

@bernaferrari
Copy link
Contributor Author

bernaferrari commented May 23, 2022

I replaced ovalness with your circularity idea.

I think 0.0 = ellipse and 1.0 = circle makes slightly more sense codewise while at the same time being weird to introduce a parameter that by default is 1.0, not 0.0. Both have pros and cons. I changed from ovalness to circularity to make this change. If you go back two or three commits you can see how it was and which way you prefer.

But eccentricity could also work. I guess first check the code, then we can discover the name we want. It could even be fitEdgesRatio or something that has zero relationship to a circle. What we are changing are the bounds from a square to a rectangle.

@bernaferrari
Copy link
Contributor Author

Now it is using eccentricity 👀

@gspencergoog
Copy link
Contributor

@bernaferrari are you still wanting to merge this? I think we're really close here.

@bernaferrari
Copy link
Contributor Author

bernaferrari commented Jul 13, 2022

Yes, I just don't know what else we need. You never reviewed the code.

Copy link
Contributor

@gspencergoog gspencergoog left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So sorry, these comments were sitting here in GitHub, I just forgot to submit them, so I thought I was still waiting for your response!

Anyhow, here are my suggestions...

Comment on lines 21 to 23
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think you need to mention the "squared space", that is just a special case that should be expected: if the aspect ratio of the rectangle is 1:1, then the "oval" will be a circle, regardless of eccentricity.

Perhaps something like this?

Suggested change
/// The [eccentricity] parameter allows the circle to be painted touching all
/// the edges of a rectangle, becoming an oval. When applied to a
/// squared space, [eccentricity] is ignored.
/// The [eccentricity] parameter describes how much the circle will deform to
/// fit the rectangle it is a border for. A value of zero implies no
/// deformation (a circle touching at least two sides of the rectangle), a
/// value of one implies full deformation (an oval touching all sides of the
/// rectangle).

Copy link
Contributor Author

@bernaferrari bernaferrari Jul 13, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, but changed 'the circle' to 'a circle'.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be a switch statement instead of an "if", just in case we add more shapes in the future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It got slightly weird (wish you could return a switch :( hopefully soon), but it is there, I agree with the more shapes in future.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might split these into separate asserts for readability, and so when they fire they are more useful.

You can also print the offending value in the assert message so it's more helpful. Like so:

assert(eccentricity >= 0.0, 'The eccentricity argument $eccentricity is not greater than or equal to zero.');

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Just question, do we need eccentricity != null? I never understood side != null since null safety kills that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it does seem kind of silly, but there are people out there still running without strict null safety, which means that the asserts still do something.

We'll eventually make a pass and remove all such asserts with a tool once it's been long enough since we turned on null safety.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought even when null-safety was off when calling code that was null-safe it would be null-safe. Ok, adding eccentricity != null

Copy link
Contributor

@gspencergoog gspencergoog left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

32384589-a60f0e74-c078-11e7-9bc1-e5b5287aea9d

With these last few nits, this looks good to go!

Thanks so much for the PR, and I'm sorry it took so long for me to notice that I hadn't submitted.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you use the same wording as above? "a squared box" doesn't make much sense to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to:

  /// Defines the ratio (0.0-1.0) from which the border will deform
  /// to fit a rectangle.
  /// When 0.0, it draws a circle touching at least two sides of the rectangle.
  /// When 1.0, it draws an oval touching all sides of the rectangle.

Comment on lines 1525 to 1529
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting here is a little different from what we normally do:

Suggested change
if (
borderRadius == null &&
(shape == BoxShape.oval || shape == BoxShape.oval) &&
!assertOval(shapeClipper, matchState)
) {
if (borderRadius == null &&
(shape == BoxShape.oval || shape == BoxShape.oval) &&
!assertOval(shapeClipper, matchState)) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

yes, but that was the reason lol

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, OK. Well, we don't usually format it like that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed the others in 6cfd093

@bernaferrari
Copy link
Contributor Author

bernaferrari commented Jul 13, 2022

Don't worry, I'll forgive you if you can help give an end to the round outside StrokeAlign saga (either Flutter stays with the current one, we merge the other PR or we merge other and propose a new way for the one you and I like) before it is too late :P

@a-wallen a-wallen added the autosubmit Merge PR when tree becomes green via auto submit App label Jul 15, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 22, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 22, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 22, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 22, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/plugins that referenced this pull request Jul 22, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 23, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 23, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 24, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 24, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 25, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 25, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 25, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 25, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 25, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 25, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 25, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 25, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 25, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 25, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 25, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 25, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 26, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 26, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 26, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 26, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 26, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Jul 26, 2022
camsim99 pushed a commit to camsim99/flutter that referenced this pull request Aug 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: tests "flutter test", flutter_test, or one of our tests autosubmit Merge PR when tree becomes green via auto submit App f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Request] Add Oval / Ellipse support to Container

5 participants