[SCM] WebKit Debian packaging branch, webkit-1.1, updated. upstream/1.1.15.1-1414-gc69ee75

hausmann at webkit.org hausmann at webkit.org
Thu Oct 29 20:40:17 UTC 2009


The following commit has been merged in the webkit-1.1 branch:
commit b725e002d0508364c3b1df8ddb8644a9b2ed6f17
Author: hausmann at webkit.org <hausmann at webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Tue Oct 6 14:15:17 2009 +0000

    [Qt] Change QImageReader usage in ImageDecoderQt
    
    https://bugs.webkit.org/show_bug.cgi?id=27538
    
    Replace the ReadContext with another appoach to
    reading the image. Attempt to only read meta information
    like the image size and number of frames (for animations)
    first and then when the page is getting drawn decode
    the image with the QImageReader.
    
    This is a huge benefit on pages with many images and saves
    ~2GB of memory on the szeged image test page.
    
    * platform/graphics/qt/ImageDecoderQt.cpp:
    (WebCore::ImageDecoderQt::ImageDecoderQt):
    (WebCore::ImageDecoderQt::~ImageDecoderQt):
    (WebCore::ImageDecoderQt::setData):
    (WebCore::ImageDecoderQt::isSizeAvailable):
    (WebCore::ImageDecoderQt::frameCount):
    (WebCore::ImageDecoderQt::repetitionCount):
    (WebCore::ImageDecoderQt::filenameExtension):
    (WebCore::ImageDecoderQt::frameBufferAtIndex):
    (WebCore::ImageDecoderQt::clearFrameBufferCache):
    (WebCore::ImageDecoderQt::internalDecodeSize):
    (WebCore::ImageDecoderQt::internalReadImage):
    (WebCore::ImageDecoderQt::internalHandleCurrentImage):
    (WebCore::ImageDecoderQt::forceLoadEverything):
    (WebCore::ImageDecoderQt::failRead):
    * platform/graphics/qt/ImageDecoderQt.h:
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@49186 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index be6c21e..a4552db 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -2,6 +2,38 @@
 
         Reviewed by Simon Hausmann.
 
+        [Qt] Change QImageReader usage in ImageDecoderQt
+        https://bugs.webkit.org/show_bug.cgi?id=27538
+
+        Replace the ReadContext with another appoach to
+        reading the image. Attempt to only read meta information
+        like the image size and number of frames (for animations)
+        first and then when the page is getting drawn decode
+        the image with the QImageReader.
+
+        This is a huge benefit on pages with many images and saves
+        ~2GB of memory on the szeged image test page.
+
+        * platform/graphics/qt/ImageDecoderQt.cpp:
+        (WebCore::ImageDecoderQt::ImageDecoderQt):
+        (WebCore::ImageDecoderQt::setData):
+        (WebCore::ImageDecoderQt::isSizeAvailable):
+        (WebCore::ImageDecoderQt::frameCount):
+        (WebCore::ImageDecoderQt::repetitionCount):
+        (WebCore::ImageDecoderQt::filenameExtension):
+        (WebCore::ImageDecoderQt::frameBufferAtIndex):
+        (WebCore::ImageDecoderQt::clearFrameBufferCache):
+        (WebCore::ImageDecoderQt::internalDecodeSize):
+        (WebCore::ImageDecoderQt::internalReadImage):
+        (WebCore::ImageDecoderQt::internalHandleCurrentImage):
+        (WebCore::ImageDecoderQt::forceLoadEverything):
+        (WebCore::ImageDecoderQt::failRead):
+        * platform/graphics/qt/ImageDecoderQt.h:
+
+2009-10-05  Holger Hans Peter Freyther  <zecke at selfish.org>
+
+        Reviewed by Simon Hausmann.
+
         [Qt] Make use of RGBA32Buffer in ImageDecoderQt
         https://bugs.webkit.org/show_bug.cgi?id=27538
 
diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
index 6831056..3a27fe3 100644
--- a/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
+++ b/WebCore/platform/graphics/qt/ImageDecoderQt.cpp
@@ -55,104 +55,17 @@ ImageDecoder* ImageDecoder::create(const SharedBuffer& data)
     return new ImageDecoderQt(imageFormat);
 }
 
-// Context, maintains IODevice on a data buffer.
-class ImageDecoderQt::ReadContext {
-public:
-
-    ReadContext(SharedBuffer* data, Vector<RGBA32Buffer>& target);
-    bool read();
-
-    QImageReader *reader() { return &m_reader; }
-
-private:
-    enum IncrementalReadResult { IncrementalReadFailed, IncrementalReadPartial, IncrementalReadComplete };
-    // Incrementally read an image
-    IncrementalReadResult readImageLines(RGBA32Buffer&);
-
-    QByteArray m_data;
-    QBuffer m_buffer;
-    QImageReader m_reader;
-
-    Vector<RGBA32Buffer> &m_target;
-};
-
-ImageDecoderQt::ReadContext::ReadContext(SharedBuffer* data, Vector<RGBA32Buffer> &target)
-    : m_data(data->data(), data->size())
-    , m_buffer(&m_data)
-    , m_reader(&m_buffer)
-    , m_target(target)
-{
-    m_buffer.open(QIODevice::ReadOnly);
-}
-
-
-bool ImageDecoderQt::ReadContext::read()
-{
-    // Attempt to read out all images
-    bool completed = false;
-    while (true) {
-        if (m_target.isEmpty() || completed) {
-            // Start a new image.
-            if (!m_reader.canRead())
-                return true;
-
-            m_target.append(RGBA32Buffer());
-            completed = false;
-        }
-
-        // read chunks
-        switch (readImageLines(m_target.last())) {
-        case IncrementalReadFailed:
-            m_target.removeLast();
-            return false;
-        case IncrementalReadPartial:
-            return true;
-        case IncrementalReadComplete:
-            completed = true;
-            //store for next
-            const bool supportsAnimation = m_reader.supportsAnimation();
-
-            // No point in readinfg further
-            if (!supportsAnimation)
-                return true;
-
-            break;
-        }
-    }
-    return true;
-}
-
-
-
-ImageDecoderQt::ReadContext::IncrementalReadResult
-        ImageDecoderQt::ReadContext::readImageLines(RGBA32Buffer& buffer)
-{
-    // TODO: Implement incremental reading here,
-    // set state to reflect complete header, etc.
-    // For now, we read the whole image.
-
-
-    const qint64 startPos = m_buffer.pos();
-    QImage img;
-    // Oops, failed. Rewind.
-    if (!m_reader.read(&img)) {
-        m_buffer.seek(startPos);
-        return IncrementalReadFailed;
-    }
-
-    buffer.setDuration(m_reader.nextImageDelay());
-    buffer.setDecodedImage(img);
-    buffer.setStatus(RGBA32Buffer::FrameComplete);
-    return IncrementalReadComplete;
-}
-
 ImageDecoderQt::ImageDecoderQt(const QByteArray& imageFormat)
-    : m_imageFormat(imageFormat.constData())
+    : m_buffer(0)
+    , m_reader(0)
+    , m_repetitionCount(-1)
 {
 }
 
 ImageDecoderQt::~ImageDecoderQt()
 {
+    delete m_reader;
+    delete m_buffer;
 }
 
 void ImageDecoderQt::setData(SharedBuffer* data, bool allDataReceived)
@@ -167,52 +80,79 @@ void ImageDecoderQt::setData(SharedBuffer* data, bool allDataReceived)
     if (!allDataReceived)
         return;
 
-    ReadContext readContext(data, m_frameBufferCache);
+    // We expect to be only called once with allDataReceived
+    ASSERT(!m_buffer);
+    ASSERT(!m_reader);
 
-    const bool result =  readContext.read();
+    // Attempt to load the data
+    QByteArray imageData = QByteArray::fromRawData(m_data->data(), m_data->size());
+    m_buffer = new QBuffer;
+    m_buffer->setData(imageData);
+    m_buffer->open(QBuffer::ReadOnly);
+    m_reader = new QImageReader(m_buffer);
 
