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 "config.h" | 5 #include "config.h" |
6 #include "core/paint/SVGClipPainter.h" | 6 #include "core/paint/SVGClipPainter.h" |
7 | 7 |
8 #include "core/dom/ElementTraversal.h" | 8 #include "core/dom/ElementTraversal.h" |
9 #include "core/layout/svg/LayoutSVGResourceClipper.h" | 9 #include "core/layout/svg/LayoutSVGResourceClipper.h" |
10 #include "core/layout/svg/SVGResources.h" | 10 #include "core/layout/svg/SVGResources.h" |
(...skipping 15 matching lines...) Expand all Loading... |
26 public: | 26 public: |
27 SVGClipExpansionCycleHelper(LayoutSVGResourceClipper& clip) : m_clip(clip) {
clip.beginClipExpansion(); } | 27 SVGClipExpansionCycleHelper(LayoutSVGResourceClipper& clip) : m_clip(clip) {
clip.beginClipExpansion(); } |
28 ~SVGClipExpansionCycleHelper() { m_clip.endClipExpansion(); } | 28 ~SVGClipExpansionCycleHelper() { m_clip.endClipExpansion(); } |
29 private: | 29 private: |
30 LayoutSVGResourceClipper& m_clip; | 30 LayoutSVGResourceClipper& m_clip; |
31 }; | 31 }; |
32 | 32 |
33 } | 33 } |
34 | 34 |
35 bool SVGClipPainter::prepareEffect(const LayoutObject& target, const FloatRect&
targetBoundingBox, | 35 bool SVGClipPainter::prepareEffect(const LayoutObject& target, const FloatRect&
targetBoundingBox, |
36 const FloatRect& paintInvalidationRect, GraphicsContext* context, ClipperSta
te& clipperState) | 36 const FloatRect& paintInvalidationRect, GraphicsContext& context, ClipperSta
te& clipperState) |
37 { | 37 { |
38 ASSERT(context); | |
39 ASSERT(clipperState == ClipperNotApplied); | 38 ASSERT(clipperState == ClipperNotApplied); |
40 ASSERT_WITH_SECURITY_IMPLICATION(!m_clip.needsLayout()); | 39 ASSERT_WITH_SECURITY_IMPLICATION(!m_clip.needsLayout()); |
41 | 40 |
42 m_clip.clearInvalidationMask(); | 41 m_clip.clearInvalidationMask(); |
43 | 42 |
44 if (paintInvalidationRect.isEmpty() || m_clip.hasCycle()) | 43 if (paintInvalidationRect.isEmpty() || m_clip.hasCycle()) |
45 return false; | 44 return false; |
46 | 45 |
47 SVGClipExpansionCycleHelper inClipExpansionChange(m_clip); | 46 SVGClipExpansionCycleHelper inClipExpansionChange(m_clip); |
48 | 47 |
49 AffineTransform animatedLocalTransform = toSVGClipPathElement(m_clip.element
())->calculateAnimatedLocalTransform(); | 48 AffineTransform animatedLocalTransform = toSVGClipPathElement(m_clip.element
())->calculateAnimatedLocalTransform(); |
50 // When drawing a clip for non-SVG elements, the CTM does not include the zo
om factor. | 49 // When drawing a clip for non-SVG elements, the CTM does not include the zo
om factor. |
51 // In this case, we need to apply the zoom scale explicitly - but only for c
lips with | 50 // In this case, we need to apply the zoom scale explicitly - but only for c
lips with |
52 // userSpaceOnUse units (the zoom is accounted for objectBoundingBox-resolve
d lengths). | 51 // userSpaceOnUse units (the zoom is accounted for objectBoundingBox-resolve
d lengths). |
53 if (!target.isSVG() && m_clip.clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE
_USERSPACEONUSE) { | 52 if (!target.isSVG() && m_clip.clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE
_USERSPACEONUSE) { |
54 ASSERT(m_clip.style()); | 53 ASSERT(m_clip.style()); |
55 animatedLocalTransform.scale(m_clip.style()->effectiveZoom()); | 54 animatedLocalTransform.scale(m_clip.style()->effectiveZoom()); |
56 } | 55 } |
57 | 56 |
58 // First, try to apply the clip as a clipPath. | 57 // First, try to apply the clip as a clipPath. |
59 Path clipPath; | 58 Path clipPath; |
60 if (m_clip.asPath(animatedLocalTransform, targetBoundingBox, clipPath)) { | 59 if (m_clip.asPath(animatedLocalTransform, targetBoundingBox, clipPath)) { |
61 clipperState = ClipperAppliedPath; | 60 clipperState = ClipperAppliedPath; |
62 context->paintController().createAndAppend<BeginClipPathDisplayItem>(tar
get, clipPath); | 61 context.paintController().createAndAppend<BeginClipPathDisplayItem>(targ
et, clipPath); |
63 return true; | 62 return true; |
64 } | 63 } |
65 | 64 |
66 // Fall back to masking. | 65 // Fall back to masking. |
67 clipperState = ClipperAppliedMask; | 66 clipperState = ClipperAppliedMask; |
68 | 67 |
69 // Begin compositing the clip mask. | 68 // Begin compositing the clip mask. |
70 CompositingRecorder::beginCompositing(*context, target, SkXfermode::kSrcOver
_Mode, 1, &paintInvalidationRect); | 69 CompositingRecorder::beginCompositing(context, target, SkXfermode::kSrcOver_
Mode, 1, &paintInvalidationRect); |
71 { | 70 { |
72 TransformRecorder recorder(*context, target, animatedLocalTransform); | 71 TransformRecorder recorder(context, target, animatedLocalTransform); |
73 | 72 |
74 // clipPath can also be clipped by another clipPath. | 73 // clipPath can also be clipped by another clipPath. |
75 SVGResources* resources = SVGResourcesCache::cachedResourcesForLayoutObj
ect(&m_clip); | 74 SVGResources* resources = SVGResourcesCache::cachedResourcesForLayoutObj
ect(&m_clip); |
76 LayoutSVGResourceClipper* clipPathClipper = resources ? resources->clipp
er() : 0; | 75 LayoutSVGResourceClipper* clipPathClipper = resources ? resources->clipp
er() : 0; |
77 ClipperState clipPathClipperState = ClipperNotApplied; | 76 ClipperState clipPathClipperState = ClipperNotApplied; |
78 if (clipPathClipper && !SVGClipPainter(*clipPathClipper).prepareEffect(m
_clip, targetBoundingBox, paintInvalidationRect, context, clipPathClipperState))
{ | 77 if (clipPathClipper && !SVGClipPainter(*clipPathClipper).prepareEffect(m
_clip, targetBoundingBox, paintInvalidationRect, context, clipPathClipperState))
{ |
79 // End the clip mask's compositor. | 78 // End the clip mask's compositor. |
80 CompositingRecorder::endCompositing(*context, target); | 79 CompositingRecorder::endCompositing(context, target); |
81 return false; | 80 return false; |
82 } | 81 } |
83 | 82 |
84 drawClipMaskContent(context, target, targetBoundingBox, paintInvalidatio
nRect); | 83 drawClipMaskContent(context, target, targetBoundingBox, paintInvalidatio
nRect); |
85 | 84 |
86 if (clipPathClipper) | 85 if (clipPathClipper) |
87 SVGClipPainter(*clipPathClipper).finishEffect(m_clip, context, clipP
athClipperState); | 86 SVGClipPainter(*clipPathClipper).finishEffect(m_clip, context, clipP
athClipperState); |
88 } | 87 } |
89 | 88 |
90 // Masked content layer start. | 89 // Masked content layer start. |
91 CompositingRecorder::beginCompositing(*context, target, SkXfermode::kSrcIn_M
ode, 1, &paintInvalidationRect); | 90 CompositingRecorder::beginCompositing(context, target, SkXfermode::kSrcIn_Mo
de, 1, &paintInvalidationRect); |
92 | 91 |
93 return true; | 92 return true; |
94 } | 93 } |
95 | 94 |
96 void SVGClipPainter::finishEffect(const LayoutObject& target, GraphicsContext* c
ontext, ClipperState& clipperState) | 95 void SVGClipPainter::finishEffect(const LayoutObject& target, GraphicsContext& c
ontext, ClipperState& clipperState) |
97 { | 96 { |
98 switch (clipperState) { | 97 switch (clipperState) { |
99 case ClipperAppliedPath: | 98 case ClipperAppliedPath: |
100 // Path-only clipping, no layers to restore but we need to emit an end t
o the clip path display item. | 99 // Path-only clipping, no layers to restore but we need to emit an end t
o the clip path display item. |
101 context->paintController().endItem<EndClipPathDisplayItem>(target); | 100 context.paintController().endItem<EndClipPathDisplayItem>(target); |
102 break; | 101 break; |
103 case ClipperAppliedMask: | 102 case ClipperAppliedMask: |
104 // Transfer content -> clip mask (SrcIn) | 103 // Transfer content -> clip mask (SrcIn) |
105 CompositingRecorder::endCompositing(*context, target); | 104 CompositingRecorder::endCompositing(context, target); |
106 | 105 |
107 // Transfer clip mask -> bg (SrcOver) | 106 // Transfer clip mask -> bg (SrcOver) |
108 CompositingRecorder::endCompositing(*context, target); | 107 CompositingRecorder::endCompositing(context, target); |
109 break; | 108 break; |
110 default: | 109 default: |
111 ASSERT_NOT_REACHED(); | 110 ASSERT_NOT_REACHED(); |
112 } | 111 } |
113 } | 112 } |
114 | 113 |
115 void SVGClipPainter::drawClipMaskContent(GraphicsContext* context, const LayoutO
bject& layoutObject, const FloatRect& targetBoundingBox, const FloatRect& target
PaintInvalidationRect) | 114 void SVGClipPainter::drawClipMaskContent(GraphicsContext& context, const LayoutO
bject& layoutObject, const FloatRect& targetBoundingBox, const FloatRect& target
PaintInvalidationRect) |
116 { | 115 { |
117 ASSERT(context); | |
118 | |
119 AffineTransform contentTransformation; | 116 AffineTransform contentTransformation; |
120 RefPtr<const SkPicture> clipContentPicture = m_clip.createContentPicture(con
tentTransformation, targetBoundingBox, context); | 117 RefPtr<const SkPicture> clipContentPicture = m_clip.createContentPicture(con
tentTransformation, targetBoundingBox, context); |
121 | 118 |
122 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(*context, layout
Object, DisplayItem::SVGClip, LayoutPoint())) | 119 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(context, layoutO
bject, DisplayItem::SVGClip, LayoutPoint())) |
123 return; | 120 return; |
124 | 121 |
125 LayoutObjectDrawingRecorder drawingRecorder(*context, layoutObject, DisplayI
tem::SVGClip, targetPaintInvalidationRect, LayoutPoint()); | 122 LayoutObjectDrawingRecorder drawingRecorder(context, layoutObject, DisplayIt
em::SVGClip, targetPaintInvalidationRect, LayoutPoint()); |
126 context->save(); | 123 context.save(); |
127 context->concatCTM(contentTransformation); | 124 context.concatCTM(contentTransformation); |
128 context->drawPicture(clipContentPicture.get()); | 125 context.drawPicture(clipContentPicture.get()); |
129 context->restore(); | 126 context.restore(); |
130 } | 127 } |
131 | 128 |
132 } | 129 } |
OLD | NEW |