Commit d0389c94 authored by chrishtr@chromium.org's avatar chrishtr@chromium.org

Add a UseCounter for clip CSS or -webkit-clip-path that clips positioned descendants.

BUG=527617

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

git-svn-id: svn://svn.chromium.org/blink/trunk@201840 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 7d8d34d7
PASS internals.isUseCounted(document, ClipPathOfPositionedElement) is true
PASS internals.isUseCounted(document, ClipCssOfPositionedElement) is true
PASS successfullyParsed is true
TEST COMPLETE
<!doctype HTML>
<style>
#scroller {
width: 400px;
height: 300px;
overflow: scroll;
position: relative;
}
#clipper {
position: absolute;
left: 50px;
top: 250px;
width: 300px;
height: 200px;
border: 5px dotted black;
clip: rect(0px, 310px, 210px, 0px);
-webkit-clip-path: polygon(626px 463px,765px 236px,687px 31px,271px 100px,70px 10px,49px 250px,133px 406px,374px 462px,529px 393px);
height: 2000px;
pointer-events: none;
}
#fixed {
position: fixed;
z-index: -1;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: blue;
}
</style>
<div id="scroller">
<div id="clipper">
<div id="fixed"></div>
</div>
</div>
<script src="../../resources/js-test.js"></script>
<script>
// These are from UseCounter.h
var ClipPathOfPositionedElement = 944;
var ClipCssOfPositionedElement = 945;
window.jsTestIsAsync = true;
if (window.testRunner) {
window.testRunner.layoutAndPaintAsyncThen(function() {
if (window.internals) {
shouldBeTrue('internals.isUseCounted(document, ClipPathOfPositionedElement)');
shouldBeTrue('internals.isUseCounted(document, ClipCssOfPositionedElement)');
finishJSTest();
}
});
}
</script>
\ No newline at end of file
...@@ -837,6 +837,8 @@ public: ...@@ -837,6 +837,8 @@ public:
WebkitTextInClipProperty = 941, WebkitTextInClipProperty = 941,
WebkitTextInColorProperty = 942, WebkitTextInColorProperty = 942,
HeaderValueNotMatchingRFC7230 = 943, HeaderValueNotMatchingRFC7230 = 943,
ClipPathOfPositionedElement = 944,
ClipCssOfPositionedElement = 945,
// Add new features immediately above this line. Don't change assigned // Add new features immediately above this line. Don't change assigned
// numbers of any item, and don't reuse removed slots. // numbers of any item, and don't reuse removed slots.
......
...@@ -591,6 +591,7 @@ bool HTMLCanvasElement::originClean() const ...@@ -591,6 +591,7 @@ bool HTMLCanvasElement::originClean() const
bool HTMLCanvasElement::shouldAccelerate(const IntSize& size) const bool HTMLCanvasElement::shouldAccelerate(const IntSize& size) const
{ {
fprintf(stderr, "shouldAccelerate?\n");
if (m_context && !m_context->is2d()) if (m_context && !m_context->is2d())
return false; return false;
......
...@@ -38,11 +38,13 @@ class ClipRect { ...@@ -38,11 +38,13 @@ class ClipRect {
public: public:
ClipRect() ClipRect()
: m_hasRadius(false) : m_hasRadius(false)
, m_isClippedByClipCss(false)
{ } { }
ClipRect(const LayoutRect& rect) ClipRect(const LayoutRect& rect)
: m_rect(rect) : m_rect(rect)
, m_hasRadius(false) , m_hasRadius(false)
, m_isClippedByClipCss(false)
{ } { }
const LayoutRect& rect() const { return m_rect; } const LayoutRect& rect() const { return m_rect; }
...@@ -68,9 +70,14 @@ public: ...@@ -68,9 +70,14 @@ public:
bool isEmpty() const { return m_rect.isEmpty(); } bool isEmpty() const { return m_rect.isEmpty(); }
bool intersects(const HitTestLocation&) const; bool intersects(const HitTestLocation&) const;
// These have no semantic use. They are used for use-counting.
bool isClippedByClipCss() const { return m_isClippedByClipCss; }
ClipRect& setIsClippedByClipCss() { m_isClippedByClipCss = true; return *this; }
private: private:
LayoutRect m_rect; LayoutRect m_rect;
bool m_hasRadius; bool m_hasRadius;
bool m_isClippedByClipCss;
}; };
inline ClipRect intersection(const ClipRect& a, const ClipRect& b) inline ClipRect intersection(const ClipRect& a, const ClipRect& b)
......
...@@ -65,6 +65,7 @@ static void adjustClipRectsForChildren(const LayoutObject& layoutObject, ClipRec ...@@ -65,6 +65,7 @@ static void adjustClipRectsForChildren(const LayoutObject& layoutObject, ClipRec
clipRects.setOverflowClipRect(clipRects.posClipRect()); clipRects.setOverflowClipRect(clipRects.posClipRect());
} }
} }
static void applyClipRects(const ClipRectsContext& context, LayoutObject& layoutObject, LayoutPoint offset, ClipRects& clipRects) static void applyClipRects(const ClipRectsContext& context, LayoutObject& layoutObject, LayoutPoint offset, ClipRects& clipRects)
{ {
ASSERT(layoutObject.hasOverflowClip() || layoutObject.hasClip()); ASSERT(layoutObject.hasOverflowClip() || layoutObject.hasClip());
...@@ -83,9 +84,10 @@ static void applyClipRects(const ClipRectsContext& context, LayoutObject& layout ...@@ -83,9 +84,10 @@ static void applyClipRects(const ClipRectsContext& context, LayoutObject& layout
} }
if (layoutObject.hasClip()) { if (layoutObject.hasClip()) {
LayoutRect newClip = toLayoutBox(layoutObject).clipRect(offset); LayoutRect newClip = toLayoutBox(layoutObject).clipRect(offset);
clipRects.setPosClipRect(intersection(newClip, clipRects.posClipRect())); clipRects.setPosClipRect(intersection(newClip, clipRects.posClipRect()).setIsClippedByClipCss());
clipRects.setOverflowClipRect(intersection(newClip, clipRects.overflowClipRect())); clipRects.setOverflowClipRect(intersection(newClip, clipRects.overflowClipRect()).setIsClippedByClipCss());
clipRects.setFixedClipRect(intersection(newClip, clipRects.fixedClipRect())); clipRects.setFixedClipRect(intersection(newClip, clipRects.fixedClipRect()).setIsClippedByClipCss());
} }
} }
...@@ -260,8 +262,11 @@ void DeprecatedPaintLayerClipper::calculateRects(const ClipRectsContext& context ...@@ -260,8 +262,11 @@ void DeprecatedPaintLayerClipper::calculateRects(const ClipRectsContext& context
// Clip applies to *us* as well, so go ahead and update the damageRect. // Clip applies to *us* as well, so go ahead and update the damageRect.
LayoutRect newPosClip = toLayoutBox(m_layoutObject).clipRect(offset); LayoutRect newPosClip = toLayoutBox(m_layoutObject).clipRect(offset);
backgroundRect.intersect(newPosClip); backgroundRect.intersect(newPosClip);
backgroundRect.setIsClippedByClipCss();
foregroundRect.intersect(newPosClip); foregroundRect.intersect(newPosClip);
foregroundRect.setIsClippedByClipCss();
outlineRect.intersect(newPosClip); outlineRect.intersect(newPosClip);
outlineRect.setIsClippedByClipCss();
} }
} }
......
...@@ -120,7 +120,7 @@ void DeprecatedPaintLayerPainter::paintLayerContentsAndReflection(GraphicsContex ...@@ -120,7 +120,7 @@ void DeprecatedPaintLayerPainter::paintLayerContentsAndReflection(GraphicsContex
class ClipPathHelper { class ClipPathHelper {
public: public:
ClipPathHelper(GraphicsContext* context, const DeprecatedPaintLayer& paintLayer, const DeprecatedPaintLayerPaintingInfo& paintingInfo, LayoutRect& rootRelativeBounds, bool& rootRelativeBoundsComputed, ClipPathHelper(GraphicsContext* context, const DeprecatedPaintLayer& paintLayer, DeprecatedPaintLayerPaintingInfo& paintingInfo, LayoutRect& rootRelativeBounds, bool& rootRelativeBoundsComputed,
const LayoutPoint& offsetFromRoot, PaintLayerFlags paintFlags) const LayoutPoint& offsetFromRoot, PaintLayerFlags paintFlags)
: m_resourceClipper(0), m_paintLayer(paintLayer), m_context(context) : m_resourceClipper(0), m_paintLayer(paintLayer), m_context(context)
{ {
...@@ -134,6 +134,8 @@ public: ...@@ -134,6 +134,8 @@ public:
m_clipperState = SVGClipPainter::ClipperNotApplied; m_clipperState = SVGClipPainter::ClipperNotApplied;
paintingInfo.ancestorHasClipPathClipping = true;
ASSERT(style.clipPath()); ASSERT(style.clipPath());
if (style.clipPath()->type() == ClipPathOperation::SHAPE) { if (style.clipPath()->type() == ClipPathOperation::SHAPE) {
ShapeClipPathOperation* clipPath = toShapeClipPathOperation(style.clipPath()); ShapeClipPathOperation* clipPath = toShapeClipPathOperation(style.clipPath());
...@@ -178,7 +180,7 @@ private: ...@@ -178,7 +180,7 @@ private:
GraphicsContext* m_context; GraphicsContext* m_context;
}; };
void DeprecatedPaintLayerPainter::paintLayerContents(GraphicsContext* context, const DeprecatedPaintLayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags, FragmentPolicy fragmentPolicy) void DeprecatedPaintLayerPainter::paintLayerContents(GraphicsContext* context, const DeprecatedPaintLayerPaintingInfo& paintingInfoArg, PaintLayerFlags paintFlags, FragmentPolicy fragmentPolicy)
{ {
ASSERT(m_paintLayer.isSelfPaintingLayer() || m_paintLayer.hasSelfPaintingLayerDescendant()); ASSERT(m_paintLayer.isSelfPaintingLayer() || m_paintLayer.hasSelfPaintingLayerDescendant());
ASSERT(!(paintFlags & PaintLayerAppliedTransform)); ASSERT(!(paintFlags & PaintLayerAppliedTransform));
...@@ -203,6 +205,8 @@ void DeprecatedPaintLayerPainter::paintLayerContents(GraphicsContext* context, c ...@@ -203,6 +205,8 @@ void DeprecatedPaintLayerPainter::paintLayerContents(GraphicsContext* context, c
if (paintFlags & PaintLayerPaintingRootBackgroundOnly && !m_paintLayer.layoutObject()->isLayoutView() && !m_paintLayer.layoutObject()->isDocumentElement()) if (paintFlags & PaintLayerPaintingRootBackgroundOnly && !m_paintLayer.layoutObject()->isLayoutView() && !m_paintLayer.layoutObject()->isDocumentElement())
return; return;
DeprecatedPaintLayerPaintingInfo paintingInfo = paintingInfoArg;
// Ensure our lists are up-to-date. // Ensure our lists are up-to-date.
m_paintLayer.stackingNode()->updateLayerListsIfNeeded(); m_paintLayer.stackingNode()->updateLayerListsIfNeeded();
...@@ -217,6 +221,9 @@ void DeprecatedPaintLayerPainter::paintLayerContents(GraphicsContext* context, c ...@@ -217,6 +221,9 @@ void DeprecatedPaintLayerPainter::paintLayerContents(GraphicsContext* context, c
LayoutRect rootRelativeBounds; LayoutRect rootRelativeBounds;
bool rootRelativeBoundsComputed = false; bool rootRelativeBoundsComputed = false;
if (paintingInfo.ancestorHasClipPathClipping && m_paintLayer.layoutObject()->style()->position() != StaticPosition)
UseCounter::count(m_paintLayer.layoutObject()->document(), UseCounter::ClipPathOfPositionedElement);
// These helpers output clip and compositing operations using a RAII pattern. Stack-allocated-varibles are destructed in the reverse order of construction, // These helpers output clip and compositing operations using a RAII pattern. Stack-allocated-varibles are destructed in the reverse order of construction,
// so they are nested properly. // so they are nested properly.
ClipPathHelper clipPathHelper(context, m_paintLayer, paintingInfo, rootRelativeBounds, rootRelativeBoundsComputed, offsetFromRoot, paintFlags); ClipPathHelper clipPathHelper(context, m_paintLayer, paintingInfo, rootRelativeBounds, rootRelativeBoundsComputed, offsetFromRoot, paintFlags);
...@@ -384,9 +391,12 @@ void DeprecatedPaintLayerPainter::paintLayerWithTransform(GraphicsContext* conte ...@@ -384,9 +391,12 @@ void DeprecatedPaintLayerPainter::paintLayerWithTransform(GraphicsContext* conte
clipRectForFragment.intersect(fragment.backgroundRect); clipRectForFragment.intersect(fragment.backgroundRect);
if (clipRectForFragment.isEmpty()) if (clipRectForFragment.isEmpty())
continue; continue;
if (needsToClip(paintingInfo, clipRectForFragment)) if (needsToClip(paintingInfo, clipRectForFragment)) {
if (m_paintLayer.layoutObject()->style()->position() != StaticPosition && clipRectForFragment.isClippedByClipCss())
UseCounter::count(m_paintLayer.layoutObject()->document(), UseCounter::ClipCssOfPositionedElement);
clipRecorder.emplace(*context, *parentLayer->layoutObject(), DisplayItem::ClipLayerParent, clipRectForFragment, &paintingInfo, fragment.paginationOffset, paintFlags); clipRecorder.emplace(*context, *parentLayer->layoutObject(), DisplayItem::ClipLayerParent, clipRectForFragment, &paintingInfo, fragment.paginationOffset, paintFlags);
} }
}
paintFragmentByApplyingTransform(context, paintingInfo, paintFlags, fragment.paginationOffset); paintFragmentByApplyingTransform(context, paintingInfo, paintFlags, fragment.paginationOffset);
} }
...@@ -409,6 +419,7 @@ void DeprecatedPaintLayerPainter::paintFragmentByApplyingTransform(GraphicsConte ...@@ -409,6 +419,7 @@ void DeprecatedPaintLayerPainter::paintFragmentByApplyingTransform(GraphicsConte
// Now do a paint with the root layer shifted to be us. // Now do a paint with the root layer shifted to be us.
DeprecatedPaintLayerPaintingInfo transformedPaintingInfo(&m_paintLayer, LayoutRect(enclosingIntRect(transform.inverse().mapRect(paintingInfo.paintDirtyRect))), paintingInfo.globalPaintFlags(), DeprecatedPaintLayerPaintingInfo transformedPaintingInfo(&m_paintLayer, LayoutRect(enclosingIntRect(transform.inverse().mapRect(paintingInfo.paintDirtyRect))), paintingInfo.globalPaintFlags(),
adjustedSubPixelAccumulation, paintingInfo.paintingRoot); adjustedSubPixelAccumulation, paintingInfo.paintingRoot);
transformedPaintingInfo.ancestorHasClipPathClipping = paintingInfo.ancestorHasClipPathClipping;
paintLayerContentsAndReflection(context, transformedPaintingInfo, paintFlags, ForceSingleFragment); paintLayerContentsAndReflection(context, transformedPaintingInfo, paintFlags, ForceSingleFragment);
} }
......
...@@ -85,6 +85,7 @@ struct DeprecatedPaintLayerPaintingInfo { ...@@ -85,6 +85,7 @@ struct DeprecatedPaintLayerPaintingInfo {
, paintDirtyRect(inDirtyRect) , paintDirtyRect(inDirtyRect)
, subPixelAccumulation(inSubPixelAccumulation) , subPixelAccumulation(inSubPixelAccumulation)
, clipToDirtyRect(true) , clipToDirtyRect(true)
, ancestorHasClipPathClipping(false)
, m_globalPaintFlags(globalPaintFlags) , m_globalPaintFlags(globalPaintFlags)
{ } { }
...@@ -97,6 +98,7 @@ struct DeprecatedPaintLayerPaintingInfo { ...@@ -97,6 +98,7 @@ struct DeprecatedPaintLayerPaintingInfo {
LayoutSize subPixelAccumulation; LayoutSize subPixelAccumulation;
IntSize scrollOffsetAccumulation; IntSize scrollOffsetAccumulation;
bool clipToDirtyRect; bool clipToDirtyRect;
bool ancestorHasClipPathClipping;
private: private:
const GlobalPaintFlags m_globalPaintFlags; const GlobalPaintFlags m_globalPaintFlags;
......
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