Changeset 44573 in webkit


Ignore:
Timestamp:
Jun 10, 2009 10:46:51 AM (15 years ago)
Author:
pkasting@chromium.org
Message:

2009-06-10 Peter Kasting <pkasting@google.com>

Reviewed by Eric Seidel.

https://bugs.webkit.org/show_bug.cgi?id=25709 part five
Rewrite users of ImageDecoder.h to use "safe" API calls, Skia side.
This tweaks the RGBA32Buffer interfaces to be implementable by Cairo as
well and modifies Skia's usage of those interfaces accordingly. Once a
similar change lands on the Cairo side, the Skia and Cairo decoders
should be identical except for the implementation of RGBA32Buffer.

  • platform/graphics/skia/ImageSourceSkia.cpp: (WebCore::ImageSource::createFrameAtIndex): Use new RGBA32Buffer::asNewNativeImage() function.
  • platform/image-decoders/skia/BMPImageReader.cpp: (WebCore::BMPImageReader::processNonRLEData): Use new RGBA32Buffer::zeroFill() function.
  • platform/image-decoders/skia/GIFImageDecoder.cpp: (WebCore::GIFImageDecoder::haveDecodedRow): Rewrite to use RGBA32Buffer::setRGBA(x, y, ...) calls as well as other RGBA32Buffer interface calls instead of knowing the underlying types inside the buffer; also try and add clarity.
  • platform/image-decoders/skia/ImageDecoder.h: Removed bitmap(), width(), and height(). (WebCore::RGBA32Buffer::zeroFill): Added. (WebCore::RGBA32Buffer::copyBitmapData): Avoid using bitmap(), which is going away. (WebCore::RGBA32Buffer::copyRowNTimes): Added. (WebCore::RGBA32Buffer::setSize): Use new zeroFill() function. (WebCore::RGBA32Buffer::asNewNativeImage): Added. (WebCore::RGBA32Buffer::setRGBA): Condensed two versions into one that takes coordinates instead of a raw pointer.
