| 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 |