| Index: Source/platform/graphics/PathTraversalState.cpp
|
| diff --git a/Source/platform/graphics/PathTraversalState.cpp b/Source/platform/graphics/PathTraversalState.cpp
|
| index 406c5b180cd6a38866b28e5882f423e23e7270ef..862ae8686e0e420da0a389d2827244a0220b0e3d 100644
|
| --- a/Source/platform/graphics/PathTraversalState.cpp
|
| +++ b/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;
|
|
|
|
|