[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