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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/paint/ClipPathClipper.h" 5 #include "core/paint/ClipPathClipper.h"
6 6
7 #include "core/dom/ElementTraversal.h"
7 #include "core/layout/svg/LayoutSVGResourceClipper.h" 8 #include "core/layout/svg/LayoutSVGResourceClipper.h"
9 #include "core/layout/svg/SVGLayoutSupport.h"
8 #include "core/layout/svg/SVGResources.h" 10 #include "core/layout/svg/SVGResources.h"
9 #include "core/layout/svg/SVGResourcesCache.h" 11 #include "core/layout/svg/SVGResourcesCache.h"
10 #include "core/paint/SVGClipPainter.h" 12 #include "core/paint/LayoutObjectDrawingRecorder.h"
13 #include "core/paint/PaintInfo.h"
14 #include "core/paint/TransformRecorder.h"
11 #include "core/style/ClipPathOperation.h" 15 #include "core/style/ClipPathOperation.h"
16 #include "platform/graphics/paint/ClipPathDisplayItem.h"
12 #include "platform/graphics/paint/ClipPathRecorder.h" 17 #include "platform/graphics/paint/ClipPathRecorder.h"
18 #include "platform/graphics/paint/DrawingDisplayItem.h"
19 #include "platform/graphics/paint/PaintController.h"
20 #include "platform/graphics/paint/PaintRecordBuilder.h"
13 21
14 namespace blink { 22 namespace blink {
15 23
16 namespace { 24 namespace {
17 25
26 class SVGClipExpansionCycleHelper {
27 public:
28 SVGClipExpansionCycleHelper(LayoutSVGResourceClipper& clip) : m_clip(clip) {
29 clip.beginClipExpansion();
30 }
31 ~SVGClipExpansionCycleHelper() { m_clip.endClipExpansion(); }
32
33 private:
34 LayoutSVGResourceClipper& m_clip;
35 };
36
18 LayoutSVGResourceClipper* resolveElementReference( 37 LayoutSVGResourceClipper* resolveElementReference(
19 const LayoutObject& layoutObject, 38 const LayoutObject& layoutObject,
20 const ReferenceClipPathOperation& referenceClipPathOperation) { 39 const ReferenceClipPathOperation& referenceClipPathOperation) {
21 if (layoutObject.isSVGChild()) { 40 if (layoutObject.isSVGChild()) {
22 // The reference will have been resolved in 41 // The reference will have been resolved in
23 // SVGResources::buildResources, so we can just use the LayoutObject's 42 // SVGResources::buildResources, so we can just use the LayoutObject's
24 // SVGResources. 43 // SVGResources.
25 SVGResources* resources = 44 SVGResources* resources =
26 SVGResourcesCache::cachedResourcesForLayoutObject(&layoutObject); 45 SVGResourcesCache::cachedResourcesForLayoutObject(&layoutObject);
27 return resources ? resources->clipper() : nullptr; 46 return resources ? resources->clipper() : nullptr;
(...skipping 22 matching lines...) Expand all
50 m_layoutObject(layoutObject), 69 m_layoutObject(layoutObject),
51 m_context(context) { 70 m_context(context) {
52 if (clipPathOperation.type() == ClipPathOperation::SHAPE) { 71 if (clipPathOperation.type() == ClipPathOperation::SHAPE) {
53 ShapeClipPathOperation& shape = toShapeClipPathOperation(clipPathOperation); 72 ShapeClipPathOperation& shape = toShapeClipPathOperation(clipPathOperation);
54 if (!shape.isValid()) 73 if (!shape.isValid())
55 return; 74 return;
56 m_clipPathRecorder.emplace(context, layoutObject, shape.path(referenceBox)); 75 m_clipPathRecorder.emplace(context, layoutObject, shape.path(referenceBox));
57 m_clipperState = ClipperState::AppliedPath; 76 m_clipperState = ClipperState::AppliedPath;
58 } else { 77 } else {
59 DCHECK_EQ(clipPathOperation.type(), ClipPathOperation::REFERENCE); 78 DCHECK_EQ(clipPathOperation.type(), ClipPathOperation::REFERENCE);
60 LayoutSVGResourceClipper* clipper = resolveElementReference( 79 m_resourceClipper = resolveElementReference(
61 layoutObject, toReferenceClipPathOperation(clipPathOperation)); 80 layoutObject, toReferenceClipPathOperation(clipPathOperation));
62 if (!clipper) 81 if (!m_resourceClipper)
63 return; 82 return;
64 // Compute the (conservative) bounds of the clip-path. 83 // Compute the (conservative) bounds of the clip-path.
65 FloatRect clipPathBounds = clipper->resourceBoundingBox(referenceBox); 84 FloatRect clipPathBounds =
85 m_resourceClipper->resourceBoundingBox(referenceBox);
66 // When SVG applies the clip, and the coordinate system is "userspace on 86 // When SVG applies the clip, and the coordinate system is "userspace on
67 // use", we must explicitly pass in the offset to have the clip paint in the 87 // use", we must explicitly pass in the offset to have the clip paint in the
68 // correct location. When the coordinate system is "object bounding box" the 88 // correct location. When the coordinate system is "object bounding box" the
69 // offset should already be accounted for in the reference box. 89 // offset should already be accounted for in the reference box.
70 FloatPoint originTranslation; 90 FloatPoint originTranslation;
71 if (clipper->clipPathUnits() == SVGUnitTypes::kSvgUnitTypeUserspaceonuse) { 91 if (m_resourceClipper->clipPathUnits() ==
92 SVGUnitTypes::kSvgUnitTypeUserspaceonuse) {
72 clipPathBounds.moveBy(origin); 93 clipPathBounds.moveBy(origin);
73 originTranslation = origin; 94 originTranslation = origin;
74 } 95 }
75 if (!SVGClipPainter(*clipper).prepareEffect( 96 if (!prepareEffect(referenceBox, clipPathBounds, originTranslation)) {
76 layoutObject, referenceBox, clipPathBounds, originTranslation, 97 // Indicate there is no cleanup to do.
77 context, m_clipperState)) 98 m_resourceClipper = nullptr;
78 return; 99 return;
79 m_resourceClipper = clipper; 100 }
80 } 101 }
81 } 102 }
82 103
83 ClipPathClipper::~ClipPathClipper() { 104 ClipPathClipper::~ClipPathClipper() {
84 if (m_resourceClipper) 105 if (m_resourceClipper)
85 SVGClipPainter(*m_resourceClipper) 106 finishEffect();
86 .finishEffect(m_layoutObject, m_context, m_clipperState); 107 }
108
109 bool ClipPathClipper::prepareEffect(const FloatRect& targetBoundingBox,
110 const FloatRect& visualRect,
111 const FloatPoint& layerPositionOffset) {
112 DCHECK_EQ(m_clipperState, ClipperState::NotApplied);
113 SECURITY_DCHECK(!m_resourceClipper->needsLayout());
114
115 m_resourceClipper->clearInvalidationMask();
116
117 if (m_resourceClipper->hasCycle())
118 return false;
119
120 SVGClipExpansionCycleHelper inClipExpansionChange(*m_resourceClipper);
121
122 AffineTransform animatedLocalTransform =
123 toSVGClipPathElement(m_resourceClipper->element())
124 ->calculateTransform(SVGElement::IncludeMotionTransform);
125 // When drawing a clip for non-SVG elements, the CTM does not include the zoom
126 // factor. In this case, we need to apply the zoom scale explicitly - but
127 // only for clips with userSpaceOnUse units (the zoom is accounted for
128 // objectBoundingBox-resolved lengths).
129 if (!m_layoutObject.isSVG() && m_resourceClipper->clipPathUnits() ==
130 SVGUnitTypes::kSvgUnitTypeUserspaceonuse) {
131 DCHECK(m_resourceClipper->style());
132 animatedLocalTransform.scale(m_resourceClipper->style()->effectiveZoom());
133 }
134
135 // First, try to apply the clip as a clipPath.
136 Path clipPath;
137 if (m_resourceClipper->asPath(animatedLocalTransform, targetBoundingBox,
138 clipPath)) {
139 AffineTransform positionTransform;
140 positionTransform.translate(layerPositionOffset.x(),
141 layerPositionOffset.y());
142 clipPath.transform(positionTransform);
143 m_clipperState = ClipperState::AppliedPath;
144 m_context.getPaintController().createAndAppend<BeginClipPathDisplayItem>(
145 m_layoutObject, clipPath);
146 return true;
147 }
148
149 // Fall back to masking.
150 m_clipperState = ClipperState::AppliedMask;
151
152 // Begin compositing the clip mask.
153 m_maskClipRecorder.emplace(m_context, m_layoutObject, SkBlendMode::kSrcOver,
154 1, &visualRect);
155 {
156 if (!drawClipAsMask(targetBoundingBox, visualRect, animatedLocalTransform,
157 layerPositionOffset)) {
158 // End the clip mask's compositor.
159 m_maskClipRecorder.reset();
160 return false;
161 }
162 }
163
164 // Masked content layer start.
165 m_maskContentRecorder.emplace(m_context, m_layoutObject, SkBlendMode::kSrcIn,
166 1, &visualRect);
167
168 return true;
169 }
170
171 bool ClipPathClipper::drawClipAsMask(const FloatRect& targetBoundingBox,
172 const FloatRect& targetVisualRect,
173 const AffineTransform& localTransform,
174 const FloatPoint& layerPositionOffset) {
175 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(
176 m_context, m_layoutObject, DisplayItem::kSVGClip))
177 return true;
178
179 PaintRecordBuilder maskBuilder(targetVisualRect, nullptr, &m_context);
180 GraphicsContext& maskContext = maskBuilder.context();
181 {
182 TransformRecorder recorder(maskContext, m_layoutObject, localTransform);
183
184 // Apply any clip-path clipping this clipPath (nested shape/clipPath.)
185 Optional<ClipPathClipper> nestedClipPathClipper;
186 if (ClipPathOperation* clipPathOperation =
187 m_resourceClipper->styleRef().clipPath()) {
188 nestedClipPathClipper.emplace(maskContext, *clipPathOperation,
189 *m_resourceClipper, targetBoundingBox,
190 layerPositionOffset);
191 }
192
193 {
194 AffineTransform contentTransform;
195 if (m_resourceClipper->clipPathUnits() ==
196 SVGUnitTypes::kSvgUnitTypeObjectboundingbox) {
197 contentTransform.translate(targetBoundingBox.x(),
198 targetBoundingBox.y());
199 contentTransform.scaleNonUniform(targetBoundingBox.width(),
200 targetBoundingBox.height());
201 }
202 SubtreeContentTransformScope contentTransformScope(contentTransform);
203
204 TransformRecorder contentTransformRecorder(maskContext, m_layoutObject,
205 contentTransform);
206 maskContext.getPaintController().createAndAppend<DrawingDisplayItem>(
207 m_layoutObject, DisplayItem::kSVGClip,
208 m_resourceClipper->createPaintRecord());
209 }
210 }
211
212 LayoutObjectDrawingRecorder drawingRecorder(
213 m_context, m_layoutObject, DisplayItem::kSVGClip, targetVisualRect);
214 sk_sp<PaintRecord> maskPaintRecord = maskBuilder.endRecording();
215 m_context.drawRecord(maskPaintRecord.get());
216 return true;
217 }
218
219 void ClipPathClipper::finishEffect() {
220 switch (m_clipperState) {
221 case ClipperState::AppliedPath:
222 // Path-only clipping, no layers to restore but we need to emit an end to
223 // the clip path display item.
224 m_context.getPaintController().endItem<EndClipPathDisplayItem>(
225 m_layoutObject);
226 break;
227 case ClipperState::AppliedMask:
228 // Transfer content -> clip mask (SrcIn)
229 m_maskContentRecorder.reset();
230
231 // Transfer clip mask -> bg (SrcOver)
232 m_maskClipRecorder.reset();
233 break;
234 case ClipperState::NotApplied:
danakj 2017/03/07 15:46:57 I made one little change here since I noticed it.
235 NOTREACHED();
236 break;
237 }
87 } 238 }
88 239
89 } // namespace blink 240 } // namespace blink
OLDNEW
« 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