OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |