diff options
Diffstat (limited to 'core/src/fxcodec')
-rw-r--r-- | core/src/fxcodec/codec/fx_codec_flate.cpp | 306 |
1 files changed, 162 insertions, 144 deletions
diff --git a/core/src/fxcodec/codec/fx_codec_flate.cpp b/core/src/fxcodec/codec/fx_codec_flate.cpp index 37aecf106d..519ff00522 100644 --- a/core/src/fxcodec/codec/fx_codec_flate.cpp +++ b/core/src/fxcodec/codec/fx_codec_flate.cpp @@ -75,6 +75,8 @@ void FPDFAPI_FlateEnd(void* context) { } } // extern "C" +namespace { + class CLZWDecoder { public: int Decode(uint8_t* output, @@ -222,7 +224,8 @@ int CLZWDecoder::Decode(uint8_t* dest_buf, src_size = (m_InPos + 7) / 8; return 0; } -static uint8_t PaethPredictor(int a, int b, int c) { + +uint8_t PaethPredictor(int a, int b, int c) { int p = a + b - c; int pa = FXSYS_abs(p - a); int pb = FXSYS_abs(p - b); @@ -235,12 +238,13 @@ static uint8_t PaethPredictor(int a, int b, int c) { } return (uint8_t)c; } -static FX_BOOL PNG_PredictorEncode(uint8_t*& data_buf, - FX_DWORD& data_size, - int predictor, - int Colors, - int BitsPerComponent, - int Columns) { + +FX_BOOL PNG_PredictorEncode(uint8_t*& data_buf, + FX_DWORD& data_size, + int predictor, + int Colors, + int BitsPerComponent, + int Columns) { const int BytesPerPixel = (Colors * BitsPerComponent + 7) / 8; const int row_size = (Colors * BitsPerComponent * Columns + 7) / 8; if (row_size <= 0) @@ -324,12 +328,13 @@ static FX_BOOL PNG_PredictorEncode(uint8_t*& data_buf, (last_row_size > 0 ? (row_size - last_row_size) : 0); return TRUE; } -static void PNG_PredictLine(uint8_t* pDestData, - const uint8_t* pSrcData, - const uint8_t* pLastLine, - int bpc, - int nColors, - int nPixels) { + +void PNG_PredictLine(uint8_t* pDestData, + const uint8_t* pSrcData, + const uint8_t* pLastLine, + int bpc, + int nColors, + int nPixels) { int row_size = (nPixels * bpc * nColors + 7) / 8; int BytesPerPixel = (bpc * nColors + 7) / 8; uint8_t tag = pSrcData[0]; @@ -390,11 +395,12 @@ static void PNG_PredictLine(uint8_t* pDestData, } } } -static FX_BOOL PNG_Predictor(uint8_t*& data_buf, - FX_DWORD& data_size, - int Colors, - int BitsPerComponent, - int Columns) { + +FX_BOOL PNG_Predictor(uint8_t*& data_buf, + FX_DWORD& data_size, + int Colors, + int BitsPerComponent, + int Columns) { const int BytesPerPixel = (Colors * BitsPerComponent + 7) / 8; const int row_size = (Colors * BitsPerComponent * Columns + 7) / 8; if (row_size <= 0) @@ -483,11 +489,12 @@ static FX_BOOL PNG_Predictor(uint8_t*& data_buf, (last_row_size > 0 ? (row_size + 1 - last_row_size) : 0); return TRUE; } -static void TIFF_PredictorEncodeLine(uint8_t* dest_buf, - int row_size, - int BitsPerComponent, - int Colors, - int Columns) { + +void TIFF_PredictorEncodeLine(uint8_t* dest_buf, + int row_size, + int BitsPerComponent, + int Colors, + int Columns) { int BytesPerPixel = BitsPerComponent * Colors / 8; if (BitsPerComponent < 8) { uint8_t mask = 0x01; @@ -528,11 +535,12 @@ static void TIFF_PredictorEncodeLine(uint8_t* dest_buf, } } } -static FX_BOOL TIFF_PredictorEncode(uint8_t*& data_buf, - FX_DWORD& data_size, - int Colors, - int BitsPerComponent, - int Columns) { + +FX_BOOL TIFF_PredictorEncode(uint8_t*& data_buf, + FX_DWORD& data_size, + int Colors, + int BitsPerComponent, + int Columns) { int row_size = (Colors * BitsPerComponent * Columns + 7) / 8; if (row_size == 0) return FALSE; @@ -548,11 +556,12 @@ static FX_BOOL TIFF_PredictorEncode(uint8_t*& data_buf, } return TRUE; } -static void TIFF_PredictLine(uint8_t* dest_buf, - int row_size, - int BitsPerComponent, - int Colors, - int Columns) { + +void TIFF_PredictLine(uint8_t* dest_buf, + int row_size, + int BitsPerComponent, + int Colors, + int Columns) { if (BitsPerComponent == 1) { int row_bits = FX_MIN(BitsPerComponent * Colors * Columns, row_size * 8); int index_pre = 0; @@ -586,11 +595,12 @@ static void TIFF_PredictLine(uint8_t* dest_buf, } } } -static FX_BOOL TIFF_Predictor(uint8_t*& data_buf, - FX_DWORD& data_size, - int Colors, - int BitsPerComponent, - int Columns) { + +FX_BOOL TIFF_Predictor(uint8_t*& data_buf, + FX_DWORD& data_size, + int Colors, + int BitsPerComponent, + int Columns) { int row_size = (Colors * BitsPerComponent * Columns + 7) / 8; if (row_size == 0) return FALSE; @@ -606,6 +616,120 @@ static FX_BOOL TIFF_Predictor(uint8_t*& data_buf, return TRUE; } +void FlateUncompress(const uint8_t* src_buf, + FX_DWORD src_size, + FX_DWORD orig_size, + uint8_t*& dest_buf, + FX_DWORD& dest_size, + FX_DWORD& offset) { + FX_DWORD guess_size = orig_size ? orig_size : src_size * 2; + const FX_DWORD kStepSize = 10240; + FX_DWORD alloc_step = orig_size ? kStepSize : std::min(src_size, kStepSize); + static const FX_DWORD kMaxInitialAllocSize = 10000000; + if (guess_size > kMaxInitialAllocSize) { + guess_size = kMaxInitialAllocSize; + alloc_step = kMaxInitialAllocSize; + } + FX_DWORD buf_size = guess_size; + FX_DWORD last_buf_size = buf_size; + + dest_buf = nullptr; + dest_size = 0; + void* context = FPDFAPI_FlateInit(my_alloc_func, my_free_func); + if (!context) + return; + + nonstd::unique_ptr<uint8_t, FxFreeDeleter> guess_buf( + FX_Alloc(uint8_t, guess_size + 1)); + guess_buf.get()[guess_size] = '\0'; + + FPDFAPI_FlateInput(context, src_buf, src_size); + + if (src_size < kStepSize) { + // This is the old implementation. + uint8_t* cur_buf = guess_buf.get(); + while (1) { + int32_t ret = FPDFAPI_FlateOutput(context, cur_buf, buf_size); + if (ret != Z_OK) + break; + int32_t avail_buf_size = FPDFAPI_FlateGetAvailOut(context); + if (avail_buf_size != 0) + break; + + FX_DWORD old_size = guess_size; + guess_size += alloc_step; + if (guess_size < old_size || guess_size + 1 < guess_size) { + FPDFAPI_FlateEnd(context); + return; + } + + { + uint8_t* new_buf = + FX_Realloc(uint8_t, guess_buf.release(), guess_size + 1); + guess_buf.reset(new_buf); + } + guess_buf.get()[guess_size] = '\0'; + cur_buf = guess_buf.get() + old_size; + buf_size = guess_size - old_size; + } + dest_size = FPDFAPI_FlateGetTotalOut(context); + offset = FPDFAPI_FlateGetTotalIn(context); + if (guess_size / 2 > dest_size) { + { + uint8_t* new_buf = + FX_Realloc(uint8_t, guess_buf.release(), dest_size + 1); + guess_buf.reset(new_buf); + } + guess_size = dest_size; + guess_buf.get()[guess_size] = '\0'; + } + dest_buf = guess_buf.release(); + } else { + CFX_ArrayTemplate<uint8_t*> result_tmp_bufs; + uint8_t* cur_buf = guess_buf.release(); + while (1) { + int32_t ret = FPDFAPI_FlateOutput(context, cur_buf, buf_size); + int32_t avail_buf_size = FPDFAPI_FlateGetAvailOut(context); + if (ret != Z_OK) { + last_buf_size = buf_size - avail_buf_size; + result_tmp_bufs.Add(cur_buf); + break; + } + if (avail_buf_size != 0) { + last_buf_size = buf_size - avail_buf_size; + result_tmp_bufs.Add(cur_buf); + break; + } + + result_tmp_bufs.Add(cur_buf); + cur_buf = FX_Alloc(uint8_t, buf_size + 1); + cur_buf[buf_size] = '\0'; + } + dest_size = FPDFAPI_FlateGetTotalOut(context); + offset = FPDFAPI_FlateGetTotalIn(context); + if (result_tmp_bufs.GetSize() == 1) { + dest_buf = result_tmp_bufs[0]; + } else { + uint8_t* result_buf = FX_Alloc(uint8_t, dest_size); + FX_DWORD result_pos = 0; + for (int32_t i = 0; i < result_tmp_bufs.GetSize(); i++) { + uint8_t* tmp_buf = result_tmp_bufs[i]; + FX_DWORD tmp_buf_size = buf_size; + if (i == result_tmp_bufs.GetSize() - 1) { + tmp_buf_size = last_buf_size; + } + FXSYS_memcpy(result_buf + result_pos, tmp_buf, tmp_buf_size); + result_pos += tmp_buf_size; + FX_Free(result_tmp_bufs[i]); + } + dest_buf = result_buf; + } + } + FPDFAPI_FlateEnd(context); +} + +} // namespace + class CCodec_FlateScanlineDecoder : public CCodec_ScanlineDecoder { public: CCodec_FlateScanlineDecoder(); @@ -761,113 +885,7 @@ uint8_t* CCodec_FlateScanlineDecoder::v_GetNextLine() { FX_DWORD CCodec_FlateScanlineDecoder::GetSrcOffset() { return FPDFAPI_FlateGetTotalIn(m_pFlate); } -static void FlateUncompress(const uint8_t* src_buf, - FX_DWORD src_size, - FX_DWORD orig_size, - uint8_t*& dest_buf, - FX_DWORD& dest_size, - FX_DWORD& offset) { - const FX_BOOL useOldImpl = src_size < 10240; - FX_DWORD guess_size = orig_size ? orig_size : src_size * 2; - FX_DWORD alloc_step = - orig_size ? 10240 : (src_size < 10240 ? 10240 : src_size); - static const FX_DWORD kMaxInitialAllocSize = 10000000; - if (guess_size > kMaxInitialAllocSize) { - guess_size = kMaxInitialAllocSize; - alloc_step = kMaxInitialAllocSize; - } - FX_DWORD buf_size = guess_size; - FX_DWORD last_buf_size = buf_size; - void* context = nullptr; - uint8_t* guess_buf = FX_Alloc(uint8_t, guess_size + 1); - uint8_t* cur_buf = guess_buf; - guess_buf[guess_size] = '\0'; - context = FPDFAPI_FlateInit(my_alloc_func, my_free_func); - if (!context) - goto fail; - FPDFAPI_FlateInput(context, src_buf, src_size); - if (useOldImpl) { - while (1) { - int32_t ret = FPDFAPI_FlateOutput(context, cur_buf, buf_size); - if (ret != Z_OK) - break; - int32_t avail_buf_size = FPDFAPI_FlateGetAvailOut(context); - if (avail_buf_size != 0) - break; - - // |avail_buf_size| == 0 case. - FX_DWORD old_size = guess_size; - guess_size += alloc_step; - if (guess_size < old_size || guess_size + 1 < guess_size) - goto fail; - guess_buf = FX_Realloc(uint8_t, guess_buf, guess_size + 1); - if (!guess_buf) - goto fail; - guess_buf[guess_size] = '\0'; - cur_buf = guess_buf + old_size; - buf_size = guess_size - old_size; - } - dest_size = FPDFAPI_FlateGetTotalOut(context); - offset = FPDFAPI_FlateGetTotalIn(context); - if (guess_size / 2 > dest_size) { - guess_buf = FX_Realloc(uint8_t, guess_buf, dest_size + 1); - if (!guess_buf) - goto fail; - guess_size = dest_size; - guess_buf[guess_size] = '\0'; - } - dest_buf = guess_buf; - } else { - CFX_ArrayTemplate<uint8_t*> result_tmp_bufs; - while (1) { - int32_t ret = FPDFAPI_FlateOutput(context, cur_buf, buf_size); - int32_t avail_buf_size = FPDFAPI_FlateGetAvailOut(context); - if (ret != Z_OK) { - last_buf_size = buf_size - avail_buf_size; - result_tmp_bufs.Add(cur_buf); - break; - } - if (avail_buf_size != 0) { - last_buf_size = buf_size - avail_buf_size; - result_tmp_bufs.Add(cur_buf); - break; - } - - // |avail_buf_size| == 0 case. - result_tmp_bufs.Add(cur_buf); - cur_buf = FX_Alloc(uint8_t, buf_size + 1); - cur_buf[buf_size] = '\0'; - } - dest_size = FPDFAPI_FlateGetTotalOut(context); - offset = FPDFAPI_FlateGetTotalIn(context); - if (result_tmp_bufs.GetSize() == 1) { - dest_buf = result_tmp_bufs[0]; - } else { - uint8_t* result_buf = FX_Alloc(uint8_t, dest_size); - FX_DWORD result_pos = 0; - for (int32_t i = 0; i < result_tmp_bufs.GetSize(); i++) { - uint8_t* tmp_buf = result_tmp_bufs[i]; - FX_DWORD tmp_buf_size = buf_size; - if (i == result_tmp_bufs.GetSize() - 1) { - tmp_buf_size = last_buf_size; - } - FXSYS_memcpy(result_buf + result_pos, tmp_buf, tmp_buf_size); - result_pos += tmp_buf_size; - FX_Free(result_tmp_bufs[i]); - } - dest_buf = result_buf; - } - } - FPDFAPI_FlateEnd(context); - return; - -fail: - FX_Free(guess_buf); - dest_buf = nullptr; - dest_size = 0; - return; -} ICodec_ScanlineDecoder* CCodec_FlateModule::CreateDecoder( const uint8_t* src_buf, FX_DWORD src_size, |