4957#if ENABLE(REQUEST_ANIMATION_FRAME)
4958int Document::webkitRequestAnimationFrame(PassRefPtr<RequestAnimationFrameCallback> callback, Element* e)
4959{
4960 if (!m_requestAnimationFrameCallbacks)
4961 m_requestAnimationFrameCallbacks = new RequestAnimationFrameCallbackList;
4962 int id = m_nextRequestAnimationFrameCallbackId++;
4963 callback->m_firedOrCancelled = false;
4964 callback->m_id = id;
4965 callback->m_element = e;
4966 m_requestAnimationFrameCallbacks->append(callback);
4967 if (FrameView* v = view())
4968 v->scheduleAnimation();
4969 return id;
4970}
4971
4972void Document::webkitCancelRequestAnimationFrame(int id)
4973{
4974 if (!m_requestAnimationFrameCallbacks)
4975 return;
4976 for (size_t i = 0; i < m_requestAnimationFrameCallbacks->size(); ++i) {
4977 if (m_requestAnimationFrameCallbacks->at(i)->m_id == id) {
4978 m_requestAnimationFrameCallbacks->at(i)->m_firedOrCancelled = true;
4979 m_requestAnimationFrameCallbacks->remove(i);
4980 return;
4981 }
4982 }
4983}
4984
4985void Document::serviceScriptedAnimations()
4986{
4987 if (!m_requestAnimationFrameCallbacks)
4988 return;
4989 // We want to run the callback for all elements in the document that have registered
4990 // for a callback and that are visible. Running the callbacks can cause new callbacks
4991 // to be registered, existing callbacks to be cancelled, and elements to gain or lose
4992 // visibility so this code has to iterate carefully.
4993
4994 // FIXME: Currently, this code doesn't do any visibility tests beyond checking display:
4995
4996 // First, generate a list of callbacks to consider. Callbacks registered from this point
4997 // on are considered only for the "next" frame, not this one.
4998 RequestAnimationFrameCallbackList callbacks(*m_requestAnimationFrameCallbacks);
4999
5000 // Firing the callback may cause the visibility of other elements to change. To avoid
5001 // missing any callbacks, we keep iterating through the list of candiate callbacks and firing
5002 // them until nothing new becomes visible.
5003 bool firedCallback;
5004 do {
5005 firedCallback = false;
5006 // A previous iteration may have invalidated style (or layout). Update styles for each iteration
5007 // for now since all we check is the existence of a renderer.
5008 updateStyleIfNeeded();
5009 for (size_t i = 0; i < callbacks.size(); ++i) {
5010 RequestAnimationFrameCallback* callback = callbacks[i].get();
5011 if (!callback->m_firedOrCancelled && (!callback->m_element || callback->m_element->renderer())) {
5012 callback->m_firedOrCancelled = true;
5013 callback->handleEvent();
5014 firedCallback = true;
5015 callbacks.remove(i);
5016 break;
5017 }
5018 }
5019 } while (firedCallback);
5020
5021 // Remove any callbacks we fired from the list of pending callbacks.
5022 for (size_t i = 0; i < m_requestAnimationFrameCallbacks->size();) {
5023 if (m_requestAnimationFrameCallbacks->at(i)->m_firedOrCancelled)
5024 m_requestAnimationFrameCallbacks->remove(i);
5025 else
5026 ++i;
5027 }
5028
5029 // In most cases we expect this list to be empty, so no need to keep around the vector's inline buffer.
5030 if (!m_requestAnimationFrameCallbacks->size())
5031 m_requestAnimationFrameCallbacks.clear();
5032 else if (FrameView* v = view())
5033 v->scheduleAnimation();
5034}
5035#endif
5036