| 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 14 matching lines...) Expand all Loading... |
| 25 * Boston, MA 02110-1301, USA. | 25 * Boston, MA 02110-1301, USA. |
| 26 */ | 26 */ |
| 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" | |
| 36 #include "core/svg/SVGGeometryElement.h" | 35 #include "core/svg/SVGGeometryElement.h" |
| 37 #include "wtf/MathExtras.h" | 36 #include "wtf/MathExtras.h" |
| 38 | 37 |
| 39 namespace blink { | 38 namespace blink { |
| 40 | 39 |
| 41 LayoutSVGPath::LayoutSVGPath(SVGGeometryElement* node) | 40 LayoutSVGPath::LayoutSVGPath(SVGGeometryElement* node) |
| 42 : LayoutSVGShape(node) | 41 : LayoutSVGShape(node) |
| 43 { | 42 { |
| 44 } | 43 } |
| 45 | 44 |
| 46 LayoutSVGPath::~LayoutSVGPath() | 45 LayoutSVGPath::~LayoutSVGPath() |
| 47 { | 46 { |
| 48 } | 47 } |
| 49 | 48 |
| 50 void LayoutSVGPath::updateShapeFromElement() | |
| 51 { | |
| 52 LayoutSVGShape::updateShapeFromElement(); | |
| 53 updateZeroLengthSubpaths(); | |
| 54 } | |
| 55 | |
| 56 void LayoutSVGPath::updateStrokeAndFillBoundingBoxes() | 49 void LayoutSVGPath::updateStrokeAndFillBoundingBoxes() |
| 57 { | 50 { |
| 58 LayoutSVGShape::updateStrokeAndFillBoundingBoxes(); | 51 LayoutSVGShape::updateStrokeAndFillBoundingBoxes(); |
| 59 | 52 |
| 60 // TODO(pdr): We should only call this in updateShapeFromElement. | 53 // TODO(pdr): We should only call this in updateShapeFromElement. |
| 61 processMarkerPositions(); | 54 processMarkerPositions(); |
| 62 if (!m_markerPositions.isEmpty()) | 55 if (!m_markerPositions.isEmpty()) |
| 63 m_strokeBoundingBox.unite(markerRect(strokeWidth())); | 56 m_strokeBoundingBox.unite(markerRect(strokeWidth())); |
| 64 | |
| 65 if (style()->svgStyle().hasStroke()) { | |
| 66 // FIXME: zero-length subpaths do not respect vector-effect = non-scalin
g-stroke. | |
| 67 float strokeWidth = this->strokeWidth(); | |
| 68 for (size_t i = 0; i < m_zeroLengthLinecapLocations.size(); ++i) | |
| 69 m_strokeBoundingBox.unite(zeroLengthSubpathRect(m_zeroLengthLinecapL
ocations[i], strokeWidth)); | |
| 70 } | |
| 71 } | 57 } |
| 72 | 58 |
| 73 FloatRect LayoutSVGPath::hitTestStrokeBoundingBox() const | 59 FloatRect LayoutSVGPath::hitTestStrokeBoundingBox() const |
| 74 { | 60 { |
| 75 const SVGComputedStyle& svgStyle = style()->svgStyle(); | 61 const SVGComputedStyle& svgStyle = style()->svgStyle(); |
| 76 if (svgStyle.hasStroke()) | 62 if (svgStyle.hasStroke()) |
| 77 return m_strokeBoundingBox; | 63 return m_strokeBoundingBox; |
| 78 | 64 |
| 79 // Implementation of http://dev.w3.org/fxtf/css-masking-1/#compute-stroke-bo
unding-box | 65 // Implementation of http://dev.w3.org/fxtf/css-masking-1/#compute-stroke-bo
unding-box |
| 80 // except that we ignore whether the stroke is none. | 66 // except that we ignore whether the stroke is none. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 91 const float miter = svgStyle.strokeMiterLimit(); | 77 const float miter = svgStyle.strokeMiterLimit(); |
| 92 if (miter < M_SQRT2 && svgStyle.hasSquareCapStyle()) | 78 if (miter < M_SQRT2 && svgStyle.hasSquareCapStyle()) |
| 93 delta *= M_SQRT2; | 79 delta *= M_SQRT2; |
| 94 else | 80 else |
| 95 delta *= miter; | 81 delta *= miter; |
| 96 } else if (svgStyle.hasSquareCapStyle()) { | 82 } else if (svgStyle.hasSquareCapStyle()) { |
| 97 delta *= M_SQRT2; | 83 delta *= M_SQRT2; |
| 98 } | 84 } |
| 99 | 85 |
| 100 box.inflate(delta); | 86 box.inflate(delta); |
| 101 | |
| 102 for (size_t i = 0; i < m_zeroLengthLinecapLocations.size(); ++i) | |
| 103 box.unite(zeroLengthSubpathRect(m_zeroLengthLinecapLocations[i], strokeW
idth)); | |
| 104 | |
| 105 return box; | 87 return box; |
| 106 } | 88 } |
| 107 | 89 |
| 108 bool LayoutSVGPath::shapeDependentStrokeContains(const FloatPoint& point) | |
| 109 { | |
| 110 if (LayoutSVGShape::shapeDependentStrokeContains(point)) | |
| 111 return true; | |
| 112 | |
| 113 const SVGComputedStyle& svgStyle = style()->svgStyle(); | |
| 114 const float strokeWidth = this->strokeWidth(); | |
| 115 for (size_t i = 0; i < m_zeroLengthLinecapLocations.size(); ++i) { | |
| 116 ASSERT(svgStyle.hasStroke()); | |
| 117 if (svgStyle.capStyle() == SquareCap) { | |
| 118 if (zeroLengthSubpathRect(m_zeroLengthLinecapLocations[i], strokeWid
th).contains(point)) | |
| 119 return true; | |
| 120 } else { | |
| 121 ASSERT(svgStyle.capStyle() == RoundCap); | |
| 122 FloatPoint radiusVector(point.x() - m_zeroLengthLinecapLocations[i].
x(), point.y() - m_zeroLengthLinecapLocations[i].y()); | |
| 123 if (radiusVector.lengthSquared() < strokeWidth * strokeWidth * .25f) | |
| 124 return true; | |
| 125 } | |
| 126 } | |
| 127 return false; | |
| 128 } | |
| 129 | |
| 130 bool LayoutSVGPath::shouldStrokeZeroLengthSubpath() const | |
| 131 { | |
| 132 // Spec(11.4): Any zero length subpath shall not be stroked if the "stroke-l
inecap" property has a value of butt | |
| 133 // but shall be stroked if the "stroke-linecap" property has a value of roun
d or square | |
| 134 return style()->svgStyle().hasStroke() && style()->svgStyle().capStyle() !=
ButtCap; | |
| 135 } | |
| 136 | |
| 137 FloatRect LayoutSVGPath::zeroLengthSubpathRect(const FloatPoint& linecapPosition
, float strokeWidth) | |
| 138 { | |
| 139 return FloatRect(linecapPosition.x() - strokeWidth / 2, linecapPosition.y()
- strokeWidth / 2, strokeWidth, strokeWidth); | |
| 140 } | |
| 141 | |
| 142 void LayoutSVGPath::updateZeroLengthSubpaths() | |
| 143 { | |
| 144 m_zeroLengthLinecapLocations.clear(); | |
| 145 | |
| 146 if (!strokeWidth() || !shouldStrokeZeroLengthSubpath()) | |
| 147 return; | |
| 148 | |
| 149 SVGSubpathData subpathData(m_zeroLengthLinecapLocations); | |
| 150 path().apply(&subpathData, SVGSubpathData::updateFromPathElement); | |
| 151 subpathData.pathIsDone(); | |
| 152 } | |
| 153 | |
| 154 FloatRect LayoutSVGPath::markerRect(float strokeWidth) const | 90 FloatRect LayoutSVGPath::markerRect(float strokeWidth) const |
| 155 { | 91 { |
| 156 ASSERT(!m_markerPositions.isEmpty()); | 92 ASSERT(!m_markerPositions.isEmpty()); |
| 157 | 93 |
| 158 SVGResources* resources = SVGResourcesCache::cachedResourcesForLayoutObject(
this); | 94 SVGResources* resources = SVGResourcesCache::cachedResourcesForLayoutObject(
this); |
| 159 ASSERT(resources); | 95 ASSERT(resources); |
| 160 | 96 |
| 161 LayoutSVGResourceMarker* markerStart = resources->markerStart(); | 97 LayoutSVGResourceMarker* markerStart = resources->markerStart(); |
| 162 LayoutSVGResourceMarker* markerMid = resources->markerMid(); | 98 LayoutSVGResourceMarker* markerMid = resources->markerMid(); |
| 163 LayoutSVGResourceMarker* markerEnd = resources->markerEnd(); | 99 LayoutSVGResourceMarker* markerEnd = resources->markerEnd(); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 ASSERT(resources); | 134 ASSERT(resources); |
| 199 | 135 |
| 200 LayoutSVGResourceMarker* markerStart = resources->markerStart(); | 136 LayoutSVGResourceMarker* markerStart = resources->markerStart(); |
| 201 | 137 |
| 202 SVGMarkerData markerData(m_markerPositions, markerStart ? markerStart->orien
tType() == SVGMarkerOrientAutoStartReverse : false); | 138 SVGMarkerData markerData(m_markerPositions, markerStart ? markerStart->orien
tType() == SVGMarkerOrientAutoStartReverse : false); |
| 203 path().apply(&markerData, SVGMarkerData::updateFromPathElement); | 139 path().apply(&markerData, SVGMarkerData::updateFromPathElement); |
| 204 markerData.pathIsDone(); | 140 markerData.pathIsDone(); |
| 205 } | 141 } |
| 206 | 142 |
| 207 } | 143 } |
| OLD | NEW |