Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve and optimize non-uniform Borders. #124417

Merged
merged 17 commits into from Aug 17, 2023

Conversation

bernaferrari
Copy link
Contributor

@bernaferrari bernaferrari commented Apr 7, 2023

Using the same priority order as a Border without borderRadius, it is possible to draw them on top of each other. This is better than the current behavior (crash!) and would work well for a "one color on top, another on bottom" scenario.

With this, if approved, we move the current number of possible exceptions from 4 to 1 (BoxShape.circle + borderRadius).

It is kind of odd how borderRadius.zero to borderRadius != BorderRadius.zero change, but I think it is better than crashing. Alternatively, we just remove the "original function" and see if any goldens are affected.

image

Another one for @gspencergoog. If this works, we could make the paint method public and re-use in the InputBorder PR (if that's also approved). Single line fix.

@flutter-dashboard flutter-dashboard bot added the framework flutter/packages/flutter repository. See also f: labels. label Apr 7, 2023
@gspencergoog
Copy link
Contributor

gspencergoog commented Apr 7, 2023

Sorry, @bernaferrari but to be honest, I'm not a fan. The "old" way is boring, but predictable and unsurprising. The "new" way seems pretty surprising to me, and not at all clear why the magenta spans the width and the red doesn't span the height.

EDIT: Ahh, I see you've updated the definitions of old and new on me. :-) OK, I'll take a look, but I think it would need to be less surprising than it currently is.

@bernaferrari
Copy link
Contributor Author

For borderRadius there is no old way, it just crashes.

@bernaferrari
Copy link
Contributor Author

This is the alternate to crashing:

image

@bernaferrari
Copy link
Contributor Author

bernaferrari commented Apr 7, 2023

It is possible for the current implementation to overlap with each other (I just don't know exactly how). I am proposing a muuuuch more agressive overlap (where possible) while respecting the original order.

image

@bernaferrari
Copy link
Contributor Author

bernaferrari commented Apr 8, 2023

Another possibility is: still crash when top+left with borderRadius, but don't crash when top+bottom or left+right with borderRadius.

I just commited this possibility, check if you are happier (if you are, I just need to re-add some crashing tests).

image

@bernaferrari bernaferrari force-pushed the Border-Again branch 6 times, most recently from 914eb59 to d5aa6dd Compare April 8, 2023 18:20
@cedvdb
Copy link
Contributor

cedvdb commented Apr 12, 2023

Why do they overlap at all ? Can't they be in diagonal like they are without border radius ? The border radius would just round the edges. Like this:

Screenshot 2023-04-12 at 15 09 59

@bernaferrari
Copy link
Contributor Author

bernaferrari commented Apr 12, 2023

They could, by clipping (slow). But I limited the behavior to only work on top, left, bottom, right or top/bottom, right/left (but these are less important).

Also, your solution wouldn't work for circular shape :(

I think if this PR addressed top/left/right/bottom would be enough already. Because it is a very simple scenario (Border.only) and the current solution fails on that, since it defaults everything else to none.

I changed from addressing "all cases" to addressing Border.only and Border.symmetrical, but I can change to support Border.only as well. What do you think?

@bernaferrari
Copy link
Contributor Author

My biggest motivator is that Border.only and Border.symmetric doesn't work because BorderSide.none uses BorderSide.color = Colors.black by default, so I think...
a) Allow painting if there is a single color and everything else is none.
b) Allow painting if there are two opposite colors (paints twice).

Or a combination of a+b.

What do you think @gspencergoog?

@gspencergoog
Copy link
Contributor

By the principle of least surprise, I agree with @cedvdb. Even if it's slower, it's much less surprising. For one thing, the lerp between no border radius and border radius would need to be smooth, and I don't see how you can do that with your design, at least not in any pleasing way.

@bernaferrari
Copy link
Contributor Author

bernaferrari commented May 2, 2023

What about supporting Border.only with a single visible color (and maybe Border.symmetrical), ignoring Border.only with multiple colors for now?

@gspencergoog
Copy link
Contributor

What about supporting Border.only with a single visible color (and maybe Border.symmetrical), ignoring Border.only with multiple colors for now?

That might work. What would that look like?

@bernaferrari
Copy link
Contributor Author

bernaferrari commented May 2, 2023

When we merged it with borderRadius, we forgot the "default" of Border.only and Border.symmetrical is black + invisible by default. So I think we could support non-uniform borderStyle (BorderStyle.none).

Border.only(top: ...) will fail with borderRadius because left/right/bottom are invisible with different colors.

image

@gspencergoog
Copy link
Contributor

I think option B seems more reasonable. Option A seems like people will just wonder why the limitation exists. I mean, they'll wonder with either one, but I think it's easier to see the logic with Option B.

