-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Canvas with relative width does not repaint correctly on parent resize #44463
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
Conversation
|
EWS run on previous version of this PR (hash c899a18) Details |
c899a18 to
858d7a8
Compare
|
EWS run on previous version of this PR (hash 858d7a8) Details |
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.
Any reason why not just pass in shouldAlwaysIssueFullRepaint to LayoutRepainter in RenderReplaced::layout() when needed?
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.
Yeah, shouldAlwaysIssueFullRepaint would work for replaced element without layer. For element hasLayer, repaintAfterLayoutIfNeeded is triggered in recursiveUpdateLayerPositions, we need to set NeedsFullRepaint to its RenderLayer.
I don't have a strong opinion. But if you prefer shouldAlwaysIssueFullRepaint + NeedsFullRepaint approach, I will adjust the patch later.
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.
oh I just realized this requires post layout check. ok, I mean I am fine either way but isn't this just a repaint() call which I think could be achieved with a more focused change, something along the lines of
static void issueFullRepaintOnSizeChangeIfNeeded(RenderReplaced& renderer)
{
auto shouldRepaintOnSizeChange = [&] {
if (is<RenderHTMLCanvas>(renderer))
return true;
if (auto* renderImage = dynamicDowncast<RenderImage>(renderer); renderImage && !is<RenderMedia>(*renderImage) && !renderImage->isShowingMissingOrImageError())
return true;
return false;
};
if (shouldRepaintOnSizeChange())
renderer.repaint();
}
called by RenderReplaced::layout when replacedContentRect() != oldContentRect
or alternatively RenderImage/RenderHTMLCanvas::layout could just call repaint() after coming backing from base class layout when content box size changed.
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.
True, it looks clearer.
858d7a8 to
9344607
Compare
|
EWS run on previous version of this PR (hash 9344607) Details |
|
EWS run on previous version of this PR (hash 44f343d) Details |
|
EWS run on previous version of this PR (hash 8f3a9e4) Details |
|
EWS run on current version of this PR (hash fae6baa) Details |
https://bugs.webkit.org/show_bug.cgi?id=267986 Reviewed by Alan Baradlay. Elements with relative width do not trigger a full repaint when their size changes because they are not selfNeedsLayout. For elements like <canvas> and <img>, a size change implies a scale change, so they should trigger a full repaint. This issue is only revealed if the replaced element is on a tiled layer and its ancestor with selfNeedsLayout on other layer. If they are on the same layer, the ancestor would trigger full repaint for itself, the repaint rect will cover the replace element. If the replaced element is on an untiled layer, this layer triggers a full repaint on layer size change. This patch triggers full repaint for elements like canvas and image in after layout. * LayoutTests/compositing/tiling/huge-layer-canvas-resize-expected.txt: Added. * LayoutTests/compositing/tiling/huge-layer-canvas-resize.html: Added. * LayoutTests/compositing/tiling/huge-layer-img-resize-expected.txt: Added. * LayoutTests/compositing/tiling/huge-layer-img-resize.html: Added. * LayoutTests/platform/glib/TestExpectations: * LayoutTests/platform/ios/compositing/tiling/huge-layer-canvas-resize-expected.txt: Added. * LayoutTests/platform/ios/compositing/tiling/huge-layer-img-resize-expected.txt: Added. * LayoutTests/platform/win/TestExpectations: * Source/WebCore/rendering/RenderReplaced.cpp: (WebCore::issueFullRepaintOnSizeChangeIfNeeded): (WebCore::RenderReplaced::layout): Canonical link: https://commits.webkit.org/294401@main
fae6baa to
7bbc1c0
Compare
|
Committed 294401@main (7bbc1c0): https://commits.webkit.org/294401@main Reviewed commits have been landed. Closing PR #44463 and removing active labels. |
| } | ||
| if (window.testRunner) | ||
| testRunner.notifyDone(); | ||
| }, 1000); |
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 exactly are you waiting 1000ms for? This makes the behavior of the test un-deterministic. Besides one second is too long time to wait. Can not it be replaced by
requestAnimationFrame(() => {
...
});
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.
We need to make sure the repaint rects before css change has flashed, so I added 1000 ms. requestAnimationFrame seems not long enough, especially in stress mode.
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.
Rego suggested me to use two requestAnimationFrame, it works! I have created a PR to address the code review comments. Please take a look, thanks:) #45040
| img.src = canvas.toDataURL(); | ||
| } | ||
|
|
||
| async function onImageLoad() |
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.
Why is this function marked as async? It does not have await statement.
| if (replacedContentRect() != oldContentRect) | ||
| if (replacedContentRect() != oldContentRect) { | ||
| setPreferredLogicalWidthsDirty(true); | ||
| issueFullRepaintOnSizeChangeIfNeeded(*this); |
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 think this is a long name for a function. Could it be just?
if (shouldRepaintOnSizeChange(*this))
repaint();
7bbc1c0
fae6baa