Location:
trunk/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r44571 r44573  
     12009-06-10  Peter Kasting  <pkasting@google.com>
     2
     3        Reviewed by Eric Seidel.
     4
     5        https://bugs.webkit.org/show_bug.cgi?id=25709 part five
     6        Rewrite users of ImageDecoder.h to use "safe" API calls, Skia side.
     7        This tweaks the RGBA32Buffer interfaces to be implementable by Cairo as
     8        well and modifies Skia's usage of those interfaces accordingly.  Once a
     9        similar change lands on the Cairo side, the Skia and Cairo decoders
     10        should be identical except for the implementation of RGBA32Buffer.
     11
     12        * platform/graphics/skia/ImageSourceSkia.cpp:
     13        (WebCore::ImageSource::createFrameAtIndex): Use new RGBA32Buffer::asNewNativeImage() function.
     14        * platform/image-decoders/skia/BMPImageReader.cpp:
     15        (WebCore::BMPImageReader::processNonRLEData): Use new RGBA32Buffer::zeroFill() function.
     16        * platform/image-decoders/skia/GIFImageDecoder.cpp:
     17        (WebCore::GIFImageDecoder::haveDecodedRow): Rewrite to use RGBA32Buffer::setRGBA(x, y, ...) calls as well as other RGBA32Buffer interface calls instead of knowing the underlying types inside the buffer; also try and add clarity.
     18        * platform/image-decoders/skia/ImageDecoder.h: Removed bitmap(), width(), and height().
     19        (WebCore::RGBA32Buffer::zeroFill): Added.
     20        (WebCore::RGBA32Buffer::copyBitmapData): Avoid using bitmap(), which is going away.
     21        (WebCore::RGBA32Buffer::copyRowNTimes): Added.
     22        (WebCore::RGBA32Buffer::setSize): Use new zeroFill() function.
     23        (WebCore::RGBA32Buffer::asNewNativeImage): Added.
     24        (WebCore::RGBA32Buffer::setRGBA): Condensed two versions into one that takes coordinates instead of a raw pointer.
     25
    1262009-06-10  Xan Lopez  <xlopez@igalia.com>
    227
  • trunk/WebCore/platform/graphics/skia/ImageSourceSkia.cpp

    r40410 r44573  
    186186
    187187    // Copy the bitmap.  The pixel data is refcounted internally by SkBitmap, so
    188     // this doesn't cost much.  This pointer will be owned by the BitmapImage
    189     // and freed in FrameData::clear().
    190     return new NativeImageSkia(buffer->bitmap());
     188    // this doesn't cost much. 
     189    return buffer->asNewNativeImage();
    191190}
    192191
  • trunk/WebCore/platform/image-decoders/skia/BMPImageReader.cpp

    r40173 r44573  
    804804                    m_seenNonZeroAlphaPixel = true;
    805805                    if (m_seenZeroAlphaPixel) {
    806                         // The eraseARGB() call here also sets "hasAlpha" true.
    807                         m_frameBufferCache.first().bitmap().eraseARGB(0, 0, 0,
    808                                                                       0);
     806                        m_frameBufferCache.first().zeroFill();
    809807                        m_seenZeroAlphaPixel = false;
    810808                    } else if (alpha != 255)
  • trunk/WebCore/platform/image-decoders/skia/GIFImageDecoder.cpp

    r44545 r44573  
    341341
    342342void GIFImageDecoder::haveDecodedRow(unsigned frameIndex,
    343                                      unsigned char* rowBuffer,   // Pointer to single scanline temporary buffer
     343                                     unsigned char* rowBuffer,
    344344                                     unsigned char* rowEnd,
    345                                      unsigned rowNumber,  // The row index
    346                                      unsigned repeatCount,  // How many times to repeat the row
     345                                     unsigned rowNumber,
     346                                     unsigned repeatCount,
    347347                                     bool writeTransparentPixels)
    348348{
    349     // Initialize the frame if necessary.
    350     RGBA32Buffer& buffer = m_frameBufferCache[frameIndex];
    351     if ((buffer.status() == RGBA32Buffer::FrameEmpty) && !initFrameBuffer(frameIndex))
    352         return;
    353 
    354     // Do nothing for bogus data.
    355     if (rowBuffer == 0 || static_cast<int>(m_reader->frameYOffset() + rowNumber) >= size().height())
    356         return;
    357 
     349    // The pixel data and coordinates supplied to us are relative to the frame's
     350    // origin within the entire image size, i.e.
     351    // (m_reader->frameXOffset(), m_reader->frameYOffset()).
     352    int x = m_reader->frameXOffset();
     353    const int y = m_reader->frameYOffset() + rowNumber;
     354
     355    // Sanity-check the arguments.
     356    if ((rowBuffer == 0) || (y >= size().height()))
     357        return;
     358
     359    // Get the colormap.
    358360    unsigned colorMapSize;
    359361    unsigned char* colorMap;
     
    362364        return;
    363365
    364     // The buffers that we draw are the entire image's width and height, so a final output frame is
    365     // width * height RGBA32 values in size.
    366     //
    367     // A single GIF frame, however, can be smaller than the entire image, i.e., it can represent some sub-rectangle
    368     // within the overall image.  The rows we are decoding are within this
    369     // sub-rectangle.  This means that if the GIF frame's sub-rectangle is (x,y,w,h) then row 0 is really row
    370     // y, and each row goes from x to x+w.
    371     unsigned dstPos = (m_reader->frameYOffset() + rowNumber) * size().width() + m_reader->frameXOffset();
    372     unsigned* dst = buffer.bitmap().getAddr32(0, 0) + dstPos;
    373     unsigned* dstEnd = dst + size().width() - m_reader->frameXOffset();
    374     unsigned* currDst = dst;
    375     unsigned char* currentRowByte = rowBuffer;
    376 
    377     while (currentRowByte != rowEnd && currDst < dstEnd) {
    378         if ((!m_reader->isTransparent() || *currentRowByte != m_reader->transparentPixel()) && *currentRowByte < colorMapSize) {
    379             unsigned colorIndex = *currentRowByte * 3;
    380             unsigned red = colorMap[colorIndex];
    381             unsigned green = colorMap[colorIndex + 1];
    382             unsigned blue = colorMap[colorIndex + 2];
    383             RGBA32Buffer::setRGBA(currDst, red, green, blue, 255);
     366    // Initialize the frame if necessary.
     367    RGBA32Buffer& buffer = m_frameBufferCache[frameIndex];
     368    if ((buffer.status() == RGBA32Buffer::FrameEmpty) && !initFrameBuffer(frameIndex))
     369        return;
     370
     371    // Write one row's worth of data into the frame.  There is no guarantee that
     372    // (rowEnd - rowBuffer) == (size().width() - m_reader->frameXOffset()), so
     373    // we must ensure we don't run off the end of either the source data or the
     374    // row's X-coordinates.
     375    for (unsigned char* sourceAddr = rowBuffer; (sourceAddr != rowEnd) && (x < size().width()); ++sourceAddr, ++x) {
     376        const unsigned char sourceValue = *sourceAddr;
     377        if ((!m_reader->isTransparent() || (sourceValue != m_reader->transparentPixel())) && (sourceValue < colorMapSize)) {
     378            const size_t colorIndex = static_cast<size_t>(sourceValue) * 3;
     379            buffer.setRGBA(x, y, colorMap[colorIndex], colorMap[colorIndex + 1], colorMap[colorIndex + 2], 255);
    384380        } else {
    385381            m_currentBufferSawAlpha = true;
     
    392388            // later ones.
    393389            if (writeTransparentPixels)
    394                 RGBA32Buffer::setRGBA(currDst, 0, 0, 0, 0);
    395         }
    396         currDst++;
    397         currentRowByte++;
    398     }
    399 
    400     if (repeatCount > 1) {
    401         // Copy the row |repeatCount|-1 times.
    402         unsigned num = currDst - dst;
    403         unsigned dataSize = num * sizeof(unsigned);
    404         unsigned width = size().width();
    405         unsigned* end = buffer.bitmap().getAddr32(0, 0) + width * size().height();
    406         currDst = dst + width;
    407         for (unsigned i = 1; i < repeatCount; i++) {
    408             if (currDst + num > end) // Protect against a buffer overrun from a bogus repeatCount.
    409                 break;
    410             memcpy(currDst, dst, dataSize);
    411             currDst += width;
    412         }
    413     }
     390                buffer.setRGBA(x, y, 0, 0, 0, 0);
     391        }
     392    }
     393
     394    // Tell the frame to copy the row data if need be.
     395    if (repeatCount > 1)
     396        buffer.copyRowNTimes(m_reader->frameXOffset(), x, y, std::min(y + static_cast<int>(repeatCount), size().height()));
    414397}
    415398
  • trunk/WebCore/platform/image-decoders/skia/ImageDecoder.h

    r44545 r44573  
    106106        }
    107107
     108        void zeroFill()
     109        {
     110            m_bitmap.eraseARGB(0, 0, 0, 0);
     111        }
     112
    108113        // This function creates a new copy of the image data in |other|, so the
    109114        // two images can be modified independently.
     
    114119
    115120            m_bitmap.reset();
    116             const NativeImageSkia& otherBitmap = other.bitmap();
     121            const NativeImageSkia& otherBitmap = other.m_bitmap;
    117122            otherBitmap.copyTo(&m_bitmap, otherBitmap.config());
    118123        }
    119124
    120         NativeImageSkia& bitmap() { return m_bitmap; }
    121         const NativeImageSkia& bitmap() const { return m_bitmap; }
     125        // This function copies [(startX, startY), (endX, startY)) to the same
     126        // X-coordinates on each subsequent row up to but not including endY.
     127        //
     128        // NOTE: This function does not sanity-check its arguments!  Callers
     129        // MUST not pass invalid values or this will corrupt memory.
     130        void copyRowNTimes(int startX, int endX, int startY, int endY)
     131        {
     132            ASSERT(startX < m_bitmap.width());
     133            ASSERT(endX <= m_bitmap.width());
     134            ASSERT(startY < m_bitmap.height());
     135            ASSERT(endY <= m_bitmap.height());
     136            const int rowBytes = (endX - startX) * sizeof uint32_t;
     137            const uint32_t* const startAddr = m_bitmap.getAddr32(startX, startY);
     138            for (int destY = startY + 1; destY < endY; ++destY)
     139                memcpy(m_bitmap.getAddr32(startX, destY), startAddr, rowBytes);
     140        }
    122141
    123142        // Must be called before any pixels are written. Will return true on
     
    135154            }
    136155
    137             // Clear the image.
    138             m_bitmap.eraseARGB(0, 0, 0, 0);
     156            // Zero the image.
     157            zeroFill();
    139158
    140159            return true;
    141160        }
    142161
    143         int width() const { return m_bitmap.width(); }
    144         int height() const { return m_bitmap.height(); }
     162        // To be used by ImageSource::createFrameAtIndex().  Returns a pointer
     163        // to the underlying native image data.  This pointer will be owned by
     164        // the BitmapImage and freed in FrameData::clear().
     165        NativeImagePtr asNewNativeImage()
     166        {
     167            return new NativeImageSkia(m_bitmap);
     168        }
    145169
    146170        const IntRect& rect() const { return m_rect; }
     
    161185        void setHasAlpha(bool alpha) { m_bitmap.setIsOpaque(!alpha); }
    162186
    163         static void setRGBA(uint32_t* dest, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
    164         {
     187        void setRGBA(int x, int y, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
     188        {
     189            uint32_t* const dest = m_bitmap.getAddr32(x, y);
     190
    165191            // We store this data pre-multiplied.
    166192            if (a == 0)
     
    177203        }
    178204
    179         void setRGBA(int x, int y, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
    180         {
    181             setRGBA(m_bitmap.getAddr32(x, y), r, g, b, a);
    182         }
    183 
    184205    private:
    185206        NativeImageSkia m_bitmap;
Note: See TracChangeset for help on using the changeset viewer.