SVGPathUtilities.cpp [plain text]
#include "config.h"
#include "SVGPathUtilities.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"
#include "SVGPathSegListSource.h"
#include "SVGPathStringBuilder.h"
#include "SVGPathStringSource.h"
#include "SVGPathTraversalStateBuilder.h"
namespace WebCore {
bool buildPathFromString(const String& d, Path& result)
{
if (d.isEmpty())
return true;
SVGPathBuilder builder(result);
SVGPathStringSource source(d);
return SVGPathParser::parse(source, builder);
}
bool buildSVGPathByteStreamFromSVGPathSegList(const SVGPathSegList& list, SVGPathByteStream& result, PathParsingMode parsingMode)
{
result.clear();
if (list.isEmpty())
return true;
SVGPathSegListSource source(list);
return SVGPathParser::parseToByteStream(source, result, parsingMode);
}
bool appendSVGPathByteStreamFromSVGPathSeg(RefPtr<SVGPathSeg>&& pathSeg, SVGPathByteStream& result, PathParsingMode parsingMode)
{
ASSERT(parsingMode == UnalteredParsing);
SVGPathSegList appendedItemList(PathSegUnalteredRole);
appendedItemList.append(WTFMove(pathSeg));
SVGPathByteStream appendedByteStream;
SVGPathSegListSource source(appendedItemList);
bool ok = SVGPathParser::parseToByteStream(source, result, parsingMode, false);
if (ok)
result.append(appendedByteStream);
return ok;
}
bool buildPathFromByteStream(const SVGPathByteStream& stream, Path& result)
{
if (stream.isEmpty())
return true;
SVGPathBuilder builder(result);
SVGPathByteStreamSource source(stream);
return SVGPathParser::parse(source, builder);
}
bool buildSVGPathSegListFromByteStream(const SVGPathByteStream& stream, SVGPathElement& element, SVGPathSegList& result, PathParsingMode parsingMode)
{
if (stream.isEmpty())
return true;
SVGPathSegListBuilder builder(element, result, parsingMode == NormalizedParsing ? PathSegNormalizedRole : PathSegUnalteredRole);
SVGPathByteStreamSource source(stream);
return SVGPathParser::parse(source, builder, parsingMode);
}
bool buildStringFromByteStream(const SVGPathByteStream& stream, String& result, PathParsingMode parsingMode)
{
if (stream.isEmpty())
return true;
SVGPathByteStreamSource source(stream);
return SVGPathParser::parseToString(source, result, parsingMode);
}
bool buildStringFromSVGPathSegList(const SVGPathSegList& list, String& result, PathParsingMode parsingMode)
{
result = String();
if (list.isEmpty())
return true;
SVGPathSegListSource source(list);
return SVGPathParser::parseToString(source, result, parsingMode);
}
bool buildSVGPathByteStreamFromString(const String& d, SVGPathByteStream& result, PathParsingMode parsingMode)
{
result.clear();
if (d.isEmpty())
return true;
SVGPathStringSource source(d);
return SVGPathParser::parseToByteStream(source, result, parsingMode);
}
bool canBlendSVGPathByteStreams(const SVGPathByteStream& fromStream, const SVGPathByteStream& toStream)
{
SVGPathByteStreamSource fromSource(fromStream);
SVGPathByteStreamSource toSource(toStream);
return SVGPathBlender::canBlendPaths(fromSource, toSource);
}
bool buildAnimatedSVGPathByteStream(const SVGPathByteStream& fromStream, const SVGPathByteStream& toStream, SVGPathByteStream& result, float progress)
{
ASSERT(&toStream != &result);
result.clear();
if (toStream.isEmpty())
return true;
SVGPathByteStreamBuilder builder(result);
SVGPathByteStreamSource fromSource(fromStream);
SVGPathByteStreamSource toSource(toStream);
return SVGPathBlender::blendAnimatedPath(fromSource, toSource, builder, progress);
}
bool addToSVGPathByteStream(SVGPathByteStream& streamToAppendTo, const SVGPathByteStream& byStream, unsigned repeatCount)
{
if (streamToAppendTo.isEmpty() || byStream.isEmpty())
return true;
SVGPathByteStreamBuilder builder(streamToAppendTo);
SVGPathByteStream fromStreamCopy = streamToAppendTo;
streamToAppendTo.clear();
SVGPathByteStreamSource fromSource(fromStreamCopy);
SVGPathByteStreamSource bySource(byStream);
return SVGPathBlender::addAnimatedPath(fromSource, bySource, builder, repeatCount);
}
bool getSVGPathSegAtLengthFromSVGPathByteStream(const SVGPathByteStream& stream, float length, unsigned& pathSeg)
{
if (stream.isEmpty())
return false;
PathTraversalState traversalState(PathTraversalState::Action::SegmentAtLength);
SVGPathTraversalStateBuilder builder(traversalState, length);
SVGPathByteStreamSource source(stream);
bool ok = SVGPathParser::parse(source, builder);
pathSeg = builder.pathSegmentIndex();
return ok;
}
bool getTotalLengthOfSVGPathByteStream(const SVGPathByteStream& stream, float& totalLength)
{
if (stream.isEmpty())
return false;
PathTraversalState traversalState(PathTraversalState::Action::TotalLength);
SVGPathTraversalStateBuilder builder(traversalState);
SVGPathByteStreamSource source(stream);
bool ok = SVGPathParser::parse(source, builder);
totalLength = builder.totalLength();
return ok;
}
bool getPointAtLengthOfSVGPathByteStream(const SVGPathByteStream& stream, float length, SVGPoint& point)
{
if (stream.isEmpty())
return false;
PathTraversalState traversalState(PathTraversalState::Action::VectorAtLength);
SVGPathTraversalStateBuilder builder(traversalState, length);
SVGPathByteStreamSource source(stream);
bool ok = SVGPathParser::parse(source, builder);
point = builder.currentPoint();
return ok;
}
static void pathIteratorForBuildingString(SVGPathConsumer& consumer, const PathElement& pathElement)
{
switch (pathElement.type) {
case PathElementMoveToPoint:
consumer.moveTo(pathElement.points[0], false, AbsoluteCoordinates);
break;
case PathElementAddLineToPoint:
consumer.lineTo(pathElement.points[0], AbsoluteCoordinates);
break;
case PathElementAddQuadCurveToPoint:
consumer.curveToQuadratic(pathElement.points[0], pathElement.points[1], AbsoluteCoordinates);
break;
case PathElementAddCurveToPoint:
consumer.curveToCubic(pathElement.points[0], pathElement.points[1], pathElement.points[2], AbsoluteCoordinates);
break;
case PathElementCloseSubpath:
consumer.closePath();
break;
default:
ASSERT_NOT_REACHED();
break;
}
}
bool buildStringFromPath(const Path& path, String& string)
{
SVGPathStringBuilder builder;
path.apply([&builder](const PathElement& pathElement) {
pathIteratorForBuildingString(builder, pathElement);
});
string = builder.result();
return true;
}
}