[SCM] WebKit Debian packaging branch, webkit-1.2, updated. upstream/1.1.90-6072-g9a69373

yong.li at torchmobile.com yong.li at torchmobile.com
Thu Apr 8 01:02:26 UTC 2010


The following commit has been merged in the webkit-1.2 branch:
commit 24c25544c8bfde31997e94b15f1f851b63914966
Author: yong.li at torchmobile.com <yong.li at torchmobile.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Tue Jan 12 18:50:07 2010 +0000

    2009-11-23  Yong Li  <yoli at rim.com>
    
            Reviewed by Adam Treat.
    
            Make GIF decoder support down-sampling
            https://bugs.webkit.org/show_bug.cgi?id=31806
    
            * platform/image-decoders/ImageDecoder.cpp:
            (WebCore::ImageDecoder::upperBoundScaledY):
            (WebCore::ImageDecoder::lowerBoundScaledY):
            * platform/image-decoders/ImageDecoder.h:
            (WebCore::RGBA32Buffer::scaledRect):
            (WebCore::RGBA32Buffer::setScaledRect):
            (WebCore::ImageDecoder::scaledSize):
            * platform/image-decoders/gif/GIFImageDecoder.cpp:
            (WebCore::GIFImageDecoder::sizeNowAvailable):
            (WebCore::GIFImageDecoder::initFrameBuffer):
            (WebCore::copyOnePixel):
            (WebCore::GIFImageDecoder::haveDecodedRow):
            (WebCore::GIFImageDecoder::frameComplete):
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@53148 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog
index 78032c7..e9009d0 100644
--- a/JavaScriptCore/ChangeLog
+++ b/JavaScriptCore/ChangeLog
@@ -1,3 +1,24 @@
+2009-11-23  Yong Li  <yoli at rim.com>
+
+        Reviewed by Adam Treat.
+
+        Make GIF decoder support down-sampling
+        https://bugs.webkit.org/show_bug.cgi?id=31806
+
+        * platform/image-decoders/ImageDecoder.cpp:
+        (WebCore::ImageDecoder::upperBoundScaledY):
+        (WebCore::ImageDecoder::lowerBoundScaledY):
+        * platform/image-decoders/ImageDecoder.h:
+        (WebCore::RGBA32Buffer::scaledRect):
+        (WebCore::RGBA32Buffer::setScaledRect):
+        (WebCore::ImageDecoder::scaledSize):
+        * platform/image-decoders/gif/GIFImageDecoder.cpp:
+        (WebCore::GIFImageDecoder::sizeNowAvailable):
+        (WebCore::GIFImageDecoder::initFrameBuffer):
+        (WebCore::copyOnePixel):
+        (WebCore::GIFImageDecoder::haveDecodedRow):
+        (WebCore::GIFImageDecoder::frameComplete):
+
 2010-01-12  Adam Barth  <abarth at webkit.org>
 
         Reviewed by Eric Seidel.
diff --git a/WebCore/platform/image-decoders/ImageDecoder.cpp b/WebCore/platform/image-decoders/ImageDecoder.cpp
index 1b23111..9f665d9 100644
--- a/WebCore/platform/image-decoders/ImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/ImageDecoder.cpp
@@ -260,6 +260,16 @@ int ImageDecoder::lowerBoundScaledX(int origX, int searchStart)
     return getScaledValue<LowerBound>(m_scaledColumns, origX, searchStart);
 }
 
