summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/WebKit/Source/platform/graphics/PathTraversalState.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/WebKit/Source/platform/graphics/PathTraversalState.cpp')
-rw-r--r--chromium/third_party/WebKit/Source/platform/graphics/PathTraversalState.cpp48
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;