- 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();