[Webkit-unassigned] [Bug 85532] [meta] Enable sub-pixel layout on all platforms

bugzilla-daemon at webkit.org bugzilla-daemon at webkit.org
Wed Jul 25 14:55:34 PDT 2012


https://bugs.webkit.org/show_bug.cgi?id=85532





--- Comment #9 from Levi Weintraub <leviw at chromium.org>  2012-07-25 14:55:37 PST ---
(In reply to comment #7)
> (In reply to comment #6)
> > (In reply to comment #3)
> > > I'd love an update on plans for enabling it in the KDE project ;)
> > I'm not working on KDE stuff since half a decade btw, historical reasons for my bugzilla account :-)
> > 
> > Anyhow, I've experimented lots with SUBPIXEL_LAYOUT turned on, on Mac. You've done a great job, it's working as-expected for most parts.
> > 
> > I've ran into an issue with transforming an absolute positioned <div>, which is aligned on sub-pixel boundaries, like this:
> > 
> > <html>
> > <body>
> > <div style="-moz-transform: scale(100); -webkit-transform: scale(100); background-color: green; position: absolute; left: -0.5px; top: -0.5px; width: 1px; height: 1px;"></div>
> > </body>
> > </html>
> > 
> > If you run this in trunk, you won't see anything, unless you zoom in or out at least once.
> > I've nailed down the problem, but I'm yet unsure on how to fix it properly, so I'd like to share it with you to get your insight:
> > void RenderBlock::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
> > {
> >     LayoutPoint adjustedPaintOffset = paintOffset + location();
> > 
> >     PaintPhase phase = paintInfo.phase;
> > 
> >     // Check if we need to do anything at all.
> >     // FIXME: Could eliminate the isRoot() check if we fix background painting so that the RenderView
> >     // paints the root's background.
> >     if (!isRoot()) {
> >         LayoutRect overflowBox = visualOverflowRect();
> >         flipForWritingMode(overflowBox);
> >         overflowBox.inflate(maximalOutlineSize(paintInfo.phase));
> >         overflowBox.moveBy(adjustedPaintOffset);
> >         if (!overflowBox.intersects(paintInfo.rect))
> >             return;
> >     ....
> > 
> > Break on RenderBlock::paint(), at some point:
> > Breakpoint 1, WebCore::RenderBlock::paint (this=0x1091271e8, paintInfo=@0x7fff5fbf97a8, paintOffset=@0x7fff5fbf98d0) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderBlock.cpp:2626
> > 2626        LayoutPoint adjustedPaintOffset = paintOffset + location();
> > (gdb) p showRenderTreeForThis()
> > RenderView 0x109124108                     #document    0x10882a600
> >   RenderBlock 0x109125b78                  HTML    0x109120380
> >     RenderBody 0x1091266d8                 BODY    0x109125ca0
> > *     RenderBlock (positioned) 0x1091271e8    DIV    0x109126400 STYLE=-moz-transform: scale(100); -webkit-transform: scale(100); background-color: green; position: absolute; left: -0.5px; top: -0.5px; width: 1px; height: 1px;
> > 
> > is reached.
> > 
> > 2638            if (!overflowBox.intersects(paintInfo.rect))
> > (gdb) p overflowBox
> > $39 = {
> >   m_location = {
> >     m_x = {
> >       m_value = 0
> >     }, 
> >     m_y = {
> >       m_value = 0
> >     }
> >   }, 
> >   m_size = {
> >     m_width = {
> >       m_value = 60
> >     }, 
> >     m_height = {
> >       m_value = 60
> >     }
> >   }
> > }
> > 
> > p paintInfo.rect
> > $40 = {
> >   m_location = {
> >     m_x = 1, 
> >     m_y = 1
> >   }, 
> >   m_size = {
> >     m_width = 8, 
> >     m_height = 6
> >   }
> > }
> > 
> > 0x000000010269d7af in WebCore::RenderBlock::paint (this=0x1091271e8, paintInfo=@0x7fff5fbf97a8, paintOffset=@0x7fff5fbf98d0) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderBlock.cpp:2638
> > 2638            if (!overflowBox.intersects(paintInfo.rect))
> > Value returned is $41 = false
> > 
> > And here's the problem. The paintInfo.rect has a location of 1x1, and a size of 8x6.
> > So let's examine where the incorrect paintInfo.rect is coming from:
> > 
> > (gdb) bt
> > #0  0x000000010269d7af in WebCore::RenderBlock::paint (this=0x1091271e8, paintInfo=@0x7fff5fbf97a8, paintOffset=@0x7fff5fbf98d0) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderBlock.cpp:2638
> > #1  0x000000010279d729 in WebCore::RenderLayer::paintLayerContents (this=0x1091272b8, rootLayer=0x1091272b8, context=0x7fff5fbfb4c0, parentPaintDirtyRect=@0x7fff5fbf9b10, paintBehavior=0, paintingRoot=0x0, region=0x0, overlapTestRequests=0x7fff5fbfb1c0, paintFlags=480) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderLayer.cpp:3149
> > 
> > Looking at frame #1:
> > #1  0x000000010279d729 in WebCore::RenderLayer::paintLayerContents (this=0x1091272b8, rootLayer=0x1091272b8, context=0x7fff5fbfb4c0, parentPaintDirtyRect=@0x7fff5fbf9b10, paintBehavior=0, paintingRoot=0x0, region=0x0, overlapTestRequests=0x7fff5fbfb1c0, paintFlags=480) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderLayer.cpp:3149
> > 3147                // Paint the background.
> > 3148                PaintInfo paintInfo(context, pixelSnappedIntRect(damageRect.rect()), PaintPhaseBlockBackground, false, paintingRootForRenderer, region, 0);
> > 3149                renderer()->paint(paintInfo, paintOffset);
> > 
> > (gdb) p damageRect.rect()
> > $51 = (const LayoutRect &) @0x7fff5fbf9908: {
> >   m_location = {
> >     m_x = {
> >       m_value = 30
> >     }, 
> >     m_y = {
> >       m_value = 30
> >     }
> >   }, 
> >   m_size = {
> >     m_width = {
> >       m_value = 480
> >     }, 
> >     m_height = {
> >       m_value = 360
> >     }
> >   }
> > }
> > 
> > The pixelSnappedIntRect() produces the x/y=1, width=8, height=6 IntRect.
> > 
> > Some more background info:
> > The RenderLayer associated with the <div> has a transform, scale(100).
> > #3  0x000000010279c370 in WebCore::RenderLayer::paintLayer (this=0x1091272b8, rootLayer=0x1091244c8, context=0x7fff5fbfb4c0, paintDirtyRect=@0x7fff5fbfa2d0, paintBehavior=0, paintingRoot=0x0, region=0x0, overlapTestRequests=0x7fff5fbfb1c0, paintFlags=480) at /Users/nzimmermann/Coding/WebKit/Source/WebCore/rendering/RenderLayer.cpp:3006
> > 
> > 3001            {
> > 3002                GraphicsContextStateSaver stateSaver(*context);
> > 3003                context->concatCTM(transform.toAffineTransform());
> > 3004    
> > 3005                // Now do a paint with the root layer shifted to be us.
> > 3006                paintLayerContentsAndReflection(this, context, transform.inverse().mapRect(paintDirtyRect), paintBehavior, paintingRoot, region, overlapTestRequests, paintFlags);
> > 3007            }        
> > 3008    
> > 3009            // Restore the clip.
> > 3010            if (parent())
> > 
> > (gdb) p transform
> > $56 = {
> >   m_matrix = {{100, 0, 0, 0}, {0, 100, 0, 0}, {0, 0, 1, 0}, {-50, -50, 0, 1}}
> > }
> > 
> > (gdb) p paintDirtyRect
> > $58 = (const LayoutRect &) @0x7fff5fbfa2d0: {
> >   m_location = {
> >     m_x = {
> >       m_value = 0
> >     }, 
> >     m_y = {
> >       m_value = 0
> >     }
> >   }, 
> >   m_size = {
> >     m_width = {
> >       m_value = 48000
> >     }, 
> >     m_height = {
> >       m_value = 36000
> >     }
> >   }
> > }
> > 
> > The mapping of the paintDirtyRect through the inverse of the transform, produces x/y=30 (aka. 0.5).
> > Now that we know the root of the problem, if you change left/top to 0.4999px, it'll show up as expected, as the paintInfo.rect is now at 0x0, as 0.4999px is pixel-snapped to 0, instead of 1.
> > 
> > I'm unsure on how to fix this properly: the intersection between the pixel-snapped paint info rect and the overflow box is lossy, as the overflow box is sub-pixel aware.
> > 
> > (gdb) p toRenderBox(renderer())->m_frameRect
> > $61 = {
> >   m_location = {
> >     m_x = {
> >       m_value = -30
> >     }, 
> >     m_y = {
> >       m_value = -30
> >     }
> >   }, 
> >   m_size = {
> >     m_width = {
> >       m_value = 60
> >     }, 
> >     m_height = {
> >       m_value = 60
> >     }
> >   }
> > }
> > 
> > As no overflow is involved in my example, visualOverflowRect() == borderBoxRect(), aka. LayoutRect(0, 0, m_frameRect->width(), m_frameRect->height()) (in this example).
> > 
> > Sorry for the long post, but I thought I'd give as much information as possible, so we can discuss this easier. Levi, any idea?
> 
> 
> Levi, eae: ping? This is somewhat of a blocker for the SVG2.0 work.

Apologies for the slow response -- I've been away on vacation. This is yet another issue that is solved by the patch on https://bugs.webkit.org/show_bug.cgi?id=89238. I've been trying rather unsuccessfully to get a review (and have been out of town) if one of you have a chance to take a look.

-- 
Configure bugmail: https://bugs.webkit.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.



More information about the webkit-unassigned mailing list