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:
WebkitTextInClipProperty = 941,
WebkitTextInColorProperty = 942,
HeaderValueNotMatchingRFC7230 = 943,
ClipPathOfPositionedElement = 944,
ClipCssOfPositionedElement = 945,
// Add new features immediately above this line. Don't change assigned
// numbers of any item, and don't reuse removed slots.
......
......@@ -591,6 +591,7 @@ bool HTMLCanvasElement::originClean() const
bool HTMLCanvasElement::shouldAccelerate(const IntSize& size) const
{
fprintf(stderr, "shouldAccelerate?\n");
if (m_context && !m_context->is2d())
return false;
......
......@@ -38,11 +38,13 @@ class ClipRect {
public:
ClipRect()
: m_hasRadius(false)
, m_isClippedByClipCss(false)
{ }
ClipRect(const LayoutRect& rect)
: m_rect(rect)
, m_hasRadius(false)
, m_isClippedByClipCss(false)
{ }
const LayoutRect& rect() const { return m_rect; }
......@@ -68,9 +70,14 @@ public:
bool isEmpty() const { return m_rect.isEmpty(); }
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:
LayoutRect m_rect;
bool m_hasRadius;
bool m_isClippedByClipCss;
};
inline ClipRect intersection(const ClipRect& a, const ClipRect& b)
......
......@@ -65,6 +65,7 @@ static void adjustClipRectsForChildren(const LayoutObject& layoutObject, ClipRec
clipRects.setOverflowClipRect(clipRects.posClipRect());
}
}
static void applyClipRects(const ClipRectsContext& context, LayoutObject& layoutObject, LayoutPoint offset, ClipRects& clipRects)
{
ASSERT(layoutObject.hasOverflowClip() || layoutObject.hasClip());
......@@ -83,9 +84,10 @@ static void applyClipRects(const ClipRectsContext& context, LayoutObject& layout
}
if (layoutObject.hasClip()) {
LayoutRect newClip = toLayoutBox(layoutObject).clipRect(offset);
clipRects.setPosClipRect(intersection(newClip, clipRects.posClipRect()));
clipRects.setOverflowClipRect(intersection(newClip, clipRects.overflowClipRect()));
clipRects.setFixedClipRect(intersection(newClip, clipRects.fixedClipRect()));
clipRects.setPosClipRect(intersection(newClip, clipRects.posClipRect()).setIsClippedByClipCss());
clipRects.setOverflowClipRect(intersection(newClip, clipRects.overflowClipRect()).setIsClippedByClipCss());
clipRects.setFixedClipRect(intersection(newClip, clipRects.fixedClipRect()).setIsClippedByClipCss());
}
}
......@@ -260,8 +262,11 @@ void DeprecatedPaintLayerClipper::calculateRects(const ClipRectsContext& context
// Clip applies to *us* as well, so go ahead and update the damageRect.
LayoutRect newPosClip = toLayoutBox(m_layoutObject).clipRect(offset);
backgroundRect.intersect(newPosClip);
backgroundRect.setIsClippedByClipCss();
foregroundRect.intersect(newPosClip);
foregroundRect.setIsClippedByClipCss();
outlineRect.intersect(newPosClip);
outlineRect.setIsClippedByClipCss();
}
}
......
......@@ -120,7 +120,7 @@ void DeprecatedPaintLayerPainter::paintLayerContentsAndReflection(GraphicsContex
class ClipPathHelper {
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)
: m_resourceClipper(0), m_paintLayer(paintLayer), m_context(context)
{
......@@ -134,6 +134,8 @@ public:
m_clipperState = SVGClipPainter::ClipperNotApplied;
paintingInfo.ancestorHasClipPathClipping = true;
ASSERT(style.clipPath());
if (style.clipPath()->type() == ClipPathOperation::SHAPE) {
ShapeClipPathOperation* clipPath = toShapeClipPathOperation(style.clipPath());
......@@ -178,7 +180,7 @@ private:
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(!(paintFlags & PaintLayerAppliedTransform));
......@@ -203,6 +205,8 @@ void DeprecatedPaintLayerPainter::paintLayerContents(GraphicsContext* context, c
if (paintFlags & PaintLayerPaintingRootBackgroundOnly && !m_paintLayer.layoutObject()->isLayoutView() && !m_paintLayer.layoutObject()->isDocumentElement())
return;
DeprecatedPaintLayerPaintingInfo paintingInfo = paintingInfoArg;
// Ensure our lists are up-to-date.
m_paintLayer.stackingNode()->updateLayerListsIfNeeded();
......@@ -217,6 +221,9 @@ void DeprecatedPaintLayerPainter::paintLayerContents(GraphicsContext* context, c
LayoutRect rootRelativeBounds;
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,
// so they are nested properly.
ClipPathHelper clipPathHelper(context, m_paintLayer, paintingInfo, rootRelativeBounds, rootRelativeBoundsComputed, offsetFromRoot, paintFlags);
......@@ -384,8 +391,11 @@ void DeprecatedPaintLayerPainter::paintLayerWithTransform(GraphicsContext* conte
clipRectForFragment.intersect(fragment.backgroundRect);
if (clipRectForFragment.isEmpty())
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);
}
}
paintFragmentByApplyingTransform(context, paintingInfo, paintFlags, fragment.paginationOffset);
......@@ -409,6 +419,7 @@ void DeprecatedPaintLayerPainter::paintFragmentByApplyingTransform(GraphicsConte
// 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(),
adjustedSubPixelAccumulation, paintingInfo.paintingRoot);
transformedPaintingInfo.ancestorHasClipPathClipping = paintingInfo.ancestorHasClipPathClipping;
paintLayerContentsAndReflection(context, transformedPaintingInfo, paintFlags, ForceSingleFragment);
}
......
......@@ -85,6 +85,7 @@ struct DeprecatedPaintLayerPaintingInfo {
, paintDirtyRect(inDirtyRect)
, subPixelAccumulation(inSubPixelAccumulation)
, clipToDirtyRect(true)
, ancestorHasClipPathClipping(false)
, m_globalPaintFlags(globalPaintFlags)
{ }
......@@ -97,6 +98,7 @@ struct DeprecatedPaintLayerPaintingInfo {
LayoutSize subPixelAccumulation;
IntSize scrollOffsetAccumulation;
bool clipToDirtyRect;
bool ancestorHasClipPathClipping;
private:
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