| 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" |
| (...skipping 28 matching lines...) Expand all Loading... |
| 39 | 39 |
| 40 #ifndef png_flush_ptr_NULL | 40 #ifndef png_flush_ptr_NULL |
| 41 #define png_flush_ptr_NULL NULL | 41 #define png_flush_ptr_NULL NULL |
| 42 #endif | 42 #endif |
| 43 | 43 |
| 44 /////////////////////////////////////////////////////////////////////////////// | 44 /////////////////////////////////////////////////////////////////////////////// |
| 45 // Callback functions | 45 // Callback functions |
| 46 /////////////////////////////////////////////////////////////////////////////// | 46 /////////////////////////////////////////////////////////////////////////////// |
| 47 | 47 |
| 48 static void sk_error_fn(png_structp png_ptr, png_const_charp msg) { | 48 static void sk_error_fn(png_structp png_ptr, png_const_charp msg) { |
| 49 SkDebugf("------ png error %s\n", msg); | 49 SkCodecPrintf("------ png error %s\n", msg); |
| 50 longjmp(png_jmpbuf(png_ptr), 1); | 50 longjmp(png_jmpbuf(png_ptr), 1); |
| 51 } | 51 } |
| 52 | 52 |
| 53 static void sk_read_fn(png_structp png_ptr, png_bytep data, | 53 static void sk_read_fn(png_structp png_ptr, png_bytep data, |
| 54 png_size_t length) { | 54 png_size_t length) { |
| 55 SkStream* stream = static_cast<SkStream*>(png_get_io_ptr(png_ptr)); | 55 SkStream* stream = static_cast<SkStream*>(png_get_io_ptr(png_ptr)); |
| 56 const size_t bytes = stream->read(data, length); | 56 const size_t bytes = stream->read(data, length); |
| 57 if (bytes != length) { | 57 if (bytes != length) { |
| 58 // FIXME: We want to report the fact that the stream was truncated. | 58 // FIXME: We want to report the fact that the stream was truncated. |
| 59 // One way to do that might be to pass a enum to longjmp so setjmp can | 59 // One way to do that might be to pass a enum to longjmp so setjmp can |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 362 return kPremul_SkAlphaType == dst.alphaType() && | 362 return kPremul_SkAlphaType == dst.alphaType() && |
| 363 kUnpremul_SkAlphaType == src.alphaType(); | 363 kUnpremul_SkAlphaType == src.alphaType(); |
| 364 } | 364 } |
| 365 | 365 |
| 366 SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo, | 366 SkCodec::Result SkPngCodec::initializeSwizzler(const SkImageInfo& requestedInfo, |
| 367 void* dst, size_t rowBytes, | 367 void* dst, size_t rowBytes, |
| 368 const Options& options) { | 368 const Options& options) { |
| 369 // FIXME: Could we use the return value of setjmp to specify the type of | 369 // FIXME: Could we use the return value of setjmp to specify the type of |
| 370 // error? | 370 // error? |
| 371 if (setjmp(png_jmpbuf(fPng_ptr))) { | 371 if (setjmp(png_jmpbuf(fPng_ptr))) { |
| 372 SkDebugf("setjmp long jump!\n"); | 372 SkCodecPrintf("setjmp long jump!\n"); |
| 373 return kInvalidInput; | 373 return kInvalidInput; |
| 374 } | 374 } |
| 375 | 375 |
| 376 // FIXME: We already retrieved this information. Store it in SkPngCodec? | 376 // FIXME: We already retrieved this information. Store it in SkPngCodec? |
| 377 png_uint_32 origWidth, origHeight; | 377 png_uint_32 origWidth, origHeight; |
| 378 int bitDepth, pngColorType, interlaceType; | 378 int bitDepth, pngColorType, interlaceType; |
| 379 png_get_IHDR(fPng_ptr, fInfo_ptr, &origWidth, &origHeight, &bitDepth, | 379 png_get_IHDR(fPng_ptr, fInfo_ptr, &origWidth, &origHeight, &bitDepth, |
| 380 &pngColorType, &interlaceType, int_p_NULL, int_p_NULL); | 380 &pngColorType, &interlaceType, int_p_NULL, int_p_NULL); |
| 381 | 381 |
| 382 fNumberPasses = (interlaceType != PNG_INTERLACE_NONE) ? | 382 fNumberPasses = (interlaceType != PNG_INTERLACE_NONE) ? |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 429 | 429 |
| 430 const Result result = this->initializeSwizzler(requestedInfo, dst, rowBytes, | 430 const Result result = this->initializeSwizzler(requestedInfo, dst, rowBytes, |
| 431 options); | 431 options); |
| 432 if (result != kSuccess) { | 432 if (result != kSuccess) { |
| 433 return result; | 433 return result; |
| 434 } | 434 } |
| 435 | 435 |
| 436 // FIXME: Could we use the return value of setjmp to specify the type of | 436 // FIXME: Could we use the return value of setjmp to specify the type of |
| 437 // error? | 437 // error? |
| 438 if (setjmp(png_jmpbuf(fPng_ptr))) { | 438 if (setjmp(png_jmpbuf(fPng_ptr))) { |
| 439 SkDebugf("setjmp long jump!\n"); | 439 SkCodecPrintf("setjmp long jump!\n"); |
| 440 return kInvalidInput; | 440 return kInvalidInput; |
| 441 } | 441 } |
| 442 | 442 |
| 443 SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES); | 443 SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES); |
| 444 SkAutoMalloc storage; | 444 SkAutoMalloc storage; |
| 445 if (fNumberPasses > 1) { | 445 if (fNumberPasses > 1) { |
| 446 const int width = requestedInfo.width(); | 446 const int width = requestedInfo.width(); |
| 447 const int height = requestedInfo.height(); | 447 const int height = requestedInfo.height(); |
| 448 const int bpp = SkSwizzler::BytesPerPixel(fSrcConfig); | 448 const int bpp = SkSwizzler::BytesPerPixel(fSrcConfig); |
| 449 const size_t rowBytes = width * bpp; | 449 const size_t rowBytes = width * bpp; |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 : INHERITED(dstInfo) | 498 : INHERITED(dstInfo) |
| 499 , fCodec(codec) | 499 , fCodec(codec) |
| 500 , fHasAlpha(false) | 500 , fHasAlpha(false) |
| 501 { | 501 { |
| 502 fStorage.reset(dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSrcC
onfig)); | 502 fStorage.reset(dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSrcC
onfig)); |
| 503 fSrcRow = static_cast<uint8_t*>(fStorage.get()); | 503 fSrcRow = static_cast<uint8_t*>(fStorage.get()); |
| 504 } | 504 } |
| 505 | 505 |
| 506 SkImageGenerator::Result onGetScanlines(void* dst, int count, size_t rowByte
s) override { | 506 SkImageGenerator::Result onGetScanlines(void* dst, int count, size_t rowByte
s) override { |
| 507 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { | 507 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { |
| 508 SkDebugf("setjmp long jump!\n"); | 508 SkCodecPrintf("setjmp long jump!\n"); |
| 509 return SkImageGenerator::kInvalidInput; | 509 return SkImageGenerator::kInvalidInput; |
| 510 } | 510 } |
| 511 | 511 |
| 512 for (int i = 0; i < count; i++) { | 512 for (int i = 0; i < count; i++) { |
| 513 png_read_rows(fCodec->fPng_ptr, &fSrcRow, png_bytepp_NULL, 1); | 513 png_read_rows(fCodec->fPng_ptr, &fSrcRow, png_bytepp_NULL, 1); |
| 514 fCodec->fSwizzler->setDstRow(dst); | 514 fCodec->fSwizzler->setDstRow(dst); |
| 515 fHasAlpha |= !SkSwizzler::IsOpaque(fCodec->fSwizzler->next(fSrcRow))
; | 515 fHasAlpha |= !SkSwizzler::IsOpaque(fCodec->fSwizzler->next(fSrcRow))
; |
| 516 dst = SkTAddOffset<void>(dst, rowBytes); | 516 dst = SkTAddOffset<void>(dst, rowBytes); |
| 517 } | 517 } |
| 518 return SkImageGenerator::kSuccess; | 518 return SkImageGenerator::kSuccess; |
| 519 } | 519 } |
| 520 | 520 |
| 521 SkImageGenerator::Result onSkipScanlines(int count) override { | 521 SkImageGenerator::Result onSkipScanlines(int count) override { |
| 522 // FIXME: Could we use the return value of setjmp to specify the type of | 522 // FIXME: Could we use the return value of setjmp to specify the type of |
| 523 // error? | 523 // error? |
| 524 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { | 524 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { |
| 525 SkDebugf("setjmp long jump!\n"); | 525 SkCodecPrintf("setjmp long jump!\n"); |
| 526 return SkImageGenerator::kInvalidInput; | 526 return SkImageGenerator::kInvalidInput; |
| 527 } | 527 } |
| 528 | 528 |
| 529 png_read_rows(fCodec->fPng_ptr, png_bytepp_NULL, png_bytepp_NULL, count)
; | 529 png_read_rows(fCodec->fPng_ptr, png_bytepp_NULL, png_bytepp_NULL, count)
; |
| 530 return SkImageGenerator::kSuccess; | 530 return SkImageGenerator::kSuccess; |
| 531 } | 531 } |
| 532 | 532 |
| 533 void onFinish() override { | 533 void onFinish() override { |
| 534 fCodec->finish(); | 534 fCodec->finish(); |
| 535 } | 535 } |
| 536 | 536 |
| 537 bool onReallyHasAlpha() const override { return fHasAlpha; } | 537 bool onReallyHasAlpha() const override { return fHasAlpha; } |
| 538 | 538 |
| 539 private: | 539 private: |
| 540 SkPngCodec* fCodec; // Unowned. | 540 SkPngCodec* fCodec; // Unowned. |
| 541 bool fHasAlpha; | 541 bool fHasAlpha; |
| 542 SkAutoMalloc fStorage; | 542 SkAutoMalloc fStorage; |
| 543 uint8_t* fSrcRow; | 543 uint8_t* fSrcRow; |
| 544 | 544 |
| 545 typedef SkScanlineDecoder INHERITED; | 545 typedef SkScanlineDecoder INHERITED; |
| 546 }; | 546 }; |
| 547 | 547 |
| 548 SkScanlineDecoder* SkPngCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo)
{ | 548 SkScanlineDecoder* SkPngCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo)
{ |
| 549 // Check to see if scaling was requested. | 549 // Check to see if scaling was requested. |
| 550 if (dstInfo.dimensions() != this->getInfo().dimensions()) { | 550 if (dstInfo.dimensions() != this->getInfo().dimensions()) { |
| 551 return NULL; | 551 return NULL; |
| 552 } | 552 } |
| 553 | 553 |
| 554 if (!conversion_possible(dstInfo, this->getInfo())) { | 554 if (!conversion_possible(dstInfo, this->getInfo())) { |
| 555 SkDebugf("no conversion possible\n"); | 555 SkCodecPrintf("no conversion possible\n"); |
| 556 return NULL; | 556 return NULL; |
| 557 } | 557 } |
| 558 | 558 |
| 559 // Note: We set dst to NULL since we do not know it yet. rowBytes is not nee
ded, | 559 // Note: We set dst to NULL since we do not know it yet. rowBytes is not nee
ded, |
| 560 // since we'll be manually updating the dstRow, but the SkSwizzler requires
it to | 560 // since we'll be manually updating the dstRow, but the SkSwizzler requires
it to |
| 561 // be at least dstInfo.minRowBytes. | 561 // be at least dstInfo.minRowBytes. |
| 562 Options opts; | 562 Options opts; |
| 563 // FIXME: Pass this in to getScanlineDecoder? | 563 // FIXME: Pass this in to getScanlineDecoder? |
| 564 opts.fZeroInitialized = kNo_ZeroInitialized; | 564 opts.fZeroInitialized = kNo_ZeroInitialized; |
| 565 if (this->initializeSwizzler(dstInfo, NULL, dstInfo.minRowBytes(), opts) !=
kSuccess) { | 565 if (this->initializeSwizzler(dstInfo, NULL, dstInfo.minRowBytes(), opts) !=
kSuccess) { |
| 566 SkDebugf("failed to initialize the swizzler.\n"); | 566 SkCodecPrintf("failed to initialize the swizzler.\n"); |
| 567 return NULL; | 567 return NULL; |
| 568 } | 568 } |
| 569 | 569 |
| 570 SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES); | 570 SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES); |
| 571 if (fNumberPasses > 1) { | 571 if (fNumberPasses > 1) { |
| 572 // We cannot efficiently do scanline decoding. | 572 // We cannot efficiently do scanline decoding. |
| 573 return NULL; | 573 return NULL; |
| 574 } | 574 } |
| 575 | 575 |
| 576 return SkNEW_ARGS(SkPngScanlineDecoder, (dstInfo, this)); | 576 return SkNEW_ARGS(SkPngScanlineDecoder, (dstInfo, this)); |
| 577 } | 577 } |
| 578 | 578 |
| OLD | NEW |