📄 svgsmilelement.cpp
字号:
if (m_endTimes.isEmpty()) tempEnd = resolveActiveEnd(tempBegin, SMILTime::indefinite()); else { tempEnd = findInstanceTime(End, tempBegin, true); if ((first && tempBegin == tempEnd && tempEnd == lastIntervalTempEnd) || (!first && tempEnd == m_intervalEnd)) tempEnd = findInstanceTime(End, tempBegin, false); if (tempEnd.isUnresolved()) { if (!m_endTimes.isEmpty() && !m_hasEndEventConditions) break; } tempEnd = resolveActiveEnd(tempBegin, tempEnd); } if (tempEnd > 0 || !first) { beginResult = tempBegin; endResult = tempEnd; return; } else if (restart() == RestartNever) break; else beginAfter = tempEnd; lastIntervalTempEnd = tempEnd; } beginResult = SMILTime::unresolved(); endResult = SMILTime::unresolved();} void SVGSMILElement::resolveFirstInterval(){ SMILTime begin; SMILTime end; resolveInterval(true, begin, end); ASSERT(!begin.isIndefinite()); if (!begin.isUnresolved() && (begin != m_intervalBegin || end != m_intervalEnd)) { bool wasUnresolved = m_intervalBegin.isUnresolved(); m_intervalBegin = begin; m_intervalEnd = end; notifyDependentsIntervalChanged(wasUnresolved ? NewInterval : ExistingInterval); m_nextProgressTime = min(m_nextProgressTime, m_intervalBegin); reschedule(); }}void SVGSMILElement::resolveNextInterval(){ SMILTime begin; SMILTime end; resolveInterval(false, begin, end); ASSERT(!begin.isIndefinite()); if (!begin.isUnresolved() && begin != m_intervalBegin) { m_intervalBegin = begin; m_intervalEnd = end; notifyDependentsIntervalChanged(NewInterval); m_nextProgressTime = min(m_nextProgressTime, m_intervalBegin); }}SMILTime SVGSMILElement::nextProgressTime() const{ return m_nextProgressTime;} void SVGSMILElement::beginListChanged(){ SMILTime elapsed = this->elapsed(); if (m_isWaitingForFirstInterval) resolveFirstInterval(); else if (elapsed < m_intervalBegin) { SMILTime newBegin = findInstanceTime(Begin, elapsed, false); if (newBegin < m_intervalBegin) { // Begin time changed, re-resolve the interval. SMILTime oldBegin = m_intervalBegin; m_intervalBegin = elapsed; resolveInterval(false, m_intervalBegin, m_intervalEnd); ASSERT(!m_intervalBegin.isUnresolved()); if (m_intervalBegin != oldBegin) notifyDependentsIntervalChanged(ExistingInterval); } } m_nextProgressTime = elapsed; reschedule();}void SVGSMILElement::endListChanged(){ SMILTime elapsed = this->elapsed(); if (m_isWaitingForFirstInterval) resolveFirstInterval(); else if (elapsed < m_intervalEnd && m_intervalBegin.isFinite()) { SMILTime newEnd = findInstanceTime(End, m_intervalBegin, false); if (newEnd < m_intervalEnd) { newEnd = resolveActiveEnd(m_intervalBegin, newEnd); if (newEnd != m_intervalEnd) { m_intervalEnd = newEnd; notifyDependentsIntervalChanged(ExistingInterval); } } } m_nextProgressTime = elapsed; reschedule();} void SVGSMILElement::checkRestart(SMILTime elapsed){ ASSERT(!m_isWaitingForFirstInterval); ASSERT(elapsed >= m_intervalBegin); Restart restart = this->restart(); if (restart == RestartNever) return; if (elapsed < m_intervalEnd) { if (restart != RestartAlways) return; SMILTime nextBegin = findInstanceTime(Begin, m_intervalBegin, false); if (nextBegin < m_intervalEnd) { m_intervalEnd = nextBegin; notifyDependentsIntervalChanged(ExistingInterval); } } if (elapsed >= m_intervalEnd) resolveNextInterval();} float SVGSMILElement::calculateAnimationPercentAndRepeat(SMILTime elapsed, unsigned& repeat) const{ SMILTime simpleDuration = this->simpleDuration(); repeat = 0; if (simpleDuration.isIndefinite()) { repeat = 0; return 0.f; } if (simpleDuration == 0) { repeat = 0; return 1.f; } ASSERT(m_intervalBegin.isFinite()); ASSERT(simpleDuration.isFinite()); SMILTime activeTime = elapsed - m_intervalBegin; SMILTime repeatingDuration = this->repeatingDuration(); if (elapsed >= m_intervalEnd || activeTime > repeatingDuration) { repeat = static_cast<unsigned>(repeatingDuration.value() / simpleDuration.value()); if (fmod(repeatingDuration.value(), simpleDuration.value() == 0.)) repeat--; return 1.f; } repeat = static_cast<unsigned>(activeTime.value() / simpleDuration.value()); SMILTime simpleTime = fmod(activeTime.value(), simpleDuration.value()); return narrowPrecisionToFloat(simpleTime.value() / simpleDuration.value());} SMILTime SVGSMILElement::calculateNextProgressTime(SMILTime elapsed) const{ if (m_activeState == Active) { // If duration is indefinite the value does not actually change over time. Same is true for <set>. SMILTime simpleDuration = this->simpleDuration(); if (simpleDuration.isIndefinite() || hasTagName(SVGNames::setTag)) { SMILTime repeatCount = this->repeatCount(); SMILTime repeatingDurationEnd = m_intervalBegin + repeatingDuration(); // We are supposed to do freeze semantics when repeating ends, even if the element is still active. // Take care that we get a timer callback at that point. if (elapsed < repeatingDurationEnd && repeatingDurationEnd < m_intervalEnd && repeatingDurationEnd.isFinite()) return repeatingDurationEnd; return m_intervalEnd; } return elapsed + 0.025; } return m_intervalBegin >= elapsed ? m_intervalBegin : SMILTime::unresolved();} SVGSMILElement::ActiveState SVGSMILElement::determineActiveState(SMILTime elapsed) const{ if (elapsed >= m_intervalBegin && elapsed < m_intervalEnd) return Active; if (m_activeState == Active) return fill() == FillFreeze ? Frozen : Inactive; return m_activeState;} bool SVGSMILElement::isContributing(SMILTime elapsed) const { // Animation does not contribute during the active time if it is past its repeating duration and has fill=remove. return (m_activeState == Active && (fill() == FillFreeze || elapsed <= m_intervalBegin + repeatingDuration())) || m_activeState == Frozen;} void SVGSMILElement::progress(SMILTime elapsed, SVGSMILElement* resultElement){ ASSERT(m_timeContainer); ASSERT(m_isWaitingForFirstInterval || m_intervalBegin.isFinite()); if (!m_conditionsConnected) connectConditions(); if (!m_intervalBegin.isFinite()) { ASSERT(m_activeState == Inactive); m_nextProgressTime = SMILTime::unresolved(); return; } if (elapsed < m_intervalBegin) { ASSERT(m_activeState != Active); if (m_activeState == Frozen && resultElement) updateAnimation(m_lastPercent, m_lastRepeat, resultElement); m_nextProgressTime = m_intervalBegin; return; } m_previousIntervalBegin = m_intervalBegin; if (m_activeState == Inactive) { m_isWaitingForFirstInterval = false; m_activeState = Active; startedActiveInterval(); } unsigned repeat; float percent = calculateAnimationPercentAndRepeat(elapsed, repeat); checkRestart(elapsed); ActiveState oldActiveState = m_activeState; m_activeState = determineActiveState(elapsed); if (isContributing(elapsed)) { if (resultElement) updateAnimation(percent, repeat, resultElement); m_lastPercent = percent; m_lastRepeat = repeat; } if (oldActiveState == Active && m_activeState != Active) endedActiveInterval(); m_nextProgressTime = calculateNextProgressTime(elapsed);} void SVGSMILElement::notifyDependentsIntervalChanged(NewOrExistingInterval newOrExisting){ ASSERT(m_intervalBegin.isFinite()); DEFINE_STATIC_LOCAL(HashSet<SVGSMILElement*>, loopBreaker, ()); if (loopBreaker.contains(this)) return; loopBreaker.add(this); TimeDependentSet::iterator end = m_timeDependents.end(); for (TimeDependentSet::iterator it = m_timeDependents.begin(); it != end; ++it) { SVGSMILElement* dependent = *it; dependent->createInstanceTimesFromSyncbase(this, newOrExisting); } loopBreaker.remove(this);} void SVGSMILElement::createInstanceTimesFromSyncbase(SVGSMILElement* syncbase, NewOrExistingInterval){ // FIXME: To be really correct, this should handle updating exising interval by changing // the associated times instead of creating new ones. for (unsigned n = 0; n < m_conditions.size(); ++n) { Condition& condition = m_conditions[n]; if (condition.m_type == Condition::Syncbase && condition.m_syncbase == syncbase) { ASSERT(condition.m_name == "begin" || condition.m_name == "end"); // No nested time containers in SVG, no need for crazy time space conversions. Phew! SMILTime time = 0; if (condition.m_name == "begin") time = syncbase->m_intervalBegin + condition.m_offset; else time = syncbase->m_intervalEnd + condition.m_offset; ASSERT(time.isFinite()); if (condition.m_beginOrEnd == Begin) addBeginTime(time); else addEndTime(time); } }} void SVGSMILElement::addTimeDependent(SVGSMILElement* animation){ m_timeDependents.add(animation); if (m_intervalBegin.isFinite()) animation->createInstanceTimesFromSyncbase(this, NewInterval);} void SVGSMILElement::removeTimeDependent(SVGSMILElement* animation){ m_timeDependents.remove(animation);} void SVGSMILElement::handleConditionEvent(Event*, Condition* condition){ if (condition->m_beginOrEnd == Begin) addBeginTime(elapsed() + condition->m_offset); else addEndTime(elapsed() + condition->m_offset);}void SVGSMILElement::beginByLinkActivation(){ addBeginTime(elapsed());} }#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -