Changeset 86973 in webkit


Ignore:
Timestamp:
May 20, 2011 12:04:52 PM (13 years ago)
Author:
krit@webkit.org
Message:

2011-05-20 Dirk Schulze <krit@webkit.org>

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:
Location:
trunk/Source/WebCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r86970 r86973  
     12011-05-20  Dirk Schulze  <krit@webkit.org>
     2
     3        Reviewed by Darin Adler.
     4
     5        SVGPathSegList needs better getTotalLength, getSegmentAtLength path traversal code
     6        https://bugs.webkit.org/show_bug.cgi?id=12047
     7
     8        Right now SVGPathElement::getTotalLength and SVGPathElement::getPointAtLength use toPathData()
     9        to transform a SVGPathByteStream to a Path. This Path gets traversed to find the searched value.
     10        With this patch both functions use the SVGPathByteStream directly together with the existing
     11        traversing code in SVG. This avoids the intermediate transforming to a platform path and gives
     12        platform independent results.
     13        The traversal code in SVG needed to be extended to support all PathTraversalActions.
     14
     15        No new tests added. The existing tests cover the changes.
     16
     17        * svg/SVGPathElement.cpp:
     18        (WebCore::SVGPathElement::getTotalLength):
     19        (WebCore::SVGPathElement::getPointAtLength):
     20        * svg/SVGPathParserFactory.cpp:
     21        (WebCore::SVGPathParserFactory::getTotalLengthOfSVGPathByteStream):
     22        (WebCore::SVGPathParserFactory::getPointAtLengthOfSVGPathByteStream):
     23        * svg/SVGPathParserFactory.h:
     24        * svg/SVGPathTraversalStateBuilder.cpp:
     25        (WebCore::SVGPathTraversalStateBuilder::continueConsuming):
     26        (WebCore::SVGPathTraversalStateBuilder::totalLength):
     27        (WebCore::SVGPathTraversalStateBuilder::currentPoint):
     28        * svg/SVGPathTraversalStateBuilder.h:
     29
    1302011-05-20  Mark Pilgrim  <pilgrim@chromium.org>
    231
  • trunk/Source/WebCore/svg/SVGPathElement.cpp

    r86050 r86973  
    6565float SVGPathElement::getTotalLength()
    6666{
    67     // FIXME: this may wish to use the pathSegList instead of the pathdata if that's cheaper to build (or cached)
    68     Path path;
    69     toPathData(path);
    70     return path.length();
     67    float totalLength = 0;
     68    SVGPathParserFactory::self()->getTotalLengthOfSVGPathByteStream(m_pathByteStream.get(), totalLength);
     69    return totalLength;
    7170}
    7271
    7372FloatPoint SVGPathElement::getPointAtLength(float length)
    7473{
    75     // FIXME: this may wish to use the pathSegList instead of the pathdata if that's cheaper to build (or cached)
    76     bool ok = false;
    77     Path path;
    78     toPathData(path);
    79     return path.pointAtLength(length, ok);
     74    FloatPoint point;
     75    SVGPathParserFactory::self()->getPointAtLengthOfSVGPathByteStream(m_pathByteStream.get(), length, point);
     76    return point;
    8077}
    8178
    8279unsigned long SVGPathElement::getPathSegAtLength(float length)
    8380{
    84     SVGPathParserFactory* factory = SVGPathParserFactory::self();
    8581    unsigned long pathSeg = 0;
    86     factory->getSVGPathSegAtLengthFromSVGPathByteStream(m_pathByteStream.get(), length, pathSeg);
     82    SVGPathParserFactory::self()->getSVGPathSegAtLengthFromSVGPathByteStream(m_pathByteStream.get(), length, pathSeg);
    8783    return pathSeg;
    8884}
  • trunk/Source/WebCore/svg/SVGPathParserFactory.cpp

    r72381 r86973  
    268268}
    269269
     270bool SVGPathParserFactory::getTotalLengthOfSVGPathByteStream(SVGPathByteStream* stream, float& totalLength)
     271{
     272    ASSERT(stream);
     273    if (stream->isEmpty())
     274        return false;
     275   
     276    PathTraversalState traversalState(PathTraversalState::TraversalTotalLength);
     277    SVGPathTraversalStateBuilder* builder = globalSVGPathTraversalStateBuilder(traversalState, 0);
     278   
     279    OwnPtr<SVGPathByteStreamSource> source = SVGPathByteStreamSource::create(stream);
     280    SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
     281    bool ok = parser->parsePathDataFromSource(NormalizedParsing);
     282    totalLength = builder->totalLength();
     283    parser->cleanup();
     284    return ok;
     285}
     286
     287bool SVGPathParserFactory::getPointAtLengthOfSVGPathByteStream(SVGPathByteStream* stream, float length, FloatPoint& point)
     288{
     289    ASSERT(stream);
     290    if (stream->isEmpty())
     291        return false;
     292   
     293    PathTraversalState traversalState(PathTraversalState::TraversalPointAtLength);
     294    SVGPathTraversalStateBuilder* builder = globalSVGPathTraversalStateBuilder(traversalState, length);
     295   
     296    OwnPtr<SVGPathByteStreamSource> source = SVGPathByteStreamSource::create(stream);
     297    SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
     298    bool ok = parser->parsePathDataFromSource(NormalizedParsing);
     299    point = builder->currentPoint();
     300    parser->cleanup();
     301    return ok;
     302}
     303
    270304}
    271305
  • trunk/Source/WebCore/svg/SVGPathParserFactory.h

    r74493 r86973  
    5555    bool buildAnimatedSVGPathByteStream(SVGPathByteStream*, SVGPathByteStream*, OwnPtr<SVGPathByteStream>&, float);
    5656    bool getSVGPathSegAtLengthFromSVGPathByteStream(SVGPathByteStream*, float length, unsigned long& pathSeg);
     57    bool getTotalLengthOfSVGPathByteStream(SVGPathByteStream*, float& totalLength);
     58    bool getPointAtLengthOfSVGPathByteStream(SVGPathByteStream*, float length, FloatPoint&);
    5759
    5860private:
  • trunk/Source/WebCore/svg/SVGPathTraversalStateBuilder.cpp

    r65605 r86973  
    6666bool SVGPathTraversalStateBuilder::continueConsuming()
    6767{
    68     ASSERT(m_traversalState);
    69     ASSERT(m_traversalState->m_action == PathTraversalState::TraversalSegmentAtLength);
    70     return m_traversalState->m_totalLength < m_traversalState->m_desiredLength;
     68    ASSERT(m_traversalState);   
     69    if (m_traversalState->m_action == PathTraversalState::TraversalSegmentAtLength
     70        && m_traversalState->m_totalLength >= m_traversalState->m_desiredLength)
     71        m_traversalState->m_success = true;
     72   
     73    if ((m_traversalState->m_action == PathTraversalState::TraversalPointAtLength
     74         || m_traversalState->m_action == PathTraversalState::TraversalNormalAngleAtLength)
     75        && m_traversalState->m_totalLength >= m_traversalState->m_desiredLength) {
     76        FloatSize change = m_traversalState->m_current - m_traversalState->m_previous;
     77        float slope = atan2f(change.height(), change.width());
     78        if (m_traversalState->m_action == PathTraversalState::TraversalPointAtLength) {
     79            float offset = m_traversalState->m_desiredLength - m_traversalState->m_totalLength;
     80            m_traversalState->m_current.move(offset * cosf(slope), offset * sinf(slope));
     81        } else
     82            m_traversalState->m_normalAngle = rad2deg(slope);
     83        m_traversalState->m_success = true;
     84    }
     85    m_traversalState->m_previous = m_traversalState->m_current;
     86
     87    return !m_traversalState->m_success;
    7188}
    7289
     
    83100}
    84101
     102float SVGPathTraversalStateBuilder::totalLength()
     103{
     104    ASSERT(m_traversalState);
     105    return m_traversalState->m_totalLength;
     106}
     107
     108FloatPoint SVGPathTraversalStateBuilder::currentPoint()
     109{
     110    ASSERT(m_traversalState);
     111    return m_traversalState->m_current;
     112}
     113
    85114}
    86115
  • trunk/Source/WebCore/svg/SVGPathTraversalStateBuilder.h

    r65605 r86973  
    3434
    3535    unsigned long pathSegmentIndex();
     36    float totalLength();
     37    FloatPoint currentPoint();
     38
    3639    void setCurrentTraversalState(PathTraversalState* traversalState) { m_traversalState = traversalState; }
    3740    void setDesiredLength(float);
Note: See TracChangeset for help on using the changeset viewer.