#include "config.h"
#include "ImageLoader.h"
#include "CSSHelper.h"
#include "CachedImage.h"
#include "DocLoader.h"
#include "Document.h"
#include "Element.h"
#include "RenderImage.h"
#include <wtf/Platform.h>
#include "Frame.h"
#include "HTMLNames.h"
#include "Page.h"
#include "Settings.h"
namespace WebCore {
ImageLoader::ImageLoader(Element* elt)
: m_element(elt)
, m_image(0)
, m_firedLoad(true)
, m_imageComplete(true)
, m_loadManually(false)
{
}
ImageLoader::~ImageLoader()
{
if (m_image && m_image->isLoaded())
m_element->document()->topDocument()->decrementTotalImageDataSize(m_image.get());
if (m_image)
m_image->removeClient(this);
m_element->document()->removeImage(this);
}
void ImageLoader::setImage(CachedImage* newImage)
{
ASSERT(m_failedLoadURL.isEmpty());
CachedImage* oldImage = m_image.get();
if (newImage != oldImage) {
if (oldImage && oldImage->isLoaded())
m_element->document()->topDocument()->decrementTotalImageDataSize(oldImage);
if (newImage && newImage->isLoaded())
m_element->document()->topDocument()->incrementTotalImageDataSize(newImage);
setLoadingImage(newImage);
m_firedLoad = true;
m_imageComplete = true;
if (newImage)
newImage->addClient(this);
if (oldImage)
oldImage->removeClient(this);
}
if (RenderObject* renderer = element()->renderer()) {
if (!renderer->isImage())
return;
static_cast<RenderImage*>(renderer)->resetAnimation();
}
}
void ImageLoader::setLoadingImage(CachedImage* loadingImage)
{
m_firedLoad = false;
m_imageComplete = false;
m_image = loadingImage;
}
void ImageLoader::updateFromElement()
{
Element* elem = element();
Document* doc = elem->document();
if (!doc->renderer())
return;
bool ok;
unsigned width = elem->getAttribute(HTMLNames::widthAttr).toInt(&ok);
if (!ok)
width = 0;
unsigned height = elem->getAttribute(HTMLNames::heightAttr).toInt(&ok);
if (!ok)
height = 0;
if (width * height * 4 > doc->settings()->maximumDecodedImageSize()) return;
if (memoryLimitReached()) return;
AtomicString attr = elem->getAttribute(elem->imageSourceAttributeName());
if (attr == m_failedLoadURL)
return;
CachedImage* newImage = 0;
if (!(attr.isNull() || attr.isEmpty() && doc->baseURI().isLocalFile())) {
if (m_loadManually) {
doc->docLoader()->setAutoLoadImages(false);
newImage = new CachedImage(sourceURI(attr));
newImage->setLoading(true);
newImage->setDocLoader(doc->docLoader());
doc->docLoader()->m_documentResources.set(newImage->url(), newImage);
} else
newImage = doc->docLoader()->requestImage(sourceURI(attr));
m_failedLoadURL = !newImage ? attr : AtomicString();
}
CachedImage* oldImage = m_image.get();
if (newImage != oldImage) {
if (oldImage && oldImage->isLoaded())
doc->topDocument()->decrementTotalImageDataSize(oldImage);
if (newImage && newImage->isLoaded())
doc->topDocument()->incrementTotalImageDataSize(newImage);
setLoadingImage(newImage);
if (newImage)
newImage->addClient(this);
if (oldImage)
oldImage->removeClient(this);
}
if (RenderObject* renderer = elem->renderer()) {
if (!renderer->isImage())
return;
static_cast<RenderImage*>(renderer)->resetAnimation();
}
}
void ImageLoader::updateFromElementIgnoringPreviousError()
{
m_failedLoadURL = AtomicString();
updateFromElement();
}
void ImageLoader::notifyFinished(CachedResource*)
{
ASSERT(m_failedLoadURL.isEmpty());
m_imageComplete = true;
Element* elem = element();
elem->document()->dispatchImageLoadEventSoon(this);
Document* mainFrameDocument = elem->document()->topDocument();
mainFrameDocument->incrementTotalImageDataSize(m_image.get());
unsigned animatedImageSize = m_image->animatedImageSize();
if (animatedImageSize) {
mainFrameDocument->incrementAnimatedImageDataCount(animatedImageSize);
if (mainFrameDocument->animatedImageDataCount() > 2 * 1024 * 1024)
m_image->stopAnimatedImage();
}
if (RenderObject* renderer = elem->renderer()) {
if (!renderer->isImage())
return;
static_cast<RenderImage*>(renderer)->setCachedImage(m_image.get());
}
}
bool ImageLoader::memoryLimitReached()
{
if (!element() || !element()->document() || !element()->document()->page() || !element()->document()->page()->mainFrame() || !element()->document()->page()->mainFrame()->document())
return false;
Frame *mainFrame = element()->document()->page()->mainFrame();
Document *mainFrameDocument = mainFrame->document();
static unsigned long maxImageSize = mainFrame->settings()->maximumDecodedImageSize() / 2; return mainFrameDocument->totalImageDataSize() > maxImageSize;
}
}