OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/SVGClipPainter.h" | 5 #include "core/paint/SVGClipPainter.h" |
6 | 6 |
7 #include "core/dom/ElementTraversal.h" | 7 #include "core/dom/ElementTraversal.h" |
8 #include "core/layout/svg/LayoutSVGResourceClipper.h" | 8 #include "core/layout/svg/LayoutSVGResourceClipper.h" |
| 9 #include "core/layout/svg/SVGLayoutSupport.h" |
9 #include "core/layout/svg/SVGResources.h" | 10 #include "core/layout/svg/SVGResources.h" |
10 #include "core/layout/svg/SVGResourcesCache.h" | 11 #include "core/layout/svg/SVGResourcesCache.h" |
11 #include "core/paint/LayoutObjectDrawingRecorder.h" | 12 #include "core/paint/LayoutObjectDrawingRecorder.h" |
12 #include "core/paint/PaintInfo.h" | 13 #include "core/paint/PaintInfo.h" |
13 #include "core/paint/TransformRecorder.h" | 14 #include "core/paint/TransformRecorder.h" |
14 #include "platform/graphics/paint/ClipPathDisplayItem.h" | 15 #include "platform/graphics/paint/ClipPathDisplayItem.h" |
15 #include "platform/graphics/paint/CompositingRecorder.h" | 16 #include "platform/graphics/paint/CompositingRecorder.h" |
16 #include "platform/graphics/paint/DrawingDisplayItem.h" | 17 #include "platform/graphics/paint/DrawingDisplayItem.h" |
17 #include "platform/graphics/paint/PaintController.h" | 18 #include "platform/graphics/paint/PaintController.h" |
| 19 #include "platform/graphics/paint/SkPictureBuilder.h" |
18 | 20 |
19 namespace blink { | 21 namespace blink { |
20 | 22 |
21 namespace { | 23 namespace { |
22 | 24 |
23 class SVGClipExpansionCycleHelper { | 25 class SVGClipExpansionCycleHelper { |
24 public: | 26 public: |
25 SVGClipExpansionCycleHelper(LayoutSVGResourceClipper& clip) : m_clip(clip) {
clip.beginClipExpansion(); } | 27 SVGClipExpansionCycleHelper(LayoutSVGResourceClipper& clip) : m_clip(clip) {
clip.beginClipExpansion(); } |
26 ~SVGClipExpansionCycleHelper() { m_clip.endClipExpansion(); } | 28 ~SVGClipExpansionCycleHelper() { m_clip.endClipExpansion(); } |
27 private: | 29 private: |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 context.getPaintController().createAndAppend<BeginClipPathDisplayItem>(t
arget, clipPath); | 61 context.getPaintController().createAndAppend<BeginClipPathDisplayItem>(t
arget, clipPath); |
60 return true; | 62 return true; |
61 } | 63 } |
62 | 64 |
63 // Fall back to masking. | 65 // Fall back to masking. |
64 clipperState = ClipperAppliedMask; | 66 clipperState = ClipperAppliedMask; |
65 | 67 |
66 // Begin compositing the clip mask. | 68 // Begin compositing the clip mask. |
67 CompositingRecorder::beginCompositing(context, target, SkXfermode::kSrcOver_
Mode, 1, &paintInvalidationRect); | 69 CompositingRecorder::beginCompositing(context, target, SkXfermode::kSrcOver_
Mode, 1, &paintInvalidationRect); |
68 { | 70 { |
69 TransformRecorder recorder(context, target, animatedLocalTransform); | 71 if (!drawClipAsMask(context, target, targetBoundingBox, paintInvalidatio
nRect, animatedLocalTransform)) { |
70 | |
71 // clipPath can also be clipped by another clipPath. | |
72 SVGResources* resources = SVGResourcesCache::cachedResourcesForLayoutObj
ect(&m_clip); | |
73 LayoutSVGResourceClipper* clipPathClipper = resources ? resources->clipp
er() : 0; | |
74 ClipperState clipPathClipperState = ClipperNotApplied; | |
75 if (clipPathClipper && !SVGClipPainter(*clipPathClipper).prepareEffect(m
_clip, targetBoundingBox, paintInvalidationRect, context, clipPathClipperState))
{ | |
76 // End the clip mask's compositor. | 72 // End the clip mask's compositor. |
77 CompositingRecorder::endCompositing(context, target); | 73 CompositingRecorder::endCompositing(context, target); |
78 return false; | 74 return false; |
79 } | 75 } |
80 | |
81 drawClipMaskContent(context, target, targetBoundingBox, paintInvalidatio
nRect); | |
82 | |
83 if (clipPathClipper) | |
84 SVGClipPainter(*clipPathClipper).finishEffect(m_clip, context, clipP
athClipperState); | |
85 } | 76 } |
86 | 77 |
87 // Masked content layer start. | 78 // Masked content layer start. |
88 CompositingRecorder::beginCompositing(context, target, SkXfermode::kSrcIn_Mo
de, 1, &paintInvalidationRect); | 79 CompositingRecorder::beginCompositing(context, target, SkXfermode::kSrcIn_Mo
de, 1, &paintInvalidationRect); |
89 | 80 |
90 return true; | 81 return true; |
91 } | 82 } |
92 | 83 |
93 void SVGClipPainter::finishEffect(const LayoutObject& target, GraphicsContext& c
ontext, ClipperState& clipperState) | 84 void SVGClipPainter::finishEffect(const LayoutObject& target, GraphicsContext& c
ontext, ClipperState& clipperState) |
94 { | 85 { |
95 switch (clipperState) { | 86 switch (clipperState) { |
96 case ClipperAppliedPath: | 87 case ClipperAppliedPath: |
97 // Path-only clipping, no layers to restore but we need to emit an end t
o the clip path display item. | 88 // Path-only clipping, no layers to restore but we need to emit an end t
o the clip path display item. |
98 context.getPaintController().endItem<EndClipPathDisplayItem>(target); | 89 context.getPaintController().endItem<EndClipPathDisplayItem>(target); |
99 break; | 90 break; |
100 case ClipperAppliedMask: | 91 case ClipperAppliedMask: |
101 // Transfer content -> clip mask (SrcIn) | 92 // Transfer content -> clip mask (SrcIn) |
102 CompositingRecorder::endCompositing(context, target); | 93 CompositingRecorder::endCompositing(context, target); |
103 | 94 |
104 // Transfer clip mask -> bg (SrcOver) | 95 // Transfer clip mask -> bg (SrcOver) |
105 CompositingRecorder::endCompositing(context, target); | 96 CompositingRecorder::endCompositing(context, target); |
106 break; | 97 break; |
107 default: | 98 default: |
108 ASSERT_NOT_REACHED(); | 99 ASSERT_NOT_REACHED(); |
109 } | 100 } |
110 } | 101 } |
111 | 102 |
112 void SVGClipPainter::drawClipMaskContent(GraphicsContext& context, const LayoutO
bject& layoutObject, const FloatRect& targetBoundingBox, const FloatRect& target
PaintInvalidationRect) | 103 bool SVGClipPainter::drawClipAsMask(GraphicsContext& context, const LayoutObject
& layoutObject, const FloatRect& targetBoundingBox, const FloatRect& targetPaint
InvalidationRect, const AffineTransform& localTransform) |
113 { | 104 { |
114 AffineTransform contentTransformation; | 105 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(context, layoutO
bject, DisplayItem::SVGClip)) |
115 RefPtr<const SkPicture> clipContentPicture = m_clip.createContentPicture(con
tentTransformation, targetBoundingBox, context); | 106 return true; |
116 | 107 |
117 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(context, layoutO
bject, DisplayItem::SVGClip)) | 108 SkPictureBuilder maskPictureBuilder(targetPaintInvalidationRect, nullptr, &c
ontext); |
118 return; | 109 GraphicsContext& maskContext = maskPictureBuilder.context(); |
| 110 { |
| 111 TransformRecorder recorder(maskContext, layoutObject, localTransform); |
| 112 |
| 113 // Create a clipPathClipper if this clipPath is clipped by another clipP
ath. |
| 114 SVGResources* resources = SVGResourcesCache::cachedResourcesForLayoutObj
ect(&m_clip); |
| 115 LayoutSVGResourceClipper* clipPathClipper = resources ? resources->clipp
er() : nullptr; |
| 116 ClipperState clipPathClipperState = ClipperNotApplied; |
| 117 if (clipPathClipper && !SVGClipPainter(*clipPathClipper).prepareEffect(m
_clip, targetBoundingBox, targetPaintInvalidationRect, maskContext, clipPathClip
perState)) |
| 118 return false; |
| 119 |
| 120 { |
| 121 AffineTransform contentTransform; |
| 122 if (m_clip.clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUN
DINGBOX) { |
| 123 contentTransform.translate(targetBoundingBox.x(), targetBounding
Box.y()); |
| 124 contentTransform.scaleNonUniform(targetBoundingBox.width(), targ
etBoundingBox.height()); |
| 125 } |
| 126 SubtreeContentTransformScope contentTransformScope(contentTransform)
; |
| 127 |
| 128 TransformRecorder contentTransformRecorder(maskContext, layoutObject
, contentTransform); |
| 129 RefPtr<const SkPicture> clipContentPicture = m_clip.createContentPic
ture(); |
| 130 maskContext.getPaintController().createAndAppend<DrawingDisplayItem>
(layoutObject, DisplayItem::SVGClip, clipContentPicture.get()); |
| 131 } |
| 132 |
| 133 if (clipPathClipper) |
| 134 SVGClipPainter(*clipPathClipper).finishEffect(m_clip, maskContext, c
lipPathClipperState); |
| 135 } |
119 | 136 |
120 LayoutObjectDrawingRecorder drawingRecorder(context, layoutObject, DisplayIt
em::SVGClip, targetPaintInvalidationRect); | 137 LayoutObjectDrawingRecorder drawingRecorder(context, layoutObject, DisplayIt
em::SVGClip, targetPaintInvalidationRect); |
121 context.save(); | 138 RefPtr<SkPicture> maskPicture = maskPictureBuilder.endRecording(); |
122 context.concatCTM(contentTransformation); | 139 context.drawPicture(maskPicture.get()); |
123 context.drawPicture(clipContentPicture.get()); | 140 return true; |
124 context.restore(); | |
125 } | 141 } |
126 | 142 |
127 } // namespace blink | 143 } // namespace blink |
OLD | NEW |