diff options
Diffstat (limited to 'chromium/third_party/WebKit/Source/platform/graphics/PathTraversalState.cpp')
-rw-r--r-- | chromium/third_party/WebKit/Source/platform/graphics/PathTraversalState.cpp | 48 |
1 files changed, 29 insertions, 19 deletions
diff --git a/chromium/third_party/WebKit/Source/platform/graphics/PathTraversalState.cpp b/chromium/third_party/WebKit/Source/platform/graphics/PathTraversalState.cpp index 406c5b180cd..862ae8686e0 100644 --- a/chromium/third_party/WebKit/Source/platform/graphics/PathTraversalState.cpp +++ b/chromium/third_party/WebKit/Source/platform/graphics/PathTraversalState.cpp @@ -25,8 +25,6 @@ namespace WebCore { -static const float kPathSegmentLengthTolerance = 0.00001f; - static inline FloatPoint midPoint(const FloatPoint& first, const FloatPoint& second) { return FloatPoint((first.x() + second.x()) / 2.0f, (first.y() + second.y()) / 2.0f); @@ -43,7 +41,13 @@ struct QuadraticBezier { : start(s) , control(c) , end(e) + , splitDepth(0) + { + } + + double magnitudeSquared() const { + return ((double)(start.dot(start)) + (double)(control.dot(control)) + (double)(end.dot(end))) / 9.0; } float approximateDistance() const @@ -62,11 +66,14 @@ struct QuadraticBezier { left.start = start; right.end = end; + + left.splitDepth = right.splitDepth = splitDepth + 1; } FloatPoint start; FloatPoint control; FloatPoint end; + unsigned short splitDepth; }; struct CubicBezier { @@ -76,7 +83,13 @@ struct CubicBezier { , control1(c1) , control2(c2) , end(e) + , splitDepth(0) + { + } + + double magnitudeSquared() const { + return ((double)(start.dot(start)) + (double)(control1.dot(control1)) + (double)(control2.dot(control2)) + (double)(end.dot(end))) / 16.0; } float approximateDistance() const @@ -99,24 +112,26 @@ struct CubicBezier { FloatPoint leftControl2ToRightControl1 = midPoint(left.control2, right.control1); left.end = leftControl2ToRightControl1; right.start = leftControl2ToRightControl1; + + left.splitDepth = right.splitDepth = splitDepth + 1; } FloatPoint start; FloatPoint control1; FloatPoint control2; FloatPoint end; + unsigned short splitDepth; }; -// FIXME: This function is possibly very slow due to the ifs required for proper path measuring -// A simple speed-up would be to use an additional boolean template parameter to control whether -// to use the "fast" version of this function with no PathTraversalState updating, vs. the slow -// version which does update the PathTraversalState. We'll have to shark it to see if that's necessary. -// Another check which is possible up-front (to send us down the fast path) would be to check if -// approximateDistance() + current total distance > desired distance template<class CurveType> static float curveLength(PathTraversalState& traversalState, CurveType curve) { - static const unsigned curveStackDepthLimit = 20; + static const unsigned short curveSplitDepthLimit = 20; + static const double pathSegmentLengthToleranceSquared = 1.e-16; + + double curveScaleForToleranceSquared = curve.magnitudeSquared(); + if (curveScaleForToleranceSquared < pathSegmentLengthToleranceSquared) + return 0; Vector<CurveType> curveStack; curveStack.append(curve); @@ -124,7 +139,8 @@ static float curveLength(PathTraversalState& traversalState, CurveType curve) float totalLength = 0; do { float length = curve.approximateDistance(); - if ((length - distanceLine(curve.start, curve.end)) > kPathSegmentLengthTolerance && curveStack.size() <= curveStackDepthLimit) { + double lengthDiscrepancy = length - distanceLine(curve.start, curve.end); + if ((lengthDiscrepancy * lengthDiscrepancy) / curveScaleForToleranceSquared > pathSegmentLengthToleranceSquared && curve.splitDepth < curveSplitDepthLimit) { CurveType leftCurve; CurveType rightCurve; curve.split(leftCurve, rightCurve); @@ -159,20 +175,20 @@ PathTraversalState::PathTraversalState(PathTraversalAction action) float PathTraversalState::closeSubpath() { float distance = distanceLine(m_current, m_start); - m_current = m_control1 = m_control2 = m_start; + m_current = m_start; return distance; } float PathTraversalState::moveTo(const FloatPoint& point) { - m_current = m_start = m_control1 = m_control2 = point; + m_current = m_start = point; return 0; } float PathTraversalState::lineTo(const FloatPoint& point) { float distance = distanceLine(m_current, point); - m_current = m_control1 = m_control2 = point; + m_current = point; return distance; } @@ -180,9 +196,6 @@ float PathTraversalState::quadraticBezierTo(const FloatPoint& newControl, const { float distance = curveLength<QuadraticBezier>(*this, QuadraticBezier(m_current, newControl, newEnd)); - m_control1 = newControl; - m_control2 = newEnd; - if (m_action != TraversalPointAtLength && m_action != TraversalNormalAngleAtLength) m_current = newEnd; @@ -193,9 +206,6 @@ float PathTraversalState::cubicBezierTo(const FloatPoint& newControl1, const Flo { float distance = curveLength<CubicBezier>(*this, CubicBezier(m_current, newControl1, newControl2, newEnd)); - m_control1 = newEnd; - m_control2 = newControl2; - if (m_action != TraversalPointAtLength && m_action != TraversalNormalAngleAtLength) m_current = newEnd; |