Fix fixed-background offset issue

Fixed-background under scrolled container has been broken when we
enabled ScrollRecorder. Because the drawing coordinates are in the
scrolled content, while fixed-background should be drawn as if it
is in the viewport, we should add the accumulated scroll offset to
the target rect of the fixed-background.

BUG=528226
TEST=paint/overflow/fixed-background-scroll.html
TEST=paint/overflow/fixed-background-scroll-window.html
TEST=paint/overflow/fixed-background-scroll-in-frame.html

Review URL: https://codereview.chromium.org/1332643002

git-svn-id: svn://svn.chromium.org/blink/trunk@202014 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent e4329694
<!DOCTYPE html>
<style>
::-webkit-scrollbar {
display: none;
}
</style>
Tests painting of fixed background content in scrolled container.
Passes if the background doesn't scroll.
<div id="container" style="width: 200px; height: 200px; overflow: hidden">
<div id="content" style="height: 2000px; background: linear-gradient(red, blue); background-attachment: fixed"></div>
</div>
<!DOCTYPE html>
Tests painting of fixed background content in scrolled container.
Passes if the background doesn't scroll.
<iframe style="position: absolute; top: 100px; left: 100px; width: 300px; height: 300px" srcdoc="
<style>
::-webkit-scrollbar {
display: none;
}
</style>
<div id='container' style='width: 200px; height: 200px; overflow: scroll'>
<div id='content' style='height: 2000px; background: linear-gradient(red, blue); background-attachment: fixed'></div>
</div>"></iframe>
<!DOCTYPE html>
Tests painting of fixed background content in scrolled container.
Passes if the background doesn't scroll.
<div style="position: absolute; top: 100px; left: 100px; width: 400px; height: 400px; backface-visibility: hidden">
<iframe style="width: 300px; height: 300px" srcdoc="
<style>
::-webkit-scrollbar {
display: none;
}
</style>
<div id='container' style='width: 200px; height: 200px; overflow: scroll'>
<div id='content' style='height: 2000px; background: linear-gradient(red, blue); background-attachment: fixed'></div>
</div>
<script>
onload = function() {
container.scrollTop = 1000;
};
</script>"></iframe>
</div>
<!DOCTYPE html>
<style>
::-webkit-scrollbar {
display: none;
}
</style>
<body style="height: 600px; background: linear-gradient(red, blue); background-size: 800px 600px;">
<p style="position: absolute; top: 100px">
Tests painting of fixed background content in scrolled container.
Passes if the background doesn't scroll.
</p>
</body>
\ No newline at end of file
<!DOCTYPE html>
<style>
::-webkit-scrollbar {
display: none;
}
</style>
<body style="height: 4000px; background: linear-gradient(red, blue); background-attachment: fixed">
<p style="position: absolute; top: 1100px">
Tests painting of fixed background content in scrolled container.
Passes if the background doesn't scroll.
</p>
<script>
onload = function() {
window.scrollTo(0, 1000);
};
</script>
<!DOCTYPE html>
<style>
::-webkit-scrollbar {
display: none;
}
</style>
Tests painting of fixed background content in scrolled container.
Passes if the background doesn't scroll.
<div id="container" style="width: 200px; height: 200px; overflow: scroll">
<div id="content" style="height: 2000px; background: linear-gradient(red, blue); background-attachment: fixed"></div>
</div>
<script>
onload = function() {
container.scrollTop = 1000;
};
</script>
......@@ -127,6 +127,20 @@ IntSize calculateFillTileSize(const LayoutBoxModelObject& obj, const FillLayer&
return IntSize();
}
IntPoint accumulatedScrollOffset(const LayoutBoxModelObject& object, const LayoutBoxModelObject* container)
{
const LayoutBlock* block = object.isLayoutBlock() ? toLayoutBlock(&object) : object.containingBlock();
IntPoint result;
while (block) {
if (block->hasOverflowClip())
result += block->scrolledContentOffset();
if (block == container)
break;
block = block->containingBlock();
}
return result;
}
} // anonymous namespace
void BackgroundImageGeometry::setNoRepeatX(int xOffset)
......@@ -223,10 +237,15 @@ void BackgroundImageGeometry::calculate(const LayoutBoxModelObject& obj, const L
setHasNonLocalGeometry();
IntRect viewportRect = pixelSnappedIntRect(obj.viewRect());
if (fixedBackgroundPaintsInLocalCoordinates(obj, globalPaintFlags))
if (fixedBackgroundPaintsInLocalCoordinates(obj, globalPaintFlags)) {
viewportRect.setLocation(IntPoint());
else if (FrameView* frameView = obj.view()->frameView())
viewportRect.setLocation(frameView->scrollPosition());
} else {
if (FrameView* frameView = obj.view()->frameView())
viewportRect.setLocation(frameView->scrollPosition());
// Compensate the translations created by ScrollRecorders.
// TODO(trchen): Fix this for SP phase 2. crbug.com/529963.
viewportRect.moveBy(accumulatedScrollOffset(obj, paintContainer));
}
if (paintContainer) {
IntPoint absoluteContainerOffset = roundedIntPoint(paintContainer->localToAbsolute(FloatPoint()));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment