OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org> | 2 * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org> |
3 * Copyright (C) 2004, 2005, 2008 Rob Buis <buis@kde.org> | 3 * Copyright (C) 2004, 2005, 2008 Rob Buis <buis@kde.org> |
4 * Copyright (C) 2005, 2007 Eric Seidel <eric@webkit.org> | 4 * Copyright (C) 2005, 2007 Eric Seidel <eric@webkit.org> |
5 * Copyright (C) 2009 Google, Inc. | 5 * Copyright (C) 2009 Google, Inc. |
6 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> | 6 * Copyright (C) 2009 Dirk Schulze <krit@webkit.org> |
7 * Copyright (C) Research In Motion Limited 2010. All rights reserved. | 7 * Copyright (C) Research In Motion Limited 2010. All rights reserved. |
8 * Copyright (C) 2009 Jeff Schiller <codedread@gmail.com> | 8 * Copyright (C) 2009 Jeff Schiller <codedread@gmail.com> |
9 * Copyright (C) 2011 Renata Hodovan <reni@webkit.org> | 9 * Copyright (C) 2011 Renata Hodovan <reni@webkit.org> |
10 * Copyright (C) 2011 University of Szeged | 10 * Copyright (C) 2011 University of Szeged |
(...skipping 16 matching lines...) Expand all Loading... |
27 | 27 |
28 #include "config.h" | 28 #include "config.h" |
29 | 29 |
30 #include "core/layout/svg/LayoutSVGPath.h" | 30 #include "core/layout/svg/LayoutSVGPath.h" |
31 | 31 |
32 #include "core/layout/svg/LayoutSVGResourceMarker.h" | 32 #include "core/layout/svg/LayoutSVGResourceMarker.h" |
33 #include "core/layout/svg/SVGResources.h" | 33 #include "core/layout/svg/SVGResources.h" |
34 #include "core/layout/svg/SVGResourcesCache.h" | 34 #include "core/layout/svg/SVGResourcesCache.h" |
35 #include "core/layout/svg/SVGSubpathData.h" | 35 #include "core/layout/svg/SVGSubpathData.h" |
36 #include "core/svg/SVGGraphicsElement.h" | 36 #include "core/svg/SVGGraphicsElement.h" |
| 37 #include "wtf/MathExtras.h" |
37 | 38 |
38 namespace blink { | 39 namespace blink { |
39 | 40 |
40 LayoutSVGPath::LayoutSVGPath(SVGGraphicsElement* node) | 41 LayoutSVGPath::LayoutSVGPath(SVGGraphicsElement* node) |
41 : LayoutSVGShape(node) | 42 : LayoutSVGShape(node) |
42 { | 43 { |
43 } | 44 } |
44 | 45 |
45 LayoutSVGPath::~LayoutSVGPath() | 46 LayoutSVGPath::~LayoutSVGPath() |
46 { | 47 { |
47 } | 48 } |
48 | 49 |
49 void LayoutSVGPath::updateShapeFromElement() | 50 void LayoutSVGPath::updateShapeFromElement() |
50 { | 51 { |
51 LayoutSVGShape::updateShapeFromElement(); | 52 LayoutSVGShape::updateShapeFromElement(); |
52 processMarkerPositions(); | 53 processMarkerPositions(); |
53 updateZeroLengthSubpaths(); | 54 updateZeroLengthSubpaths(); |
54 | 55 |
55 m_strokeBoundingBox = calculateUpdatedStrokeBoundingBox(); | 56 m_strokeBoundingBox = calculateUpdatedStrokeBoundingBox(); |
56 } | 57 } |
57 | 58 |
| 59 FloatRect LayoutSVGPath::hitTestStrokeBoundingBox() const |
| 60 { |
| 61 const SVGComputedStyle& svgStyle = style()->svgStyle(); |
| 62 if (svgStyle.hasStroke()) |
| 63 return m_strokeBoundingBox; |
| 64 |
| 65 // Implementation of http://dev.w3.org/fxtf/css-masking-1/#compute-stroke-bo
unding-box |
| 66 // except that we ignore whether the stroke is none. |
| 67 |
| 68 FloatRect box = m_fillBoundingBox; |
| 69 |
| 70 const float strokeWidth = this->strokeWidth(); |
| 71 if (strokeWidth <= 0) |
| 72 return box; |
| 73 |
| 74 float delta = strokeWidth / 2; |
| 75 |
| 76 if (svgStyle.hasMiterJoinStyle()) { |
| 77 const float miter = svgStyle.strokeMiterLimit(); |
| 78 if (miter < M_SQRT2 && svgStyle.hasSquareCapStyle()) |
| 79 delta *= M_SQRT2; |
| 80 else |
| 81 delta *= miter; |
| 82 } else if (svgStyle.hasSquareCapStyle()) { |
| 83 delta *= M_SQRT2; |
| 84 } |
| 85 |
| 86 box.inflate(delta); |
| 87 |
| 88 for (size_t i = 0; i < m_zeroLengthLinecapLocations.size(); ++i) |
| 89 box.unite(zeroLengthSubpathRect(m_zeroLengthLinecapLocations[i], strokeW
idth)); |
| 90 |
| 91 return box; |
| 92 } |
| 93 |
58 FloatRect LayoutSVGPath::calculateUpdatedStrokeBoundingBox() const | 94 FloatRect LayoutSVGPath::calculateUpdatedStrokeBoundingBox() const |
59 { | 95 { |
60 FloatRect strokeBoundingBox = m_strokeBoundingBox; | 96 FloatRect strokeBoundingBox = m_strokeBoundingBox; |
61 | 97 |
62 if (!m_markerPositions.isEmpty()) | 98 if (!m_markerPositions.isEmpty()) |
63 strokeBoundingBox.unite(markerRect(strokeWidth())); | 99 strokeBoundingBox.unite(markerRect(strokeWidth())); |
64 | 100 |
65 if (style()->svgStyle().hasStroke()) { | 101 if (style()->svgStyle().hasStroke()) { |
66 // FIXME: zero-length subpaths do not respect vector-effect = non-scalin
g-stroke. | 102 // FIXME: zero-length subpaths do not respect vector-effect = non-scalin
g-stroke. |
67 float strokeWidth = this->strokeWidth(); | 103 float strokeWidth = this->strokeWidth(); |
68 for (size_t i = 0; i < m_zeroLengthLinecapLocations.size(); ++i) | 104 for (size_t i = 0; i < m_zeroLengthLinecapLocations.size(); ++i) |
69 strokeBoundingBox.unite(zeroLengthSubpathRect(m_zeroLengthLinecapLoc
ations[i], strokeWidth)); | 105 strokeBoundingBox.unite(zeroLengthSubpathRect(m_zeroLengthLinecapLoc
ations[i], strokeWidth)); |
70 } | 106 } |
71 | 107 |
72 return strokeBoundingBox; | 108 return strokeBoundingBox; |
73 } | 109 } |
74 | 110 |
75 bool LayoutSVGPath::shapeDependentStrokeContains(const FloatPoint& point) | 111 bool LayoutSVGPath::shapeDependentStrokeContains(const FloatPoint& point) |
76 { | 112 { |
77 if (LayoutSVGShape::shapeDependentStrokeContains(point)) | 113 if (LayoutSVGShape::shapeDependentStrokeContains(point)) |
78 return true; | 114 return true; |
79 | 115 |
80 const SVGComputedStyle& svgStyle = style()->svgStyle(); | 116 const SVGComputedStyle& svgStyle = style()->svgStyle(); |
| 117 const float strokeWidth = this->strokeWidth(); |
81 for (size_t i = 0; i < m_zeroLengthLinecapLocations.size(); ++i) { | 118 for (size_t i = 0; i < m_zeroLengthLinecapLocations.size(); ++i) { |
82 ASSERT(svgStyle.hasStroke()); | 119 ASSERT(svgStyle.hasStroke()); |
83 float strokeWidth = this->strokeWidth(); | |
84 if (svgStyle.capStyle() == SquareCap) { | 120 if (svgStyle.capStyle() == SquareCap) { |
85 if (zeroLengthSubpathRect(m_zeroLengthLinecapLocations[i], strokeWid
th).contains(point)) | 121 if (zeroLengthSubpathRect(m_zeroLengthLinecapLocations[i], strokeWid
th).contains(point)) |
86 return true; | 122 return true; |
87 } else { | 123 } else { |
88 ASSERT(svgStyle.capStyle() == RoundCap); | 124 ASSERT(svgStyle.capStyle() == RoundCap); |
89 FloatPoint radiusVector(point.x() - m_zeroLengthLinecapLocations[i].
x(), point.y() - m_zeroLengthLinecapLocations[i].y()); | 125 FloatPoint radiusVector(point.x() - m_zeroLengthLinecapLocations[i].
x(), point.y() - m_zeroLengthLinecapLocations[i].y()); |
90 if (radiusVector.lengthSquared() < strokeWidth * strokeWidth * .25f) | 126 if (radiusVector.lengthSquared() < strokeWidth * strokeWidth * .25f) |
91 return true; | 127 return true; |
92 } | 128 } |
93 } | 129 } |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
165 ASSERT(resources); | 201 ASSERT(resources); |
166 | 202 |
167 LayoutSVGResourceMarker* markerStart = resources->markerStart(); | 203 LayoutSVGResourceMarker* markerStart = resources->markerStart(); |
168 | 204 |
169 SVGMarkerData markerData(m_markerPositions, markerStart ? markerStart->orien
tType() == SVGMarkerOrientAutoStartReverse : false); | 205 SVGMarkerData markerData(m_markerPositions, markerStart ? markerStart->orien
tType() == SVGMarkerOrientAutoStartReverse : false); |
170 path().apply(&markerData, SVGMarkerData::updateFromPathElement); | 206 path().apply(&markerData, SVGMarkerData::updateFromPathElement); |
171 markerData.pathIsDone(); | 207 markerData.pathIsDone(); |
172 } | 208 } |
173 | 209 |
174 } | 210 } |
OLD | NEW |