Index: core/src/fxcodec/codec/fx_codec_flate.cpp |
diff --git a/core/src/fxcodec/codec/fx_codec_flate.cpp b/core/src/fxcodec/codec/fx_codec_flate.cpp |
index 37aecf106d2e8bde56c874ab25abde5c6a0316b4..519ff0052254aa1b9c70bbe59242a8089d2d0651 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, |