OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2008 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 m_condition == conditionEventListener->m_condition; | 117 m_condition == conditionEventListener->m_condition; |
118 return false; | 118 return false; |
119 } | 119 } |
120 | 120 |
121 void ConditionEventListener::handleEvent(ExecutionContext*, Event* event) { | 121 void ConditionEventListener::handleEvent(ExecutionContext*, Event* event) { |
122 if (!m_animation) | 122 if (!m_animation) |
123 return; | 123 return; |
124 m_animation->handleConditionEvent(event, m_condition); | 124 m_animation->handleConditionEvent(event, m_condition); |
125 } | 125 } |
126 | 126 |
127 void SVGSMILElement::Condition::setEventListener( | |
128 ConditionEventListener* eventListener) { | |
129 m_eventListener = eventListener; | |
130 } | |
131 | |
132 SVGSMILElement::Condition::Condition(Type type, | 127 SVGSMILElement::Condition::Condition(Type type, |
133 BeginOrEnd beginOrEnd, | 128 BeginOrEnd beginOrEnd, |
134 const String& baseID, | 129 const AtomicString& baseID, |
135 const String& name, | 130 const AtomicString& name, |
136 SMILTime offset, | 131 SMILTime offset, |
137 int repeat) | 132 int repeat) |
138 : m_type(type), | 133 : m_type(type), |
139 m_beginOrEnd(beginOrEnd), | 134 m_beginOrEnd(beginOrEnd), |
140 m_baseID(baseID), | 135 m_baseID(baseID), |
141 m_name(name), | 136 m_name(name), |
142 m_offset(offset), | 137 m_offset(offset), |
143 m_repeat(repeat) {} | 138 m_repeat(repeat) {} |
144 | 139 |
| 140 SVGSMILElement::Condition::~Condition() = default; |
| 141 |
| 142 DEFINE_TRACE(SVGSMILElement::Condition) { |
| 143 visitor->trace(m_syncBase); |
| 144 visitor->trace(m_eventListener); |
| 145 } |
| 146 |
| 147 void SVGSMILElement::Condition::connectSyncBase(SVGSMILElement& timedElement) { |
| 148 DCHECK(!m_baseID.isEmpty()); |
| 149 Element* element = timedElement.treeScope().getElementById(m_baseID); |
| 150 if (!element || !isSVGSMILElement(*element)) { |
| 151 m_syncBase = nullptr; |
| 152 return; |
| 153 } |
| 154 m_syncBase = toSVGSMILElement(element); |
| 155 m_syncBase->addSyncBaseDependent(timedElement); |
| 156 } |
| 157 |
| 158 void SVGSMILElement::Condition::disconnectSyncBase( |
| 159 SVGSMILElement& timedElement) { |
| 160 if (!m_syncBase) |
| 161 return; |
| 162 m_syncBase->removeSyncBaseDependent(timedElement); |
| 163 m_syncBase = nullptr; |
| 164 } |
| 165 |
| 166 SVGElement* SVGSMILElement::Condition::lookupEventBase( |
| 167 SVGSMILElement& timedElement) const { |
| 168 Element* eventBase = m_baseID.isEmpty() |
| 169 ? timedElement.targetElement() |
| 170 : timedElement.treeScope().getElementById(m_baseID); |
| 171 if (!eventBase || !eventBase->isSVGElement()) |
| 172 return nullptr; |
| 173 return toSVGElement(eventBase); |
| 174 } |
| 175 |
| 176 void SVGSMILElement::Condition::connectEventBase(SVGSMILElement& timedElement) { |
| 177 DCHECK(!m_syncBase); |
| 178 SVGElement* eventBase = lookupEventBase(timedElement); |
| 179 if (!eventBase) { |
| 180 if (m_baseID.isEmpty()) |
| 181 return; |
| 182 SVGTreeScopeResources& treeScopeResources = |
| 183 timedElement.treeScope().ensureSVGTreeScopedResources(); |
| 184 if (!treeScopeResources.isElementPendingResource(timedElement, m_baseID)) |
| 185 treeScopeResources.addPendingResource(m_baseID, timedElement); |
| 186 return; |
| 187 } |
| 188 DCHECK(!m_eventListener); |
| 189 m_eventListener = ConditionEventListener::create(&timedElement, this); |
| 190 eventBase->addEventListener(m_name, m_eventListener, false); |
| 191 timedElement.addReferenceTo(eventBase); |
| 192 } |
| 193 |
| 194 void SVGSMILElement::Condition::disconnectEventBase( |
| 195 SVGSMILElement& timedElement) { |
| 196 DCHECK(!m_syncBase); |
| 197 if (!m_eventListener) |
| 198 return; |
| 199 // Note: It's a memory optimization to try to remove our condition event |
| 200 // listener, but it's not guaranteed to work, since we have no guarantee that |
| 201 // we will be able to find our condition's original eventBase. So, we also |
| 202 // have to disconnect ourselves from our condition event listener, in case it |
| 203 // later fires. |
| 204 if (SVGElement* eventBase = lookupEventBase(timedElement)) |
| 205 eventBase->removeEventListener(m_name, m_eventListener, false); |
| 206 m_eventListener->disconnectAnimation(); |
| 207 m_eventListener = nullptr; |
| 208 } |
| 209 |
145 SVGSMILElement::SVGSMILElement(const QualifiedName& tagName, Document& doc) | 210 SVGSMILElement::SVGSMILElement(const QualifiedName& tagName, Document& doc) |
146 : SVGElement(tagName, doc), | 211 : SVGElement(tagName, doc), |
147 SVGTests(this), | 212 SVGTests(this), |
148 m_attributeName(anyQName()), | 213 m_attributeName(anyQName()), |
149 m_targetElement(nullptr), | 214 m_targetElement(nullptr), |
150 m_syncBaseConditionsConnected(false), | 215 m_syncBaseConditionsConnected(false), |
151 m_hasEndEventConditions(false), | 216 m_hasEndEventConditions(false), |
152 m_isWaitingForFirstInterval(true), | 217 m_isWaitingForFirstInterval(true), |
153 m_isScheduled(false), | 218 m_isScheduled(false), |
154 m_interval(SMILInterval(SMILTime::unresolved(), SMILTime::unresolved())), | 219 m_interval(SMILInterval(SMILTime::unresolved(), SMILTime::unresolved())), |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 type = Condition::Syncbase; | 471 type = Condition::Syncbase; |
407 } else if (nameString.startsWith("accesskey(")) { | 472 } else if (nameString.startsWith("accesskey(")) { |
408 // FIXME: accesskey() support. | 473 // FIXME: accesskey() support. |
409 type = Condition::AccessKey; | 474 type = Condition::AccessKey; |
410 } else { | 475 } else { |
411 UseCounter::count(&document(), UseCounter::SVGSMILBeginOrEndEventValue); | 476 UseCounter::count(&document(), UseCounter::SVGSMILBeginOrEndEventValue); |
412 type = Condition::EventBase; | 477 type = Condition::EventBase; |
413 } | 478 } |
414 | 479 |
415 m_conditions.push_back( | 480 m_conditions.push_back( |
416 Condition::create(type, beginOrEnd, baseID, nameString, offset, repeat)); | 481 Condition::create(type, beginOrEnd, AtomicString(baseID), |
| 482 AtomicString(nameString), offset, repeat)); |
417 | 483 |
418 if (type == Condition::EventBase && beginOrEnd == End) | 484 if (type == Condition::EventBase && beginOrEnd == End) |
419 m_hasEndEventConditions = true; | 485 m_hasEndEventConditions = true; |
420 | 486 |
421 return true; | 487 return true; |
422 } | 488 } |
423 | 489 |
424 void SVGSMILElement::parseBeginOrEnd(const String& parseString, | 490 void SVGSMILElement::parseBeginOrEnd(const String& parseString, |
425 BeginOrEnd beginOrEnd) { | 491 BeginOrEnd beginOrEnd) { |
426 Vector<SMILTimeWithOrigin>& timeList = | 492 Vector<SMILTimeWithOrigin>& timeList = |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
509 endListChanged(elapsed()); | 575 endListChanged(elapsed()); |
510 } | 576 } |
511 } else { | 577 } else { |
512 SVGElement::svgAttributeChanged(attrName); | 578 SVGElement::svgAttributeChanged(attrName); |
513 return; | 579 return; |
514 } | 580 } |
515 | 581 |
516 animationAttributeChanged(); | 582 animationAttributeChanged(); |
517 } | 583 } |
518 | 584 |
519 inline SVGElement* SVGSMILElement::eventBaseFor(const Condition& condition) { | |
520 Element* eventBase = | |
521 condition.baseID().isEmpty() | |
522 ? targetElement() | |
523 : treeScope().getElementById(AtomicString(condition.baseID())); | |
524 if (eventBase && eventBase->isSVGElement()) | |
525 return toSVGElement(eventBase); | |
526 return nullptr; | |
527 } | |
528 | |
529 void SVGSMILElement::connectSyncBaseConditions() { | 585 void SVGSMILElement::connectSyncBaseConditions() { |
530 if (m_syncBaseConditionsConnected) | 586 if (m_syncBaseConditionsConnected) |
531 disconnectSyncBaseConditions(); | 587 disconnectSyncBaseConditions(); |
532 m_syncBaseConditionsConnected = true; | 588 m_syncBaseConditionsConnected = true; |
533 for (unsigned n = 0; n < m_conditions.size(); ++n) { | 589 for (Condition* condition : m_conditions) { |
534 Condition* condition = m_conditions[n].get(); | 590 if (condition->getType() == Condition::Syncbase) |
535 if (condition->getType() == Condition::Syncbase) { | 591 condition->connectSyncBase(*this); |
536 ASSERT(!condition->baseID().isEmpty()); | |
537 Element* element = | |
538 treeScope().getElementById(AtomicString(condition->baseID())); | |
539 if (!element || !isSVGSMILElement(*element)) { | |
540 condition->setSyncBase(0); | |
541 continue; | |
542 } | |
543 SVGSMILElement* svgSMILElement = toSVGSMILElement(element); | |
544 condition->setSyncBase(svgSMILElement); | |
545 svgSMILElement->addSyncBaseDependent(this); | |
546 } | |
547 } | 592 } |
548 } | 593 } |
549 | 594 |
550 void SVGSMILElement::disconnectSyncBaseConditions() { | 595 void SVGSMILElement::disconnectSyncBaseConditions() { |
551 if (!m_syncBaseConditionsConnected) | 596 if (!m_syncBaseConditionsConnected) |
552 return; | 597 return; |
553 m_syncBaseConditionsConnected = false; | 598 m_syncBaseConditionsConnected = false; |
554 for (unsigned n = 0; n < m_conditions.size(); ++n) { | 599 for (Condition* condition : m_conditions) { |
555 Condition* condition = m_conditions[n].get(); | 600 if (condition->getType() == Condition::Syncbase) |
556 if (condition->getType() == Condition::Syncbase) { | 601 condition->disconnectSyncBase(*this); |
557 if (condition->syncBase()) | |
558 condition->syncBase()->removeSyncBaseDependent(this); | |
559 condition->setSyncBase(0); | |
560 } | |
561 } | 602 } |
562 } | 603 } |
563 | 604 |
564 void SVGSMILElement::connectEventBaseConditions() { | 605 void SVGSMILElement::connectEventBaseConditions() { |
565 disconnectEventBaseConditions(); | 606 disconnectEventBaseConditions(); |
566 for (unsigned n = 0; n < m_conditions.size(); ++n) { | 607 for (Condition* condition : m_conditions) { |
567 Condition* condition = m_conditions[n].get(); | 608 if (condition->getType() == Condition::EventBase) |
568 if (condition->getType() == Condition::EventBase) { | 609 condition->connectEventBase(*this); |
569 ASSERT(!condition->syncBase()); | |
570 SVGElement* eventBase = eventBaseFor(*condition); | |
571 if (!eventBase) { | |
572 if (!condition->baseID().isEmpty() && | |
573 !treeScope() | |
574 .ensureSVGTreeScopedResources() | |
575 .isElementPendingResource(*this, | |
576 AtomicString(condition->baseID()))) { | |
577 treeScope().ensureSVGTreeScopedResources().addPendingResource( | |
578 AtomicString(condition->baseID()), *this); | |
579 } | |
580 continue; | |
581 } | |
582 ASSERT(!condition->eventListener()); | |
583 condition->setEventListener( | |
584 ConditionEventListener::create(this, condition)); | |
585 eventBase->addEventListener(AtomicString(condition->name()), | |
586 condition->eventListener(), false); | |
587 addReferenceTo(eventBase); | |
588 } | |
589 } | 610 } |
590 } | 611 } |
591 | 612 |
592 void SVGSMILElement::disconnectEventBaseConditions() { | 613 void SVGSMILElement::disconnectEventBaseConditions() { |
593 for (unsigned n = 0; n < m_conditions.size(); ++n) { | 614 for (Condition* condition : m_conditions) { |
594 Condition* condition = m_conditions[n].get(); | 615 if (condition->getType() == Condition::EventBase) |
595 if (condition->getType() == Condition::EventBase) { | 616 condition->disconnectEventBase(*this); |
596 ASSERT(!condition->syncBase()); | |
597 if (!condition->eventListener()) | |
598 continue; | |
599 // Note: It's a memory optimization to try to remove our condition | |
600 // event listener, but it's not guaranteed to work, since we have | |
601 // no guarantee that eventBaseFor() will be able to find our condition's | |
602 // original eventBase. So, we also have to disconnect ourselves from | |
603 // our condition event listener, in case it later fires. | |
604 SVGElement* eventBase = eventBaseFor(*condition); | |
605 if (eventBase) | |
606 eventBase->removeEventListener(AtomicString(condition->name()), | |
607 condition->eventListener(), false); | |
608 condition->eventListener()->disconnectAnimation(); | |
609 condition->setEventListener(nullptr); | |
610 } | |
611 } | 617 } |
612 } | 618 } |
613 | 619 |
614 void SVGSMILElement::setTargetElement(SVGElement* target) { | 620 void SVGSMILElement::setTargetElement(SVGElement* target) { |
615 unscheduleIfScheduled(); | 621 unscheduleIfScheduled(); |
616 | 622 |
617 if (m_targetElement) { | 623 if (m_targetElement) { |
618 // Clear values that may depend on the previous target. | 624 // Clear values that may depend on the previous target. |
619 clearAnimatedType(); | 625 clearAnimatedType(); |
620 disconnectSyncBaseConditions(); | 626 disconnectSyncBaseConditions(); |
(...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1176 // |notifyDependentsIntervalChanged| | 1182 // |notifyDependentsIntervalChanged| |
1177 // | 1183 // |
1178 // As the set here records SVGSMILElements on the stack, it is acceptable to | 1184 // As the set here records SVGSMILElements on the stack, it is acceptable to |
1179 // use a HashSet of untraced heap references -- any conservative GC which | 1185 // use a HashSet of untraced heap references -- any conservative GC which |
1180 // strikes before unwinding will find these elements on the stack. | 1186 // strikes before unwinding will find these elements on the stack. |
1181 DEFINE_STATIC_LOCAL(HashSet<UntracedMember<SVGSMILElement>>, loopBreaker, ()); | 1187 DEFINE_STATIC_LOCAL(HashSet<UntracedMember<SVGSMILElement>>, loopBreaker, ()); |
1182 if (!loopBreaker.insert(this).isNewEntry) | 1188 if (!loopBreaker.insert(this).isNewEntry) |
1183 return; | 1189 return; |
1184 | 1190 |
1185 for (SVGSMILElement* element : m_syncBaseDependents) | 1191 for (SVGSMILElement* element : m_syncBaseDependents) |
1186 element->createInstanceTimesFromSyncbase(this); | 1192 element->createInstanceTimesFromSyncbase(*this); |
1187 | 1193 |
1188 loopBreaker.erase(this); | 1194 loopBreaker.erase(this); |
1189 } | 1195 } |
1190 | 1196 |
1191 void SVGSMILElement::createInstanceTimesFromSyncbase(SVGSMILElement* syncBase) { | 1197 void SVGSMILElement::createInstanceTimesFromSyncbase(SVGSMILElement& syncBase) { |
1192 // FIXME: To be really correct, this should handle updating exising interval | 1198 // FIXME: To be really correct, this should handle updating exising interval |
1193 // by changing the associated times instead of creating new ones. | 1199 // by changing the associated times instead of creating new ones. |
1194 for (unsigned n = 0; n < m_conditions.size(); ++n) { | 1200 for (Condition* condition : m_conditions) { |
1195 Condition* condition = m_conditions[n].get(); | |
1196 if (condition->getType() == Condition::Syncbase && | 1201 if (condition->getType() == Condition::Syncbase && |
1197 condition->syncBase() == syncBase) { | 1202 condition->syncBaseEquals(syncBase)) { |
1198 ASSERT(condition->name() == "begin" || condition->name() == "end"); | 1203 ASSERT(condition->name() == "begin" || condition->name() == "end"); |
1199 // No nested time containers in SVG, no need for crazy time space | 1204 // No nested time containers in SVG, no need for crazy time space |
1200 // conversions. Phew! | 1205 // conversions. Phew! |
1201 SMILTime time = 0; | 1206 SMILTime time = 0; |
1202 if (condition->name() == "begin") | 1207 if (condition->name() == "begin") |
1203 time = syncBase->m_interval.begin + condition->offset(); | 1208 time = syncBase.m_interval.begin + condition->offset(); |
1204 else | 1209 else |
1205 time = syncBase->m_interval.end + condition->offset(); | 1210 time = syncBase.m_interval.end + condition->offset(); |
1206 if (!time.isFinite()) | 1211 if (!time.isFinite()) |
1207 continue; | 1212 continue; |
1208 SMILTime elapsed = this->elapsed(); | 1213 SMILTime elapsed = this->elapsed(); |
1209 if (elapsed.isUnresolved()) | 1214 if (elapsed.isUnresolved()) |
1210 continue; | 1215 continue; |
1211 if (condition->getBeginOrEnd() == Begin) | 1216 if (condition->getBeginOrEnd() == Begin) |
1212 addBeginTime(elapsed, time); | 1217 addBeginTime(elapsed, time); |
1213 else | 1218 else |
1214 addEndTime(elapsed, time); | 1219 addEndTime(elapsed, time); |
1215 } | 1220 } |
1216 } | 1221 } |
1217 } | 1222 } |
1218 | 1223 |
1219 void SVGSMILElement::addSyncBaseDependent(SVGSMILElement* animation) { | 1224 void SVGSMILElement::addSyncBaseDependent(SVGSMILElement& animation) { |
1220 m_syncBaseDependents.insert(animation); | 1225 m_syncBaseDependents.insert(&animation); |
1221 if (m_interval.begin.isFinite()) | 1226 if (m_interval.begin.isFinite()) |
1222 animation->createInstanceTimesFromSyncbase(this); | 1227 animation.createInstanceTimesFromSyncbase(*this); |
1223 } | 1228 } |
1224 | 1229 |
1225 void SVGSMILElement::removeSyncBaseDependent(SVGSMILElement* animation) { | 1230 void SVGSMILElement::removeSyncBaseDependent(SVGSMILElement& animation) { |
1226 m_syncBaseDependents.erase(animation); | 1231 m_syncBaseDependents.erase(&animation); |
1227 } | 1232 } |
1228 | 1233 |
1229 void SVGSMILElement::handleConditionEvent(Event* event, Condition* condition) { | 1234 void SVGSMILElement::handleConditionEvent(Event* event, Condition* condition) { |
1230 if (event->type() == "repeatn" && | 1235 if (event->type() == "repeatn" && |
1231 toRepeatEvent(event)->repeat() != condition->repeat()) | 1236 toRepeatEvent(event)->repeat() != condition->repeat()) |
1232 return; | 1237 return; |
1233 | 1238 |
1234 SMILTime elapsed = this->elapsed(); | 1239 SMILTime elapsed = this->elapsed(); |
1235 if (elapsed.isUnresolved()) | 1240 if (elapsed.isUnresolved()) |
1236 return; | 1241 return; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1295 void SVGSMILElement::unscheduleIfScheduled() { | 1300 void SVGSMILElement::unscheduleIfScheduled() { |
1296 if (!m_isScheduled) | 1301 if (!m_isScheduled) |
1297 return; | 1302 return; |
1298 | 1303 |
1299 DCHECK(m_timeContainer); | 1304 DCHECK(m_timeContainer); |
1300 DCHECK(m_targetElement); | 1305 DCHECK(m_targetElement); |
1301 m_timeContainer->unschedule(this, m_targetElement, m_attributeName); | 1306 m_timeContainer->unschedule(this, m_targetElement, m_attributeName); |
1302 m_isScheduled = false; | 1307 m_isScheduled = false; |
1303 } | 1308 } |
1304 | 1309 |
1305 SVGSMILElement::Condition::~Condition() {} | |
1306 | |
1307 DEFINE_TRACE(SVGSMILElement::Condition) { | |
1308 visitor->trace(m_syncBase); | |
1309 visitor->trace(m_eventListener); | |
1310 } | |
1311 | |
1312 DEFINE_TRACE(SVGSMILElement) { | 1310 DEFINE_TRACE(SVGSMILElement) { |
1313 visitor->trace(m_targetElement); | 1311 visitor->trace(m_targetElement); |
1314 visitor->trace(m_timeContainer); | 1312 visitor->trace(m_timeContainer); |
1315 visitor->trace(m_conditions); | 1313 visitor->trace(m_conditions); |
1316 visitor->trace(m_syncBaseDependents); | 1314 visitor->trace(m_syncBaseDependents); |
1317 SVGElement::trace(visitor); | 1315 SVGElement::trace(visitor); |
1318 SVGTests::trace(visitor); | 1316 SVGTests::trace(visitor); |
1319 } | 1317 } |
1320 | 1318 |
1321 } // namespace blink | 1319 } // namespace blink |
OLD | NEW |