📄 svganimationelement.cpp
字号:
return true; // Regular CSS properties also in SVG return id == CSSPropertyColor || id == CSSPropertyDisplay || id == CSSPropertyOpacity || (id >= CSSPropertyFont && id <= CSSPropertyFontWeight) || id == CSSPropertyOverflow || id == CSSPropertyVisibility;} bool SVGAnimationElement::targetAttributeIsCSS() const{ AttributeType type = attributeType(); if (type == AttributeTypeCSS) return true; if (type == AttributeTypeXML) return false; return attributeIsCSS(attributeName());}void SVGAnimationElement::setTargetAttributeAnimatedValue(const String& value){ if (!hasValidTarget()) return; SVGElement* target = targetElement(); String attributeName = this->attributeName(); if (!target || attributeName.isEmpty() || value.isNull()) return; // We don't want the instance tree to get rebuild. Instances are updated in the loop below. if (target->isStyled()) static_cast<SVGStyledElement*>(target)->setInstanceUpdatesBlocked(true); ExceptionCode ec; bool isCSS = targetAttributeIsCSS(); if (isCSS) { // FIXME: This should set the override style, not the inline style. // Sadly override styles are not yet implemented. target->style()->setProperty(attributeName, value, "", ec); } else { // FIXME: This should set the 'presentation' value, not the actual // attribute value. Whatever that means in practice. target->setAttribute(attributeName, value, ec); } if (target->isStyled()) static_cast<SVGStyledElement*>(target)->setInstanceUpdatesBlocked(false); // If the target element is used in an <use> instance tree, update that as well. HashSet<SVGElementInstance*> instances = target->instancesForElement(); HashSet<SVGElementInstance*>::iterator end = instances.end(); for (HashSet<SVGElementInstance*>::iterator it = instances.begin(); it != end; ++it) { SVGElement* shadowTreeElement = (*it)->shadowTreeElement(); ASSERT(shadowTreeElement); if (isCSS) shadowTreeElement->style()->setProperty(attributeName, value, "", ec); else shadowTreeElement->setAttribute(attributeName, value, ec); (*it)->correspondingUseElement()->setChanged(); }} void SVGAnimationElement::calculateKeyTimesForCalcModePaced(){ ASSERT(calcMode() == CalcModePaced); ASSERT(animationMode() == ValuesAnimation); unsigned valuesCount = m_values.size(); ASSERT(valuesCount > 1); Vector<float> keyTimesForPaced; float totalDistance = 0; keyTimesForPaced.append(0); for (unsigned n = 0; n < valuesCount - 1; ++n) { // Distance in any units float distance = calculateDistance(m_values[n], m_values[n + 1]); if (distance < 0) return; totalDistance += distance; keyTimesForPaced.append(distance); } if (!totalDistance) return; // Normalize. for (unsigned n = 1; n < keyTimesForPaced.size() - 1; ++n) keyTimesForPaced[n] = keyTimesForPaced[n - 1] + keyTimesForPaced[n] / totalDistance; keyTimesForPaced[keyTimesForPaced.size() - 1] = 1.f; // Use key times calculated based on pacing instead of the user provided ones. m_keyTimes.swap(keyTimesForPaced);}static inline double solveEpsilon(double duration) { return 1. / (200. * duration); } float SVGAnimationElement::calculatePercentForSpline(float percent, unsigned splineIndex) const{ ASSERT(calcMode() == CalcModeSpline); ASSERT(splineIndex < m_keySplines.size()); UnitBezier bezier = m_keySplines[splineIndex]; SMILTime duration = simpleDuration(); if (!duration.isFinite()) duration = 100.0; return narrowPrecisionToFloat(bezier.solve(percent, solveEpsilon(duration.value())));}float SVGAnimationElement::calculatePercentFromKeyPoints(float percent) const{ ASSERT(!m_keyPoints.isEmpty()); ASSERT(calcMode() != CalcModePaced); unsigned keyTimesCount = m_keyTimes.size(); ASSERT(keyTimesCount > 1); ASSERT(m_keyPoints.size() == keyTimesCount); unsigned index; for (index = 1; index < keyTimesCount; ++index) { if (m_keyTimes[index] >= percent) break; } --index; 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 percent == 1.0f ? toKeyPoint : fromKeyPoint; float keyPointPercent = percent == 1.0f ? 1.0f : (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::currentValuesFromKeyPoints(float percent, float& effectivePercent, String& from, String& to) const{ ASSERT(!m_keyPoints.isEmpty()); ASSERT(m_keyPoints.size() == m_keyTimes.size()); ASSERT(calcMode() != CalcModePaced); effectivePercent = calculatePercentFromKeyPoints(percent); unsigned index = effectivePercent == 1.0f ? m_values.size() - 2 : static_cast<unsigned>(effectivePercent * (m_values.size() - 1)); from = m_values[index]; to = m_values[index + 1];} void SVGAnimationElement::currentValuesForValuesAnimation(float percent, float& effectivePercent, String& from, String& to) const{ unsigned valuesCount = m_values.size(); ASSERT(m_animationValid); ASSERT(valuesCount > 1); CalcMode calcMode = this->calcMode(); 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] == 0)); unsigned index; for (index = 1; index < keyTimesCount; ++index) { if (m_keyTimes[index] >= percent) break; } --index; if (calcMode == CalcModeDiscrete) { if (!keyTimesCount) index = percent == 1.0f ? valuesCount - 1 : static_cast<unsigned>(percent * valuesCount); from = m_values[index]; to = m_values[index]; effectivePercent = 0.0f; return; } float fromPercent; float toPercent; if (keyTimesCount) { fromPercent = m_keyTimes[index]; toPercent = m_keyTimes[index + 1]; } else { index = static_cast<unsigned>(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 == 1.0f ? 1.0f : (percent - fromPercent) / (toPercent - fromPercent); if (calcMode == CalcModeSpline) { ASSERT(m_keySplines.size() == m_values.size() - 1); effectivePercent = calculatePercentForSpline(effectivePercent, index); }} void SVGAnimationElement::startedActiveInterval(){ m_animationValid = false; if (!hasValidTarget()) return; AnimationMode animationMode = this->animationMode(); if (animationMode == NoAnimation) return; if (animationMode == FromToAnimation) m_animationValid = calculateFromAndToValues(fromValue(), toValue()); else if (animationMode == ToAnimation) { // For to-animations the from value is the current accumulated value from lower priority animations. // The value is not static and is determined during the animation. m_animationValid = calculateFromAndToValues(String(), toValue()); } else if (animationMode == FromByAnimation) m_animationValid = calculateFromAndByValues(fromValue(), byValue()); else if (animationMode == ByAnimation) m_animationValid = calculateFromAndByValues(String(), byValue()); else if (animationMode == ValuesAnimation) { CalcMode calcMode = this->calcMode(); m_animationValid = m_values.size() > 1 && (calcMode == CalcModePaced || !hasAttribute(SVGNames::keyTimesAttr) || hasAttribute(SVGNames::keyPointsAttr) || (m_values.size() == m_keyTimes.size())) && (calcMode == CalcModeDiscrete || !m_keyTimes.size() || m_keyTimes.last() == 1.0) && (calcMode != CalcModeSpline || (m_keySplines.size() && (m_keySplines.size() == m_values.size() - 1) || m_keySplines.size() == m_keyPoints.size() - 1)) && (!hasAttribute(SVGNames::keyPointsAttr) || (m_keyTimes.size() > 1 && m_keyTimes.size() == m_keyPoints.size())); if (calcMode == CalcModePaced && m_animationValid) calculateKeyTimesForCalcModePaced(); } else if (animationMode == PathAnimation) m_animationValid = calcMode() == CalcModePaced || !hasAttribute(SVGNames::keyPointsAttr) || (m_keyTimes.size() > 1 && m_keyTimes.size() == m_keyPoints.size());} void SVGAnimationElement::updateAnimation(float percent, unsigned repeat, SVGSMILElement* resultElement){ if (!m_animationValid) return; float effectivePercent; 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 effectivePercent = percent; calculateAnimatedValue(effectivePercent, repeat, resultElement);}void SVGAnimationElement::endedActiveInterval(){}}// vim:ts=4:noet#endif // ENABLE(SVG_ANIMATION)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -