Title: [86973] trunk/Source/WebCore
Revision
86973
Author
[email protected]
Date
2011-05-20 12:04:52 -0700 (Fri, 20 May 2011)

Log Message

2011-05-20  Dirk Schulze  <[email protected]>

        Reviewed by Darin Adler.

        SVGPathSegList needs better getTotalLength, getSegmentAtLength path traversal code
        https://bugs.webkit.org/show_bug.cgi?id=12047

        Right now SVGPathElement::getTotalLength and SVGPathElement::getPointAtLength use toPathData()
        to transform a SVGPathByteStream to a Path. This Path gets traversed to find the searched value.
        With this patch both functions use the SVGPathByteStream directly together with the existing
        traversing code in SVG. This avoids the intermediate transforming to a platform path and gives
        platform independent results.
        The traversal code in SVG needed to be extended to support all PathTraversalActions.

        No new tests added. The existing tests cover the changes.

        * svg/SVGPathElement.cpp:
        (WebCore::SVGPathElement::getTotalLength):
        (WebCore::SVGPathElement::getPointAtLength):
        * svg/SVGPathParserFactory.cpp:
        (WebCore::SVGPathParserFactory::getTotalLengthOfSVGPathByteStream):
        (WebCore::SVGPathParserFactory::getPointAtLengthOfSVGPathByteStream):
        * svg/SVGPathParserFactory.h:
        * svg/SVGPathTraversalStateBuilder.cpp:
        (WebCore::SVGPathTraversalStateBuilder::continueConsuming):
        (WebCore::SVGPathTraversalStateBuilder::totalLength):
        (WebCore::SVGPathTraversalStateBuilder::currentPoint):
        * svg/SVGPathTraversalStateBuilder.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (86972 => 86973)


--- trunk/Source/WebCore/ChangeLog	2011-05-20 18:46:19 UTC (rev 86972)
+++ trunk/Source/WebCore/ChangeLog	2011-05-20 19:04:52 UTC (rev 86973)
@@ -1,3 +1,32 @@
+2011-05-20  Dirk Schulze  <[email protected]>
+
+        Reviewed by Darin Adler.
+
+        SVGPathSegList needs better getTotalLength, getSegmentAtLength path traversal code
+        https://bugs.webkit.org/show_bug.cgi?id=12047
+
+        Right now SVGPathElement::getTotalLength and SVGPathElement::getPointAtLength use toPathData()
+        to transform a SVGPathByteStream to a Path. This Path gets traversed to find the searched value.
+        With this patch both functions use the SVGPathByteStream directly together with the existing
+        traversing code in SVG. This avoids the intermediate transforming to a platform path and gives
+        platform independent results.
+        The traversal code in SVG needed to be extended to support all PathTraversalActions.
+
+        No new tests added. The existing tests cover the changes.
+
+        * svg/SVGPathElement.cpp:
+        (WebCore::SVGPathElement::getTotalLength):
+        (WebCore::SVGPathElement::getPointAtLength):
+        * svg/SVGPathParserFactory.cpp:
+        (WebCore::SVGPathParserFactory::getTotalLengthOfSVGPathByteStream):
+        (WebCore::SVGPathParserFactory::getPointAtLengthOfSVGPathByteStream):
+        * svg/SVGPathParserFactory.h:
+        * svg/SVGPathTraversalStateBuilder.cpp:
+        (WebCore::SVGPathTraversalStateBuilder::continueConsuming):
+        (WebCore::SVGPathTraversalStateBuilder::totalLength):
+        (WebCore::SVGPathTraversalStateBuilder::currentPoint):
+        * svg/SVGPathTraversalStateBuilder.h:
+
 2011-05-20  Mark Pilgrim  <[email protected]>
 
         Reviewed by Tony Chang.

Modified: trunk/Source/WebCore/svg/SVGPathElement.cpp (86972 => 86973)


