Reviewed by Mitz.
[WebKit-https.git] / WebCore / loader / ImageDocument.cpp
index e4fffb0d59bcfecb741f433c08cd5f59b1c8e8e5..a1b566d5c21099ffc059131f6a114559b1a7134d 100644 (file)
@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -56,8 +56,8 @@ using namespace HTMLNames;
 class ImageEventListener : public EventListener {
 public:
     ImageEventListener(ImageDocument* doc) : m_doc(doc) { }
 class ImageEventListener : public EventListener {
 public:
     ImageEventListener(ImageDocument* doc) : m_doc(doc) { }
-    
     virtual void handleEvent(Event*, bool isWindowEvent);
     virtual void handleEvent(Event*, bool isWindowEvent);
+
 private:
     ImageDocument* m_doc;
 };
 private:
     ImageDocument* m_doc;
 };
@@ -65,17 +65,30 @@ private:
 class ImageTokenizer : public Tokenizer {
 public:
     ImageTokenizer(ImageDocument* doc) : m_doc(doc) {}
 class ImageTokenizer : public Tokenizer {
 public:
     ImageTokenizer(ImageDocument* doc) : m_doc(doc) {}
-        
+
     virtual bool write(const SegmentedString&, bool appendData);
     virtual void finish();
     virtual bool isWaitingForScripts() const;
     
     virtual bool wantsRawData() const { return true; }
     virtual bool writeRawData(const char* data, int len);
     virtual bool write(const SegmentedString&, bool appendData);
     virtual void finish();
     virtual bool isWaitingForScripts() const;
     
     virtual bool wantsRawData() const { return true; }
     virtual bool writeRawData(const char* data, int len);
+
 private:
     ImageDocument* m_doc;
 };
 
 private:
     ImageDocument* m_doc;
 };
 
+class ImageDocumentElement : public HTMLImageElement {
+public:
+    ImageDocumentElement(ImageDocument* doc) : HTMLImageElement(doc), m_imageDocument(doc) { }
+    virtual ~ImageDocumentElement();
+    virtual void willMoveToNewOwnerDocument();
+
+private:
+    ImageDocument* m_imageDocument;
+};
+
+// --------
+
 bool ImageTokenizer::write(const SegmentedString& s, bool appendData)
 {
     ASSERT_NOT_REACHED();
 bool ImageTokenizer::write(const SegmentedString& s, bool appendData)
 {
     ASSERT_NOT_REACHED();
@@ -123,6 +136,8 @@ bool ImageTokenizer::isWaitingForScripts() const
     return false;
 }
     
     return false;
 }
     
+// --------
+
 ImageDocument::ImageDocument(DOMImplementation* implementation, Frame* frame)
     : HTMLDocument(implementation, frame)
     , m_imageElement(0)
 ImageDocument::ImageDocument(DOMImplementation* implementation, Frame* frame)
     : HTMLDocument(implementation, frame)
     , m_imageElement(0)
@@ -150,12 +165,11 @@ void ImageDocument::createDocumentStructure()
     
     rootElement->appendChild(body, ec);
     
     
     rootElement->appendChild(body, ec);
     
-    RefPtr<Element> imageElement = createElementNS(xhtmlNamespaceURI, "img", ec);
+    RefPtr<ImageDocumentElement> imageElement = new ImageDocumentElement(this);
     
     
-    m_imageElement = static_cast<HTMLImageElement *>(imageElement.get());
-    m_imageElement->setAttribute(styleAttr, "-webkit-user-select: none");        
-    m_imageElement->setLoadManually(true);
-    m_imageElement->setSrc(URL());
+    imageElement->setAttribute(styleAttr, "-webkit-user-select: none");        
+    imageElement->setLoadManually(true);
+    imageElement->setSrc(URL());
     
     body->appendChild(imageElement, ec);
     
     
     body->appendChild(imageElement, ec);
     
@@ -163,12 +177,17 @@ void ImageDocument::createDocumentStructure()
         // Add event listeners
         RefPtr<EventListener> listener = new ImageEventListener(this);
         addWindowEventListener("resize", listener, false);
         // Add event listeners
         RefPtr<EventListener> listener = new ImageEventListener(this);
         addWindowEventListener("resize", listener, false);
