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()) { |
| 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, |
| 40 ClipPathOperation& clipPathOperation, |
15 const LayoutObject& layoutObject, | 41 const LayoutObject& layoutObject, |
16 const FloatRect& referenceBox, | 42 const FloatRect& referenceBox, |
17 const FloatPoint& origin) | 43 const FloatPoint& origin) |
18 : m_resourceClipper(nullptr) | 44 : m_resourceClipper(nullptr) |
19 , m_clipperState(SVGClipPainter::ClipperNotApplied) | 45 , m_clipperState(ClipperState::NotApplied) |
20 , m_layoutObject(layoutObject) | 46 , m_layoutObject(layoutObject) |
21 , m_context(context) | 47 , m_context(context) |
22 { | 48 { |
23 DCHECK(layoutObject.styleRef().clipPath()); | 49 if (clipPathOperation.type() == ClipPathOperation::SHAPE) { |
24 ClipPathOperation* clipPathOperation = layoutObject.styleRef().clipPath(); | 50 ShapeClipPathOperation& shape = toShapeClipPathOperation(clipPathOperati
on); |
25 if (clipPathOperation->type() == ClipPathOperation::SHAPE) { | 51 if (!shape.isValid()) |
26 ShapeClipPathOperation* shape = toShapeClipPathOperation(clipPathOperati
on); | |
27 if (!shape->isValid()) | |
28 return; | 52 return; |
29 m_clipPathRecorder.emplace(context, layoutObject, shape->path(referenceB
ox)); | 53 m_clipPathRecorder.emplace(context, layoutObject, shape.path(referenceBo
x)); |
| 54 m_clipperState = ClipperState::AppliedPath; |
30 } else { | 55 } else { |
31 DCHECK_EQ(clipPathOperation->type(), ClipPathOperation::REFERENCE); | 56 DCHECK_EQ(clipPathOperation.type(), ClipPathOperation::REFERENCE); |
32 ReferenceClipPathOperation* referenceClipPathOperation = toReferenceClip
PathOperation(clipPathOperation); | 57 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) | 58 layoutObject, toReferenceClipPathOperation(clipPathOperation)); |
34 Element* element = layoutObject.document().getElementById(referenceClipP
athOperation->fragment()); | 59 if (!clipper) |
35 if (!isSVGClipPathElement(element) || !element->layoutObject()) | |
36 return; | 60 return; |
37 LayoutSVGResourceClipper* clipper = toLayoutSVGResourceClipper(toLayoutS
VGResourceContainer(element->layoutObject())); | |
38 // Compute the (conservative) bounds of the clip-path. | 61 // Compute the (conservative) bounds of the clip-path. |
39 FloatRect clipPathBounds = clipper->resourceBoundingBox(referenceBox); | 62 FloatRect clipPathBounds = clipper->resourceBoundingBox(referenceBox); |
40 // When SVG applies the clip, and the coordinate system is "userspace on
use", we must explicitly pass in | 63 // 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 | 64 // 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. | 65 // "object bounding box" the offset should already be accounted for in t
he reference box. |
43 FloatPoint originTranslation; | 66 FloatPoint originTranslation; |
44 if (clipper->clipPathUnits() == SVGUnitTypes::kSvgUnitTypeUserspaceonuse
) { | 67 if (clipper->clipPathUnits() == SVGUnitTypes::kSvgUnitTypeUserspaceonuse
) { |
45 clipPathBounds.moveBy(origin); | 68 clipPathBounds.moveBy(origin); |
46 originTranslation = origin; | 69 originTranslation = origin; |
47 } | 70 } |
48 if (!SVGClipPainter(*clipper).prepareEffect(layoutObject, referenceBox, | 71 if (!SVGClipPainter(*clipper).prepareEffect(layoutObject, referenceBox, |
49 clipPathBounds, originTranslation, context, m_clipperState)) | 72 clipPathBounds, originTranslation, context, m_clipperState)) |
50 return; | 73 return; |
51 m_resourceClipper = clipper; | 74 m_resourceClipper = clipper; |
52 } | 75 } |
53 } | 76 } |
54 | 77 |
55 ClipPathClipper::~ClipPathClipper() | 78 ClipPathClipper::~ClipPathClipper() |
56 { | 79 { |
57 if (m_resourceClipper) | 80 if (m_resourceClipper) |
58 SVGClipPainter(*m_resourceClipper).finishEffect(m_layoutObject, m_contex
t, m_clipperState); | 81 SVGClipPainter(*m_resourceClipper).finishEffect(m_layoutObject, m_contex
t, m_clipperState); |
59 } | 82 } |
60 | 83 |
61 } // namespace blink | 84 } // namespace blink |
OLD | NEW |