-    if (!result)
-        setFailed();
-    else if (!m_frameBufferCache.isEmpty()) {
-        QSize imgSize = m_frameBufferCache[0].decodedImage().size();
-        setSize(imgSize.width(), imgSize.height());
-
-        if (readContext.reader()->supportsAnimation()) {
-            if (readContext.reader()->loopCount() != -1)
-                m_loopCount = readContext.reader()->loopCount();
-            else
-                m_loopCount = 0; //loop forever
-        }
-    }
+    if (!m_reader->canRead())
+        failRead();
 }
 
-
 bool ImageDecoderQt::isSizeAvailable()
 {
+    if (!m_failed && !ImageDecoder::isSizeAvailable() && m_reader)
+        internalDecodeSize();
+
     return ImageDecoder::isSizeAvailable();
 }
 
 size_t ImageDecoderQt::frameCount()
 {
+    if (m_frameBufferCache.isEmpty() && m_reader) {
+        if (m_reader->supportsAnimation()) {
+            int imageCount = m_reader->imageCount();
+
+            // Fixup for Qt decoders... imageCount() is wrong
+            // and jumpToNextImage does not work either... so
+            // we will have to parse everything...
+            if (imageCount == 0)
+                forceLoadEverything();
+            else
+                m_frameBufferCache.resize(imageCount);
+        } else {
+            m_frameBufferCache.resize(1);
+        }
+    }
+
     return m_frameBufferCache.size();
 }
 
 int ImageDecoderQt::repetitionCount() const
 {
-    return m_loopCount;
+    if (m_reader && m_reader->supportsAnimation())
+        m_repetitionCount = qMax(0, m_reader->loopCount());
+
+    return m_repetitionCount;
 }
 
 String ImageDecoderQt::filenameExtension() const
 {
-    return m_imageFormat;
+    return m_format;
 };
 
 RGBA32Buffer* ImageDecoderQt::frameBufferAtIndex(size_t index)
 {
-    if (index >= m_frameBufferCache.size())
+    // this information might not have been set
+    int count = m_frameBufferCache.size();
+    if (count == 0) {
+        internalDecodeSize();
+        count = frameCount();
+    }
+
+    if (index >= static_cast<size_t>(count))
         return 0;
 
-    return &m_frameBufferCache[index];
+    RGBA32Buffer& frame = m_frameBufferCache[index];
+    if (frame.status() != RGBA32Buffer::FrameComplete && m_reader)
+        internalReadImage(index);
+    return &frame;
 }
 
 void ImageDecoderQt::clearFrameBufferCache(size_t index)
@@ -224,9 +164,80 @@ void ImageDecoderQt::clearFrameBufferCache(size_t index)
         return;
 
     for (size_t i = 0; i < index; ++index)
-        m_frameBufferCache[index].setDecodedImage(QImage());
+        m_frameBufferCache[index].clear();
+}
+
+void ImageDecoderQt::internalDecodeSize()
+{
+    ASSERT(m_reader);
+
+    QSize size = m_reader->size();
+    setSize(size.width(), size.height());
 }
 
