summaryrefslogtreecommitdiff
path: root/Source/WebCore/svg/SVGPathUtilities.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/svg/SVGPathUtilities.cpp')
-rw-r--r--Source/WebCore/svg/SVGPathUtilities.cpp296
1 files changed, 85 insertions, 211 deletions
diff --git a/Source/WebCore/svg/SVGPathUtilities.cpp b/Source/WebCore/svg/SVGPathUtilities.cpp
index 1c7ce1629..3e900e41b 100644
--- a/Source/WebCore/svg/SVGPathUtilities.cpp
+++ b/Source/WebCore/svg/SVGPathUtilities.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) Research In Motion Limited 2010, 2012. All rights reserved.
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -18,16 +19,16 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "SVGPathUtilities.h"
+#include "FloatPoint.h"
#include "Path.h"
#include "PathTraversalState.h"
#include "SVGPathBlender.h"
#include "SVGPathBuilder.h"
#include "SVGPathByteStreamBuilder.h"
#include "SVGPathByteStreamSource.h"
+#include "SVGPathConsumer.h"
#include "SVGPathElement.h"
#include "SVGPathParser.h"
#include "SVGPathSegListBuilder.h"
@@ -38,300 +39,173 @@
namespace WebCore {
-static SVGPathBuilder* globalSVGPathBuilder(Path& result)
-{
- static SVGPathBuilder* s_builder = 0;
- if (!s_builder)
- s_builder = new SVGPathBuilder;
-
- s_builder->setCurrentPath(&result);
- return s_builder;
-}
-
-static SVGPathSegListBuilder* globalSVGPathSegListBuilder(SVGPathElement* element, SVGPathSegRole role, SVGPathSegList& result)
-{
- static SVGPathSegListBuilder* s_builder = 0;
- if (!s_builder)
- s_builder = new SVGPathSegListBuilder;
-
- s_builder->setCurrentSVGPathElement(element);
- s_builder->setCurrentSVGPathSegList(result);
- s_builder->setCurrentSVGPathSegRole(role);
- return s_builder;
-}
-
-static SVGPathByteStreamBuilder* globalSVGPathByteStreamBuilder(SVGPathByteStream* result)
-{
- static SVGPathByteStreamBuilder* s_builder = 0;
- if (!s_builder)
- s_builder = new SVGPathByteStreamBuilder;
-
- s_builder->setCurrentByteStream(result);
- return s_builder;
-}
-
-static SVGPathStringBuilder* globalSVGPathStringBuilder()
-{
- static SVGPathStringBuilder* s_builder = 0;
- if (!s_builder)
- s_builder = new SVGPathStringBuilder;
-
- return s_builder;
-}
-
-static SVGPathTraversalStateBuilder* globalSVGPathTraversalStateBuilder(PathTraversalState& traversalState, float length)
-{
- static SVGPathTraversalStateBuilder* s_builder = 0;
- if (!s_builder)
- s_builder = new SVGPathTraversalStateBuilder;
-
- s_builder->setCurrentTraversalState(&traversalState);
- s_builder->setDesiredLength(length);
- return s_builder;
-}
-
-static SVGPathParser* globalSVGPathParser(SVGPathSource* source, SVGPathConsumer* consumer)
-{
- static SVGPathParser* s_parser = 0;
- if (!s_parser)
- s_parser = new SVGPathParser;
-
- s_parser->setCurrentSource(source);
- s_parser->setCurrentConsumer(consumer);
- return s_parser;
-}
-
-static SVGPathBlender* globalSVGPathBlender()
-{
- static SVGPathBlender* s_blender = 0;
- if (!s_blender)
- s_blender = new SVGPathBlender;
-
- return s_blender;
-}
-
bool buildPathFromString(const String& d, Path& result)
{
if (d.isEmpty())
return true;
- SVGPathBuilder* builder = globalSVGPathBuilder(result);
-
- auto source = std::make_unique<SVGPathStringSource>(d);
- SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
- bool ok = parser->parsePathDataFromSource(NormalizedParsing);
- parser->cleanup();
- return ok;
+ SVGPathBuilder builder(result);
+ SVGPathStringSource source(d);
+ return SVGPathParser::parse(source, builder);
}
-bool buildSVGPathByteStreamFromSVGPathSegList(const SVGPathSegList& list, SVGPathByteStream* result, PathParsingMode parsingMode)
+bool buildSVGPathByteStreamFromSVGPathSegListValues(const SVGPathSegListValues& list, SVGPathByteStream& result, PathParsingMode parsingMode)
{
- ASSERT(result);
- result->clear();
+ result.clear();
if (list.isEmpty())
return true;
- SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(result);
-
- auto source = std::make_unique<SVGPathSegListSource>(list);
- SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
- bool ok = parser->parsePathDataFromSource(parsingMode);
- parser->cleanup();
- return ok;
+ SVGPathSegListSource source(list);
+ return SVGPathParser::parseToByteStream(source, result, parsingMode);
}
-bool appendSVGPathByteStreamFromSVGPathSeg(PassRefPtr<SVGPathSeg> pathSeg, SVGPathByteStream* result, PathParsingMode parsingMode)
+bool appendSVGPathByteStreamFromSVGPathSeg(RefPtr<SVGPathSeg>&& pathSeg, SVGPathByteStream& result, PathParsingMode parsingMode)
{
- ASSERT(result);
// FIXME: https://bugs.webkit.org/show_bug.cgi?id=15412 - Implement normalized path segment lists!
ASSERT(parsingMode == UnalteredParsing);
- SVGPathSegList appendedItemList(PathSegUnalteredRole);
- appendedItemList.append(pathSeg);
- auto appendedByteStream = std::make_unique<SVGPathByteStream>();
+ SVGPathSegListValues appendedItemList(PathSegUnalteredRole);
+ appendedItemList.append(WTFMove(pathSeg));
- SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(appendedByteStream.get());
- auto source = std::make_unique<SVGPathSegListSource>(appendedItemList);
- SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
- bool ok = parser->parsePathDataFromSource(parsingMode, false);
- parser->cleanup();
+ SVGPathByteStream appendedByteStream;
+ SVGPathSegListSource source(appendedItemList);
+ bool ok = SVGPathParser::parseToByteStream(source, result, parsingMode, false);
if (ok)
- result->append(appendedByteStream.get());
+ result.append(appendedByteStream);
return ok;
}
-bool buildPathFromByteStream(SVGPathByteStream* stream, Path& result)
+bool buildPathFromByteStream(const SVGPathByteStream& stream, Path& result)
{
- ASSERT(stream);
- if (stream->isEmpty())
+ if (stream.isEmpty())
return true;
- SVGPathBuilder* builder = globalSVGPathBuilder(result);
-
- auto source = std::make_unique<SVGPathByteStreamSource>(stream);
- SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
- bool ok = parser->parsePathDataFromSource(NormalizedParsing);
- parser->cleanup();
- return ok;
+ SVGPathBuilder builder(result);
+ SVGPathByteStreamSource source(stream);
+ return SVGPathParser::parse(source, builder);
}
-bool buildSVGPathSegListFromByteStream(SVGPathByteStream* stream, SVGPathElement* element, SVGPathSegList& result, PathParsingMode parsingMode)
+bool buildSVGPathSegListValuesFromByteStream(const SVGPathByteStream& stream, SVGPathElement& element, SVGPathSegListValues& result, PathParsingMode parsingMode)
{
- ASSERT(stream);
- if (stream->isEmpty())
+ if (stream.isEmpty())
return true;
- SVGPathSegListBuilder* builder = globalSVGPathSegListBuilder(element, parsingMode == NormalizedParsing ? PathSegNormalizedRole : PathSegUnalteredRole, result);
-
- auto source = std::make_unique<SVGPathByteStreamSource>(stream);
- SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
- bool ok = parser->parsePathDataFromSource(parsingMode);
- parser->cleanup();
- return ok;
+ SVGPathSegListBuilder builder(element, result, parsingMode == NormalizedParsing ? PathSegNormalizedRole : PathSegUnalteredRole);
+ SVGPathByteStreamSource source(stream);
+ return SVGPathParser::parse(source, builder, parsingMode);
}
-bool buildStringFromByteStream(SVGPathByteStream* stream, String& result, PathParsingMode parsingMode)
+bool buildStringFromByteStream(const SVGPathByteStream& stream, String& result, PathParsingMode parsingMode)
{
- ASSERT(stream);
- if (stream->isEmpty())
+ if (stream.isEmpty())
return true;
- SVGPathStringBuilder* builder = globalSVGPathStringBuilder();
-
- auto source = std::make_unique<SVGPathByteStreamSource>(stream);
- SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
- bool ok = parser->parsePathDataFromSource(parsingMode);
- result = builder->result();
- parser->cleanup();
- return ok;
+ SVGPathByteStreamSource source(stream);
+ return SVGPathParser::parseToString(source, result, parsingMode);
}
-bool buildStringFromSVGPathSegList(const SVGPathSegList& list, String& result, PathParsingMode parsingMode)
+bool buildStringFromSVGPathSegListValues(const SVGPathSegListValues& list, String& result, PathParsingMode parsingMode)
{
result = String();
if (list.isEmpty())
return true;
- SVGPathStringBuilder* builder = globalSVGPathStringBuilder();
-
- auto source = std::make_unique<SVGPathSegListSource>(list);
- SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
- bool ok = parser->parsePathDataFromSource(parsingMode);
- result = builder->result();
- parser->cleanup();
- return ok;
+ SVGPathSegListSource source(list);
+ return SVGPathParser::parseToString(source, result, parsingMode);
}
-bool buildSVGPathByteStreamFromString(const String& d, SVGPathByteStream* result, PathParsingMode parsingMode)
+bool buildSVGPathByteStreamFromString(const String& d, SVGPathByteStream& result, PathParsingMode parsingMode)
{
- ASSERT(result);
- result->clear();
+ result.clear();
if (d.isEmpty())
return true;
- SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(result);
-
- auto source = std::make_unique<SVGPathStringSource>(d);
- SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
- bool ok = parser->parsePathDataFromSource(parsingMode);
- parser->cleanup();
- return ok;
+ SVGPathStringSource source(d);
+ return SVGPathParser::parseToByteStream(source, result, parsingMode);
}
-bool buildAnimatedSVGPathByteStream(SVGPathByteStream* fromStream, SVGPathByteStream* toStream, SVGPathByteStream* result, float progress)
+bool canBlendSVGPathByteStreams(const SVGPathByteStream& fromStream, const SVGPathByteStream& toStream)
{
- ASSERT(fromStream);
- ASSERT(toStream);
- ASSERT(result);
- ASSERT(toStream != result);
+ SVGPathByteStreamSource fromSource(fromStream);
+ SVGPathByteStreamSource toSource(toStream);
+ return SVGPathBlender::canBlendPaths(fromSource, toSource);
+}
- result->clear();
- if (toStream->isEmpty())
+bool buildAnimatedSVGPathByteStream(const SVGPathByteStream& fromStream, const SVGPathByteStream& toStream, SVGPathByteStream& result, float progress)
+{
+ ASSERT(&toStream != &result);
+ result.clear();
+ if (toStream.isEmpty())
return true;
- SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(result);
+ SVGPathByteStreamBuilder builder(result);
- auto fromSource = std::make_unique<SVGPathByteStreamSource>(fromStream);
- auto toSource = std::make_unique<SVGPathByteStreamSource>(toStream);
- SVGPathBlender* blender = globalSVGPathBlender();
- bool ok = blender->blendAnimatedPath(progress, fromSource.get(), toSource.get(), builder);
- blender->cleanup();
- return ok;
+ SVGPathByteStreamSource fromSource(fromStream);
+ SVGPathByteStreamSource toSource(toStream);
+ return SVGPathBlender::blendAnimatedPath(fromSource, toSource, builder, progress);
}
-bool addToSVGPathByteStream(SVGPathByteStream* fromStream, SVGPathByteStream* byStream, unsigned repeatCount)
+bool addToSVGPathByteStream(SVGPathByteStream& streamToAppendTo, const SVGPathByteStream& byStream, unsigned repeatCount)
{
- ASSERT(fromStream);
- ASSERT(byStream);
- if (fromStream->isEmpty() || byStream->isEmpty())
+ // Why return when streamToAppendTo is empty? Don't we still need to append?
+ if (streamToAppendTo.isEmpty() || byStream.isEmpty())
return true;
- SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(fromStream);
+ // Is it OK to make the SVGPathByteStreamBuilder from a stream, and then clear that stream?
+ SVGPathByteStreamBuilder builder(streamToAppendTo);
- auto fromStreamCopy = fromStream->copy();
- fromStream->clear();
+ SVGPathByteStream fromStreamCopy = streamToAppendTo;
+ streamToAppendTo.clear();
- auto fromSource = std::make_unique<SVGPathByteStreamSource>(fromStreamCopy.get());
- auto bySource = std::make_unique<SVGPathByteStreamSource>(byStream);
- SVGPathBlender* blender = globalSVGPathBlender();
- bool ok = blender->addAnimatedPath(fromSource.get(), bySource.get(), builder, repeatCount);
- blender->cleanup();
- return ok;
+ SVGPathByteStreamSource fromSource(fromStreamCopy);
+ SVGPathByteStreamSource bySource(byStream);
+ return SVGPathBlender::addAnimatedPath(fromSource, bySource, builder, repeatCount);
}
-bool getSVGPathSegAtLengthFromSVGPathByteStream(SVGPathByteStream* stream, float length, unsigned& pathSeg)
+bool getSVGPathSegAtLengthFromSVGPathByteStream(const SVGPathByteStream& stream, float length, unsigned& pathSeg)
{
- ASSERT(stream);
- if (stream->isEmpty())
+ if (stream.isEmpty())
return false;
- PathTraversalState traversalState(PathTraversalState::TraversalSegmentAtLength);
- SVGPathTraversalStateBuilder* builder = globalSVGPathTraversalStateBuilder(traversalState, length);
+ PathTraversalState traversalState(PathTraversalState::Action::SegmentAtLength);
+ SVGPathTraversalStateBuilder builder(traversalState, length);
- auto source = std::make_unique<SVGPathByteStreamSource>(stream);
- SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
- bool ok = parser->parsePathDataFromSource(NormalizedParsing);
- pathSeg = builder->pathSegmentIndex();
- parser->cleanup();
+ SVGPathByteStreamSource source(stream);
+ bool ok = SVGPathParser::parse(source, builder);
+ pathSeg = builder.pathSegmentIndex();
return ok;
}
-bool getTotalLengthOfSVGPathByteStream(SVGPathByteStream* stream, float& totalLength)
+bool getTotalLengthOfSVGPathByteStream(const SVGPathByteStream& stream, float& totalLength)
{
- ASSERT(stream);
- if (stream->isEmpty())
+ if (stream.isEmpty())
return false;
- PathTraversalState traversalState(PathTraversalState::TraversalTotalLength);
- SVGPathTraversalStateBuilder* builder = globalSVGPathTraversalStateBuilder(traversalState, 0);
+ PathTraversalState traversalState(PathTraversalState::Action::TotalLength);
- auto source = std::make_unique<SVGPathByteStreamSource>(stream);
- SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
- bool ok = parser->parsePathDataFromSource(NormalizedParsing);
- totalLength = builder->totalLength();
- parser->cleanup();
+ SVGPathTraversalStateBuilder builder(traversalState);
+
+ SVGPathByteStreamSource source(stream);
+ bool ok = SVGPathParser::parse(source, builder);
+ totalLength = builder.totalLength();
return ok;
}
-bool getPointAtLengthOfSVGPathByteStream(SVGPathByteStream* stream, float length, SVGPoint& point)
+bool getPointAtLengthOfSVGPathByteStream(const SVGPathByteStream& stream, float length, FloatPoint& point)
{
- ASSERT(stream);
- if (stream->isEmpty())
+ if (stream.isEmpty())
return false;
- PathTraversalState traversalState(PathTraversalState::TraversalPointAtLength);
- SVGPathTraversalStateBuilder* builder = globalSVGPathTraversalStateBuilder(traversalState, length);
+ PathTraversalState traversalState(PathTraversalState::Action::VectorAtLength);
+
+ SVGPathTraversalStateBuilder builder(traversalState, length);
- auto source = std::make_unique<SVGPathByteStreamSource>(stream);
- SVGPathParser* parser = globalSVGPathParser(source.get(), builder);
- bool ok = parser->parsePathDataFromSource(NormalizedParsing);
- point = builder->currentPoint();
- parser->cleanup();
+ SVGPathByteStreamSource source(stream);
+ bool ok = SVGPathParser::parse(source, builder);
+ point = builder.currentPoint();
return ok;
}
}
-
-#endif