Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(598)

Side by Side Diff: third_party/WebKit/Source/core/svg/animation/SVGSMILElement.cpp

Issue 2714643007: Tidy up event-/syncbase registration in SVGSMILElement (Closed)
Patch Set: Attempt to fix Win compilation Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/core/svg/animation/SVGSMILElement.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/svg/animation/SVGSMILElement.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698