diff options
-rw-r--r-- | BUILD.gn | 15 | ||||
-rw-r--r-- | core/fxcodec/codec/ccodec_progressivedecoder.h | 61 | ||||
-rw-r--r-- | core/fxcodec/codec/fx_codec_progress.cpp | 1571 | ||||
-rw-r--r-- | core/fxcodec/fx_codec_def.h | 3 | ||||
-rw-r--r-- | testing/libfuzzer/BUILD.gn | 16 | ||||
-rw-r--r-- | xfa/fxfa/cxfa_ffwidget.cpp | 2 | ||||
-rw-r--r-- | xfa/fxfa/parser/cxfa_node.cpp | 2 |
7 files changed, 855 insertions, 815 deletions
@@ -284,10 +284,7 @@ jumbo_static_library("image_diff") { "testing/image_diff/image_diff_png.h", ] configs += [ ":pdfium_core_config" ] - deps = [] - if (!pdf_enable_xfa) { - deps += [ "third_party:png" ] - } + deps = [ "third_party:png" ] } # Targets below this are only visible within this file (and to the @@ -791,8 +788,6 @@ jumbo_static_library("fxcodec") { "core/fxcodec/codec/ccodec_bmpmodule.h", "core/fxcodec/codec/ccodec_gifmodule.cpp", "core/fxcodec/codec/ccodec_gifmodule.h", - "core/fxcodec/codec/ccodec_pngmodule.cpp", - "core/fxcodec/codec/ccodec_pngmodule.h", "core/fxcodec/codec/ccodec_progressivedecoder.h", "core/fxcodec/codec/fx_codec_progress.cpp", "core/fxcodec/gif/cfx_gif.cpp", @@ -802,7 +797,13 @@ jumbo_static_library("fxcodec") { "core/fxcodec/gif/cfx_lzwdecompressor.cpp", "core/fxcodec/gif/cfx_lzwdecompressor.h", ] - deps += [ "third_party:png" ] + if (pdf_enable_xfa_png) { + sources += [ + "core/fxcodec/codec/ccodec_pngmodule.cpp", + "core/fxcodec/codec/ccodec_pngmodule.h", + ] + deps += [ "third_party:png" ] + } if (pdf_enable_xfa_tiff) { sources += [ "core/fxcodec/codec/ccodec_tiffmodule.cpp", diff --git a/core/fxcodec/codec/ccodec_progressivedecoder.h b/core/fxcodec/codec/ccodec_progressivedecoder.h index 9a0136c872..476a7c1b4a 100644 --- a/core/fxcodec/codec/ccodec_progressivedecoder.h +++ b/core/fxcodec/codec/ccodec_progressivedecoder.h @@ -14,7 +14,6 @@ #include "core/fxcodec/codec/ccodec_bmpmodule.h" #include "core/fxcodec/codec/ccodec_gifmodule.h" #include "core/fxcodec/codec/ccodec_jpegmodule.h" -#include "core/fxcodec/codec/ccodec_pngmodule.h" #include "core/fxcodec/fx_codec_def.h" #include "core/fxcrt/fx_system.h" #include "core/fxcrt/retain_ptr.h" @@ -22,6 +21,10 @@ #include "core/fxge/dib/cfx_dibitmap.h" #include "core/fxge/fx_dib.h" +#ifdef PDF_ENABLE_XFA_PNG +#include "core/fxcodec/codec/ccodec_pngmodule.h" +#endif // PDF_ENABLE_XFA_PNG + #ifdef PDF_ENABLE_XFA_TIFF #include "core/fxcodec/codec/ccodec_tiffmodule.h" #endif // PDF_ENABLE_XFA_TIFF @@ -30,9 +33,14 @@ class CCodec_ModuleMgr; class CFX_DIBAttribute; class IFX_SeekableReadStream; +class CCodec_Dummy {}; // Placeholder to work around C++ syntax issues + class CCodec_ProgressiveDecoder : public CCodec_BmpModule::Delegate, public CCodec_GifModule::Delegate, - public CCodec_PngModule::Delegate { +#ifdef PDF_ENABLE_XFA_PNG + public CCodec_PngModule::Delegate, +#endif // PDF_ENABLE_XFA_PNG + public CCodec_Dummy { public: enum FXCodec_Format { FXCodec_Invalid = 0, @@ -126,6 +134,7 @@ class CCodec_ProgressiveDecoder : public CCodec_BmpModule::Delegate, std::vector<uint8_t> m_pWeightTables; }; +#ifdef PDF_ENABLE_XFA_PNG // CCodec_PngModule::Delegate bool PngReadHeader(int width, int height, @@ -135,6 +144,7 @@ class CCodec_ProgressiveDecoder : public CCodec_BmpModule::Delegate, double* gamma) override; bool PngAskScanlineBuf(int line, uint8_t** pSrcBuf) override; void PngFillScanlineBufCompleted(int pass, int line) override; +#endif // PDF_ENABLE_XFA_PNG // CCodec_GifModule::Delegate void GifRecordCurrentPosition(uint32_t& cur_pos) override; @@ -157,24 +167,43 @@ class CCodec_ProgressiveDecoder : public CCodec_BmpModule::Delegate, private: bool BmpReadMoreData(CCodec_BmpModule* pBmpModule, FXCODEC_STATUS& err_status); + bool BmpDetectImageType(CFX_DIBAttribute* pAttribute, uint32_t size); + FXCODEC_STATUS BmpStartDecode(const RetainPtr<CFX_DIBitmap>& pDIBitmap); + FXCODEC_STATUS BmpContinueDecode(); + bool GifReadMoreData(CCodec_GifModule* pGifModule, FXCODEC_STATUS& err_status); + bool GifDetectImageType(CFX_DIBAttribute* pAttribute, uint32_t size); + FXCODEC_STATUS GifStartDecode(const RetainPtr<CFX_DIBitmap>& pDIBitmap); + FXCODEC_STATUS GifContinueDecode(); + void GifDoubleLineResampleVert(const RetainPtr<CFX_DIBitmap>& pDeviceBitmap, + double scale_y, + int dest_row); + bool JpegReadMoreData(CCodec_JpegModule* pJpegModule, FXCODEC_STATUS& err_status); + bool JpegDetectImageType(CFX_DIBAttribute* pAttribute, uint32_t size); + FXCODEC_STATUS JpegStartDecode(const RetainPtr<CFX_DIBitmap>& pDIBitmap); + FXCODEC_STATUS JpegContinueDecode(); + +#ifdef PDF_ENABLE_XFA_PNG void PngOneOneMapResampleHorz(const RetainPtr<CFX_DIBitmap>& pDeviceBitmap, int32_t dest_line, uint8_t* src_scan, FXCodec_Format src_format); - bool DetectImageType(FXCODEC_IMAGE_TYPE imageType, - CFX_DIBAttribute* pAttribute); - bool BmpDetectImageType(CFX_DIBAttribute* pAttribute, uint32_t size); - bool JpegDetectImageType(CFX_DIBAttribute* pAttribute, uint32_t size); bool PngDetectImageType(CFX_DIBAttribute* pAttribute, uint32_t size); - bool GifDetectImageType(CFX_DIBAttribute* pAttribute, uint32_t size); + FXCODEC_STATUS PngStartDecode(const RetainPtr<CFX_DIBitmap>& pDIBitmap); + FXCODEC_STATUS PngContinueDecode(); +#endif // PDF_ENABLE_XFA_PNG + #ifdef PDF_ENABLE_XFA_TIFF bool TiffDetectImageType(CFX_DIBAttribute* pAttribute, uint32_t size); + FXCODEC_STATUS TiffContinueDecode(); #endif // PDF_ENABLE_XFA_TIFF + bool DetectImageType(FXCODEC_IMAGE_TYPE imageType, + CFX_DIBAttribute* pAttribute); + void GetDownScale(int& down_scale); void GetTransMethod(FXDIB_Format dest_format, FXCodec_Format src_format); @@ -192,28 +221,14 @@ class CCodec_ProgressiveDecoder : public CCodec_BmpModule::Delegate, void ResampleVertBT(const RetainPtr<CFX_DIBitmap>& pDeviceBitmap, double scale_y, int dest_row); - void GifDoubleLineResampleVert(const RetainPtr<CFX_DIBitmap>& pDeviceBitmap, - double scale_y, - int dest_row); - - FXCODEC_STATUS JpegStartDecode(const RetainPtr<CFX_DIBitmap>& pDIBitmap); - FXCODEC_STATUS PngStartDecode(const RetainPtr<CFX_DIBitmap>& pDIBitmap); - FXCODEC_STATUS GifStartDecode(const RetainPtr<CFX_DIBitmap>& pDIBitmap); - FXCODEC_STATUS BmpStartDecode(const RetainPtr<CFX_DIBitmap>& pDIBitmap); - - FXCODEC_STATUS JpegContinueDecode(); - FXCODEC_STATUS PngContinueDecode(); - FXCODEC_STATUS GifContinueDecode(); - FXCODEC_STATUS BmpContinueDecode(); -#ifdef PDF_ENABLE_XFA_TIFF - FXCODEC_STATUS TiffContinueDecode(); -#endif // PDF_ENABLE_XFA_TIFF RetainPtr<IFX_SeekableReadStream> m_pFile; RetainPtr<CFX_DIBitmap> m_pDeviceBitmap; UnownedPtr<CCodec_ModuleMgr> m_pCodecMgr; std::unique_ptr<CCodec_JpegModule::Context> m_pJpegContext; +#ifdef PDF_ENABLE_XFA_PNG std::unique_ptr<CCodec_PngModule::Context> m_pPngContext; +#endif // PDF_ENABLE_XFA_PNG std::unique_ptr<CCodec_GifModule::Context> m_pGifContext; std::unique_ptr<CCodec_BmpModule::Context> m_pBmpContext; #ifdef PDF_ENABLE_XFA_TIFF diff --git a/core/fxcodec/codec/fx_codec_progress.cpp b/core/fxcodec/codec/fx_codec_progress.cpp index e606c414bb..bfd60acd0e 100644 --- a/core/fxcodec/codec/fx_codec_progress.cpp +++ b/core/fxcodec/codec/fx_codec_progress.cpp @@ -23,11 +23,13 @@ namespace { +#ifdef PDF_ENABLE_XFA_PNG #if _FX_OS_ == _FX_OS_MACOSX_ const double kPngGamma = 1.7; #else // _FX_OS_ == _FX_OS_MACOSX_ const double kPngGamma = 2.2; #endif // _FX_OS_ == _FX_OS_MACOSX_ +#endif // PDF_ENABLE_XFA_PNG void RGB2BGR(uint8_t* buffer, int width = 1) { if (buffer && width > 0) { @@ -288,43 +290,7 @@ CCodec_ProgressiveDecoder::~CCodec_ProgressiveDecoder() { FX_Free(m_pSrcPalette); } -bool CCodec_ProgressiveDecoder::JpegReadMoreData(CCodec_JpegModule* pJpegModule, - FXCODEC_STATUS& err_status) { - uint32_t dwSize = (uint32_t)m_pFile->GetSize(); - if (dwSize <= m_offSet) { - return false; - } - dwSize = dwSize - m_offSet; - uint32_t dwAvail = pJpegModule->GetAvailInput(m_pJpegContext.get(), nullptr); - if (dwAvail == m_SrcSize) { - if (dwSize > FXCODEC_BLOCK_SIZE) { - dwSize = FXCODEC_BLOCK_SIZE; - } - m_SrcSize = (dwSize + dwAvail + FXCODEC_BLOCK_SIZE - 1) / - FXCODEC_BLOCK_SIZE * FXCODEC_BLOCK_SIZE; - m_pSrcBuf = FX_TryRealloc(uint8_t, m_pSrcBuf, m_SrcSize); - if (!m_pSrcBuf) { - err_status = FXCODEC_STATUS_ERR_MEMORY; - return false; - } - } else { - uint32_t dwConsume = m_SrcSize - dwAvail; - if (dwAvail) { - memmove(m_pSrcBuf, m_pSrcBuf + dwConsume, dwAvail); - } - if (dwSize > dwConsume) { - dwSize = dwConsume; - } - } - if (!m_pFile->ReadBlock(m_pSrcBuf + dwAvail, m_offSet, dwSize)) { - err_status = FXCODEC_STATUS_ERR_READ; - return false; - } - m_offSet += dwSize; - pJpegModule->Input(m_pJpegContext.get(), m_pSrcBuf, dwSize + dwAvail); - return true; -} - +#ifdef PDF_ENABLE_XFA_PNG bool CCodec_ProgressiveDecoder::PngReadHeader(int width, int height, int bpc, @@ -455,82 +421,6 @@ bool CCodec_ProgressiveDecoder::PngAskScanlineBuf(int line, uint8_t** pSrcBuf) { return true; } -void CCodec_ProgressiveDecoder::PngOneOneMapResampleHorz( - const RetainPtr<CFX_DIBitmap>& pDeviceBitmap, - int32_t dest_line, - uint8_t* src_scan, - FXCodec_Format src_format) { - uint8_t* dest_scan = (uint8_t*)pDeviceBitmap->GetScanline(dest_line); - int32_t src_Bpp = (m_SrcFormat & 0xff) >> 3; - int32_t dest_Bpp = pDeviceBitmap->GetBPP() >> 3; - int32_t src_left = m_clipBox.left; - int32_t dest_left = m_startX; - src_scan += src_left * src_Bpp; - dest_scan += dest_left * dest_Bpp; - for (int32_t dest_col = 0; dest_col < m_sizeX; dest_col++) { - PixelWeight* pPixelWeights = m_WeightHorzOO.GetPixelWeight(dest_col); - switch (pDeviceBitmap->GetFormat()) { - case FXDIB_1bppMask: - case FXDIB_1bppRgb: - NOTREACHED(); - return; - case FXDIB_8bppMask: - case FXDIB_8bppRgb: { - if (pDeviceBitmap->GetPalette()) { - return; - } - uint32_t dest_g = 0; - dest_g += - pPixelWeights->m_Weights[0] * src_scan[pPixelWeights->m_SrcStart]; - dest_g += - pPixelWeights->m_Weights[1] * src_scan[pPixelWeights->m_SrcEnd]; - *dest_scan++ = (uint8_t)(dest_g >> 16); - } break; - case FXDIB_Rgb: - case FXDIB_Rgb32: { - uint32_t dest_b = 0; - uint32_t dest_g = 0; - uint32_t dest_r = 0; - const uint8_t* p = src_scan; - p = src_scan + pPixelWeights->m_SrcStart * src_Bpp; - dest_b += pPixelWeights->m_Weights[0] * (*p++); - dest_g += pPixelWeights->m_Weights[0] * (*p++); - dest_r += pPixelWeights->m_Weights[0] * (*p); - p = src_scan + pPixelWeights->m_SrcEnd * src_Bpp; - dest_b += pPixelWeights->m_Weights[1] * (*p++); - dest_g += pPixelWeights->m_Weights[1] * (*p++); - dest_r += pPixelWeights->m_Weights[1] * (*p); - *dest_scan++ = (uint8_t)((dest_b) >> 16); - *dest_scan++ = (uint8_t)((dest_g) >> 16); - *dest_scan++ = (uint8_t)((dest_r) >> 16); - dest_scan += dest_Bpp - 3; - } break; - case FXDIB_Argb: { - uint32_t dest_a = 0; - uint32_t dest_b = 0; - uint32_t dest_g = 0; - uint32_t dest_r = 0; - const uint8_t* p = src_scan; - p = src_scan + pPixelWeights->m_SrcStart * src_Bpp; - dest_b += pPixelWeights->m_Weights[0] * (*p++); - dest_g += pPixelWeights->m_Weights[0] * (*p++); - dest_r += pPixelWeights->m_Weights[0] * (*p++); - dest_a += pPixelWeights->m_Weights[0] * (*p); - p = src_scan + pPixelWeights->m_SrcEnd * src_Bpp; - dest_b += pPixelWeights->m_Weights[1] * (*p++); - dest_g += pPixelWeights->m_Weights[1] * (*p++); - dest_r += pPixelWeights->m_Weights[1] * (*p++); - dest_a += pPixelWeights->m_Weights[1] * (*p); - *dest_scan++ = (uint8_t)((dest_b) >> 16); - *dest_scan++ = (uint8_t)((dest_g) >> 16); - *dest_scan++ = (uint8_t)((dest_r) >> 16); - *dest_scan++ = (uint8_t)((dest_a) >> 16); - } break; - default: - return; - } - } -} void CCodec_ProgressiveDecoder::PngFillScanlineBufCompleted(int pass, int line) { @@ -558,50 +448,7 @@ void CCodec_ProgressiveDecoder::PngFillScanlineBufCompleted(int pass, } } } - -bool CCodec_ProgressiveDecoder::GifReadMoreData(CCodec_GifModule* pGifModule, - FXCODEC_STATUS& err_status) { - if (static_cast<uint32_t>(m_pFile->GetSize()) <= m_offSet) - return false; - - uint32_t dwFileRemaining = m_pFile->GetSize() - m_offSet; - uint32_t dwUnusedBuffer = - !m_InvalidateGifBuffer - ? pGifModule->GetAvailInput(m_pGifContext.get(), nullptr) - : 0; - uint32_t dwAmountToFetchFromFile = dwFileRemaining; - if (dwUnusedBuffer == m_SrcSize) { - if (dwFileRemaining > FXCODEC_BLOCK_SIZE) - dwAmountToFetchFromFile = FXCODEC_BLOCK_SIZE; - m_SrcSize = std::min( - (dwAmountToFetchFromFile + dwUnusedBuffer + FXCODEC_BLOCK_SIZE - 1) / - FXCODEC_BLOCK_SIZE * FXCODEC_BLOCK_SIZE, - static_cast<uint32_t>(m_pFile->GetSize())); - m_pSrcBuf = FX_TryRealloc(uint8_t, m_pSrcBuf, m_SrcSize); - if (!m_pSrcBuf) { - err_status = FXCODEC_STATUS_ERR_MEMORY; - return false; - } - } else { - uint32_t dwConsumed = m_SrcSize - dwUnusedBuffer; - if (dwUnusedBuffer) - memmove(m_pSrcBuf, m_pSrcBuf + dwConsumed, dwUnusedBuffer); - if (dwFileRemaining > dwConsumed) - dwAmountToFetchFromFile = dwConsumed; - } - - if (!m_pFile->ReadBlock(m_pSrcBuf + dwUnusedBuffer, m_offSet, - dwAmountToFetchFromFile)) { - err_status = FXCODEC_STATUS_ERR_READ; - return false; - } - - m_offSet += dwAmountToFetchFromFile; - pGifModule->Input(m_pGifContext.get(), m_pSrcBuf, - dwAmountToFetchFromFile + dwUnusedBuffer); - m_InvalidateGifBuffer = false; - return true; -} +#endif // PDF_ENABLE_XFA_PNG void CCodec_ProgressiveDecoder::GifRecordCurrentPosition(uint32_t& cur_pos) { uint32_t remain_size = @@ -762,135 +609,6 @@ void CCodec_ProgressiveDecoder::GifReadScanline(int32_t row_num, GifDoubleLineResampleVert(pDIBitmap, scale_y, dest_row); } -void CCodec_ProgressiveDecoder::GifDoubleLineResampleVert( - const RetainPtr<CFX_DIBitmap>& pDeviceBitmap, - double scale_y, - int dest_row) { - int dest_Bpp = pDeviceBitmap->GetBPP() >> 3; - uint32_t dest_ScanOffet = m_startX * dest_Bpp; - int dest_top = m_startY; - pdfium::base::CheckedNumeric<double> scale_y2 = scale_y; - scale_y2 *= 2; - pdfium::base::CheckedNumeric<int> check_dest_row_1 = dest_row; - check_dest_row_1 -= scale_y2.ValueOrDie(); - int dest_row_1 = check_dest_row_1.ValueOrDie(); - dest_row_1 = std::max(dest_row_1, dest_top); - for (; dest_row_1 < dest_row; dest_row_1++) { - uint8_t* scan_des = - (uint8_t*)pDeviceBitmap->GetScanline(dest_row_1) + dest_ScanOffet; - PixelWeight* pWeight = m_WeightVert.GetPixelWeight(dest_row_1 - dest_top); - const uint8_t* scan_src1 = - pDeviceBitmap->GetScanline(pWeight->m_SrcStart + dest_top) + - dest_ScanOffet; - const uint8_t* scan_src2 = - pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + dest_top) + - dest_ScanOffet; - for (int dest_col = 0; dest_col < m_sizeX; dest_col++) { - switch (pDeviceBitmap->GetFormat()) { - case FXDIB_Invalid: - case FXDIB_1bppMask: - case FXDIB_1bppRgb: - return; - case FXDIB_8bppMask: - case FXDIB_8bppRgb: { - if (pDeviceBitmap->GetPalette()) { - return; - } - int dest_g = 0; - dest_g += pWeight->m_Weights[0] * (*scan_src1++); - dest_g += pWeight->m_Weights[1] * (*scan_src2++); - *scan_des++ = (uint8_t)(dest_g >> 16); - } break; - case FXDIB_Rgb: - case FXDIB_Rgb32: { - uint32_t dest_b = 0; - uint32_t dest_g = 0; - uint32_t dest_r = 0; - dest_b += pWeight->m_Weights[0] * (*scan_src1++); - dest_g += pWeight->m_Weights[0] * (*scan_src1++); - dest_r += pWeight->m_Weights[0] * (*scan_src1++); - scan_src1 += dest_Bpp - 3; - dest_b += pWeight->m_Weights[1] * (*scan_src2++); - dest_g += pWeight->m_Weights[1] * (*scan_src2++); - dest_r += pWeight->m_Weights[1] * (*scan_src2++); - scan_src2 += dest_Bpp - 3; - *scan_des++ = (uint8_t)((dest_b) >> 16); - *scan_des++ = (uint8_t)((dest_g) >> 16); - *scan_des++ = (uint8_t)((dest_r) >> 16); - scan_des += dest_Bpp - 3; - } break; - case FXDIB_Argb: { - uint32_t dest_a = 0; - uint32_t dest_b = 0; - uint32_t dest_g = 0; - uint32_t dest_r = 0; - dest_b += pWeight->m_Weights[0] * (*scan_src1++); - dest_g += pWeight->m_Weights[0] * (*scan_src1++); - dest_r += pWeight->m_Weights[0] * (*scan_src1++); - dest_a += pWeight->m_Weights[0] * (*scan_src1++); - dest_b += pWeight->m_Weights[1] * (*scan_src2++); - dest_g += pWeight->m_Weights[1] * (*scan_src2++); - dest_r += pWeight->m_Weights[1] * (*scan_src2++); - dest_a += pWeight->m_Weights[1] * (*scan_src2++); - *scan_des++ = (uint8_t)((dest_b) >> 16); - *scan_des++ = (uint8_t)((dest_g) >> 16); - *scan_des++ = (uint8_t)((dest_r) >> 16); - *scan_des++ = (uint8_t)((dest_a) >> 16); - } break; - default: - return; - } - } - } - int dest_bottom = dest_top + m_sizeY - 1; - if (dest_row + (int)(2 * scale_y) >= dest_bottom && - dest_row + (int)scale_y < dest_bottom) { - GifDoubleLineResampleVert(pDeviceBitmap, scale_y, dest_row + (int)scale_y); - } -} - -bool CCodec_ProgressiveDecoder::BmpReadMoreData(CCodec_BmpModule* pBmpModule, - FXCODEC_STATUS& err_status) { - uint32_t dwSize = (uint32_t)m_pFile->GetSize(); - if (dwSize <= m_offSet) - return false; - - dwSize = dwSize - m_offSet; - FX_SAFE_UINT32 avail_input = - pBmpModule->GetAvailInput(m_pBmpContext.get(), nullptr); - if (!avail_input.IsValid()) - return false; - - uint32_t dwAvail = avail_input.ValueOrDie(); - if (dwAvail == m_SrcSize) { - if (dwSize > FXCODEC_BLOCK_SIZE) { - dwSize = FXCODEC_BLOCK_SIZE; - } - m_SrcSize = (dwSize + dwAvail + FXCODEC_BLOCK_SIZE - 1) / - FXCODEC_BLOCK_SIZE * FXCODEC_BLOCK_SIZE; - m_pSrcBuf = FX_TryRealloc(uint8_t, m_pSrcBuf, m_SrcSize); - if (!m_pSrcBuf) { - err_status = FXCODEC_STATUS_ERR_MEMORY; - return false; - } - } else { - uint32_t dwConsume = m_SrcSize - dwAvail; - if (dwAvail) { - memmove(m_pSrcBuf, m_pSrcBuf + dwConsume, dwAvail); - } - if (dwSize > dwConsume) { - dwSize = dwConsume; - } - } - if (!m_pFile->ReadBlock(m_pSrcBuf + dwAvail, m_offSet, dwSize)) { - err_status = FXCODEC_STATUS_ERR_READ; - return false; - } - m_offSet += dwSize; - pBmpModule->Input(m_pBmpContext.get(), m_pSrcBuf, dwSize + dwAvail); - return true; -} - bool CCodec_ProgressiveDecoder::BmpInputImagePositionBuf(uint32_t rcd_pos) { m_offSet = rcd_pos; FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR; @@ -1021,36 +739,6 @@ void CCodec_ProgressiveDecoder::ResampleVertBT( } } -bool CCodec_ProgressiveDecoder::DetectImageType(FXCODEC_IMAGE_TYPE imageType, - CFX_DIBAttribute* pAttribute) { - m_offSet = 0; - uint32_t size = (uint32_t)m_pFile->GetSize(); - if (size > FXCODEC_BLOCK_SIZE) { - size = FXCODEC_BLOCK_SIZE; - } - FX_Free(m_pSrcBuf); - m_pSrcBuf = FX_Alloc(uint8_t, size); - memset(m_pSrcBuf, 0, size); - m_SrcSize = size; - switch (imageType) { - case FXCODEC_IMAGE_BMP: - return BmpDetectImageType(pAttribute, size); - case FXCODEC_IMAGE_JPG: - return JpegDetectImageType(pAttribute, size); - case FXCODEC_IMAGE_PNG: - return PngDetectImageType(pAttribute, size); - case FXCODEC_IMAGE_GIF: - return GifDetectImageType(pAttribute, size); -#ifdef PDF_ENABLE_XFA_TIFF - case FXCODEC_IMAGE_TIFF: - return TiffDetectImageType(pAttribute, size); -#endif // PDF_ENABLE_XFA_TIFF - default: - m_status = FXCODEC_STATUS_ERR_FORMAT; - return false; - } -} - bool CCodec_ProgressiveDecoder::BmpDetectImageType(CFX_DIBAttribute* pAttribute, uint32_t size) { CCodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); @@ -1141,6 +829,366 @@ bool CCodec_ProgressiveDecoder::BmpDetectImageType(CFX_DIBAttribute* pAttribute, return true; } +bool CCodec_ProgressiveDecoder::BmpReadMoreData(CCodec_BmpModule* pBmpModule, + FXCODEC_STATUS& err_status) { + uint32_t dwSize = (uint32_t)m_pFile->GetSize(); + if (dwSize <= m_offSet) + return false; + + dwSize = dwSize - m_offSet; + FX_SAFE_UINT32 avail_input = + pBmpModule->GetAvailInput(m_pBmpContext.get(), nullptr); + if (!avail_input.IsValid()) + return false; + + uint32_t dwAvail = avail_input.ValueOrDie(); + if (dwAvail == m_SrcSize) { + if (dwSize > FXCODEC_BLOCK_SIZE) { + dwSize = FXCODEC_BLOCK_SIZE; + } + m_SrcSize = (dwSize + dwAvail + FXCODEC_BLOCK_SIZE - 1) / + FXCODEC_BLOCK_SIZE * FXCODEC_BLOCK_SIZE; + m_pSrcBuf = FX_TryRealloc(uint8_t, m_pSrcBuf, m_SrcSize); + if (!m_pSrcBuf) { + err_status = FXCODEC_STATUS_ERR_MEMORY; + return false; + } + } else { + uint32_t dwConsume = m_SrcSize - dwAvail; + if (dwAvail) { + memmove(m_pSrcBuf, m_pSrcBuf + dwConsume, dwAvail); + } + if (dwSize > dwConsume) { + dwSize = dwConsume; + } + } + if (!m_pFile->ReadBlock(m_pSrcBuf + dwAvail, m_offSet, dwSize)) { + err_status = FXCODEC_STATUS_ERR_READ; + return false; + } + m_offSet += dwSize; + pBmpModule->Input(m_pBmpContext.get(), m_pSrcBuf, dwSize + dwAvail); + return true; +} + +FXCODEC_STATUS CCodec_ProgressiveDecoder::BmpStartDecode( + const RetainPtr<CFX_DIBitmap>& pDIBitmap) { + CCodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); + if (!pBmpModule) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); + m_ScanlineSize = (m_SrcWidth * m_SrcComponents + 3) / 4 * 4; + FX_Free(m_pDecodeBuf); + m_pDecodeBuf = FX_Alloc(uint8_t, m_ScanlineSize); + memset(m_pDecodeBuf, 0, m_ScanlineSize); + m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, + m_clipBox.Width()); + m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); + m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + return m_status; +} + +FXCODEC_STATUS CCodec_ProgressiveDecoder::BmpContinueDecode() { + CCodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); + if (!pBmpModule) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + while (true) { + int32_t readRes = pBmpModule->LoadImage(m_pBmpContext.get()); + while (readRes == 2) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; + if (!BmpReadMoreData(pBmpModule, error_status)) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = error_status; + return m_status; + } + readRes = pBmpModule->LoadImage(m_pBmpContext.get()); + } + if (readRes == 1) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_DECODE_FINISH; + return m_status; + } + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERROR; + return m_status; + } +} + +bool CCodec_ProgressiveDecoder::GifReadMoreData(CCodec_GifModule* pGifModule, + FXCODEC_STATUS& err_status) { + if (static_cast<uint32_t>(m_pFile->GetSize()) <= m_offSet) + return false; + + uint32_t dwFileRemaining = m_pFile->GetSize() - m_offSet; + uint32_t dwUnusedBuffer = + !m_InvalidateGifBuffer + ? pGifModule->GetAvailInput(m_pGifContext.get(), nullptr) + : 0; + uint32_t dwAmountToFetchFromFile = dwFileRemaining; + if (dwUnusedBuffer == m_SrcSize) { + if (dwFileRemaining > FXCODEC_BLOCK_SIZE) + dwAmountToFetchFromFile = FXCODEC_BLOCK_SIZE; + m_SrcSize = std::min( + (dwAmountToFetchFromFile + dwUnusedBuffer + FXCODEC_BLOCK_SIZE - 1) / + FXCODEC_BLOCK_SIZE * FXCODEC_BLOCK_SIZE, + static_cast<uint32_t>(m_pFile->GetSize())); + m_pSrcBuf = FX_TryRealloc(uint8_t, m_pSrcBuf, m_SrcSize); + if (!m_pSrcBuf) { + err_status = FXCODEC_STATUS_ERR_MEMORY; + return false; + } + } else { + uint32_t dwConsumed = m_SrcSize - dwUnusedBuffer; + if (dwUnusedBuffer) + memmove(m_pSrcBuf, m_pSrcBuf + dwConsumed, dwUnusedBuffer); + if (dwFileRemaining > dwConsumed) + dwAmountToFetchFromFile = dwConsumed; + } + + if (!m_pFile->ReadBlock(m_pSrcBuf + dwUnusedBuffer, m_offSet, + dwAmountToFetchFromFile)) { + err_status = FXCODEC_STATUS_ERR_READ; + return false; + } + + m_offSet += dwAmountToFetchFromFile; + pGifModule->Input(m_pGifContext.get(), m_pSrcBuf, + dwAmountToFetchFromFile + dwUnusedBuffer); + m_InvalidateGifBuffer = false; + return true; +} + +bool CCodec_ProgressiveDecoder::GifDetectImageType(CFX_DIBAttribute* pAttribute, + uint32_t size) { + CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); + if (!pGifModule) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return false; + } + m_pGifContext = pGifModule->Start(this); + bool bResult = m_pFile->ReadBlock(m_pSrcBuf, 0, size); + if (!bResult) { + m_status = FXCODEC_STATUS_ERR_READ; + return false; + } + m_offSet += size; + pGifModule->Input(m_pGifContext.get(), m_pSrcBuf, size); + m_SrcComponents = 1; + CFX_GifDecodeStatus readResult = pGifModule->ReadHeader( + m_pGifContext.get(), &m_SrcWidth, &m_SrcHeight, &m_GifPltNumber, + &m_pGifPalette, &m_GifBgIndex, nullptr); + while (readResult == CFX_GifDecodeStatus::Unfinished) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT; + if (!GifReadMoreData(pGifModule, error_status)) { + m_pGifContext = nullptr; + m_status = error_status; + return false; + } + readResult = pGifModule->ReadHeader(m_pGifContext.get(), &m_SrcWidth, + &m_SrcHeight, &m_GifPltNumber, + &m_pGifPalette, &m_GifBgIndex, nullptr); + } + if (readResult == CFX_GifDecodeStatus::Success) { + m_SrcBPC = 8; + m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); + return true; + } + m_pGifContext = nullptr; + m_status = FXCODEC_STATUS_ERR_FORMAT; + return false; +} + +FXCODEC_STATUS CCodec_ProgressiveDecoder::GifStartDecode( + const RetainPtr<CFX_DIBitmap>& pDIBitmap) { + CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); + if (!pGifModule) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + m_SrcFormat = FXCodec_8bppRgb; + GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); + int scanline_size = (m_SrcWidth + 3) / 4 * 4; + FX_Free(m_pDecodeBuf); + m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); + memset(m_pDecodeBuf, 0, scanline_size); + m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, + m_clipBox.Width()); + m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); + m_FrameCur = 0; + m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + return m_status; +} + +FXCODEC_STATUS CCodec_ProgressiveDecoder::GifContinueDecode() { + CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); + if (!pGifModule) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + + CFX_GifDecodeStatus readRes = + pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur, nullptr); + while (readRes == CFX_GifDecodeStatus::Unfinished) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; + if (!GifReadMoreData(pGifModule, error_status)) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = error_status; + return m_status; + } + readRes = pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur, nullptr); + } + + if (readRes == CFX_GifDecodeStatus::Success) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_DECODE_FINISH; + return m_status; + } + + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERROR; + return m_status; +} + +void CCodec_ProgressiveDecoder::GifDoubleLineResampleVert( + const RetainPtr<CFX_DIBitmap>& pDeviceBitmap, + double scale_y, + int dest_row) { + int dest_Bpp = pDeviceBitmap->GetBPP() >> 3; + uint32_t dest_ScanOffet = m_startX * dest_Bpp; + int dest_top = m_startY; + pdfium::base::CheckedNumeric<double> scale_y2 = scale_y; + scale_y2 *= 2; + pdfium::base::CheckedNumeric<int> check_dest_row_1 = dest_row; + check_dest_row_1 -= scale_y2.ValueOrDie(); + int dest_row_1 = check_dest_row_1.ValueOrDie(); + dest_row_1 = std::max(dest_row_1, dest_top); + for (; dest_row_1 < dest_row; dest_row_1++) { + uint8_t* scan_des = + (uint8_t*)pDeviceBitmap->GetScanline(dest_row_1) + dest_ScanOffet; + PixelWeight* pWeight = m_WeightVert.GetPixelWeight(dest_row_1 - dest_top); + const uint8_t* scan_src1 = + pDeviceBitmap->GetScanline(pWeight->m_SrcStart + dest_top) + + dest_ScanOffet; + const uint8_t* scan_src2 = + pDeviceBitmap->GetScanline(pWeight->m_SrcEnd + dest_top) + + dest_ScanOffet; + for (int dest_col = 0; dest_col < m_sizeX; dest_col++) { + switch (pDeviceBitmap->GetFormat()) { + case FXDIB_Invalid: + case FXDIB_1bppMask: + case FXDIB_1bppRgb: + return; + case FXDIB_8bppMask: + case FXDIB_8bppRgb: { + if (pDeviceBitmap->GetPalette()) { + return; + } + int dest_g = 0; + dest_g += pWeight->m_Weights[0] * (*scan_src1++); + dest_g += pWeight->m_Weights[1] * (*scan_src2++); + *scan_des++ = (uint8_t)(dest_g >> 16); + } break; + case FXDIB_Rgb: + case FXDIB_Rgb32: { + uint32_t dest_b = 0; + uint32_t dest_g = 0; + uint32_t dest_r = 0; + dest_b += pWeight->m_Weights[0] * (*scan_src1++); + dest_g += pWeight->m_Weights[0] * (*scan_src1++); + dest_r += pWeight->m_Weights[0] * (*scan_src1++); + scan_src1 += dest_Bpp - 3; + dest_b += pWeight->m_Weights[1] * (*scan_src2++); + dest_g += pWeight->m_Weights[1] * (*scan_src2++); + dest_r += pWeight->m_Weights[1] * (*scan_src2++); + scan_src2 += dest_Bpp - 3; + *scan_des++ = (uint8_t)((dest_b) >> 16); + *scan_des++ = (uint8_t)((dest_g) >> 16); + *scan_des++ = (uint8_t)((dest_r) >> 16); + scan_des += dest_Bpp - 3; + } break; + case FXDIB_Argb: { + uint32_t dest_a = 0; + uint32_t dest_b = 0; + uint32_t dest_g = 0; + uint32_t dest_r = 0; + dest_b += pWeight->m_Weights[0] * (*scan_src1++); + dest_g += pWeight->m_Weights[0] * (*scan_src1++); + dest_r += pWeight->m_Weights[0] * (*scan_src1++); + dest_a += pWeight->m_Weights[0] * (*scan_src1++); + dest_b += pWeight->m_Weights[1] * (*scan_src2++); + dest_g += pWeight->m_Weights[1] * (*scan_src2++); + dest_r += pWeight->m_Weights[1] * (*scan_src2++); + dest_a += pWeight->m_Weights[1] * (*scan_src2++); + *scan_des++ = (uint8_t)((dest_b) >> 16); + *scan_des++ = (uint8_t)((dest_g) >> 16); + *scan_des++ = (uint8_t)((dest_r) >> 16); + *scan_des++ = (uint8_t)((dest_a) >> 16); + } break; + default: + return; + } + } + } + int dest_bottom = dest_top + m_sizeY - 1; + if (dest_row + (int)(2 * scale_y) >= dest_bottom && + dest_row + (int)scale_y < dest_bottom) { + GifDoubleLineResampleVert(pDeviceBitmap, scale_y, dest_row + (int)scale_y); + } +} + +bool CCodec_ProgressiveDecoder::JpegReadMoreData(CCodec_JpegModule* pJpegModule, + FXCODEC_STATUS& err_status) { + uint32_t dwSize = (uint32_t)m_pFile->GetSize(); + if (dwSize <= m_offSet) { + return false; + } + dwSize = dwSize - m_offSet; + uint32_t dwAvail = pJpegModule->GetAvailInput(m_pJpegContext.get(), nullptr); + if (dwAvail == m_SrcSize) { + if (dwSize > FXCODEC_BLOCK_SIZE) { + dwSize = FXCODEC_BLOCK_SIZE; + } + m_SrcSize = (dwSize + dwAvail + FXCODEC_BLOCK_SIZE - 1) / + FXCODEC_BLOCK_SIZE * FXCODEC_BLOCK_SIZE; + m_pSrcBuf = FX_TryRealloc(uint8_t, m_pSrcBuf, m_SrcSize); + if (!m_pSrcBuf) { + err_status = FXCODEC_STATUS_ERR_MEMORY; + return false; + } + } else { + uint32_t dwConsume = m_SrcSize - dwAvail; + if (dwAvail) { + memmove(m_pSrcBuf, m_pSrcBuf + dwConsume, dwAvail); + } + if (dwSize > dwConsume) { + dwSize = dwConsume; + } + } + if (!m_pFile->ReadBlock(m_pSrcBuf + dwAvail, m_offSet, dwSize)) { + err_status = FXCODEC_STATUS_ERR_READ; + return false; + } + m_offSet += dwSize; + pJpegModule->Input(m_pJpegContext.get(), m_pSrcBuf, dwSize + dwAvail); + return true; +} + bool CCodec_ProgressiveDecoder::JpegDetectImageType( CFX_DIBAttribute* pAttribute, uint32_t size) { @@ -1187,6 +1235,172 @@ bool CCodec_ProgressiveDecoder::JpegDetectImageType( return false; } +FXCODEC_STATUS CCodec_ProgressiveDecoder::JpegStartDecode( + const RetainPtr<CFX_DIBitmap>& pDIBitmap) { + int down_scale = 1; + GetDownScale(down_scale); + // Setting jump marker before calling StartScanLine, since a longjmp to + // the marker indicates a fatal error. + if (setjmp(*m_pJpegContext->GetJumpMark()) == -1) { + m_pJpegContext.reset(); + m_status = FXCODEC_STATUS_ERROR; + return FXCODEC_STATUS_ERROR; + } + + CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); + bool startStatus = + pJpegModule->StartScanline(m_pJpegContext.get(), down_scale); + while (!startStatus) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR; + if (!JpegReadMoreData(pJpegModule, error_status)) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = error_status; + return m_status; + } + + startStatus = pJpegModule->StartScanline(m_pJpegContext.get(), down_scale); + } + int scanline_size = (m_SrcWidth + down_scale - 1) / down_scale; + scanline_size = (scanline_size * m_SrcComponents + 3) / 4 * 4; + FX_Free(m_pDecodeBuf); + m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); + memset(m_pDecodeBuf, 0, scanline_size); + m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, + m_clipBox.Width()); + m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); + switch (m_SrcComponents) { + case 1: + m_SrcFormat = FXCodec_8bppGray; + break; + case 3: + m_SrcFormat = FXCodec_Rgb; + break; + case 4: + m_SrcFormat = FXCodec_Cmyk; + break; + } + GetTransMethod(pDIBitmap->GetFormat(), m_SrcFormat); + m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + return m_status; +} + +FXCODEC_STATUS CCodec_ProgressiveDecoder::JpegContinueDecode() { + CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); + // Setting jump marker before calling ReadScanLine, since a longjmp to + // the marker indicates a fatal error. + if (setjmp(*m_pJpegContext->GetJumpMark()) == -1) { + m_pJpegContext.reset(); + m_status = FXCODEC_STATUS_ERROR; + return FXCODEC_STATUS_ERROR; + } + + while (true) { + bool readRes = + pJpegModule->ReadScanline(m_pJpegContext.get(), m_pDecodeBuf); + while (!readRes) { + FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; + if (!JpegReadMoreData(pJpegModule, error_status)) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = error_status; + return m_status; + } + readRes = pJpegModule->ReadScanline(m_pJpegContext.get(), m_pDecodeBuf); + } + if (m_SrcFormat == FXCodec_Rgb) { + int src_Bpp = (m_SrcFormat & 0xff) >> 3; + RGB2BGR(m_pDecodeBuf + m_clipBox.left * src_Bpp, m_clipBox.Width()); + } + if (m_SrcRow >= m_clipBox.bottom) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_DECODE_FINISH; + return m_status; + } + Resample(m_pDeviceBitmap, m_SrcRow, m_pDecodeBuf, m_SrcFormat); + m_SrcRow++; + } +} + +#ifdef PDF_ENABLE_XFA_PNG +void CCodec_ProgressiveDecoder::PngOneOneMapResampleHorz( + const RetainPtr<CFX_DIBitmap>& pDeviceBitmap, + int32_t dest_line, + uint8_t* src_scan, + FXCodec_Format src_format) { + uint8_t* dest_scan = (uint8_t*)pDeviceBitmap->GetScanline(dest_line); + int32_t src_Bpp = (m_SrcFormat & 0xff) >> 3; + int32_t dest_Bpp = pDeviceBitmap->GetBPP() >> 3; + int32_t src_left = m_clipBox.left; + int32_t dest_left = m_startX; + src_scan += src_left * src_Bpp; + dest_scan += dest_left * dest_Bpp; + for (int32_t dest_col = 0; dest_col < m_sizeX; dest_col++) { + PixelWeight* pPixelWeights = m_WeightHorzOO.GetPixelWeight(dest_col); + switch (pDeviceBitmap->GetFormat()) { + case FXDIB_1bppMask: + case FXDIB_1bppRgb: + NOTREACHED(); + return; + case FXDIB_8bppMask: + case FXDIB_8bppRgb: { + if (pDeviceBitmap->GetPalette()) { + return; + } + uint32_t dest_g = 0; + dest_g += + pPixelWeights->m_Weights[0] * src_scan[pPixelWeights->m_SrcStart]; + dest_g += + pPixelWeights->m_Weights[1] * src_scan[pPixelWeights->m_SrcEnd]; + *dest_scan++ = (uint8_t)(dest_g >> 16); + } break; + case FXDIB_Rgb: + case FXDIB_Rgb32: { + uint32_t dest_b = 0; + uint32_t dest_g = 0; + uint32_t dest_r = 0; + const uint8_t* p = src_scan; + p = src_scan + pPixelWeights->m_SrcStart * src_Bpp; + dest_b += pPixelWeights->m_Weights[0] * (*p++); + dest_g += pPixelWeights->m_Weights[0] * (*p++); + dest_r += pPixelWeights->m_Weights[0] * (*p); + p = src_scan + pPixelWeights->m_SrcEnd * src_Bpp; + dest_b += pPixelWeights->m_Weights[1] * (*p++); + dest_g += pPixelWeights->m_Weights[1] * (*p++); + dest_r += pPixelWeights->m_Weights[1] * (*p); + *dest_scan++ = (uint8_t)((dest_b) >> 16); + *dest_scan++ = (uint8_t)((dest_g) >> 16); + *dest_scan++ = (uint8_t)((dest_r) >> 16); + dest_scan += dest_Bpp - 3; + } break; + case FXDIB_Argb: { + uint32_t dest_a = 0; + uint32_t dest_b = 0; + uint32_t dest_g = 0; + uint32_t dest_r = 0; + const uint8_t* p = src_scan; + p = src_scan + pPixelWeights->m_SrcStart * src_Bpp; + dest_b += pPixelWeights->m_Weights[0] * (*p++); + dest_g += pPixelWeights->m_Weights[0] * (*p++); + dest_r += pPixelWeights->m_Weights[0] * (*p++); + dest_a += pPixelWeights->m_Weights[0] * (*p); + p = src_scan + pPixelWeights->m_SrcEnd * src_Bpp; + dest_b += pPixelWeights->m_Weights[1] * (*p++); + dest_g += pPixelWeights->m_Weights[1] * (*p++); + dest_r += pPixelWeights->m_Weights[1] * (*p++); + dest_a += pPixelWeights->m_Weights[1] * (*p); + *dest_scan++ = (uint8_t)((dest_b) >> 16); + *dest_scan++ = (uint8_t)((dest_g) >> 16); + *dest_scan++ = (uint8_t)((dest_r) >> 16); + *dest_scan++ = (uint8_t)((dest_a) >> 16); + } break; + default: + return; + } + } +} + bool CCodec_ProgressiveDecoder::PngDetectImageType(CFX_DIBAttribute* pAttribute, uint32_t size) { CCodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); @@ -1240,45 +1454,98 @@ bool CCodec_ProgressiveDecoder::PngDetectImageType(CFX_DIBAttribute* pAttribute, return true; } -bool CCodec_ProgressiveDecoder::GifDetectImageType(CFX_DIBAttribute* pAttribute, - uint32_t size) { - CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); - if (!pGifModule) { +FXCODEC_STATUS CCodec_ProgressiveDecoder::PngStartDecode( + const RetainPtr<CFX_DIBitmap>& pDIBitmap) { + CCodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); + if (!pPngModule) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; m_status = FXCODEC_STATUS_ERR_MEMORY; - return false; + return m_status; } - m_pGifContext = pGifModule->Start(this); - bool bResult = m_pFile->ReadBlock(m_pSrcBuf, 0, size); - if (!bResult) { - m_status = FXCODEC_STATUS_ERR_READ; - return false; + m_pPngContext = pPngModule->Start(this); + if (!m_pPngContext) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; } - m_offSet += size; - pGifModule->Input(m_pGifContext.get(), m_pSrcBuf, size); - m_SrcComponents = 1; - CFX_GifDecodeStatus readResult = pGifModule->ReadHeader( - m_pGifContext.get(), &m_SrcWidth, &m_SrcHeight, &m_GifPltNumber, - &m_pGifPalette, &m_GifBgIndex, nullptr); - while (readResult == CFX_GifDecodeStatus::Unfinished) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_ERR_FORMAT; - if (!GifReadMoreData(pGifModule, error_status)) { - m_pGifContext = nullptr; - m_status = error_status; - return false; + m_offSet = 0; + switch (m_pDeviceBitmap->GetFormat()) { + case FXDIB_8bppMask: + case FXDIB_8bppRgb: + m_SrcComponents = 1; + m_SrcFormat = FXCodec_8bppGray; + break; + case FXDIB_Rgb: + m_SrcComponents = 3; + m_SrcFormat = FXCodec_Rgb; + break; + case FXDIB_Rgb32: + case FXDIB_Argb: + m_SrcComponents = 4; + m_SrcFormat = FXCodec_Argb; + break; + default: { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_PARAMS; + return m_status; } - readResult = pGifModule->ReadHeader(m_pGifContext.get(), &m_SrcWidth, - &m_SrcHeight, &m_GifPltNumber, - &m_pGifPalette, &m_GifBgIndex, nullptr); } - if (readResult == CFX_GifDecodeStatus::Success) { - m_SrcBPC = 8; - m_clipBox = FX_RECT(0, 0, m_SrcWidth, m_SrcHeight); - return true; + GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); + int scanline_size = (m_SrcWidth * m_SrcComponents + 3) / 4 * 4; + FX_Free(m_pDecodeBuf); + m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); + memset(m_pDecodeBuf, 0, scanline_size); + m_WeightHorzOO.Calc(m_sizeX, m_clipBox.Width()); + m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); + m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; + return m_status; +} + +FXCODEC_STATUS CCodec_ProgressiveDecoder::PngContinueDecode() { + CCodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); + if (!pPngModule) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + while (true) { + uint32_t remain_size = (uint32_t)m_pFile->GetSize() - m_offSet; + uint32_t input_size = + remain_size > FXCODEC_BLOCK_SIZE ? FXCODEC_BLOCK_SIZE : remain_size; + if (input_size == 0) { + m_pPngContext.reset(); + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_DECODE_FINISH; + return m_status; + } + if (m_pSrcBuf && input_size > m_SrcSize) { + FX_Free(m_pSrcBuf); + m_pSrcBuf = FX_Alloc(uint8_t, input_size); + memset(m_pSrcBuf, 0, input_size); + m_SrcSize = input_size; + } + bool bResult = m_pFile->ReadBlock(m_pSrcBuf, m_offSet, input_size); + if (!bResult) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_READ; + return m_status; + } + m_offSet += input_size; + bResult = + pPngModule->Input(m_pPngContext.get(), m_pSrcBuf, input_size, nullptr); + if (!bResult) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERROR; + return m_status; + } } - m_pGifContext = nullptr; - m_status = FXCODEC_STATUS_ERR_FORMAT; - return false; } +#endif // PDF_ENABLE_XFA_PNG #ifdef PDF_ENABLE_XFA_TIFF bool CCodec_ProgressiveDecoder::TiffDetectImageType( @@ -1307,8 +1574,179 @@ bool CCodec_ProgressiveDecoder::TiffDetectImageType( } return true; } + +FXCODEC_STATUS CCodec_ProgressiveDecoder::TiffContinueDecode() { + CCodec_TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule(); + if (!pTiffModule) { + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + bool ret = false; + if (m_pDeviceBitmap->GetBPP() == 32 && + m_pDeviceBitmap->GetWidth() == m_SrcWidth && m_SrcWidth == m_sizeX && + m_pDeviceBitmap->GetHeight() == m_SrcHeight && m_SrcHeight == m_sizeY && + m_startX == 0 && m_startY == 0 && m_clipBox.left == 0 && + m_clipBox.top == 0 && m_clipBox.right == m_SrcWidth && + m_clipBox.bottom == m_SrcHeight) { + ret = pTiffModule->Decode(m_pTiffContext.get(), m_pDeviceBitmap); + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + if (!ret) { + m_status = FXCODEC_STATUS_ERROR; + return m_status; + } + m_status = FXCODEC_STATUS_DECODE_FINISH; + return m_status; + } + + auto pDIBitmap = pdfium::MakeRetain<CFX_DIBitmap>(); + pDIBitmap->Create(m_SrcWidth, m_SrcHeight, FXDIB_Argb); + if (!pDIBitmap->GetBuffer()) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + ret = pTiffModule->Decode(m_pTiffContext.get(), pDIBitmap); + if (!ret) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERROR; + return m_status; + } + RetainPtr<CFX_DIBitmap> pClipBitmap = + (m_clipBox.left == 0 && m_clipBox.top == 0 && + m_clipBox.right == m_SrcWidth && m_clipBox.bottom == m_SrcHeight) + ? pDIBitmap + : pDIBitmap->Clone(&m_clipBox); + if (!pClipBitmap) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + RetainPtr<CFX_DIBitmap> pFormatBitmap; + switch (m_pDeviceBitmap->GetFormat()) { + case FXDIB_8bppRgb: + pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>(); + pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), + FXDIB_8bppRgb); + break; + case FXDIB_8bppMask: + pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>(); + pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), + FXDIB_8bppMask); + break; + case FXDIB_Rgb: + pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>(); + pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), + FXDIB_Rgb); + break; + case FXDIB_Rgb32: + pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>(); + pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), + FXDIB_Rgb32); + break; + case FXDIB_Argb: + pFormatBitmap = pClipBitmap; + break; + default: + break; + } + switch (m_pDeviceBitmap->GetFormat()) { + case FXDIB_8bppRgb: + case FXDIB_8bppMask: { + for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) { + uint8_t* src_line = (uint8_t*)pClipBitmap->GetScanline(row); + uint8_t* dest_line = (uint8_t*)pFormatBitmap->GetScanline(row); + for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) { + uint8_t _a = 255 - src_line[3]; + uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255; + uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255; + uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255; + *dest_line++ = FXRGB2GRAY(r, g, b); + src_line += 4; + } + } + } break; + case FXDIB_Rgb: + case FXDIB_Rgb32: { + int32_t desBpp = (m_pDeviceBitmap->GetFormat() == FXDIB_Rgb) ? 3 : 4; + for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) { + uint8_t* src_line = (uint8_t*)pClipBitmap->GetScanline(row); + uint8_t* dest_line = (uint8_t*)pFormatBitmap->GetScanline(row); + for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) { + uint8_t _a = 255 - src_line[3]; + uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255; + uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255; + uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255; + *dest_line++ = b; + *dest_line++ = g; + *dest_line++ = r; + dest_line += desBpp - 3; + src_line += 4; + } + } + } break; + default: + break; + } + if (!pFormatBitmap) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + RetainPtr<CFX_DIBitmap> pStrechBitmap = + pFormatBitmap->StretchTo(m_sizeX, m_sizeY, FXDIB_INTERPOL, nullptr); + pFormatBitmap = nullptr; + if (!pStrechBitmap) { + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_ERR_MEMORY; + return m_status; + } + m_pDeviceBitmap->TransferBitmap(m_startX, m_startY, m_sizeX, m_sizeY, + pStrechBitmap, 0, 0); + m_pDeviceBitmap = nullptr; + m_pFile = nullptr; + m_status = FXCODEC_STATUS_DECODE_FINISH; + return m_status; +} #endif // PDF_ENABLE_XFA_TIFF +bool CCodec_ProgressiveDecoder::DetectImageType(FXCODEC_IMAGE_TYPE imageType, + CFX_DIBAttribute* pAttribute) { + m_offSet = 0; + uint32_t size = (uint32_t)m_pFile->GetSize(); + if (size > FXCODEC_BLOCK_SIZE) { + size = FXCODEC_BLOCK_SIZE; + } + FX_Free(m_pSrcBuf); + m_pSrcBuf = FX_Alloc(uint8_t, size); + memset(m_pSrcBuf, 0, size); + m_SrcSize = size; + switch (imageType) { + case FXCODEC_IMAGE_BMP: + return BmpDetectImageType(pAttribute, size); + case FXCODEC_IMAGE_JPG: + return JpegDetectImageType(pAttribute, size); +#ifdef PDF_ENABLE_XFA_PNG + case FXCODEC_IMAGE_PNG: + return PngDetectImageType(pAttribute, size); +#endif // PDF_ENABLE_XFA_PNG + case FXCODEC_IMAGE_GIF: + return GifDetectImageType(pAttribute, size); +#ifdef PDF_ENABLE_XFA_TIFF + case FXCODEC_IMAGE_TIFF: + return TiffDetectImageType(pAttribute, size); +#endif // PDF_ENABLE_XFA_TIFF + default: + m_status = FXCODEC_STATUS_ERR_FORMAT; + return false; + } +} + FXCODEC_STATUS CCodec_ProgressiveDecoder::LoadImageInfo( const RetainPtr<IFX_SeekableReadStream>& pFile, FXCODEC_IMAGE_TYPE imageType, @@ -1862,7 +2300,9 @@ std::pair<FXCODEC_STATUS, size_t> CCodec_ProgressiveDecoder::GetFrames() { switch (m_imagType) { case FXCODEC_IMAGE_JPG: case FXCODEC_IMAGE_BMP: +#ifdef PDF_ENABLE_XFA_PNG case FXCODEC_IMAGE_PNG: +#endif // PDF_ENABLE_XFA_PNG #ifdef PDF_ENABLE_XFA_TIFF case FXCODEC_IMAGE_TIFF: #endif // PDF_ENABLE_XFA_TIFF @@ -1957,8 +2397,10 @@ FXCODEC_STATUS CCodec_ProgressiveDecoder::StartDecode( switch (m_imagType) { case FXCODEC_IMAGE_JPG: return JpegStartDecode(pDIBitmap); +#ifdef PDF_ENABLE_XFA_PNG case FXCODEC_IMAGE_PNG: return PngStartDecode(pDIBitmap); +#endif // PDF_ENABLE_XFA_PNG case FXCODEC_IMAGE_GIF: return GifStartDecode(pDIBitmap); case FXCODEC_IMAGE_BMP: @@ -1973,150 +2415,6 @@ FXCODEC_STATUS CCodec_ProgressiveDecoder::StartDecode( } } -FXCODEC_STATUS CCodec_ProgressiveDecoder::JpegStartDecode( - const RetainPtr<CFX_DIBitmap>& pDIBitmap) { - int down_scale = 1; - GetDownScale(down_scale); - // Setting jump marker before calling StartScanLine, since a longjmp to - // the marker indicates a fatal error. - if (setjmp(*m_pJpegContext->GetJumpMark()) == -1) { - m_pJpegContext.reset(); - m_status = FXCODEC_STATUS_ERROR; - return FXCODEC_STATUS_ERROR; - } - - CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); - bool startStatus = - pJpegModule->StartScanline(m_pJpegContext.get(), down_scale); - while (!startStatus) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_ERROR; - if (!JpegReadMoreData(pJpegModule, error_status)) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = error_status; - return m_status; - } - - startStatus = pJpegModule->StartScanline(m_pJpegContext.get(), down_scale); - } - int scanline_size = (m_SrcWidth + down_scale - 1) / down_scale; - scanline_size = (scanline_size * m_SrcComponents + 3) / 4 * 4; - FX_Free(m_pDecodeBuf); - m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); - memset(m_pDecodeBuf, 0, scanline_size); - m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, - m_clipBox.Width()); - m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); - switch (m_SrcComponents) { - case 1: - m_SrcFormat = FXCodec_8bppGray; - break; - case 3: - m_SrcFormat = FXCodec_Rgb; - break; - case 4: - m_SrcFormat = FXCodec_Cmyk; - break; - } - GetTransMethod(pDIBitmap->GetFormat(), m_SrcFormat); - m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - return m_status; -} - -FXCODEC_STATUS CCodec_ProgressiveDecoder::PngStartDecode( - const RetainPtr<CFX_DIBitmap>& pDIBitmap) { - CCodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); - if (!pPngModule) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - m_pPngContext = pPngModule->Start(this); - if (!m_pPngContext) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - m_offSet = 0; - switch (m_pDeviceBitmap->GetFormat()) { - case FXDIB_8bppMask: - case FXDIB_8bppRgb: - m_SrcComponents = 1; - m_SrcFormat = FXCodec_8bppGray; - break; - case FXDIB_Rgb: - m_SrcComponents = 3; - m_SrcFormat = FXCodec_Rgb; - break; - case FXDIB_Rgb32: - case FXDIB_Argb: - m_SrcComponents = 4; - m_SrcFormat = FXCodec_Argb; - break; - default: { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_PARAMS; - return m_status; - } - } - GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); - int scanline_size = (m_SrcWidth * m_SrcComponents + 3) / 4 * 4; - FX_Free(m_pDecodeBuf); - m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); - memset(m_pDecodeBuf, 0, scanline_size); - m_WeightHorzOO.Calc(m_sizeX, m_clipBox.Width()); - m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); - m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - return m_status; -} - -FXCODEC_STATUS CCodec_ProgressiveDecoder::GifStartDecode( - const RetainPtr<CFX_DIBitmap>& pDIBitmap) { - CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); - if (!pGifModule) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - m_SrcFormat = FXCodec_8bppRgb; - GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); - int scanline_size = (m_SrcWidth + 3) / 4 * 4; - FX_Free(m_pDecodeBuf); - m_pDecodeBuf = FX_Alloc(uint8_t, scanline_size); - memset(m_pDecodeBuf, 0, scanline_size); - m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, - m_clipBox.Width()); - m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); - m_FrameCur = 0; - m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - return m_status; -} - -FXCODEC_STATUS CCodec_ProgressiveDecoder::BmpStartDecode( - const RetainPtr<CFX_DIBitmap>& pDIBitmap) { - CCodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); - if (!pBmpModule) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - GetTransMethod(m_pDeviceBitmap->GetFormat(), m_SrcFormat); - m_ScanlineSize = (m_SrcWidth * m_SrcComponents + 3) / 4 * 4; - FX_Free(m_pDecodeBuf); - m_pDecodeBuf = FX_Alloc(uint8_t, m_ScanlineSize); - memset(m_pDecodeBuf, 0, m_ScanlineSize); - m_WeightHorz.Calc(m_sizeX, 0, m_sizeX, m_clipBox.Width(), 0, - m_clipBox.Width()); - m_WeightVert.Calc(m_sizeY, m_clipBox.Height()); - m_status = FXCODEC_STATUS_DECODE_TOBECONTINUE; - return m_status; -} - FXCODEC_STATUS CCodec_ProgressiveDecoder::ContinueDecode() { if (m_status != FXCODEC_STATUS_DECODE_TOBECONTINUE) return FXCODEC_STATUS_ERROR; @@ -2124,8 +2422,10 @@ FXCODEC_STATUS CCodec_ProgressiveDecoder::ContinueDecode() { switch (m_imagType) { case FXCODEC_IMAGE_JPG: return JpegContinueDecode(); +#ifdef PDF_ENABLE_XFA_PNG case FXCODEC_IMAGE_PNG: return PngContinueDecode(); +#endif // PDF_ENABLE_XFA_PNG case FXCODEC_IMAGE_GIF: return GifContinueDecode(); case FXCODEC_IMAGE_BMP: @@ -2139,293 +2439,6 @@ FXCODEC_STATUS CCodec_ProgressiveDecoder::ContinueDecode() { } } -FXCODEC_STATUS CCodec_ProgressiveDecoder::JpegContinueDecode() { - CCodec_JpegModule* pJpegModule = m_pCodecMgr->GetJpegModule(); - // Setting jump marker before calling ReadScanLine, since a longjmp to - // the marker indicates a fatal error. - if (setjmp(*m_pJpegContext->GetJumpMark()) == -1) { - m_pJpegContext.reset(); - m_status = FXCODEC_STATUS_ERROR; - return FXCODEC_STATUS_ERROR; - } - - while (true) { - bool readRes = - pJpegModule->ReadScanline(m_pJpegContext.get(), m_pDecodeBuf); - while (!readRes) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; - if (!JpegReadMoreData(pJpegModule, error_status)) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = error_status; - return m_status; - } - readRes = pJpegModule->ReadScanline(m_pJpegContext.get(), m_pDecodeBuf); - } - if (m_SrcFormat == FXCodec_Rgb) { - int src_Bpp = (m_SrcFormat & 0xff) >> 3; - RGB2BGR(m_pDecodeBuf + m_clipBox.left * src_Bpp, m_clipBox.Width()); - } - if (m_SrcRow >= m_clipBox.bottom) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_DECODE_FINISH; - return m_status; - } - Resample(m_pDeviceBitmap, m_SrcRow, m_pDecodeBuf, m_SrcFormat); - m_SrcRow++; - } -} - -FXCODEC_STATUS CCodec_ProgressiveDecoder::PngContinueDecode() { - CCodec_PngModule* pPngModule = m_pCodecMgr->GetPngModule(); - if (!pPngModule) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - while (true) { - uint32_t remain_size = (uint32_t)m_pFile->GetSize() - m_offSet; - uint32_t input_size = - remain_size > FXCODEC_BLOCK_SIZE ? FXCODEC_BLOCK_SIZE : remain_size; - if (input_size == 0) { - m_pPngContext.reset(); - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_DECODE_FINISH; - return m_status; - } - if (m_pSrcBuf && input_size > m_SrcSize) { - FX_Free(m_pSrcBuf); - m_pSrcBuf = FX_Alloc(uint8_t, input_size); - memset(m_pSrcBuf, 0, input_size); - m_SrcSize = input_size; - } - bool bResult = m_pFile->ReadBlock(m_pSrcBuf, m_offSet, input_size); - if (!bResult) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_READ; - return m_status; - } - m_offSet += input_size; - bResult = - pPngModule->Input(m_pPngContext.get(), m_pSrcBuf, input_size, nullptr); - if (!bResult) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERROR; - return m_status; - } - } -} - -FXCODEC_STATUS CCodec_ProgressiveDecoder::GifContinueDecode() { - CCodec_GifModule* pGifModule = m_pCodecMgr->GetGifModule(); - if (!pGifModule) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - - CFX_GifDecodeStatus readRes = - pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur, nullptr); - while (readRes == CFX_GifDecodeStatus::Unfinished) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; - if (!GifReadMoreData(pGifModule, error_status)) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = error_status; - return m_status; - } - readRes = pGifModule->LoadFrame(m_pGifContext.get(), m_FrameCur, nullptr); - } - - if (readRes == CFX_GifDecodeStatus::Success) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_DECODE_FINISH; - return m_status; - } - - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERROR; - return m_status; -} - -FXCODEC_STATUS CCodec_ProgressiveDecoder::BmpContinueDecode() { - CCodec_BmpModule* pBmpModule = m_pCodecMgr->GetBmpModule(); - if (!pBmpModule) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - while (true) { - int32_t readRes = pBmpModule->LoadImage(m_pBmpContext.get()); - while (readRes == 2) { - FXCODEC_STATUS error_status = FXCODEC_STATUS_DECODE_FINISH; - if (!BmpReadMoreData(pBmpModule, error_status)) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = error_status; - return m_status; - } - readRes = pBmpModule->LoadImage(m_pBmpContext.get()); - } - if (readRes == 1) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_DECODE_FINISH; - return m_status; - } - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERROR; - return m_status; - } -} - -#ifdef PDF_ENABLE_XFA_TIFF -FXCODEC_STATUS CCodec_ProgressiveDecoder::TiffContinueDecode() { - CCodec_TiffModule* pTiffModule = m_pCodecMgr->GetTiffModule(); - if (!pTiffModule) { - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - bool ret = false; - if (m_pDeviceBitmap->GetBPP() == 32 && - m_pDeviceBitmap->GetWidth() == m_SrcWidth && m_SrcWidth == m_sizeX && - m_pDeviceBitmap->GetHeight() == m_SrcHeight && m_SrcHeight == m_sizeY && - m_startX == 0 && m_startY == 0 && m_clipBox.left == 0 && - m_clipBox.top == 0 && m_clipBox.right == m_SrcWidth && - m_clipBox.bottom == m_SrcHeight) { - ret = pTiffModule->Decode(m_pTiffContext.get(), m_pDeviceBitmap); - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - if (!ret) { - m_status = FXCODEC_STATUS_ERROR; - return m_status; - } - m_status = FXCODEC_STATUS_DECODE_FINISH; - return m_status; - } - - auto pDIBitmap = pdfium::MakeRetain<CFX_DIBitmap>(); - pDIBitmap->Create(m_SrcWidth, m_SrcHeight, FXDIB_Argb); - if (!pDIBitmap->GetBuffer()) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - ret = pTiffModule->Decode(m_pTiffContext.get(), pDIBitmap); - if (!ret) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERROR; - return m_status; - } - RetainPtr<CFX_DIBitmap> pClipBitmap = - (m_clipBox.left == 0 && m_clipBox.top == 0 && - m_clipBox.right == m_SrcWidth && m_clipBox.bottom == m_SrcHeight) - ? pDIBitmap - : pDIBitmap->Clone(&m_clipBox); - if (!pClipBitmap) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - RetainPtr<CFX_DIBitmap> pFormatBitmap; - switch (m_pDeviceBitmap->GetFormat()) { - case FXDIB_8bppRgb: - pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>(); - pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), - FXDIB_8bppRgb); - break; - case FXDIB_8bppMask: - pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>(); - pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), - FXDIB_8bppMask); - break; - case FXDIB_Rgb: - pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>(); - pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), - FXDIB_Rgb); - break; - case FXDIB_Rgb32: - pFormatBitmap = pdfium::MakeRetain<CFX_DIBitmap>(); - pFormatBitmap->Create(pClipBitmap->GetWidth(), pClipBitmap->GetHeight(), - FXDIB_Rgb32); - break; - case FXDIB_Argb: - pFormatBitmap = pClipBitmap; - break; - default: - break; - } - switch (m_pDeviceBitmap->GetFormat()) { - case FXDIB_8bppRgb: - case FXDIB_8bppMask: { - for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) { - uint8_t* src_line = (uint8_t*)pClipBitmap->GetScanline(row); - uint8_t* dest_line = (uint8_t*)pFormatBitmap->GetScanline(row); - for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) { - uint8_t _a = 255 - src_line[3]; - uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255; - uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255; - uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255; - *dest_line++ = FXRGB2GRAY(r, g, b); - src_line += 4; - } - } - } break; - case FXDIB_Rgb: - case FXDIB_Rgb32: { - int32_t desBpp = (m_pDeviceBitmap->GetFormat() == FXDIB_Rgb) ? 3 : 4; - for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) { - uint8_t* src_line = (uint8_t*)pClipBitmap->GetScanline(row); - uint8_t* dest_line = (uint8_t*)pFormatBitmap->GetScanline(row); - for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) { - uint8_t _a = 255 - src_line[3]; - uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255; - uint8_t g = (src_line[1] * src_line[3] + 0xFF * _a) / 255; - uint8_t r = (src_line[2] * src_line[3] + 0xFF * _a) / 255; - *dest_line++ = b; - *dest_line++ = g; - *dest_line++ = r; - dest_line += desBpp - 3; - src_line += 4; - } - } - } break; - default: - break; - } - if (!pFormatBitmap) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - RetainPtr<CFX_DIBitmap> pStrechBitmap = - pFormatBitmap->StretchTo(m_sizeX, m_sizeY, FXDIB_INTERPOL, nullptr); - pFormatBitmap = nullptr; - if (!pStrechBitmap) { - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_ERR_MEMORY; - return m_status; - } - m_pDeviceBitmap->TransferBitmap(m_startX, m_startY, m_sizeX, m_sizeY, - pStrechBitmap, 0, 0); - m_pDeviceBitmap = nullptr; - m_pFile = nullptr; - m_status = FXCODEC_STATUS_DECODE_FINISH; - return m_status; -} -#endif // PDF_ENABLE_XFA_TIFF - std::unique_ptr<CCodec_ProgressiveDecoder> CCodec_ModuleMgr::CreateProgressiveDecoder() { return pdfium::MakeUnique<CCodec_ProgressiveDecoder>(this); diff --git a/core/fxcodec/fx_codec_def.h b/core/fxcodec/fx_codec_def.h index e4ac0437eb..b7944ee1c1 100644 --- a/core/fxcodec/fx_codec_def.h +++ b/core/fxcodec/fx_codec_def.h @@ -28,13 +28,16 @@ enum FXCODEC_IMAGE_TYPE { FXCODEC_IMAGE_UNKNOWN = 0, FXCODEC_IMAGE_BMP, FXCODEC_IMAGE_JPG, +#ifdef PDF_ENABLE_XFA_PNG FXCODEC_IMAGE_PNG, +#endif // PDF_ENABLE_XFA_PNG FXCODEC_IMAGE_GIF, #ifdef PDF_ENABLE_XFA_TIFF FXCODEC_IMAGE_TIFF, #endif // PDF_ENABLE_XFA_TIFF FXCODEC_IMAGE_MAX }; + enum FXCODEC_RESUNIT { FXCODEC_RESUNIT_NONE = 0, FXCODEC_RESUNIT_INCH, diff --git a/testing/libfuzzer/BUILD.gn b/testing/libfuzzer/BUILD.gn index a45c8d2576..5a050a2237 100644 --- a/testing/libfuzzer/BUILD.gn +++ b/testing/libfuzzer/BUILD.gn @@ -42,12 +42,14 @@ group("libfuzzer") { ":pdf_codec_bmp_fuzzer", ":pdf_codec_gif_fuzzer", ":pdf_codec_jpeg_fuzzer", - ":pdf_codec_png_fuzzer", ":pdf_css_fuzzer", ":pdf_fm2js_fuzzer", ":pdf_formcalc_fuzzer", ":pdf_lzw_fuzzer", ] + if (pdf_enable_xfa_png) { + deps += [ ":pdf_codec_png_fuzzer" ] + } if (pdf_enable_xfa_tiff) { deps += [ ":pdf_codec_tiff_fuzzer" ] } @@ -100,11 +102,13 @@ if (pdf_enable_xfa) { ] } - pdfium_fuzzer("pdf_codec_png_fuzzer") { - sources = [ - "pdf_codec_png_fuzzer.cc", - "xfa_codec_fuzzer.h", - ] + if (pdf_enable_xfa_png) { + pdfium_fuzzer("pdf_codec_png_fuzzer") { + sources = [ + "pdf_codec_png_fuzzer.cc", + "xfa_codec_fuzzer.h", + ] + } } if (pdf_enable_xfa_tiff) { diff --git a/xfa/fxfa/cxfa_ffwidget.cpp b/xfa/fxfa/cxfa_ffwidget.cpp index 6fd2397670..3c5a3411a7 100644 --- a/xfa/fxfa/cxfa_ffwidget.cpp +++ b/xfa/fxfa/cxfa_ffwidget.cpp @@ -52,7 +52,9 @@ FXDIB_Format XFA_GetDIBFormat(FXCODEC_IMAGE_TYPE type, dibFormat = FXDIB_Rgb; } } break; +#ifdef PDF_ENABLE_XFA_PNG case FXCODEC_IMAGE_PNG: +#endif // PDF_ENABLE_XFA_PNG default: break; } diff --git a/xfa/fxfa/parser/cxfa_node.cpp b/xfa/fxfa/parser/cxfa_node.cpp index 674ec00d8e..7e479b1858 100644 --- a/xfa/fxfa/parser/cxfa_node.cpp +++ b/xfa/fxfa/parser/cxfa_node.cpp @@ -165,8 +165,10 @@ FXCODEC_IMAGE_TYPE XFA_GetImageType(const WideString& wsType) { wsContentType.MakeLower(); if (wsContentType == L"image/jpg") return FXCODEC_IMAGE_JPG; +#ifdef PDF_ENABLE_XFA_PNG if (wsContentType == L"image/png") return FXCODEC_IMAGE_PNG; +#endif // PDF_ENABLE_XFA_PNG if (wsContentType == L"image/gif") return FXCODEC_IMAGE_GIF; if (wsContentType == L"image/bmp") |