+int ImageDecoder::upperBoundScaledY(int origY, int searchStart)
+{
+    return getScaledValue<UpperBound>(m_scaledRows, origY, searchStart);
+}
+
+int ImageDecoder::lowerBoundScaledY(int origY, int searchStart)
+{
+    return getScaledValue<LowerBound>(m_scaledRows, origY, searchStart);
+}
+
 int ImageDecoder::scaledY(int origY, int searchStart)
 {
     return getScaledValue<Exact>(m_scaledRows, origY, searchStart);
diff --git a/WebCore/platform/image-decoders/ImageDecoder.h b/WebCore/platform/image-decoders/ImageDecoder.h
index 4355f63..558dc77 100644
--- a/WebCore/platform/image-decoders/ImageDecoder.h
+++ b/WebCore/platform/image-decoders/ImageDecoder.h
@@ -130,6 +130,11 @@ namespace WebCore {
             setRGBA(getAddr(x, y), r, g, b, a);
         }
 
+#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
+        const IntRect& scaledRect() const { return m_scaledRect; }
+        void setScaledRect(const IntRect& r) { m_scaledRect = r; }
+#endif
+
 #if PLATFORM(QT)
         void setDecodedImage(const QImage& image);
         QImage decodedImage() const { return m_image; }
@@ -187,6 +192,9 @@ namespace WebCore {
         unsigned m_duration;  // The animation delay.
         FrameDisposalMethod m_disposalMethod;
                               // What to do with this frame's data when initializing the next frame.
+#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
+        IntRect m_scaledRect;
+#endif
     };
 
     // The ImageDecoder class represents a base class for specific image format decoders
@@ -299,6 +307,7 @@ namespace WebCore {
 
 #if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
         void setMaxNumPixels(int m) { m_maxNumPixels = m; }
+        IntSize scaledSize() const { return m_scaled ? IntSize(m_scaledColumns.size(), m_scaledRows.size()) : m_size; }
 #endif
 
     protected:
@@ -306,6 +315,8 @@ namespace WebCore {
         void prepareScaleDataIfNecessary();
         int upperBoundScaledX(int origX, int searchStart = 0);
         int lowerBoundScaledX(int origX, int searchStart = 0);
+        int upperBoundScaledY(int origY, int searchStart = 0);
+        int lowerBoundScaledY(int origY, int searchStart = 0);
         int scaledY(int origY, int searchStart = 0);
 #endif
 
diff --git a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
index 50b91c6..3fd442f 100644
--- a/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
+++ b/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
@@ -246,7 +246,12 @@ void GIFImageDecoder::decode(GIFQuery query, unsigned haltAtFrame)
 // Callbacks from the GIF reader.
 bool GIFImageDecoder::sizeNowAvailable(unsigned width, unsigned height)
 {
-    return setSize(width, height);
+    if (!setSize(width, height))
+        return false;
+#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
+    prepareScaleDataIfNecessary();
+#endif
+    return true;
 }
 
 void GIFImageDecoder::decodingHalted(unsigned bytesLeft)
@@ -268,10 +273,26 @@ bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
 
     RGBA32Buffer* const buffer = &m_frameBufferCache[frameIndex];
     buffer->setRect(frameRect);
+
+#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
+    if (m_scaled) {
+        int left = upperBoundScaledX(frameRect.x());
+        int right = lowerBoundScaledX(frameRect.right(), left);
+        int top = upperBoundScaledY(frameRect.y());
+        int bottom = lowerBoundScaledY(frameRect.bottom(), top);
+        buffer->setScaledRect(IntRect(left, top, right - left, bottom - top));
+    } else
+        buffer->setScaledRect(frameRect);
+#endif
     
     if (frameIndex == 0) {
         // This is the first frame, so we're not relying on any previous data.
-        if (!buffer->setSize(size().width(), size().height())) {
+#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
+        const IntSize& bufferSize = scaledSize();
+#else
+        const IntSize& bufferSize = size();
+#endif
+        if (!buffer->setSize(bufferSize.width(), bufferSize.height())) {
             m_failed = true;
             return false;
         }
@@ -301,12 +322,18 @@ bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
         } else {
             // We want to clear the previous frame to transparent, without
             // affecting pixels in the image outside of the frame.
+#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
+            const IntRect& prevRect = prevBuffer->scaledRect();
+            const IntSize& bufferSize = scaledSize();
+#else
             const IntRect& prevRect = prevBuffer->rect();
+            const IntSize& bufferSize = size();
+#endif
             if ((frameIndex == 0)
-                || prevRect.contains(IntRect(IntPoint(), size()))) {
+                || prevRect.contains(IntRect(IntPoint(), bufferSize))) {
                 // Clearing the first frame, or a frame the size of the whole
                 // image, results in a completely empty image.
-                if (!buffer->setSize(size().width(), size().height())) {
+                if (!buffer->setSize(bufferSize.width(), bufferSize.height())) {
                     m_failed = true;
                     return false;
                 }
@@ -331,6 +358,27 @@ bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
     return true;
 }
 
+static inline void copyOnePixel(const GIFImageDecoderPrivate* reader, const unsigned char* sourceAddr, unsigned char* colorMap,
+                                unsigned colorMapSize, bool writeTransparentPixels, RGBA32Buffer& buffer, int x, int  y, bool& sawAlpha)
+{
+    const unsigned char sourceValue = *sourceAddr;
+    if ((!reader->isTransparent() || (sourceValue != reader->transparentPixel())) && (sourceValue < colorMapSize)) {
+        const size_t colorIndex = static_cast<size_t>(sourceValue) * 3;
+        buffer.setRGBA(x, y, colorMap[colorIndex], colorMap[colorIndex + 1], colorMap[colorIndex + 2], 255);
+    } else {
+        sawAlpha = true;
+        // We may or may not need to write transparent pixels to the buffer.
+        // If we're compositing against a previous image, it's wrong, and if
+        // we're writing atop a cleared, fully transparent buffer, it's
+        // unnecessary; but if we're decoding an interlaced gif and
+        // displaying it "Haeberli"-style, we must write these for passes
+        // beyond the first, or the initial passes will "show through" the
+        // later ones.
+        if (writeTransparentPixels)
+            buffer.setRGBA(x, y, 0, 0, 0, 0);
+    }
+}
+
 bool GIFImageDecoder::haveDecodedRow(unsigned frameIndex,
                                      unsigned char* rowBuffer,
                                      unsigned char* rowEnd,
@@ -342,7 +390,7 @@ bool GIFImageDecoder::haveDecodedRow(unsigned frameIndex,
     // origin within the entire image size, i.e.
     // (m_reader->frameXOffset(), m_reader->frameYOffset()).
     int x = m_reader->frameXOffset();
-    const int y = m_reader->frameYOffset() + rowNumber;
+    int y = m_reader->frameYOffset() + rowNumber;
 
     // Sanity-check the arguments.
     if ((rowBuffer == 0) || (y >= size().height()))
@@ -360,32 +408,57 @@ bool GIFImageDecoder::haveDecodedRow(unsigned frameIndex,
     if ((buffer.status() == RGBA32Buffer::FrameEmpty) && !initFrameBuffer(frameIndex))
         return false;
 
+#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
+    int destYBegin = y;
+    int destYEnd = std::min(y + static_cast<int>(repeatCount), size().height());
+    int destXBegin = x;
+    int destXEnd = std::min(x + (rowEnd - rowBuffer), size().width());
+
+    if (m_scaled) {
+        destYBegin = upperBoundScaledY(destYBegin);
+        if (destYBegin < 0)
+            return true;
+        destYEnd = lowerBoundScaledY(destYEnd - 1, destYBegin + 1);
+        if (destYEnd < destYBegin)
+            return true;
+
+        destXBegin = upperBoundScaledX(destXBegin);
+        if (destXBegin < 0)
+            return true;
+        destXEnd = lowerBoundScaledX(destXEnd - 1, destXBegin + 1);
+        if (destXEnd < destXBegin)
+            return true;
+
+        ++destXEnd;
+        ++destYEnd;
+        x = destXBegin;
+        y = destYBegin;
+    }
+#endif
+
     // Write one row's worth of data into the frame.  There is no guarantee that
     // (rowEnd - rowBuffer) == (size().width() - m_reader->frameXOffset()), so
     // we must ensure we don't run off the end of either the source data or the
     // row's X-coordinates.
-    for (unsigned char* sourceAddr = rowBuffer; (sourceAddr != rowEnd) && (x < size().width()); ++sourceAddr, ++x) {
-        const unsigned char sourceValue = *sourceAddr;
-        if ((!m_reader->isTransparent() || (sourceValue != m_reader->transparentPixel())) && (sourceValue < colorMapSize)) {
-            const size_t colorIndex = static_cast<size_t>(sourceValue) * 3;
-            buffer.setRGBA(x, y, colorMap[colorIndex], colorMap[colorIndex + 1], colorMap[colorIndex + 2], 255);
-        } else {
-            m_currentBufferSawAlpha = true;
-            // We may or may not need to write transparent pixels to the buffer.
-            // If we're compositing against a previous image, it's wrong, and if
-            // we're writing atop a cleared, fully transparent buffer, it's
-            // unnecessary; but if we're decoding an interlaced gif and
-            // displaying it "Haeberli"-style, we must write these for passes
-            // beyond the first, or the initial passes will "show through" the
-            // later ones.
-            if (writeTransparentPixels)
-                buffer.setRGBA(x, y, 0, 0, 0, 0);
+#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
+    if (m_scaled) {
+        for (; x < destXEnd; ++x) {
+            unsigned char* sourceAddr = rowBuffer + m_scaledColumns[x] - m_reader->frameXOffset();
+            copyOnePixel(m_reader, sourceAddr, colorMap, colorMapSize, writeTransparentPixels, buffer, x, y, m_currentBufferSawAlpha);
         }
-    }
-
-    // Tell the frame to copy the row data if need be.
-    if (repeatCount > 1)
+    } else
+#endif
+    for (unsigned char* sourceAddr = rowBuffer; sourceAddr < rowEnd && x < size().width(); ++sourceAddr, ++x)
+        copyOnePixel(m_reader, sourceAddr, colorMap, colorMapSize, writeTransparentPixels, buffer, x, y, m_currentBufferSawAlpha);
+
+     // Tell the frame to copy the row data if need be.
+    if (repeatCount > 1) {
+#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
+        buffer.copyRowNTimes(destXBegin, destXEnd, destYBegin, destYEnd);
+#else
         buffer.copyRowNTimes(m_reader->frameXOffset(), x, y, std::min(y + static_cast<int>(repeatCount), size().height()));
+#endif
+    }
 
     return true;
 }
@@ -405,7 +478,11 @@ void GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration,
     if (!m_currentBufferSawAlpha) {
         // The whole frame was non-transparent, so it's possible that the entire
         // resulting buffer was non-transparent, and we can setHasAlpha(false).
+#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
+        if (buffer.scaledRect().contains(IntRect(IntPoint(), scaledSize())))
+#else
         if (buffer.rect().contains(IntRect(IntPoint(), size())))
+#endif
             buffer.setHasAlpha(false);
         else if (frameIndex > 0) {
             // Tricky case.  This frame does not have alpha only if everywhere
@@ -430,7 +507,11 @@ void GIFImageDecoder::frameComplete(unsigned frameIndex, unsigned frameDuration,
             // it had no alpha, and its rect is contained in the current frame's
             // rect, we know the current frame has no alpha.
             if ((prevBuffer->disposalMethod() == RGBA32Buffer::DisposeOverwriteBgcolor)
+#if ENABLE(IMAGE_DECODER_DOWN_SAMPLING)
+                && !prevBuffer->hasAlpha() && buffer.scaledRect().contains(prevBuffer->scaledRect()))
+#else
                 && !prevBuffer->hasAlpha() && buffer.rect().contains(prevBuffer->rect()))
+#endif
                 buffer.setHasAlpha(false);
         }
     }

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list