--- trunk/Source/WebCore/svg/SVGPathElement.cpp	2011-05-20 18:46:19 UTC (rev 86972)
+++ trunk/Source/WebCore/svg/SVGPathElement.cpp	2011-05-20 19:04:52 UTC (rev 86973)
@@ -64,26 +64,22 @@
 
 float SVGPathElement::getTotalLength()
 {
-    // FIXME: this may wish to use the pathSegList instead of the pathdata if that's cheaper to build (or cached)
-    Path path;
-    toPathData(path);
-    return path.length();
+    float totalLength = 0;
+    SVGPathParserFactory::self()->getTotalLengthOfSVGPathByteStream(m_pathByteStream.get(), totalLength);
+    return totalLength;
 }
 
 FloatPoint SVGPathElement::getPointAtLength(float length)
 {
-    // FIXME: this may wish to use the pathSegList instead of the pathdata if that's cheaper to build (or cached)
-    bool ok = false;
-    Path path;
-    toPathData(path);
-    return path.pointAtLength(length, ok);
+    FloatPoint point;
+    SVGPathParserFactory::self()->getPointAtLengthOfSVGPathByteStream(m_pathByteStream.get(), length, point);
+    return point;
 }
 
 unsigned long SVGPathElement::getPathSegAtLength(float length)
 {
-    SVGPathParserFactory* factory = SVGPathParserFactory::self();
     unsigned long pathSeg = 0;
-    factory->getSVGPathSegAtLengthFromSVGPathByteStream(m_pathByteStream.get(), length, pathSeg);
+    SVGPathParserFactory::self()->getSVGPathSegAtLengthFromSVGPathByteStream(m_pathByteStream.get(), length, pathSeg);
     return pathSeg;
 }
 

Modified: trunk/Source/WebCore/svg/SVGPathParserFactory.cpp (86972 => 86973)


--- trunk/Source/WebCore/svg/SVGPathParserFactory.cpp	2011-05-20 18:46:19 UTC (rev 86972)
+++ trunk/Source/WebCore/svg/SVGPathParserFactory.cpp	2011-05-20 19:04:52 UTC (rev 86973)
@@ -267,6 +267,40 @@
     return ok;
 }
 
+bool SVGPathParserFactory::getTotalLengthOfSVGPathByteStream(SVGPathByteStream* stream, float& totalLength)
+{
+    ASSERT(stream);
+    if (stream->isEmpty())
+        return false;
+    
+    PathTraversalState traversalState(PathTraversalState::TraversalTotalLength);
+    SVGPathTraversalStateBuilder* builder = globalSVGPathTraversalStateBuilder(traversalState, 0);
+    
+    OwnPtr<SVGPathByteStreamSource> source = SVGPathByteStreamSource::create(stream);
+    SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
+    bool ok = parser->parsePathDataFromSource(NormalizedParsing);
+    totalLength = builder->totalLength();
+    parser->cleanup();
+    return ok;
 }
 
+bool SVGPathParserFactory::getPointAtLengthOfSVGPathByteStream(SVGPathByteStream* stream, float length, FloatPoint& point)
+{
+    ASSERT(stream);
+    if (stream->isEmpty())
+        return false;
+    
+    PathTraversalState traversalState(PathTraversalState::TraversalPointAtLength);
+    SVGPathTraversalStateBuilder* builder = globalSVGPathTraversalStateBuilder(traversalState, length);
+    
+    OwnPtr<SVGPathByteStreamSource> source = SVGPathByteStreamSource::create(stream);
+    SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
+    bool ok = parser->parsePathDataFromSource(NormalizedParsing);
+    point = builder->currentPoint();
+    parser->cleanup();
+    return ok;
+}
+
+}
+
 #endif

Modified: trunk/Source/WebCore/svg/SVGPathParserFactory.h (86972 => 86973)


