| 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/SVGLayoutSupport.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 } // namespace | 33 } // namespace |
| 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, const FloatPoint& layerPositionOffse
t, GraphicsContext& context, ClipperState& clipperState) |
| 37 { | 37 { |
| 38 ASSERT(clipperState == ClipperNotApplied); | 38 ASSERT(clipperState == ClipperNotApplied); |
| 39 ASSERT_WITH_SECURITY_IMPLICATION(!m_clip.needsLayout()); | 39 ASSERT_WITH_SECURITY_IMPLICATION(!m_clip.needsLayout()); |
| 40 | 40 |
| 41 m_clip.clearInvalidationMask(); | 41 m_clip.clearInvalidationMask(); |
| 42 | 42 |
| 43 if (paintInvalidationRect.isEmpty() || m_clip.hasCycle()) | 43 if (paintInvalidationRect.isEmpty() || m_clip.hasCycle()) |
| 44 return false; | 44 return false; |
| 45 | 45 |
| 46 SVGClipExpansionCycleHelper inClipExpansionChange(m_clip); | 46 SVGClipExpansionCycleHelper inClipExpansionChange(m_clip); |
| 47 | 47 |
| 48 AffineTransform animatedLocalTransform = toSVGClipPathElement(m_clip.element
())->calculateAnimatedLocalTransform(); | 48 AffineTransform animatedLocalTransform = toSVGClipPathElement(m_clip.element
())->calculateAnimatedLocalTransform(); |
| 49 // 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. |
| 50 // 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 |
| 51 // userSpaceOnUse units (the zoom is accounted for objectBoundingBox-resolve
d lengths). | 51 // userSpaceOnUse units (the zoom is accounted for objectBoundingBox-resolve
d lengths). |
| 52 if (!target.isSVG() && m_clip.clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE
_USERSPACEONUSE) { | 52 if (!target.isSVG() && m_clip.clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE
_USERSPACEONUSE) { |
| 53 ASSERT(m_clip.style()); | 53 ASSERT(m_clip.style()); |
| 54 animatedLocalTransform.scale(m_clip.style()->effectiveZoom()); | 54 animatedLocalTransform.scale(m_clip.style()->effectiveZoom()); |
| 55 } | 55 } |
| 56 | 56 |
| 57 // First, try to apply the clip as a clipPath. | 57 // First, try to apply the clip as a clipPath. |
| 58 Path clipPath; | 58 Path clipPath; |
| 59 if (m_clip.asPath(animatedLocalTransform, targetBoundingBox, clipPath)) { | 59 if (m_clip.asPath(animatedLocalTransform, targetBoundingBox, clipPath)) { |
| 60 AffineTransform positionTransform; |
| 61 positionTransform.translate(layerPositionOffset.x(), layerPositionOffset
.y()); |
| 62 clipPath.transform(positionTransform); |
| 60 clipperState = ClipperAppliedPath; | 63 clipperState = ClipperAppliedPath; |
| 61 context.getPaintController().createAndAppend<BeginClipPathDisplayItem>(t
arget, clipPath); | 64 context.getPaintController().createAndAppend<BeginClipPathDisplayItem>(t
arget, clipPath); |
| 62 return true; | 65 return true; |
| 63 } | 66 } |
| 64 | 67 |
| 65 // Fall back to masking. | 68 // Fall back to masking. |
| 66 clipperState = ClipperAppliedMask; | 69 clipperState = ClipperAppliedMask; |
| 67 | 70 |
| 68 // Begin compositing the clip mask. | 71 // Begin compositing the clip mask. |
| 69 CompositingRecorder::beginCompositing(context, target, SkXfermode::kSrcOver_
Mode, 1, &paintInvalidationRect); | 72 CompositingRecorder::beginCompositing(context, target, SkXfermode::kSrcOver_
Mode, 1, &paintInvalidationRect); |
| 70 { | 73 { |
| 71 if (!drawClipAsMask(context, target, targetBoundingBox, paintInvalidatio
nRect, animatedLocalTransform)) { | 74 if (!drawClipAsMask(context, target, targetBoundingBox, paintInvalidatio
nRect, animatedLocalTransform, layerPositionOffset)) { |
| 72 // End the clip mask's compositor. | 75 // End the clip mask's compositor. |
| 73 CompositingRecorder::endCompositing(context, target); | 76 CompositingRecorder::endCompositing(context, target); |
| 74 return false; | 77 return false; |
| 75 } | 78 } |
| 76 } | 79 } |
| 77 | 80 |
| 78 // Masked content layer start. | 81 // Masked content layer start. |
| 79 CompositingRecorder::beginCompositing(context, target, SkXfermode::kSrcIn_Mo
de, 1, &paintInvalidationRect); | 82 CompositingRecorder::beginCompositing(context, target, SkXfermode::kSrcIn_Mo
de, 1, &paintInvalidationRect); |
| 80 | 83 |
| 81 return true; | 84 return true; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 93 CompositingRecorder::endCompositing(context, target); | 96 CompositingRecorder::endCompositing(context, target); |
| 94 | 97 |
| 95 // Transfer clip mask -> bg (SrcOver) | 98 // Transfer clip mask -> bg (SrcOver) |
| 96 CompositingRecorder::endCompositing(context, target); | 99 CompositingRecorder::endCompositing(context, target); |
| 97 break; | 100 break; |
| 98 default: | 101 default: |
| 99 ASSERT_NOT_REACHED(); | 102 ASSERT_NOT_REACHED(); |
| 100 } | 103 } |
| 101 } | 104 } |
| 102 | 105 |
| 103 bool SVGClipPainter::drawClipAsMask(GraphicsContext& context, const LayoutObject
& layoutObject, const FloatRect& targetBoundingBox, const FloatRect& targetPaint
InvalidationRect, const AffineTransform& localTransform) | 106 bool SVGClipPainter::drawClipAsMask(GraphicsContext& context, const LayoutObject
& layoutObject, const FloatRect& targetBoundingBox, |
| 107 const FloatRect& targetPaintInvalidationRect, const AffineTransform& localTr
ansform, const FloatPoint& layerPositionOffset) |
| 104 { | 108 { |
| 105 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(context, layoutO
bject, DisplayItem::SVGClip)) | 109 if (LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(context, layoutO
bject, DisplayItem::SVGClip)) |
| 106 return true; | 110 return true; |
| 107 | 111 |
| 108 SkPictureBuilder maskPictureBuilder(targetPaintInvalidationRect, nullptr, &c
ontext); | 112 SkPictureBuilder maskPictureBuilder(targetPaintInvalidationRect, nullptr, &c
ontext); |
| 109 GraphicsContext& maskContext = maskPictureBuilder.context(); | 113 GraphicsContext& maskContext = maskPictureBuilder.context(); |
| 110 { | 114 { |
| 111 TransformRecorder recorder(maskContext, layoutObject, localTransform); | 115 TransformRecorder recorder(maskContext, layoutObject, localTransform); |
| 112 | 116 |
| 113 // Create a clipPathClipper if this clipPath is clipped by another clipP
ath. | 117 // Create a clipPathClipper if this clipPath is clipped by another clipP
ath. |
| 114 SVGResources* resources = SVGResourcesCache::cachedResourcesForLayoutObj
ect(&m_clip); | 118 SVGResources* resources = SVGResourcesCache::cachedResourcesForLayoutObj
ect(&m_clip); |
| 115 LayoutSVGResourceClipper* clipPathClipper = resources ? resources->clipp
er() : nullptr; | 119 LayoutSVGResourceClipper* clipPathClipper = resources ? resources->clipp
er() : nullptr; |
| 116 ClipperState clipPathClipperState = ClipperNotApplied; | 120 ClipperState clipPathClipperState = ClipperNotApplied; |
| 117 if (clipPathClipper && !SVGClipPainter(*clipPathClipper).prepareEffect(m
_clip, targetBoundingBox, targetPaintInvalidationRect, maskContext, clipPathClip
perState)) | 121 if (clipPathClipper && !SVGClipPainter(*clipPathClipper).prepareEffect(m
_clip, targetBoundingBox, targetPaintInvalidationRect, layerPositionOffset, mask
Context, clipPathClipperState)) |
| 118 return false; | 122 return false; |
| 119 | 123 |
| 120 { | 124 { |
| 121 AffineTransform contentTransform; | 125 AffineTransform contentTransform; |
| 122 if (m_clip.clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUN
DINGBOX) { | 126 if (m_clip.clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUN
DINGBOX) { |
| 123 contentTransform.translate(targetBoundingBox.x(), targetBounding
Box.y()); | 127 contentTransform.translate(targetBoundingBox.x(), targetBounding
Box.y()); |
| 124 contentTransform.scaleNonUniform(targetBoundingBox.width(), targ
etBoundingBox.height()); | 128 contentTransform.scaleNonUniform(targetBoundingBox.width(), targ
etBoundingBox.height()); |
| 125 } | 129 } |
| 126 SubtreeContentTransformScope contentTransformScope(contentTransform)
; | 130 SubtreeContentTransformScope contentTransformScope(contentTransform)
; |
| 127 | 131 |
| 128 TransformRecorder contentTransformRecorder(maskContext, layoutObject
, contentTransform); | 132 TransformRecorder contentTransformRecorder(maskContext, layoutObject
, contentTransform); |
| 129 RefPtr<const SkPicture> clipContentPicture = m_clip.createContentPic
ture(); | 133 RefPtr<const SkPicture> clipContentPicture = m_clip.createContentPic
ture(); |
| 130 maskContext.getPaintController().createAndAppend<DrawingDisplayItem>
(layoutObject, DisplayItem::SVGClip, clipContentPicture.get()); | 134 maskContext.getPaintController().createAndAppend<DrawingDisplayItem>
(layoutObject, DisplayItem::SVGClip, clipContentPicture.get()); |
| 131 } | 135 } |
| 132 | 136 |
| 133 if (clipPathClipper) | 137 if (clipPathClipper) |
| 134 SVGClipPainter(*clipPathClipper).finishEffect(m_clip, maskContext, c
lipPathClipperState); | 138 SVGClipPainter(*clipPathClipper).finishEffect(m_clip, maskContext, c
lipPathClipperState); |
| 135 } | 139 } |
| 136 | 140 |
| 137 LayoutObjectDrawingRecorder drawingRecorder(context, layoutObject, DisplayIt
em::SVGClip, targetPaintInvalidationRect); | 141 LayoutObjectDrawingRecorder drawingRecorder(context, layoutObject, DisplayIt
em::SVGClip, targetPaintInvalidationRect); |
| 138 RefPtr<SkPicture> maskPicture = maskPictureBuilder.endRecording(); | 142 RefPtr<SkPicture> maskPicture = maskPictureBuilder.endRecording(); |
| 139 context.drawPicture(maskPicture.get()); | 143 context.drawPicture(maskPicture.get()); |
| 140 return true; | 144 return true; |
| 141 } | 145 } |
| 142 | 146 |
| 143 } // namespace blink | 147 } // namespace blink |
| OLD | NEW |