OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2011 University of Szeged | 2 * Copyright (C) 2011 University of Szeged |
3 * Copyright (C) 2011 Renata Hodovan <reni@webkit.org> | 3 * Copyright (C) 2011 Renata Hodovan <reni@webkit.org> |
4 * All rights reserved. | 4 * All rights reserved. |
5 * | 5 * |
6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
8 * are met: | 8 * are met: |
9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 27 matching lines...) Expand all Loading... |
38 , m_usePathFallback(false) | 38 , m_usePathFallback(false) |
39 { | 39 { |
40 } | 40 } |
41 | 41 |
42 LayoutSVGRect::~LayoutSVGRect() | 42 LayoutSVGRect::~LayoutSVGRect() |
43 { | 43 { |
44 } | 44 } |
45 | 45 |
46 void LayoutSVGRect::updateShapeFromElement() | 46 void LayoutSVGRect::updateShapeFromElement() |
47 { | 47 { |
48 // Before creating a new object we need to clear the cached bounding box | |
49 // to avoid using garbage. | |
50 m_fillBoundingBox = FloatRect(); | |
51 m_strokeBoundingBox = FloatRect(); | |
52 m_usePathFallback = false; | 48 m_usePathFallback = false; |
53 SVGRectElement* rect = toSVGRectElement(element()); | |
54 ASSERT(rect); | |
55 | 49 |
56 SVGLengthContext lengthContext(rect); | 50 // Fallback to LayoutSVGShape and path-based hit detection if the rect |
| 51 // has rounded corners or a non-scaling or non-simple stroke. |
| 52 SVGLengthContext lengthContext(toSVGRectElement(element())); |
| 53 if (lengthContext.valueForLength(styleRef().svgStyle().rx(), styleRef(), SVG
LengthMode::Width) > 0 |
| 54 || lengthContext.valueForLength(styleRef().svgStyle().ry(), styleRef(),
SVGLengthMode::Height) > 0 |
| 55 || hasNonScalingStroke() |
| 56 || !definitelyHasSimpleStroke()) { |
| 57 LayoutSVGShape::updateShapeFromElement(); |
| 58 m_usePathFallback = true; |
| 59 return; |
| 60 } |
| 61 |
| 62 clearPath(); |
| 63 } |
| 64 |
| 65 void LayoutSVGRect::updateStrokeAndFillBoundingBoxes() |
| 66 { |
| 67 SVGLengthContext lengthContext(toSVGRectElement(element())); |
57 FloatSize boundingBoxSize( | 68 FloatSize boundingBoxSize( |
58 lengthContext.valueForLength(styleRef().width(), styleRef(), SVGLengthMo
de::Width), | 69 lengthContext.valueForLength(styleRef().width(), styleRef(), SVGLengthMo
de::Width), |
59 lengthContext.valueForLength(styleRef().height(), styleRef(), SVGLengthM
ode::Height)); | 70 lengthContext.valueForLength(styleRef().height(), styleRef(), SVGLengthM
ode::Height)); |
60 | 71 |
61 // Spec: "A negative value is an error." | 72 // Spec: "A negative value is an error." |
62 if (boundingBoxSize.width() < 0 || boundingBoxSize.height() < 0) | 73 if (boundingBoxSize.width() < 0 || boundingBoxSize.height() < 0) { |
| 74 m_fillBoundingBox = FloatRect(); |
| 75 m_strokeBoundingBox = FloatRect(); |
63 return; | 76 return; |
| 77 } |
64 | 78 |
65 // Spec: "A value of zero disables rendering of the element." | 79 if (m_usePathFallback) { |
66 if (!boundingBoxSize.isEmpty()) { | 80 // Spec: "A value of zero disables rendering of the element." so we can
skip |
67 // Fallback to LayoutSVGShape and path-based hit detection if the rect | 81 // the path fallback and rely on the existing bounding box calculation. |
68 // has rounded corners or a non-scaling or non-simple stroke. | 82 if (!boundingBoxSize.isEmpty()) { |
69 if (lengthContext.valueForLength(styleRef().svgStyle().rx(), styleRef(),
SVGLengthMode::Width) > 0 | 83 LayoutSVGShape::updateStrokeAndFillBoundingBoxes(); |
70 || lengthContext.valueForLength(styleRef().svgStyle().ry(), styleRef
(), SVGLengthMode::Height) > 0 | |
71 || hasNonScalingStroke() | |
72 || !definitelyHasSimpleStroke()) { | |
73 LayoutSVGShape::updateShapeFromElement(); | |
74 m_usePathFallback = true; | |
75 return; | 84 return; |
76 } | 85 } |
| 86 m_usePathFallback = false; |
| 87 clearPath(); |
77 } | 88 } |
78 | 89 |
79 m_fillBoundingBox = FloatRect( | 90 m_fillBoundingBox = FloatRect( |
80 FloatPoint( | 91 FloatPoint( |
81 lengthContext.valueForLength(styleRef().svgStyle().x(), styleRef(),
SVGLengthMode::Width), | 92 lengthContext.valueForLength(styleRef().svgStyle().x(), styleRef(),
SVGLengthMode::Width), |
82 lengthContext.valueForLength(styleRef().svgStyle().y(), styleRef(),
SVGLengthMode::Height)), | 93 lengthContext.valueForLength(styleRef().svgStyle().y(), styleRef(),
SVGLengthMode::Height)), |
83 boundingBoxSize); | 94 boundingBoxSize); |
84 m_strokeBoundingBox = m_fillBoundingBox; | 95 m_strokeBoundingBox = m_fillBoundingBox; |
85 if (style()->svgStyle().hasStroke()) | 96 if (style()->svgStyle().hasStroke()) |
86 m_strokeBoundingBox.inflate(strokeWidth() / 2); | 97 m_strokeBoundingBox.inflate(strokeWidth() / 2); |
87 } | 98 } |
88 | 99 |
89 bool LayoutSVGRect::shapeDependentStrokeContains(const FloatPoint& point) | 100 bool LayoutSVGRect::shapeDependentStrokeContains(const FloatPoint& point) |
90 { | 101 { |
91 // The optimized code below does not support non-simple strokes so we need | 102 // The optimized code below does not support non-simple strokes so we need |
92 // to fall back to LayoutSVGShape::shapeDependentStrokeContains in these cas
es. | 103 // to fall back to LayoutSVGShape::shapeDependentStrokeContains in these cas
es. |
93 if (m_usePathFallback || !definitelyHasSimpleStroke()) { | 104 if (m_usePathFallback || !definitelyHasSimpleStroke()) { |
94 if (!hasPath()) | 105 if (!m_usePathFallback) |
95 LayoutSVGShape::updateShapeFromElement(); | 106 LayoutSVGShape::updateShapeFromElement(); |
96 return LayoutSVGShape::shapeDependentStrokeContains(point); | 107 return LayoutSVGShape::shapeDependentStrokeContains(point); |
97 } | 108 } |
98 | 109 |
99 const float halfStrokeWidth = strokeWidth() / 2; | 110 const float halfStrokeWidth = strokeWidth() / 2; |
100 const float halfWidth = m_fillBoundingBox.width() / 2; | 111 const float halfWidth = m_fillBoundingBox.width() / 2; |
101 const float halfHeight = m_fillBoundingBox.height() / 2; | 112 const float halfHeight = m_fillBoundingBox.height() / 2; |
102 | 113 |
103 const FloatPoint fillBoundingBoxCenter = FloatPoint(m_fillBoundingBox.x() +
halfWidth, m_fillBoundingBox.y() + halfHeight); | 114 const FloatPoint fillBoundingBoxCenter = FloatPoint(m_fillBoundingBox.x() +
halfWidth, m_fillBoundingBox.y() + halfHeight); |
104 const float absDeltaX = std::abs(point.x() - fillBoundingBoxCenter.x()); | 115 const float absDeltaX = std::abs(point.x() - fillBoundingBoxCenter.x()); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 // An approximation of sqrt(2) is used here because at certain precise | 149 // An approximation of sqrt(2) is used here because at certain precise |
139 // miterlimits, the join style used might not be correct (e.g. a miterlimit | 150 // miterlimits, the join style used might not be correct (e.g. a miterlimit |
140 // of 1.4142135 should result in bevel joins, but may be drawn using miter | 151 // of 1.4142135 should result in bevel joins, but may be drawn using miter |
141 // joins). | 152 // joins). |
142 return svgStyle.strokeDashArray()->isEmpty() | 153 return svgStyle.strokeDashArray()->isEmpty() |
143 && svgStyle.joinStyle() == MiterJoin | 154 && svgStyle.joinStyle() == MiterJoin |
144 && svgStyle.strokeMiterLimit() >= 1.5; | 155 && svgStyle.strokeMiterLimit() >= 1.5; |
145 } | 156 } |
146 | 157 |
147 } | 158 } |
OLD | NEW |