| OLD | NEW |
| 1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ | 1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
| 2 /* ***** BEGIN LICENSE BLOCK ***** | 2 /* ***** BEGIN LICENSE BLOCK ***** |
| 3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | 3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
| 4 * | 4 * |
| 5 * The contents of this file are subject to the Mozilla Public License Version | 5 * The contents of this file are subject to the Mozilla Public License Version |
| 6 * 1.1 (the "License"); you may not use this file except in compliance with | 6 * 1.1 (the "License"); you may not use this file except in compliance with |
| 7 * the License. You may obtain a copy of the License at | 7 * the License. You may obtain a copy of the License at |
| 8 * http://www.mozilla.org/MPL/ | 8 * http://www.mozilla.org/MPL/ |
| 9 * | 9 * |
| 10 * Software distributed under the License is distributed on an "AS IS" basis, | 10 * Software distributed under the License is distributed on an "AS IS" basis, |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 PR_BEGIN_MACRO \ | 97 PR_BEGIN_MACRO \ |
| 98 bytes_to_consume = (n); \ | 98 bytes_to_consume = (n); \ |
| 99 state = (s); \ | 99 state = (s); \ |
| 100 PR_END_MACRO | 100 PR_END_MACRO |
| 101 | 101 |
| 102 /* Get a 16-bit value stored in little-endian format */ | 102 /* Get a 16-bit value stored in little-endian format */ |
| 103 #define GETINT16(p) ((p)[1]<<8|(p)[0]) | 103 #define GETINT16(p) ((p)[1]<<8|(p)[0]) |
| 104 | 104 |
| 105 //****************************************************************************** | 105 //****************************************************************************** |
| 106 // Send the data to the display front-end. | 106 // Send the data to the display front-end. |
| 107 void GIFImageReader::output_row() | 107 bool GIFImageReader::output_row() |
| 108 { | 108 { |
| 109 GIFFrameReader* gs = frame_reader; | 109 GIFFrameReader* gs = frame_reader; |
| 110 | 110 |
| 111 int drow_start, drow_end; | 111 int drow_start, drow_end; |
| 112 | 112 |
| 113 drow_start = drow_end = gs->irow; | 113 drow_start = drow_end = gs->irow; |
| 114 | 114 |
| 115 /* | 115 /* |
| 116 * Haeberli-inspired hack for interlaced GIFs: Replicate lines while | 116 * Haeberli-inspired hack for interlaced GIFs: Replicate lines while |
| 117 * displaying to diminish the "venetian-blind" effect as the image is | 117 * displaying to diminish the "venetian-blind" effect as the image is |
| (...skipping 29 matching lines...) Expand all Loading... |
| 147 | 147 |
| 148 /* Clamp first and last rows to upper and lower edge of image. */ | 148 /* Clamp first and last rows to upper and lower edge of image. */ |
| 149 if (drow_start < 0) | 149 if (drow_start < 0) |
| 150 drow_start = 0; | 150 drow_start = 0; |
| 151 if ((unsigned)drow_end >= gs->height) | 151 if ((unsigned)drow_end >= gs->height) |
| 152 drow_end = gs->height - 1; | 152 drow_end = gs->height - 1; |
| 153 } | 153 } |
| 154 | 154 |
| 155 /* Protect against too much image data */ | 155 /* Protect against too much image data */ |
| 156 if ((unsigned)drow_start >= gs->height) | 156 if ((unsigned)drow_start >= gs->height) |
| 157 return; | 157 return true; |
| 158 | 158 |
| 159 // CALLBACK: Let the client know we have decoded a row. | 159 // CALLBACK: Let the client know we have decoded a row. |
| 160 if (clientptr && frame_reader) | 160 if (clientptr && frame_reader && |
| 161 clientptr->haveDecodedRow(images_count - 1, frame_reader->rowbuf, frame_read
er->rowend, | 161 !clientptr->haveDecodedRow(images_count - 1, frame_reader->rowbuf, frame_r
eader->rowend, |
| 162 drow_start, drow_end - drow_start + 1, | 162 drow_start, drow_end - drow_start + 1, |
| 163 gs->progressive_display && gs->interlaced && gs->i
pass > 1); | 163 gs->progressive_display && gs->interlaced && gs
->ipass > 1)) |
| 164 return false; |
| 164 | 165 |
| 165 gs->rowp = gs->rowbuf; | 166 gs->rowp = gs->rowbuf; |
| 166 | 167 |
| 167 if (!gs->interlaced) | 168 if (!gs->interlaced) |
| 168 gs->irow++; | 169 gs->irow++; |
| 169 else { | 170 else { |
| 170 do { | 171 do { |
| 171 switch (gs->ipass) | 172 switch (gs->ipass) |
| 172 { | 173 { |
| 173 case 1: | 174 case 1: |
| (...skipping 26 matching lines...) Expand all Loading... |
| 200 gs->ipass++; | 201 gs->ipass++; |
| 201 gs->irow = 0; | 202 gs->irow = 0; |
| 202 } | 203 } |
| 203 break; | 204 break; |
| 204 | 205 |
| 205 default: | 206 default: |
| 206 break; | 207 break; |
| 207 } | 208 } |
| 208 } while (gs->irow > (gs->height - 1)); | 209 } while (gs->irow > (gs->height - 1)); |
| 209 } | 210 } |
| 211 |
| 212 return true; |
| 210 } | 213 } |
| 211 | 214 |
| 212 //****************************************************************************** | 215 //****************************************************************************** |
| 213 /* Perform Lempel-Ziv-Welch decoding */ | 216 /* Perform Lempel-Ziv-Welch decoding */ |
| 214 int GIFImageReader::do_lzw(const unsigned char *q) | 217 bool GIFImageReader::do_lzw(const unsigned char *q) |
| 215 { | 218 { |
| 216 GIFFrameReader* gs = frame_reader; | 219 GIFFrameReader* gs = frame_reader; |
| 217 if (!gs) | 220 if (!gs) |
| 218 return 0; | 221 return true; |
| 219 | 222 |
| 220 int code; | 223 int code; |
| 221 int incode; | 224 int incode; |
| 222 const unsigned char *ch; | 225 const unsigned char *ch; |
| 223 | 226 |
| 224 /* Copy all the decoder state variables into locals so the compiler | 227 /* Copy all the decoder state variables into locals so the compiler |
| 225 * won't worry about them being aliased. The locals will be homed | 228 * won't worry about them being aliased. The locals will be homed |
| 226 * back into the GIF decoder structure when we exit. | 229 * back into the GIF decoder structure when we exit. |
| 227 */ | 230 */ |
| 228 int avail = gs->avail; | 231 int avail = gs->avail; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 242 | 245 |
| 243 unsigned short *prefix = gs->prefix; | 246 unsigned short *prefix = gs->prefix; |
| 244 unsigned char *stackp = gs->stackp; | 247 unsigned char *stackp = gs->stackp; |
| 245 unsigned char *suffix = gs->suffix; | 248 unsigned char *suffix = gs->suffix; |
| 246 unsigned char *stack = gs->stack; | 249 unsigned char *stack = gs->stack; |
| 247 unsigned char *rowp = gs->rowp; | 250 unsigned char *rowp = gs->rowp; |
| 248 unsigned char *rowend = gs->rowend; | 251 unsigned char *rowend = gs->rowend; |
| 249 unsigned rows_remaining = gs->rows_remaining; | 252 unsigned rows_remaining = gs->rows_remaining; |
| 250 | 253 |
| 251 if (rowp == rowend) | 254 if (rowp == rowend) |
| 252 return 0; | 255 return true; |
| 253 | 256 |
| 254 #define OUTPUT_ROW \ | 257 #define OUTPUT_ROW \ |
| 255 PR_BEGIN_MACRO \ | 258 PR_BEGIN_MACRO \ |
| 256 output_row(); \ | 259 if (!output_row()) \ |
| 260 return false; \ |
| 257 rows_remaining--; \ | 261 rows_remaining--; \ |
| 258 rowp = frame_reader->rowp;
\ | 262 rowp = frame_reader->rowp;
\ |
| 259 if (!rows_remaining) \ | 263 if (!rows_remaining) \ |
| 260 goto END; \ | 264 goto END; \ |
| 261 PR_END_MACRO | 265 PR_END_MACRO |
| 262 | 266 |
| 263 for (ch = q; cnt-- > 0; ch++) | 267 for (ch = q; cnt-- > 0; ch++) |
| 264 { | 268 { |
| 265 /* Feed the next byte into the decoder's 32-bit input buffer. */ | 269 /* Feed the next byte into the decoder's 32-bit input buffer. */ |
| 266 datum += ((int) *ch) << bits; | 270 datum += ((int) *ch) << bits; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 279 codesize = gs->datasize + 1; | 283 codesize = gs->datasize + 1; |
| 280 codemask = (1 << codesize) - 1; | 284 codemask = (1 << codesize) - 1; |
| 281 avail = clear_code + 2; | 285 avail = clear_code + 2; |
| 282 oldcode = -1; | 286 oldcode = -1; |
| 283 continue; | 287 continue; |
| 284 } | 288 } |
| 285 | 289 |
| 286 /* Check for explicit end-of-stream code */ | 290 /* Check for explicit end-of-stream code */ |
| 287 if (code == (clear_code + 1)) { | 291 if (code == (clear_code + 1)) { |
| 288 /* end-of-stream should only appear after all image data */ | 292 /* end-of-stream should only appear after all image data */ |
| 289 if (rows_remaining != 0) | 293 return rows_remaining == 0; |
| 290 return -1; | |
| 291 return 0; | |
| 292 } | 294 } |
| 293 | 295 |
| 294 if (oldcode == -1) { | 296 if (oldcode == -1) { |
| 295 *rowp++ = suffix[code]; | 297 *rowp++ = suffix[code]; |
| 296 if (rowp == rowend) | 298 if (rowp == rowend) |
| 297 OUTPUT_ROW; | 299 OUTPUT_ROW; |
| 298 | 300 |
| 299 firstchar = oldcode = code; | 301 firstchar = oldcode = code; |
| 300 continue; | 302 continue; |
| 301 } | 303 } |
| 302 | 304 |
| 303 incode = code; | 305 incode = code; |
| 304 if (code >= avail) { | 306 if (code >= avail) { |
| 305 *stackp++ = firstchar; | 307 *stackp++ = firstchar; |
| 306 code = oldcode; | 308 code = oldcode; |
| 307 | 309 |
| 308 if (stackp == stack + MAX_BITS) | 310 if (stackp == stack + MAX_BITS) |
| 309 return -1; | 311 return false; |
| 310 } | 312 } |
| 311 | 313 |
| 312 while (code >= clear_code) | 314 while (code >= clear_code) |
| 313 { | 315 { |
| 314 if (code >= MAX_BITS || code == prefix[code]) | 316 if (code >= MAX_BITS || code == prefix[code]) |
| 315 return -1; | 317 return false; |
| 316 | 318 |
| 317 // Even though suffix[] only holds characters through suffix[avail - 1], | 319 // Even though suffix[] only holds characters through suffix[avail - 1], |
| 318 // allowing code >= avail here lets us be more tolerant of malformed | 320 // allowing code >= avail here lets us be more tolerant of malformed |
| 319 // data. As long as code < MAX_BITS, the only risk is a garbled image, | 321 // data. As long as code < MAX_BITS, the only risk is a garbled image, |
| 320 // which is no worse than refusing to display it. | 322 // which is no worse than refusing to display it. |
| 321 *stackp++ = suffix[code]; | 323 *stackp++ = suffix[code]; |
| 322 code = prefix[code]; | 324 code = prefix[code]; |
| 323 | 325 |
| 324 if (stackp == stack + MAX_BITS) | 326 if (stackp == stack + MAX_BITS) |
| 325 return -1; | 327 return false; |
| 326 } | 328 } |
| 327 | 329 |
| 328 *stackp++ = firstchar = suffix[code]; | 330 *stackp++ = firstchar = suffix[code]; |
| 329 | 331 |
| 330 /* Define a new codeword in the dictionary. */ | 332 /* Define a new codeword in the dictionary. */ |
| 331 if (avail < 4096) { | 333 if (avail < 4096) { |
| 332 prefix[avail] = oldcode; | 334 prefix[avail] = oldcode; |
| 333 suffix[avail] = firstchar; | 335 suffix[avail] = firstchar; |
| 334 avail++; | 336 avail++; |
| 335 | 337 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 362 gs->codesize = codesize; | 364 gs->codesize = codesize; |
| 363 gs->codemask = codemask; | 365 gs->codemask = codemask; |
| 364 count = cnt; | 366 count = cnt; |
| 365 gs->oldcode = oldcode; | 367 gs->oldcode = oldcode; |
| 366 gs->firstchar = firstchar; | 368 gs->firstchar = firstchar; |
| 367 gs->datum = datum; | 369 gs->datum = datum; |
| 368 gs->stackp = stackp; | 370 gs->stackp = stackp; |
| 369 gs->rowp = rowp; | 371 gs->rowp = rowp; |
| 370 gs->rows_remaining = rows_remaining; | 372 gs->rows_remaining = rows_remaining; |
| 371 | 373 |
| 372 return 0; | 374 return true; |
| 373 } | 375 } |
| 374 | 376 |
| 375 | 377 |
| 376 /******************************************************************************/ | 378 /******************************************************************************/ |
| 377 /* | 379 /* |
| 378 * process data arriving from the stream for the gif decoder | 380 * process data arriving from the stream for the gif decoder |
| 379 */ | 381 */ |
| 380 | 382 |
| 381 bool GIFImageReader::read(const unsigned char *buf, unsigned len, | 383 bool GIFImageReader::read(const unsigned char *buf, unsigned len, |
| 382 GIFImageDecoder::GIFQuery query, unsigned haltAtFrame) | 384 GIFImageDecoder::GIFQuery query, unsigned haltAtFrame) |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 // So that next round in for loop, q gets pointed to the next buffer. | 433 // So that next round in for loop, q gets pointed to the next buffer. |
| 432 | 434 |
| 433 for (;len >= bytes_to_consume; q=buf) { | 435 for (;len >= bytes_to_consume; q=buf) { |
| 434 // Eat the current block from the buffer, q keeps pointed at current block | 436 // Eat the current block from the buffer, q keeps pointed at current block |
| 435 buf += bytes_to_consume; | 437 buf += bytes_to_consume; |
| 436 len -= bytes_to_consume; | 438 len -= bytes_to_consume; |
| 437 | 439 |
| 438 switch (state) | 440 switch (state) |
| 439 { | 441 { |
| 440 case gif_lzw: | 442 case gif_lzw: |
| 441 if (do_lzw(q) < 0) { | 443 if (!do_lzw(q)) { |
| 442 state = gif_error; | 444 state = gif_error; |
| 443 break; | 445 break; |
| 444 } | 446 } |
| 445 GETN(1, gif_sub_block); | 447 GETN(1, gif_sub_block); |
| 446 break; | 448 break; |
| 447 | 449 |
| 448 case gif_lzw_start: | 450 case gif_lzw_start: |
| 449 { | 451 { |
| 450 /* Initialize LZW parser/decoder */ | 452 /* Initialize LZW parser/decoder */ |
| 451 int datasize = *q; | 453 int datasize = *q; |
| (...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 939 p = hold; | 941 p = hold; |
| 940 if (p) | 942 if (p) |
| 941 memcpy(p, buf, len); | 943 memcpy(p, buf, len); |
| 942 bytes_to_consume -= len; | 944 bytes_to_consume -= len; |
| 943 } | 945 } |
| 944 | 946 |
| 945 if (clientptr) | 947 if (clientptr) |
| 946 clientptr->decodingHalted(0); | 948 clientptr->decodingHalted(0); |
| 947 return true; | 949 return true; |
| 948 } | 950 } |
| OLD | NEW |