Bug 93703 - fast/repaint/float-in-new-block-with-layout-delta.html is overpainting
Summary: fast/repaint/float-in-new-block-with-layout-delta.html is overpainting
Status: RESOLVED DUPLICATE of bug 92800
Alias: None
Product: WebKit
Classification: Unclassified
Component: Layout and Rendering (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-08-10 02:31 PDT by Eric Seidel (no email)
Modified: 2012-08-10 03:37 PDT (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Eric Seidel (no email) 2012-08-10 02:31:17 PDT
fast/repaint/float-in-new-block-with-layout-delta.html is overpainting

Looking at the expected image:
http://trac.webkit.org/browser/trunk/LayoutTests/platform/mac/fast/repaint/float-in-new-block-with-layout-delta-expected.png

Notice how we repaint 100x200 instead of 100x100 (which is actually all we need).

The "overpaint" is caused by:
RenderBlock::repaintDirtyFloats
which is called at the last line of:
RenderBlock::layoutRunsAndFloats

and repaints the float inside the div which is of course still at 0,0.

The problem appears to be the layoutDelta in:

LayoutRect RenderBox::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer) const
{
    if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent())
        return LayoutRect();

    LayoutRect r = visualOverflowRect();

    RenderView* v = view();
    if (v) {
        // FIXME: layoutDelta needs to be applied in parts before/after transforms and
        // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
        r.move(v->layoutDelta());
    }

Which at time of repaint is 0, -118, which adjusts the rect from the repaint() call back to 0.

It seems that the repaintDirtyFloats call is attempting to repaint the *new* location of the float, not the *old* location, but maybe I"m misunderstanding.

I'll have to look again to understand why we're actually invalidating the new location, although initial testing of my patch on bug 92800, may suggest that our invalidation of the new location is wrong, as bug 92800 disables it (possibly incorrectly).

The first issue is for me to understand what the purpose of RenderBlock::repaintDirtyFloats at the end of RenderBlock::layoutRunsAndFloats is.
Comment 1 Eric Seidel (no email) 2012-08-10 02:38:14 PDT
It's also unclear to me what the purpose of layoutDelta() is.  Since it makes it awkward to call clippedOverflowRectForRepaint() as you'll never know whether you're getting the "new" or "old" repaint rect for an object, as layoutDelta will make that function return the "old" bounds when it's in effect.
Comment 2 Eric Seidel (no email) 2012-08-10 03:05:06 PDT
Yup, re-confirmed.

repaintDirtyFloats() causes this new float to repaint it's old (invalid) bounds of 8,8; 100,100

This code in layoutBlockChild():
    if (!childHadLayout && child->checkForRepaintDuringLayout()) {
        child->repaint();
        child->repaintOverhangingFloats(true);
    }

is causing the new bounds to repaint.  Which is correct.  Except checkForRepaintDuringLayout() may be wrong there.

This is an example of the current contract whereby your parent will force you to repaint when you're painting for the first time.

In bug 92800, I'm exploring making checkForRepaintDuringLayout return true only if the object has ever painted before.  Obviously that would be incompatible with this usage here.

From this analysis it looks like repaintDirtyFloats() is intentionally repainting the old bounds.  Which is just wrong in the first-layout case.
Comment 3 Eric Seidel (no email) 2012-08-10 03:37:26 PDT
I've sorted through my confusion enough to fix this as part of bug 92800.

*** This bug has been marked as a duplicate of bug 92800 ***