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

Side by Side Diff: Source/platform/graphics/PathTraversalState.cpp

Issue 190943002: [SVG] Fix infinite curveLength() loop. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 9 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
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2006, 2007 Eric Seidel <eric@webkit.org> 2 * Copyright (C) 2006, 2007 Eric Seidel <eric@webkit.org>
3 * 3 *
4 * This library is free software; you can redistribute it and/or 4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public 5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either 6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version. 7 * version 2 of the License, or (at your option) any later version.
8 * 8 *
9 * This library is distributed in the hope that it will be useful, 9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 , control(c) 44 , control(c)
45 , end(e) 45 , end(e)
46 { 46 {
47 } 47 }
48 48
49 float approximateDistance() const 49 float approximateDistance() const
50 { 50 {
51 return distanceLine(start, control) + distanceLine(control, end); 51 return distanceLine(start, control) + distanceLine(control, end);
52 } 52 }
53 53
54 void split(QuadraticBezier& left, QuadraticBezier& right) const 54 bool equals(const QuadraticBezier& other) const
55 {
56 return start == other.start
57 && end == other.end
58 && control == other.control;
59 }
60
61 bool split(QuadraticBezier& left, QuadraticBezier& right) const
55 { 62 {
56 left.control = midPoint(start, control); 63 left.control = midPoint(start, control);
57 right.control = midPoint(control, end); 64 right.control = midPoint(control, end);
58 65
59 FloatPoint leftControlToRightControl = midPoint(left.control, right.cont rol); 66 FloatPoint leftControlToRightControl = midPoint(left.control, right.cont rol);
60 left.end = leftControlToRightControl; 67 left.end = leftControlToRightControl;
61 right.start = leftControlToRightControl; 68 right.start = leftControlToRightControl;
62 69
63 left.start = start; 70 left.start = start;
64 right.end = end; 71 right.end = end;
72
73 return !equals(left) && !equals(right);
65 } 74 }
66 75
67 FloatPoint start; 76 FloatPoint start;
68 FloatPoint control; 77 FloatPoint control;
69 FloatPoint end; 78 FloatPoint end;
70 }; 79 };
71 80
72 struct CubicBezier { 81 struct CubicBezier {
73 CubicBezier() { } 82 CubicBezier() { }
74 CubicBezier(const FloatPoint& s, const FloatPoint& c1, const FloatPoint& c2, const FloatPoint& e) 83 CubicBezier(const FloatPoint& s, const FloatPoint& c1, const FloatPoint& c2, const FloatPoint& e)
75 : start(s) 84 : start(s)
76 , control1(c1) 85 , control1(c1)
77 , control2(c2) 86 , control2(c2)
78 , end(e) 87 , end(e)
79 { 88 {
80 } 89 }
81 90
82 float approximateDistance() const 91 float approximateDistance() const
83 { 92 {
84 return distanceLine(start, control1) + distanceLine(control1, control2) + distanceLine(control2, end); 93 return distanceLine(start, control1) + distanceLine(control1, control2) + distanceLine(control2, end);
85 } 94 }
86 95
87 void split(CubicBezier& left, CubicBezier& right) const 96 bool equals(const CubicBezier& other) const
97 {
98 return start == other.start
99 && end == other.end
100 && control1 == other.control1
101 && control2 == other.control2;
102 }
103
104 bool split(CubicBezier& left, CubicBezier& right) const
88 { 105 {
89 FloatPoint startToControl1 = midPoint(control1, control2); 106 FloatPoint startToControl1 = midPoint(control1, control2);
90 107
91 left.start = start; 108 left.start = start;
92 left.control1 = midPoint(start, control1); 109 left.control1 = midPoint(start, control1);
93 left.control2 = midPoint(left.control1, startToControl1); 110 left.control2 = midPoint(left.control1, startToControl1);
94 111
95 right.control2 = midPoint(control2, end); 112 right.control2 = midPoint(control2, end);
96 right.control1 = midPoint(right.control2, startToControl1); 113 right.control1 = midPoint(right.control2, startToControl1);
97 right.end = end; 114 right.end = end;
98 115
99 FloatPoint leftControl2ToRightControl1 = midPoint(left.control2, right.c ontrol1); 116 FloatPoint leftControl2ToRightControl1 = midPoint(left.control2, right.c ontrol1);
100 left.end = leftControl2ToRightControl1; 117 left.end = leftControl2ToRightControl1;
101 right.start = leftControl2ToRightControl1; 118 right.start = leftControl2ToRightControl1;
119
120 return !equals(left) && !equals(right);
102 } 121 }
103 122
104 FloatPoint start; 123 FloatPoint start;
105 FloatPoint control1; 124 FloatPoint control1;
106 FloatPoint control2; 125 FloatPoint control2;
107 FloatPoint end; 126 FloatPoint end;
108 }; 127 };
109 128
110 // FIXME: This function is possibly very slow due to the ifs required for proper path measuring 129 // FIXME: This function is possibly very slow due to the ifs required for proper path measuring
111 // A simple speed-up would be to use an additional boolean template parameter to control whether 130 // A simple speed-up would be to use an additional boolean template parameter to control whether
112 // to use the "fast" version of this function with no PathTraversalState updatin g, vs. the slow 131 // to use the "fast" version of this function with no PathTraversalState updatin g, vs. the slow
113 // version which does update the PathTraversalState. We'll have to shark it to s ee if that's necessary. 132 // version which does update the PathTraversalState. We'll have to shark it to s ee if that's necessary.
114 // Another check which is possible up-front (to send us down the fast path) woul d be to check if 133 // Another check which is possible up-front (to send us down the fast path) woul d be to check if
115 // approximateDistance() + current total distance > desired distance 134 // approximateDistance() + current total distance > desired distance
116 template<class CurveType> 135 template<class CurveType>
117 static float curveLength(PathTraversalState& traversalState, CurveType curve) 136 static float curveLength(PathTraversalState& traversalState, CurveType curve)
118 { 137 {
119 static const unsigned curveStackDepthLimit = 20; 138 static const unsigned curveStackDepthLimit = 20;
120 139
121 Vector<CurveType> curveStack; 140 Vector<CurveType> curveStack;
122 curveStack.append(curve); 141 curveStack.append(curve);
123 142
124 float totalLength = 0; 143 float totalLength = 0;
144 CurveType leftCurve, rightCurve;
125 do { 145 do {
126 float length = curve.approximateDistance(); 146 float length = curve.approximateDistance();
127 if ((length - distanceLine(curve.start, curve.end)) > kPathSegmentLength Tolerance && curveStack.size() <= curveStackDepthLimit) { 147 if ((length - distanceLine(curve.start, curve.end)) > kPathSegmentLength Tolerance
Stephen Chennney 2014/03/07 16:25:31 The real problem is that tolerance is a fixed valu
f(malita) 2014/03/07 18:02:26 I disagree: the immediate problem is that the algo
f(malita) 2014/03/07 19:14:08 Come to think of it, it's obvious this would not w
128 CurveType leftCurve; 148 && curveStack.size() <= curveStackDepthLimit
129 CurveType rightCurve; 149 && curve.split(leftCurve, rightCurve)) {
130 curve.split(leftCurve, rightCurve);
131 curve = leftCurve; 150 curve = leftCurve;
132 curveStack.append(rightCurve); 151 curveStack.append(rightCurve);
133 } else { 152 } else {
134 totalLength += length; 153 totalLength += length;
135 if (traversalState.m_action == PathTraversalState::TraversalPointAtL ength || traversalState.m_action == PathTraversalState::TraversalNormalAngleAtLe ngth) { 154 if (traversalState.m_action == PathTraversalState::TraversalPointAtL ength || traversalState.m_action == PathTraversalState::TraversalNormalAngleAtLe ngth) {
136 traversalState.m_previous = curve.start; 155 traversalState.m_previous = curve.start;
137 traversalState.m_current = curve.end; 156 traversalState.m_current = curve.end;
138 if (traversalState.m_totalLength + totalLength > traversalState. m_desiredLength) 157 if (traversalState.m_totalLength + totalLength > traversalState. m_desiredLength)
139 return totalLength; 158 return totalLength;
140 } 159 }
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 } else { 234 } else {
216 m_normalAngle = rad2deg(slope); 235 m_normalAngle = rad2deg(slope);
217 } 236 }
218 m_success = true; 237 m_success = true;
219 } 238 }
220 m_previous = m_current; 239 m_previous = m_current;
221 } 240 }
222 241
223 } 242 }
224 243
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698