void SVGPath::calculateAnimatedValue(SVGAnimationElement* animationElement, float percentage, unsigned repeatCount, PassRefPtrWillBeRawPtr<SVGPropertyBase> fromValue, PassRefPtrWillBeRawPtr<SVGPropertyBase> toValue, PassRefPtrWillBeRawPtr<SVGPropertyBase> toAtEndOfDurationValue, SVGElement*) { ASSERT(animationElement); bool isToAnimation = animationElement->animationMode() == ToAnimation; const RefPtrWillBeRawPtr<SVGPath> from = toSVGPath(fromValue); const RefPtrWillBeRawPtr<SVGPath> to = toSVGPath(toValue); const RefPtrWillBeRawPtr<SVGPath> toAtEndOfDuration = toSVGPath(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(*m_byteStream); SVGPathByteStreamSource fromSource(*fromStream); SVGPathByteStreamSource toSource(toStream); SVGPathBlender blender(&fromSource, &toSource, &builder); blender.blendAnimatedPath(percentage); // Handle additive='sum'. if (!fromStream->size() || (animationElement->isAdditive() && !isToAnimation)) addToSVGPathByteStream(*m_byteStream, *lastAnimatedStream); // Handle accumulate='sum'. if (animationElement->isAccumulated() && repeatCount) addToSVGPathByteStream(*m_byteStream, toAtEndOfDuration->byteStream(), repeatCount); }
PassOwnPtr<InterpolationValue> SVGPathInterpolationType::maybeConvertSVGValue(const SVGPropertyBase& svgValue) const { if (svgValue.type() != AnimatedPath) return nullptr; SVGPathByteStreamSource pathSource(toSVGPath(svgValue).byteStream()); size_t length = 0; PathCoordinates currentCoordinates; Vector<OwnPtr<InterpolableValue>> interpolablePathSegs; Vector<SVGPathSegType> pathSegTypes; while (pathSource.hasMoreData()) { const PathSegmentData segment = pathSource.parseSegment(); interpolablePathSegs.append(SVGPathSegInterpolationFunctions::consumePathSeg(segment, currentCoordinates)); pathSegTypes.append(segment.command); length++; } OwnPtr<InterpolableList> pathArgs = InterpolableList::create(length); for (size_t i = 0; i < interpolablePathSegs.size(); i++) pathArgs->set(i, interpolablePathSegs[i].release()); OwnPtr<InterpolableList> result = InterpolableList::create(PathComponentIndexCount); result->set(PathArgsIndex, pathArgs.release()); result->set(PathNeutralIndex, InterpolableNumber::create(0)); return InterpolationValue::create(*this, result.release(), SVGPathNonInterpolableValue::create(pathSegTypes)); }
void SVGPath::add(PassRefPtrWillBeRawPtr<SVGPropertyBase> other, SVGElement*) { RefPtrWillBeRawPtr<SVGPath> otherList = toSVGPath(other); if (byteStream().size() != otherList->byteStream().size()) return; addToSVGPathByteStream(mutableByteStream(), otherList->byteStream()); }
void SVGPath::calculateAnimatedValue(SVGAnimationElement* animationElement, float percentage, unsigned repeatCount, RawPtr<SVGPropertyBase> fromValue, RawPtr<SVGPropertyBase> toValue, RawPtr<SVGPropertyBase> toAtEndOfDurationValue, SVGElement*) { ASSERT(animationElement); bool isToAnimation = animationElement->getAnimationMode() == ToAnimation; const SVGPath& to = toSVGPath(*toValue); const SVGPathByteStream& toStream = to.byteStream(); // If no 'to' value is given, nothing to animate. if (!toStream.size()) return; const SVGPath& from = toSVGPath(*fromValue); const SVGPathByteStream* fromStream = &from.byteStream(); OwnPtr<SVGPathByteStream> copy; if (isToAnimation) { copy = byteStream().clone(); 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_pathValue = from.pathValue(); return; } } else { m_pathValue = to.pathValue(); return; } } OwnPtr<SVGPathByteStream> newStream = blendPathByteStreams(*fromStream, toStream, percentage); // Handle additive='sum'. if (animationElement->isAdditive() && !isToAnimation) newStream = conditionallyAddPathByteStreams(newStream.release(), byteStream()); // Handle accumulate='sum'. if (animationElement->isAccumulated() && repeatCount) newStream = conditionallyAddPathByteStreams(newStream.release(), toSVGPath(toAtEndOfDurationValue)->byteStream(), repeatCount); m_pathValue = CSSPathValue::create(newStream.release()); }
InterpolationValue SVGPathInterpolationType::maybeConvertSVGValue( const SVGPropertyBase& svgValue) const { if (svgValue.type() != AnimatedPath) return nullptr; return PathInterpolationFunctions::convertValue( toSVGPath(svgValue).byteStream()); }
void SVGPath::add(RawPtr<SVGPropertyBase> other, SVGElement*) { const SVGPathByteStream& otherPathByteStream = toSVGPath(other)->byteStream(); if (byteStream().size() != otherPathByteStream.size() || byteStream().isEmpty() || otherPathByteStream.isEmpty()) return; m_pathValue = CSSPathValue::create(addPathByteStreams(byteStream(), otherPathByteStream)); }