Changeset 142528 in webkit


Ignore:
Timestamp:
Feb 11, 2013 3:21:32 PM (11 years ago)
Author:
hclam@chromium.org
Message:

Fix code style violations in GIFImageReader.{cc|h}
https://bugs.webkit.org/show_bug.cgi?id=109007

Reviewed by Stephen White.

This is just a style clean up for GIFImageReader.{cc|h}.

There's going to be a lot changes in these two files and style check
will add a lot of noise in later reviews. Fix style problems first.

There is no change in logic at all. Just style fixes.

No new tests.

  • platform/image-decoders/gif/GIFImageDecoder.cpp:

(WebCore::GIFImageDecoder::frameCount):
(WebCore::GIFImageDecoder::repetitionCount):
(WebCore::GIFImageDecoder::haveDecodedRow):
(WebCore::GIFImageDecoder::initFrameBuffer):

  • platform/image-decoders/gif/GIFImageReader.cpp:

(GIFImageReader::outputRow):
(GIFImageReader::doLZW):
(GIFImageReader::read):

  • platform/image-decoders/gif/GIFImageReader.h:

(GIFFrameContext):
(GIFFrameContext::GIFFrameContext):
(GIFFrameContext::~GIFFrameContext):
(GIFImageReader::GIFImageReader):
(GIFImageReader::~GIFImageReader):
(GIFImageReader):
(GIFImageReader::imagesCount):
(GIFImageReader::loopCount):
(GIFImageReader::globalColormap):
(GIFImageReader::globalColormapSize):
(GIFImageReader::frameContext):

Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r142527 r142528  
     12013-02-11  Alpha Lam  <hclam@chromium.org>
     2
     3        Fix code style violations in GIFImageReader.{cc|h}
     4        https://bugs.webkit.org/show_bug.cgi?id=109007
     5
     6        Reviewed by Stephen White.
     7
     8        This is just a style clean up for GIFImageReader.{cc|h}.
     9
     10        There's going to be a lot changes in these two files and style check
     11        will add a lot of noise in later reviews. Fix style problems first.
     12
     13        There is no change in logic at all. Just style fixes.
     14
     15        No new tests.
     16
     17        * platform/image-decoders/gif/GIFImageDecoder.cpp:
     18        (WebCore::GIFImageDecoder::frameCount):
     19        (WebCore::GIFImageDecoder::repetitionCount):
     20        (WebCore::GIFImageDecoder::haveDecodedRow):
     21        (WebCore::GIFImageDecoder::initFrameBuffer):
     22        * platform/image-decoders/gif/GIFImageReader.cpp:
     23        (GIFImageReader::outputRow):
     24        (GIFImageReader::doLZW):
     25        (GIFImageReader::read):
     26        * platform/image-decoders/gif/GIFImageReader.h:
     27        (GIFFrameContext):
     28        (GIFFrameContext::GIFFrameContext):
     29        (GIFFrameContext::~GIFFrameContext):
     30        (GIFImageReader::GIFImageReader):
     31        (GIFImageReader::~GIFImageReader):
     32        (GIFImageReader):
     33        (GIFImageReader::imagesCount):
     34        (GIFImageReader::loopCount):
     35        (GIFImageReader::globalColormap):
     36        (GIFImageReader::globalColormapSize):
     37        (GIFImageReader::frameContext):
     38
    1392013-02-11  Bem Jones-Bey  <bjonesbe@adobe.com>
    240
  • trunk/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp

    r135976 r142528  
    8888        reader.read((const unsigned char*)m_data->data(), m_data->size(), GIFFrameCountQuery, static_cast<unsigned>(-1));
    8989        m_alreadyScannedThisDataForFrameCount = true;
    90         m_frameBufferCache.resize(reader.images_count);
    91         for (int i = 0; i < reader.images_count; ++i)
     90        m_frameBufferCache.resize(reader.imagesCount());
     91        for (int i = 0; i < reader.imagesCount(); ++i)
    9292            m_frameBufferCache[i].setPremultiplyAlpha(m_premultiplyAlpha);
    9393    }
     
    117117    // special code here either, because in this case we'll never change
    118118    // |m_repetitionCount| from its default value.
    119     if (m_reader && (m_reader->loop_count != cLoopCountNotSeen))
    120         m_repetitionCount = m_reader->loop_count;
     119    if (m_reader && (m_reader->loopCount() != cLoopCountNotSeen))
     120        m_repetitionCount = m_reader->loopCount();
    121121    return m_repetitionCount;
    122122}
     
    199199bool GIFImageDecoder::haveDecodedRow(unsigned frameIndex, unsigned char* rowBuffer, unsigned char* rowEnd, unsigned rowNumber, unsigned repeatCount, bool writeTransparentPixels)
    200200{
    201     const GIFFrameReader* frameReader = m_reader->frame_reader;
     201    const GIFFrameContext* frameContext = m_reader->frameContext();
    202202    // The pixel data and coordinates supplied to us are relative to the frame's
    203203    // origin within the entire image size, i.e.
    204     // (frameReader->x_offset, frameReader->y_offset). There is no guarantee
    205     // that (rowEnd - rowBuffer) == (size().width() - frameReader->x_offset), so
     204    // (frameContext->xOffset, frameContext->yOffset). There is no guarantee
     205    // that (rowEnd - rowBuffer) == (size().width() - frameContext->xOffset), so
    206206    // we must ensure we don't run off the end of either the source data or the
    207207    // row's X-coordinates.
    208     int xBegin = upperBoundScaledX(frameReader->x_offset);
    209     int yBegin = upperBoundScaledY(frameReader->y_offset + rowNumber);
    210     int xEnd = lowerBoundScaledX(std::min(static_cast<int>(frameReader->x_offset + (rowEnd - rowBuffer)), size().width()) - 1, xBegin + 1) + 1;
    211     int yEnd = lowerBoundScaledY(std::min(static_cast<int>(frameReader->y_offset + rowNumber + repeatCount), size().height()) - 1, yBegin + 1) + 1;
     208    int xBegin = upperBoundScaledX(frameContext->xOffset);
     209    int yBegin = upperBoundScaledY(frameContext->yOffset + rowNumber);
     210    int xEnd = lowerBoundScaledX(std::min(static_cast<int>(frameContext->xOffset + (rowEnd - rowBuffer)), size().width()) - 1, xBegin + 1) + 1;
     211    int yEnd = lowerBoundScaledY(std::min(static_cast<int>(frameContext->yOffset + rowNumber + repeatCount), size().height()) - 1, yBegin + 1) + 1;
    212212    if (!rowBuffer || (xBegin < 0) || (yBegin < 0) || (xEnd <= xBegin) || (yEnd <= yBegin))
    213213        return true;
     
    216216    const unsigned char* colorMap;
    217217    unsigned colorMapSize;
    218     if (frameReader->is_local_colormap_defined) {
    219         colorMap = frameReader->local_colormap;
    220         colorMapSize = (unsigned)frameReader->local_colormap_size;
     218    if (frameContext->isLocalColormapDefined) {
     219        colorMap = frameContext->localColormap;
     220        colorMapSize = (unsigned)frameContext->localColormapSize;
    221221    } else {
    222         colorMap = m_reader->global_colormap;
    223         colorMapSize = m_reader->global_colormap_size;
     222        colorMap = m_reader->globalColormap();
     223        colorMapSize = m_reader->globalColormapSize();
    224224    }
    225225    if (!colorMap)
     
    234234    // Write one row's worth of data into the frame. 
    235235    for (int x = xBegin; x < xEnd; ++x) {
    236         const unsigned char sourceValue = *(rowBuffer + (m_scaled ? m_scaledColumns[x] : x) - frameReader->x_offset);
    237         if ((!frameReader->is_transparent || (sourceValue != frameReader->tpixel)) && (sourceValue < colorMapSize)) {
     236        const unsigned char sourceValue = *(rowBuffer + (m_scaled ? m_scaledColumns[x] : x) - frameContext->xOffset);
     237        if ((!frameContext->isTransparent || (sourceValue != frameContext->tpixel)) && (sourceValue < colorMapSize)) {
    238238            const size_t colorIndex = static_cast<size_t>(sourceValue) * 3;
    239239            buffer.setRGBA(currentAddress, colorMap[colorIndex], colorMap[colorIndex + 1], colorMap[colorIndex + 2], 255);
     
    332332{
    333333    // Initialize the frame rect in our buffer.
    334     const GIFFrameReader* frameReader = m_reader->frame_reader;
    335     IntRect frameRect(frameReader->x_offset, frameReader->y_offset, frameReader->width, frameReader->height);
     334    const GIFFrameContext* frameContext = m_reader->frameContext();
     335    IntRect frameRect(frameContext->xOffset, frameContext->yOffset, frameContext->width, frameContext->height);
    336336
    337337    // Make sure the frameRect doesn't extend outside the buffer.
    338338    if (frameRect.maxX() > size().width())
    339         frameRect.setWidth(size().width() - frameReader->x_offset);
     339        frameRect.setWidth(size().width() - frameContext->xOffset);
    340340    if (frameRect.maxY() > size().height())
    341         frameRect.setHeight(size().height() - frameReader->y_offset);
     341        frameRect.setHeight(size().height() - frameContext->yOffset);
    342342
    343343    ImageFrame* const buffer = &m_frameBufferCache[frameIndex];
  • trunk/Source/WebCore/platform/image-decoders/gif/GIFImageReader.cpp

    r129523 r142528  
    8282using WebCore::GIFImageDecoder;
    8383
    84 // Define the Mozilla macro setup so that we can leave the macros alone.
    85 #define PR_BEGIN_MACRO  do {
    86 #define PR_END_MACRO    } while (0)
    87 
    88 /*
    89  * GETN(n, s) requests at least 'n' bytes available from 'q', at start of state 's'
    90  *
    91  * Note, the hold will never need to be bigger than 256 bytes to gather up in the hold,
    92  * as each GIF block (except colormaps) can never be bigger than 256 bytes.
    93  * Colormaps are directly copied in the resp. global_colormap or dynamically allocated local_colormap.
    94  * So a fixed buffer in GIFImageReader is good enough.
    95  * This buffer is only needed to copy left-over data from one GifWrite call to the next
    96  */
    97 #define GETN(n,s)                    \
    98   PR_BEGIN_MACRO                     \
    99     bytes_to_consume = (n);      \
    100     state = (s);                 \
    101   PR_END_MACRO
    102 
    103 /* Get a 16-bit value stored in little-endian format */
     84// GETN(n, s) requests at least 'n' bytes available from 'q', at start of state 's'.
     85//
     86// Note, the hold will never need to be bigger than 256 bytes to gather up in the hold,
     87// as each GIF block (except colormaps) can never be bigger than 256 bytes.
     88// Colormaps are directly copied in the resp. global_colormap or dynamically allocated local_colormap.
     89// So a fixed buffer in GIFImageReader is good enough.
     90// This buffer is only needed to copy left-over data from one GifWrite call to the next
     91#define GETN(n, s) \
     92    do { \
     93        m_bytesToConsume = (n); \
     94        m_state = (s); \
     95    } while (0)
     96
     97// Get a 16-bit value stored in little-endian format.
    10498#define GETINT16(p)   ((p)[1]<<8|(p)[0])
    10599
    106 //******************************************************************************
    107100// Send the data to the display front-end.
    108 bool GIFImageReader::output_row()
     101bool GIFImageReader::outputRow()
    109102{
    110   GIFFrameReader* gs = frame_reader;
    111 
    112   int drow_start, drow_end;
    113 
    114   drow_start = drow_end = gs->irow;
    115 
    116   /*
    117    * Haeberli-inspired hack for interlaced GIFs: Replicate lines while
    118    * displaying to diminish the "venetian-blind" effect as the image is
    119    * loaded. Adjust pixel vertical positions to avoid the appearance of the
    120    * image crawling up the screen as successive passes are drawn.
    121    */
    122   if (gs->progressive_display && gs->interlaced && gs->ipass < 4) {
    123     unsigned row_dup = 0, row_shift = 0;
    124 
    125     switch (gs->ipass) {
    126     case 1:
    127       row_dup = 7;
    128       row_shift = 3;
    129       break;
    130     case 2:
    131       row_dup = 3;
    132       row_shift = 1;
    133       break;
    134     case 3:
    135       row_dup = 1;
    136       row_shift = 0;
    137       break;
    138     default:
    139       break;
     103    int drowStart = m_frameContext->irow;
     104    int drowEnd = m_frameContext->irow;
     105
     106    // Haeberli-inspired hack for interlaced GIFs: Replicate lines while
     107    // displaying to diminish the "venetian-blind" effect as the image is
     108    // loaded. Adjust pixel vertical positions to avoid the appearance of the
     109    // image crawling up the screen as successive passes are drawn.
     110    if (m_frameContext->progressiveDisplay && m_frameContext->interlaced && m_frameContext->ipass < 4) {
     111        unsigned rowDup = 0;
     112        unsigned rowShift = 0;
     113
     114        switch (m_frameContext->ipass) {
     115        case 1:
     116            rowDup = 7;
     117            rowShift = 3;
     118            break;
     119        case 2:
     120            rowDup = 3;
     121            rowShift = 1;
     122            break;
     123        case 3:
     124            rowDup = 1;
     125            rowShift = 0;
     126            break;
     127        default:
     128            break;
     129        }
     130
     131        drowStart -= rowShift;
     132        drowEnd = drowStart + rowDup;
     133
     134        // Extend if bottom edge isn't covered because of the shift upward.
     135        if (((m_frameContext->height - 1) - drowEnd) <= rowShift)
     136            drowEnd = m_frameContext->height - 1;
     137
     138        // Clamp first and last rows to upper and lower edge of image.
     139        if (drowStart < 0)
     140            drowStart = 0;
     141
     142        if ((unsigned)drowEnd >= m_frameContext->height)
     143            drowEnd = m_frameContext->height - 1;
    140144    }
    141145
    142     drow_start -= row_shift;
    143     drow_end = drow_start + row_dup;
    144 
    145     /* Extend if bottom edge isn't covered because of the shift upward. */
    146     if (((gs->height - 1) - drow_end) <= row_shift)
    147       drow_end = gs->height - 1;
    148 
    149     /* Clamp first and last rows to upper and lower edge of image. */
    150     if (drow_start < 0)
    151       drow_start = 0;
    152     if ((unsigned)drow_end >= gs->height)
    153       drow_end = gs->height - 1;
    154   }
    155 
    156   /* Protect against too much image data */
    157   if ((unsigned)drow_start >= gs->height)
     146    // Protect against too much image data.
     147    if ((unsigned)drowStart >= m_frameContext->height)
     148        return true;
     149
     150    // CALLBACK: Let the client know we have decoded a row.
     151    if (m_client && m_frameContext
     152        && !m_client->haveDecodedRow(m_imagesCount - 1, m_frameContext->rowbuf, m_frameContext->rowend,
     153            drowStart, drowEnd - drowStart + 1, m_frameContext->progressiveDisplay && m_frameContext->interlaced && m_frameContext->ipass > 1))
     154        return false;
     155
     156    m_frameContext->rowp = m_frameContext->rowbuf;
     157
     158    if (!m_frameContext->interlaced)
     159        m_frameContext->irow++;
     160    else {
     161        do {
     162            switch (m_frameContext->ipass) {
     163            case 1:
     164                m_frameContext->irow += 8;
     165                if (m_frameContext->irow >= m_frameContext->height) {
     166                    m_frameContext->ipass++;
     167                    m_frameContext->irow = 4;
     168                }
     169                break;
     170
     171            case 2:
     172                m_frameContext->irow += 8;
     173                if (m_frameContext->irow >= m_frameContext->height) {
     174                    m_frameContext->ipass++;
     175                    m_frameContext->irow = 2;
     176                }
     177                break;
     178
     179            case 3:
     180                m_frameContext->irow += 4;
     181                if (m_frameContext->irow >= m_frameContext->height) {
     182                    m_frameContext->ipass++;
     183                    m_frameContext->irow = 1;
     184                }
     185                break;
     186
     187            case 4:
     188                m_frameContext->irow += 2;
     189                if (m_frameContext->irow >= m_frameContext->height) {
     190                    m_frameContext->ipass++;
     191                    m_frameContext->irow = 0;
     192                }
     193                break;
     194
     195            default:
     196                break;
     197            }
     198        } while (m_frameContext->irow > (m_frameContext->height - 1));
     199    }
    158200    return true;
    159 
    160   // CALLBACK: Let the client know we have decoded a row.
    161   if (clientptr && frame_reader &&
    162       !clientptr->haveDecodedRow(images_count - 1, frame_reader->rowbuf, frame_reader->rowend,
    163                                  drow_start, drow_end - drow_start + 1,
    164                                  gs->progressive_display && gs->interlaced && gs->ipass > 1))
     201}
     202
     203// Perform Lempel-Ziv-Welch decoding.
     204bool GIFImageReader::doLZW(const unsigned char *q)
     205{
     206    if (!m_frameContext)
     207        return true;
     208
     209    int code;
     210    int incode;
     211    const unsigned char *ch;
     212
     213    // Copy all the decoder state variables into locals so the compiler
     214    // won't worry about them being aliased. The locals will be homed
     215    // back into the GIF decoder structure when we exit.
     216    int avail = m_frameContext->avail;
     217    int bits = m_frameContext->bits;
     218    int cnt = m_count;
     219    int codesize = m_frameContext->codesize;
     220    int codemask = m_frameContext->codemask;
     221    int oldcode = m_frameContext->oldcode;
     222    int clearCode = m_frameContext->clearCode;
     223    unsigned char firstchar = m_frameContext->firstchar;
     224    int datum = m_frameContext->datum;
     225
     226    if (!m_frameContext->prefix) {
     227        m_frameContext->prefix = new unsigned short[MAX_BITS];
     228        memset(m_frameContext->prefix, 0, MAX_BITS * sizeof(short));
     229    }
     230
     231    unsigned short *prefix = m_frameContext->prefix;
     232    unsigned char *stackp = m_frameContext->stackp;
     233    unsigned char *suffix = m_frameContext->suffix;
     234    unsigned char *stack = m_frameContext->stack;
     235    unsigned char *rowp = m_frameContext->rowp;
     236    unsigned char *rowend = m_frameContext->rowend;
     237    unsigned rowsRemaining = m_frameContext->rowsRemaining;
     238
     239    if (rowp == rowend)
     240        return true;
     241
     242#define OUTPUT_ROW \
     243    do { \
     244        if (!outputRow()) \
     245            return false; \
     246        rowsRemaining--; \
     247        rowp = m_frameContext->rowp; \
     248        if (!rowsRemaining) \
     249            goto END; \
     250    } while (0)
     251
     252    for (ch = q; cnt-- > 0; ch++) {
     253        // Feed the next byte into the decoder's 32-bit input buffer.
     254        datum += ((int) *ch) << bits;
     255        bits += 8;
     256
     257        // Check for underflow of decoder's 32-bit input buffer.
     258        while (bits >= codesize) {
     259            // Get the leading variable-length symbol from the data stream.
     260            code = datum & codemask;
     261            datum >>= codesize;
     262            bits -= codesize;
     263
     264            // Reset the dictionary to its original state, if requested.
     265            if (code == clearCode) {
     266                codesize = m_frameContext->datasize + 1;
     267                codemask = (1 << codesize) - 1;
     268                avail = clearCode + 2;
     269                oldcode = -1;
     270                continue;
     271            }
     272
     273            // Check for explicit end-of-stream code.
     274            if (code == (clearCode + 1)) {
     275                // end-of-stream should only appear after all image data.
     276                if (!rowsRemaining)
     277                    return true;
     278                return m_client ? m_client->setFailed() : false;
     279            }
     280
     281            if (oldcode == -1) {
     282                *rowp++ = suffix[code];
     283                if (rowp == rowend)
     284                    OUTPUT_ROW;
     285
     286                firstchar = oldcode = code;
     287                continue;
     288            }
     289
     290            incode = code;
     291            if (code >= avail) {
     292                *stackp++ = firstchar;
     293                code = oldcode;
     294
     295                if (stackp == stack + MAX_BITS)
     296                    return m_client ? m_client->setFailed() : false;
     297            }
     298
     299            while (code >= clearCode) {
     300                if (code >= MAX_BITS || code == prefix[code])
     301                    return m_client ? m_client->setFailed() : false;
     302
     303                // Even though suffix[] only holds characters through suffix[avail - 1],
     304                // allowing code >= avail here lets us be more tolerant of malformed
     305                // data. As long as code < MAX_BITS, the only risk is a garbled image,
     306                // which is no worse than refusing to display it.
     307                *stackp++ = suffix[code];
     308                code = prefix[code];
     309
     310                if (stackp == stack + MAX_BITS)
     311                    return m_client ? m_client->setFailed() : false;
     312            }
     313
     314            *stackp++ = firstchar = suffix[code];
     315
     316            // Define a new codeword in the dictionary.
     317            if (avail < 4096) {
     318                prefix[avail] = oldcode;
     319                suffix[avail] = firstchar;
     320                avail++;
     321
     322                // If we've used up all the codewords of a given length
     323                // increase the length of codewords by one bit, but don't
     324                // exceed the specified maximum codeword size of 12 bits.
     325                if ((!(avail & codemask)) && (avail < 4096)) {
     326                    codesize++;
     327                    codemask += avail;
     328                }
     329            }
     330            oldcode = incode;
     331
     332            // Copy the decoded data out to the scanline buffer.
     333            do {
     334                *rowp++ = *--stackp;
     335                if (rowp == rowend)
     336                    OUTPUT_ROW;
     337            } while (stackp > stack);
     338        }
     339    }
     340
     341END:
     342    // Home the local copies of the GIF decoder state variables.
     343    m_frameContext->avail = avail;
     344    m_frameContext->bits = bits;
     345    m_frameContext->codesize = codesize;
     346    m_frameContext->codemask = codemask;
     347    m_count = cnt;
     348    m_frameContext->oldcode = oldcode;
     349    m_frameContext->firstchar = firstchar;
     350    m_frameContext->datum = datum;
     351    m_frameContext->stackp = stackp;
     352    m_frameContext->rowp = rowp;
     353    m_frameContext->rowsRemaining = rowsRemaining;
     354    return true;
     355}
     356
     357
     358// Process data arriving from the stream for the gif decoder.
     359bool GIFImageReader::read(const unsigned char *buf, unsigned len, GIFImageDecoder::GIFQuery query, unsigned haltAtFrame)
     360{
     361    if (!len) {
     362        // No new data has come in since the last call, just ignore this call.
     363        return true;
     364    }
     365
     366    const unsigned char *q = buf;
     367
     368    // Add what we have so far to the block.
     369    // If previous call to me left something in the hold first complete current block
     370    // or if we are filling the colormaps, first complete the colormap.
     371    unsigned char* p = 0;
     372    if (m_state == GIFGlobalColormap)
     373        p = m_globalColormap;
     374    else if (m_state == GIFImageColormap)
     375        p = m_frameContext ? m_frameContext->localColormap : 0;
     376    else if (m_bytesInHold)
     377        p = m_hold;
     378    else
     379        p = 0;
     380
     381    if (p || (m_state == GIFGlobalColormap) || (m_state == GIFImageColormap)) {
     382        // Add what we have sofar to the block
     383        unsigned length = len < m_bytesToConsume ? len : m_bytesToConsume;
     384        if (p)
     385            memcpy(p + m_bytesInHold, buf, length);
     386
     387        if (length < m_bytesToConsume) {
     388            // Not enough in 'buf' to complete current block, get more
     389            m_bytesInHold += length;
     390            m_bytesToConsume -= length;
     391            if (m_client)
     392                m_client->decodingHalted(0);
     393            return false;
     394        }
     395
     396        // Reset hold buffer count
     397        m_bytesInHold = 0;
     398
     399        // Point 'q' to complete block in hold (or in colormap)
     400        q = p;
     401    }
     402
     403    // Invariant:
     404    //    'q' is start of current to be processed block (hold, colormap or buf)
     405    //    'm_bytesToConsume' is number of bytes to consume from 'buf'
     406    //    'buf' points to the bytes to be consumed from the input buffer
     407    //    'len' is number of bytes left in input buffer from position 'buf'.
     408    //    At entrance of the for loop will 'buf' will be moved 'm_bytesToConsume'
     409    //    to point to next buffer, 'len' is adjusted accordingly.
     410    //    So that next round in for loop, q gets pointed to the next buffer.
     411    for (;len >= m_bytesToConsume; q = buf) {
     412        // Eat the current block from the buffer, q keeps pointed at current block.
     413        buf += m_bytesToConsume;
     414        len -= m_bytesToConsume;
     415
     416        switch (m_state) {
     417        case GIFLZW:
     418            if (!doLZW(q))
     419                return false; // If doLZW() encountered an error, it has already called m_client->setFailed().
     420            GETN(1, GIFSubBlock);
     421            break;
     422
     423        case GIFLZWStart: {
     424            // Initialize LZW parser/decoder.
     425            int datasize = *q;
     426
     427            // Since we use a codesize of 1 more than the datasize, we need to ensure
     428            // that our datasize is strictly less than the MAX_LZW_BITS value (12).
     429            // This sets the largest possible codemask correctly at 4095.
     430            if (datasize >= MAX_LZW_BITS)
     431                return m_client ? m_client->setFailed() : false;
     432            int clearCode = 1 << datasize;
     433            if (clearCode >= MAX_BITS)
     434                return m_client ? m_client->setFailed() : false;
     435
     436            if (m_frameContext) {
     437                m_frameContext->datasize = datasize;
     438                m_frameContext->clearCode = clearCode;
     439                m_frameContext->avail = m_frameContext->clearCode + 2;
     440                m_frameContext->oldcode = -1;
     441                m_frameContext->codesize = m_frameContext->datasize + 1;
     442                m_frameContext->codemask = (1 << m_frameContext->codesize) - 1;
     443                m_frameContext->datum = m_frameContext->bits = 0;
     444
     445                // Init the tables.
     446                if (!m_frameContext->suffix)
     447                    m_frameContext->suffix = new unsigned char[MAX_BITS];
     448
     449                // Clearing the whole suffix table lets us be more tolerant of bad data.
     450                memset(m_frameContext->suffix, 0, MAX_BITS);
     451                for (int i = 0; i < m_frameContext->clearCode; i++)
     452                    m_frameContext->suffix[i] = i;
     453
     454                if (!m_frameContext->stack)
     455                    m_frameContext->stack = new unsigned char[MAX_BITS];
     456                m_frameContext->stackp = m_frameContext->stack;
     457            }
     458
     459            GETN(1, GIFSubBlock);
     460            break;
     461        }
     462
     463        case GIFType: {
     464            // All GIF files begin with "GIF87a" or "GIF89a".
     465            if (!strncmp((char*)q, "GIF89a", 6))
     466                m_version = 89;
     467            else if (!strncmp((char*)q, "GIF87a", 6))
     468                m_version = 87;
     469            else
     470                return m_client ? m_client->setFailed() : false;
     471            GETN(7, GIFGlobalHeader);
     472            break;
     473        }
     474
     475        case GIFGlobalHeader: {
     476            // This is the height and width of the "screen" or frame into which images are rendered. The
     477            // individual images can be smaller than the screen size and located with an origin anywhere
     478            // within the screen.
     479            m_screenWidth = GETINT16(q);
     480            m_screenHeight = GETINT16(q + 2);
     481
     482            // CALLBACK: Inform the decoderplugin of our size.
     483            if (m_client && !m_client->setSize(m_screenWidth, m_screenHeight))
     484                return false;
     485
     486            m_screenBgcolor = q[5];
     487            m_globalColormapSize = 2 << (q[4] & 0x07);
     488
     489            if ((q[4] & 0x80) && m_globalColormapSize > 0) { /* global map */
     490                // Get the global colormap
     491                const unsigned size = 3*m_globalColormapSize;
     492
     493                // Malloc the color map, but only if we're not just counting frames.
     494                if (query != GIFImageDecoder::GIFFrameCountQuery)
     495                    m_globalColormap = new unsigned char[size];
     496
     497                if (len < size) {
     498                    // Use 'hold' pattern to get the global colormap
     499                    GETN(size, GIFGlobalColormap);
     500                    break;
     501                }
     502
     503                // Copy everything and go directly to GIFImage_start.
     504                if (m_globalColormap)
     505                    memcpy(m_globalColormap, buf, size);
     506                buf += size;
     507                len -= size;
     508            }
     509
     510            GETN(1, GIFImageStart);
     511
     512            // q[6] = Pixel Aspect Ratio
     513            //   Not used
     514            //   float aspect = (float)((q[6] + 15) / 64.0);
     515            break;
     516        }
     517
     518        case GIFGlobalColormap: {
     519            // Everything is already copied into m_globalColormap
     520            GETN(1, GIFImageStart);
     521            break;
     522        }
     523
     524        case GIFImageStart: {
     525            if (*q == ';') { // terminator.
     526                GETN(0, GIFDone);
     527                break;
     528            }
     529
     530            if (*q == '!') { // extension.
     531                GETN(2, GIFExtension);
     532                break;
     533            }
     534
     535            // If we get anything other than ',' (image separator), '!'
     536            // (extension), or ';' (trailer), there is extraneous data
     537            // between blocks. The GIF87a spec tells us to keep reading
     538            // until we find an image separator, but GIF89a says such
     539            // a file is corrupt. We follow GIF89a and bail out.
     540            if (*q != ',')
     541                return m_client ? m_client->setFailed() : false;
     542
     543            GETN(9, GIFImageHeader);
     544            break;
     545        }
     546
     547        case GIFExtension: {
     548            m_count = q[1];
     549            GIFState es = GIFSkipBlock;
     550
     551            // The GIF spec mandates lengths for three of the extensions below.
     552            // However, it's possible for GIFs in the wild to deviate. For example,
     553            // some GIFs that embed ICC color profiles using GIFApplicationExtension
     554            // violate the spec and treat this extension block like a sort of
     555            // "extension + data" block, giving a size greater than 11 and filling the
     556            // remaining bytes with data (then following with more data blocks as
     557            // needed), instead of placing a true data block just after the 11 byte
     558            // extension block.
     559            //
     560            // Accordingly, if the specified length is larger than the required value,
     561            // we use it. If it's smaller, then we enforce the spec value, because the
     562            // parsers for these extensions expect to have the specified number of
     563            // bytes available, and if we don't ensure that, they could read off the
     564            // end of the heap buffer. (In this case, it's likely the GIF is corrupt
     565            // and we'll soon fail to decode anyway.)
     566            switch (*q) {
     567            case 0xf9:
     568                es = GIFControlExtension;
     569                m_count = std::max(m_count, 4);
     570                break;
     571
     572            case 0x01:
     573                // ignoring plain text extension
     574                m_count = std::max(m_count, 12);
     575                break;
     576
     577            case 0xff:
     578                es = GIFApplicationExtension;
     579                m_count = std::max(m_count, 11);
     580                break;
     581
     582            case 0xfe:
     583                es = GIFConsumeComment;
     584                break;
     585            }
     586
     587            if (m_count)
     588                GETN(m_count, es);
     589            else
     590                GETN(1, GIFImageStart);
     591            break;
     592        }
     593
     594        case GIFConsumeBlock: {
     595            if (!*q)
     596                GETN(1, GIFImageStart);
     597            else
     598                GETN(*q, GIFSkipBlock);
     599            break;
     600        }
     601
     602        case GIFSkipBlock: {
     603            GETN(1, GIFConsumeBlock);
     604            break;
     605        }
     606
     607        case GIFControlExtension: {
     608            if (query != GIFImageDecoder::GIFFrameCountQuery) {
     609                if (!m_frameContext)
     610                    m_frameContext = new GIFFrameContext();
     611            }
     612
     613            if (m_frameContext) {
     614                if (*q & 0x1) {
     615                    m_frameContext->tpixel = q[3];
     616                    m_frameContext->isTransparent = true;
     617                } else {
     618                    m_frameContext->isTransparent = false;
     619                    // ignoring gfx control extension
     620                }
     621                // NOTE: This relies on the values in the FrameDisposalMethod enum
     622                // matching those in the GIF spec!
     623                int disposalMethod = ((*q) >> 2) & 0x7;
     624                m_frameContext->disposalMethod = (WebCore::ImageFrame::FrameDisposalMethod)disposalMethod;
     625
     626                // Some specs say 3rd bit (value 4), other specs say value 3
     627                // Let's choose 3 (the more popular)
     628                if (disposalMethod == 4)
     629                    m_frameContext->disposalMethod = WebCore::ImageFrame::DisposeOverwritePrevious;
     630                m_frameContext->delayTime = GETINT16(q + 1) * 10;
     631            }
     632            GETN(1, GIFConsumeBlock);
     633            break;
     634        }
     635
     636        case GIFCommentExtension: {
     637            if (*q)
     638                GETN(*q, GIFConsumeComment);
     639            else
     640                GETN(1, GIFImageStart);
     641            break;
     642        }
     643
     644        case GIFConsumeComment: {
     645            GETN(1, GIFCommentExtension);
     646            break;
     647        }
     648
     649        case GIFApplicationExtension: {
     650            // Check for netscape application extension.
     651            if (!strncmp((char*)q, "NETSCAPE2.0", 11) || !strncmp((char*)q, "ANIMEXTS1.0", 11))
     652                GETN(1, GIFNetscapeExtensionBlock);
     653            else
     654                GETN(1, GIFConsumeBlock);
     655            break;
     656        }
     657
     658        // Netscape-specific GIF extension: animation looping.
     659        case GIFNetscapeExtensionBlock: {
     660            if (*q)
     661                GETN(*q, GIFConsumeNetscapeExtension);
     662            else
     663                GETN(1, GIFImageStart);
     664            break;
     665        }
     666
     667        // Parse netscape-specific application extensions
     668        case GIFConsumeNetscapeExtension: {
     669            int netscapeExtension = q[0] & 7;
     670
     671            // Loop entire animation specified # of times. Only read the loop count during the first iteration.
     672            if (netscapeExtension == 1) {
     673                m_loopCount = GETINT16(q + 1);
     674
     675                // Zero loop count is infinite animation loop request.
     676                if (!m_loopCount)
     677                    m_loopCount = WebCore::cAnimationLoopInfinite;
     678
     679                GETN(1, GIFNetscapeExtensionBlock);
     680            } else if (netscapeExtension == 2) {
     681                // Wait for specified # of bytes to enter buffer.
     682
     683                // Don't do this, this extension doesn't exist (isn't used at all)
     684                // and doesn't do anything, as our streaming/buffering takes care of it all...
     685                // See: http://semmix.pl/color/exgraf/eeg24.htm
     686                GETN(1, GIFNetscapeExtensionBlock);
     687            } else {
     688                // 0,3-7 are yet to be defined netscape extension codes
     689                return m_client ? m_client->setFailed() : false;
     690            }
     691            break;
     692        }
     693
     694        case GIFImageHeader: {
     695            unsigned height, width, xOffset, yOffset;
     696
     697            /* Get image offsets, with respect to the screen origin */
     698            xOffset = GETINT16(q);
     699            yOffset = GETINT16(q + 2);
     700
     701            /* Get image width and height. */
     702            width  = GETINT16(q + 4);
     703            height = GETINT16(q + 6);
     704
     705            /* Work around broken GIF files where the logical screen
     706             * size has weird width or height.  We assume that GIF87a
     707             * files don't contain animations.
     708             */
     709            if (!m_imagesDecoded
     710                && ((m_screenHeight < height) || (m_screenWidth < width) || (m_version == 87))) {
     711                m_screenHeight = height;
     712                m_screenWidth = width;
     713                xOffset = 0;
     714                yOffset = 0;
     715
     716                // CALLBACK: Inform the decoderplugin of our size.
     717                if (m_client && !m_client->setSize(m_screenWidth, m_screenHeight))
     718                    return false;
     719            }
     720
     721            // Work around more broken GIF files that have zero image width or height
     722            if (!height || !width) {
     723                height = m_screenHeight;
     724                width = m_screenWidth;
     725                if (!height || !width)
     726                    return m_client ? m_client->setFailed() : false;
     727            }
     728
     729            if (query == GIFImageDecoder::GIFSizeQuery || haltAtFrame == m_imagesDecoded) {
     730                // The decoder needs to stop. Hand back the number of bytes we consumed from
     731                // buffer minus 9 (the amount we consumed to read the header).
     732                if (m_client)
     733                    m_client->decodingHalted(len + 9);
     734                GETN(9, GIFImageHeader);
     735                return true;
     736            }
     737
     738            m_imagesCount = m_imagesDecoded + 1;
     739
     740            if (query == GIFImageDecoder::GIFFullQuery && !m_frameContext)
     741                m_frameContext = new GIFFrameContext();
     742
     743            if (m_frameContext) {
     744                m_frameContext->xOffset = xOffset;
     745                m_frameContext->yOffset = yOffset;
     746                m_frameContext->height = height;
     747                m_frameContext->width = width;
     748
     749                /* This case will never be taken if this is the first image */
     750                /* being decoded. If any of the later images are larger     */
     751                /* than the screen size, we need to reallocate buffers.     */
     752                if (m_screenWidth < width) {
     753                    /* XXX Deviant! */
     754                    delete []m_frameContext->rowbuf;
     755                    m_screenWidth = width;
     756                    m_frameContext->rowbuf = new unsigned char[m_screenWidth];
     757                } else if (!m_frameContext->rowbuf)
     758                    m_frameContext->rowbuf = new unsigned char[m_screenWidth];
     759
     760                if (!m_frameContext->rowbuf)
     761                    return m_client ? m_client->setFailed() : false;
     762                if (m_screenHeight < height)
     763                    m_screenHeight = height;
     764
     765                if (q[8] & 0x40) {
     766                    m_frameContext->interlaced = true;
     767                    m_frameContext->ipass = 1;
     768                } else {
     769                    m_frameContext->interlaced = false;
     770                    m_frameContext->ipass = 0;
     771                }
     772
     773                if (!m_imagesDecoded)
     774                    m_frameContext->progressiveDisplay = true;
     775                else {
     776                    // Overlaying interlaced, transparent GIFs over
     777                    // existing image data using the Haeberli display hack
     778                    // requires saving the underlying image in order to
     779                    // avoid jaggies at the transparency edges. We are
     780                    // unprepared to deal with that, so don't display such
     781                    // images progressively
     782                    m_frameContext->progressiveDisplay = false;
     783                }
     784
     785                // Clear state from last image.
     786                m_frameContext->irow = 0;
     787                m_frameContext->rowsRemaining = m_frameContext->height;
     788                m_frameContext->rowend = m_frameContext->rowbuf + m_frameContext->width;
     789                m_frameContext->rowp = m_frameContext->rowbuf;
     790
     791                // bits per pixel is q[8]&0x07
     792            }
     793
     794            // has a local colormap?
     795            if (q[8] & 0x80) {
     796                int numColors = 2 << (q[8] & 0x7);
     797                const unsigned size = 3 * numColors;
     798                unsigned char *map = m_frameContext ? m_frameContext->localColormap : 0;
     799                if (m_frameContext && (!map || (numColors > m_frameContext->localColormapSize))) {
     800                    delete []map;
     801                    map = new unsigned char[size];
     802                    if (!map)
     803                        return m_client ? m_client->setFailed() : false;
     804                }
     805
     806                // Switch to the new local palette after it loads
     807                if (m_frameContext) {
     808                    m_frameContext->localColormap = map;
     809                    m_frameContext->localColormapSize = numColors;
     810                    m_frameContext->isLocalColormapDefined = true;
     811                }
     812
     813                if (len < size) {
     814                    // Use 'hold' pattern to get the image colormap
     815                    GETN(size, GIFImageColormap);
     816                    break;
     817                }
     818
     819                // Copy everything and directly go to GIFLZWStart
     820                if (m_frameContext)
     821                    memcpy(m_frameContext->localColormap, buf, size);
     822                buf += size;
     823                len -= size;
     824            } else if (m_frameContext) {
     825                // Switch back to the global palette
     826                m_frameContext->isLocalColormapDefined = false;
     827            }
     828            GETN(1, GIFLZWStart);
     829            break;
     830        }
     831
     832        case GIFImageColormap: {
     833            // Everything is already copied into localColormap
     834            GETN(1, GIFLZWStart);
     835            break;
     836        }
     837
     838        case GIFSubBlock: {
     839            // Still working on the same image: Process next LZW data block.
     840            if ((m_count = *q)) {
     841                // Make sure there are still rows left. If the GIF data
     842                // is corrupt, we may not get an explicit terminator.
     843                if (m_frameContext && !m_frameContext->rowsRemaining) {
     844                    // This is an illegal GIF, but we remain tolerant.
     845                    GETN(1, GIFSubBlock);
     846                }
     847                GETN(m_count, GIFLZW);
     848            } else {
     849                // See if there are any more images in this sequence.
     850                m_imagesDecoded++;
     851
     852                // CALLBACK: The frame is now complete.
     853                if (m_client && m_frameContext && !m_client->frameComplete(m_imagesDecoded - 1, m_frameContext->delayTime, m_frameContext->disposalMethod))
     854                    return false; // frameComplete() has already called m_client->setFailed().
     855
     856                // Clear state from this image
     857                if (m_frameContext) {
     858                    m_frameContext->isLocalColormapDefined = false;
     859                    m_frameContext->isTransparent = false;
     860                }
     861
     862                GETN(1, GIFImageStart);
     863            }
     864            break;
     865        }
     866
     867        case GIFDone: {
     868            // When the GIF is done, we can stop.
     869            if (m_client)
     870                m_client->gifComplete();
     871            return true;
     872        }
     873
     874        default:
     875            // We shouldn't ever get here.
     876            break;
     877        }
     878    }
     879
     880    // Copy the leftover into m_frameContext->m_hold
     881    m_bytesInHold = len;
     882    if (len) {
     883        // Add what we have sofar to the block
     884        unsigned char* p;
     885        if (m_state == GIFGlobalColormap)
     886            p = m_globalColormap;
     887        else if (m_state == GIFImageColormap)
     888            p = m_frameContext ? m_frameContext->localColormap : 0;
     889        else
     890            p = m_hold;
     891        if (p)
     892            memcpy(p, buf, len);
     893        m_bytesToConsume -= len;
     894    }
     895
     896    if (m_client)
     897        m_client->decodingHalted(0);
    165898    return false;
    166 
    167   gs->rowp = gs->rowbuf;
    168 
    169   if (!gs->interlaced)
    170     gs->irow++;
    171   else {
    172     do {
    173       switch (gs->ipass)
    174       {
    175         case 1:
    176           gs->irow += 8;
    177           if (gs->irow >= gs->height) {
    178             gs->ipass++;
    179             gs->irow = 4;
    180           }
    181           break;
    182 
    183         case 2:
    184           gs->irow += 8;
    185           if (gs->irow >= gs->height) {
    186             gs->ipass++;
    187             gs->irow = 2;
    188           }
    189           break;
    190 
    191         case 3:
    192           gs->irow += 4;
    193           if (gs->irow >= gs->height) {
    194             gs->ipass++;
    195             gs->irow = 1;
    196           }
    197           break;
    198 
    199         case 4:
    200           gs->irow += 2;
    201           if (gs->irow >= gs->height){
    202             gs->ipass++;
    203             gs->irow = 0;
    204           }
    205           break;
    206 
    207         default:
    208           break;
    209       }
    210     } while (gs->irow > (gs->height - 1));
    211   }
    212 
    213   return true;
    214899}
    215 
    216 //******************************************************************************
    217 /* Perform Lempel-Ziv-Welch decoding */
    218 bool GIFImageReader::do_lzw(const unsigned char *q)
    219 {
    220   GIFFrameReader* gs = frame_reader;
    221   if (!gs)
    222     return true;
    223 
    224   int code;
    225   int incode;
    226   const unsigned char *ch;
    227  
    228   /* Copy all the decoder state variables into locals so the compiler
    229    * won't worry about them being aliased.  The locals will be homed
    230    * back into the GIF decoder structure when we exit.
    231    */
    232   int avail       = gs->avail;
    233   int bits        = gs->bits;
    234   int cnt         = count;
    235   int codesize    = gs->codesize;
    236   int codemask    = gs->codemask;
    237   int oldcode     = gs->oldcode;
    238   int clear_code  = gs->clear_code;
    239   unsigned char firstchar = gs->firstchar;
    240   int datum     = gs->datum;
    241 
    242   if (!gs->prefix) {
    243     gs->prefix = new unsigned short[MAX_BITS];
    244     memset(gs->prefix, 0, MAX_BITS * sizeof(short));
    245   }
    246 
    247   unsigned short *prefix  = gs->prefix;
    248   unsigned char *stackp   = gs->stackp;
    249   unsigned char *suffix   = gs->suffix;
    250   unsigned char *stack    = gs->stack;
    251   unsigned char *rowp     = gs->rowp;
    252   unsigned char *rowend   = gs->rowend;
    253   unsigned rows_remaining = gs->rows_remaining;
    254 
    255   if (rowp == rowend)
    256     return true;
    257 
    258 #define OUTPUT_ROW                                                  \
    259   PR_BEGIN_MACRO                                                        \
    260     if (!output_row())                                                     \
    261       return false;                                                        \
    262     rows_remaining--;                                                   \
    263     rowp = frame_reader->rowp;                                                    \
    264     if (!rows_remaining)                                                \
    265       goto END;                                                         \
    266   PR_END_MACRO
    267 
    268   for (ch = q; cnt-- > 0; ch++)
    269   {
    270     /* Feed the next byte into the decoder's 32-bit input buffer. */
    271     datum += ((int) *ch) << bits;
    272     bits += 8;
    273 
    274     /* Check for underflow of decoder's 32-bit input buffer. */
    275     while (bits >= codesize)
    276     {
    277       /* Get the leading variable-length symbol from the data stream */
    278       code = datum & codemask;
    279       datum >>= codesize;
    280       bits -= codesize;
    281 
    282       /* Reset the dictionary to its original state, if requested */
    283       if (code == clear_code) {
    284         codesize = gs->datasize + 1;
    285         codemask = (1 << codesize) - 1;
    286         avail = clear_code + 2;
    287         oldcode = -1;
    288         continue;
    289       }
    290 
    291       /* Check for explicit end-of-stream code */
    292       if (code == (clear_code + 1)) {
    293         /* end-of-stream should only appear after all image data */
    294         if (!rows_remaining)
    295           return true;
    296         return clientptr ? clientptr->setFailed() : false;
    297       }
    298 
    299       if (oldcode == -1) {
    300         *rowp++ = suffix[code];
    301         if (rowp == rowend)
    302           OUTPUT_ROW;
    303 
    304         firstchar = oldcode = code;
    305         continue;
    306       }
    307 
    308       incode = code;
    309       if (code >= avail) {
    310         *stackp++ = firstchar;
    311         code = oldcode;
    312 
    313         if (stackp == stack + MAX_BITS)
    314           return clientptr ? clientptr->setFailed() : false;
    315       }
    316 
    317       while (code >= clear_code)
    318       {
    319         if (code >= MAX_BITS || code == prefix[code])
    320           return clientptr ? clientptr->setFailed() : false;
    321 
    322         // Even though suffix[] only holds characters through suffix[avail - 1],
    323         // allowing code >= avail here lets us be more tolerant of malformed
    324         // data. As long as code < MAX_BITS, the only risk is a garbled image,
    325         // which is no worse than refusing to display it.
    326         *stackp++ = suffix[code];
    327         code = prefix[code];
    328 
    329         if (stackp == stack + MAX_BITS)
    330           return clientptr ? clientptr->setFailed() : false;
    331       }
    332 
    333       *stackp++ = firstchar = suffix[code];
    334 
    335       /* Define a new codeword in the dictionary. */
    336       if (avail < 4096) {
    337         prefix[avail] = oldcode;
    338         suffix[avail] = firstchar;
    339         avail++;
    340 
    341         /* If we've used up all the codewords of a given length
    342          * increase the length of codewords by one bit, but don't
    343          * exceed the specified maximum codeword size of 12 bits.
    344          */
    345         if (((avail & codemask) == 0) && (avail < 4096)) {
    346           codesize++;
    347           codemask += avail;
    348         }
    349       }
    350       oldcode = incode;
    351 
    352         /* Copy the decoded data out to the scanline buffer. */
    353       do {
    354         *rowp++ = *--stackp;
    355         if (rowp == rowend) {
    356           OUTPUT_ROW;
    357         }
    358       } while (stackp > stack);
    359     }
    360   }
    361 
    362   END:
    363 
    364   /* Home the local copies of the GIF decoder state variables */
    365   gs->avail = avail;
    366   gs->bits = bits;
    367   gs->codesize = codesize;
    368   gs->codemask = codemask;
    369   count = cnt;
    370   gs->oldcode = oldcode;
    371   gs->firstchar = firstchar;
    372   gs->datum = datum;
    373   gs->stackp = stackp;
    374   gs->rowp = rowp;
    375   gs->rows_remaining = rows_remaining;
    376 
    377   return true;
    378 }
    379 
    380 
    381 /******************************************************************************/
    382 /*
    383  * process data arriving from the stream for the gif decoder
    384  */
    385 
    386 bool GIFImageReader::read(const unsigned char *buf, unsigned len,
    387                      GIFImageDecoder::GIFQuery query, unsigned haltAtFrame)
    388 {
    389   if (!len) {
    390     // No new data has come in since the last call, just ignore this call.
    391     return true;
    392   }
    393 
    394   const unsigned char *q = buf;
    395 
    396   // Add what we have so far to the block
    397   // If previous call to me left something in the hold first complete current block
    398   // Or if we are filling the colormaps, first complete the colormap
    399   unsigned char* p = 0;
    400   if (state == gif_global_colormap)
    401     p = global_colormap;
    402   else if (state == gif_image_colormap)
    403     p = frame_reader ? frame_reader->local_colormap : 0;
    404   else if (bytes_in_hold)
    405     p = hold;
    406   else
    407     p = 0;
    408 
    409   if (p || (state == gif_global_colormap) || (state == gif_image_colormap)) {
    410     // Add what we have sofar to the block
    411     unsigned l = len < bytes_to_consume ? len : bytes_to_consume;
    412     if (p)
    413         memcpy(p + bytes_in_hold, buf, l);
    414 
    415     if (l < bytes_to_consume) {
    416       // Not enough in 'buf' to complete current block, get more
    417       bytes_in_hold += l;
    418       bytes_to_consume -= l;
    419       if (clientptr)
    420         clientptr->decodingHalted(0);
    421       return false;
    422     }
    423     // Reset hold buffer count
    424     bytes_in_hold = 0;
    425     // Point 'q' to complete block in hold (or in colormap)
    426     q = p;
    427   }
    428 
    429   // Invariant:
    430   //    'q' is start of current to be processed block (hold, colormap or buf)
    431   //    'bytes_to_consume' is number of bytes to consume from 'buf'
    432   //    'buf' points to the bytes to be consumed from the input buffer
    433   //    'len' is number of bytes left in input buffer from position 'buf'.
    434   //    At entrance of the for loop will 'buf' will be moved 'bytes_to_consume'
    435   //    to point to next buffer, 'len' is adjusted accordingly.
    436   //    So that next round in for loop, q gets pointed to the next buffer.
    437 
    438   for (;len >= bytes_to_consume; q=buf) {
    439     // Eat the current block from the buffer, q keeps pointed at current block
    440     buf += bytes_to_consume;
    441     len -= bytes_to_consume;
    442 
    443     switch (state)
    444     {
    445     case gif_lzw:
    446       if (!do_lzw(q))
    447         return false; // If do_lzw() encountered an error, it has already called
    448                       // clientptr->setFailed().
    449       GETN(1, gif_sub_block);
    450       break;
    451 
    452     case gif_lzw_start:
    453     {
    454       /* Initialize LZW parser/decoder */
    455       int datasize = *q;
    456       // Since we use a codesize of 1 more than the datasize, we need to ensure
    457       // that our datasize is strictly less than the MAX_LZW_BITS value (12).
    458       // This sets the largest possible codemask correctly at 4095.
    459       if (datasize >= MAX_LZW_BITS)
    460         return clientptr ? clientptr->setFailed() : false;
    461       int clear_code = 1 << datasize;
    462       if (clear_code >= MAX_BITS)
    463         return clientptr ? clientptr->setFailed() : false;
    464 
    465       if (frame_reader) {
    466         frame_reader->datasize = datasize;
    467         frame_reader->clear_code = clear_code;
    468         frame_reader->avail = frame_reader->clear_code + 2;
    469         frame_reader->oldcode = -1;
    470         frame_reader->codesize = frame_reader->datasize + 1;
    471         frame_reader->codemask = (1 << frame_reader->codesize) - 1;
    472 
    473         frame_reader->datum = frame_reader->bits = 0;
    474 
    475         /* init the tables */
    476         if (!frame_reader->suffix)
    477           frame_reader->suffix = new unsigned char[MAX_BITS];
    478         // Clearing the whole suffix table lets us be more tolerant of bad data.
    479         memset(frame_reader->suffix, 0, MAX_BITS);
    480         for (int i = 0; i < frame_reader->clear_code; i++)
    481           frame_reader->suffix[i] = i;
    482 
    483         if (!frame_reader->stack)
    484           frame_reader->stack = new unsigned char[MAX_BITS];
    485         frame_reader->stackp = frame_reader->stack;
    486       }
    487 
    488       GETN(1, gif_sub_block);
    489     }
    490     break;
    491 
    492     /* All GIF files begin with "GIF87a" or "GIF89a" */
    493     case gif_type:
    494     {
    495       if (!strncmp((char*)q, "GIF89a", 6))
    496         version = 89;
    497       else if (!strncmp((char*)q, "GIF87a", 6))
    498         version = 87;
    499       else
    500         return clientptr ? clientptr->setFailed() : false;
    501       GETN(7, gif_global_header);
    502     }
    503     break;
    504 
    505     case gif_global_header:
    506     {
    507       /* This is the height and width of the "screen" or
    508        * frame into which images are rendered.  The
    509        * individual images can be smaller than the
    510        * screen size and located with an origin anywhere
    511        * within the screen.
    512        */
    513 
    514       screen_width = GETINT16(q);
    515       screen_height = GETINT16(q + 2);
    516 
    517       // CALLBACK: Inform the decoderplugin of our size.
    518       if (clientptr && !clientptr->setSize(screen_width, screen_height))
    519         return false;
    520      
    521       screen_bgcolor = q[5];
    522       global_colormap_size = 2<<(q[4]&0x07);
    523 
    524       if ((q[4] & 0x80) && global_colormap_size > 0) { /* global map */
    525         // Get the global colormap
    526         const unsigned size = 3*global_colormap_size;
    527        
    528         // Malloc the color map, but only if we're not just counting frames.
    529         if (query != GIFImageDecoder::GIFFrameCountQuery)
    530           global_colormap = new unsigned char[size];
    531 
    532         if (len < size) {
    533           // Use 'hold' pattern to get the global colormap
    534           GETN(size, gif_global_colormap);
    535           break;
    536         }
    537        
    538         // Copy everything and go directly to gif_image_start.
    539         if (global_colormap)
    540             memcpy(global_colormap, buf, size);
    541         buf += size;
    542         len -= size;
    543       }
    544 
    545       GETN(1, gif_image_start);
    546 
    547       // q[6] = Pixel Aspect Ratio
    548       //   Not used
    549       //   float aspect = (float)((q[6] + 15) / 64.0);
    550     }
    551     break;
    552 
    553     case gif_global_colormap:
    554       // Everything is already copied into global_colormap
    555       GETN(1, gif_image_start);
    556     break;
    557 
    558     case gif_image_start:
    559     {
    560       if (*q == ';') { /* terminator */
    561         GETN(0, gif_done);
    562         break;
    563       }
    564 
    565       if (*q == '!') { /* extension */
    566         GETN(2, gif_extension);
    567         break;
    568       }
    569 
    570       /* If we get anything other than ',' (image separator), '!'
    571        * (extension), or ';' (trailer), there is extraneous data
    572        * between blocks. The GIF87a spec tells us to keep reading
    573        * until we find an image separator, but GIF89a says such
    574        * a file is corrupt. We follow GIF89a and bail out. */
    575       if (*q != ',')
    576         return clientptr ? clientptr->setFailed() : false;
    577 
    578       GETN(9, gif_image_header);
    579     }
    580     break;
    581 
    582     case gif_extension:
    583     {
    584       count = q[1];
    585       gstate es = gif_skip_block;
    586 
    587       // The GIF spec mandates lengths for three of the extensions below.
    588       // However, it's possible for GIFs in the wild to deviate. For example,
    589       // some GIFs that embed ICC color profiles using gif_application_extension
    590       // violate the spec and treat this extension block like a sort of
    591       // "extension + data" block, giving a size greater than 11 and filling the
    592       // remaining bytes with data (then following with more data blocks as
    593       // needed), instead of placing a true data block just after the 11 byte
    594       // extension block.
    595       //
    596       // Accordingly, if the specified length is larger than the required value,
    597       // we use it. If it's smaller, then we enforce the spec value, because the
    598       // parsers for these extensions expect to have the specified number of
    599       // bytes available, and if we don't ensure that, they could read off the
    600       // end of the heap buffer. (In this case, it's likely the GIF is corrupt
    601       // and we'll soon fail to decode anyway.)
    602       switch (*q)
    603       {
    604       case 0xf9:
    605         es = gif_control_extension;
    606         count = std::max(count, 4);
    607         break;
    608 
    609       case 0x01:
    610         // ignoring plain text extension
    611         count = std::max(count, 12);
    612         break;
    613 
    614       case 0xff:
    615         es = gif_application_extension;
    616         count = std::max(count, 11);
    617         break;
    618 
    619       case 0xfe:
    620         es = gif_consume_comment;
    621         break;
    622       }
    623 
    624       if (count)
    625         GETN(count, es);
    626       else
    627         GETN(1, gif_image_start);
    628     }
    629     break;
    630 
    631     case gif_consume_block:
    632       if (!*q)
    633         GETN(1, gif_image_start);
    634       else
    635         GETN(*q, gif_skip_block);
    636     break;
    637 
    638     case gif_skip_block:
    639       GETN(1, gif_consume_block);
    640       break;
    641 
    642     case gif_control_extension:
    643     {
    644       if (query != GIFImageDecoder::GIFFrameCountQuery) {
    645           if (!frame_reader)
    646             frame_reader = new GIFFrameReader();
    647       }
    648 
    649       if (frame_reader) {
    650         if (*q & 0x1) {
    651           frame_reader->tpixel = q[3];
    652           frame_reader->is_transparent = true;
    653         } else {
    654           frame_reader->is_transparent = false;
    655           // ignoring gfx control extension
    656         }
    657         // NOTE: This relies on the values in the FrameDisposalMethod enum
    658         // matching those in the GIF spec!
    659         int disposal_method = ((*q) >> 2) & 0x7;
    660         frame_reader->disposal_method = (WebCore::ImageFrame::FrameDisposalMethod)disposal_method;
    661         // Some specs say 3rd bit (value 4), other specs say value 3
    662         // Let's choose 3 (the more popular)
    663         if (disposal_method == 4)
    664           frame_reader->disposal_method = WebCore::ImageFrame::DisposeOverwritePrevious;
    665         frame_reader->delay_time = GETINT16(q + 1) * 10;
    666       }
    667       GETN(1, gif_consume_block);
    668     }
    669     break;
    670 
    671     case gif_comment_extension:
    672     {
    673       if (*q)
    674         GETN(*q, gif_consume_comment);
    675       else
    676         GETN(1, gif_image_start);
    677     }
    678     break;
    679 
    680     case gif_consume_comment:
    681       GETN(1, gif_comment_extension);
    682     break;
    683 
    684     case gif_application_extension:
    685       /* Check for netscape application extension */
    686       if (!strncmp((char*)q, "NETSCAPE2.0", 11) ||
    687         !strncmp((char*)q, "ANIMEXTS1.0", 11))
    688         GETN(1, gif_netscape_extension_block);
    689       else
    690         GETN(1, gif_consume_block);
    691     break;
    692 
    693     /* Netscape-specific GIF extension: animation looping */
    694     case gif_netscape_extension_block:
    695       if (*q)
    696         GETN(*q, gif_consume_netscape_extension);
    697       else
    698         GETN(1, gif_image_start);
    699     break;
    700 
    701     /* Parse netscape-specific application extensions */
    702     case gif_consume_netscape_extension:
    703     {
    704       int netscape_extension = q[0] & 7;
    705 
    706       /* Loop entire animation specified # of times.  Only read the
    707          loop count during the first iteration. */
    708       if (netscape_extension == 1) {
    709         loop_count = GETINT16(q + 1);
    710 
    711         /* Zero loop count is infinite animation loop request */
    712         if (loop_count == 0)
    713           loop_count = WebCore::cAnimationLoopInfinite;
    714 
    715         GETN(1, gif_netscape_extension_block);
    716       }
    717       /* Wait for specified # of bytes to enter buffer */
    718       else if (netscape_extension == 2) {
    719         // Don't do this, this extension doesn't exist (isn't used at all)
    720         // and doesn't do anything, as our streaming/buffering takes care of it all...
    721         // See: http://semmix.pl/color/exgraf/eeg24.htm
    722         GETN(1, gif_netscape_extension_block);
    723       } else {
    724         // 0,3-7 are yet to be defined netscape extension codes
    725         return clientptr ? clientptr->setFailed() : false;
    726       }
    727 
    728       break;
    729     }
    730 
    731     case gif_image_header:
    732     {
    733       unsigned height, width, x_offset, y_offset;
    734      
    735       /* Get image offsets, with respect to the screen origin */
    736       x_offset = GETINT16(q);
    737       y_offset = GETINT16(q + 2);
    738 
    739       /* Get image width and height. */
    740       width  = GETINT16(q + 4);
    741       height = GETINT16(q + 6);
    742 
    743       /* Work around broken GIF files where the logical screen
    744        * size has weird width or height.  We assume that GIF87a
    745        * files don't contain animations.
    746        */
    747       if ((images_decoded == 0) &&
    748           ((screen_height < height) || (screen_width < width) ||
    749            (version == 87)))
    750       {
    751         screen_height = height;
    752         screen_width = width;
    753         x_offset = 0;
    754         y_offset = 0;
    755 
    756         // CALLBACK: Inform the decoderplugin of our size.
    757         if (clientptr && !clientptr->setSize(screen_width, screen_height))
    758           return false;
    759       }
    760 
    761       /* Work around more broken GIF files that have zero image
    762          width or height */
    763       if (!height || !width) {
    764         height = screen_height;
    765         width = screen_width;
    766         if (!height || !width)
    767           return clientptr ? clientptr->setFailed() : false;
    768       }
    769 
    770       if (query == GIFImageDecoder::GIFSizeQuery || haltAtFrame == images_decoded) {
    771         // The decoder needs to stop.  Hand back the number of bytes we consumed from
    772         // buffer minus 9 (the amount we consumed to read the header).
    773         if (clientptr)
    774             clientptr->decodingHalted(len + 9);
    775         GETN(9, gif_image_header);
    776         return true;
    777       }
    778      
    779       images_count = images_decoded + 1;
    780 
    781       if (query == GIFImageDecoder::GIFFullQuery && !frame_reader)
    782         frame_reader = new GIFFrameReader();
    783 
    784       if (frame_reader) {
    785         frame_reader->x_offset = x_offset;
    786         frame_reader->y_offset = y_offset;
    787         frame_reader->height = height;
    788         frame_reader->width = width;
    789 
    790         /* This case will never be taken if this is the first image */
    791         /* being decoded. If any of the later images are larger     */
    792         /* than the screen size, we need to reallocate buffers.     */
    793         if (screen_width < width) {
    794           /* XXX Deviant! */
    795 
    796           delete []frame_reader->rowbuf;
    797           screen_width = width;
    798           frame_reader->rowbuf = new unsigned char[screen_width];
    799         } else if (!frame_reader->rowbuf) {
    800           frame_reader->rowbuf = new unsigned char[screen_width];
    801         }
    802 
    803         if (!frame_reader->rowbuf)
    804           return clientptr ? clientptr->setFailed() : false;
    805         if (screen_height < height)
    806           screen_height = height;
    807 
    808         if (q[8] & 0x40) {
    809           frame_reader->interlaced = true;
    810           frame_reader->ipass = 1;
    811         } else {
    812           frame_reader->interlaced = false;
    813           frame_reader->ipass = 0;
    814         }
    815 
    816         if (images_decoded == 0) {
    817           frame_reader->progressive_display = true;
    818         } else {
    819           /* Overlaying interlaced, transparent GIFs over
    820              existing image data using the Haeberli display hack
    821              requires saving the underlying image in order to
    822              avoid jaggies at the transparency edges.  We are
    823              unprepared to deal with that, so don't display such
    824              images progressively */
    825           frame_reader->progressive_display = false;
    826         }
    827 
    828         /* Clear state from last image */
    829         frame_reader->irow = 0;
    830         frame_reader->rows_remaining = frame_reader->height;
    831         frame_reader->rowend = frame_reader->rowbuf + frame_reader->width;
    832         frame_reader->rowp = frame_reader->rowbuf;
    833 
    834         /* bits per pixel is q[8]&0x07 */
    835       }
    836      
    837       if (q[8] & 0x80) /* has a local colormap? */
    838       {
    839         int num_colors = 2 << (q[8] & 0x7);
    840         const unsigned size = 3*num_colors;
    841         unsigned char *map = frame_reader ? frame_reader->local_colormap : 0;
    842         if (frame_reader && (!map || (num_colors > frame_reader->local_colormap_size))) {
    843           delete []map;
    844           map = new unsigned char[size];
    845           if (!map)
    846             return clientptr ? clientptr->setFailed() : false;
    847         }
    848 
    849         /* Switch to the new local palette after it loads */
    850         if (frame_reader) {
    851           frame_reader->local_colormap = map;
    852           frame_reader->local_colormap_size = num_colors;
    853           frame_reader->is_local_colormap_defined = true;
    854         }
    855 
    856         if (len < size) {
    857           // Use 'hold' pattern to get the image colormap
    858           GETN(size, gif_image_colormap);
    859           break;
    860         }
    861         // Copy everything and directly go to gif_lzw_start
    862         if (frame_reader)
    863           memcpy(frame_reader->local_colormap, buf, size);
    864         buf += size;
    865         len -= size;
    866       } else if (frame_reader) {
    867         /* Switch back to the global palette */
    868         frame_reader->is_local_colormap_defined = false;
    869       }
    870       GETN(1, gif_lzw_start);
    871     }
    872     break;
    873 
    874     case gif_image_colormap:
    875       // Everything is already copied into local_colormap
    876       GETN(1, gif_lzw_start);
    877     break;
    878 
    879     case gif_sub_block:
    880     {
    881       if ((count = *q) != 0)
    882       /* Still working on the same image: Process next LZW data block */
    883       {
    884         /* Make sure there are still rows left. If the GIF data */
    885         /* is corrupt, we may not get an explicit terminator.   */
    886         if (frame_reader && frame_reader->rows_remaining == 0) {
    887           /* This is an illegal GIF, but we remain tolerant. */
    888           GETN(1, gif_sub_block);
    889         }
    890         GETN(count, gif_lzw);
    891       }
    892       else
    893       /* See if there are any more images in this sequence. */
    894       {
    895         images_decoded++;
    896 
    897         // CALLBACK: The frame is now complete.
    898         if (clientptr && frame_reader && !clientptr->frameComplete(images_decoded - 1, frame_reader->delay_time, frame_reader->disposal_method))
    899           return false; // frameComplete() has already called
    900                         // clientptr->setFailed().
    901 
    902         /* Clear state from this image */
    903         if (frame_reader) {
    904             frame_reader->is_local_colormap_defined = false;
    905             frame_reader->is_transparent = false;
    906         }
    907 
    908         GETN(1, gif_image_start);
    909       }
    910     }
    911     break;
    912 
    913     case gif_done:
    914       // When the GIF is done, we can stop.
    915       if (clientptr)
    916         clientptr->gifComplete();
    917       return true;
    918 
    919     // We shouldn't ever get here.
    920     default:
    921       break;
    922     }
    923   }
    924 
    925   // Copy the leftover into gs->hold
    926   bytes_in_hold = len;
    927   if (len) {
    928     // Add what we have sofar to the block
    929     unsigned char* p;
    930     if (state == gif_global_colormap)
    931       p = global_colormap;
    932     else if (state == gif_image_colormap)
    933       p = frame_reader ? frame_reader->local_colormap : 0;
    934     else
    935       p = hold;
    936     if (p)
    937       memcpy(p, buf, len);
    938     bytes_to_consume -= len;
    939   }
    940 
    941   if (clientptr)
    942     clientptr->decodingHalted(0);
    943   return false;
    944 }
  • trunk/Source/WebCore/platform/image-decoders/gif/GIFImageReader.h

    r128572 r142528  
    5050const int cLoopCountNotSeen = -2;
    5151
    52 /* gif2.h 
    53    The interface for the GIF87/89a decoder.
    54 */
    55 // List of possible parsing states
    56 typedef enum {
    57     gif_type,
    58     gif_global_header,
    59     gif_global_colormap,
    60     gif_image_start,           
    61     gif_image_header,
    62     gif_image_colormap,
    63     gif_image_body,
    64     gif_lzw_start,
    65     gif_lzw,
    66     gif_sub_block,
    67     gif_extension,
    68     gif_control_extension,
    69     gif_consume_block,
    70     gif_skip_block,
    71     gif_done,
    72     gif_comment_extension,
    73     gif_application_extension,
    74     gif_netscape_extension_block,
    75     gif_consume_netscape_extension,
    76     gif_consume_comment
    77 } gstate;
    78 
    79 struct GIFFrameReader {
     52// List of possible parsing states.
     53enum GIFState {
     54    GIFType,
     55    GIFGlobalHeader,
     56    GIFGlobalColormap,
     57    GIFImageStart,           
     58    GIFImageHeader,
     59    GIFImageColormap,
     60    GIFImageBody,
     61    GIFLZWStart,
     62    GIFLZW,
     63    GIFSubBlock,
     64    GIFExtension,
     65    GIFControlExtension,
     66    GIFConsumeBlock,
     67    GIFSkipBlock,
     68    GIFDone,
     69    GIFCommentExtension,
     70    GIFApplicationExtension,
     71    GIFNetscapeExtensionBlock,
     72    GIFConsumeNetscapeExtension,
     73    GIFConsumeComment
     74};
     75
     76struct GIFFrameContext {
    8077    WTF_MAKE_FAST_ALLOCATED;
    8178public:
    82     /* LZW decoder state machine */
    83     unsigned char *stackp;              /* Current stack pointer */
     79    // LZW decoder state machine.
     80    unsigned char *stackp; // Current stack pointer.
    8481    int datasize;
    8582    int codesize;
    8683    int codemask;
    87     int clear_code;             /* Codeword used to trigger dictionary reset */
    88     int avail;                  /* Index of next available slot in dictionary */
     84    int clearCode; // Codeword used to trigger dictionary reset.
     85    int avail; // Index of next available slot in dictionary.
    8986    int oldcode;
    9087    unsigned char firstchar;
    91     int bits;                   /* Number of unread bits in "datum" */
    92     int datum;                /* 32-bit input buffer */
    93 
    94     /* Output state machine */
    95     int ipass;                  /* Interlace pass; Ranges 1-4 if interlaced. */
    96     unsigned int rows_remaining;        /* Rows remaining to be output */
    97     unsigned int irow;                  /* Current output row, starting at zero */
    98     unsigned char *rowbuf;              /* Single scanline temporary buffer */
    99     unsigned char *rowend;              /* Pointer to end of rowbuf */
    100     unsigned char *rowp;                /* Current output pointer */
    101 
    102     /* Parameters for image frame currently being decoded */
    103     unsigned int x_offset, y_offset;    /* With respect to "screen" origin */
    104     unsigned int height, width;
    105     int tpixel;                 /* Index of transparent pixel */
    106     WebCore::ImageFrame::FrameDisposalMethod disposal_method;   /* Restore to background, leave in place, etc.*/
    107     unsigned char *local_colormap;    /* Per-image colormap */
    108     int local_colormap_size;    /* Size of local colormap array. */
    109    
    110     bool is_local_colormap_defined : 1;
    111     bool progressive_display : 1;    /* If TRUE, do Haeberli interlace hack */
    112     bool interlaced : 1;             /* TRUE, if scanlines arrive interlaced order */
    113     bool is_transparent : 1;         /* TRUE, if tpixel is valid */
    114 
    115     unsigned delay_time;        /* Display time, in milliseconds,
    116                                    for this image in a multi-image GIF */
    117 
    118 
    119     unsigned short*  prefix;          /* LZW decoding tables */
    120     unsigned char*   suffix;          /* LZW decoding tables */
    121     unsigned char*   stack;           /* Base of LZW decoder stack */
    122 
    123 
    124     GIFFrameReader() {
    125         stackp = 0;
    126         datasize = codesize = codemask = clear_code = avail = oldcode = 0;
    127         firstchar = 0;
    128         bits = datum = 0;
    129         ipass = 0;
    130         rows_remaining = irow = 0;
    131         rowbuf = rowend = rowp = 0;
    132 
    133         x_offset = y_offset = width = height = 0;
    134         tpixel = 0;
    135         disposal_method = WebCore::ImageFrame::DisposeNotSpecified;
    136 
    137         local_colormap = 0;
    138         local_colormap_size = 0;
    139         is_local_colormap_defined = progressive_display = is_transparent = interlaced = false;
    140 
    141         delay_time = 0;
    142 
    143         prefix = 0;
    144         suffix = stack = 0;
    145     }
    146    
    147     ~GIFFrameReader() {
    148         delete []rowbuf;
    149         delete []local_colormap;
    150         delete []prefix;
    151         delete []suffix;
    152         delete []stack;
     88    int bits; // Number of unread bits in "datum".
     89    int datum; // 32-bit input buffer.
     90
     91    // Output state machine.
     92    int ipass; // Interlace pass; Ranges 1-4 if interlaced.
     93    unsigned rowsRemaining; // Rows remaining to be output.
     94    unsigned irow; // Current output row, starting at zero.
     95    unsigned char *rowbuf; // Single scanline temporary buffer.
     96    unsigned char *rowend; // Pointer to end of rowbuf.
     97    unsigned char *rowp; // Current output pointer.
     98
     99    // Parameters for image frame currently being decoded.
     100    unsigned xOffset;
     101    unsigned yOffset; // With respect to "screen" origin.
     102    unsigned width;
     103    unsigned height;
     104    int tpixel; // Index of transparent pixel.
     105    WebCore::ImageFrame::FrameDisposalMethod disposalMethod; // Restore to background, leave in place, etc.
     106    unsigned char *localColormap; // Per-image colormap.
     107    int localColormapSize; // Size of local colormap array.
     108   
     109    bool isLocalColormapDefined : 1;
     110    bool progressiveDisplay : 1; // If true, do Haeberli interlace hack.
     111    bool interlaced : 1; // True, if scanlines arrive interlaced order.
     112    bool isTransparent : 1; // TRUE, if tpixel is valid.
     113
     114    unsigned delayTime; // Display time, in milliseconds, for this image in a multi-image GIF.
     115
     116    unsigned short* prefix; // LZW decoding tables.
     117    unsigned char* suffix; // LZW decoding tables.
     118    unsigned char* stack; // Base of LZW decoder stack.
     119
     120    GIFFrameContext()
     121        : stackp(0)
     122        , datasize(0)
     123        , codesize(0)
     124        , codemask(0)
     125        , clearCode(0)
     126        , avail(0)
     127        , oldcode(0)
     128        , firstchar(0)
     129        , bits(0)
     130        , datum(0)
     131        , ipass(0)
     132        , rowsRemaining(0)
     133        , irow(0)
     134        , rowbuf(0)
     135        , rowend(0)
     136        , rowp(0)
     137        , xOffset(0)
     138        , yOffset(0)
     139        , width(0)
     140        , height(0)
     141        , tpixel(0)
     142        , disposalMethod(WebCore::ImageFrame::DisposeNotSpecified)
     143        , localColormap(0)
     144        , localColormapSize(0)
     145        , isLocalColormapDefined(false)
     146        , progressiveDisplay(false)
     147        , interlaced(false)
     148        , isTransparent(false)
     149        , delayTime(0)
     150        , prefix(0)
     151        , suffix(0)
     152        , stack(0)
     153    {
     154    }
     155   
     156    ~GIFFrameContext()
     157    {
     158        delete [] rowbuf;
     159        delete [] localColormap;
     160        delete [] prefix;
     161        delete [] suffix;
     162        delete [] stack;
    153163    }
    154164};
    155165
    156 struct GIFImageReader {
     166class GIFImageReader {
    157167    WTF_MAKE_FAST_ALLOCATED;
    158168public:
    159     WebCore::GIFImageDecoder* clientptr;
    160     /* Parsing state machine */
    161     gstate state;                      /* Current decoder master state */
    162     unsigned bytes_to_consume;         /* Number of bytes to accumulate */
    163     unsigned bytes_in_hold;            /* bytes accumulated so far*/
    164     unsigned char hold[MAX_HOLD_SIZE]; /* Accumulation buffer */
    165     unsigned char* global_colormap;    /* (3* MAX_COLORS in size) Default colormap if local not supplied, 3 bytes for each color  */
    166    
    167      /* Global (multi-image) state */
    168     int screen_bgcolor;         /* Logical screen background color */
    169     int version;                /* Either 89 for GIF89 or 87 for GIF87 */
    170     unsigned screen_width;       /* Logical screen width & height */
    171     unsigned screen_height;
    172     int global_colormap_size;   /* Size of global colormap array. */
    173     unsigned images_decoded;    /* Counts completed frames for animated GIFs */
    174     int images_count;           /* Counted all frames seen so far (including incomplete frames) */
    175     int loop_count;             /* Netscape specific extension block to control
    176                                    the number of animation loops a GIF renders. */
     169    GIFImageReader(WebCore::GIFImageDecoder* client = 0)
     170        : m_client(client)
     171        , m_state(GIFType)
     172        , m_bytesToConsume(6)
     173        , m_bytesInHold(0)
     174        , m_globalColormap(0)
     175        , m_screenBgcolor(0)
     176        , m_version(0)
     177        , m_screenWidth(0)
     178        , m_screenHeight(0)
     179        , m_globalColormapSize(0)
     180        , m_imagesDecoded(0)
     181        , m_imagesCount(0)
     182        , m_loopCount(cLoopCountNotSeen)
     183        , m_count(0)
     184        , m_frameContext(0)
     185    {
     186    }
     187
     188    ~GIFImageReader()
     189    {
     190        delete [] m_globalColormap;
     191        m_globalColormap = 0;
     192
     193        delete m_frameContext;
     194        m_frameContext = 0;
     195    }
     196
     197    bool read(const unsigned char* buf, unsigned numbytes, WebCore::GIFImageDecoder::GIFQuery = WebCore::GIFImageDecoder::GIFFullQuery, unsigned haltAtFrame = -1);
     198
     199    int imagesCount() const { return m_imagesCount; }
     200    int loopCount() const { return m_loopCount; }
     201    unsigned char* globalColormap() const { return m_globalColormap; }
     202    int globalColormapSize() const { return m_globalColormapSize; }
     203    const GIFFrameContext* frameContext() const { return m_frameContext; }
     204
     205private:
     206    bool outputRow();
     207    bool doLZW(const unsigned char *q);
     208
     209    WebCore::GIFImageDecoder* m_client;
     210
     211    // Parsing state machine.
     212    GIFState m_state; // Current decoder master state.
     213    unsigned m_bytesToConsume; // Number of bytes to accumulate.
     214    unsigned m_bytesInHold; // bytes accumulated so far.
     215    unsigned char m_hold[MAX_HOLD_SIZE]; // Accumulation buffer.
     216    unsigned char* m_globalColormap; // (3* MAX_COLORS in size) Default colormap if local not supplied, 3 bytes for each color.
     217   
     218    // Global (multi-image) state.
     219    int m_screenBgcolor; // Logical screen background color.
     220    int m_version; // Either 89 for GIF89 or 87 for GIF87.
     221    unsigned m_screenWidth; // Logical screen width & height.
     222    unsigned m_screenHeight;
     223    int m_globalColormapSize; // Size of global colormap array.
     224    unsigned m_imagesDecoded; // Counts completed frames for animated GIFs.
     225    int m_imagesCount; // Counted all frames seen so far (including incomplete frames).
     226    int m_loopCount; // Netscape specific extension block to control the number of animation loops a GIF renders.
    177227   
    178228    // Not really global, but convenient to locate here.
    179     int count;                  /* Remaining # bytes in sub-block */
    180    
    181     GIFFrameReader* frame_reader;
    182 
    183     GIFImageReader(WebCore::GIFImageDecoder* client = 0) {
    184         clientptr = client;
    185         state = gif_type;
    186         bytes_to_consume = 6;
    187         bytes_in_hold = 0;
    188         frame_reader = 0;
    189         global_colormap = 0;
    190 
    191         screen_bgcolor = version = 0;
    192         screen_width = screen_height = 0;
    193         global_colormap_size = images_decoded = images_count = 0;
    194         loop_count = cLoopCountNotSeen;
    195         count = 0;
    196     }
    197 
    198     ~GIFImageReader() {
    199         delete []global_colormap;
    200         global_colormap = 0;
    201         delete frame_reader;
    202         frame_reader = 0;
    203     }
    204 
    205     bool read(const unsigned char * buf, unsigned int numbytes,
    206               WebCore::GIFImageDecoder::GIFQuery query = WebCore::GIFImageDecoder::GIFFullQuery, unsigned haltAtFrame = -1);
    207 
    208 private:
    209     bool output_row();
    210     bool do_lzw(const unsigned char *q);
     229    int m_count; // Remaining # bytes in sub-block.
     230   
     231    GIFFrameContext* m_frameContext;
    211232};
    212233
Note: See TracChangeset for help on using the changeset viewer.