| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * Copyright 2015 Google Inc. | 2  * Copyright 2015 Google Inc. | 
| 3  * | 3  * | 
| 4  * Use of this source code is governed by a BSD-style license that can be | 4  * Use of this source code is governed by a BSD-style license that can be | 
| 5  * found in the LICENSE file. | 5  * found in the LICENSE file. | 
| 6  */ | 6  */ | 
| 7 | 7 | 
| 8 #include "SkCodecPriv.h" | 8 #include "SkCodecPriv.h" | 
| 9 #include "SkColorPriv.h" | 9 #include "SkColorPriv.h" | 
| 10 #include "SkColorTable.h" | 10 #include "SkColorTable.h" | 
| (...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 366         png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, nullptr); | 366         png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, nullptr); | 
| 367         fPng_ptr = nullptr; | 367         fPng_ptr = nullptr; | 
| 368         fInfo_ptr = nullptr; | 368         fInfo_ptr = nullptr; | 
| 369     } | 369     } | 
| 370 } | 370 } | 
| 371 | 371 | 
| 372 /////////////////////////////////////////////////////////////////////////////// | 372 /////////////////////////////////////////////////////////////////////////////// | 
| 373 // Getting the pixels | 373 // Getting the pixels | 
| 374 /////////////////////////////////////////////////////////////////////////////// | 374 /////////////////////////////////////////////////////////////////////////////// | 
| 375 | 375 | 
| 376 SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo, | 376 void SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo, const Opti
     ons& options) { | 
| 377                                                const Options& options, | 377     const SkPMColor* colors = get_color_ptr(fColorTable.get()); | 
| 378                                                SkPMColor ctable[], | 378     fSwizzler.reset(SkSwizzler::CreateSwizzler(fSrcConfig, colors, requestedInfo
     , options)); | 
| 379                                                int* ctableCount) { | 379     SkASSERT(fSwizzler); | 
|  | 380 } | 
|  | 381 | 
|  | 382 SkCodec::Result SkPngCodec::prepareToDecode(const SkImageInfo& requestedInfo, | 
|  | 383                                             const Options& options, | 
|  | 384                                             SkPMColor ctable[], | 
|  | 385                                             int* ctableCount) { | 
| 380     // FIXME: Could we use the return value of setjmp to specify the type of | 386     // FIXME: Could we use the return value of setjmp to specify the type of | 
| 381     // error? | 387     // error? | 
| 382     if (setjmp(png_jmpbuf(fPng_ptr))) { | 388     if (setjmp(png_jmpbuf(fPng_ptr))) { | 
| 383         SkCodecPrintf("setjmp long jump!\n"); | 389         SkCodecPrintf("setjmp long jump!\n"); | 
| 384         return kInvalidInput; | 390         return kInvalidInput; | 
| 385     } | 391     } | 
| 386     png_read_update_info(fPng_ptr, fInfo_ptr); | 392     png_read_update_info(fPng_ptr, fInfo_ptr); | 
| 387 | 393 | 
| 388     // suggestedColorType was determined in read_header() based on the encodedCo
     lorType | 394     // suggestedColorType was determined in read_header() based on the encodedCo
     lorType | 
| 389     const SkColorType suggestedColorType = this->getInfo().colorType(); | 395     const SkColorType suggestedColorType = this->getInfo().colorType(); | 
| 390 | 396 | 
|  | 397     // If the conversion provided by the swizzler would be a no-op, we may be ab
     le | 
|  | 398     // to skip the swizzle step. | 
|  | 399     bool skipSwizzle = false; | 
|  | 400 | 
| 391     switch (suggestedColorType) { | 401     switch (suggestedColorType) { | 
| 392         case kIndex_8_SkColorType: | 402         case kIndex_8_SkColorType: | 
| 393             //decode palette to Skia format |  | 
| 394             fSrcConfig = SkSwizzler::kIndex; | 403             fSrcConfig = SkSwizzler::kIndex; | 
|  | 404             skipSwizzle = (kIndex_8_SkColorType == requestedInfo.colorType()); | 
|  | 405 | 
|  | 406             // Decode palette to Skia format | 
| 395             if (!this->decodePalette(kPremul_SkAlphaType == requestedInfo.alphaT
     ype(), | 407             if (!this->decodePalette(kPremul_SkAlphaType == requestedInfo.alphaT
     ype(), | 
| 396                     ctableCount)) { | 408                     ctableCount)) { | 
| 397                 return kInvalidInput; | 409                 return kInvalidInput; | 
| 398             } | 410             } | 
| 399             break; | 411             break; | 
| 400         case kGray_8_SkColorType: | 412         case kGray_8_SkColorType: | 
| 401             fSrcConfig = SkSwizzler::kGray; | 413             fSrcConfig = SkSwizzler::kGray; | 
|  | 414             skipSwizzle = (kGray_8_SkColorType == requestedInfo.colorType()); | 
| 402             break; | 415             break; | 
| 403         case kN32_SkColorType: { | 416         case kN32_SkColorType: { | 
| 404             const uint8_t encodedColorType = png_get_color_type(fPng_ptr, fInfo_
     ptr); | 417             const uint8_t encodedColorType = png_get_color_type(fPng_ptr, fInfo_
     ptr); | 
| 405             if (PNG_COLOR_TYPE_GRAY_ALPHA == encodedColorType || | 418             if (PNG_COLOR_TYPE_GRAY_ALPHA == encodedColorType || | 
| 406                     PNG_COLOR_TYPE_GRAY == encodedColorType) { | 419                     PNG_COLOR_TYPE_GRAY == encodedColorType) { | 
| 407                 // If encodedColorType is GRAY, there must be a transparent chun
     k. | 420                 // If encodedColorType is GRAY, there must be a transparent chun
     k. | 
| 408                 // Otherwise, suggestedColorType would be kGray.  We have alread
     y | 421                 // Otherwise, suggestedColorType would be kGray.  We have alread
     y | 
| 409                 // instructed libpng to convert the transparent chunk to alpha, | 422                 // instructed libpng to convert the transparent chunk to alpha, | 
| 410                 // so we can treat both GRAY and GRAY_ALPHA as kGrayAlpha. | 423                 // so we can treat both GRAY and GRAY_ALPHA as kGrayAlpha. | 
| 411                 SkASSERT(encodedColorType == PNG_COLOR_TYPE_GRAY_ALPHA || | 424                 SkASSERT(encodedColorType == PNG_COLOR_TYPE_GRAY_ALPHA || | 
| 412                         png_get_valid(fPng_ptr, fInfo_ptr, PNG_INFO_tRNS)); | 425                         png_get_valid(fPng_ptr, fInfo_ptr, PNG_INFO_tRNS)); | 
| 413 | 426 | 
| 414                 fSrcConfig = SkSwizzler::kGrayAlpha; | 427                 fSrcConfig = SkSwizzler::kGrayAlpha; | 
| 415             } else { | 428             } else { | 
| 416                 if (this->getInfo().alphaType() == kOpaque_SkAlphaType) { | 429                 if (this->getInfo().alphaType() == kOpaque_SkAlphaType) { | 
| 417                     fSrcConfig = SkSwizzler::kRGB; | 430                     fSrcConfig = SkSwizzler::kRGB; | 
| 418                 } else { | 431                 } else { | 
| 419                     fSrcConfig = SkSwizzler::kRGBA; | 432                     fSrcConfig = SkSwizzler::kRGBA; | 
|  | 433 #ifdef SK_PMCOLOR_IS_RGBA | 
|  | 434                     skipSwizzle = (kUnpremul_SkAlphaType == this->getInfo().alph
     aType()); | 
|  | 435 #endif | 
| 420                 } | 436                 } | 
| 421             } | 437             } | 
| 422             break; | 438             break; | 
| 423         } | 439         } | 
| 424         default: | 440         default: | 
| 425             // We will always recommend one of the above colorTypes. | 441             // We will always recommend one of the above colorTypes. | 
| 426             SkASSERT(false); | 442             SkASSERT(false); | 
| 427     } | 443     } | 
| 428 | 444 | 
| 429     // Copy the color table to the client if they request kIndex8 mode | 445     // Copy the color table to the client if they request kIndex8 mode | 
| 430     copy_color_table(requestedInfo, fColorTable, ctable, ctableCount); | 446     copy_color_table(requestedInfo, fColorTable, ctable, ctableCount); | 
| 431 | 447 | 
|  | 448     // If this is a subset decode, we will need a swizzler. | 
|  | 449     if (options.fSubset) { | 
|  | 450         skipSwizzle = false; | 
|  | 451     } | 
|  | 452 | 
| 432     // Create the swizzler.  SkPngCodec retains ownership of the color table. | 453     // Create the swizzler.  SkPngCodec retains ownership of the color table. | 
| 433     const SkPMColor* colors = get_color_ptr(fColorTable.get()); | 454     if (!skipSwizzle) { | 
| 434     fSwizzler.reset(SkSwizzler::CreateSwizzler(fSrcConfig, colors, requestedInfo
     , options)); | 455         this->initializeSwizzler(requestedInfo, options); | 
| 435     SkASSERT(fSwizzler); | 456     } | 
| 436 | 457 | 
| 437     return kSuccess; | 458     return kSuccess; | 
| 438 } | 459 } | 
| 439 | 460 | 
|  | 461 SkSampler* SkPngCodec::getSampler(bool createIfNecessary) { | 
|  | 462     if (!createIfNecessary || fSwizzler) { | 
|  | 463         return fSwizzler; | 
|  | 464     } | 
|  | 465 | 
|  | 466     this->initializeSwizzler(this->dstInfo(), this->options()); | 
|  | 467     return fSwizzler; | 
|  | 468 } | 
| 440 | 469 | 
| 441 bool SkPngCodec::onRewind() { | 470 bool SkPngCodec::onRewind() { | 
| 442     // This sets fPng_ptr and fInfo_ptr to nullptr. If read_header | 471     // This sets fPng_ptr and fInfo_ptr to nullptr. If read_header | 
| 443     // succeeds, they will be repopulated, and if it fails, they will | 472     // succeeds, they will be repopulated, and if it fails, they will | 
| 444     // remain nullptr. Any future accesses to fPng_ptr and fInfo_ptr will | 473     // remain nullptr. Any future accesses to fPng_ptr and fInfo_ptr will | 
| 445     // come through this function which will rewind and again attempt | 474     // come through this function which will rewind and again attempt | 
| 446     // to reinitialize them. | 475     // to reinitialize them. | 
| 447     this->destroyReadStruct(); | 476     this->destroyReadStruct(); | 
| 448 | 477 | 
| 449     png_structp png_ptr; | 478     png_structp png_ptr; | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
| 464                                         int* rowsDecoded) { | 493                                         int* rowsDecoded) { | 
| 465     if (!conversion_possible(requestedInfo, this->getInfo())) { | 494     if (!conversion_possible(requestedInfo, this->getInfo())) { | 
| 466         return kInvalidConversion; | 495         return kInvalidConversion; | 
| 467     } | 496     } | 
| 468     if (options.fSubset) { | 497     if (options.fSubset) { | 
| 469         // Subsets are not supported. | 498         // Subsets are not supported. | 
| 470         return kUnimplemented; | 499         return kUnimplemented; | 
| 471     } | 500     } | 
| 472 | 501 | 
| 473     // Note that ctable and ctableCount may be modified if there is a color tabl
     e | 502     // Note that ctable and ctableCount may be modified if there is a color tabl
     e | 
| 474     const Result result = this->initializeSwizzler(requestedInfo, options, ctabl
     e, ctableCount); | 503     const Result result = this->prepareToDecode(requestedInfo, options, ctable, 
     ctableCount); | 
| 475     if (result != kSuccess) { | 504     if (result != kSuccess) { | 
| 476         return result; | 505         return result; | 
| 477     } | 506     } | 
|  | 507 | 
|  | 508     const int width = requestedInfo.width(); | 
|  | 509     const int height = requestedInfo.height(); | 
|  | 510     const int bpp = SkSwizzler::BytesPerPixel(fSrcConfig); | 
|  | 511 | 
| 478     // FIXME: Could we use the return value of setjmp to specify the type of | 512     // FIXME: Could we use the return value of setjmp to specify the type of | 
| 479     // error? | 513     // error? | 
| 480     int row = 0; | 514     int row = 0; | 
| 481     // This must be declared above the call to setjmp to avoid memory leaks on i
     ncomplete images. | 515     // This must be declared above the call to setjmp to avoid memory leaks on i
     ncomplete images. | 
| 482     SkAutoTMalloc<uint8_t> storage; | 516     SkAutoTMalloc<uint8_t> storage; | 
| 483     if (setjmp(png_jmpbuf(fPng_ptr))) { | 517     if (setjmp(png_jmpbuf(fPng_ptr))) { | 
| 484         // Assume that any error that occurs while reading rows is caused by an 
     incomplete input. | 518         // Assume that any error that occurs while reading rows is caused by an 
     incomplete input. | 
| 485         if (fNumberPasses > 1) { | 519         if (fNumberPasses > 1) { | 
| 486             // FIXME (msarett): Handle incomplete interlaced pngs. | 520             // FIXME (msarett): Handle incomplete interlaced pngs. | 
| 487             return kInvalidInput; | 521             return row == height ? kSuccess : kInvalidInput; | 
| 488         } | 522         } | 
| 489         // FIXME: We do a poor job on incomplete pngs compared to other decoders
      (ex: Chromium, | 523         // FIXME: We do a poor job on incomplete pngs compared to other decoders
      (ex: Chromium, | 
| 490         // Ubuntu Image Viewer).  This is because we use the default buffer size
      in libpng (8192 | 524         // Ubuntu Image Viewer).  This is because we use the default buffer size
      in libpng (8192 | 
| 491         // bytes), and if we can't fill the buffer, we immediately fail. | 525         // bytes), and if we can't fill the buffer, we immediately fail. | 
| 492         // For example, if we try to read 8192 bytes, and the image (incorrectly
     ) only contains | 526         // For example, if we try to read 8192 bytes, and the image (incorrectly
     ) only contains | 
| 493         // half that, which may have been enough to contain a non-zero number of
      lines, we fail | 527         // half that, which may have been enough to contain a non-zero number of
      lines, we fail | 
| 494         // when we could have decoded a few more lines and then failed. | 528         // when we could have decoded a few more lines and then failed. | 
| 495         // The read function that we provide for libpng has no way of indicating
      that we have | 529         // The read function that we provide for libpng has no way of indicating
      that we have | 
| 496         // made a partial read. | 530         // made a partial read. | 
| 497         // Making our buffer size smaller improves our incomplete decodes, but w
     hat impact does | 531         // Making our buffer size smaller improves our incomplete decodes, but w
     hat impact does | 
| 498         // it have on regular decode performance?  Should we investigate using a
      different API | 532         // it have on regular decode performance?  Should we investigate using a
      different API | 
| 499         // instead of png_read_row(s)?  Chromium uses png_process_data. | 533         // instead of png_read_row(s)?  Chromium uses png_process_data. | 
| 500         *rowsDecoded = row; | 534         *rowsDecoded = row; | 
| 501         return kIncompleteInput; | 535         return row == height ? kSuccess : kIncompleteInput; | 
| 502     } | 536     } | 
| 503 | 537 | 
| 504     // FIXME: We could split these out based on subclass. | 538     // FIXME: We could split these out based on subclass. | 
| 505     void* dstRow = dst; |  | 
| 506     if (fNumberPasses > 1) { | 539     if (fNumberPasses > 1) { | 
| 507         const int width = requestedInfo.width(); |  | 
| 508         const int height = requestedInfo.height(); |  | 
| 509         const int bpp = SkSwizzler::BytesPerPixel(fSrcConfig); |  | 
| 510         const size_t srcRowBytes = width * bpp; | 540         const size_t srcRowBytes = width * bpp; | 
|  | 541         const size_t rowBytes = fSwizzler ? srcRowBytes : dstRowBytes; | 
|  | 542         uint8_t* const base = fSwizzler ? storage.reset(width * height * bpp) : 
     (uint8_t*) dst; | 
|  | 543         for (int i = 0; i < fNumberPasses; i++) { | 
|  | 544             uint8_t* rowPtr = base; | 
|  | 545             for (int y = 0; y < height; y++) { | 
|  | 546                 png_read_rows(fPng_ptr, &rowPtr, nullptr, 1); | 
|  | 547                 rowPtr += rowBytes; | 
|  | 548             } | 
|  | 549         } | 
| 511 | 550 | 
| 512         storage.reset(width * height * bpp); | 551         // Swizzle if necessary. | 
| 513         uint8_t* const base = storage.get(); | 552         if (fSwizzler) { | 
| 514 |  | 
| 515         for (int i = 0; i < fNumberPasses; i++) { |  | 
| 516             uint8_t* srcRow = base; | 553             uint8_t* srcRow = base; | 
| 517             for (int y = 0; y < height; y++) { | 554             for (int y = 0; y < height; y++) { | 
| 518                 uint8_t* bmRow = srcRow; | 555                 fSwizzler->swizzle(dst, srcRow); | 
| 519                 png_read_rows(fPng_ptr, &bmRow, nullptr, 1); | 556                 dst = SkTAddOffset<void>(dst, dstRowBytes); | 
| 520                 srcRow += srcRowBytes; | 557                 srcRow += srcRowBytes; | 
| 521             } | 558             } | 
| 522         } | 559         } | 
| 523 | 560     } else { | 
| 524         // Now swizzle it. | 561         if (fSwizzler) { | 
| 525         uint8_t* srcRow = base; | 562             uint8_t* rowPtr = storage.reset(width * bpp); | 
| 526         for (int y = 0; y < height; y++) { | 563             for (; row < requestedInfo.height(); row++) { | 
| 527             fSwizzler->swizzle(dstRow, srcRow); | 564                 png_read_rows(fPng_ptr, &rowPtr, nullptr, 1); | 
| 528             dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); | 565                 fSwizzler->swizzle(dst, rowPtr); | 
| 529             srcRow += srcRowBytes; | 566                 dst = SkTAddOffset<void>(dst, dstRowBytes); | 
|  | 567             } | 
|  | 568         } else { | 
|  | 569             uint8_t* rowPtr = (uint8_t*) dst; | 
|  | 570             SkAutoMalloc storage(sizeof(uint8_t*) * requestedInfo.height()); | 
|  | 571             uint8_t** ptrs = (uint8_t**) storage.get(); | 
|  | 572             for (int i = 0; i < requestedInfo.height(); i++) { | 
|  | 573                 ptrs[i] = rowPtr; | 
|  | 574                 rowPtr += dstRowBytes; | 
|  | 575             } | 
|  | 576             png_read_rows(fPng_ptr, ptrs, nullptr, requestedInfo.height()); | 
| 530         } | 577         } | 
| 531     } else { |  | 
| 532         storage.reset(requestedInfo.width() * SkSwizzler::BytesPerPixel(fSrcConf
     ig)); |  | 
| 533         uint8_t* srcRow = storage.get(); |  | 
| 534         for (; row < requestedInfo.height(); row++) { |  | 
| 535             png_read_rows(fPng_ptr, &srcRow, nullptr, 1); |  | 
| 536             // FIXME: Only call IsOpaque once, outside the loop. Same for onGetS
     canlines. |  | 
| 537             fSwizzler->swizzle(dstRow, srcRow); |  | 
| 538             dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); |  | 
| 539         } |  | 
| 540     } |  | 
| 541 |  | 
| 542     if (setjmp(png_jmpbuf(fPng_ptr))) { |  | 
| 543         // We've already read all the scanlines. This is a success. |  | 
| 544         return kSuccess; |  | 
| 545     } | 578     } | 
| 546 | 579 | 
| 547     // read rest of file, and get additional comment and time chunks in info_ptr | 580     // read rest of file, and get additional comment and time chunks in info_ptr | 
| 548     png_read_end(fPng_ptr, fInfo_ptr); | 581     png_read_end(fPng_ptr, fInfo_ptr); | 
| 549 | 582 | 
| 550     return kSuccess; | 583     return kSuccess; | 
| 551 } | 584 } | 
| 552 | 585 | 
| 553 uint32_t SkPngCodec::onGetFillValue(SkColorType colorType) const { | 586 uint32_t SkPngCodec::onGetFillValue(SkColorType colorType) const { | 
| 554     const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); | 587     const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 566         : INHERITED(srcInfo, stream, chunkReader, png_ptr, info_ptr, bitDepth, 1
     ) | 599         : INHERITED(srcInfo, stream, chunkReader, png_ptr, info_ptr, bitDepth, 1
     ) | 
| 567         , fSrcRow(nullptr) | 600         , fSrcRow(nullptr) | 
| 568     {} | 601     {} | 
| 569 | 602 | 
| 570     Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti
     ons, | 603     Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti
     ons, | 
| 571             SkPMColor ctable[], int* ctableCount) override { | 604             SkPMColor ctable[], int* ctableCount) override { | 
| 572         if (!conversion_possible(dstInfo, this->getInfo())) { | 605         if (!conversion_possible(dstInfo, this->getInfo())) { | 
| 573             return kInvalidConversion; | 606             return kInvalidConversion; | 
| 574         } | 607         } | 
| 575 | 608 | 
| 576         const Result result = this->initializeSwizzler(dstInfo, options, ctable, | 609         const Result result = this->prepareToDecode(dstInfo, options, ctable, ct
     ableCount); | 
| 577                                                        ctableCount); |  | 
| 578         if (result != kSuccess) { | 610         if (result != kSuccess) { | 
| 579             return result; | 611             return result; | 
| 580         } | 612         } | 
| 581 | 613 | 
| 582         fStorage.reset(this->getInfo().width() * SkSwizzler::BytesPerPixel(this-
     >srcConfig())); | 614         fStorage.reset(this->getInfo().width() * SkSwizzler::BytesPerPixel(this-
     >srcConfig())); | 
| 583         fSrcRow = fStorage.get(); | 615         fSrcRow = fStorage.get(); | 
| 584 | 616 | 
| 585         return kSuccess; | 617         return kSuccess; | 
| 586     } | 618     } | 
| 587 | 619 | 
| 588     int onGetScanlines(void* dst, int count, size_t rowBytes) override { | 620     int onGetScanlines(void* dst, int count, size_t rowBytes) override { | 
| 589         // Assume that an error in libpng indicates an incomplete input. | 621         // Assume that an error in libpng indicates an incomplete input. | 
| 590         int row = 0; | 622         int row = 0; | 
| 591         if (setjmp(png_jmpbuf(this->png_ptr()))) { | 623         if (setjmp(png_jmpbuf(this->png_ptr()))) { | 
| 592             SkCodecPrintf("setjmp long jump!\n"); | 624             SkCodecPrintf("setjmp long jump!\n"); | 
| 593             return row; | 625             return row; | 
| 594         } | 626         } | 
| 595 | 627 | 
| 596         void* dstRow = dst; | 628         uint8_t* rowPtr; | 
|  | 629         if (this->swizzler()) { | 
|  | 630             rowPtr = fSrcRow; | 
|  | 631         } else { | 
|  | 632             // Write decoded pixels directly to dst. | 
|  | 633             rowPtr = (uint8_t*) dst; | 
|  | 634         } | 
|  | 635 | 
| 597         for (; row < count; row++) { | 636         for (; row < count; row++) { | 
| 598             png_read_rows(this->png_ptr(), &fSrcRow, nullptr, 1); | 637             png_read_rows(this->png_ptr(), &rowPtr, nullptr, 1); | 
| 599             this->swizzler()->swizzle(dstRow, fSrcRow); | 638 | 
| 600             dstRow = SkTAddOffset<void>(dstRow, rowBytes); | 639             if (this->swizzler()) { | 
|  | 640                 this->swizzler()->swizzle(dst, rowPtr); | 
|  | 641                 dst = SkTAddOffset<void>(dst, rowBytes); | 
|  | 642             } else { | 
|  | 643                 rowPtr += rowBytes; | 
|  | 644             } | 
| 601         } | 645         } | 
| 602 | 646 | 
| 603         return row; | 647         return row; | 
| 604     } | 648     } | 
| 605 | 649 | 
| 606     bool onSkipScanlines(int count) override { | 650     bool onSkipScanlines(int count) override { | 
| 607         // Assume that an error in libpng indicates an incomplete input. | 651         // Assume that an error in libpng indicates an incomplete input. | 
| 608         if (setjmp(png_jmpbuf(this->png_ptr()))) { | 652         if (setjmp(png_jmpbuf(this->png_ptr()))) { | 
| 609             SkCodecPrintf("setjmp long jump!\n"); | 653             SkCodecPrintf("setjmp long jump!\n"); | 
| 610             return false; | 654             return false; | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
| 637     { | 681     { | 
| 638         SkASSERT(numberPasses != 1); | 682         SkASSERT(numberPasses != 1); | 
| 639     } | 683     } | 
| 640 | 684 | 
| 641     Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti
     ons, | 685     Result onStartScanlineDecode(const SkImageInfo& dstInfo, const Options& opti
     ons, | 
| 642             SkPMColor ctable[], int* ctableCount) override { | 686             SkPMColor ctable[], int* ctableCount) override { | 
| 643         if (!conversion_possible(dstInfo, this->getInfo())) { | 687         if (!conversion_possible(dstInfo, this->getInfo())) { | 
| 644             return kInvalidConversion; | 688             return kInvalidConversion; | 
| 645         } | 689         } | 
| 646 | 690 | 
| 647         const Result result = this->initializeSwizzler(dstInfo, options, ctable, | 691         const Result result = this->prepareToDecode(dstInfo, options, ctable, ct
     ableCount); | 
| 648                                                        ctableCount); |  | 
| 649         if (result != kSuccess) { | 692         if (result != kSuccess) { | 
| 650             return result; | 693             return result; | 
| 651         } | 694         } | 
| 652 | 695 | 
| 653         fHeight = dstInfo.height(); | 696         fHeight = dstInfo.height(); | 
| 654         // FIXME: This need not be called on a second call to onStartScanlineDec
     ode. | 697         // FIXME: This need not be called on a second call to onStartScanlineDec
     ode. | 
| 655         fSrcRowBytes = this->getInfo().width() * SkSwizzler::BytesPerPixel(this-
     >srcConfig()); | 698         fSrcRowBytes = this->getInfo().width() * SkSwizzler::BytesPerPixel(this-
     >srcConfig()); | 
| 656         fGarbageRow.reset(fSrcRowBytes); | 699         fGarbageRow.reset(fSrcRowBytes); | 
| 657         fGarbageRowPtr = static_cast<uint8_t*>(fGarbageRow.get()); | 700         fGarbageRowPtr = static_cast<uint8_t*>(fGarbageRow.get()); | 
| 658         fCanSkipRewind = true; | 701         fCanSkipRewind = true; | 
| (...skipping 24 matching lines...) Expand all  Loading... | 
| 683             this->updateCurrScanline(currScanline); | 726             this->updateCurrScanline(currScanline); | 
| 684         } | 727         } | 
| 685 | 728 | 
| 686         if (setjmp(png_jmpbuf(this->png_ptr()))) { | 729         if (setjmp(png_jmpbuf(this->png_ptr()))) { | 
| 687             SkCodecPrintf("setjmp long jump!\n"); | 730             SkCodecPrintf("setjmp long jump!\n"); | 
| 688             // FIXME (msarett): Returning 0 is pessimistic.  If we can complete 
     a single pass, | 731             // FIXME (msarett): Returning 0 is pessimistic.  If we can complete 
     a single pass, | 
| 689             // we may be able to report that all of the memory has been initiali
     zed.  Even if we | 732             // we may be able to report that all of the memory has been initiali
     zed.  Even if we | 
| 690             // fail on the first pass, we can still report than some scanlines a
     re initialized. | 733             // fail on the first pass, we can still report than some scanlines a
     re initialized. | 
| 691             return 0; | 734             return 0; | 
| 692         } | 735         } | 
| 693         SkAutoTMalloc<uint8_t> storage(count * fSrcRowBytes); | 736         SkAutoTMalloc<uint8_t> storage; | 
| 694         uint8_t* storagePtr = storage.get(); | 737         uint8_t* const base = this->swizzler() ? | 
| 695         uint8_t* srcRow; | 738                 storage.reset(count * fSrcRowBytes) : (uint8_t*) dst; | 
|  | 739         const size_t rowBytes = this->swizzler() ? fSrcRowBytes : dstRowBytes; | 
| 696         const int startRow = this->nextScanline(); | 740         const int startRow = this->nextScanline(); | 
| 697         for (int i = 0; i < this->numberPasses(); i++) { | 741         for (int i = 0; i < this->numberPasses(); i++) { | 
| 698             // read rows we planned to skip into garbage row | 742             // read rows we planned to skip into garbage row | 
| 699             for (int y = 0; y < startRow; y++){ | 743             for (int y = 0; y < startRow; y++){ | 
| 700                 png_read_rows(this->png_ptr(), &fGarbageRowPtr, nullptr, 1); | 744                 png_read_rows(this->png_ptr(), &fGarbageRowPtr, nullptr, 1); | 
| 701             } | 745             } | 
| 702             // read rows we care about into buffer | 746             // read rows we care about into buffer | 
| 703             srcRow = storagePtr; | 747             uint8_t* rowPtr = base; | 
| 704             for (int y = 0; y < count; y++) { | 748             for (int y = 0; y < count; y++) { | 
| 705                 png_read_rows(this->png_ptr(), &srcRow, nullptr, 1); | 749                 png_read_rows(this->png_ptr(), &rowPtr, nullptr, 1); | 
| 706                 srcRow += fSrcRowBytes; | 750                 rowPtr += rowBytes; | 
| 707             } | 751             } | 
| 708             // read rows we don't want into garbage buffer | 752             // read rows we don't want into garbage buffer | 
| 709             for (int y = 0; y < fHeight - startRow - count; y++) { | 753             for (int y = 0; y < fHeight - startRow - count; y++) { | 
| 710                 png_read_rows(this->png_ptr(), &fGarbageRowPtr, nullptr, 1); | 754                 png_read_rows(this->png_ptr(), &fGarbageRowPtr, nullptr, 1); | 
| 711             } | 755             } | 
| 712         } | 756         } | 
| 713         //swizzle the rows we care about | 757 | 
| 714         srcRow = storagePtr; | 758         // Swizzle if necessary | 
| 715         void* dstRow = dst; | 759         if (this->swizzler()) { | 
| 716         for (int y = 0; y < count; y++) { | 760             uint8_t* srcRow = storage.get(); | 
| 717             this->swizzler()->swizzle(dstRow, srcRow); | 761             void* dstRow = dst; | 
| 718             dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); | 762             for (int y = 0; y < count; y++) { | 
| 719             srcRow += fSrcRowBytes; | 763                 this->swizzler()->swizzle(dstRow, srcRow); | 
|  | 764                 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); | 
|  | 765                 srcRow += fSrcRowBytes; | 
|  | 766             } | 
| 720         } | 767         } | 
| 721 | 768 | 
| 722         return count; | 769         return count; | 
| 723     } | 770     } | 
| 724 | 771 | 
| 725     bool onSkipScanlines(int count) override { | 772     bool onSkipScanlines(int count) override { | 
| 726         // The non-virtual version will update fCurrScanline. | 773         // The non-virtual version will update fCurrScanline. | 
| 727         return true; | 774         return true; | 
| 728     } | 775     } | 
| 729 | 776 | 
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 763     } | 810     } | 
| 764 | 811 | 
| 765     if (1 == numberPasses) { | 812     if (1 == numberPasses) { | 
| 766         return new SkPngScanlineDecoder(imageInfo, streamDeleter.detach(), chunk
     Reader, | 813         return new SkPngScanlineDecoder(imageInfo, streamDeleter.detach(), chunk
     Reader, | 
| 767                                         png_ptr, info_ptr, bitDepth); | 814                                         png_ptr, info_ptr, bitDepth); | 
| 768     } | 815     } | 
| 769 | 816 | 
| 770     return new SkPngInterlacedScanlineDecoder(imageInfo, streamDeleter.detach(),
      chunkReader, | 817     return new SkPngInterlacedScanlineDecoder(imageInfo, streamDeleter.detach(),
      chunkReader, | 
| 771                                               png_ptr, info_ptr, bitDepth, numbe
     rPasses); | 818                                               png_ptr, info_ptr, bitDepth, numbe
     rPasses); | 
| 772 } | 819 } | 
| OLD | NEW | 
|---|