+void ImageDecoderQt::internalReadImage(size_t frameIndex)
+{
+    ASSERT(m_reader);
+
+    if (m_reader->supportsAnimation())
+        m_reader->jumpToImage(frameIndex);
+    else if (frameIndex != 0)
+        return failRead();
+
+    internalHandleCurrentImage(frameIndex);
+
+    // Attempt to return some memory
+    for (int i = 0; i < m_frameBufferCache.size(); ++i)
+        if (m_frameBufferCache[i].status() != RGBA32Buffer::FrameComplete)
+            return;
+
+    delete m_reader;
+    delete m_buffer;
+    m_buffer = 0;
+    m_reader = 0;
+}
+
+void ImageDecoderQt::internalHandleCurrentImage(size_t frameIndex)
+{
+    // Now get the QImage from Qt and place it in the RGBA32Buffer
+    QImage img;
+    if (!m_reader->read(&img))
+        return failRead();
+
+    // now into the RGBA32Buffer - even if the image is not
+    QSize imageSize = img.size();
+    RGBA32Buffer* const buffer = &m_frameBufferCache[frameIndex];
+    buffer->setRect(m_reader->currentImageRect());
+    buffer->setStatus(RGBA32Buffer::FrameComplete);
+    buffer->setDuration(m_reader->nextImageDelay());
+    buffer->setDecodedImage(img);
+}
+
+// We will parse everything and we have no idea how
+// many images we have... We will have to find out the
+// hard way.
+void ImageDecoderQt::forceLoadEverything()
+{
+    int imageCount = 0;
+
+    do {
+        m_frameBufferCache.resize(++imageCount);
+        internalHandleCurrentImage(imageCount - 1);
+    } while(!m_failed);
+
+    // reset the failed state and resize the vector...
+    m_frameBufferCache.resize(imageCount - 1);
+    m_failed = false;
+}
+
+void ImageDecoderQt::failRead()
+{
+    setFailed();
+    delete m_reader;
+    delete m_buffer;
+    m_reader = 0;
+    m_buffer = 0;
+}
 }
 
 // vim: ts=4 sw=4 et
diff --git a/WebCore/platform/graphics/qt/ImageDecoderQt.h b/WebCore/platform/graphics/qt/ImageDecoderQt.h
index 6a272e9..7b3b686 100644
--- a/WebCore/platform/graphics/qt/ImageDecoderQt.h
+++ b/WebCore/platform/graphics/qt/ImageDecoderQt.h
@@ -28,10 +28,11 @@
 #define ImageDecoderQt_h
 
 #include "ImageDecoder.h"
-#include <QtGui/QImage>
+#include <QtGui/QImageReader>
 #include <QtGui/QPixmap>
 #include <QtCore/QList>
 #include <QtCore/QHash>
+#include <QtCore/QBuffer>
 
 namespace WebCore {
 
@@ -56,10 +57,18 @@ private:
     ImageDecoderQt(const ImageDecoderQt&);
     ImageDecoderQt &operator=(const ImageDecoderQt&);
 
-    class ReadContext;
+private:
+    void internalDecodeSize();
+    void internalReadImage(size_t);
+    void internalHandleCurrentImage(size_t);
+    void forceLoadEverything();
+    void failRead();
 
-    int m_loopCount;
-    String m_imageFormat;
+private:
+    String m_format;
+    QBuffer* m_buffer;
+    QImageReader* m_reader;
+    mutable int m_repetitionCount;
 };
 
 
diff --git a/WebCore/platform/image-decoders/ImageDecoder.h b/WebCore/platform/image-decoders/ImageDecoder.h
index 1c095d0..5692de7 100644
--- a/WebCore/platform/image-decoders/ImageDecoder.h
+++ b/WebCore/platform/image-decoders/ImageDecoder.h
@@ -170,7 +170,7 @@ namespace WebCore {
 #if PLATFORM(SKIA)
         NativeImageSkia m_bitmap;
 #elif PLATFORM(QT)
-        QImage m_image;
+        mutable QImage m_image;
         bool m_hasAlpha;
         IntSize m_size;
 #else
diff --git a/WebCore/platform/image-decoders/qt/RGBA32BufferQt.cpp b/WebCore/platform/image-decoders/qt/RGBA32BufferQt.cpp
index e96389d..da6ab38 100644
--- a/WebCore/platform/image-decoders/qt/RGBA32BufferQt.cpp
+++ b/WebCore/platform/image-decoders/qt/RGBA32BufferQt.cpp
@@ -97,7 +97,10 @@ bool RGBA32Buffer::setSize(int newWidth, int newHeight)
 
 QPixmap* RGBA32Buffer::asNewNativeImage() const
 {
-    return new QPixmap(QPixmap::fromImage(m_image));
+    QPixmap pix = QPixmap::fromImage(m_image);
+    m_image = QImage();
+
+    return new QPixmap(pix);
 }
 
 bool RGBA32Buffer::hasAlpha() const

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list