@bernaferrari bernaferrari force-pushed the Border-Again branch 4 times, most recently from e287dbd to 5b0d24f Compare May 2, 2023 19:35
@bernaferrari bernaferrari changed the title Add four-sided borderRadius border. Improve and optimize non-uniform Borders. May 5, 2023
@bernaferrari
Copy link
Contributor Author

bernaferrari commented May 5, 2023

Up to this point, it wasn't supposed to trigger Google Testing. Now it might. Not using paintBorder (when possible) is much faster than using it.

Goldens will also trigger. It is the path -> drrect difference.

I painted 100k borders on each test. This PR is ~15-50% faster.

00:05 +0: Divider control test                                                                                                                            
BoxBorder._paintNonUniformBorder: 80
BoxBorder.paintBorder: 101
00:05 +1: Divider custom thickness                                                                                                                        
BoxBorder._paintNonUniformBorder: 70
BoxBorder.paintBorder: 107
00:05 +2: Horizontal divider custom indentation                                                                                                           
BoxBorder._paintNonUniformBorder: 60
BoxBorder.paintBorder: 88
BoxBorder._paintNonUniformBorder: 61
BoxBorder.paintBorder: 93
BoxBorder._paintNonUniformBorder: 61
BoxBorder.paintBorder: 87
00:06 +3: Vertical Divider Test                                                                                                                           
BoxBorder._paintNonUniformBorder: 57
BoxBorder.paintBorder: 87
00:06 +4: Divider custom thickness                                                                                                                        
BoxBorder._paintNonUniformBorder: 62
BoxBorder.paintBorder: 95
00:06 +5: Vertical Divider Test 2                                                                                                                         
BoxBorder._paintNonUniformBorder: 57
BoxBorder.paintBorder: 91
BoxBorder._paintNonUniformBorder: 383
BoxBorder.paintBorder: 434
00:07 +6: Vertical divider custom indentation                                                                                                             
BoxBorder._paintNonUniformBorder: 65
BoxBorder.paintBorder: 89
BoxBorder._paintNonUniformBorder: 65
BoxBorder.paintBorder: 90
BoxBorder._paintNonUniformBorder: 68
BoxBorder.paintBorder: 91
00:08 +8: All tests passed!                                                                                                                              

@bernaferrari bernaferrari marked this pull request as ready for review May 5, 2023 19:40
@gspencergoog
Copy link
Contributor

Nice! Let's see how bad the Google test fallout is.

@bernaferrari bernaferrari force-pushed the Border-Again branch 2 times, most recently from 62a907c to 2513469 Compare August 16, 2023 23:40
@bernaferrari bernaferrari added the autosubmit Merge PR when tree becomes green via auto submit App label Aug 16, 2023
@auto-submit auto-submit bot merged commit b7046b3 into flutter:master Aug 17, 2023
73 checks passed
@bernaferrari bernaferrari deleted the Border-Again branch August 17, 2023 04:23
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Aug 17, 2023
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Aug 18, 2023
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Aug 18, 2023
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Aug 18, 2023
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Aug 18, 2023
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Nov 15, 2023
Comment on lines +667 to +668
assert(borderRadius == null || borderRadius == BorderRadius.zero,
'A hairline border like `BorderSide(width: 0.0, style: BorderStyle.solid)` can only be drawn when BorderRadius is zero or null.');
Copy link

Choose a reason for hiding this comment

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

this new assert broke app-bar in my app after updating to 3.16.

Choose a reason for hiding this comment

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

@Hixie @bernaferrari is it a good idea to mention this change in breaking points page for 3.16?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Can you show the code? It isn't supposed to break anything because the behavior was wrong

Choose a reason for hiding this comment

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

made a reproducible sample: https://dartpad.dev/?id=413770c667697ac3472fc03d12d4fe54

Issue: "FAQs" widget is not shown because of the new assert.


either setting the border-radius to zero or removing the BorderSide's with 0 width, fixes the problem. not sure why we were using border-side 0 in our code but code was in app-bar hence I noticed it when it glitched after stable update.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, but the 0 as hidden is a bug, because flutter uses that for hairline border (I wish it were different but I can't change it because visual density depends on context), so instead of fixing to show it (which would be a bug for you), we fixed to assert to prevent problems in the future

Copy link

Choose a reason for hiding this comment

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

Same here. Not sure what was wrong with hairline borders, but we use them pretty extensively in our app and now they aren't visible anymore after updating to the latest Flutter version. Could you clarify what was the issue with drawing hairline borders with rounded corners?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is an inconsistent behavior, I just updated to be consistent. The issue is that for any other corner it draws hairline on width = 0 and you can't draw it on non uniform, so I added an assert.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
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.

None yet

7 participants