-        m_imageElement->addEventListener("click", listener.release(), false);
+        imageElement->addEventListener("click", listener.release(), false);
     }
     }
+
+    m_imageElement = imageElement.get();
 }
 
 float ImageDocument::scale() const
 {
 }
 
 float ImageDocument::scale() const
 {
+    if (!m_imageElement)
+        return 1.0f;
+
     IntSize imageSize = m_imageElement->cachedImage()->imageSize();
     IntSize windowSize = IntSize(frame()->view()->width(), frame()->view()->height());
     
     IntSize imageSize = m_imageElement->cachedImage()->imageSize();
     IntSize windowSize = IntSize(frame()->view()->width(), frame()->view()->height());
     
@@ -180,6 +199,9 @@ float ImageDocument::scale() const
 
 void ImageDocument::resizeImageToFit()
 {
 
 void ImageDocument::resizeImageToFit()
 {
+    if (!m_imageElement)
+        return;
+
     IntSize imageSize = m_imageElement->cachedImage()->imageSize();
 
     float scale = this->scale();
     IntSize imageSize = m_imageElement->cachedImage()->imageSize();
 
     float scale = this->scale();
@@ -233,7 +255,7 @@ void ImageDocument::imageChanged()
 
 void ImageDocument::restoreImageSize()
 {
 
 void ImageDocument::restoreImageSize()
 {
-    if (!m_imageSizeIsKnown)
+    if (!m_imageElement || !m_imageSizeIsKnown)
         return;
     
     m_imageElement->setWidth(m_imageElement->cachedImage()->imageSize().width());
         return;
     
     m_imageElement->setWidth(m_imageElement->cachedImage()->imageSize().width());
@@ -250,6 +272,9 @@ void ImageDocument::restoreImageSize()
 
 bool ImageDocument::imageFitsInWindow() const
 {
 
 bool ImageDocument::imageFitsInWindow() const
 {
+    if (!m_imageElement)
+        return true;
+
     IntSize imageSize = m_imageElement->cachedImage()->imageSize();
     IntSize windowSize = IntSize(frame()->view()->width(), frame()->view()->height());
     
     IntSize imageSize = m_imageElement->cachedImage()->imageSize();
     IntSize windowSize = IntSize(frame()->view()->width(), frame()->view()->height());
     
@@ -258,7 +283,7 @@ bool ImageDocument::imageFitsInWindow() const
 
 void ImageDocument::windowSizeChanged()
 {
 
 void ImageDocument::windowSizeChanged()
 {
-    if (!m_imageSizeIsKnown)
+    if (!m_imageElement || !m_imageSizeIsKnown)
         return;
 
     bool fitsInWindow = imageFitsInWindow();
         return;
 
     bool fitsInWindow = imageFitsInWindow();
@@ -305,6 +330,8 @@ bool ImageDocument::shouldShrinkToFit() const
         frame()->page()->mainFrame() == frame();
 }
 
         frame()->page()->mainFrame() == frame();
 }
 
+// --------
+
 void ImageEventListener::handleEvent(Event* event, bool isWindowEvent)
 {
     if (event->type() == resizeEvent)
 void ImageEventListener::handleEvent(Event* event, bool isWindowEvent)
 {
     if (event->type() == resizeEvent)
@@ -315,4 +342,21 @@ void ImageEventListener::handleEvent(Event* event, bool isWindowEvent)
     }
 }
 
     }
 }
 
+// --------
+
+ImageDocumentElement::~ImageDocumentElement()
+{
+    if (m_imageDocument)
+        m_imageDocument->disconnectImageElement();
+}
+
+void ImageDocumentElement::willMoveToNewOwnerDocument()
+{
+    if (m_imageDocument) {
+        m_imageDocument->disconnectImageElement();
+        m_imageDocument = 0;
+    }
+    HTMLImageElement::willMoveToNewOwnerDocument();
+}
+
 }
 }