| 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 "SkCodec_libpng.h" | 8 #include "SkCodec_libpng.h" |
| 9 #include "SkCodecPriv.h" | 9 #include "SkCodecPriv.h" |
| 10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
| 11 #include "SkColorTable.h" | 11 #include "SkColorTable.h" |
| 12 #include "SkBitmap.h" | 12 #include "SkBitmap.h" |
| 13 #include "SkMath.h" | 13 #include "SkMath.h" |
| 14 #include "SkScaledCodec.h" | 14 #include "SkScaledCodec.h" |
| 15 #include "SkScanlineDecoder.h" | 15 #include "SkScanlineDecoder.h" |
| 16 #include "SkSize.h" | 16 #include "SkSize.h" |
| 17 #include "SkStream.h" | 17 #include "SkStream.h" |
| 18 #include "SkSwizzler.h" | 18 #include "SkSwizzler.h" |
| 19 | 19 |
| 20 /////////////////////////////////////////////////////////////////////////////// | 20 /////////////////////////////////////////////////////////////////////////////// |
| 21 // Helper macros | 21 // Helper macros |
| 22 /////////////////////////////////////////////////////////////////////////////// | 22 /////////////////////////////////////////////////////////////////////////////// |
| 23 | 23 |
| 24 #ifndef png_jmpbuf | 24 #ifndef png_jmpbuf |
| 25 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) | 25 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) |
| 26 #endif | 26 #endif |
| 27 | 27 |
| 28 /* These were dropped in libpng >= 1.4 */ | 28 /* These were dropped in libpng >= 1.4 */ |
| 29 #ifndef png_infopp_NULL | 29 #ifndef png_infopp_NULL |
| 30 #define png_infopp_NULL NULL | 30 #define png_infopp_NULL nullptr |
| 31 #endif | 31 #endif |
| 32 | 32 |
| 33 #ifndef png_bytepp_NULL | 33 #ifndef png_bytepp_NULL |
| 34 #define png_bytepp_NULL NULL | 34 #define png_bytepp_NULL nullptr |
| 35 #endif | 35 #endif |
| 36 | 36 |
| 37 #ifndef int_p_NULL | 37 #ifndef int_p_NULL |
| 38 #define int_p_NULL NULL | 38 #define int_p_NULL nullptr |
| 39 #endif | 39 #endif |
| 40 | 40 |
| 41 #ifndef png_flush_ptr_NULL | 41 #ifndef png_flush_ptr_NULL |
| 42 #define png_flush_ptr_NULL NULL | 42 #define png_flush_ptr_NULL nullptr |
| 43 #endif | 43 #endif |
| 44 | 44 |
| 45 /////////////////////////////////////////////////////////////////////////////// | 45 /////////////////////////////////////////////////////////////////////////////// |
| 46 // Callback functions | 46 // Callback functions |
| 47 /////////////////////////////////////////////////////////////////////////////// | 47 /////////////////////////////////////////////////////////////////////////////// |
| 48 | 48 |
| 49 static void sk_error_fn(png_structp png_ptr, png_const_charp msg) { | 49 static void sk_error_fn(png_structp png_ptr, png_const_charp msg) { |
| 50 SkCodecPrintf("------ png error %s\n", msg); | 50 SkCodecPrintf("------ png error %s\n", msg); |
| 51 longjmp(png_jmpbuf(png_ptr), 1); | 51 longjmp(png_jmpbuf(png_ptr), 1); |
| 52 } | 52 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 68 } | 68 } |
| 69 | 69 |
| 70 /////////////////////////////////////////////////////////////////////////////// | 70 /////////////////////////////////////////////////////////////////////////////// |
| 71 // Helpers | 71 // Helpers |
| 72 /////////////////////////////////////////////////////////////////////////////// | 72 /////////////////////////////////////////////////////////////////////////////// |
| 73 | 73 |
| 74 class AutoCleanPng : public SkNoncopyable { | 74 class AutoCleanPng : public SkNoncopyable { |
| 75 public: | 75 public: |
| 76 AutoCleanPng(png_structp png_ptr) | 76 AutoCleanPng(png_structp png_ptr) |
| 77 : fPng_ptr(png_ptr) | 77 : fPng_ptr(png_ptr) |
| 78 , fInfo_ptr(NULL) {} | 78 , fInfo_ptr(nullptr) {} |
| 79 | 79 |
| 80 ~AutoCleanPng() { | 80 ~AutoCleanPng() { |
| 81 // fInfo_ptr will never be non-NULL unless fPng_ptr is. | 81 // fInfo_ptr will never be non-nullptr unless fPng_ptr is. |
| 82 if (fPng_ptr) { | 82 if (fPng_ptr) { |
| 83 png_infopp info_pp = fInfo_ptr ? &fInfo_ptr : NULL; | 83 png_infopp info_pp = fInfo_ptr ? &fInfo_ptr : nullptr; |
| 84 png_destroy_read_struct(&fPng_ptr, info_pp, png_infopp_NULL); | 84 png_destroy_read_struct(&fPng_ptr, info_pp, png_infopp_NULL); |
| 85 } | 85 } |
| 86 } | 86 } |
| 87 | 87 |
| 88 void setInfoPtr(png_infop info_ptr) { | 88 void setInfoPtr(png_infop info_ptr) { |
| 89 SkASSERT(NULL == fInfo_ptr); | 89 SkASSERT(nullptr == fInfo_ptr); |
| 90 fInfo_ptr = info_ptr; | 90 fInfo_ptr = info_ptr; |
| 91 } | 91 } |
| 92 | 92 |
| 93 void detach() { | 93 void detach() { |
| 94 fPng_ptr = NULL; | 94 fPng_ptr = nullptr; |
| 95 fInfo_ptr = NULL; | 95 fInfo_ptr = nullptr; |
| 96 } | 96 } |
| 97 | 97 |
| 98 private: | 98 private: |
| 99 png_structp fPng_ptr; | 99 png_structp fPng_ptr; |
| 100 png_infop fInfo_ptr; | 100 png_infop fInfo_ptr; |
| 101 }; | 101 }; |
| 102 #define AutoCleanPng(...) SK_REQUIRE_LOCAL_VAR(AutoCleanPng) | 102 #define AutoCleanPng(...) SK_REQUIRE_LOCAL_VAR(AutoCleanPng) |
| 103 | 103 |
| 104 //checks if there is transparency info in the tRNS chunk | 104 //checks if there is transparency info in the tRNS chunk |
| 105 //image types which could have data in the tRNS chunk include: Index8, Gray8, RG
B | 105 //image types which could have data in the tRNS chunk include: Index8, Gray8, RG
B |
| 106 static bool has_transparency_in_tRNS(png_structp png_ptr, | 106 static bool has_transparency_in_tRNS(png_structp png_ptr, |
| 107 png_infop info_ptr) { | 107 png_infop info_ptr) { |
| 108 if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { | 108 if (!png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) { |
| 109 return false; | 109 return false; |
| 110 } | 110 } |
| 111 | 111 |
| 112 png_bytep trans; | 112 png_bytep trans; |
| 113 int num_trans; | 113 int num_trans; |
| 114 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL); | 114 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, nullptr); |
| 115 return num_trans > 0; | 115 return num_trans > 0; |
| 116 } | 116 } |
| 117 | 117 |
| 118 // Method for coverting to either an SkPMColor or a similarly packed | 118 // Method for coverting to either an SkPMColor or a similarly packed |
| 119 // unpremultiplied color. | 119 // unpremultiplied color. |
| 120 typedef uint32_t (*PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b); | 120 typedef uint32_t (*PackColorProc)(U8CPU a, U8CPU r, U8CPU g, U8CPU b); |
| 121 | 121 |
| 122 // Note: SkColorTable claims to store SkPMColors, which is not necessarily | 122 // Note: SkColorTable claims to store SkPMColors, which is not necessarily |
| 123 // the case here. | 123 // the case here. |
| 124 bool SkPngCodec::decodePalette(bool premultiply, int* ctableCount) { | 124 bool SkPngCodec::decodePalette(bool premultiply, int* ctableCount) { |
| 125 int numPalette; | 125 int numPalette; |
| 126 png_colorp palette; | 126 png_colorp palette; |
| 127 png_bytep trans; | 127 png_bytep trans; |
| 128 | 128 |
| 129 if (!png_get_PLTE(fPng_ptr, fInfo_ptr, &palette, &numPalette)) { | 129 if (!png_get_PLTE(fPng_ptr, fInfo_ptr, &palette, &numPalette)) { |
| 130 return false; | 130 return false; |
| 131 } | 131 } |
| 132 | 132 |
| 133 // Note: These are not necessarily SkPMColors | 133 // Note: These are not necessarily SkPMColors |
| 134 SkPMColor colorStorage[256]; // worst-case storage | 134 SkPMColor colorStorage[256]; // worst-case storage |
| 135 SkPMColor* colorPtr = colorStorage; | 135 SkPMColor* colorPtr = colorStorage; |
| 136 | 136 |
| 137 int numTrans; | 137 int numTrans; |
| 138 if (png_get_valid(fPng_ptr, fInfo_ptr, PNG_INFO_tRNS)) { | 138 if (png_get_valid(fPng_ptr, fInfo_ptr, PNG_INFO_tRNS)) { |
| 139 png_get_tRNS(fPng_ptr, fInfo_ptr, &trans, &numTrans, NULL); | 139 png_get_tRNS(fPng_ptr, fInfo_ptr, &trans, &numTrans, nullptr); |
| 140 } else { | 140 } else { |
| 141 numTrans = 0; | 141 numTrans = 0; |
| 142 } | 142 } |
| 143 | 143 |
| 144 // check for bad images that might make us crash | 144 // check for bad images that might make us crash |
| 145 if (numTrans > numPalette) { | 145 if (numTrans > numPalette) { |
| 146 numTrans = numPalette; | 146 numTrans = numPalette; |
| 147 } | 147 } |
| 148 | 148 |
| 149 int index = 0; | 149 int index = 0; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 178 addressed by the bitdepth of the image and fill it with the last palette
color or black if | 178 addressed by the bitdepth of the image and fill it with the last palette
color or black if |
| 179 the palette is empty (really broken image). | 179 the palette is empty (really broken image). |
| 180 */ | 180 */ |
| 181 int colorCount = SkTMax(numPalette, 1 << SkTMin(fBitDepth, 8)); | 181 int colorCount = SkTMax(numPalette, 1 << SkTMin(fBitDepth, 8)); |
| 182 SkPMColor lastColor = index > 0 ? colorPtr[-1] : SkPackARGB32(0xFF, 0, 0, 0)
; | 182 SkPMColor lastColor = index > 0 ? colorPtr[-1] : SkPackARGB32(0xFF, 0, 0, 0)
; |
| 183 for (; index < colorCount; index++) { | 183 for (; index < colorCount; index++) { |
| 184 *colorPtr++ = lastColor; | 184 *colorPtr++ = lastColor; |
| 185 } | 185 } |
| 186 | 186 |
| 187 // Set the new color count | 187 // Set the new color count |
| 188 if (ctableCount != NULL) { | 188 if (ctableCount != nullptr) { |
| 189 *ctableCount = colorCount; | 189 *ctableCount = colorCount; |
| 190 } | 190 } |
| 191 | 191 |
| 192 fColorTable.reset(new SkColorTable(colorStorage, colorCount)); | 192 fColorTable.reset(new SkColorTable(colorStorage, colorCount)); |
| 193 return true; | 193 return true; |
| 194 } | 194 } |
| 195 | 195 |
| 196 /////////////////////////////////////////////////////////////////////////////// | 196 /////////////////////////////////////////////////////////////////////////////// |
| 197 // Creation | 197 // Creation |
| 198 /////////////////////////////////////////////////////////////////////////////// | 198 /////////////////////////////////////////////////////////////////////////////// |
| 199 | 199 |
| 200 #define PNG_BYTES_TO_CHECK 4 | 200 #define PNG_BYTES_TO_CHECK 4 |
| 201 | 201 |
| 202 bool SkPngCodec::IsPng(SkStream* stream) { | 202 bool SkPngCodec::IsPng(SkStream* stream) { |
| 203 char buf[PNG_BYTES_TO_CHECK]; | 203 char buf[PNG_BYTES_TO_CHECK]; |
| 204 if (stream->read(buf, PNG_BYTES_TO_CHECK) != PNG_BYTES_TO_CHECK) { | 204 if (stream->read(buf, PNG_BYTES_TO_CHECK) != PNG_BYTES_TO_CHECK) { |
| 205 return false; | 205 return false; |
| 206 } | 206 } |
| 207 if (png_sig_cmp((png_bytep) buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) { | 207 if (png_sig_cmp((png_bytep) buf, (png_size_t)0, PNG_BYTES_TO_CHECK)) { |
| 208 return false; | 208 return false; |
| 209 } | 209 } |
| 210 return true; | 210 return true; |
| 211 } | 211 } |
| 212 | 212 |
| 213 // Reads the header, and initializes the passed in fields, if not NULL (except | 213 // Reads the header, and initializes the passed in fields, if not nullptr (excep
t |
| 214 // stream, which is passed to the read function). | 214 // stream, which is passed to the read function). |
| 215 // Returns true on success, in which case the caller is responsible for calling | 215 // Returns true on success, in which case the caller is responsible for calling |
| 216 // png_destroy_read_struct. If it returns false, the passed in fields (except | 216 // png_destroy_read_struct. If it returns false, the passed in fields (except |
| 217 // stream) are unchanged. | 217 // stream) are unchanged. |
| 218 static bool read_header(SkStream* stream, png_structp* png_ptrp, | 218 static bool read_header(SkStream* stream, png_structp* png_ptrp, |
| 219 png_infop* info_ptrp, SkImageInfo* imageInfo, int* bitDe
pthPtr) { | 219 png_infop* info_ptrp, SkImageInfo* imageInfo, int* bitDe
pthPtr) { |
| 220 // The image is known to be a PNG. Decode enough to know the SkImageInfo. | 220 // The image is known to be a PNG. Decode enough to know the SkImageInfo. |
| 221 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, | 221 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, |
| 222 sk_error_fn, sk_warning_fn); | 222 sk_error_fn, sk_warning_fn); |
| 223 if (!png_ptr) { | 223 if (!png_ptr) { |
| 224 return false; | 224 return false; |
| 225 } | 225 } |
| 226 | 226 |
| 227 AutoCleanPng autoClean(png_ptr); | 227 AutoCleanPng autoClean(png_ptr); |
| 228 | 228 |
| 229 png_infop info_ptr = png_create_info_struct(png_ptr); | 229 png_infop info_ptr = png_create_info_struct(png_ptr); |
| 230 if (info_ptr == NULL) { | 230 if (info_ptr == nullptr) { |
| 231 return false; | 231 return false; |
| 232 } | 232 } |
| 233 | 233 |
| 234 autoClean.setInfoPtr(info_ptr); | 234 autoClean.setInfoPtr(info_ptr); |
| 235 | 235 |
| 236 // FIXME: Could we use the return value of setjmp to specify the type of | 236 // FIXME: Could we use the return value of setjmp to specify the type of |
| 237 // error? | 237 // error? |
| 238 if (setjmp(png_jmpbuf(png_ptr))) { | 238 if (setjmp(png_jmpbuf(png_ptr))) { |
| 239 return false; | 239 return false; |
| 240 } | 240 } |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 351 | 351 |
| 352 SkCodec* SkPngCodec::NewFromStream(SkStream* stream) { | 352 SkCodec* SkPngCodec::NewFromStream(SkStream* stream) { |
| 353 SkAutoTDelete<SkStream> streamDeleter(stream); | 353 SkAutoTDelete<SkStream> streamDeleter(stream); |
| 354 png_structp png_ptr; | 354 png_structp png_ptr; |
| 355 png_infop info_ptr; | 355 png_infop info_ptr; |
| 356 SkImageInfo imageInfo; | 356 SkImageInfo imageInfo; |
| 357 int bitDepth; | 357 int bitDepth; |
| 358 if (read_header(stream, &png_ptr, &info_ptr, &imageInfo, &bitDepth)) { | 358 if (read_header(stream, &png_ptr, &info_ptr, &imageInfo, &bitDepth)) { |
| 359 return new SkPngCodec(imageInfo, streamDeleter.detach(), png_ptr, info_p
tr, bitDepth); | 359 return new SkPngCodec(imageInfo, streamDeleter.detach(), png_ptr, info_p
tr, bitDepth); |
| 360 } | 360 } |
| 361 return NULL; | 361 return nullptr; |
| 362 } | 362 } |
| 363 | 363 |
| 364 #define INVALID_NUMBER_PASSES -1 | 364 #define INVALID_NUMBER_PASSES -1 |
| 365 SkPngCodec::SkPngCodec(const SkImageInfo& info, SkStream* stream, | 365 SkPngCodec::SkPngCodec(const SkImageInfo& info, SkStream* stream, |
| 366 png_structp png_ptr, png_infop info_ptr, int bitDepth) | 366 png_structp png_ptr, png_infop info_ptr, int bitDepth) |
| 367 : INHERITED(info, stream) | 367 : INHERITED(info, stream) |
| 368 , fPng_ptr(png_ptr) | 368 , fPng_ptr(png_ptr) |
| 369 , fInfo_ptr(info_ptr) | 369 , fInfo_ptr(info_ptr) |
| 370 , fSrcConfig(SkSwizzler::kUnknown) | 370 , fSrcConfig(SkSwizzler::kUnknown) |
| 371 , fNumberPasses(INVALID_NUMBER_PASSES) | 371 , fNumberPasses(INVALID_NUMBER_PASSES) |
| 372 , fReallyHasAlpha(false) | 372 , fReallyHasAlpha(false) |
| 373 , fBitDepth(bitDepth) | 373 , fBitDepth(bitDepth) |
| 374 {} | 374 {} |
| 375 | 375 |
| 376 SkPngCodec::~SkPngCodec() { | 376 SkPngCodec::~SkPngCodec() { |
| 377 this->destroyReadStruct(); | 377 this->destroyReadStruct(); |
| 378 } | 378 } |
| 379 | 379 |
| 380 void SkPngCodec::destroyReadStruct() { | 380 void SkPngCodec::destroyReadStruct() { |
| 381 if (fPng_ptr) { | 381 if (fPng_ptr) { |
| 382 // We will never have a NULL fInfo_ptr with a non-NULL fPng_ptr | 382 // We will never have a nullptr fInfo_ptr with a non-nullptr fPng_ptr |
| 383 SkASSERT(fInfo_ptr); | 383 SkASSERT(fInfo_ptr); |
| 384 png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, png_infopp_NULL); | 384 png_destroy_read_struct(&fPng_ptr, &fInfo_ptr, png_infopp_NULL); |
| 385 fPng_ptr = NULL; | 385 fPng_ptr = nullptr; |
| 386 fInfo_ptr = NULL; | 386 fInfo_ptr = nullptr; |
| 387 } | 387 } |
| 388 } | 388 } |
| 389 | 389 |
| 390 /////////////////////////////////////////////////////////////////////////////// | 390 /////////////////////////////////////////////////////////////////////////////// |
| 391 // Getting the pixels | 391 // Getting the pixels |
| 392 /////////////////////////////////////////////////////////////////////////////// | 392 /////////////////////////////////////////////////////////////////////////////// |
| 393 | 393 |
| 394 SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo, | 394 SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo, |
| 395 const Options& options, | 395 const Options& options, |
| 396 SkPMColor ctable[], | 396 SkPMColor ctable[], |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 options.fZeroInitialized, this->getInfo())); | 443 options.fZeroInitialized, this->getInfo())); |
| 444 if (!fSwizzler) { | 444 if (!fSwizzler) { |
| 445 // FIXME: CreateSwizzler could fail for another reason. | 445 // FIXME: CreateSwizzler could fail for another reason. |
| 446 return kUnimplemented; | 446 return kUnimplemented; |
| 447 } | 447 } |
| 448 return kSuccess; | 448 return kSuccess; |
| 449 } | 449 } |
| 450 | 450 |
| 451 | 451 |
| 452 bool SkPngCodec::onRewind() { | 452 bool SkPngCodec::onRewind() { |
| 453 // This sets fPng_ptr and fInfo_ptr to NULL. If read_header | 453 // This sets fPng_ptr and fInfo_ptr to nullptr. If read_header |
| 454 // succeeds, they will be repopulated, and if it fails, they will | 454 // succeeds, they will be repopulated, and if it fails, they will |
| 455 // remain NULL. Any future accesses to fPng_ptr and fInfo_ptr will | 455 // remain nullptr. Any future accesses to fPng_ptr and fInfo_ptr will |
| 456 // come through this function which will rewind and again attempt | 456 // come through this function which will rewind and again attempt |
| 457 // to reinitialize them. | 457 // to reinitialize them. |
| 458 this->destroyReadStruct(); | 458 this->destroyReadStruct(); |
| 459 | 459 |
| 460 png_structp png_ptr; | 460 png_structp png_ptr; |
| 461 png_infop info_ptr; | 461 png_infop info_ptr; |
| 462 if (!read_header(this->stream(), &png_ptr, &info_ptr, NULL, NULL)) { | 462 if (!read_header(this->stream(), &png_ptr, &info_ptr, nullptr, nullptr)) { |
| 463 return false; | 463 return false; |
| 464 } | 464 } |
| 465 | 465 |
| 466 fPng_ptr = png_ptr; | 466 fPng_ptr = png_ptr; |
| 467 fInfo_ptr = info_ptr; | 467 fInfo_ptr = info_ptr; |
| 468 return true; | 468 return true; |
| 469 } | 469 } |
| 470 | 470 |
| 471 SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void*
dst, | 471 SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void*
dst, |
| 472 size_t dstRowBytes, const Options& optio
ns, | 472 size_t dstRowBytes, const Options& optio
ns, |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 764 // rewindIfNeeded does not have this flexibility, we need to add another | 764 // rewindIfNeeded does not have this flexibility, we need to add another |
| 765 // layer. | 765 // layer. |
| 766 bool fCanSkipRewind; | 766 bool fCanSkipRewind; |
| 767 | 767 |
| 768 typedef SkScanlineDecoder INHERITED; | 768 typedef SkScanlineDecoder INHERITED; |
| 769 }; | 769 }; |
| 770 | 770 |
| 771 SkScanlineDecoder* SkPngCodec::NewSDFromStream(SkStream* stream) { | 771 SkScanlineDecoder* SkPngCodec::NewSDFromStream(SkStream* stream) { |
| 772 SkAutoTDelete<SkPngCodec> codec (static_cast<SkPngCodec*>(SkPngCodec::NewFro
mStream(stream))); | 772 SkAutoTDelete<SkPngCodec> codec (static_cast<SkPngCodec*>(SkPngCodec::NewFro
mStream(stream))); |
| 773 if (!codec) { | 773 if (!codec) { |
| 774 return NULL; | 774 return nullptr; |
| 775 } | 775 } |
| 776 | 776 |
| 777 codec->fNumberPasses = png_set_interlace_handling(codec->fPng_ptr); | 777 codec->fNumberPasses = png_set_interlace_handling(codec->fPng_ptr); |
| 778 SkASSERT(codec->fNumberPasses != INVALID_NUMBER_PASSES); | 778 SkASSERT(codec->fNumberPasses != INVALID_NUMBER_PASSES); |
| 779 | 779 |
| 780 const SkImageInfo& srcInfo = codec->getInfo(); | 780 const SkImageInfo& srcInfo = codec->getInfo(); |
| 781 if (codec->fNumberPasses > 1) { | 781 if (codec->fNumberPasses > 1) { |
| 782 // interlaced image | 782 // interlaced image |
| 783 return new SkPngInterlacedScanlineDecoder(srcInfo, codec.detach()); | 783 return new SkPngInterlacedScanlineDecoder(srcInfo, codec.detach()); |
| 784 } | 784 } |
| 785 | 785 |
| 786 return new SkPngScanlineDecoder(srcInfo, codec.detach()); | 786 return new SkPngScanlineDecoder(srcInfo, codec.detach()); |
| 787 } | 787 } |
| 788 | 788 |
| OLD | NEW |