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

Unified Diff: third_party/WebKit/Source/core/paint/ClipPathClipper.cpp

Issue 2738493002: Remove begin/end methods on CompositingRecorder. (Closed)
Patch Set: rm-compositingrecorder-methods: replace-default Created 3 years, 9 months 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
Index: third_party/WebKit/Source/core/paint/ClipPathClipper.cpp
diff --git a/third_party/WebKit/Source/core/paint/ClipPathClipper.cpp b/third_party/WebKit/Source/core/paint/ClipPathClipper.cpp
index bf8dd25eaedc6c1b2dd16b66078c90629e99c041..58bb12919ff0b5f86c303e23960faae416fd0dcd 100644
--- a/third_party/WebKit/Source/core/paint/ClipPathClipper.cpp
+++ b/third_party/WebKit/Source/core/paint/ClipPathClipper.cpp
@@ -4,17 +4,36 @@
#include "core/paint/ClipPathClipper.h"
+#include "core/dom/ElementTraversal.h"
#include "core/layout/svg/LayoutSVGResourceClipper.h"
+#include "core/layout/svg/SVGLayoutSupport.h"
#include "core/layout/svg/SVGResources.h"
#include "core/layout/svg/SVGResourcesCache.h"
-#include "core/paint/SVGClipPainter.h"
+#include "core/paint/LayoutObjectDrawingRecorder.h"
+#include "core/paint/PaintInfo.h"
+#include "core/paint/TransformRecorder.h"
#include "core/style/ClipPathOperation.h"
+#include "platform/graphics/paint/ClipPathDisplayItem.h"
#include "platform/graphics/paint/ClipPathRecorder.h"
+#include "platform/graphics/paint/DrawingDisplayItem.h"
+#include "platform/graphics/paint/PaintController.h"
+#include "platform/graphics/paint/PaintRecordBuilder.h"
namespace blink {
namespace {
+class SVGClipExpansionCycleHelper {
+ public:
+ SVGClipExpansionCycleHelper(LayoutSVGResourceClipper& clip) : m_clip(clip) {
+ clip.beginClipExpansion();
+ }
+ ~SVGClipExpansionCycleHelper() { m_clip.endClipExpansion(); }
+
+ private:
+ LayoutSVGResourceClipper& m_clip;
+};
+
LayoutSVGResourceClipper* resolveElementReference(
const LayoutObject& layoutObject,
const ReferenceClipPathOperation& referenceClipPathOperation) {
@@ -57,33 +76,165 @@ ClipPathClipper::ClipPathClipper(GraphicsContext& context,
m_clipperState = ClipperState::AppliedPath;
} else {
DCHECK_EQ(clipPathOperation.type(), ClipPathOperation::REFERENCE);
- LayoutSVGResourceClipper* clipper = resolveElementReference(
+ m_resourceClipper = resolveElementReference(
layoutObject, toReferenceClipPathOperation(clipPathOperation));
- if (!clipper)
+ if (!m_resourceClipper)
return;
// Compute the (conservative) bounds of the clip-path.
- FloatRect clipPathBounds = clipper->resourceBoundingBox(referenceBox);
+ FloatRect clipPathBounds =
+ m_resourceClipper->resourceBoundingBox(referenceBox);
// When SVG applies the clip, and the coordinate system is "userspace on
// use", we must explicitly pass in the offset to have the clip paint in the
// correct location. When the coordinate system is "object bounding box" the
// offset should already be accounted for in the reference box.
FloatPoint originTranslation;
- if (clipper->clipPathUnits() == SVGUnitTypes::kSvgUnitTypeUserspaceonuse) {
+ if (m_resourceClipper->clipPathUnits() ==
+ SVGUnitTypes::kSvgUnitTypeUserspaceonuse) {
clipPathBounds.moveBy(origin);
originTranslation = origin;
}
- if (!SVGClipPainter(*clipper).prepareEffect(
- layoutObject, referenceBox, clipPathBounds, originTranslation,
- context, m_clipperState))
+ if (!prepareEffect(referenceBox, clipPathBounds, originTranslation)) {
+ // Indicate there is no cleanup to do.
+ m_resourceClipper = nullptr;
return;
- m_resourceClipper = clipper;
+ }
}
}
ClipPathClipper::~ClipPathClipper() {
if (m_resourceClipper)
- SVGClipPainter(*m_resourceClipper)
- .finishEffect(m_layoutObject, m_context, m_clipperState);
+ finishEffect();
+}
+
+bool ClipPathClipper::prepareEffect(const FloatRect& targetBoundingBox,
+ const FloatRect& visualRect,
+ const FloatPoint& layerPositionOffset) {
+ DCHECK_EQ(m_clipperState, ClipperState::NotApplied);
+ SECURITY_DCHECK(!m_resourceClipper->needsLayout());
+
+ m_resourceClipper->clearInvalidationMask();
+
+ if (m_resourceClipper->hasCycle())
+ return false;
+
+ SVGClipExpansionCycleHelper inClipExpansionChange(*m_resourceClipper);
+
+ AffineTransform animatedLocalTransform =
+ toSVGClipPathElement(m_resourceClipper->element())
+ ->calculateTransform(SVGElement::IncludeMotionTransform);
+ // When drawing a clip for non-SVG elements, the CTM does not include the zoom
+ // factor. In this case, we need to apply the zoom scale explicitly - but
+ // only for clips with userSpaceOnUse units (the zoom is accounted for
+ // objectBoundingBox-resolved lengths).
+ if (!m_layoutObject.isSVG() && m_resourceClipper->clipPathUnits() ==
+ SVGUnitTypes::kSvgUnitTypeUserspaceonuse) {
+ DCHECK(m_resourceClipper->style());
+ animatedLocalTransform.scale(m_resourceClipper->style()->effectiveZoom());
+ }
+
+ // First, try to apply the clip as a clipPath.
+ Path clipPath;
+ if (m_resourceClipper->asPath(animatedLocalTransform, targetBoundingBox,
+ clipPath)) {
+ AffineTransform positionTransform;
+ positionTransform.translate(layerPositionOffset.x(),
+ layerPositionOffset.y());
+ clipPath.transform(positionTransform);
+ m_clipperState = ClipperState::AppliedPath;
+ m_context.getPaintController().createAndAppend<BeginClipPathDisplayItem>(
+ m_layoutObject, clipPath);
+ return true;
+ }
+
+ // Fall back to masking.
+ m_clipperState = ClipperState::AppliedMask;
+
+ // Begin compositing the clip mask.
+ m_maskClipRecorder.emplace(m_context, m_layoutObject, SkBlendMode::kSrcOver,
+ 1, &visualRect);
+ {
+ if (!drawClipAsMask(targetBoundingBox, visualRect, animatedLocalTransform,
+ layerPositionOffset)) {
+ // End the clip mask's compositor.
+ m_maskClipRecorder.reset();
+ return false;
+ }
+ }
+
+ // Masked content layer start.
+ m_maskContentRecorder.emplace(m_context, m_layoutObject, SkBlendMode::kSrcIn,
+ 1, &visualRect);
+
+ return true;
+}
+
+bool ClipPathClipper::drawClipAsMask(const FloatRect& targetBoundingBox,
+ const FloatRect& targetVisualRect,
+ const AffineTransform& localTransform,
+ const FloatPoint& layerPositionOffset) {
+ if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(
+ m_context, m_layoutObject, DisplayItem::kSVGClip))
+ return true;
+
+ PaintRecordBuilder maskBuilder(targetVisualRect, nullptr, &m_context);
+ GraphicsContext& maskContext = maskBuilder.context();
+ {
+ TransformRecorder recorder(maskContext, m_layoutObject, localTransform);
+
+ // Apply any clip-path clipping this clipPath (nested shape/clipPath.)
+ Optional<ClipPathClipper> nestedClipPathClipper;
+ if (ClipPathOperation* clipPathOperation =
+ m_resourceClipper->styleRef().clipPath()) {
+ nestedClipPathClipper.emplace(maskContext, *clipPathOperation,
+ *m_resourceClipper, targetBoundingBox,
+ layerPositionOffset);
+ }
+
+ {
+ AffineTransform contentTransform;
+ if (m_resourceClipper->clipPathUnits() ==
+ SVGUnitTypes::kSvgUnitTypeObjectboundingbox) {
+ contentTransform.translate(targetBoundingBox.x(),
+ targetBoundingBox.y());
+ contentTransform.scaleNonUniform(targetBoundingBox.width(),
+ targetBoundingBox.height());
+ }
+ SubtreeContentTransformScope contentTransformScope(contentTransform);
+
+ TransformRecorder contentTransformRecorder(maskContext, m_layoutObject,
+ contentTransform);
+ maskContext.getPaintController().createAndAppend<DrawingDisplayItem>(
+ m_layoutObject, DisplayItem::kSVGClip,
+ m_resourceClipper->createPaintRecord());
+ }
+ }
+
+ LayoutObjectDrawingRecorder drawingRecorder(
+ m_context, m_layoutObject, DisplayItem::kSVGClip, targetVisualRect);
+ sk_sp<PaintRecord> maskPaintRecord = maskBuilder.endRecording();
+ m_context.drawRecord(maskPaintRecord.get());
+ return true;
+}
+
+void ClipPathClipper::finishEffect() {
+ switch (m_clipperState) {
+ case ClipperState::AppliedPath:
+ // Path-only clipping, no layers to restore but we need to emit an end to
+ // the clip path display item.
+ m_context.getPaintController().endItem<EndClipPathDisplayItem>(
+ m_layoutObject);
+ break;
+ case ClipperState::AppliedMask:
+ // Transfer content -> clip mask (SrcIn)
+ m_maskContentRecorder.reset();
+
+ // Transfer clip mask -> bg (SrcOver)
+ m_maskClipRecorder.reset();
+ break;
+ case ClipperState::NotApplied:
danakj 2017/03/07 15:46:57 I made one little change here since I noticed it.
+ NOTREACHED();
+ break;
+ }
}
} // namespace blink
« no previous file with comments | « third_party/WebKit/Source/core/paint/ClipPathClipper.h ('k') | third_party/WebKit/Source/core/paint/SVGClipPainter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698