Changeset 142528 in webkit
- Timestamp:
- Feb 11, 2013 3:21:32 PM (11 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r142527 r142528 1 2013-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 1 39 2013-02-11 Bem Jones-Bey <bjonesbe@adobe.com> 2 40 -
trunk/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp
r135976 r142528 88 88 reader.read((const unsigned char*)m_data->data(), m_data->size(), GIFFrameCountQuery, static_cast<unsigned>(-1)); 89 89 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) 92 92 m_frameBufferCache[i].setPremultiplyAlpha(m_premultiplyAlpha); 93 93 } … … 117 117 // special code here either, because in this case we'll never change 118 118 // |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(); 121 121 return m_repetitionCount; 122 122 } … … 199 199 bool GIFImageDecoder::haveDecodedRow(unsigned frameIndex, unsigned char* rowBuffer, unsigned char* rowEnd, unsigned rowNumber, unsigned repeatCount, bool writeTransparentPixels) 200 200 { 201 const GIFFrame Reader* frameReader = m_reader->frame_reader;201 const GIFFrameContext* frameContext = m_reader->frameContext(); 202 202 // The pixel data and coordinates supplied to us are relative to the frame's 203 203 // origin within the entire image size, i.e. 204 // (frame Reader->x_offset, frameReader->y_offset).There is no guarantee205 // that (rowEnd - rowBuffer) == (size().width() - frame Reader->x_offset), so204 // (frameContext->xOffset, frameContext->yOffset). There is no guarantee 205 // that (rowEnd - rowBuffer) == (size().width() - frameContext->xOffset), so 206 206 // we must ensure we don't run off the end of either the source data or the 207 207 // row's X-coordinates. 208 int xBegin = upperBoundScaledX(frame Reader->x_offset);209 int yBegin = upperBoundScaledY(frame Reader->y_offset + rowNumber);210 int xEnd = lowerBoundScaledX(std::min(static_cast<int>(frame Reader->x_offset + (rowEnd - rowBuffer)), size().width()) - 1, xBegin + 1) + 1;211 int yEnd = lowerBoundScaledY(std::min(static_cast<int>(frame Reader->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; 212 212 if (!rowBuffer || (xBegin < 0) || (yBegin < 0) || (xEnd <= xBegin) || (yEnd <= yBegin)) 213 213 return true; … … 216 216 const unsigned char* colorMap; 217 217 unsigned colorMapSize; 218 if (frame Reader->is_local_colormap_defined) {219 colorMap = frame Reader->local_colormap;220 colorMapSize = (unsigned)frame Reader->local_colormap_size;218 if (frameContext->isLocalColormapDefined) { 219 colorMap = frameContext->localColormap; 220 colorMapSize = (unsigned)frameContext->localColormapSize; 221 221 } else { 222 colorMap = m_reader->global _colormap;223 colorMapSize = m_reader->global _colormap_size;222 colorMap = m_reader->globalColormap(); 223 colorMapSize = m_reader->globalColormapSize(); 224 224 } 225 225 if (!colorMap) … … 234 234 // Write one row's worth of data into the frame. 235 235 for (int x = xBegin; x < xEnd; ++x) { 236 const unsigned char sourceValue = *(rowBuffer + (m_scaled ? m_scaledColumns[x] : x) - frame Reader->x_offset);237 if ((!frame Reader->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)) { 238 238 const size_t colorIndex = static_cast<size_t>(sourceValue) * 3; 239 239 buffer.setRGBA(currentAddress, colorMap[colorIndex], colorMap[colorIndex + 1], colorMap[colorIndex + 2], 255); … … 332 332 { 333 333 // Initialize the frame rect in our buffer. 334 const GIFFrame Reader* frameReader = m_reader->frame_reader;335 IntRect frameRect(frame Reader->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); 336 336 337 337 // Make sure the frameRect doesn't extend outside the buffer. 338 338 if (frameRect.maxX() > size().width()) 339 frameRect.setWidth(size().width() - frame Reader->x_offset);339 frameRect.setWidth(size().width() - frameContext->xOffset); 340 340 if (frameRect.maxY() > size().height()) 341 frameRect.setHeight(size().height() - frame Reader->y_offset);341 frameRect.setHeight(size().height() - frameContext->yOffset); 342 342 343 343 ImageFrame* const buffer = &m_frameBufferCache[frameIndex]; -
trunk/Source/WebCore/platform/image-decoders/gif/GIFImageReader.cpp
r129523 r142528 82 82 using WebCore::GIFImageDecoder; 83 83 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. 104 98 #define GETINT16(p) ((p)[1]<<8|(p)[0]) 105 99 106 //******************************************************************************107 100 // Send the data to the display front-end. 108 bool GIFImageReader::output _row()101 bool GIFImageReader::outputRow() 109 102 { 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; 140 144 } 141 145 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 } 158 200 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. 204 bool 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 341 END: 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. 359 bool 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); 165 898 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;214 899 } 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 compiler229 * won't worry about them being aliased. The locals will be homed230 * 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_MACRO267 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 malformed324 // 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 length342 * increase the length of codewords by one bit, but don't343 * 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 decoder384 */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 block397 // If previous call to me left something in the hold first complete current block398 // Or if we are filling the colormaps, first complete the colormap399 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 else407 p = 0;408 409 if (p || (state == gif_global_colormap) || (state == gif_image_colormap)) {410 // Add what we have sofar to the block411 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 more417 bytes_in_hold += l;418 bytes_to_consume -= l;419 if (clientptr)420 clientptr->decodingHalted(0);421 return false;422 }423 // Reset hold buffer count424 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 buffer433 // '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 block440 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 called448 // 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 ensure457 // 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 else500 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" or508 * frame into which images are rendered. The509 * individual images can be smaller than the510 * screen size and located with an origin anywhere511 * 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 colormap526 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 colormap534 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 Ratio548 // Not used549 // float aspect = (float)((q[6] + 15) / 64.0);550 }551 break;552 553 case gif_global_colormap:554 // Everything is already copied into global_colormap555 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 data572 * between blocks. The GIF87a spec tells us to keep reading573 * until we find an image separator, but GIF89a says such574 * 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_extension590 // violate the spec and treat this extension block like a sort of591 // "extension + data" block, giving a size greater than 11 and filling the592 // remaining bytes with data (then following with more data blocks as593 // needed), instead of placing a true data block just after the 11 byte594 // 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 the598 // parsers for these extensions expect to have the specified number of599 // bytes available, and if we don't ensure that, they could read off the600 // end of the heap buffer. (In this case, it's likely the GIF is corrupt601 // 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 extension611 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 else627 GETN(1, gif_image_start);628 }629 break;630 631 case gif_consume_block:632 if (!*q)633 GETN(1, gif_image_start);634 else635 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 extension656 }657 // NOTE: This relies on the values in the FrameDisposalMethod enum658 // 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 3662 // 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 else676 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 else690 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 else698 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 the707 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.htm722 GETN(1, gif_netscape_extension_block);723 } else {724 // 0,3-7 are yet to be defined netscape extension codes725 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 screen744 * size has weird width or height. We assume that GIF87a745 * 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 image762 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 from772 // 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 over820 existing image data using the Haeberli display hack821 requires saving the underlying image in order to822 avoid jaggies at the transparency edges. We are823 unprepared to deal with that, so don't display such824 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 colormap858 GETN(size, gif_image_colormap);859 break;860 }861 // Copy everything and directly go to gif_lzw_start862 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_colormap876 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 else893 /* 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 called900 // 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->hold926 bytes_in_hold = len;927 if (len) {928 // Add what we have sofar to the block929 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 else935 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 50 50 const int cLoopCountNotSeen = -2; 51 51 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. 53 enum 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 76 struct GIFFrameContext { 80 77 WTF_MAKE_FAST_ALLOCATED; 81 78 public: 82 / * LZW decoder state machine */83 unsigned char *stackp; /* Current stack pointer */79 // LZW decoder state machine. 80 unsigned char *stackp; // Current stack pointer. 84 81 int datasize; 85 82 int codesize; 86 83 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. 89 86 int oldcode; 90 87 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; 153 163 } 154 164 }; 155 165 156 structGIFImageReader {166 class GIFImageReader { 157 167 WTF_MAKE_FAST_ALLOCATED; 158 168 public: 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 205 private: 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. 177 227 178 228 // 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; 211 232 }; 212 233
Note: See TracChangeset
for help on using the changeset viewer.