📄 svgsmilelement.cpp
字号:
for (unsigned n = 0; n < timeList.size(); ++n) existing.add(timeList[n].value()); Vector<String> splitString; parseString.split(';', splitString); for (unsigned n = 0; n < splitString.size(); ++n) { SMILTime value = parseClockValue(splitString[n]); if (value.isUnresolved()) parseCondition(splitString[n], beginOrEnd); else if (!existing.contains(value.value())) timeList.append(value); } sortTimeList(timeList);}void SVGSMILElement::parseMappedAttribute(MappedAttribute* attr){ if (attr->name() == SVGNames::beginAttr) { if (!m_conditions.isEmpty()) { disconnectConditions(); m_conditions.clear(); parseBeginOrEnd(getAttribute(SVGNames::endAttr), End); } parseBeginOrEnd(attr->value().string(), Begin); if (inDocument()) connectConditions(); } else if (attr->name() == SVGNames::endAttr) { if (!m_conditions.isEmpty()) { disconnectConditions(); m_conditions.clear(); parseBeginOrEnd(getAttribute(SVGNames::beginAttr), Begin); } parseBeginOrEnd(attr->value().string(), End); if (inDocument()) connectConditions(); } else SVGElement::parseMappedAttribute(attr);}void SVGSMILElement::attributeChanged(Attribute* attr, bool preserveDecls){ SVGElement::attributeChanged(attr, preserveDecls); const QualifiedName& attrName = attr->name(); if (attrName == SVGNames::durAttr) m_cachedDur = invalidCachedTime; else if (attrName == SVGNames::repeatDurAttr) m_cachedRepeatDur = invalidCachedTime; else if (attrName == SVGNames::repeatCountAttr) m_cachedRepeatCount = invalidCachedTime; else if (attrName == SVGNames::minAttr) m_cachedMin = invalidCachedTime; else if (attrName == SVGNames::maxAttr) m_cachedMax = invalidCachedTime; if (inDocument()) { if (attrName == SVGNames::beginAttr) beginListChanged(); else if (attrName == SVGNames::endAttr) endListChanged(); }}void SVGSMILElement::connectConditions(){ if (m_conditionsConnected) disconnectConditions(); m_conditionsConnected = true; for (unsigned n = 0; n < m_conditions.size(); ++n) { Condition& condition = m_conditions[n]; if (condition.m_type == Condition::EventBase) { ASSERT(!condition.m_syncbase); Element* eventBase = condition.m_baseID.isEmpty() ? targetElement() : document()->getElementById(condition.m_baseID); if (!eventBase) continue; ASSERT(!condition.m_eventListener); condition.m_eventListener = ConditionEventListener::create(this, eventBase, &condition); } else if (condition.m_type == Condition::Syncbase) { ASSERT(!condition.m_baseID.isEmpty()); condition.m_syncbase = document()->getElementById(condition.m_baseID); if (!isSMILElement(condition.m_syncbase.get())) { condition.m_syncbase = 0; continue; } SVGSMILElement* syncbase = static_cast<SVGSMILElement*>(condition.m_syncbase.get()); syncbase->addTimeDependent(this); } }}void SVGSMILElement::disconnectConditions(){ if (!m_conditionsConnected) return; m_conditionsConnected = false; for (unsigned n = 0; n < m_conditions.size(); ++n) { Condition& condition = m_conditions[n]; if (condition.m_type == Condition::EventBase) { ASSERT(!condition.m_syncbase); if (condition.m_eventListener) { condition.m_eventListener->unregister(); condition.m_eventListener = 0; } } else if (condition.m_type == Condition::Syncbase) { if (condition.m_syncbase) { ASSERT(isSMILElement(condition.m_syncbase.get())); static_cast<SVGSMILElement*>(condition.m_syncbase.get())->removeTimeDependent(this); } } condition.m_syncbase = 0; }}void SVGSMILElement::reschedule(){ if (m_timeContainer) m_timeContainer->schedule(this);}SVGElement* SVGSMILElement::targetElement() const{ String href = xlinkHref(); Node* target = href.isEmpty() ? parentNode() : document()->getElementById(SVGURIReference::getTarget(href)); if (target && target->isSVGElement()) return static_cast<SVGElement*>(target); return 0;} String SVGSMILElement::attributeName() const{ return getAttribute(SVGNames::attributeNameAttr).string().stripWhiteSpace();} SMILTime SVGSMILElement::elapsed() const { return m_timeContainer ? m_timeContainer->elapsed() : 0;} bool SVGSMILElement::isInactive() const{ return m_activeState == Inactive;}bool SVGSMILElement::isFrozen() const{ return m_activeState == Frozen;} SVGSMILElement::Restart SVGSMILElement::restart() const{ DEFINE_STATIC_LOCAL(const AtomicString, never, ("never")); DEFINE_STATIC_LOCAL(const AtomicString, whenNotActive, ("whenNotActive")); const AtomicString& value = getAttribute(SVGNames::restartAttr); if (value == never) return RestartNever; if (value == whenNotActive) return RestartWhenNotActive; return RestartAlways;} SVGSMILElement::FillMode SVGSMILElement::fill() const{ DEFINE_STATIC_LOCAL(const AtomicString, freeze, ("freeze")); const AtomicString& value = getAttribute(SVGNames::fillAttr); return value == freeze ? FillFreeze : FillRemove;} String SVGSMILElement::xlinkHref() const{ return getAttribute(XLinkNames::hrefAttr);} SMILTime SVGSMILElement::dur() const{ if (m_cachedDur != invalidCachedTime) return m_cachedDur; const AtomicString& value = getAttribute(SVGNames::durAttr); SMILTime clockValue = parseClockValue(value); return m_cachedDur = clockValue <= 0 ? SMILTime::unresolved() : clockValue;}SMILTime SVGSMILElement::repeatDur() const{ if (m_cachedRepeatDur != invalidCachedTime) return m_cachedRepeatDur; const AtomicString& value = getAttribute(SVGNames::repeatDurAttr); SMILTime clockValue = parseClockValue(value); return m_cachedRepeatDur = clockValue < 0 ? SMILTime::unresolved() : clockValue;} // So a count is not really a time but let just all pretend we did not notice.SMILTime SVGSMILElement::repeatCount() const{ if (m_cachedRepeatCount != invalidCachedTime) return m_cachedRepeatCount; const AtomicString& value = getAttribute(SVGNames::repeatCountAttr); if (value.isNull()) return SMILTime::unresolved(); DEFINE_STATIC_LOCAL(const AtomicString, indefiniteValue, ("indefinite")); if (value == indefiniteValue) return SMILTime::indefinite(); bool ok; double result = value.string().toDouble(&ok); return m_cachedRepeatCount = ok && result > 0 ? result : SMILTime::unresolved();}SMILTime SVGSMILElement::maxValue() const{ if (m_cachedMax != invalidCachedTime) return m_cachedMax; const AtomicString& value = getAttribute(SVGNames::maxAttr); SMILTime result = parseClockValue(value); return m_cachedMax = (result.isUnresolved() || result < 0) ? SMILTime::indefinite() : result;} SMILTime SVGSMILElement::minValue() const{ if (m_cachedMin != invalidCachedTime) return m_cachedMin; const AtomicString& value = getAttribute(SVGNames::minAttr); SMILTime result = parseClockValue(value); return m_cachedMin = (result.isUnresolved() || result < 0) ? 0 : result;} SMILTime SVGSMILElement::simpleDuration() const{ return min(dur(), SMILTime::indefinite());} void SVGSMILElement::addBeginTime(SMILTime time){ m_beginTimes.append(time); sortTimeList(m_beginTimes); beginListChanged();} void SVGSMILElement::addEndTime(SMILTime time){ m_endTimes.append(time); sortTimeList(m_endTimes); endListChanged();} SMILTime SVGSMILElement::findInstanceTime(BeginOrEnd beginOrEnd, SMILTime minimumTime, bool equalsMinimumOK) const{ // FIXME: This searches from the beginning which is inefficient. The list is usually not long // (one entry in common cases) but you can construct a case where it does grow. const Vector<SMILTime>& list = beginOrEnd == Begin ? m_beginTimes : m_endTimes; for (unsigned n = 0; n < list.size(); ++n) { SMILTime time = list[n]; ASSERT(!time.isUnresolved()); if (time.isIndefinite() && beginOrEnd == Begin) { // "The special value "indefinite" does not yield an instance time in the begin list." continue; } if (equalsMinimumOK) { if (time >= minimumTime) return time; } else if (time > minimumTime) return time; } return SMILTime::unresolved();}SMILTime SVGSMILElement::repeatingDuration() const{ // Computing the active duration // http://www.w3.org/TR/SMIL2/smil-timing.html#Timing-ComputingActiveDur SMILTime repeatCount = this->repeatCount(); SMILTime repeatDur = this->repeatDur(); SMILTime simpleDuration = this->simpleDuration(); if (simpleDuration == 0 || (repeatDur.isUnresolved() && repeatCount.isUnresolved())) return simpleDuration; SMILTime repeatCountDuration = simpleDuration * repeatCount; return min(repeatCountDuration, min(repeatDur, SMILTime::indefinite()));}SMILTime SVGSMILElement::resolveActiveEnd(SMILTime resolvedBegin, SMILTime resolvedEnd) const{ // Computing the active duration // http://www.w3.org/TR/SMIL2/smil-timing.html#Timing-ComputingActiveDur SMILTime preliminaryActiveDuration; if (!resolvedEnd.isUnresolved() && dur().isUnresolved() && repeatDur().isUnresolved() && repeatCount().isUnresolved()) preliminaryActiveDuration = resolvedEnd - resolvedBegin; else if (!resolvedEnd.isFinite()) preliminaryActiveDuration = repeatingDuration(); else preliminaryActiveDuration = min(repeatingDuration(), resolvedEnd - resolvedBegin); SMILTime minValue = this->minValue(); SMILTime maxValue = this->maxValue(); if (minValue > maxValue) { // Ignore both. // http://www.w3.org/TR/2001/REC-smil-animation-20010904/#MinMax minValue = 0; maxValue = SMILTime::indefinite(); } return resolvedBegin + min(maxValue, max(minValue, preliminaryActiveDuration));}void SVGSMILElement::resolveInterval(bool first, SMILTime& beginResult, SMILTime& endResult) const{ // See the pseudocode in // http://www.w3.org/TR/2001/REC-smil-animation-20010904/#Timing-BeginEnd-LifeCycle SMILTime beginAfter = first ? -numeric_limits<double>::infinity() : m_intervalEnd; SMILTime lastIntervalTempEnd = numeric_limits<double>::infinity(); while (true) { SMILTime tempBegin = findInstanceTime(Begin, beginAfter, true); if (tempBegin.isUnresolved()) break; SMILTime tempEnd;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -