void SVGAnimationElement::updateAnimation(float percent, unsigned repeatCount, SVGSMILElement* resultElement) { if (!m_animationValid) return; float effectivePercent; CalcMode calcMode = this->calcMode(); AnimationMode animationMode = this->animationMode(); if (animationMode == ValuesAnimation) { String from; String to; currentValuesForValuesAnimation(percent, effectivePercent, from, to); if (from != m_lastValuesAnimationFrom || to != m_lastValuesAnimationTo) { m_animationValid = calculateFromAndToValues(from, to); if (!m_animationValid) return; m_lastValuesAnimationFrom = from; m_lastValuesAnimationTo = to; } } else if (!m_keyPoints.isEmpty() && calcMode != CalcModePaced) effectivePercent = calculatePercentFromKeyPoints(percent); else if (m_keyPoints.isEmpty() && calcMode == CalcModeSpline && m_keyTimes.size() > 1) effectivePercent = calculatePercentForSpline(percent, calculateKeyTimesIndex(percent)); else if (animationMode == FromToAnimation || animationMode == ToAnimation) effectivePercent = calculatePercentForFromTo(percent); else effectivePercent = percent; calculateAnimatedValue(effectivePercent, repeatCount, resultElement); }
float SVGAnimationElement::calculatePercentFromKeyPoints(float percent) const { ASSERT(!m_keyPoints.isEmpty()); ASSERT(calcMode() != CalcModePaced); ASSERT(m_keyTimes.size() > 1); ASSERT(m_keyPoints.size() == m_keyTimes.size()); if (percent == 1) return m_keyPoints[m_keyPoints.size() - 1]; unsigned index = calculateKeyTimesIndex(percent); float fromPercent = m_keyTimes[index]; float toPercent = m_keyTimes[index + 1]; float fromKeyPoint = m_keyPoints[index]; float toKeyPoint = m_keyPoints[index + 1]; if (calcMode() == CalcModeDiscrete) return fromKeyPoint; float keyPointPercent = (percent - fromPercent) / (toPercent - fromPercent); if (calcMode() == CalcModeSpline) { ASSERT(m_keySplines.size() == m_keyPoints.size() - 1); keyPointPercent = calculatePercentForSpline(keyPointPercent, index); } return (toKeyPoint - fromKeyPoint) * keyPointPercent + fromKeyPoint; }
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 (is<SVGAnimateElement>(*this) || is<SVGAnimateColorElement>(*this)) { ASSERT(targetElement()); AnimatedPropertyType type = downcast<SVGAnimateElementBase>(*this).determineAnimatedPropertyType(*targetElement()); if (type == AnimatedBoolean || type == AnimatedEnumeration || type == AnimatedPreserveAspectRatio || type == AnimatedString) 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_WITH_SECURITY_IMPLICATION(toPercent > fromPercent); effectivePercent = (percent - fromPercent) / (toPercent - fromPercent); if (calcMode == CalcModeSpline) { ASSERT(m_keySplines.size() == m_values.size() - 1); effectivePercent = calculatePercentForSpline(effectivePercent, index); } }
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); } }