Bug 91007 - Seams appear when zooming page with absolutely positioned canvas objects
Summary: Seams appear when zooming page with absolutely positioned canvas objects
Status: RESOLVED DUPLICATE of bug 99104
Alias: None
Product: WebKit
Classification: Unclassified
Component: Layout and Rendering (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Emil A Eklund
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-07-11 13:15 PDT by Justin Novosad
Modified: 2012-11-01 09:13 PDT (History)
3 users (show)

See Also:


Attachments
Test case (2.00 KB, text/html)
2012-07-11 13:16 PDT, Justin Novosad
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Justin Novosad 2012-07-11 13:15:35 PDT
This bug is reproducible in Safari and Chrome with GPU-accelerated canvas rendering.

Load attached "grid bug.html" file in the browser, and zoom the page in or out.
Result -> White grid lines appear and most zoom factors

Seems to be a problem with the compositor's layout algorithm.  The rounding of canvas layers' zoomed size is probably to blame.
Comment 1 Justin Novosad 2012-07-11 13:16:22 PDT
Created attachment 151758 [details]
Test case
Comment 2 Justin Novosad 2012-08-01 11:55:05 PDT
@leviw: any idea what may have caused this? It appears to be a recent regression.
Comment 3 Justin Novosad 2012-08-01 12:00:45 PDT
I found that the problem has to do with the rounding of the zomed canvas size in WebCore::RenderHTMLCanvas::canvasSizeChanges.  It disagrees with the coordinate snapping.

The following way of computing intrinsic size seems to fix the bug on windows, but not quite on linux, so I think there is more to it that what I understand so far:

void RenderHTMLCanvas::canvasSizeChanged()
{
    IntSize canvasSize = static_cast<HTMLCanvasElement*>(node())->size();
    IntSize zoomedSize;

    RenderStyle* styleToUse = style();
    float effectiveZoom = styleToUse->effectiveZoom();

    if (styleToUse->isOutOfFlowPositioned()) {
        // When positioning is out of flow, the zoomed size must be computed from the zoomed bounds,
        // otherwise there is a risk of creating gaps between adjacent canvases due to integer coordinate
        // snapping
        float left = styleToUse->logicalLeft().getFloatValue();
        float right = left + canvasSize.width() * effectiveZoom;
        zoomedSize.setWidth(roundToInt(right) - roundToInt(left));
        float top = styleToUse->top().getFloatValue();
        float bottom = top + canvasSize.height() * effectiveZoom;
        zoomedSize.setHeight(roundToInt(bottom) - roundToInt(top));
    } else {
        zoomedSize.setWidth(roundToInt(canvasSize.width() * effectiveZoom));
        zoomedSize.setHeight(roundToInt(canvasSize.height() * effectiveZoom));
    }

    if (zoomedSize == intrinsicSize())
        return;
(...)

(In reply to comment #2)
> @leviw: any idea what may have caused this? It appears to be a recent regression.
Comment 4 Levi Weintraub 2012-08-07 15:50:54 PDT
(In reply to comment #3)
> I found that the problem has to do with the rounding of the zomed canvas size in WebCore::RenderHTMLCanvas::canvasSizeChanges.  It disagrees with the coordinate snapping.
> 
> The following way of computing intrinsic size seems to fix the bug on windows, but not quite on linux, so I think there is more to it that what I understand so far:
> 
> void RenderHTMLCanvas::canvasSizeChanged()
> {
>     IntSize canvasSize = static_cast<HTMLCanvasElement*>(node())->size();
>     IntSize zoomedSize;
> 
>     RenderStyle* styleToUse = style();
>     float effectiveZoom = styleToUse->effectiveZoom();
> 
>     if (styleToUse->isOutOfFlowPositioned()) {
>         // When positioning is out of flow, the zoomed size must be computed from the zoomed bounds,
>         // otherwise there is a risk of creating gaps between adjacent canvases due to integer coordinate
>         // snapping
>         float left = styleToUse->logicalLeft().getFloatValue();
>         float right = left + canvasSize.width() * effectiveZoom;
>         zoomedSize.setWidth(roundToInt(right) - roundToInt(left));
>         float top = styleToUse->top().getFloatValue();
>         float bottom = top + canvasSize.height() * effectiveZoom;
>         zoomedSize.setHeight(roundToInt(bottom) - roundToInt(top));
>     } else {
>         zoomedSize.setWidth(roundToInt(canvasSize.width() * effectiveZoom));
>         zoomedSize.setHeight(roundToInt(canvasSize.height() * effectiveZoom));
>     }
> 
>     if (zoomedSize == intrinsicSize())
>         return;
> (...)
> 
> (In reply to comment #2)
> > @leviw: any idea what may have caused this? It appears to be a recent regression.

Interesting! I'm not surprised this doesn't solve the problem in all cases since we use different snapping logic than what you implemented here. I've got another Layout issue in front of this, but it's on my list. Thanks for taking a preliminary look!
Comment 5 Emil A Eklund 2012-10-08 16:32:52 PDT
This seems quite similar to bug 98205, will try the same approach for canvas.
Comment 6 Emil A Eklund 2012-10-11 16:19:01 PDT
Bug 99104 tracks another approach for fixing this.
Comment 7 Emil A Eklund 2012-11-01 09:13:46 PDT

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