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);