--- trunk/Source/WebCore/svg/SVGPathParserFactory.h	2011-05-20 18:46:19 UTC (rev 86972)
+++ trunk/Source/WebCore/svg/SVGPathParserFactory.h	2011-05-20 19:04:52 UTC (rev 86973)
@@ -54,6 +54,8 @@
 
     bool buildAnimatedSVGPathByteStream(SVGPathByteStream*, SVGPathByteStream*, OwnPtr<SVGPathByteStream>&, float);
     bool getSVGPathSegAtLengthFromSVGPathByteStream(SVGPathByteStream*, float length, unsigned long& pathSeg);
+    bool getTotalLengthOfSVGPathByteStream(SVGPathByteStream*, float& totalLength);
+    bool getPointAtLengthOfSVGPathByteStream(SVGPathByteStream*, float length, FloatPoint&);
 
 private:
     SVGPathParserFactory();

Modified: trunk/Source/WebCore/svg/SVGPathTraversalStateBuilder.cpp (86972 => 86973)


--- trunk/Source/WebCore/svg/SVGPathTraversalStateBuilder.cpp	2011-05-20 18:46:19 UTC (rev 86972)
+++ trunk/Source/WebCore/svg/SVGPathTraversalStateBuilder.cpp	2011-05-20 19:04:52 UTC (rev 86973)
@@ -65,9 +65,26 @@
 
 bool SVGPathTraversalStateBuilder::continueConsuming()
 {
-    ASSERT(m_traversalState);
-    ASSERT(m_traversalState->m_action == PathTraversalState::TraversalSegmentAtLength);
-    return m_traversalState->m_totalLength < m_traversalState->m_desiredLength;
+    ASSERT(m_traversalState);    
+    if (m_traversalState->m_action == PathTraversalState::TraversalSegmentAtLength
+        && m_traversalState->m_totalLength >= m_traversalState->m_desiredLength)
+        m_traversalState->m_success = true;
+    
+    if ((m_traversalState->m_action == PathTraversalState::TraversalPointAtLength
+         || m_traversalState->m_action == PathTraversalState::TraversalNormalAngleAtLength)
+        && m_traversalState->m_totalLength >= m_traversalState->m_desiredLength) {
+        FloatSize change = m_traversalState->m_current - m_traversalState->m_previous;
+        float slope = atan2f(change.height(), change.width());
+        if (m_traversalState->m_action == PathTraversalState::TraversalPointAtLength) {
+            float offset = m_traversalState->m_desiredLength - m_traversalState->m_totalLength;
+            m_traversalState->m_current.move(offset * cosf(slope), offset * sinf(slope));
+        } else
+            m_traversalState->m_normalAngle = rad2deg(slope);
+        m_traversalState->m_success = true;
+    }
+    m_traversalState->m_previous = m_traversalState->m_current;
+
+    return !m_traversalState->m_success;
 }
 
 void SVGPathTraversalStateBuilder::incrementPathSegmentCount()
@@ -82,6 +99,18 @@
     return m_traversalState->m_segmentIndex;
 }
 
+float SVGPathTraversalStateBuilder::totalLength()
+{
+    ASSERT(m_traversalState);
+    return m_traversalState->m_totalLength;
 }
 
+FloatPoint SVGPathTraversalStateBuilder::currentPoint()
+{
+    ASSERT(m_traversalState);
+    return m_traversalState->m_current;
+}
+
+}
+
 #endif // ENABLE(SVG)

Modified: trunk/Source/WebCore/svg/SVGPathTraversalStateBuilder.h (86972 => 86973)


--- trunk/Source/WebCore/svg/SVGPathTraversalStateBuilder.h	2011-05-20 18:46:19 UTC (rev 86972)
+++ trunk/Source/WebCore/svg/SVGPathTraversalStateBuilder.h	2011-05-20 19:04:52 UTC (rev 86973)
@@ -33,6 +33,9 @@
     SVGPathTraversalStateBuilder();
 
     unsigned long pathSegmentIndex();
+    float totalLength();
+    FloatPoint currentPoint();
+
     void setCurrentTraversalState(PathTraversalState* traversalState) { m_traversalState = traversalState; }
     void setDesiredLength(float);
     virtual void incrementPathSegmentCount();
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to