OLD | NEW |
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/layout/svg/LayoutSVGResourceClipper.h" | 7 #include "core/layout/svg/LayoutSVGResourceClipper.h" |
| 8 #include "core/layout/svg/SVGResources.h" |
| 9 #include "core/layout/svg/SVGResourcesCache.h" |
| 10 #include "core/paint/SVGClipPainter.h" |
8 #include "core/style/ClipPathOperation.h" | 11 #include "core/style/ClipPathOperation.h" |
9 #include "platform/graphics/paint/ClipPathRecorder.h" | 12 #include "platform/graphics/paint/ClipPathRecorder.h" |
10 | 13 |
11 namespace blink { | 14 namespace blink { |
12 | 15 |
| 16 namespace { |
| 17 |
| 18 LayoutSVGResourceClipper* resolveElementReference( |
| 19 const LayoutObject& layoutObject, |
| 20 const ReferenceClipPathOperation& referenceClipPathOperation) |
| 21 { |
| 22 if (layoutObject.isSVG() && !layoutObject.isSVGRoot()) { |
| 23 // The reference will have been resolved in |
| 24 // SVGResources::buildResources, so we can just use the LayoutObject's |
| 25 // SVGResources. |
| 26 SVGResources* resources = SVGResourcesCache::cachedResourcesForLayoutObj
ect(&layoutObject); |
| 27 return resources ? resources->clipper() : nullptr; |
| 28 } |
| 29 // TODO(fs): It doesn't work with forward or external SVG references (https:
//bugs.webkit.org/show_bug.cgi?id=90405) |
| 30 Element* element = layoutObject.document().getElementById(referenceClipPathO
peration.fragment()); |
| 31 if (!isSVGClipPathElement(element) || !element->layoutObject()) |
| 32 return nullptr; |
| 33 return toLayoutSVGResourceClipper(toLayoutSVGResourceContainer(element->layo
utObject())); |
| 34 } |
| 35 |
| 36 } // namespace |
| 37 |
13 ClipPathClipper::ClipPathClipper( | 38 ClipPathClipper::ClipPathClipper( |
14 GraphicsContext& context, | 39 GraphicsContext& context, |
15 const LayoutObject& layoutObject, | 40 const LayoutObject& layoutObject, |
16 const FloatRect& referenceBox, | 41 const FloatRect& referenceBox, |
17 const FloatPoint& origin) | 42 const FloatPoint& origin) |
18 : m_resourceClipper(nullptr) | 43 : m_resourceClipper(nullptr) |
19 , m_clipperState(SVGClipPainter::ClipperNotApplied) | 44 , m_clipperState(ClipperState::NotApplied) |
20 , m_layoutObject(layoutObject) | 45 , m_layoutObject(layoutObject) |
21 , m_context(context) | 46 , m_context(context) |
22 { | 47 { |
23 DCHECK(layoutObject.styleRef().clipPath()); | 48 DCHECK(layoutObject.styleRef().clipPath()); |
24 ClipPathOperation* clipPathOperation = layoutObject.styleRef().clipPath(); | 49 ClipPathOperation* clipPathOperation = layoutObject.styleRef().clipPath(); |
25 if (clipPathOperation->type() == ClipPathOperation::SHAPE) { | 50 if (clipPathOperation->type() == ClipPathOperation::SHAPE) { |
26 ShapeClipPathOperation* shape = toShapeClipPathOperation(clipPathOperati
on); | 51 ShapeClipPathOperation* shape = toShapeClipPathOperation(clipPathOperati
on); |
27 if (!shape->isValid()) | 52 if (!shape->isValid()) |
28 return; | 53 return; |
29 m_clipPathRecorder.emplace(context, layoutObject, shape->path(referenceB
ox)); | 54 m_clipPathRecorder.emplace(context, layoutObject, shape->path(referenceB
ox)); |
| 55 m_clipperState = ClipperState::AppliedPath; |
30 } else { | 56 } else { |
31 DCHECK_EQ(clipPathOperation->type(), ClipPathOperation::REFERENCE); | 57 DCHECK_EQ(clipPathOperation->type(), ClipPathOperation::REFERENCE); |
32 ReferenceClipPathOperation* referenceClipPathOperation = toReferenceClip
PathOperation(clipPathOperation); | 58 LayoutSVGResourceClipper* clipper = resolveElementReference( |
33 // TODO(fs): It doesn't work with forward or external SVG references (ht
tps://bugs.webkit.org/show_bug.cgi?id=90405) | 59 layoutObject, toReferenceClipPathOperation(*clipPathOperation)); |
34 Element* element = layoutObject.document().getElementById(referenceClipP
athOperation->fragment()); | 60 if (!clipper) |
35 if (!isSVGClipPathElement(element) || !element->layoutObject()) | |
36 return; | 61 return; |
37 LayoutSVGResourceClipper* clipper = toLayoutSVGResourceClipper(toLayoutS
VGResourceContainer(element->layoutObject())); | |
38 // Compute the (conservative) bounds of the clip-path. | 62 // Compute the (conservative) bounds of the clip-path. |
39 FloatRect clipPathBounds = clipper->resourceBoundingBox(referenceBox); | 63 FloatRect clipPathBounds = clipper->resourceBoundingBox(referenceBox); |
40 // When SVG applies the clip, and the coordinate system is "userspace on
use", we must explicitly pass in | 64 // When SVG applies the clip, and the coordinate system is "userspace on
use", we must explicitly pass in |
41 // the offset to have the clip paint in the correct location. When the c
oordinate system is | 65 // the offset to have the clip paint in the correct location. When the c
oordinate system is |
42 // "object bounding box" the offset should already be accounted for in t
he reference box. | 66 // "object bounding box" the offset should already be accounted for in t
he reference box. |
43 FloatPoint originTranslation; | 67 FloatPoint originTranslation; |
44 if (clipper->clipPathUnits() == SVGUnitTypes::kSvgUnitTypeUserspaceonuse
) { | 68 if (clipper->clipPathUnits() == SVGUnitTypes::kSvgUnitTypeUserspaceonuse
) { |
45 clipPathBounds.moveBy(origin); | 69 clipPathBounds.moveBy(origin); |
46 originTranslation = origin; | 70 originTranslation = origin; |
47 } | 71 } |
48 if (!SVGClipPainter(*clipper).prepareEffect(layoutObject, referenceBox, | 72 if (!SVGClipPainter(*clipper).prepareEffect(layoutObject, referenceBox, |
49 clipPathBounds, originTranslation, context, m_clipperState)) | 73 clipPathBounds, originTranslation, context, m_clipperState)) |
50 return; | 74 return; |
51 m_resourceClipper = clipper; | 75 m_resourceClipper = clipper; |
52 } | 76 } |
53 } | 77 } |
54 | 78 |
55 ClipPathClipper::~ClipPathClipper() | 79 ClipPathClipper::~ClipPathClipper() |
56 { | 80 { |
57 if (m_resourceClipper) | 81 if (m_resourceClipper) |
58 SVGClipPainter(*m_resourceClipper).finishEffect(m_layoutObject, m_contex
t, m_clipperState); | 82 SVGClipPainter(*m_resourceClipper).finishEffect(m_layoutObject, m_contex
t, m_clipperState); |
59 } | 83 } |
60 | 84 |
61 } // namespace blink | 85 } // namespace blink |
OLD | NEW |