From cac0f67c402d107cdb10971b95719e2ff9c7c76b Mon Sep 17 00:00:00 2001 From: Steve Block Date: Thu, 5 Nov 2009 09:23:40 +0000 Subject: Merge webkit.org at r50258 : Initial merge by git. Change-Id: I1a9e1dc4ed654b69174ad52a4f031a07240f37b0 --- WebCore/loader/ImageLoader.cpp | 112 ++++++++++++++++++++++++++++++----------- 1 file changed, 82 insertions(+), 30 deletions(-) (limited to 'WebCore/loader/ImageLoader.cpp') diff --git a/WebCore/loader/ImageLoader.cpp b/WebCore/loader/ImageLoader.cpp index b183a66..cdc31bc 100644 --- a/WebCore/loader/ImageLoader.cpp +++ b/WebCore/loader/ImageLoader.cpp @@ -31,34 +31,40 @@ namespace WebCore { -class ImageLoadEventSender { +class ImageEventSender { public: - ImageLoadEventSender(); + ImageEventSender(const AtomicString& eventType); - void dispatchLoadEventSoon(ImageLoader*); - void cancelLoadEvent(ImageLoader*); + void dispatchEventSoon(ImageLoader*); + void cancelEvent(ImageLoader*); - void dispatchPendingLoadEvents(); + void dispatchPendingEvents(); private: - ~ImageLoadEventSender(); + void timerFired(Timer*); - void timerFired(Timer*); - - Timer m_timer; + AtomicString m_eventType; + Timer m_timer; Vector m_dispatchSoonList; Vector m_dispatchingList; }; -static ImageLoadEventSender& loadEventSender() +static ImageEventSender& beforeLoadEventSender() +{ + DEFINE_STATIC_LOCAL(ImageEventSender, sender, (eventNames().beforeloadEvent)); + return sender; +} + +static ImageEventSender& loadEventSender() { - DEFINE_STATIC_LOCAL(ImageLoadEventSender, sender, ()); + DEFINE_STATIC_LOCAL(ImageEventSender, sender, (eventNames().loadEvent)); return sender; } ImageLoader::ImageLoader(Element* element) : m_element(element) , m_image(0) + , m_firedBeforeLoad(true) , m_firedLoad(true) , m_imageComplete(true) , m_loadManually(false) @@ -69,7 +75,10 @@ ImageLoader::~ImageLoader() { if (m_image) m_image->removeClient(this); - loadEventSender().cancelLoadEvent(this); + if (!m_firedBeforeLoad) + beforeLoadEventSender().cancelEvent(this); + if (!m_firedLoad) + loadEventSender().cancelEvent(this); } void ImageLoader::setImage(CachedImage* newImage) @@ -78,6 +87,7 @@ void ImageLoader::setImage(CachedImage* newImage) CachedImage* oldImage = m_image.get(); if (newImage != oldImage) { setLoadingImage(newImage); + m_firedBeforeLoad = true; m_firedLoad = true; m_imageComplete = true; if (newImage) @@ -89,16 +99,16 @@ void ImageLoader::setImage(CachedImage* newImage) if (RenderObject* renderer = m_element->renderer()) { if (!renderer->isImage()) return; - toRenderImage(renderer)->resetAnimation(); } } void ImageLoader::setLoadingImage(CachedImage* loadingImage) { - m_firedLoad = false; - m_imageComplete = false; m_image = loadingImage; + m_firedBeforeLoad = !loadingImage; + m_firedLoad = !loadingImage; + m_imageComplete = !loadingImage; } void ImageLoader::updateFromElement() @@ -137,8 +147,13 @@ void ImageLoader::updateFromElement() CachedImage* oldImage = m_image.get(); if (newImage != oldImage) { setLoadingImage(newImage); - if (newImage) + if (newImage) { newImage->addClient(this); + if (!m_element->document()->hasListenerType(Document::BEFORELOAD_LISTENER)) + dispatchPendingBeforeLoadEvent(); + else + beforeLoadEventSender().dispatchEventSoon(this); + } if (oldImage) oldImage->removeClient(this); } @@ -146,7 +161,6 @@ void ImageLoader::updateFromElement() if (RenderObject* renderer = m_element->renderer()) { if (!renderer->isImage()) return; - toRenderImage(renderer)->resetAnimation(); } } @@ -161,16 +175,48 @@ void ImageLoader::updateFromElementIgnoringPreviousError() void ImageLoader::notifyFinished(CachedResource*) { ASSERT(m_failedLoadURL.isEmpty()); + m_imageComplete = true; + if (haveFiredBeforeLoadEvent()) + updateRenderer(); - loadEventSender().dispatchLoadEventSoon(this); + loadEventSender().dispatchEventSoon(this); +} +void ImageLoader::updateRenderer() +{ if (RenderObject* renderer = m_element->renderer()) { if (!renderer->isImage()) return; + RenderImage* imageRenderer = toRenderImage(renderer); + + // Only update the renderer if it doesn't have an image or if what we have + // is a complete image. This prevents flickering in the case where a dynamic + // change is happening between two images. + CachedImage* cachedImage = imageRenderer->cachedImage(); + if (m_image != cachedImage && (m_imageComplete || !imageRenderer->cachedImage())) + imageRenderer->setCachedImage(m_image.get()); + } +} - toRenderImage(renderer)->setCachedImage(m_image.get()); +void ImageLoader::dispatchPendingBeforeLoadEvent() +{ + if (m_firedBeforeLoad) + return; + if (!m_image) + return; + if (!m_element->document()->attached()) + return; + m_firedBeforeLoad = true; + if (m_element->dispatchBeforeLoadEvent(m_image->url())) { + updateRenderer(); + return; + } + if (m_image) { + m_image->removeClient(this); + m_image = 0; } + loadEventSender().cancelEvent(this); } void ImageLoader::dispatchPendingLoadEvent() @@ -185,24 +231,26 @@ void ImageLoader::dispatchPendingLoadEvent() dispatchLoadEvent(); } -void ImageLoader::dispatchPendingLoadEvents() +void ImageLoader::dispatchPendingEvents() { - loadEventSender().dispatchPendingLoadEvents(); + beforeLoadEventSender().dispatchPendingEvents(); + loadEventSender().dispatchPendingEvents(); } -ImageLoadEventSender::ImageLoadEventSender() - : m_timer(this, &ImageLoadEventSender::timerFired) +ImageEventSender::ImageEventSender(const AtomicString& eventType) + : m_eventType(eventType) + , m_timer(this, &ImageEventSender::timerFired) { } -void ImageLoadEventSender::dispatchLoadEventSoon(ImageLoader* loader) +void ImageEventSender::dispatchEventSoon(ImageLoader* loader) { m_dispatchSoonList.append(loader); if (!m_timer.isActive()) m_timer.startOneShot(0); } -void ImageLoadEventSender::cancelLoadEvent(ImageLoader* loader) +void ImageEventSender::cancelEvent(ImageLoader* loader) { // Remove instances of this loader from both lists. // Use loops because we allow multiple instances to get into the lists. @@ -220,7 +268,7 @@ void ImageLoadEventSender::cancelLoadEvent(ImageLoader* loader) m_timer.stop(); } -void ImageLoadEventSender::dispatchPendingLoadEvents() +void ImageEventSender::dispatchPendingEvents() { // Need to avoid re-entering this function; if new dispatches are // scheduled before the parent finishes processing the list, they @@ -233,15 +281,19 @@ void ImageLoadEventSender::dispatchPendingLoadEvents() m_dispatchingList.swap(m_dispatchSoonList); size_t size = m_dispatchingList.size(); for (size_t i = 0; i < size; ++i) { - if (ImageLoader* loader = m_dispatchingList[i]) - loader->dispatchPendingLoadEvent(); + if (ImageLoader* loader = m_dispatchingList[i]) { + if (m_eventType == eventNames().beforeloadEvent) + loader->dispatchPendingBeforeLoadEvent(); + else + loader->dispatchPendingLoadEvent(); + } } m_dispatchingList.clear(); } -void ImageLoadEventSender::timerFired(Timer*) +void ImageEventSender::timerFired(Timer*) { - dispatchPendingLoadEvents(); + dispatchPendingEvents(); } } -- cgit v1.1