[Webkit-unassigned] [Bug 85532] [meta] Enable sub-pixel layout on all platforms
bugzilla-daemon at webkit.org
bugzilla-daemon at webkit.org
Tue Jun 26 07:48:03 PDT 2012
https://bugs.webkit.org/show_bug.cgi?id=85532
--- Comment #6 from Nikolas Zimmermann <zimmermann at kde.org> 2012-06-26 07:48:01 PST ---
(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?
--
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