-
Notifications
You must be signed in to change notification settings - Fork 6k
Canvas regression #17738
Canvas regression #17738
Conversation
String width = '${rect.width}px'; | ||
String height = '${rect.height}px'; | ||
while (parentSurface != null) { | ||
html.HtmlElement parentElement = parentSurface.rootElement; |
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.
The surface is placed in the DOM after it is updated. When the surface is moved to another parent, this will get a wrong DOM element.
To fix this you can schedule the update after the update, similar to how canvas painting is scheduled into the _paintQueue
.
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.
Actually, I think I know the proper place for the logic that figures out the nearest clip: recomputeTransformAndClip
. It is invoked as part of the preroll
to figure out clip changes even for addRetained
. This way, the backdrop filter doesn't need to walk up the parent chain at all. Instead, it will be given nearest clip, so it can react appropriately when the clip changes.
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. Reading localClipRect from PersistedContainerSurface instead.
String height = '${rect.height}px'; | ||
while (parentSurface != null) { | ||
html.HtmlElement parentElement = parentSurface.rootElement; | ||
if (parentElement.tagName == 'flt-clip' || parentElement.tagName == 'FLT-CLIP') { |
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.
Relying on element tag name seems error-prone as we can have other clipping elements with different tag names. In fact, I think this already missed <flt-clippath>
.
Instead, let's add a bool isClipping
getter to PersistedContainerSurface
that returns false
by default. Clips can override it and return true
instead.
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.
@@ -65,14 +65,41 @@ class PersistedBackdropFilter extends PersistedContainerSurface | |||
_invertedTransform = Matrix4.inverted(_transform); | |||
_previousTransform = _transform; | |||
} | |||
final ui.Rect rect = transformLTRB(_invertedTransform, 0, 0, | |||
ui.window.physicalSize.width, ui.window.physicalSize.height); | |||
// https://api.flutter.dev/flutter/widgets/BackdropFilter-class.html |
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.
For performance reasons the apply()
is not called when the surface is added using addRetained
. You also need to override retain()
to schedule this logic.
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.
Modified update.
@@ -0,0 +1,106 @@ | |||
// Copyright 2013 The Flutter Authors. All rights reserved. |
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.
The implementation is sensitive to the surface lifecycle. We should have tests that move the surface around (both as retained and as updated) and check that the style is applied correctly.
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.
Added test that moves clipRect.
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.
LGTM modulo the grandparent bug.
void _checkForUpdatedAncestorClipElement() { | ||
// If parent clip element has moved, adjust bounds. | ||
PersistedContainerSurface parentSurface = parent; | ||
html.HtmlElement parentElement = null; |
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.
Unused variable?
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.
// If parent clip element has moved, adjust bounds. | ||
PersistedContainerSurface parentSurface = parent; | ||
html.HtmlElement parentElement = null; | ||
while (parentSurface != null) { |
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 looks like it will be an infinite loop unless the immediate parent is a clip. I think there should be parentSurface = parentSurface.parent
somewhere inside the loop. Would also be good to add a test that checks that we can climb up the parent chain.
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.
Fixes: flutter/flutter#54871
Fixes: flutter/flutter#55193