void SVGPathSegList::calculateAnimatedValue(SVGAnimationElement* animationElement, float percentage, unsigned repeatCount, PassRefPtr<SVGPropertyBase> fromValue, PassRefPtr<SVGPropertyBase> toValue, PassRefPtr<SVGPropertyBase> toAtEndOfDurationValue, SVGElement*) { invalidateList(); ASSERT(animationElement); bool isToAnimation = animationElement->animationMode() == ToAnimation; const RefPtr<SVGPathSegList> from = toSVGPathSegList(fromValue); const RefPtr<SVGPathSegList> to = toSVGPathSegList(toValue); const RefPtr<SVGPathSegList> toAtEndOfDuration = toSVGPathSegList(toAtEndOfDurationValue); const SVGPathByteStream* toStream = to->byteStream(); const SVGPathByteStream* fromStream = from->byteStream(); OwnPtr<SVGPathByteStream> copy; // If no 'to' value is given, nothing to animate. if (!toStream->size()) return; if (isToAnimation) { copy = byteStream()->copy(); fromStream = copy.get(); } // If the 'from' value is given and it's length doesn't match the 'to' value list length, fallback to a discrete animation. if (fromStream->size() != toStream->size() && fromStream->size()) { if (percentage < 0.5) { if (!isToAnimation) { m_byteStream = fromStream->copy(); return; } } else { m_byteStream = toStream->copy(); return; } } OwnPtr<SVGPathByteStream> lastAnimatedStream = m_byteStream.release(); m_byteStream = SVGPathByteStream::create(); SVGPathByteStreamBuilder builder; builder.setCurrentByteStream(m_byteStream.get()); SVGPathByteStreamSource fromSource(fromStream); SVGPathByteStreamSource toSource(toStream); SVGPathBlender blender; blender.blendAnimatedPath(percentage, &fromSource, &toSource, &builder); // Handle additive='sum'. if (!fromStream->size() || (animationElement->isAdditive() && !isToAnimation)) addToSVGPathByteStream(m_byteStream.get(), lastAnimatedStream.get()); // Handle accumulate='sum'. if (animationElement->isAccumulated() && repeatCount) { const SVGPathByteStream* toAtEndOfDurationStream = toAtEndOfDuration->byteStream(); addToSVGPathByteStream(m_byteStream.get(), toAtEndOfDurationStream, repeatCount); } }
bool SVGPathParserFactory::buildAnimatedSVGPathByteStream(SVGPathByteStream* fromStream, SVGPathByteStream* toStream, OwnPtr<SVGPathByteStream>& result, float progress) { ASSERT(fromStream); ASSERT(toStream); result = SVGPathByteStream::create(); if (fromStream->isEmpty() || toStream->isEmpty()) return false; SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(result.get()); OwnPtr<SVGPathByteStreamSource> fromSource = SVGPathByteStreamSource::create(fromStream); OwnPtr<SVGPathByteStreamSource> toSource = SVGPathByteStreamSource::create(toStream); SVGPathBlender* blender = globalSVGPathBlender(); bool ok = blender->blendAnimatedPath(progress, fromSource.get(), toSource.get(), builder); blender->cleanup(); return ok; }
bool addToSVGPathByteStream(SVGPathByteStream* fromStream, SVGPathByteStream* byStream, unsigned repeatCount) { ASSERT(fromStream); ASSERT(byStream); if (fromStream->isEmpty() || byStream->isEmpty()) return true; SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(fromStream); auto fromStreamCopy = fromStream->copy(); fromStream->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; }
bool addToSVGPathByteStream(SVGPathByteStream* fromStream, SVGPathByteStream* byStream, unsigned repeatCount) { ASSERT(fromStream); ASSERT(byStream); if (fromStream->isEmpty() || byStream->isEmpty()) return false; SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(fromStream); OwnPtr<SVGPathByteStream> fromStreamCopy = fromStream->copy(); fromStream->clear(); OwnPtr<SVGPathByteStreamSource> fromSource = SVGPathByteStreamSource::create(fromStreamCopy.get()); OwnPtr<SVGPathByteStreamSource> bySource = SVGPathByteStreamSource::create(byStream); SVGPathBlender* blender = globalSVGPathBlender(); bool ok = blender->addAnimatedPath(fromSource.get(), bySource.get(), builder, repeatCount); blender->cleanup(); return ok; }
bool buildAnimatedSVGPathByteStream(SVGPathByteStream* fromStream, SVGPathByteStream* toStream, SVGPathByteStream* result, float progress) { ASSERT(fromStream); ASSERT(toStream); ASSERT(result); ASSERT(toStream != result); result->clear(); if (toStream->isEmpty()) return true; SVGPathByteStreamBuilder* builder = globalSVGPathByteStreamBuilder(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; }