-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Test for invalid elevations #27137
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
Test for invalid elevations #27137
Conversation
|
I have to fix the tests. I tried this at one point and it was passing, but probably because the implementation was off. |
|
Marking this as WIP until I can figure out a way to determine whether a widget should be excluded from this test or not. There seems to be a whole class of objects that ask to paint but don't actually affect the rendering. |
|
There's still a potentially open question about this around whether we really should scope to overlays (or, RenderOffstages here). I'd like to leave it as is for now, as it at least gives a check for a lot of common cases. We can figure out how to handle this for transitions once we get some more input from the folks who want this. |
| final Matrix4 matrix = Matrix4.identity()..translate(offset.dx, offset.dy); | ||
| return p.transform(matrix.storage); | ||
| } | ||
| bool _printedExceededmaxElevationObjectsToCheckWarning = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should Max be capitalized in here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, done
| /// [RenderPhysicalModel] or [RenderPhysicalShape]. The [area] parameter | ||
| /// specifies the [Rect] on the screen in which the physical model will be | ||
| /// drawn, and the [path] parameter specifies the actual [Path] to be drawn. | ||
| /// The path is expected to be smaller than the area. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can both be the same?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes - clarifying this...
| /// drawn, and the [path] parameter specifies the actual [Path] to be drawn. | ||
| /// The path is expected to be smaller than the area. | ||
| /// | ||
| /// If the durrent paint cycle results in drawing a shape at an elevation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
durrent > current
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
| double elevation, | ||
| Rect area, | ||
| Path path, | ||
| RenderObject object, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you document these two parameters as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
|
||
| Map<RenderObject, List<_ElevationData>> _elevations; | ||
| Path _translatePath(Path p, Offset offset) { | ||
| final Matrix4 matrix = Matrix4.identity()..translate(offset.dx, offset.dy); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
his probably also need to take other paint transformations into consideration? (applyPaintTransform maybe)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
I could use some feedback on whether I'm right to ignore RenderView. That one ends up applying th edevicepixelratio to the transform, and it messes things up. But I'm not sure how else it might get used.
| ); | ||
| // Check if the union created a path with a single segment. If so, the | ||
| // paths overlap. | ||
| // This will not work if we're dealing with input paths that are already |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder how common this is going to be - and how expensive it actually would be to account for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated the logic to support this - if it's looking good I'll do some perf tests and we can figure out if it needs to go or maybe get guarded somehow.
|
@goderbauer This is ready for another review pass. I've added some tests to acocunt for a |
|
@amirh I'm hoping you have some context on the failing test here (notched app bar with no margin). The algorithm I'm using marks it as a problem, because we're trying to draw a FAB with elevation 6 after an app bar with elevation 8, and the edges are touching. I'm not entirely sure what that would do in Fuchsia, but it seems off (in fact, the whole shadow rendering on iOS and Android for this seems pretty wrong to me). |
| /// | ||
| /// See also: [debugCheckElevationData]. | ||
| int get maxElevationObjectsToCheck => _maxElevationObjectsToCheck; | ||
| int _maxElevationObjectsToCheck = 10; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder what the default should be here. Setting this to 10 may break some existing apps? Should we have a way to opt-in to this?
| /// an `assert` from within the framework. All of the parameters must not be | ||
| /// null. | ||
| /// | ||
| /// The [elevation] refers to the elevation specified on the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Document if this value is relative to the parent or in terms of absolute elevation?
| /// [RenderPhysicalModel] or [RenderPhysicalShape]. The [area] parameter | ||
| /// specifies the [Rect] on the screen in which the physical model will be | ||
| /// drawn, and the [path] parameter specifies the actual [Path] to be drawn, | ||
| /// with the corret paint translations already applied. The path may be |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What coordinate system are these in?
| final Matrix4 transform = Matrix4.identity()..translate(offset.dx, offset.dy); | ||
| while (ancestor != null) { | ||
| if (ancestor is _RenderPhysicalModelBase) { | ||
| // We're the direct child of another physical model. We need to add |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given the while loop, it may not be a direct child, but a grandchild or grand-grand-...-child etc?
| } | ||
| if (ancestor is RenderObject) { | ||
| // We don't want the devicePixelRatio included in this transform. | ||
| if (ancestor is! RenderView) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems odd. Is the problem maybe that it introduces another transform and the algo can't handle two transformation?
It seems odd to me that the path drawn on the canvas below is not transformed back into the coordinate system of that canvas...
| // doing the more expensive path comparison | ||
| area.overlaps(elevationData.area) && | ||
| // ignore PhysicalModels that are direct descendants of this | ||
| // one, in case a parent is getting checked after its children |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one is odd. Why would that happen?
|
I wonder if the problem with that failing test is that we mark shapes that are just touching as overlapping. |
|
Rather than breaking out of the transforms, I would recommend moving the logic for reporting this to somewhere higher-level, e.g. a widget child of WidgetsApp, the same way we do the DEBUG banner. |
|
I am closing this one for now since @dnfield is working on a new approach, which is going to be different from what's proposed here. |


Fixes #25673
Updates the
paintmethod on_RenderPhysicalModelBaseto ask the pipeline owner to check the elevation in the area of the screen it wants to paint in. If there is such a problem, aFlutterErroris thrown and the screen is painted with a path outlining the two problematic elevations. This is only done in debug mode (or at least only whenasserts are enabled).The algorithm used has a worst-case performance of
1 + 2 + 3 + 4 + .. + n, wherenis the number of_RenderPhysicalModelBaseobjects in the render tree (which should be a small subset of total render objects in the tree for a given frame). I've added a parameter to control how many iterations we acutally check for (so at runtime it can be set lower if needed). The default is completely arbitrary right now, I'll try to test it on an older phone soon. The default for tests is arbitrarily high to be more aggressive about catching them in testing scenarios - but even for a specific test they can be turned off.