Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(117)

Side by Side Diff: Source/core/layout/svg/LayoutSVGEllipse.cpp

Issue 1158583003: Reduce how often LayoutSVGShape::updateShapeFromElement is called (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Put selfHasRelativeLengths back Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « Source/core/layout/svg/LayoutSVGEllipse.h ('k') | Source/core/layout/svg/LayoutSVGPath.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2012 Google, Inc. 2 * Copyright (C) 2012 Google, Inc.
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 27 matching lines...) Expand all
38 LayoutSVGEllipse::LayoutSVGEllipse(SVGGeometryElement* node) 38 LayoutSVGEllipse::LayoutSVGEllipse(SVGGeometryElement* node)
39 : LayoutSVGShape(node) 39 : LayoutSVGShape(node)
40 , m_usePathFallback(false) 40 , m_usePathFallback(false)
41 { 41 {
42 } 42 }
43 43
44 LayoutSVGEllipse::~LayoutSVGEllipse() 44 LayoutSVGEllipse::~LayoutSVGEllipse()
45 { 45 {
46 } 46 }
47 47
48 void LayoutSVGEllipse::styleDidChange(StyleDifference diff, const ComputedStyle* oldStyle)
49 {
50 if (diff.needsFullLayout() && oldStyle) {
51 const SVGComputedStyle& oldSvgStyle = oldStyle->svgStyle();
52 const SVGComputedStyle& svgStyle = style()->svgStyle();
53
54 bool radiusChanged;
55 if (isSVGCircleElement(*element()))
56 radiusChanged = oldSvgStyle.r() != svgStyle.r();
57 else
58 radiusChanged = (oldSvgStyle.rx() != svgStyle.rx()) || (oldSvgStyle. ry() != svgStyle.ry());
59
60 if (oldSvgStyle.cx() != svgStyle.cx()
61 || oldSvgStyle.cy() != svgStyle.cy()
62 || radiusChanged
63 || oldSvgStyle.vectorEffect() != svgStyle.vectorEffect()
64 || hasContinuousStroke(oldSvgStyle) != hasContinuousStroke(svgStyle) )
65 setNeedsShapeUpdate();
66 }
67
68 // Superclass will take care of calling clientStyleChanged.
69 LayoutSVGShape::styleDidChange(diff, oldStyle);
70 }
71
48 void LayoutSVGEllipse::updateShapeFromElement() 72 void LayoutSVGEllipse::updateShapeFromElement()
49 { 73 {
50 // Before creating a new object we need to clear the cached bounding box
51 // to avoid using garbage.
52 m_fillBoundingBox = FloatRect();
53 m_strokeBoundingBox = FloatRect();
54 m_center = FloatPoint();
55 m_radii = FloatSize();
56 m_usePathFallback = false; 74 m_usePathFallback = false;
57
58 calculateRadiiAndCenter(); 75 calculateRadiiAndCenter();
59 76
60 // Spec: "A negative value is an error. A value of zero disables rendering o f the element." 77 // Fall back to LayoutSVGShape and path-based hit detection if the ellipse
61 if (m_radii.width() < 0 || m_radii.height() < 0) 78 // has a non-scaling or discontinuous stroke.
79 if (hasNonScalingStroke() || !hasContinuousStroke(style()->svgStyle())) {
80 LayoutSVGShape::updateShapeFromElement();
81 m_usePathFallback = true;
62 return; 82 return;
63
64 if (!m_radii.isEmpty()) {
65 // Fall back to LayoutSVGShape and path-based hit detection if the ellip se
66 // has a non-scaling or discontinuous stroke.
67 if (hasNonScalingStroke() || !hasContinuousStroke()) {
68 LayoutSVGShape::updateShapeFromElement();
69 m_usePathFallback = true;
70 return;
71 }
72 } 83 }
73 84
74 clearPath(); 85 clearPath();
75
76 m_fillBoundingBox = FloatRect(m_center.x() - m_radii.width(), m_center.y() - m_radii.height(), 2 * m_radii.width(), 2 * m_radii.height());
77 m_strokeBoundingBox = m_fillBoundingBox;
78 if (style()->svgStyle().hasStroke())
79 m_strokeBoundingBox.inflate(strokeWidth() / 2);
80 } 86 }
81 87
82 void LayoutSVGEllipse::calculateRadiiAndCenter() 88 void LayoutSVGEllipse::calculateRadiiAndCenter()
83 { 89 {
84 ASSERT(element()); 90 ASSERT(element());
85 SVGLengthContext lengthContext(element()); 91 SVGLengthContext lengthContext(element());
86 m_center = FloatPoint( 92 m_center = FloatPoint(
87 lengthContext.valueForLength(style()->svgStyle().cx(), styleRef(), SVGLe ngthMode::Width), 93 lengthContext.valueForLength(style()->svgStyle().cx(), styleRef(), SVGLe ngthMode::Width),
88 lengthContext.valueForLength(style()->svgStyle().cy(), styleRef(), SVGLe ngthMode::Height)); 94 lengthContext.valueForLength(style()->svgStyle().cy(), styleRef(), SVGLe ngthMode::Height));
89 95
90 if (isSVGCircleElement(*element())) { 96 if (isSVGCircleElement(*element())) {
91 float radius = lengthContext.valueForLength(style()->svgStyle().r(), sty leRef(), SVGLengthMode::Other); 97 float radius = lengthContext.valueForLength(style()->svgStyle().r(), sty leRef(), SVGLengthMode::Other);
92 m_radii = FloatSize(radius, radius); 98 m_radii = FloatSize(radius, radius);
93 } else { 99 } else {
94 m_radii = FloatSize( 100 m_radii = FloatSize(
95 lengthContext.valueForLength(style()->svgStyle().rx(), styleRef(), S VGLengthMode::Width), 101 lengthContext.valueForLength(style()->svgStyle().rx(), styleRef(), S VGLengthMode::Width),
96 lengthContext.valueForLength(style()->svgStyle().ry(), styleRef(), S VGLengthMode::Height)); 102 lengthContext.valueForLength(style()->svgStyle().ry(), styleRef(), S VGLengthMode::Height));
97 } 103 }
98 } 104 }
99 105
106 void LayoutSVGEllipse::updateStrokeAndFillBoundingBoxes()
107 {
108 // Spec: "A negative value is an error."
109 if (m_radii.width() < 0 || m_radii.height() < 0) {
110 m_fillBoundingBox = FloatRect();
111 m_strokeBoundingBox = FloatRect();
112 return;
113 }
114
115 if (m_usePathFallback) {
116 // Spec: "A value of zero disables rendering of the element." so we can skip
117 // the path fallback and rely on the existing bounding box calculation.
118 if (!m_radii.isEmpty()) {
119 LayoutSVGShape::updateStrokeAndFillBoundingBoxes();
120 return;
121 }
122 m_usePathFallback = false;
123 clearPath();
124 }
125
126 m_fillBoundingBox = FloatRect(m_center.x() - m_radii.width(), m_center.y() - m_radii.height(), 2 * m_radii.width(), 2 * m_radii.height());
127 m_strokeBoundingBox = m_fillBoundingBox;
128 if (style()->svgStyle().hasStroke())
129 m_strokeBoundingBox.inflate(strokeWidth() / 2);
130 }
131
100 bool LayoutSVGEllipse::shapeDependentStrokeContains(const FloatPoint& point) 132 bool LayoutSVGEllipse::shapeDependentStrokeContains(const FloatPoint& point)
101 { 133 {
102 // The optimized check below for circles does not support non-scaling or 134 // The optimized check below for circles does not support non-scaling or
103 // discontinuous strokes. 135 // discontinuous strokes.
104 if (m_usePathFallback 136 if (m_usePathFallback
105 || !hasContinuousStroke() 137 || !hasContinuousStroke(style()->svgStyle())
106 || m_radii.width() != m_radii.height()) { 138 || m_radii.width() != m_radii.height()) {
107 if (!hasPath()) 139 if (!m_usePathFallback)
108 createPath(); 140 LayoutSVGShape::updateShapeFromElement();
109 return LayoutSVGShape::shapeDependentStrokeContains(point); 141 return LayoutSVGShape::shapeDependentStrokeContains(point);
110 } 142 }
111 143
112 const FloatPoint center = FloatPoint(m_center.x() - point.x(), m_center.y() - point.y()); 144 const FloatPoint center = FloatPoint(m_center.x() - point.x(), m_center.y() - point.y());
113 const float halfStrokeWidth = strokeWidth() / 2; 145 const float halfStrokeWidth = strokeWidth() / 2;
114 const float r = m_radii.width(); 146 const float r = m_radii.width();
115 return std::abs(center.length() - r) <= halfStrokeWidth; 147 return std::abs(center.length() - r) <= halfStrokeWidth;
116 } 148 }
117 149
118 bool LayoutSVGEllipse::shapeDependentFillContains(const FloatPoint& point, const WindRule fillRule) const 150 bool LayoutSVGEllipse::shapeDependentFillContains(const FloatPoint& point, const WindRule fillRule) const
119 { 151 {
120 const FloatPoint center = FloatPoint(m_center.x() - point.x(), m_center.y() - point.y()); 152 const FloatPoint center = FloatPoint(m_center.x() - point.x(), m_center.y() - point.y());
121 153
122 // This works by checking if the point satisfies the ellipse equation. 154 // This works by checking if the point satisfies the ellipse equation.
123 // (x/rX)^2 + (y/rY)^2 <= 1 155 // (x/rX)^2 + (y/rY)^2 <= 1
124 const float xrX = center.x() / m_radii.width(); 156 const float xrX = center.x() / m_radii.width();
125 const float yrY = center.y() / m_radii.height(); 157 const float yrY = center.y() / m_radii.height();
126 return xrX * xrX + yrY * yrY <= 1.0; 158 return xrX * xrX + yrY * yrY <= 1.0;
127 } 159 }
128 160
129 bool LayoutSVGEllipse::hasContinuousStroke() const 161 bool LayoutSVGEllipse::hasContinuousStroke(const SVGComputedStyle& svgStyle) con st
130 { 162 {
131 const SVGComputedStyle& svgStyle = style()->svgStyle();
132 return svgStyle.strokeDashArray()->isEmpty(); 163 return svgStyle.strokeDashArray()->isEmpty();
133 } 164 }
134 165
135 } 166 }
OLDNEW
« no previous file with comments | « Source/core/layout/svg/LayoutSVGEllipse.h ('k') | Source/core/layout/svg/LayoutSVGPath.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698