Get rid of CCodec_ModuleMgr::GetBasicModule(). The CCodec_BasicModule class consists of a set of methods that can all be static. Make the methods static, and make sure CCodec_BasicModule cannot be instantiated. Then CCodec_ModuleMgr::GetBasicModule() becomes pointless and all the callers can just call CCodec_BasicModule directly. While making the above changes, move the CCodec_BasicModule code into its own separate file. Change-Id: I11981544f304dbd98ec8cc9e94506209758a338e Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/55030 Commit-Queue: Lei Zhang <thestig@chromium.org> Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fxcodec/codec/ccodec_basicmodule.cpp b/core/fxcodec/codec/ccodec_basicmodule.cpp new file mode 100644 index 0000000..ff3824d --- /dev/null +++ b/core/fxcodec/codec/ccodec_basicmodule.cpp
@@ -0,0 +1,372 @@ +// Copyright 2019 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "core/fxcodec/codec/ccodec_basicmodule.h" + +#include <algorithm> +#include <utility> + +#include "core/fxcodec/codec/ccodec_scanlinedecoder.h" +#include "third_party/base/ptr_util.h" + +namespace { + +class CCodec_RLScanlineDecoder final : public CCodec_ScanlineDecoder { + public: + CCodec_RLScanlineDecoder(); + ~CCodec_RLScanlineDecoder() override; + + bool Create(pdfium::span<const uint8_t> src_buf, + int width, + int height, + int nComps, + int bpc); + + // CCodec_ScanlineDecoder + bool v_Rewind() override; + uint8_t* v_GetNextLine() override; + uint32_t GetSrcOffset() override { return m_SrcOffset; } + + private: + bool CheckDestSize(); + void GetNextOperator(); + void UpdateOperator(uint8_t used_bytes); + + std::unique_ptr<uint8_t, FxFreeDeleter> m_pScanline; + pdfium::span<const uint8_t> m_SrcBuf; + size_t m_dwLineBytes = 0; + size_t m_SrcOffset = 0; + bool m_bEOD = false; + uint8_t m_Operator = 0; +}; + +CCodec_RLScanlineDecoder::CCodec_RLScanlineDecoder() = default; + +CCodec_RLScanlineDecoder::~CCodec_RLScanlineDecoder() = default; + +bool CCodec_RLScanlineDecoder::CheckDestSize() { + size_t i = 0; + uint32_t old_size = 0; + uint32_t dest_size = 0; + while (i < m_SrcBuf.size()) { + if (m_SrcBuf[i] < 128) { + old_size = dest_size; + dest_size += m_SrcBuf[i] + 1; + if (dest_size < old_size) { + return false; + } + i += m_SrcBuf[i] + 2; + } else if (m_SrcBuf[i] > 128) { + old_size = dest_size; + dest_size += 257 - m_SrcBuf[i]; + if (dest_size < old_size) { + return false; + } + i += 2; + } else { + break; + } + } + if (((uint32_t)m_OrigWidth * m_nComps * m_bpc * m_OrigHeight + 7) / 8 > + dest_size) { + return false; + } + return true; +} + +bool CCodec_RLScanlineDecoder::Create(pdfium::span<const uint8_t> src_buf, + int width, + int height, + int nComps, + int bpc) { + m_SrcBuf = src_buf; + m_OutputWidth = m_OrigWidth = width; + m_OutputHeight = m_OrigHeight = height; + m_nComps = nComps; + m_bpc = bpc; + // Aligning the pitch to 4 bytes requires an integer overflow check. + FX_SAFE_UINT32 pitch = width; + pitch *= nComps; + pitch *= bpc; + pitch += 31; + pitch /= 32; + pitch *= 4; + if (!pitch.IsValid()) { + return false; + } + m_Pitch = pitch.ValueOrDie(); + // Overflow should already have been checked before this is called. + m_dwLineBytes = (static_cast<uint32_t>(width) * nComps * bpc + 7) / 8; + m_pScanline.reset(FX_Alloc(uint8_t, m_Pitch)); + return CheckDestSize(); +} + +bool CCodec_RLScanlineDecoder::v_Rewind() { + memset(m_pScanline.get(), 0, m_Pitch); + m_SrcOffset = 0; + m_bEOD = false; + m_Operator = 0; + return true; +} + +uint8_t* CCodec_RLScanlineDecoder::v_GetNextLine() { + if (m_SrcOffset == 0) { + GetNextOperator(); + } else if (m_bEOD) { + return nullptr; + } + memset(m_pScanline.get(), 0, m_Pitch); + uint32_t col_pos = 0; + bool eol = false; + while (m_SrcOffset < m_SrcBuf.size() && !eol) { + if (m_Operator < 128) { + uint32_t copy_len = m_Operator + 1; + if (col_pos + copy_len >= m_dwLineBytes) { + copy_len = m_dwLineBytes - col_pos; + eol = true; + } + if (copy_len >= m_SrcBuf.size() - m_SrcOffset) { + copy_len = m_SrcBuf.size() - m_SrcOffset; + m_bEOD = true; + } + auto copy_span = m_SrcBuf.subspan(m_SrcOffset, copy_len); + memcpy(m_pScanline.get() + col_pos, copy_span.data(), copy_span.size()); + col_pos += copy_len; + UpdateOperator((uint8_t)copy_len); + } else if (m_Operator > 128) { + int fill = 0; + if (m_SrcOffset - 1 < m_SrcBuf.size() - 1) { + fill = m_SrcBuf[m_SrcOffset]; + } + uint32_t duplicate_len = 257 - m_Operator; + if (col_pos + duplicate_len >= m_dwLineBytes) { + duplicate_len = m_dwLineBytes - col_pos; + eol = true; + } + memset(m_pScanline.get() + col_pos, fill, duplicate_len); + col_pos += duplicate_len; + UpdateOperator((uint8_t)duplicate_len); + } else { + m_bEOD = true; + break; + } + } + return m_pScanline.get(); +} + +void CCodec_RLScanlineDecoder::GetNextOperator() { + if (m_SrcOffset >= m_SrcBuf.size()) { + m_Operator = 128; + return; + } + m_Operator = m_SrcBuf[m_SrcOffset]; + m_SrcOffset++; +} +void CCodec_RLScanlineDecoder::UpdateOperator(uint8_t used_bytes) { + if (used_bytes == 0) { + return; + } + if (m_Operator < 128) { + ASSERT((uint32_t)m_Operator + 1 >= used_bytes); + if (used_bytes == m_Operator + 1) { + m_SrcOffset += used_bytes; + GetNextOperator(); + return; + } + m_Operator -= used_bytes; + m_SrcOffset += used_bytes; + if (m_SrcOffset >= m_SrcBuf.size()) { + m_Operator = 128; + } + return; + } + uint8_t count = 257 - m_Operator; + ASSERT((uint32_t)count >= used_bytes); + if (used_bytes == count) { + m_SrcOffset++; + GetNextOperator(); + return; + } + count -= used_bytes; + m_Operator = 257 - count; +} + +} // namespace + +// static +std::unique_ptr<CCodec_ScanlineDecoder> +CCodec_BasicModule::CreateRunLengthDecoder(pdfium::span<const uint8_t> src_buf, + int width, + int height, + int nComps, + int bpc) { + auto pDecoder = pdfium::MakeUnique<CCodec_RLScanlineDecoder>(); + if (!pDecoder->Create(src_buf, width, height, nComps, bpc)) + return nullptr; + + return std::move(pDecoder); +} + +// static +bool CCodec_BasicModule::RunLengthEncode( + pdfium::span<const uint8_t> src_span, + std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf, + uint32_t* dest_size) { + // Check inputs + if (src_span.empty() || !dest_buf || !dest_size) + return false; + + // Edge case + if (src_span.size() == 1) { + *dest_size = 3; + dest_buf->reset(FX_Alloc(uint8_t, *dest_size)); + auto dest_buf_span = pdfium::make_span(dest_buf->get(), *dest_size); + dest_buf_span[0] = 0; + dest_buf_span[1] = src_span[0]; + dest_buf_span[2] = 128; + return true; + } + + // Worst case: 1 nonmatch, 2 match, 1 nonmatch, 2 match, etc. This becomes + // 4 output chars for every 3 input, plus up to 4 more for the 1-2 chars + // rounded off plus the terminating character. + FX_SAFE_SIZE_T estimated_size = src_span.size(); + estimated_size += 2; + estimated_size /= 3; + estimated_size *= 4; + estimated_size += 1; + dest_buf->reset(FX_Alloc(uint8_t, estimated_size.ValueOrDie())); + + // Set up pointers. + uint8_t* out = dest_buf->get(); + uint32_t run_start = 0; + uint32_t run_end = 1; + uint8_t x = src_span[run_start]; + uint8_t y = src_span[run_end]; + while (run_end < src_span.size()) { + size_t max_len = std::min<size_t>(128, src_span.size() - run_start); + while (x == y && (run_end - run_start < max_len - 1)) + y = src_span[++run_end]; + + // Reached end with matched run. Update variables to expected values. + if (x == y) { + run_end++; + if (run_end < src_span.size()) + y = src_span[run_end]; + } + if (run_end - run_start > 1) { // Matched run but not at end of input. + out[0] = 257 - (run_end - run_start); + out[1] = x; + x = y; + run_start = run_end; + run_end++; + if (run_end < src_span.size()) + y = src_span[run_end]; + out += 2; + continue; + } + // Mismatched run + while (x != y && run_end <= run_start + max_len) { + out[run_end - run_start] = x; + x = y; + run_end++; + if (run_end == src_span.size()) { + if (run_end <= run_start + max_len) { + out[run_end - run_start] = x; + run_end++; + } + break; + } + y = src_span[run_end]; + } + out[0] = run_end - run_start - 2; + out += run_end - run_start; + run_start = run_end - 1; + } + if (run_start < src_span.size()) { // 1 leftover character + out[0] = 0; + out[1] = x; + out += 2; + } + *out = 128; + *dest_size = out + 1 - dest_buf->get(); + return true; +} + +// static +bool CCodec_BasicModule::A85Encode( + pdfium::span<const uint8_t> src_span, + std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf, + uint32_t* dest_size) { + // Check inputs. + if (!dest_buf || !dest_size) + return false; + + if (src_span.empty()) { + *dest_size = 0; + return false; + } + + // Worst case: 5 output for each 4 input (plus up to 4 from leftover), plus + // 2 character new lines each 75 output chars plus 2 termination chars. May + // have fewer if there are special "z" chars. + FX_SAFE_SIZE_T estimated_size = src_span.size(); + estimated_size /= 4; + estimated_size *= 5; + estimated_size += 4; + estimated_size += src_span.size() / 30; + estimated_size += 2; + dest_buf->reset(FX_Alloc(uint8_t, estimated_size.ValueOrDie())); + + // Set up pointers. + uint8_t* out = dest_buf->get(); + uint32_t pos = 0; + uint32_t line_length = 0; + while (src_span.size() >= 4 && pos < src_span.size() - 3) { + uint32_t val = ((uint32_t)(src_span[pos]) << 24) + + ((uint32_t)(src_span[pos + 1]) << 16) + + ((uint32_t)(src_span[pos + 2]) << 8) + + (uint32_t)(src_span[pos + 3]); + pos += 4; + if (val == 0) { // All zero special case + *out = 'z'; + out++; + line_length++; + } else { // Compute base 85 characters and add 33. + for (int i = 4; i >= 0; i--) { + out[i] = (uint8_t)(val % 85) + 33; + val = val / 85; + } + out += 5; + line_length += 5; + } + if (line_length >= 75) { // Add a return. + *out++ = '\r'; + *out++ = '\n'; + line_length = 0; + } + } + if (pos < src_span.size()) { // Leftover bytes + uint32_t val = 0; + int count = 0; + while (pos < src_span.size()) { + val += (uint32_t)(src_span[pos]) << (8 * (3 - count)); + count++; + pos++; + } + for (int i = 4; i >= 0; i--) { + if (i <= count) + out[i] = (uint8_t)(val % 85) + 33; + val = val / 85; + } + out += count + 1; + } + + // Terminating characters. + out[0] = '~'; + out[1] = '>'; + out += 2; + *dest_size = out - dest_buf->get(); + return true; +}
diff --git a/core/fxcodec/codec/ccodec_basicmodule.h b/core/fxcodec/codec/ccodec_basicmodule.h index 72dd016..8f55901 100644 --- a/core/fxcodec/codec/ccodec_basicmodule.h +++ b/core/fxcodec/codec/ccodec_basicmodule.h
@@ -17,20 +17,24 @@ class CCodec_BasicModule { public: - std::unique_ptr<CCodec_ScanlineDecoder> CreateRunLengthDecoder( + static std::unique_ptr<CCodec_ScanlineDecoder> CreateRunLengthDecoder( pdfium::span<const uint8_t> src_buf, int width, int height, int nComps, int bpc); - bool RunLengthEncode(pdfium::span<const uint8_t> src_buf, - std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf, - uint32_t* dest_size); + static bool RunLengthEncode(pdfium::span<const uint8_t> src_buf, + std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf, + uint32_t* dest_size); - bool A85Encode(pdfium::span<const uint8_t> src_buf, - std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf, - uint32_t* dest_size); + static bool A85Encode(pdfium::span<const uint8_t> src_buf, + std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf, + uint32_t* dest_size); + + CCodec_BasicModule() = delete; + CCodec_BasicModule(const CCodec_BasicModule&) = delete; + CCodec_BasicModule& operator=(const CCodec_BasicModule&) = delete; }; #endif // CORE_FXCODEC_CODEC_CCODEC_BASICMODULE_H_
diff --git a/core/fxcodec/codec/fx_codec.cpp b/core/fxcodec/codec/fx_codec.cpp index 0a34a1d..e2ba733 100644 --- a/core/fxcodec/codec/fx_codec.cpp +++ b/core/fxcodec/codec/fx_codec.cpp
@@ -11,13 +11,11 @@ #include <memory> #include <utility> -#include "core/fxcodec/codec/ccodec_basicmodule.h" #include "core/fxcodec/codec/ccodec_faxmodule.h" #include "core/fxcodec/codec/ccodec_iccmodule.h" #include "core/fxcodec/codec/ccodec_jbig2module.h" #include "core/fxcodec/codec/ccodec_jpegmodule.h" #include "core/fxcodec/codec/ccodec_jpxmodule.h" -#include "core/fxcodec/codec/ccodec_scanlinedecoder.h" #include "core/fxcodec/codec/codec_int.h" #include "core/fxcrt/fx_extension.h" #include "core/fxcrt/fx_safe_types.h" @@ -25,8 +23,7 @@ #include "third_party/base/ptr_util.h" CCodec_ModuleMgr::CCodec_ModuleMgr() - : m_pBasicModule(pdfium::MakeUnique<CCodec_BasicModule>()), - m_pFaxModule(pdfium::MakeUnique<CCodec_FaxModule>()), + : m_pFaxModule(pdfium::MakeUnique<CCodec_FaxModule>()), m_pJpegModule(pdfium::MakeUnique<CCodec_JpegModule>()), m_pJpxModule(pdfium::MakeUnique<CCodec_JpxModule>()), m_pJbig2Module(pdfium::MakeUnique<CCodec_Jbig2Module>()), @@ -34,167 +31,6 @@ CCodec_ModuleMgr::~CCodec_ModuleMgr() = default; -bool CCodec_BasicModule::RunLengthEncode( - pdfium::span<const uint8_t> src_span, - std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf, - uint32_t* dest_size) { - // Check inputs - if (src_span.empty() || !dest_buf || !dest_size) - return false; - - // Edge case - if (src_span.size() == 1) { - *dest_size = 3; - dest_buf->reset(FX_Alloc(uint8_t, *dest_size)); - auto dest_buf_span = pdfium::make_span(dest_buf->get(), *dest_size); - dest_buf_span[0] = 0; - dest_buf_span[1] = src_span[0]; - dest_buf_span[2] = 128; - return true; - } - - // Worst case: 1 nonmatch, 2 match, 1 nonmatch, 2 match, etc. This becomes - // 4 output chars for every 3 input, plus up to 4 more for the 1-2 chars - // rounded off plus the terminating character. - FX_SAFE_SIZE_T estimated_size = src_span.size(); - estimated_size += 2; - estimated_size /= 3; - estimated_size *= 4; - estimated_size += 1; - dest_buf->reset(FX_Alloc(uint8_t, estimated_size.ValueOrDie())); - - // Set up pointers. - uint8_t* out = dest_buf->get(); - uint32_t run_start = 0; - uint32_t run_end = 1; - uint8_t x = src_span[run_start]; - uint8_t y = src_span[run_end]; - while (run_end < src_span.size()) { - size_t max_len = std::min<size_t>(128, src_span.size() - run_start); - while (x == y && (run_end - run_start < max_len - 1)) - y = src_span[++run_end]; - - // Reached end with matched run. Update variables to expected values. - if (x == y) { - run_end++; - if (run_end < src_span.size()) - y = src_span[run_end]; - } - if (run_end - run_start > 1) { // Matched run but not at end of input. - out[0] = 257 - (run_end - run_start); - out[1] = x; - x = y; - run_start = run_end; - run_end++; - if (run_end < src_span.size()) - y = src_span[run_end]; - out += 2; - continue; - } - // Mismatched run - while (x != y && run_end <= run_start + max_len) { - out[run_end - run_start] = x; - x = y; - run_end++; - if (run_end == src_span.size()) { - if (run_end <= run_start + max_len) { - out[run_end - run_start] = x; - run_end++; - } - break; - } - y = src_span[run_end]; - } - out[0] = run_end - run_start - 2; - out += run_end - run_start; - run_start = run_end - 1; - } - if (run_start < src_span.size()) { // 1 leftover character - out[0] = 0; - out[1] = x; - out += 2; - } - *out = 128; - *dest_size = out + 1 - dest_buf->get(); - return true; -} - -bool CCodec_BasicModule::A85Encode( - pdfium::span<const uint8_t> src_span, - std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf, - uint32_t* dest_size) { - // Check inputs. - if (!dest_buf || !dest_size) - return false; - - if (src_span.empty()) { - *dest_size = 0; - return false; - } - - // Worst case: 5 output for each 4 input (plus up to 4 from leftover), plus - // 2 character new lines each 75 output chars plus 2 termination chars. May - // have fewer if there are special "z" chars. - FX_SAFE_SIZE_T estimated_size = src_span.size(); - estimated_size /= 4; - estimated_size *= 5; - estimated_size += 4; - estimated_size += src_span.size() / 30; - estimated_size += 2; - dest_buf->reset(FX_Alloc(uint8_t, estimated_size.ValueOrDie())); - - // Set up pointers. - uint8_t* out = dest_buf->get(); - uint32_t pos = 0; - uint32_t line_length = 0; - while (src_span.size() >= 4 && pos < src_span.size() - 3) { - uint32_t val = ((uint32_t)(src_span[pos]) << 24) + - ((uint32_t)(src_span[pos + 1]) << 16) + - ((uint32_t)(src_span[pos + 2]) << 8) + - (uint32_t)(src_span[pos + 3]); - pos += 4; - if (val == 0) { // All zero special case - *out = 'z'; - out++; - line_length++; - } else { // Compute base 85 characters and add 33. - for (int i = 4; i >= 0; i--) { - out[i] = (uint8_t)(val % 85) + 33; - val = val / 85; - } - out += 5; - line_length += 5; - } - if (line_length >= 75) { // Add a return. - *out++ = '\r'; - *out++ = '\n'; - line_length = 0; - } - } - if (pos < src_span.size()) { // Leftover bytes - uint32_t val = 0; - int count = 0; - while (pos < src_span.size()) { - val += (uint32_t)(src_span[pos]) << (8 * (3 - count)); - count++; - pos++; - } - for (int i = 4; i >= 0; i--) { - if (i <= count) - out[i] = (uint8_t)(val % 85) + 33; - val = val / 85; - } - out += count + 1; - } - - // Terminating characters. - out[0] = '~'; - out[1] = '>'; - out += 2; - *dest_size = out - dest_buf->get(); - return true; -} - #ifdef PDF_ENABLE_XFA CFX_DIBAttribute::CFX_DIBAttribute() {} @@ -204,199 +40,6 @@ } #endif // PDF_ENABLE_XFA -class CCodec_RLScanlineDecoder final : public CCodec_ScanlineDecoder { - public: - CCodec_RLScanlineDecoder(); - ~CCodec_RLScanlineDecoder() override; - - bool Create(pdfium::span<const uint8_t> src_buf, - int width, - int height, - int nComps, - int bpc); - - // CCodec_ScanlineDecoder - bool v_Rewind() override; - uint8_t* v_GetNextLine() override; - uint32_t GetSrcOffset() override { return m_SrcOffset; } - - private: - bool CheckDestSize(); - void GetNextOperator(); - void UpdateOperator(uint8_t used_bytes); - - std::unique_ptr<uint8_t, FxFreeDeleter> m_pScanline; - pdfium::span<const uint8_t> m_SrcBuf; - size_t m_dwLineBytes = 0; - size_t m_SrcOffset = 0; - bool m_bEOD = false; - uint8_t m_Operator = 0; -}; - -CCodec_RLScanlineDecoder::CCodec_RLScanlineDecoder() = default; - -CCodec_RLScanlineDecoder::~CCodec_RLScanlineDecoder() = default; - -bool CCodec_RLScanlineDecoder::CheckDestSize() { - size_t i = 0; - uint32_t old_size = 0; - uint32_t dest_size = 0; - while (i < m_SrcBuf.size()) { - if (m_SrcBuf[i] < 128) { - old_size = dest_size; - dest_size += m_SrcBuf[i] + 1; - if (dest_size < old_size) { - return false; - } - i += m_SrcBuf[i] + 2; - } else if (m_SrcBuf[i] > 128) { - old_size = dest_size; - dest_size += 257 - m_SrcBuf[i]; - if (dest_size < old_size) { - return false; - } - i += 2; - } else { - break; - } - } - if (((uint32_t)m_OrigWidth * m_nComps * m_bpc * m_OrigHeight + 7) / 8 > - dest_size) { - return false; - } - return true; -} - -bool CCodec_RLScanlineDecoder::Create(pdfium::span<const uint8_t> src_buf, - int width, - int height, - int nComps, - int bpc) { - m_SrcBuf = src_buf; - m_OutputWidth = m_OrigWidth = width; - m_OutputHeight = m_OrigHeight = height; - m_nComps = nComps; - m_bpc = bpc; - // Aligning the pitch to 4 bytes requires an integer overflow check. - FX_SAFE_UINT32 pitch = width; - pitch *= nComps; - pitch *= bpc; - pitch += 31; - pitch /= 32; - pitch *= 4; - if (!pitch.IsValid()) { - return false; - } - m_Pitch = pitch.ValueOrDie(); - // Overflow should already have been checked before this is called. - m_dwLineBytes = (static_cast<uint32_t>(width) * nComps * bpc + 7) / 8; - m_pScanline.reset(FX_Alloc(uint8_t, m_Pitch)); - return CheckDestSize(); -} - -bool CCodec_RLScanlineDecoder::v_Rewind() { - memset(m_pScanline.get(), 0, m_Pitch); - m_SrcOffset = 0; - m_bEOD = false; - m_Operator = 0; - return true; -} - -uint8_t* CCodec_RLScanlineDecoder::v_GetNextLine() { - if (m_SrcOffset == 0) { - GetNextOperator(); - } else if (m_bEOD) { - return nullptr; - } - memset(m_pScanline.get(), 0, m_Pitch); - uint32_t col_pos = 0; - bool eol = false; - while (m_SrcOffset < m_SrcBuf.size() && !eol) { - if (m_Operator < 128) { - uint32_t copy_len = m_Operator + 1; - if (col_pos + copy_len >= m_dwLineBytes) { - copy_len = m_dwLineBytes - col_pos; - eol = true; - } - if (copy_len >= m_SrcBuf.size() - m_SrcOffset) { - copy_len = m_SrcBuf.size() - m_SrcOffset; - m_bEOD = true; - } - auto copy_span = m_SrcBuf.subspan(m_SrcOffset, copy_len); - memcpy(m_pScanline.get() + col_pos, copy_span.data(), copy_span.size()); - col_pos += copy_len; - UpdateOperator((uint8_t)copy_len); - } else if (m_Operator > 128) { - int fill = 0; - if (m_SrcOffset - 1 < m_SrcBuf.size() - 1) { - fill = m_SrcBuf[m_SrcOffset]; - } - uint32_t duplicate_len = 257 - m_Operator; - if (col_pos + duplicate_len >= m_dwLineBytes) { - duplicate_len = m_dwLineBytes - col_pos; - eol = true; - } - memset(m_pScanline.get() + col_pos, fill, duplicate_len); - col_pos += duplicate_len; - UpdateOperator((uint8_t)duplicate_len); - } else { - m_bEOD = true; - break; - } - } - return m_pScanline.get(); -} - -void CCodec_RLScanlineDecoder::GetNextOperator() { - if (m_SrcOffset >= m_SrcBuf.size()) { - m_Operator = 128; - return; - } - m_Operator = m_SrcBuf[m_SrcOffset]; - m_SrcOffset++; -} -void CCodec_RLScanlineDecoder::UpdateOperator(uint8_t used_bytes) { - if (used_bytes == 0) { - return; - } - if (m_Operator < 128) { - ASSERT((uint32_t)m_Operator + 1 >= used_bytes); - if (used_bytes == m_Operator + 1) { - m_SrcOffset += used_bytes; - GetNextOperator(); - return; - } - m_Operator -= used_bytes; - m_SrcOffset += used_bytes; - if (m_SrcOffset >= m_SrcBuf.size()) { - m_Operator = 128; - } - return; - } - uint8_t count = 257 - m_Operator; - ASSERT((uint32_t)count >= used_bytes); - if (used_bytes == count) { - m_SrcOffset++; - GetNextOperator(); - return; - } - count -= used_bytes; - m_Operator = 257 - count; -} - -std::unique_ptr<CCodec_ScanlineDecoder> -CCodec_BasicModule::CreateRunLengthDecoder(pdfium::span<const uint8_t> src_buf, - int width, - int height, - int nComps, - int bpc) { - auto pDecoder = pdfium::MakeUnique<CCodec_RLScanlineDecoder>(); - if (!pDecoder->Create(src_buf, width, height, nComps, bpc)) - return nullptr; - - return std::move(pDecoder); -} - FX_SAFE_UINT32 CalculatePitch8(uint32_t bpc, uint32_t components, int width) { FX_SAFE_UINT32 pitch = bpc; pitch *= components;
diff --git a/core/fxcodec/codec/fx_codec_a85_unittest.cpp b/core/fxcodec/codec/fx_codec_a85_unittest.cpp index 1372858..c6eb34d 100644 --- a/core/fxcodec/codec/fx_codec_a85_unittest.cpp +++ b/core/fxcodec/codec/fx_codec_a85_unittest.cpp
@@ -8,7 +8,6 @@ #include <memory> #include "core/fxcodec/codec/ccodec_basicmodule.h" -#include "core/fxcodec/fx_codec.h" #include "testing/gtest/include/gtest/gtest.h" TEST(fxcodec, A85TestBadInputs) { @@ -16,25 +15,19 @@ std::unique_ptr<uint8_t, FxFreeDeleter> dest_buf; uint32_t dest_size = 0; - CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); - EXPECT_TRUE(pEncoders); - // Error codes, not segvs, should callers pass us a nullptr pointer. - EXPECT_FALSE(pEncoders->A85Encode(src_buf, &dest_buf, nullptr)); - EXPECT_FALSE(pEncoders->A85Encode(src_buf, nullptr, &dest_size)); - EXPECT_FALSE(pEncoders->A85Encode({}, &dest_buf, &dest_size)); + EXPECT_FALSE(CCodec_BasicModule::A85Encode(src_buf, &dest_buf, nullptr)); + EXPECT_FALSE(CCodec_BasicModule::A85Encode(src_buf, nullptr, &dest_size)); + EXPECT_FALSE(CCodec_BasicModule::A85Encode({}, &dest_buf, &dest_size)); } // No leftover bytes, just translate 2 sets of symbols. TEST(fxcodec, A85TestBasic) { - CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); - EXPECT_TRUE(pEncoders); - // Make sure really big values don't break. const uint8_t src_buf[] = {1, 2, 3, 4, 255, 255, 255, 255}; std::unique_ptr<uint8_t, FxFreeDeleter> dest_buf; uint32_t dest_size = 0; - EXPECT_TRUE(pEncoders->A85Encode(src_buf, &dest_buf, &dest_size)); + EXPECT_TRUE(CCodec_BasicModule::A85Encode(src_buf, &dest_buf, &dest_size)); // Should have 5 chars for each set of 4 and 2 terminators. const uint8_t expected_out[] = {33, 60, 78, 63, 43, 115, @@ -49,16 +42,14 @@ // Leftover bytes. TEST(fxcodec, A85TestLeftoverBytes) { - CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); - EXPECT_TRUE(pEncoders); - std::unique_ptr<uint8_t, FxFreeDeleter> dest_buf; uint32_t dest_size = 0; { // 1 Leftover Byte: const uint8_t src_buf_1leftover[] = {1, 2, 3, 4, 255}; - EXPECT_TRUE(pEncoders->A85Encode(src_buf_1leftover, &dest_buf, &dest_size)); + EXPECT_TRUE(CCodec_BasicModule::A85Encode(src_buf_1leftover, &dest_buf, + &dest_size)); // 5 chars for first symbol + 2 + 2 terminators. uint8_t expected_out_1leftover[] = {33, 60, 78, 63, 43, 114, 114, 126, 62}; @@ -75,7 +66,8 @@ const uint8_t src_buf_2leftover[] = {1, 2, 3, 4, 255, 254}; dest_buf.reset(); dest_size = 0; - EXPECT_TRUE(pEncoders->A85Encode(src_buf_2leftover, &dest_buf, &dest_size)); + EXPECT_TRUE(CCodec_BasicModule::A85Encode(src_buf_2leftover, &dest_buf, + &dest_size)); // 5 chars for first symbol + 3 + 2 terminators. const uint8_t expected_out_2leftover[] = {33, 60, 78, 63, 43, 115, 56, 68, 126, 62}; @@ -92,7 +84,8 @@ const uint8_t src_buf_3leftover[] = {1, 2, 3, 4, 255, 254, 253}; dest_buf.reset(); dest_size = 0; - EXPECT_TRUE(pEncoders->A85Encode(src_buf_3leftover, &dest_buf, &dest_size)); + EXPECT_TRUE(CCodec_BasicModule::A85Encode(src_buf_3leftover, &dest_buf, + &dest_size)); // 5 chars for first symbol + 4 + 2 terminators. const uint8_t expected_out_3leftover[] = {33, 60, 78, 63, 43, 115, 56, 77, 114, 126, 62}; @@ -107,16 +100,13 @@ // Test all zeros comes through as "z". TEST(fxcodec, A85TestZeros) { - CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); - EXPECT_TRUE(pEncoders); - std::unique_ptr<uint8_t, FxFreeDeleter> dest_buf; uint32_t dest_size = 0; { // Make sure really big values don't break. const uint8_t src_buf[] = {1, 2, 3, 4, 0, 0, 0, 0}; - EXPECT_TRUE(pEncoders->A85Encode(src_buf, &dest_buf, &dest_size)); + EXPECT_TRUE(CCodec_BasicModule::A85Encode(src_buf, &dest_buf, &dest_size)); // Should have 5 chars for first set of 4 + 1 for z + 2 terminators. const uint8_t expected_out[] = {33, 60, 78, 63, 43, 122, 126, 62}; @@ -133,7 +123,8 @@ const uint8_t src_buf_2[] = {0, 0, 0, 0, 1, 2, 3, 4}; dest_buf.reset(); dest_size = 0; - EXPECT_TRUE(pEncoders->A85Encode(src_buf_2, &dest_buf, &dest_size)); + EXPECT_TRUE( + CCodec_BasicModule::A85Encode(src_buf_2, &dest_buf, &dest_size)); // Should have 5 chars for set of 4 + 1 for z + 2 terminators. const uint8_t expected_out_2[] = {122, 33, 60, 78, 63, 43, 126, 62}; @@ -150,7 +141,8 @@ const uint8_t src_buf_3[] = {1, 2, 3, 4, 0, 0}; dest_buf.reset(); dest_size = 0; - EXPECT_TRUE(pEncoders->A85Encode(src_buf_3, &dest_buf, &dest_size)); + EXPECT_TRUE( + CCodec_BasicModule::A85Encode(src_buf_3, &dest_buf, &dest_size)); // Should have 5 chars for set of 4 + 3 for last 2 + 2 terminators. const uint8_t expected_out_leftover[] = {33, 60, 78, 63, 43, @@ -185,11 +177,8 @@ std::unique_ptr<uint8_t, FxFreeDeleter> dest_buf; uint32_t dest_size = 0; - CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); - EXPECT_TRUE(pEncoders); - // Should succeed. - EXPECT_TRUE(pEncoders->A85Encode(src_buf, &dest_buf, &dest_size)); + EXPECT_TRUE(CCodec_BasicModule::A85Encode(src_buf, &dest_buf, &dest_size)); // Should have 75 chars in the first row plus 2 char return, // 76 chars in the second row plus 2 char return,
diff --git a/core/fxcodec/codec/fx_codec_rle_unittest.cpp b/core/fxcodec/codec/fx_codec_rle_unittest.cpp index 433d96d..b0323c1 100644 --- a/core/fxcodec/codec/fx_codec_rle_unittest.cpp +++ b/core/fxcodec/codec/fx_codec_rle_unittest.cpp
@@ -9,7 +9,6 @@ #include "core/fpdfapi/parser/fpdf_parser_decode.h" #include "core/fxcodec/codec/ccodec_basicmodule.h" -#include "core/fxcodec/fx_codec.h" #include "testing/gtest/include/gtest/gtest.h" TEST(fxcodec, RLETestBadInputs) { @@ -17,25 +16,22 @@ std::unique_ptr<uint8_t, FxFreeDeleter> dest_buf; uint32_t dest_size = 0; - CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); - EXPECT_TRUE(pEncoders); - // Error codes, not segvs, should callers pass us a nullptr pointer. - EXPECT_FALSE(pEncoders->RunLengthEncode(src_buf, &dest_buf, nullptr)); - EXPECT_FALSE(pEncoders->RunLengthEncode(src_buf, nullptr, &dest_size)); - EXPECT_FALSE(pEncoders->RunLengthEncode({}, &dest_buf, &dest_size)); + EXPECT_FALSE( + CCodec_BasicModule::RunLengthEncode(src_buf, &dest_buf, nullptr)); + EXPECT_FALSE( + CCodec_BasicModule::RunLengthEncode(src_buf, nullptr, &dest_size)); + EXPECT_FALSE(CCodec_BasicModule::RunLengthEncode({}, &dest_buf, &dest_size)); } // Check length 1 input works. Check terminating character is applied. TEST(fxcodec, RLETestShortInput) { - CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); - EXPECT_TRUE(pEncoders); - const uint8_t src_buf[] = {1}; std::unique_ptr<uint8_t, FxFreeDeleter> dest_buf; uint32_t dest_size = 0; - EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf, &dest_buf, &dest_size)); + EXPECT_TRUE( + CCodec_BasicModule::RunLengthEncode(src_buf, &dest_buf, &dest_size)); ASSERT_EQ(3u, dest_size); auto dest_buf_span = pdfium::make_span(dest_buf.get(), dest_size); EXPECT_EQ(0, dest_buf_span[0]); @@ -46,9 +42,6 @@ // Check a few basic cases (2 matching runs in a row, matching run followed // by a non-matching run, and non-matching run followed by a matching run). TEST(fxcodec, RLETestNormalInputs) { - CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); - EXPECT_TRUE(pEncoders); - std::unique_ptr<uint8_t, FxFreeDeleter> dest_buf; uint32_t dest_size = 0; std::unique_ptr<uint8_t, FxFreeDeleter> decoded_buf; @@ -57,7 +50,8 @@ { // Case 1: Match, match const uint8_t src_buf_1[] = {2, 2, 2, 2, 4, 4, 4, 4, 4, 4}; - EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_1, &dest_buf, &dest_size)); + EXPECT_TRUE( + CCodec_BasicModule::RunLengthEncode(src_buf_1, &dest_buf, &dest_size)); RunLengthDecode({dest_buf.get(), dest_size}, &decoded_buf, &decoded_size); ASSERT_EQ(sizeof(src_buf_1), decoded_size); auto decoded_buf_span = pdfium::make_span(decoded_buf.get(), decoded_size); @@ -70,7 +64,8 @@ const uint8_t src_buf_2[] = {2, 2, 2, 2, 1, 2, 3, 4, 5, 6}; dest_buf.reset(); dest_size = 0; - EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_2, &dest_buf, &dest_size)); + EXPECT_TRUE( + CCodec_BasicModule::RunLengthEncode(src_buf_2, &dest_buf, &dest_size)); decoded_buf.reset(); decoded_size = 0; RunLengthDecode({dest_buf.get(), dest_size}, &decoded_buf, &decoded_size); @@ -85,7 +80,8 @@ const uint8_t src_buf_3[] = {1, 2, 3, 4, 5, 3, 3, 3, 3, 3}; dest_buf.reset(); dest_size = 0; - EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_3, &dest_buf, &dest_size)); + EXPECT_TRUE( + CCodec_BasicModule::RunLengthEncode(src_buf_3, &dest_buf, &dest_size)); decoded_buf.reset(); decoded_size = 0; RunLengthDecode({dest_buf.get(), dest_size}, &decoded_buf, &decoded_size); @@ -99,9 +95,6 @@ // Check that runs longer than 128 are broken up properly, both matched and // non-matched. TEST(fxcodec, RLETestFullLengthInputs) { - CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); - EXPECT_TRUE(pEncoders); - std::unique_ptr<uint8_t, FxFreeDeleter> dest_buf; uint32_t dest_size = 0; std::unique_ptr<uint8_t, FxFreeDeleter> decoded_buf; @@ -110,7 +103,8 @@ { // Case 1: Match, match const uint8_t src_buf_1[260] = {1}; - EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_1, &dest_buf, &dest_size)); + EXPECT_TRUE( + CCodec_BasicModule::RunLengthEncode(src_buf_1, &dest_buf, &dest_size)); RunLengthDecode({dest_buf.get(), dest_size}, &decoded_buf, &decoded_size); ASSERT_EQ(sizeof(src_buf_1), decoded_size); auto decoded_buf_span = pdfium::make_span(decoded_buf.get(), decoded_size); @@ -125,7 +119,8 @@ src_buf_2[i] = static_cast<uint8_t>(i - 125); dest_buf.reset(); dest_size = 0; - EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_2, &dest_buf, &dest_size)); + EXPECT_TRUE( + CCodec_BasicModule::RunLengthEncode(src_buf_2, &dest_buf, &dest_size)); decoded_buf.reset(); decoded_size = 0; RunLengthDecode({dest_buf.get(), dest_size}, &decoded_buf, &decoded_size); @@ -142,7 +137,8 @@ src_buf_3[i] = i; dest_buf.reset(); dest_size = 0; - EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_3, &dest_buf, &dest_size)); + EXPECT_TRUE( + CCodec_BasicModule::RunLengthEncode(src_buf_3, &dest_buf, &dest_size)); decoded_buf.reset(); decoded_size = 0; RunLengthDecode({dest_buf.get(), dest_size}, &decoded_buf, &decoded_size); @@ -159,7 +155,8 @@ src_buf_4[i] = static_cast<uint8_t>(i); dest_buf.reset(); dest_size = 0; - EXPECT_TRUE(pEncoders->RunLengthEncode(src_buf_4, &dest_buf, &dest_size)); + EXPECT_TRUE( + CCodec_BasicModule::RunLengthEncode(src_buf_4, &dest_buf, &dest_size)); decoded_buf.reset(); decoded_size = 0; RunLengthDecode({dest_buf.get(), dest_size}, &decoded_buf, &decoded_size);