Commit 9df701ea authored by leviw@chromium.org's avatar leviw@chromium.org

Fix sub-pixel handling of transparency boxes in DPL

DeprecatedPaintLayer::transparencyClipBox and
DeprecatedPaintLayer::paintingExtent used to take a sub-pixel accumulation
value as an argument, but that value was inconsistent and often incorrect.
DeprecatedPaintLayer's have a sub-pixel accumulation value as a member for
this purpose, so this patch makes these methods use it. This fixes some
cases where partially transparent nested objects would be clipped
incorrectly at certain sub-pixel offsets.

BUG=476139

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

git-svn-id: svn://svn.chromium.org/blink/trunk@200922 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent d7145fab
<!DOCTYPE html>
<style>
body {
position: relative;
left: 1px;
}
.parent {
display: inline-block;
transform: scale(5);
opacity: 0.8;
}
.child {
position: absolute;
width: 10px;
height: 10px;
background: red;
border: 1px solid black;
}
</style>
<div class="parent">
<div class="child"></div>
</div>
\ No newline at end of file
<!DOCTYPE html>
<style>
body {
position: relative;
left: 0.5px;
}
.parent {
display: inline-block;
transform: scale(5);
opacity: 0.8;
}
.child {
position: absolute;
width: 10px;
height: 10px;
background: red;
border: 1px solid black;
}
</style>
<div class="parent">
<div class="child"></div>
</div>
\ No newline at end of file
...@@ -1003,7 +1003,7 @@ static void expandClipRectForDescendantsAndReflection(LayoutRect& clipRect, cons ...@@ -1003,7 +1003,7 @@ static void expandClipRectForDescendantsAndReflection(LayoutRect& clipRect, cons
// a stacking container. This means we can just walk the layer tree directly. // a stacking container. This means we can just walk the layer tree directly.
for (DeprecatedPaintLayer* curr = layer->firstChild(); curr; curr = curr->nextSibling()) { for (DeprecatedPaintLayer* curr = layer->firstChild(); curr; curr = curr->nextSibling()) {
if (!layer->reflectionInfo() || layer->reflectionInfo()->reflectionLayer() != curr) if (!layer->reflectionInfo() || layer->reflectionInfo()->reflectionLayer() != curr)
clipRect.unite(DeprecatedPaintLayer::transparencyClipBox(curr, rootLayer, transparencyBehavior, DeprecatedPaintLayer::DescendantsOfTransparencyClipBox, subPixelAccumulation, globalPaintFlags)); clipRect.unite(DeprecatedPaintLayer::transparencyClipBox(curr, rootLayer, transparencyBehavior, DeprecatedPaintLayer::DescendantsOfTransparencyClipBox, globalPaintFlags));
} }
} }
...@@ -1021,7 +1021,7 @@ static void expandClipRectForDescendantsAndReflection(LayoutRect& clipRect, cons ...@@ -1021,7 +1021,7 @@ static void expandClipRectForDescendantsAndReflection(LayoutRect& clipRect, cons
} }
LayoutRect DeprecatedPaintLayer::transparencyClipBox(const DeprecatedPaintLayer* layer, const DeprecatedPaintLayer* rootLayer, TransparencyClipBoxBehavior transparencyBehavior, LayoutRect DeprecatedPaintLayer::transparencyClipBox(const DeprecatedPaintLayer* layer, const DeprecatedPaintLayer* rootLayer, TransparencyClipBoxBehavior transparencyBehavior,
TransparencyClipBoxMode transparencyMode, const LayoutSize& subPixelAccumulation, GlobalPaintFlags globalPaintFlags) TransparencyClipBoxMode transparencyMode, GlobalPaintFlags globalPaintFlags)
{ {
// FIXME: Although this function completely ignores CSS-imposed clipping, we did already intersect with the // FIXME: Although this function completely ignores CSS-imposed clipping, we did already intersect with the
// paintDirtyRect, and that should cut down on the amount we have to paint. Still it // paintDirtyRect, and that should cut down on the amount we have to paint. Still it
...@@ -1036,7 +1036,7 @@ LayoutRect DeprecatedPaintLayer::transparencyClipBox(const DeprecatedPaintLayer* ...@@ -1036,7 +1036,7 @@ LayoutRect DeprecatedPaintLayer::transparencyClipBox(const DeprecatedPaintLayer*
LayoutPoint delta; LayoutPoint delta;
layer->convertToLayerCoords(rootLayerForTransform, delta); layer->convertToLayerCoords(rootLayerForTransform, delta);
delta.move(subPixelAccumulation); delta.move(layer->subpixelAccumulation());
IntPoint pixelSnappedDelta = roundedIntPoint(delta); IntPoint pixelSnappedDelta = roundedIntPoint(delta);
TransformationMatrix transform; TransformationMatrix transform;
transform.translate(pixelSnappedDelta.x(), pixelSnappedDelta.y()); transform.translate(pixelSnappedDelta.x(), pixelSnappedDelta.y());
...@@ -1046,7 +1046,7 @@ LayoutRect DeprecatedPaintLayer::transparencyClipBox(const DeprecatedPaintLayer* ...@@ -1046,7 +1046,7 @@ LayoutRect DeprecatedPaintLayer::transparencyClipBox(const DeprecatedPaintLayer*
// We don't use fragment boxes when collecting a transformed layer's bounding box, since it always // We don't use fragment boxes when collecting a transformed layer's bounding box, since it always
// paints unfragmented. // paints unfragmented.
LayoutRect clipRect = layer->physicalBoundingBox(layer); LayoutRect clipRect = layer->physicalBoundingBox(layer);
expandClipRectForDescendantsAndReflection(clipRect, layer, layer, transparencyBehavior, subPixelAccumulation, globalPaintFlags); expandClipRectForDescendantsAndReflection(clipRect, layer, layer, transparencyBehavior, layer->subpixelAccumulation(), globalPaintFlags);
clipRect.expand(layer->layoutObject()->style()->filterOutsets()); clipRect.expand(layer->layoutObject()->style()->filterOutsets());
LayoutRect result = transform.mapRect(clipRect); LayoutRect result = transform.mapRect(clipRect);
if (!paginationLayer) if (!paginationLayer)
...@@ -1065,15 +1065,15 @@ LayoutRect DeprecatedPaintLayer::transparencyClipBox(const DeprecatedPaintLayer* ...@@ -1065,15 +1065,15 @@ LayoutRect DeprecatedPaintLayer::transparencyClipBox(const DeprecatedPaintLayer*
} }
LayoutRect clipRect = layer->fragmentsBoundingBox(rootLayer); LayoutRect clipRect = layer->fragmentsBoundingBox(rootLayer);
expandClipRectForDescendantsAndReflection(clipRect, layer, rootLayer, transparencyBehavior, subPixelAccumulation, globalPaintFlags); expandClipRectForDescendantsAndReflection(clipRect, layer, rootLayer, transparencyBehavior, layer->subpixelAccumulation(), globalPaintFlags);
clipRect.expand(layer->layoutObject()->style()->filterOutsets()); clipRect.expand(layer->layoutObject()->style()->filterOutsets());
clipRect.move(subPixelAccumulation); clipRect.move(layer->subpixelAccumulation());
return clipRect; return clipRect;
} }
LayoutRect DeprecatedPaintLayer::paintingExtent(const DeprecatedPaintLayer* rootLayer, const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation, GlobalPaintFlags globalPaintFlags) LayoutRect DeprecatedPaintLayer::paintingExtent(const DeprecatedPaintLayer* rootLayer, const LayoutRect& paintDirtyRect, GlobalPaintFlags globalPaintFlags)
{ {
return intersection(transparencyClipBox(this, rootLayer, PaintingTransparencyClipBox, RootOfTransparencyClipBox, subPixelAccumulation, globalPaintFlags), paintDirtyRect); return intersection(transparencyClipBox(this, rootLayer, PaintingTransparencyClipBox, RootOfTransparencyClipBox, globalPaintFlags), paintDirtyRect);
} }
void* DeprecatedPaintLayer::operator new(size_t sz) void* DeprecatedPaintLayer::operator new(size_t sz)
...@@ -1797,7 +1797,7 @@ DeprecatedPaintLayer* DeprecatedPaintLayer::hitTestTransformedLayerInFragments(D ...@@ -1797,7 +1797,7 @@ DeprecatedPaintLayer* DeprecatedPaintLayer::hitTestTransformedLayerInFragments(D
DeprecatedPaintLayerFragments enclosingPaginationFragments; DeprecatedPaintLayerFragments enclosingPaginationFragments;
LayoutPoint offsetOfPaginationLayerFromRoot; LayoutPoint offsetOfPaginationLayerFromRoot;
// FIXME: We're missing a sub-pixel offset here crbug.com/348728 // FIXME: We're missing a sub-pixel offset here crbug.com/348728
LayoutRect transformedExtent = transparencyClipBox(this, enclosingPaginationLayer(), HitTestingTransparencyClipBox, DeprecatedPaintLayer::RootOfTransparencyClipBox, LayoutSize()); LayoutRect transformedExtent = transparencyClipBox(this, enclosingPaginationLayer(), HitTestingTransparencyClipBox, DeprecatedPaintLayer::RootOfTransparencyClipBox);
enclosingPaginationLayer()->collectFragments(enclosingPaginationFragments, rootLayer, hitTestRect, enclosingPaginationLayer()->collectFragments(enclosingPaginationFragments, rootLayer, hitTestRect,
clipRectsCacheSlot, IncludeOverlayScrollbarSize, RespectOverflowClip, &offsetOfPaginationLayerFromRoot, LayoutSize(), &transformedExtent); clipRectsCacheSlot, IncludeOverlayScrollbarSize, RespectOverflowClip, &offsetOfPaginationLayerFromRoot, LayoutSize(), &transformedExtent);
......
...@@ -515,7 +515,7 @@ public: ...@@ -515,7 +515,7 @@ public:
ASSERT(!m_hasSelfPaintingLayerDescendantDirty); ASSERT(!m_hasSelfPaintingLayerDescendantDirty);
return m_hasSelfPaintingLayerDescendant; return m_hasSelfPaintingLayerDescendant;
} }
LayoutRect paintingExtent(const DeprecatedPaintLayer* rootLayer, const LayoutRect& paintDirtyRect, const LayoutSize& subPixelAccumulation, GlobalPaintFlags); LayoutRect paintingExtent(const DeprecatedPaintLayer* rootLayer, const LayoutRect& paintDirtyRect, GlobalPaintFlags);
void appendSingleFragmentIgnoringPagination(DeprecatedPaintLayerFragments&, const DeprecatedPaintLayer* rootLayer, const LayoutRect& dirtyRect, ClipRectsCacheSlot, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize, ShouldRespectOverflowClip = RespectOverflowClip, const LayoutPoint* offsetFromRoot = 0, const LayoutSize& subPixelAccumulation = LayoutSize()); void appendSingleFragmentIgnoringPagination(DeprecatedPaintLayerFragments&, const DeprecatedPaintLayer* rootLayer, const LayoutRect& dirtyRect, ClipRectsCacheSlot, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize, ShouldRespectOverflowClip = RespectOverflowClip, const LayoutPoint* offsetFromRoot = 0, const LayoutSize& subPixelAccumulation = LayoutSize());
void collectFragments(DeprecatedPaintLayerFragments&, const DeprecatedPaintLayer* rootLayer, const LayoutRect& dirtyRect, void collectFragments(DeprecatedPaintLayerFragments&, const DeprecatedPaintLayer* rootLayer, const LayoutRect& dirtyRect,
ClipRectsCacheSlot, OverlayScrollbarSizeRelevancy inOverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize, ClipRectsCacheSlot, OverlayScrollbarSizeRelevancy inOverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize,
...@@ -535,7 +535,7 @@ public: ...@@ -535,7 +535,7 @@ public:
}; };
static LayoutRect transparencyClipBox(const DeprecatedPaintLayer*, const DeprecatedPaintLayer* rootLayer, TransparencyClipBoxBehavior transparencyBehavior, static LayoutRect transparencyClipBox(const DeprecatedPaintLayer*, const DeprecatedPaintLayer* rootLayer, TransparencyClipBoxBehavior transparencyBehavior,
TransparencyClipBoxMode transparencyMode, const LayoutSize& subPixelAccumulation, GlobalPaintFlags = GlobalPaintNormalPhase); TransparencyClipBoxMode transparencyMode, GlobalPaintFlags = GlobalPaintNormalPhase);
private: private:
// Bounding box in the coordinates of this layer. // Bounding box in the coordinates of this layer.
......
...@@ -219,7 +219,7 @@ void DeprecatedPaintLayerPainter::paintLayerContents(GraphicsContext* context, c ...@@ -219,7 +219,7 @@ void DeprecatedPaintLayerPainter::paintLayerContents(GraphicsContext* context, c
bool shouldCompositeForBlendMode = (!m_paintLayer.layoutObject()->isDocumentElement() || m_paintLayer.layoutObject()->isSVGRoot()) && m_paintLayer.stackingNode()->isStackingContext() && m_paintLayer.hasNonIsolatedDescendantWithBlendMode(); bool shouldCompositeForBlendMode = (!m_paintLayer.layoutObject()->isDocumentElement() || m_paintLayer.layoutObject()->isSVGRoot()) && m_paintLayer.stackingNode()->isStackingContext() && m_paintLayer.hasNonIsolatedDescendantWithBlendMode();
if (shouldCompositeForBlendMode || m_paintLayer.paintsWithTransparency(paintingInfo.globalPaintFlags())) { if (shouldCompositeForBlendMode || m_paintLayer.paintsWithTransparency(paintingInfo.globalPaintFlags())) {
clipRecorder.emplace(*context, *m_paintLayer.layoutObject(), DisplayItem::TransparencyClip, clipRecorder.emplace(*context, *m_paintLayer.layoutObject(), DisplayItem::TransparencyClip,
m_paintLayer.paintingExtent(paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.subPixelAccumulation, paintingInfo.globalPaintFlags()), m_paintLayer.paintingExtent(paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.globalPaintFlags()),
&paintingInfo, LayoutPoint(), paintFlags); &paintingInfo, LayoutPoint(), paintFlags);
compositingRecorder.emplace(*context, *m_paintLayer.layoutObject(), compositingRecorder.emplace(*context, *m_paintLayer.layoutObject(),
...@@ -351,7 +351,7 @@ void DeprecatedPaintLayerPainter::paintLayerWithTransform(GraphicsContext* conte ...@@ -351,7 +351,7 @@ void DeprecatedPaintLayerPainter::paintLayerWithTransform(GraphicsContext* conte
ShouldRespectOverflowClip respectOverflowClip = shouldRespectOverflowClip(paintFlags, m_paintLayer.layoutObject()); ShouldRespectOverflowClip respectOverflowClip = shouldRespectOverflowClip(paintFlags, m_paintLayer.layoutObject());
// Calculate the transformed bounding box in the current coordinate space, to figure out // Calculate the transformed bounding box in the current coordinate space, to figure out
// which fragmentainers (e.g. columns) we need to visit. // which fragmentainers (e.g. columns) we need to visit.
LayoutRect transformedExtent = DeprecatedPaintLayer::transparencyClipBox(&m_paintLayer, paginationLayer, DeprecatedPaintLayer::PaintingTransparencyClipBox, DeprecatedPaintLayer::RootOfTransparencyClipBox, paintingInfo.subPixelAccumulation, paintingInfo.globalPaintFlags()); LayoutRect transformedExtent = DeprecatedPaintLayer::transparencyClipBox(&m_paintLayer, paginationLayer, DeprecatedPaintLayer::PaintingTransparencyClipBox, DeprecatedPaintLayer::RootOfTransparencyClipBox, paintingInfo.globalPaintFlags());
// FIXME: we don't check if paginationLayer is within paintingInfo.rootLayer here. // FIXME: we don't check if paginationLayer is within paintingInfo.rootLayer here.
paginationLayer->collectFragments(fragments, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, cacheSlot, IgnoreOverlayScrollbarSize, respectOverflowClip, 0, paintingInfo.subPixelAccumulation, &transformedExtent); paginationLayer->collectFragments(fragments, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, cacheSlot, IgnoreOverlayScrollbarSize, respectOverflowClip, 0, paintingInfo.subPixelAccumulation, &transformedExtent);
} else { } else {
......
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