Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(548)

Unified Diff: third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceClipper.cpp

Issue 2560513002: Unify predicates for elements "contributing" to a <clipPath> (Closed)
Patch Set: Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | third_party/WebKit/Source/core/svg/SVGUseElement.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceClipper.cpp
diff --git a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceClipper.cpp b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceClipper.cpp
index 9ed7c72d32a89996c6a5310e3624e0244119abb8..d26df1fe523da7d7444da8e06cd35d18feb16988 100644
--- a/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceClipper.cpp
+++ b/third_party/WebKit/Source/core/layout/svg/LayoutSVGResourceClipper.cpp
@@ -22,20 +22,73 @@
#include "core/layout/svg/LayoutSVGResourceClipper.h"
-#include "core/SVGNames.h"
#include "core/dom/ElementTraversal.h"
#include "core/layout/HitTestResult.h"
#include "core/layout/svg/SVGLayoutSupport.h"
#include "core/paint/PaintInfo.h"
#include "core/svg/SVGGeometryElement.h"
#include "core/svg/SVGUseElement.h"
-#include "platform/RuntimeEnabledFeatures.h"
#include "platform/graphics/paint/SkPictureBuilder.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/pathops/SkPathOps.h"
namespace blink {
+namespace {
+
+bool requiresMask(const SVGElement& childElement) {
+ // TODO(fs): This needs to special-case <use> in a way similar to
+ // contributesToClip. (crbug.com/604677)
+ LayoutObject* layoutObject = childElement.layoutObject();
+ DCHECK(layoutObject);
+ // Only basic shapes or paths are supported for direct clipping. We need to
+ // fallback to masking for texts.
+ if (layoutObject->isSVGText())
+ return true;
+ // Current shape in clip-path gets clipped too. Fallback to masking.
+ return layoutObject->styleRef().clipPath();
+}
+
+bool contributesToClip(const SVGGraphicsElement& element) {
+ const LayoutObject* layoutObject = element.layoutObject();
+ if (!layoutObject)
+ return false;
+ const ComputedStyle& style = layoutObject->styleRef();
+ if (style.display() == EDisplay::None ||
+ style.visibility() != EVisibility::Visible)
+ return false;
+ // Only shapes, paths and texts are allowed for clipping.
+ return layoutObject->isSVGShape() || layoutObject->isSVGText();
+}
+
+bool contributesToClip(const SVGElement& element) {
+ // <use> within <clipPath> have a restricted content model.
+ // (https://drafts.fxtf.org/css-masking-1/#ClipPathElement)
+ if (isSVGUseElement(element)) {
+ const LayoutObject* useLayoutObject = element.layoutObject();
+ if (!useLayoutObject ||
+ useLayoutObject->styleRef().display() == EDisplay::None)
+ return false;
+ const SVGGraphicsElement* clippingElement =
+ toSVGUseElement(element).visibleTargetGraphicsElementForClipping();
+ if (!clippingElement)
+ return false;
+ return contributesToClip(*clippingElement);
+ }
+ if (!element.isSVGGraphicsElement())
+ return false;
+ return contributesToClip(toSVGGraphicsElement(element));
+}
+
+void pathFromElement(const SVGElement& element, Path& clipPath) {
+ if (isSVGGeometryElement(element))
+ toSVGGeometryElement(element).toClipPath(clipPath);
+ else if (isSVGUseElement(element))
+ toSVGUseElement(element).toClipPath(clipPath);
+}
+
+} // namespace
+
LayoutSVGResourceClipper::LayoutSVGResourceClipper(SVGClipPathElement* node)
: LayoutSVGResourceContainer(node), m_inClipExpansion(false) {}
@@ -72,40 +125,19 @@ bool LayoutSVGResourceClipper::calculateClipContentPathIfNeeded() {
bool usingBuilder = false;
SkOpBuilder clipPathBuilder;
- for (SVGElement* childElement = Traversal<SVGElement>::firstChild(*element());
- childElement;
- childElement = Traversal<SVGElement>::nextSibling(*childElement)) {
- LayoutObject* childLayoutObject = childElement->layoutObject();
- if (!childLayoutObject)
- continue;
- // Only shapes or paths are supported for direct clipping. We need to
- // fallback to masking for texts.
- if (childLayoutObject->isSVGText()) {
- m_clipContentPath.clear();
- return false;
- }
- if (!childElement->isSVGGraphicsElement())
- continue;
-
- const ComputedStyle* style = childLayoutObject->style();
- if (!style || style->display() == EDisplay::None ||
- (style->visibility() != EVisibility::Visible &&
- !isSVGUseElement(*childElement)))
+ for (const SVGElement& childElement :
+ Traversal<SVGElement>::childrenOf(*element())) {
+ if (!contributesToClip(childElement))
continue;
- // Current shape in clip-path gets clipped too. Fallback to masking.
- if (style->clipPath()) {
+ if (requiresMask(childElement)) {
m_clipContentPath.clear();
return false;
}
// First clip shape.
if (m_clipContentPath.isEmpty()) {
- if (isSVGGeometryElement(childElement))
- toSVGGeometryElement(childElement)->toClipPath(m_clipContentPath);
- else if (isSVGUseElement(childElement))
- toSVGUseElement(childElement)->toClipPath(m_clipContentPath);
-
+ pathFromElement(childElement, m_clipContentPath);
continue;
}
@@ -125,10 +157,7 @@ bool LayoutSVGResourceClipper::calculateClipContentPathIfNeeded() {
}
Path subPath;
- if (isSVGGeometryElement(childElement))
- toSVGGeometryElement(childElement)->toClipPath(subPath);
- else if (isSVGUseElement(childElement))
- toSVGUseElement(childElement)->toClipPath(subPath);
+ pathFromElement(childElement, subPath);
clipPathBuilder.add(subPath.getSkPath(), kUnion_SkPathOp);
}
@@ -177,49 +206,23 @@ sk_sp<const SkPicture> LayoutSVGResourceClipper::createContentPicture() {
FloatRect bounds = strokeBoundingBox();
SkPictureBuilder pictureBuilder(bounds, nullptr, nullptr);
-
- for (SVGElement* childElement = Traversal<SVGElement>::firstChild(*element());
- childElement;
- childElement = Traversal<SVGElement>::nextSibling(*childElement)) {
- LayoutObject* layoutObject = childElement->layoutObject();
- if (!layoutObject)
- continue;
-
- const ComputedStyle* style = layoutObject->style();
- if (!style || style->display() == EDisplay::None ||
- (style->visibility() != EVisibility::Visible &&
- !isSVGUseElement(*childElement)))
+ // Switch to a paint behavior where all children of this <clipPath> will be
+ // laid out using special constraints:
+ // - fill-opacity/stroke-opacity/opacity set to 1
+ // - masker/filter not applied when laying out the children
+ // - fill is set to the initial fill paint server (solid, black)
+ // - stroke is set to the initial stroke paint server (none)
+ PaintInfo info(pictureBuilder.context(), LayoutRect::infiniteIntRect(),
+ PaintPhaseForeground, GlobalPaintNormalPhase,
+ PaintLayerPaintingRenderingClipPathAsMask);
+
+ for (const SVGElement& childElement :
+ Traversal<SVGElement>::childrenOf(*element())) {
+ if (!contributesToClip(childElement))
continue;
-
- bool isUseElement = isSVGUseElement(*childElement);
- if (isUseElement) {
- const SVGGraphicsElement* clippingElement =
- toSVGUseElement(*childElement)
- .visibleTargetGraphicsElementForClipping();
- if (!clippingElement)
- continue;
-
- layoutObject = clippingElement->layoutObject();
- if (!layoutObject)
- continue;
- }
-
- // Only shapes, paths and texts are allowed for clipping.
- if (!layoutObject->isSVGShape() && !layoutObject->isSVGText())
- continue;
-
- if (isUseElement)
- layoutObject = childElement->layoutObject();
-
- // Switch to a paint behavior where all children of this <clipPath> will be
- // laid out using special constraints:
- // - fill-opacity/stroke-opacity/opacity set to 1
- // - masker/filter not applied when laying out the children
- // - fill is set to the initial fill paint server (solid, black)
- // - stroke is set to the initial stroke paint server (none)
- PaintInfo info(pictureBuilder.context(), LayoutRect::infiniteIntRect(),
- PaintPhaseForeground, GlobalPaintNormalPhase,
- PaintLayerPaintingRenderingClipPathAsMask);
+ // Use the LayoutObject of the direct child even if it is a <use>. In that
+ // case, we will paint the targeted element indirectly.
+ const LayoutObject* layoutObject = childElement.layoutObject();
layoutObject->paint(info, IntPoint());
}
@@ -230,25 +233,11 @@ sk_sp<const SkPicture> LayoutSVGResourceClipper::createContentPicture() {
void LayoutSVGResourceClipper::calculateLocalClipBounds() {
// This is a rough heuristic to appraise the clip size and doesn't consider
// clip on clip.
- for (SVGElement* childElement = Traversal<SVGElement>::firstChild(*element());
- childElement;
- childElement = Traversal<SVGElement>::nextSibling(*childElement)) {
- LayoutObject* layoutObject = childElement->layoutObject();
- if (!layoutObject)
- continue;
- if (!layoutObject->isSVGShape() && !layoutObject->isSVGText() &&
- !isSVGUseElement(*childElement))
- continue;
- const ComputedStyle* style = layoutObject->style();
- if (!style || style->display() == EDisplay::None ||
- (style->visibility() != EVisibility::Visible &&
- !isSVGUseElement(*childElement)))
+ for (const SVGElement& childElement :
+ Traversal<SVGElement>::childrenOf(*element())) {
+ if (!contributesToClip(childElement))
continue;
- if (isSVGUseElement(*childElement) &&
- !toSVGUseElement(*childElement)
- .visibleTargetGraphicsElementForClipping())
- continue;
-
+ const LayoutObject* layoutObject = childElement.layoutObject();
m_localClipBounds.unite(layoutObject->localToSVGParentTransform().mapRect(
layoutObject->visualRectInLocalSVGCoordinates()));
}
@@ -277,21 +266,16 @@ bool LayoutSVGResourceClipper::hitTestClipContent(
point = animatedLocalTransform.inverse().mapPoint(point);
- for (SVGElement* childElement = Traversal<SVGElement>::firstChild(*element());
- childElement;
- childElement = Traversal<SVGElement>::nextSibling(*childElement)) {
- LayoutObject* layoutObject = childElement->layoutObject();
- if (!layoutObject)
- continue;
- if (!layoutObject->isSVGShape() && !layoutObject->isSVGText() &&
- !isSVGUseElement(*childElement))
+ for (const SVGElement& childElement :
+ Traversal<SVGElement>::childrenOf(*element())) {
+ if (!contributesToClip(childElement))
continue;
IntPoint hitPoint;
HitTestResult result(HitTestRequest::SVGClipContent, hitPoint);
+ LayoutObject* layoutObject = childElement.layoutObject();
if (layoutObject->nodeAtFloatPoint(result, point, HitTestForeground))
return true;
}
-
return false;
}
« no previous file with comments | « no previous file | third_party/WebKit/Source/core/svg/SVGUseElement.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698