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