void SVGAnimateElement::calculateAnimatedValue(float percentage, unsigned repeatCount, SVGSMILElement* resultElement) { ASSERT(resultElement); SVGElement* targetElement = this->targetElement(); if (!targetElement || !isSVGAnimateElement(*resultElement)) return; ASSERT(percentage >= 0 && percentage <= 1); ASSERT(m_animator); ASSERT(animatedPropertyType() != AnimatedTransformList || isSVGAnimateTransformElement(*this)); ASSERT(animatedPropertyType() != AnimatedUnknown); ASSERT(m_fromProperty); ASSERT(m_fromProperty->type() == animatedPropertyType()); ASSERT(m_toProperty); SVGAnimateElement* resultAnimationElement = toSVGAnimateElement(resultElement); ASSERT(resultAnimationElement->m_animatedProperty); ASSERT(resultAnimationElement->animatedPropertyType() == animatedPropertyType()); if (isSVGSetElement(*this)) percentage = 1; if (calcMode() == CalcModeDiscrete) percentage = percentage < 0.5 ? 0 : 1; // Target element might have changed. m_animator->setContextElement(targetElement); // Values-animation accumulates using the last values entry corresponding to the end of duration time. SVGPropertyBase* toAtEndOfDurationProperty = m_toAtEndOfDurationProperty ? m_toAtEndOfDurationProperty.get() : m_toProperty.get(); m_animator->calculateAnimatedValue(percentage, repeatCount, m_fromProperty.get(), m_toProperty.get(), toAtEndOfDurationProperty, resultAnimationElement->m_animatedProperty.get()); }
void SVGAnimateElement::applyResultsToTarget() { ASSERT(animatedPropertyType() != AnimatedTransformList || isSVGAnimateTransformElement(*this)); ASSERT(animatedPropertyType() != AnimatedUnknown); // Early exit if our animated type got destructed by a previous endedActiveInterval(). if (!m_animatedProperty) return; // We do update the style and the animation property independent of each other. ShouldApplyAnimationType shouldApply = shouldApplyAnimation(targetElement(), attributeName()); if (shouldApply == ApplyXMLandCSSAnimation) { applyCSSPropertyToTargetAndInstances(targetElement(), attributeName(), m_animatedProperty->valueAsString()); } else if (m_animator.isAnimatingCSSProperty()) { // CSS properties animation code-path. // Convert the result of the animation to a String and apply it as CSS property on the target & all instances. applyCSSPropertyToTargetAndInstances(targetElement(), attributeName(), m_animatedProperty->valueAsString()); return; } // SVG DOM animVal animation code-path. // At this point the SVG DOM values are already changed, unlike for CSS. // We only have to trigger update notifications here. notifyTargetAndInstancesAboutAnimValChange(targetElement(), attributeName()); }
SVGAnimatedTypeAnimator::SVGAnimatedTypeAnimator(SVGAnimationElement* animationElement, SVGElement* contextElement) : m_animationElement(animationElement) , m_contextElement(contextElement) { ASSERT(m_animationElement); ASSERT(m_contextElement); const QualifiedName& attributeName = m_animationElement->attributeName(); m_animatedProperty = m_contextElement->propertyFromAttribute(attributeName); m_type = m_animatedProperty ? m_animatedProperty->type() : SVGElement::animatedPropertyTypeForCSSAttribute(attributeName); // Only <animateTransform> is allowed to animate AnimatedTransformList. // http://www.w3.org/TR/SVG/animate.html#AnimationAttributesAndProperties if (m_type == AnimatedTransformList && !isSVGAnimateTransformElement(*animationElement)) m_type = AnimatedUnknown; ASSERT(m_type != AnimatedPoint && m_type != AnimatedStringList && m_type != AnimatedTransform); }
void SVGAnimationElement::currentValuesForValuesAnimation(float percent, float& effectivePercent, String& from, String& to) { unsigned valuesCount = m_values.size(); ASSERT(m_animationValid); ASSERT(valuesCount >= 1); if (percent == 1 || valuesCount == 1) { from = m_values[valuesCount - 1]; to = m_values[valuesCount - 1]; effectivePercent = 1; return; } CalcMode calcMode = this->calcMode(); if (isSVGAnimateElement(*this)) { SVGAnimateElement& animateElement = toSVGAnimateElement(*this); if (!animateElement.animatedPropertyTypeSupportsAddition()) { ASSERT(animateElement.animatedPropertyType() != AnimatedTransformList || isSVGAnimateTransformElement(*this)); ASSERT(animateElement.animatedPropertyType() != AnimatedUnknown); calcMode = CalcModeDiscrete; } } if (!m_keyPoints.isEmpty() && calcMode != CalcModePaced) return currentValuesFromKeyPoints(percent, effectivePercent, from, to); unsigned keyTimesCount = m_keyTimes.size(); ASSERT(!keyTimesCount || valuesCount == keyTimesCount); ASSERT(!keyTimesCount || (keyTimesCount > 1 && !m_keyTimes[0])); unsigned index = calculateKeyTimesIndex(percent); if (calcMode == CalcModeDiscrete) { if (!keyTimesCount) index = static_cast<unsigned>(percent * valuesCount); from = m_values[index]; to = m_values[index]; effectivePercent = 0; return; } float fromPercent; float toPercent; if (keyTimesCount) { fromPercent = m_keyTimes[index]; toPercent = m_keyTimes[index + 1]; } else { index = static_cast<unsigned>(floorf(percent * (valuesCount - 1))); fromPercent = static_cast<float>(index) / (valuesCount - 1); toPercent = static_cast<float>(index + 1) / (valuesCount - 1); } if (index == valuesCount - 1) --index; from = m_values[index]; to = m_values[index + 1]; ASSERT(toPercent > fromPercent); effectivePercent = (percent - fromPercent) / (toPercent - fromPercent); if (calcMode == CalcModeSpline) { ASSERT(m_keySplines.size() == m_values.size() - 1); effectivePercent = calculatePercentForSpline(effectivePercent, index); } }