void SVGAnimatedPathAnimator::addAnimatedTypes(SVGAnimatedType* from, SVGAnimatedType* to) { ASSERT(from->type() == AnimatedPath); ASSERT(from->type() == to->type()); SVGPathByteStream* fromPath = from->path(); SVGPathByteStream* toPath = to->path(); unsigned fromPathSize = fromPath->size(); if (!fromPathSize || fromPathSize != toPath->size()) return; addToSVGPathByteStream(toPath, fromPath); }
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& fromStream, const SVGPathByteStream& byStream, unsigned repeatCount) { if (fromStream.isEmpty() || byStream.isEmpty()) return true; OwnPtr<SVGPathByteStream> fromStreamCopy = fromStream.copy(); fromStream.clear(); SVGPathByteStreamBuilder builder(fromStream); SVGPathByteStreamSource fromSource(*fromStreamCopy); SVGPathByteStreamSource bySource(byStream); SVGPathBlender blender(&fromSource, &bySource, &builder); return blender.addAnimatedPath(repeatCount); }
bool buildSVGPathByteStreamFromString(const String& d, SVGPathByteStream& result, PathParsingMode parsingMode) { result.clear(); if (d.isEmpty()) return true; // The string length is typically a minor overestimate of eventual byte stream size, so it avoids us a lot of reallocs. result.reserveInitialCapacity(d.length()); SVGPathByteStreamBuilder builder(result); SVGPathStringSource source(d); SVGPathParser parser(&source, &builder); bool ok = parser.parsePathDataFromSource(parsingMode); result.shrinkToFit(); return ok; }
bool addToSVGPathByteStream(SVGPathByteStream& streamToAppendTo, const SVGPathByteStream& byStream, unsigned repeatCount) { // Why return when streamToAppendTo is empty? Don't we still need to append? if (streamToAppendTo.isEmpty() || byStream.isEmpty()) return true; // Is it OK to make the SVGPathByteStreamBuilder from a stream, and then clear that stream? SVGPathByteStreamBuilder builder(streamToAppendTo); SVGPathByteStream fromStreamCopy = streamToAppendTo; streamToAppendTo.clear(); SVGPathByteStreamSource fromSource(fromStreamCopy); SVGPathByteStreamSource bySource(byStream); return SVGPathBlender::addAnimatedPath(fromSource, bySource, builder, repeatCount); }
bool buildStringFromByteStream(const SVGPathByteStream& stream, String& result, PathParsingMode parsingMode) { if (stream.isEmpty()) return true; SVGPathByteStreamSource source(stream); 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 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 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 buildPathFromByteStream(const SVGPathByteStream& stream, Path& result) { if (stream.isEmpty()) return true; SVGPathBuilder builder(result); SVGPathByteStreamSource source(stream); SVGPathParser parser(&source, &builder); return parser.parsePathDataFromSource(NormalizedParsing); }
FloatPoint getPointAtLengthOfSVGPathByteStream(const SVGPathByteStream& stream, float length) { if (stream.isEmpty()) return FloatPoint(); SVGPathTraversalStateBuilder builder(PathTraversalState::TraversalPointAtLength, length); SVGPathByteStreamSource source(stream); SVGPathParser parser(&source, &builder); parser.parsePathDataFromSource(NormalizedParsing); return builder.currentPoint(); }
float getTotalLengthOfSVGPathByteStream(const SVGPathByteStream& stream) { if (stream.isEmpty()) return 0; SVGPathTraversalStateBuilder builder(PathTraversalState::TraversalTotalLength); SVGPathByteStreamSource source(stream); SVGPathParser parser(&source, &builder); parser.parsePathDataFromSource(NormalizedParsing); return builder.totalLength(); }
unsigned getSVGPathSegAtLengthFromSVGPathByteStream(const SVGPathByteStream& stream, float length) { if (stream.isEmpty()) return 0; SVGPathTraversalStateBuilder builder(PathTraversalState::TraversalSegmentAtLength, length); SVGPathByteStreamSource source(stream); SVGPathParser parser(&source, &builder); parser.parsePathDataFromSource(NormalizedParsing); return builder.pathSegmentIndex(); }
bool buildStringFromByteStream(const SVGPathByteStream& stream, String& result, PathParsingMode parsingMode) { if (stream.isEmpty()) return true; SVGPathStringBuilder builder; SVGPathByteStreamSource source(stream); SVGPathParser parser(&source, &builder); bool ok = parser.parsePathDataFromSource(parsingMode); result = builder.result(); return ok; }
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; }
void SVGAnimatedPathAnimator::calculateAnimatedValue(float percentage, unsigned repeatCount, SVGAnimatedType* from, SVGAnimatedType* to, SVGAnimatedType* toAtEndOfDuration, SVGAnimatedType* animated) { ASSERT(m_animationElement); ASSERT(m_contextElement); SVGPathByteStream* fromPath = from->path(); SVGPathByteStream* toPath = to->path(); SVGPathByteStream* toAtEndOfDurationPath = toAtEndOfDuration->path(); SVGPathByteStream* animatedPath = animated->path(); OwnPtr<SVGPathByteStream> underlyingPath; bool isToAnimation = m_animationElement->animationMode() == ToAnimation; if (isToAnimation) { underlyingPath = animatedPath->copy(); fromPath = underlyingPath.get(); } // Cache the current animated value before the buildAnimatedSVGPathByteStream() clears animatedPath. OwnPtr<SVGPathByteStream> lastAnimatedPath; if (!fromPath->size() || (m_animationElement->isAdditive() && !isToAnimation)) lastAnimatedPath = animatedPath->copy(); // Pass false to 'resizeAnimatedListIfNeeded' here, as the path animation is not a regular Vector<SVGXXX> type, but a SVGPathByteStream, that works differently. if (!m_animationElement->adjustFromToListValues<SVGPathByteStream>(*fromPath, *toPath, *animatedPath, percentage, false)) return; buildAnimatedSVGPathByteStream(fromPath, toPath, animatedPath, percentage); // Handle additive='sum'. if (lastAnimatedPath) addToSVGPathByteStream(animatedPath, lastAnimatedPath.get()); // Handle accumulate='sum'. if (m_animationElement->isAccumulated() && repeatCount) addToSVGPathByteStream(animatedPath, toAtEndOfDurationPath, repeatCount); }
bool appendSVGPathByteStreamFromSVGPathSeg(RefPtr<SVGPathSeg>&& pathSeg, SVGPathByteStream& result, PathParsingMode parsingMode) { // FIXME: https://bugs.webkit.org/show_bug.cgi?id=15412 - Implement normalized path segment lists! 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; }
void SVGAnimatedPathAnimator::calculateAnimatedValue(float percentage, unsigned, OwnPtr<SVGAnimatedType>& from, OwnPtr<SVGAnimatedType>& to, OwnPtr<SVGAnimatedType>& animated) { ASSERT(m_animationElement); ASSERT(m_contextElement); SVGAnimateElement* animationElement = static_cast<SVGAnimateElement*>(m_animationElement); AnimationMode animationMode = animationElement->animationMode(); SVGPathByteStream* toPath = to->path(); ASSERT(toPath); SVGPathByteStream* fromPath = from->path(); ASSERT(fromPath); SVGPathByteStream* animatedPath = animated->path(); ASSERT(animatedPath); if (animationMode == ToAnimation) fromPath->initializeFrom(animatedPath); if (!percentage) { animatedPath->initializeFrom(fromPath); return; } if (percentage == 1) { animatedPath->initializeFrom(toPath); return; } OwnPtr<SVGPathByteStream> newAnimatedPath = adoptPtr(animatedPath); bool success = SVGPathParserFactory::self()->buildAnimatedSVGPathByteStream(fromPath, toPath, newAnimatedPath, percentage); animatedPath = newAnimatedPath.leakPtr(); if (success) return; if ((animationMode == FromToAnimation && percentage > 0.5) || animationMode == ToAnimation) animatedPath->initializeFrom(toPath); else animatedPath->initializeFrom(fromPath); }