summaryrefslogtreecommitdiff
path: root/core/fxcodec/jbig2
diff options
context:
space:
mode:
Diffstat (limited to 'core/fxcodec/jbig2')
-rw-r--r--core/fxcodec/jbig2/JBig2_ArithDecoder.cpp120
-rw-r--r--core/fxcodec/jbig2/JBig2_ArithDecoder.h38
-rw-r--r--core/fxcodec/jbig2/JBig2_ArithIntDecoder.cpp92
-rw-r--r--core/fxcodec/jbig2/JBig2_ArithIntDecoder.h41
-rw-r--r--core/fxcodec/jbig2/JBig2_BitStream.cpp188
-rw-r--r--core/fxcodec/jbig2/JBig2_BitStream.h58
-rw-r--r--core/fxcodec/jbig2/JBig2_Context.cpp1439
-rw-r--r--core/fxcodec/jbig2/JBig2_Context.h134
-rw-r--r--core/fxcodec/jbig2/JBig2_Define.h36
-rw-r--r--core/fxcodec/jbig2/JBig2_GrdProc.cpp1259
-rw-r--r--core/fxcodec/jbig2/JBig2_GrdProc.h124
-rw-r--r--core/fxcodec/jbig2/JBig2_GrrdProc.cpp516
-rw-r--r--core/fxcodec/jbig2/JBig2_GrrdProc.h43
-rw-r--r--core/fxcodec/jbig2/JBig2_GsidProc.cpp123
-rw-r--r--core/fxcodec/jbig2/JBig2_GsidProc.h36
-rw-r--r--core/fxcodec/jbig2/JBig2_HtrdProc.cpp104
-rw-r--r--core/fxcodec/jbig2/JBig2_HtrdProc.h46
-rw-r--r--core/fxcodec/jbig2/JBig2_HuffmanDecoder.cpp45
-rw-r--r--core/fxcodec/jbig2/JBig2_HuffmanDecoder.h24
-rw-r--r--core/fxcodec/jbig2/JBig2_HuffmanTable.cpp136
-rw-r--r--core/fxcodec/jbig2/JBig2_HuffmanTable.h50
-rw-r--r--core/fxcodec/jbig2/JBig2_HuffmanTable_Standard.h98
-rw-r--r--core/fxcodec/jbig2/JBig2_Image.cpp1099
-rw-r--r--core/fxcodec/jbig2/JBig2_Image.h85
-rw-r--r--core/fxcodec/jbig2/JBig2_List.h54
-rw-r--r--core/fxcodec/jbig2/JBig2_Page.h22
-rw-r--r--core/fxcodec/jbig2/JBig2_PatternDict.cpp23
-rw-r--r--core/fxcodec/jbig2/JBig2_PatternDict.h23
-rw-r--r--core/fxcodec/jbig2/JBig2_PddProc.cpp87
-rw-r--r--core/fxcodec/jbig2/JBig2_PddProc.h34
-rw-r--r--core/fxcodec/jbig2/JBig2_SddProc.cpp624
-rw-r--r--core/fxcodec/jbig2/JBig2_SddProc.h49
-rw-r--r--core/fxcodec/jbig2/JBig2_Segment.cpp44
-rw-r--r--core/fxcodec/jbig2/JBig2_Segment.h66
-rw-r--r--core/fxcodec/jbig2/JBig2_SymbolDict.cpp26
-rw-r--r--core/fxcodec/jbig2/JBig2_SymbolDict.h48
-rw-r--r--core/fxcodec/jbig2/JBig2_TrdProc.cpp407
-rw-r--r--core/fxcodec/jbig2/JBig2_TrdProc.h82
38 files changed, 7523 insertions, 0 deletions
diff --git a/core/fxcodec/jbig2/JBig2_ArithDecoder.cpp b/core/fxcodec/jbig2/JBig2_ArithDecoder.cpp
new file mode 100644
index 0000000000..1673110c7e
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_ArithDecoder.cpp
@@ -0,0 +1,120 @@
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxcodec/jbig2/JBig2_ArithDecoder.h"
+
+#include "core/fxcodec/jbig2/JBig2_BitStream.h"
+#include "core/include/fxcrt/fx_basic.h"
+
+namespace {
+
+struct JBig2ArithQe {
+ unsigned int Qe;
+ unsigned int NMPS;
+ unsigned int NLPS;
+ unsigned int nSwitch;
+};
+
+const JBig2ArithQe kQeTable[] = {
+ // Stupid hack to keep clang-format from reformatting this badly.
+ {0x5601, 1, 1, 1}, {0x3401, 2, 6, 0}, {0x1801, 3, 9, 0},
+ {0x0AC1, 4, 12, 0}, {0x0521, 5, 29, 0}, {0x0221, 38, 33, 0},
+ {0x5601, 7, 6, 1}, {0x5401, 8, 14, 0}, {0x4801, 9, 14, 0},
+ {0x3801, 10, 14, 0}, {0x3001, 11, 17, 0}, {0x2401, 12, 18, 0},
+ {0x1C01, 13, 20, 0}, {0x1601, 29, 21, 0}, {0x5601, 15, 14, 1},
+ {0x5401, 16, 14, 0}, {0x5101, 17, 15, 0}, {0x4801, 18, 16, 0},
+ {0x3801, 19, 17, 0}, {0x3401, 20, 18, 0}, {0x3001, 21, 19, 0},
+ {0x2801, 22, 19, 0}, {0x2401, 23, 20, 0}, {0x2201, 24, 21, 0},
+ {0x1C01, 25, 22, 0}, {0x1801, 26, 23, 0}, {0x1601, 27, 24, 0},
+ {0x1401, 28, 25, 0}, {0x1201, 29, 26, 0}, {0x1101, 30, 27, 0},
+ {0x0AC1, 31, 28, 0}, {0x09C1, 32, 29, 0}, {0x08A1, 33, 30, 0},
+ {0x0521, 34, 31, 0}, {0x0441, 35, 32, 0}, {0x02A1, 36, 33, 0},
+ {0x0221, 37, 34, 0}, {0x0141, 38, 35, 0}, {0x0111, 39, 36, 0},
+ {0x0085, 40, 37, 0}, {0x0049, 41, 38, 0}, {0x0025, 42, 39, 0},
+ {0x0015, 43, 40, 0}, {0x0009, 44, 41, 0}, {0x0005, 45, 42, 0},
+ {0x0001, 45, 43, 0}, {0x5601, 46, 46, 0}};
+
+const unsigned int kDefaultAValue = 0x8000;
+
+int DecodeNMPS(JBig2ArithCtx* pCX, const JBig2ArithQe& qe) {
+ pCX->I = qe.NMPS;
+ return pCX->MPS;
+}
+
+int DecodeNLPS(JBig2ArithCtx* pCX, const JBig2ArithQe& qe) {
+ // TODO(thestig): |D|, |MPS| and friends probably should be booleans.
+ int D = 1 - pCX->MPS;
+ if (qe.nSwitch == 1)
+ pCX->MPS = 1 - pCX->MPS;
+ pCX->I = qe.NLPS;
+ return D;
+}
+
+} // namespace
+
+CJBig2_ArithDecoder::CJBig2_ArithDecoder(CJBig2_BitStream* pStream)
+ : m_pStream(pStream) {
+ m_B = m_pStream->getCurByte_arith();
+ m_C = (m_B ^ 0xff) << 16;
+ BYTEIN();
+ m_C = m_C << 7;
+ m_CT = m_CT - 7;
+ m_A = kDefaultAValue;
+}
+
+CJBig2_ArithDecoder::~CJBig2_ArithDecoder() {}
+
+int CJBig2_ArithDecoder::DECODE(JBig2ArithCtx* pCX) {
+ if (!pCX || pCX->I >= FX_ArraySize(kQeTable))
+ return 0;
+
+ const JBig2ArithQe& qe = kQeTable[pCX->I];
+ m_A -= qe.Qe;
+ if ((m_C >> 16) < m_A) {
+ if (m_A & kDefaultAValue)
+ return pCX->MPS;
+
+ const int D = m_A < qe.Qe ? DecodeNLPS(pCX, qe) : DecodeNMPS(pCX, qe);
+ ReadValueA();
+ return D;
+ }
+
+ m_C -= m_A << 16;
+ const int D = m_A < qe.Qe ? DecodeNMPS(pCX, qe) : DecodeNLPS(pCX, qe);
+ m_A = qe.Qe;
+ ReadValueA();
+ return D;
+}
+
+void CJBig2_ArithDecoder::BYTEIN() {
+ unsigned char B1;
+ if (m_B == 0xff) {
+ B1 = m_pStream->getNextByte_arith();
+ if (B1 > 0x8f) {
+ m_CT = 8;
+ } else {
+ m_pStream->incByteIdx();
+ m_B = B1;
+ m_C = m_C + 0xfe00 - (m_B << 9);
+ m_CT = 7;
+ }
+ } else {
+ m_pStream->incByteIdx();
+ m_B = m_pStream->getCurByte_arith();
+ m_C = m_C + 0xff00 - (m_B << 8);
+ m_CT = 8;
+ }
+}
+
+void CJBig2_ArithDecoder::ReadValueA() {
+ do {
+ if (m_CT == 0)
+ BYTEIN();
+ m_A <<= 1;
+ m_C <<= 1;
+ --m_CT;
+ } while ((m_A & kDefaultAValue) == 0);
+}
diff --git a/core/fxcodec/jbig2/JBig2_ArithDecoder.h b/core/fxcodec/jbig2/JBig2_ArithDecoder.h
new file mode 100644
index 0000000000..a8ab5dd730
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_ArithDecoder.h
@@ -0,0 +1,38 @@
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_JBIG2_JBIG2_ARITHDECODER_H_
+#define CORE_FXCODEC_JBIG2_JBIG2_ARITHDECODER_H_
+
+class CJBig2_BitStream;
+
+struct JBig2ArithCtx {
+ JBig2ArithCtx() : MPS(0), I(0) {}
+
+ unsigned int MPS;
+ unsigned int I;
+};
+
+class CJBig2_ArithDecoder {
+ public:
+ explicit CJBig2_ArithDecoder(CJBig2_BitStream* pStream);
+
+ ~CJBig2_ArithDecoder();
+
+ int DECODE(JBig2ArithCtx* pCX);
+
+ private:
+ void BYTEIN();
+ void ReadValueA();
+
+ unsigned char m_B;
+ unsigned int m_C;
+ unsigned int m_A;
+ unsigned int m_CT;
+ CJBig2_BitStream* const m_pStream;
+};
+
+#endif // CORE_FXCODEC_JBIG2_JBIG2_ARITHDECODER_H_
diff --git a/core/fxcodec/jbig2/JBig2_ArithIntDecoder.cpp b/core/fxcodec/jbig2/JBig2_ArithIntDecoder.cpp
new file mode 100644
index 0000000000..63594672c7
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_ArithIntDecoder.cpp
@@ -0,0 +1,92 @@
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxcodec/jbig2/JBig2_ArithIntDecoder.h"
+
+#include <vector>
+
+#include "core/include/fxcrt/fx_basic.h"
+
+namespace {
+
+int ShiftOr(int val, int bitwise_or_val) {
+ return (val << 1) | bitwise_or_val;
+}
+
+const struct ArithIntDecodeData {
+ int nNeedBits;
+ int nValue;
+} g_ArithIntDecodeData[] = {
+ {2, 0}, {4, 4}, {6, 20}, {8, 84}, {12, 340}, {32, 4436},
+};
+
+size_t RecursiveDecode(CJBig2_ArithDecoder* decoder,
+ std::vector<JBig2ArithCtx>* context,
+ int* prev,
+ size_t depth) {
+ static const size_t kDepthEnd = FX_ArraySize(g_ArithIntDecodeData) - 1;
+ if (depth == kDepthEnd)
+ return kDepthEnd;
+
+ JBig2ArithCtx* pCX = &(*context)[*prev];
+ int D = decoder->DECODE(pCX);
+ *prev = ShiftOr(*prev, D);
+ if (!D)
+ return depth;
+ return RecursiveDecode(decoder, context, prev, depth + 1);
+}
+
+} // namespace
+
+CJBig2_ArithIntDecoder::CJBig2_ArithIntDecoder() {
+ m_IAx.resize(512);
+}
+
+CJBig2_ArithIntDecoder::~CJBig2_ArithIntDecoder() {}
+
+bool CJBig2_ArithIntDecoder::decode(CJBig2_ArithDecoder* pArithDecoder,
+ int* nResult) {
+ int PREV = 1;
+ const int S = pArithDecoder->DECODE(&m_IAx[PREV]);
+ PREV = ShiftOr(PREV, S);
+
+ const size_t nDecodeDataIndex =
+ RecursiveDecode(pArithDecoder, &m_IAx, &PREV, 0);
+
+ int nTemp = 0;
+ for (int i = 0; i < g_ArithIntDecodeData[nDecodeDataIndex].nNeedBits; ++i) {
+ int D = pArithDecoder->DECODE(&m_IAx[PREV]);
+ PREV = ShiftOr(PREV, D);
+ if (PREV >= 256)
+ PREV = (PREV & 511) | 256;
+ nTemp = ShiftOr(nTemp, D);
+ }
+ int nValue = g_ArithIntDecodeData[nDecodeDataIndex].nValue;
+ nValue += nTemp;
+ if (S == 1 && nValue > 0)
+ nValue = -nValue;
+
+ *nResult = nValue;
+ return S != 1 || nValue != 0;
+}
+
+CJBig2_ArithIaidDecoder::CJBig2_ArithIaidDecoder(unsigned char SBSYMCODELENA)
+ : SBSYMCODELEN(SBSYMCODELENA) {
+ m_IAID.resize(1 << SBSYMCODELEN);
+}
+
+CJBig2_ArithIaidDecoder::~CJBig2_ArithIaidDecoder() {}
+
+void CJBig2_ArithIaidDecoder::decode(CJBig2_ArithDecoder* pArithDecoder,
+ FX_DWORD* nResult) {
+ int PREV = 1;
+ for (unsigned char i = 0; i < SBSYMCODELEN; ++i) {
+ JBig2ArithCtx* pCX = &m_IAID[PREV];
+ int D = pArithDecoder->DECODE(pCX);
+ PREV = ShiftOr(PREV, D);
+ }
+ *nResult = PREV - (1 << SBSYMCODELEN);
+}
diff --git a/core/fxcodec/jbig2/JBig2_ArithIntDecoder.h b/core/fxcodec/jbig2/JBig2_ArithIntDecoder.h
new file mode 100644
index 0000000000..9a04504ca7
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_ArithIntDecoder.h
@@ -0,0 +1,41 @@
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_JBIG2_JBIG2_ARITHINTDECODER_H_
+#define CORE_FXCODEC_JBIG2_JBIG2_ARITHINTDECODER_H_
+
+#include <vector>
+
+#include "core/fxcodec/jbig2/JBig2_ArithDecoder.h"
+#include "core/include/fxcrt/fx_system.h"
+
+class CJBig2_ArithIntDecoder {
+ public:
+ CJBig2_ArithIntDecoder();
+ ~CJBig2_ArithIntDecoder();
+
+ // Returns true on success, and false when an OOB condition occurs. Many
+ // callers can tolerate OOB and do not check the return value.
+ bool decode(CJBig2_ArithDecoder* pArithDecoder, int* nResult);
+
+ private:
+ std::vector<JBig2ArithCtx> m_IAx;
+};
+
+class CJBig2_ArithIaidDecoder {
+ public:
+ explicit CJBig2_ArithIaidDecoder(unsigned char SBSYMCODELENA);
+ ~CJBig2_ArithIaidDecoder();
+
+ void decode(CJBig2_ArithDecoder* pArithDecoder, FX_DWORD* nResult);
+
+ private:
+ std::vector<JBig2ArithCtx> m_IAID;
+
+ const unsigned char SBSYMCODELEN;
+};
+
+#endif // CORE_FXCODEC_JBIG2_JBIG2_ARITHINTDECODER_H_
diff --git a/core/fxcodec/jbig2/JBig2_BitStream.cpp b/core/fxcodec/jbig2/JBig2_BitStream.cpp
new file mode 100644
index 0000000000..87451c2d72
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_BitStream.cpp
@@ -0,0 +1,188 @@
+// Copyright 2015 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxcodec/jbig2/JBig2_BitStream.h"
+
+#include <algorithm>
+
+#include "core/include/fpdfapi/cpdf_stream.h"
+
+CJBig2_BitStream::CJBig2_BitStream(CPDF_StreamAcc* pSrcStream)
+ : m_pBuf(pSrcStream->GetData()),
+ m_dwLength(pSrcStream->GetSize()),
+ m_dwByteIdx(0),
+ m_dwBitIdx(0),
+ m_dwObjNum(pSrcStream->GetStream() ? pSrcStream->GetStream()->GetObjNum()
+ : 0) {
+ if (m_dwLength > 256 * 1024 * 1024) {
+ m_dwLength = 0;
+ m_pBuf = nullptr;
+ }
+}
+
+CJBig2_BitStream::~CJBig2_BitStream() {}
+
+int32_t CJBig2_BitStream::readNBits(FX_DWORD dwBits, FX_DWORD* dwResult) {
+ FX_DWORD dwBitPos = getBitPos();
+ if (dwBitPos > LengthInBits())
+ return -1;
+
+ *dwResult = 0;
+ if (dwBitPos + dwBits <= LengthInBits())
+ dwBitPos = dwBits;
+ else
+ dwBitPos = LengthInBits() - dwBitPos;
+
+ for (; dwBitPos > 0; --dwBitPos) {
+ *dwResult =
+ (*dwResult << 1) | ((m_pBuf[m_dwByteIdx] >> (7 - m_dwBitIdx)) & 0x01);
+ AdvanceBit();
+ }
+ return 0;
+}
+
+int32_t CJBig2_BitStream::readNBits(FX_DWORD dwBits, int32_t* nResult) {
+ FX_DWORD dwBitPos = getBitPos();
+ if (dwBitPos > LengthInBits())
+ return -1;
+
+ *nResult = 0;
+ if (dwBitPos + dwBits <= LengthInBits())
+ dwBitPos = dwBits;
+ else
+ dwBitPos = LengthInBits() - dwBitPos;
+
+ for (; dwBitPos > 0; --dwBitPos) {
+ *nResult =
+ (*nResult << 1) | ((m_pBuf[m_dwByteIdx] >> (7 - m_dwBitIdx)) & 0x01);
+ AdvanceBit();
+ }
+ return 0;
+}
+
+int32_t CJBig2_BitStream::read1Bit(FX_DWORD* dwResult) {
+ if (!IsInBound())
+ return -1;
+
+ *dwResult = (m_pBuf[m_dwByteIdx] >> (7 - m_dwBitIdx)) & 0x01;
+ AdvanceBit();
+ return 0;
+}
+
+int32_t CJBig2_BitStream::read1Bit(FX_BOOL* bResult) {
+ if (!IsInBound())
+ return -1;
+
+ *bResult = (m_pBuf[m_dwByteIdx] >> (7 - m_dwBitIdx)) & 0x01;
+ AdvanceBit();
+ return 0;
+}
+
+int32_t CJBig2_BitStream::read1Byte(uint8_t* cResult) {
+ if (!IsInBound())
+ return -1;
+
+ *cResult = m_pBuf[m_dwByteIdx];
+ ++m_dwByteIdx;
+ return 0;
+}
+
+int32_t CJBig2_BitStream::readInteger(FX_DWORD* dwResult) {
+ if (m_dwByteIdx + 3 >= m_dwLength)
+ return -1;
+
+ *dwResult = (m_pBuf[m_dwByteIdx] << 24) | (m_pBuf[m_dwByteIdx + 1] << 16) |
+ (m_pBuf[m_dwByteIdx + 2] << 8) | m_pBuf[m_dwByteIdx + 3];
+ m_dwByteIdx += 4;
+ return 0;
+}
+
+int32_t CJBig2_BitStream::readShortInteger(FX_WORD* dwResult) {
+ if (m_dwByteIdx + 1 >= m_dwLength)
+ return -1;
+
+ *dwResult = (m_pBuf[m_dwByteIdx] << 8) | m_pBuf[m_dwByteIdx + 1];
+ m_dwByteIdx += 2;
+ return 0;
+}
+
+void CJBig2_BitStream::alignByte() {
+ if (m_dwBitIdx != 0) {
+ ++m_dwByteIdx;
+ m_dwBitIdx = 0;
+ }
+}
+
+uint8_t CJBig2_BitStream::getCurByte() const {
+ return IsInBound() ? m_pBuf[m_dwByteIdx] : 0;
+}
+
+void CJBig2_BitStream::incByteIdx() {
+ if (IsInBound())
+ ++m_dwByteIdx;
+}
+
+uint8_t CJBig2_BitStream::getCurByte_arith() const {
+ return IsInBound() ? m_pBuf[m_dwByteIdx] : 0xFF;
+}
+
+uint8_t CJBig2_BitStream::getNextByte_arith() const {
+ return m_dwByteIdx + 1 < m_dwLength ? m_pBuf[m_dwByteIdx + 1] : 0xFF;
+}
+
+FX_DWORD CJBig2_BitStream::getOffset() const {
+ return m_dwByteIdx;
+}
+
+void CJBig2_BitStream::setOffset(FX_DWORD dwOffset) {
+ m_dwByteIdx = std::min(dwOffset, m_dwLength);
+}
+
+FX_DWORD CJBig2_BitStream::getBitPos() const {
+ return (m_dwByteIdx << 3) + m_dwBitIdx;
+}
+
+void CJBig2_BitStream::setBitPos(FX_DWORD dwBitPos) {
+ m_dwByteIdx = dwBitPos >> 3;
+ m_dwBitIdx = dwBitPos & 7;
+}
+
+const uint8_t* CJBig2_BitStream::getBuf() const {
+ return m_pBuf;
+}
+
+const uint8_t* CJBig2_BitStream::getPointer() const {
+ return m_pBuf + m_dwByteIdx;
+}
+
+void CJBig2_BitStream::offset(FX_DWORD dwOffset) {
+ m_dwByteIdx += dwOffset;
+}
+
+FX_DWORD CJBig2_BitStream::getByteLeft() const {
+ return m_dwLength - m_dwByteIdx;
+}
+
+void CJBig2_BitStream::AdvanceBit() {
+ if (m_dwBitIdx == 7) {
+ ++m_dwByteIdx;
+ m_dwBitIdx = 0;
+ } else {
+ ++m_dwBitIdx;
+ }
+}
+
+bool CJBig2_BitStream::IsInBound() const {
+ return m_dwByteIdx < m_dwLength;
+}
+
+FX_DWORD CJBig2_BitStream::LengthInBits() const {
+ return m_dwLength << 3;
+}
+
+FX_DWORD CJBig2_BitStream::getObjNum() const {
+ return m_dwObjNum;
+}
diff --git a/core/fxcodec/jbig2/JBig2_BitStream.h b/core/fxcodec/jbig2/JBig2_BitStream.h
new file mode 100644
index 0000000000..c24fedfba1
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_BitStream.h
@@ -0,0 +1,58 @@
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_JBIG2_JBIG2_BITSTREAM_H_
+#define CORE_FXCODEC_JBIG2_JBIG2_BITSTREAM_H_
+
+#include "core/include/fxcrt/fx_basic.h"
+
+class CPDF_StreamAcc;
+
+class CJBig2_BitStream {
+ public:
+ explicit CJBig2_BitStream(CPDF_StreamAcc* pSrcStream);
+ ~CJBig2_BitStream();
+
+ // TODO(thestig): readFoo() should return bool.
+ int32_t readNBits(FX_DWORD nBits, FX_DWORD* dwResult);
+ int32_t readNBits(FX_DWORD nBits, int32_t* nResult);
+ int32_t read1Bit(FX_DWORD* dwResult);
+ int32_t read1Bit(FX_BOOL* bResult);
+ int32_t read1Byte(uint8_t* cResult);
+ int32_t readInteger(FX_DWORD* dwResult);
+ int32_t readShortInteger(FX_WORD* wResult);
+ void alignByte();
+ uint8_t getCurByte() const;
+ void incByteIdx();
+ uint8_t getCurByte_arith() const;
+ uint8_t getNextByte_arith() const;
+ FX_DWORD getOffset() const;
+ void setOffset(FX_DWORD dwOffset);
+ FX_DWORD getBitPos() const;
+ void setBitPos(FX_DWORD dwBitPos);
+ const uint8_t* getBuf() const;
+ FX_DWORD getLength() const { return m_dwLength; }
+ const uint8_t* getPointer() const;
+ void offset(FX_DWORD dwOffset);
+ FX_DWORD getByteLeft() const;
+ FX_DWORD getObjNum() const;
+
+ private:
+ void AdvanceBit();
+ bool IsInBound() const;
+ FX_DWORD LengthInBits() const;
+
+ const uint8_t* m_pBuf;
+ FX_DWORD m_dwLength;
+ FX_DWORD m_dwByteIdx;
+ FX_DWORD m_dwBitIdx;
+ const FX_DWORD m_dwObjNum;
+
+ CJBig2_BitStream(const CJBig2_BitStream&) = delete;
+ void operator=(const CJBig2_BitStream&) = delete;
+};
+
+#endif // CORE_FXCODEC_JBIG2_JBIG2_BITSTREAM_H_
diff --git a/core/fxcodec/jbig2/JBig2_Context.cpp b/core/fxcodec/jbig2/JBig2_Context.cpp
new file mode 100644
index 0000000000..0a17fff328
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_Context.cpp
@@ -0,0 +1,1439 @@
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxcodec/jbig2/JBig2_Context.h"
+
+#include <algorithm>
+#include <list>
+#include <utility>
+#include <vector>
+
+#include "core/fxcodec/jbig2/JBig2_ArithDecoder.h"
+#include "core/fxcodec/jbig2/JBig2_BitStream.h"
+#include "core/fxcodec/jbig2/JBig2_GrdProc.h"
+#include "core/fxcodec/jbig2/JBig2_GrrdProc.h"
+#include "core/fxcodec/jbig2/JBig2_HtrdProc.h"
+#include "core/fxcodec/jbig2/JBig2_HuffmanTable_Standard.h"
+#include "core/fxcodec/jbig2/JBig2_PddProc.h"
+#include "core/fxcodec/jbig2/JBig2_SddProc.h"
+#include "core/fxcodec/jbig2/JBig2_TrdProc.h"
+#include "core/include/fpdfapi/cpdf_stream.h"
+#include "third_party/base/stl_util.h"
+
+namespace {
+
+size_t GetHuffContextSize(uint8_t val) {
+ return val == 0 ? 65536 : val == 1 ? 8192 : 1024;
+}
+
+size_t GetRefAggContextSize(FX_BOOL val) {
+ return val ? 1024 : 8192;
+}
+
+} // namespace
+
+// Implement a very small least recently used (LRU) cache. It is very
+// common for a JBIG2 dictionary to span multiple pages in a PDF file,
+// and we do not want to decode the same dictionary over and over
+// again. We key off of the memory location of the dictionary. The
+// list keeps track of the freshness of entries, with freshest ones
+// at the front. Even a tiny cache size like 2 makes a dramatic
+// difference for typical JBIG2 documents.
+static const int kSymbolDictCacheMaxSize = 2;
+
+CJBig2_Context* CJBig2_Context::CreateContext(
+ CPDF_StreamAcc* pGlobalStream,
+ CPDF_StreamAcc* pSrcStream,
+ std::list<CJBig2_CachePair>* pSymbolDictCache,
+ IFX_Pause* pPause) {
+ return new CJBig2_Context(pGlobalStream, pSrcStream, pSymbolDictCache, pPause,
+ false);
+}
+
+void CJBig2_Context::DestroyContext(CJBig2_Context* pContext) {
+ delete pContext;
+}
+
+CJBig2_Context::CJBig2_Context(CPDF_StreamAcc* pGlobalStream,
+ CPDF_StreamAcc* pSrcStream,
+ std::list<CJBig2_CachePair>* pSymbolDictCache,
+ IFX_Pause* pPause,
+ bool bIsGlobal)
+ : m_nSegmentDecoded(0),
+ m_bInPage(false),
+ m_bBufSpecified(false),
+ m_PauseStep(10),
+ m_pPause(pPause),
+ m_ProcessingStatus(FXCODEC_STATUS_FRAME_READY),
+ m_gbContext(NULL),
+ m_dwOffset(0),
+ m_pSymbolDictCache(pSymbolDictCache),
+ m_bIsGlobal(bIsGlobal) {
+ if (pGlobalStream && (pGlobalStream->GetSize() > 0)) {
+ m_pGlobalContext = new CJBig2_Context(nullptr, pGlobalStream,
+ pSymbolDictCache, pPause, true);
+ } else {
+ m_pGlobalContext = nullptr;
+ }
+
+ m_pStream.reset(new CJBig2_BitStream(pSrcStream));
+}
+
+CJBig2_Context::~CJBig2_Context() {
+ FX_Free(m_gbContext);
+ m_gbContext = NULL;
+ delete m_pGlobalContext;
+ m_pGlobalContext = NULL;
+}
+
+int32_t CJBig2_Context::decode_SquentialOrgnazation(IFX_Pause* pPause) {
+ int32_t nRet;
+ if (m_pStream->getByteLeft() <= 0)
+ return JBIG2_END_OF_FILE;
+
+ while (m_pStream->getByteLeft() >= JBIG2_MIN_SEGMENT_SIZE) {
+ if (!m_pSegment) {
+ m_pSegment.reset(new CJBig2_Segment);
+ nRet = parseSegmentHeader(m_pSegment.get());
+ if (nRet != JBIG2_SUCCESS) {
+ m_pSegment.reset();
+ return nRet;
+ }
+ m_dwOffset = m_pStream->getOffset();
+ }
+ nRet = parseSegmentData(m_pSegment.get(), pPause);
+ if (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
+ m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
+ m_PauseStep = 2;
+ return JBIG2_SUCCESS;
+ }
+ if (nRet == JBIG2_END_OF_PAGE || nRet == JBIG2_END_OF_FILE) {
+ m_pSegment.reset();
+ return JBIG2_SUCCESS;
+ }
+ if (nRet != JBIG2_SUCCESS) {
+ m_pSegment.reset();
+ return nRet;
+ }
+ if (m_pSegment->m_dwData_length != 0xffffffff) {
+ m_dwOffset += m_pSegment->m_dwData_length;
+ m_pStream->setOffset(m_dwOffset);
+ } else {
+ m_pStream->offset(4);
+ }
+ m_SegmentList.push_back(m_pSegment.release());
+ if (m_pStream->getByteLeft() > 0 && m_pPage && pPause &&
+ pPause->NeedToPauseNow()) {
+ m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
+ m_PauseStep = 2;
+ return JBIG2_SUCCESS;
+ }
+ }
+ return JBIG2_SUCCESS;
+}
+int32_t CJBig2_Context::decode_EmbedOrgnazation(IFX_Pause* pPause) {
+ return decode_SquentialOrgnazation(pPause);
+}
+int32_t CJBig2_Context::decode_RandomOrgnazation_FirstPage(IFX_Pause* pPause) {
+ int32_t nRet;
+ while (m_pStream->getByteLeft() > JBIG2_MIN_SEGMENT_SIZE) {
+ std::unique_ptr<CJBig2_Segment> pSegment(new CJBig2_Segment);
+ nRet = parseSegmentHeader(pSegment.get());
+ if (nRet != JBIG2_SUCCESS) {
+ return nRet;
+ } else if (pSegment->m_cFlags.s.type == 51) {
+ break;
+ }
+ m_SegmentList.push_back(pSegment.release());
+ if (pPause && m_pPause && pPause->NeedToPauseNow()) {
+ m_PauseStep = 3;
+ m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
+ return JBIG2_SUCCESS;
+ }
+ }
+ m_nSegmentDecoded = 0;
+ return decode_RandomOrgnazation(pPause);
+}
+int32_t CJBig2_Context::decode_RandomOrgnazation(IFX_Pause* pPause) {
+ for (; m_nSegmentDecoded < m_SegmentList.size(); ++m_nSegmentDecoded) {
+ int32_t nRet =
+ parseSegmentData(m_SegmentList.get(m_nSegmentDecoded), pPause);
+ if (nRet == JBIG2_END_OF_PAGE || nRet == JBIG2_END_OF_FILE)
+ return JBIG2_SUCCESS;
+
+ if (nRet != JBIG2_SUCCESS)
+ return nRet;
+
+ if (m_pPage && pPause && pPause->NeedToPauseNow()) {
+ m_PauseStep = 4;
+ m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
+ return JBIG2_SUCCESS;
+ }
+ }
+ return JBIG2_SUCCESS;
+}
+int32_t CJBig2_Context::getFirstPage(uint8_t* pBuf,
+ int32_t width,
+ int32_t height,
+ int32_t stride,
+ IFX_Pause* pPause) {
+ int32_t nRet = 0;
+ if (m_pGlobalContext) {
+ nRet = m_pGlobalContext->decode_EmbedOrgnazation(pPause);
+ if (nRet != JBIG2_SUCCESS) {
+ m_ProcessingStatus = FXCODEC_STATUS_ERROR;
+ return nRet;
+ }
+ }
+ m_PauseStep = 0;
+ m_pPage.reset(new CJBig2_Image(width, height, stride, pBuf));
+ m_bBufSpecified = true;
+ if (pPause && pPause->NeedToPauseNow()) {
+ m_PauseStep = 1;
+ m_ProcessingStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
+ return nRet;
+ }
+ return Continue(pPause);
+}
+int32_t CJBig2_Context::Continue(IFX_Pause* pPause) {
+ m_ProcessingStatus = FXCODEC_STATUS_DECODE_READY;
+ int32_t nRet;
+ if (m_PauseStep <= 1) {
+ nRet = decode_EmbedOrgnazation(pPause);
+ } else if (m_PauseStep == 2) {
+ nRet = decode_SquentialOrgnazation(pPause);
+ } else if (m_PauseStep == 3) {
+ nRet = decode_RandomOrgnazation_FirstPage(pPause);
+ } else if (m_PauseStep == 4) {
+ nRet = decode_RandomOrgnazation(pPause);
+ } else if (m_PauseStep == 5) {
+ m_ProcessingStatus = FXCODEC_STATUS_DECODE_FINISH;
+ return JBIG2_SUCCESS;
+ }
+ if (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
+ return nRet;
+ }
+ m_PauseStep = 5;
+ if (!m_bBufSpecified && nRet == JBIG2_SUCCESS) {
+ m_ProcessingStatus = FXCODEC_STATUS_DECODE_FINISH;
+ return JBIG2_SUCCESS;
+ }
+ if (nRet == JBIG2_SUCCESS) {
+ m_ProcessingStatus = FXCODEC_STATUS_DECODE_FINISH;
+ } else {
+ m_ProcessingStatus = FXCODEC_STATUS_ERROR;
+ }
+ return nRet;
+}
+
+CJBig2_Segment* CJBig2_Context::findSegmentByNumber(FX_DWORD dwNumber) {
+ if (m_pGlobalContext) {
+ CJBig2_Segment* pSeg = m_pGlobalContext->findSegmentByNumber(dwNumber);
+ if (pSeg) {
+ return pSeg;
+ }
+ }
+ for (size_t i = 0; i < m_SegmentList.size(); ++i) {
+ CJBig2_Segment* pSeg = m_SegmentList.get(i);
+ if (pSeg->m_dwNumber == dwNumber) {
+ return pSeg;
+ }
+ }
+ return nullptr;
+}
+CJBig2_Segment* CJBig2_Context::findReferredSegmentByTypeAndIndex(
+ CJBig2_Segment* pSegment,
+ uint8_t cType,
+ int32_t nIndex) {
+ int32_t count = 0;
+ for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
+ CJBig2_Segment* pSeg =
+ findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
+ if (pSeg && pSeg->m_cFlags.s.type == cType) {
+ if (count == nIndex)
+ return pSeg;
+ ++count;
+ }
+ }
+ return NULL;
+}
+int32_t CJBig2_Context::parseSegmentHeader(CJBig2_Segment* pSegment) {
+ if (m_pStream->readInteger(&pSegment->m_dwNumber) != 0 ||
+ m_pStream->read1Byte(&pSegment->m_cFlags.c) != 0) {
+ return JBIG2_ERROR_TOO_SHORT;
+ }
+
+ FX_DWORD dwTemp;
+ uint8_t cTemp = m_pStream->getCurByte();
+ if ((cTemp >> 5) == 7) {
+ if (m_pStream->readInteger(
+ (FX_DWORD*)&pSegment->m_nReferred_to_segment_count) != 0) {
+ return JBIG2_ERROR_TOO_SHORT;
+ }
+ pSegment->m_nReferred_to_segment_count &= 0x1fffffff;
+ if (pSegment->m_nReferred_to_segment_count >
+ JBIG2_MAX_REFERRED_SEGMENT_COUNT) {
+ return JBIG2_ERROR_LIMIT;
+ }
+ dwTemp = 5 + 4 + (pSegment->m_nReferred_to_segment_count + 1) / 8;
+ } else {
+ if (m_pStream->read1Byte(&cTemp) != 0)
+ return JBIG2_ERROR_TOO_SHORT;
+
+ pSegment->m_nReferred_to_segment_count = cTemp >> 5;
+ dwTemp = 5 + 1;
+ }
+ uint8_t cSSize =
+ pSegment->m_dwNumber > 65536 ? 4 : pSegment->m_dwNumber > 256 ? 2 : 1;
+ uint8_t cPSize = pSegment->m_cFlags.s.page_association_size ? 4 : 1;
+ if (pSegment->m_nReferred_to_segment_count) {
+ pSegment->m_pReferred_to_segment_numbers =
+ FX_Alloc(FX_DWORD, pSegment->m_nReferred_to_segment_count);
+ for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
+ switch (cSSize) {
+ case 1:
+ if (m_pStream->read1Byte(&cTemp) != 0)
+ return JBIG2_ERROR_TOO_SHORT;
+
+ pSegment->m_pReferred_to_segment_numbers[i] = cTemp;
+ break;
+ case 2:
+ FX_WORD wTemp;
+ if (m_pStream->readShortInteger(&wTemp) != 0)
+ return JBIG2_ERROR_TOO_SHORT;
+
+ pSegment->m_pReferred_to_segment_numbers[i] = wTemp;
+ break;
+ case 4:
+ if (m_pStream->readInteger(&dwTemp) != 0)
+ return JBIG2_ERROR_TOO_SHORT;
+
+ pSegment->m_pReferred_to_segment_numbers[i] = dwTemp;
+ break;
+ }
+ if (pSegment->m_pReferred_to_segment_numbers[i] >= pSegment->m_dwNumber)
+ return JBIG2_ERROR_TOO_SHORT;
+ }
+ }
+ if (cPSize == 1) {
+ if (m_pStream->read1Byte(&cTemp) != 0)
+ return JBIG2_ERROR_TOO_SHORT;
+ pSegment->m_dwPage_association = cTemp;
+ } else {
+ if (m_pStream->readInteger(&pSegment->m_dwPage_association) != 0) {
+ return JBIG2_ERROR_TOO_SHORT;
+ }
+ }
+ if (m_pStream->readInteger(&pSegment->m_dwData_length) != 0)
+ return JBIG2_ERROR_TOO_SHORT;
+
+ pSegment->m_dwObjNum = m_pStream->getObjNum();
+ pSegment->m_dwDataOffset = m_pStream->getOffset();
+ pSegment->m_State = JBIG2_SEGMENT_DATA_UNPARSED;
+ return JBIG2_SUCCESS;
+}
+
+int32_t CJBig2_Context::parseSegmentData(CJBig2_Segment* pSegment,
+ IFX_Pause* pPause) {
+ int32_t ret = ProcessingParseSegmentData(pSegment, pPause);
+ while (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE &&
+ m_pStream->getByteLeft() > 0) {
+ ret = ProcessingParseSegmentData(pSegment, pPause);
+ }
+ return ret;
+}
+
+int32_t CJBig2_Context::ProcessingParseSegmentData(CJBig2_Segment* pSegment,
+ IFX_Pause* pPause) {
+ switch (pSegment->m_cFlags.s.type) {
+ case 0:
+ return parseSymbolDict(pSegment, pPause);
+ case 4:
+ case 6:
+ case 7:
+ if (!m_bInPage)
+ return JBIG2_ERROR_FATAL;
+ return parseTextRegion(pSegment);
+ case 16:
+ return parsePatternDict(pSegment, pPause);
+ case 20:
+ case 22:
+ case 23:
+ if (!m_bInPage)
+ return JBIG2_ERROR_FATAL;
+ return parseHalftoneRegion(pSegment, pPause);
+ case 36:
+ case 38:
+ case 39:
+ if (!m_bInPage)
+ return JBIG2_ERROR_FATAL;
+ return parseGenericRegion(pSegment, pPause);
+ case 40:
+ case 42:
+ case 43:
+ if (!m_bInPage)
+ return JBIG2_ERROR_FATAL;
+ return parseGenericRefinementRegion(pSegment);
+ case 48: {
+ FX_WORD wTemp;
+ std::unique_ptr<JBig2PageInfo> pPageInfo(new JBig2PageInfo);
+ if (m_pStream->readInteger(&pPageInfo->m_dwWidth) != 0 ||
+ m_pStream->readInteger(&pPageInfo->m_dwHeight) != 0 ||
+ m_pStream->readInteger(&pPageInfo->m_dwResolutionX) != 0 ||
+ m_pStream->readInteger(&pPageInfo->m_dwResolutionY) != 0 ||
+ m_pStream->read1Byte(&pPageInfo->m_cFlags) != 0 ||
+ m_pStream->readShortInteger(&wTemp) != 0) {
+ return JBIG2_ERROR_TOO_SHORT;
+ }
+ pPageInfo->m_bIsStriped = !!(wTemp & 0x8000);
+ pPageInfo->m_wMaxStripeSize = wTemp & 0x7fff;
+ bool bMaxHeight = (pPageInfo->m_dwHeight == 0xffffffff);
+ if (bMaxHeight && pPageInfo->m_bIsStriped != TRUE)
+ pPageInfo->m_bIsStriped = TRUE;
+
+ if (!m_bBufSpecified) {
+ FX_DWORD height =
+ bMaxHeight ? pPageInfo->m_wMaxStripeSize : pPageInfo->m_dwHeight;
+ m_pPage.reset(new CJBig2_Image(pPageInfo->m_dwWidth, height));
+ }
+
+ if (!m_pPage->m_pData) {
+ m_ProcessingStatus = FXCODEC_STATUS_ERROR;
+ return JBIG2_ERROR_TOO_SHORT;
+ }
+
+ m_pPage->fill((pPageInfo->m_cFlags & 4) ? 1 : 0);
+ m_PageInfoList.push_back(pPageInfo.release());
+ m_bInPage = true;
+ } break;
+ case 49:
+ m_bInPage = false;
+ return JBIG2_END_OF_PAGE;
+ break;
+ case 50:
+ m_pStream->offset(pSegment->m_dwData_length);
+ break;
+ case 51:
+ return JBIG2_END_OF_FILE;
+ case 52:
+ m_pStream->offset(pSegment->m_dwData_length);
+ break;
+ case 53:
+ return parseTable(pSegment);
+ case 62:
+ m_pStream->offset(pSegment->m_dwData_length);
+ break;
+ default:
+ break;
+ }
+ return JBIG2_SUCCESS;
+}
+
+int32_t CJBig2_Context::parseSymbolDict(CJBig2_Segment* pSegment,
+ IFX_Pause* pPause) {
+ FX_WORD wFlags;
+ if (m_pStream->readShortInteger(&wFlags) != 0)
+ return JBIG2_ERROR_TOO_SHORT;
+
+ std::unique_ptr<CJBig2_SDDProc> pSymbolDictDecoder(new CJBig2_SDDProc);
+ pSymbolDictDecoder->SDHUFF = wFlags & 0x0001;
+ pSymbolDictDecoder->SDREFAGG = (wFlags >> 1) & 0x0001;
+ pSymbolDictDecoder->SDTEMPLATE = (wFlags >> 10) & 0x0003;
+ pSymbolDictDecoder->SDRTEMPLATE = (wFlags >> 12) & 0x0003;
+ uint8_t cSDHUFFDH = (wFlags >> 2) & 0x0003;
+ uint8_t cSDHUFFDW = (wFlags >> 4) & 0x0003;
+ uint8_t cSDHUFFBMSIZE = (wFlags >> 6) & 0x0001;
+ uint8_t cSDHUFFAGGINST = (wFlags >> 7) & 0x0001;
+ if (pSymbolDictDecoder->SDHUFF == 0) {
+ const FX_DWORD dwTemp = (pSymbolDictDecoder->SDTEMPLATE == 0) ? 8 : 2;
+ for (FX_DWORD i = 0; i < dwTemp; ++i) {
+ if (m_pStream->read1Byte((uint8_t*)&pSymbolDictDecoder->SDAT[i]) != 0)
+ return JBIG2_ERROR_TOO_SHORT;
+ }
+ }
+ if (pSymbolDictDecoder->SDREFAGG == 1 &&
+ pSymbolDictDecoder->SDRTEMPLATE == 0) {
+ for (int32_t i = 0; i < 4; ++i) {
+ if (m_pStream->read1Byte((uint8_t*)&pSymbolDictDecoder->SDRAT[i]) != 0)
+ return JBIG2_ERROR_TOO_SHORT;
+ }
+ }
+ if (m_pStream->readInteger(&pSymbolDictDecoder->SDNUMEXSYMS) != 0 ||
+ m_pStream->readInteger(&pSymbolDictDecoder->SDNUMNEWSYMS) != 0) {
+ return JBIG2_ERROR_TOO_SHORT;
+ }
+ if (pSymbolDictDecoder->SDNUMEXSYMS > JBIG2_MAX_EXPORT_SYSMBOLS ||
+ pSymbolDictDecoder->SDNUMNEWSYMS > JBIG2_MAX_NEW_SYSMBOLS) {
+ return JBIG2_ERROR_LIMIT;
+ }
+ for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
+ if (!findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]))
+ return JBIG2_ERROR_FATAL;
+ }
+ CJBig2_Segment* pLRSeg = nullptr;
+ pSymbolDictDecoder->SDNUMINSYMS = 0;
+ for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
+ CJBig2_Segment* pSeg =
+ findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
+ if (pSeg->m_cFlags.s.type == 0) {
+ pSymbolDictDecoder->SDNUMINSYMS += pSeg->m_Result.sd->NumImages();
+ pLRSeg = pSeg;
+ }
+ }
+
+ std::unique_ptr<CJBig2_Image*, FxFreeDeleter> SDINSYMS;
+ if (pSymbolDictDecoder->SDNUMINSYMS != 0) {
+ SDINSYMS.reset(FX_Alloc(CJBig2_Image*, pSymbolDictDecoder->SDNUMINSYMS));
+ FX_DWORD dwTemp = 0;
+ for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
+ CJBig2_Segment* pSeg =
+ findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
+ if (pSeg->m_cFlags.s.type == 0) {
+ const CJBig2_SymbolDict& dict = *pSeg->m_Result.sd;
+ for (size_t j = 0; j < dict.NumImages(); ++j)
+ SDINSYMS.get()[dwTemp + j] = dict.GetImage(j);
+ dwTemp += dict.NumImages();
+ }
+ }
+ }
+ pSymbolDictDecoder->SDINSYMS = SDINSYMS.get();
+
+ std::unique_ptr<CJBig2_HuffmanTable> Table_B1;
+ std::unique_ptr<CJBig2_HuffmanTable> Table_B2;
+ std::unique_ptr<CJBig2_HuffmanTable> Table_B3;
+ std::unique_ptr<CJBig2_HuffmanTable> Table_B4;
+ std::unique_ptr<CJBig2_HuffmanTable> Table_B5;
+ if (pSymbolDictDecoder->SDHUFF == 1) {
+ if (cSDHUFFDH == 2 || cSDHUFFDW == 2)
+ return JBIG2_ERROR_FATAL;
+
+ int32_t nIndex = 0;
+ if (cSDHUFFDH == 0) {
+ Table_B4.reset(new CJBig2_HuffmanTable(HuffmanTable_B4,
+ FX_ArraySize(HuffmanTable_B4),
+ HuffmanTable_HTOOB_B4));
+ pSymbolDictDecoder->SDHUFFDH = Table_B4.get();
+ } else if (cSDHUFFDH == 1) {
+ Table_B5.reset(new CJBig2_HuffmanTable(HuffmanTable_B5,
+ FX_ArraySize(HuffmanTable_B5),
+ HuffmanTable_HTOOB_B5));
+ pSymbolDictDecoder->SDHUFFDH = Table_B5.get();
+ } else {
+ CJBig2_Segment* pSeg =
+ findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
+ if (!pSeg)
+ return JBIG2_ERROR_FATAL;
+ pSymbolDictDecoder->SDHUFFDH = pSeg->m_Result.ht;
+ }
+ if (cSDHUFFDW == 0) {
+ Table_B2.reset(new CJBig2_HuffmanTable(HuffmanTable_B2,
+ FX_ArraySize(HuffmanTable_B2),
+ HuffmanTable_HTOOB_B2));
+ pSymbolDictDecoder->SDHUFFDW = Table_B2.get();
+ } else if (cSDHUFFDW == 1) {
+ Table_B3.reset(new CJBig2_HuffmanTable(HuffmanTable_B3,
+ FX_ArraySize(HuffmanTable_B3),
+ HuffmanTable_HTOOB_B3));
+ pSymbolDictDecoder->SDHUFFDW = Table_B3.get();
+ } else {
+ CJBig2_Segment* pSeg =
+ findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
+ if (!pSeg)
+ return JBIG2_ERROR_FATAL;
+ pSymbolDictDecoder->SDHUFFDW = pSeg->m_Result.ht;
+ }
+ if (cSDHUFFBMSIZE == 0) {
+ Table_B1.reset(new CJBig2_HuffmanTable(HuffmanTable_B1,
+ FX_ArraySize(HuffmanTable_B1),
+ HuffmanTable_HTOOB_B1));
+ pSymbolDictDecoder->SDHUFFBMSIZE = Table_B1.get();
+ } else {
+ CJBig2_Segment* pSeg =
+ findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
+ if (!pSeg)
+ return JBIG2_ERROR_FATAL;
+ pSymbolDictDecoder->SDHUFFBMSIZE = pSeg->m_Result.ht;
+ }
+ if (pSymbolDictDecoder->SDREFAGG == 1) {
+ if (cSDHUFFAGGINST == 0) {
+ if (!Table_B1) {
+ Table_B1.reset(new CJBig2_HuffmanTable(HuffmanTable_B1,
+ FX_ArraySize(HuffmanTable_B1),
+ HuffmanTable_HTOOB_B1));
+ }
+ pSymbolDictDecoder->SDHUFFAGGINST = Table_B1.get();
+ } else {
+ CJBig2_Segment* pSeg =
+ findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
+ if (!pSeg)
+ return JBIG2_ERROR_FATAL;
+ pSymbolDictDecoder->SDHUFFAGGINST = pSeg->m_Result.ht;
+ }
+ }
+ }
+
+ const bool bUseGbContext = (pSymbolDictDecoder->SDHUFF == 0);
+ const bool bUseGrContext = (pSymbolDictDecoder->SDREFAGG == 1);
+ const size_t gbContextSize =
+ GetHuffContextSize(pSymbolDictDecoder->SDTEMPLATE);
+ const size_t grContextSize =
+ GetRefAggContextSize(pSymbolDictDecoder->SDRTEMPLATE);
+ std::vector<JBig2ArithCtx> gbContext;
+ std::vector<JBig2ArithCtx> grContext;
+ if ((wFlags & 0x0100) && pLRSeg) {
+ if (bUseGbContext) {
+ gbContext = pLRSeg->m_Result.sd->GbContext();
+ if (gbContext.size() != gbContextSize)
+ return JBIG2_ERROR_FATAL;
+ }
+ if (bUseGrContext) {
+ grContext = pLRSeg->m_Result.sd->GrContext();
+ if (grContext.size() != grContextSize)
+ return JBIG2_ERROR_FATAL;
+ }
+ } else {
+ if (bUseGbContext)
+ gbContext.resize(gbContextSize);
+ if (bUseGrContext)
+ grContext.resize(grContextSize);
+ }
+
+ CJBig2_CacheKey key =
+ CJBig2_CacheKey(pSegment->m_dwObjNum, pSegment->m_dwDataOffset);
+ FX_BOOL cache_hit = false;
+ pSegment->m_nResultType = JBIG2_SYMBOL_DICT_POINTER;
+ if (m_bIsGlobal && key.first != 0) {
+ for (auto it = m_pSymbolDictCache->begin(); it != m_pSymbolDictCache->end();
+ ++it) {
+ if (it->first == key) {
+ std::unique_ptr<CJBig2_SymbolDict> copy(it->second->DeepCopy());
+ pSegment->m_Result.sd = copy.release();
+ m_pSymbolDictCache->push_front(*it);
+ m_pSymbolDictCache->erase(it);
+ cache_hit = true;
+ break;
+ }
+ }
+ }
+ if (!cache_hit) {
+ if (bUseGbContext) {
+ std::unique_ptr<CJBig2_ArithDecoder> pArithDecoder(
+ new CJBig2_ArithDecoder(m_pStream.get()));
+ pSegment->m_Result.sd = pSymbolDictDecoder->decode_Arith(
+ pArithDecoder.get(), &gbContext, &grContext);
+ if (!pSegment->m_Result.sd)
+ return JBIG2_ERROR_FATAL;
+
+ m_pStream->alignByte();
+ m_pStream->offset(2);
+ } else {
+ pSegment->m_Result.sd = pSymbolDictDecoder->decode_Huffman(
+ m_pStream.get(), &gbContext, &grContext, pPause);
+ if (!pSegment->m_Result.sd)
+ return JBIG2_ERROR_FATAL;
+ m_pStream->alignByte();
+ }
+ if (m_bIsGlobal && kSymbolDictCacheMaxSize > 0) {
+ std::unique_ptr<CJBig2_SymbolDict> value =
+ pSegment->m_Result.sd->DeepCopy();
+ int size = pdfium::CollectionSize<int>(*m_pSymbolDictCache);
+ while (size >= kSymbolDictCacheMaxSize) {
+ delete m_pSymbolDictCache->back().second;
+ m_pSymbolDictCache->pop_back();
+ --size;
+ }
+ m_pSymbolDictCache->push_front(CJBig2_CachePair(key, value.release()));
+ }
+ }
+ if (wFlags & 0x0200) {
+ if (bUseGbContext)
+ pSegment->m_Result.sd->SetGbContext(gbContext);
+ if (bUseGrContext)
+ pSegment->m_Result.sd->SetGrContext(grContext);
+ }
+ return JBIG2_SUCCESS;
+}
+
+int32_t CJBig2_Context::parseTextRegion(CJBig2_Segment* pSegment) {
+ FX_WORD wFlags;
+ JBig2RegionInfo ri;
+ if (parseRegionInfo(&ri) != JBIG2_SUCCESS ||
+ m_pStream->readShortInteger(&wFlags) != 0) {
+ return JBIG2_ERROR_TOO_SHORT;
+ }
+
+ std::unique_ptr<CJBig2_TRDProc> pTRD(new CJBig2_TRDProc);
+ pTRD->SBW = ri.width;
+ pTRD->SBH = ri.height;
+ pTRD->SBHUFF = wFlags & 0x0001;
+ pTRD->SBREFINE = (wFlags >> 1) & 0x0001;
+ FX_DWORD dwTemp = (wFlags >> 2) & 0x0003;
+ pTRD->SBSTRIPS = 1 << dwTemp;
+ pTRD->REFCORNER = (JBig2Corner)((wFlags >> 4) & 0x0003);
+ pTRD->TRANSPOSED = (wFlags >> 6) & 0x0001;
+ pTRD->SBCOMBOP = (JBig2ComposeOp)((wFlags >> 7) & 0x0003);
+ pTRD->SBDEFPIXEL = (wFlags >> 9) & 0x0001;
+ pTRD->SBDSOFFSET = (wFlags >> 10) & 0x001f;
+ if (pTRD->SBDSOFFSET >= 0x0010) {
+ pTRD->SBDSOFFSET = pTRD->SBDSOFFSET - 0x0020;
+ }
+ pTRD->SBRTEMPLATE = (wFlags >> 15) & 0x0001;
+
+ uint8_t cSBHUFFFS;
+ uint8_t cSBHUFFDS;
+ uint8_t cSBHUFFDT;
+ uint8_t cSBHUFFRDW;
+ uint8_t cSBHUFFRDH;
+ uint8_t cSBHUFFRDX;
+ uint8_t cSBHUFFRDY;
+ uint8_t cSBHUFFRSIZE;
+ if (pTRD->SBHUFF == 1) {
+ if (m_pStream->readShortInteger(&wFlags) != 0)
+ return JBIG2_ERROR_TOO_SHORT;
+
+ cSBHUFFFS = wFlags & 0x0003;
+ cSBHUFFDS = (wFlags >> 2) & 0x0003;
+ cSBHUFFDT = (wFlags >> 4) & 0x0003;
+ cSBHUFFRDW = (wFlags >> 6) & 0x0003;
+ cSBHUFFRDH = (wFlags >> 8) & 0x0003;
+ cSBHUFFRDX = (wFlags >> 10) & 0x0003;
+ cSBHUFFRDY = (wFlags >> 12) & 0x0003;
+ cSBHUFFRSIZE = (wFlags >> 14) & 0x0001;
+ }
+ if (pTRD->SBREFINE == 1 && pTRD->SBRTEMPLATE == 0) {
+ for (int32_t i = 0; i < 4; ++i) {
+ if (m_pStream->read1Byte((uint8_t*)&pTRD->SBRAT[i]) != 0)
+ return JBIG2_ERROR_TOO_SHORT;
+ }
+ }
+ if (m_pStream->readInteger(&pTRD->SBNUMINSTANCES) != 0)
+ return JBIG2_ERROR_TOO_SHORT;
+
+ for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
+ if (!findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]))
+ return JBIG2_ERROR_FATAL;
+ }
+
+ pTRD->SBNUMSYMS = 0;
+ for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
+ CJBig2_Segment* pSeg =
+ findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
+ if (pSeg->m_cFlags.s.type == 0) {
+ pTRD->SBNUMSYMS += pSeg->m_Result.sd->NumImages();
+ }
+ }
+
+ std::unique_ptr<CJBig2_Image*, FxFreeDeleter> SBSYMS;
+ if (pTRD->SBNUMSYMS > 0) {
+ SBSYMS.reset(FX_Alloc(CJBig2_Image*, pTRD->SBNUMSYMS));
+ dwTemp = 0;
+ for (int32_t i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
+ CJBig2_Segment* pSeg =
+ findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[i]);
+ if (pSeg->m_cFlags.s.type == 0) {
+ const CJBig2_SymbolDict& dict = *pSeg->m_Result.sd;
+ for (size_t j = 0; j < dict.NumImages(); ++j)
+ SBSYMS.get()[dwTemp + j] = dict.GetImage(j);
+ dwTemp += dict.NumImages();
+ }
+ }
+ pTRD->SBSYMS = SBSYMS.get();
+ } else {
+ pTRD->SBSYMS = NULL;
+ }
+
+ std::unique_ptr<JBig2HuffmanCode, FxFreeDeleter> SBSYMCODES;
+ if (pTRD->SBHUFF == 1) {
+ SBSYMCODES.reset(
+ decodeSymbolIDHuffmanTable(m_pStream.get(), pTRD->SBNUMSYMS));
+ if (!SBSYMCODES)
+ return JBIG2_ERROR_FATAL;
+
+ m_pStream->alignByte();
+ pTRD->SBSYMCODES = SBSYMCODES.get();
+ } else {
+ dwTemp = 0;
+ while ((FX_DWORD)(1 << dwTemp) < pTRD->SBNUMSYMS) {
+ ++dwTemp;
+ }
+ pTRD->SBSYMCODELEN = (uint8_t)dwTemp;
+ }
+
+ std::unique_ptr<CJBig2_HuffmanTable> Table_B1;
+ std::unique_ptr<CJBig2_HuffmanTable> Table_B6;
+ std::unique_ptr<CJBig2_HuffmanTable> Table_B7;
+ std::unique_ptr<CJBig2_HuffmanTable> Table_B8;
+ std::unique_ptr<CJBig2_HuffmanTable> Table_B9;
+ std::unique_ptr<CJBig2_HuffmanTable> Table_B10;
+ std::unique_ptr<CJBig2_HuffmanTable> Table_B11;
+ std::unique_ptr<CJBig2_HuffmanTable> Table_B12;
+ std::unique_ptr<CJBig2_HuffmanTable> Table_B13;
+ std::unique_ptr<CJBig2_HuffmanTable> Table_B14;
+ std::unique_ptr<CJBig2_HuffmanTable> Table_B15;
+ if (pTRD->SBHUFF == 1) {
+ if (cSBHUFFFS == 2 || cSBHUFFRDW == 2 || cSBHUFFRDH == 2 ||
+ cSBHUFFRDX == 2 || cSBHUFFRDY == 2) {
+ return JBIG2_ERROR_FATAL;
+ }
+ int32_t nIndex = 0;
+ if (cSBHUFFFS == 0) {
+ Table_B6.reset(new CJBig2_HuffmanTable(HuffmanTable_B6,
+ FX_ArraySize(HuffmanTable_B6),
+ HuffmanTable_HTOOB_B6));
+ pTRD->SBHUFFFS = Table_B6.get();
+ } else if (cSBHUFFFS == 1) {
+ Table_B7.reset(new CJBig2_HuffmanTable(HuffmanTable_B7,
+ FX_ArraySize(HuffmanTable_B7),
+ HuffmanTable_HTOOB_B7));
+ pTRD->SBHUFFFS = Table_B7.get();
+ } else {
+ CJBig2_Segment* pSeg =
+ findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
+ if (!pSeg)
+ return JBIG2_ERROR_FATAL;
+ pTRD->SBHUFFFS = pSeg->m_Result.ht;
+ }
+ if (cSBHUFFDS == 0) {
+ Table_B8.reset(new CJBig2_HuffmanTable(HuffmanTable_B8,
+ FX_ArraySize(HuffmanTable_B8),
+ HuffmanTable_HTOOB_B8));
+ pTRD->SBHUFFDS = Table_B8.get();
+ } else if (cSBHUFFDS == 1) {
+ Table_B9.reset(new CJBig2_HuffmanTable(HuffmanTable_B9,
+ FX_ArraySize(HuffmanTable_B9),
+ HuffmanTable_HTOOB_B9));
+ pTRD->SBHUFFDS = Table_B9.get();
+ } else if (cSBHUFFDS == 2) {
+ Table_B10.reset(new CJBig2_HuffmanTable(HuffmanTable_B10,
+ FX_ArraySize(HuffmanTable_B10),
+ HuffmanTable_HTOOB_B10));
+ pTRD->SBHUFFDS = Table_B10.get();
+ } else {
+ CJBig2_Segment* pSeg =
+ findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
+ if (!pSeg)
+ return JBIG2_ERROR_FATAL;
+ pTRD->SBHUFFDS = pSeg->m_Result.ht;
+ }
+ if (cSBHUFFDT == 0) {
+ Table_B11.reset(new CJBig2_HuffmanTable(HuffmanTable_B11,
+ FX_ArraySize(HuffmanTable_B11),
+ HuffmanTable_HTOOB_B11));
+ pTRD->SBHUFFDT = Table_B11.get();
+ } else if (cSBHUFFDT == 1) {
+ Table_B12.reset(new CJBig2_HuffmanTable(HuffmanTable_B12,
+ FX_ArraySize(HuffmanTable_B12),
+ HuffmanTable_HTOOB_B12));
+ pTRD->SBHUFFDT = Table_B12.get();
+ } else if (cSBHUFFDT == 2) {
+ Table_B13.reset(new CJBig2_HuffmanTable(HuffmanTable_B13,
+ FX_ArraySize(HuffmanTable_B13),
+ HuffmanTable_HTOOB_B13));
+ pTRD->SBHUFFDT = Table_B13.get();
+ } else {
+ CJBig2_Segment* pSeg =
+ findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
+ if (!pSeg)
+ return JBIG2_ERROR_FATAL;
+ pTRD->SBHUFFDT = pSeg->m_Result.ht;
+ }
+ if (cSBHUFFRDW == 0) {
+ Table_B14.reset(new CJBig2_HuffmanTable(HuffmanTable_B14,
+ FX_ArraySize(HuffmanTable_B14),
+ HuffmanTable_HTOOB_B14));
+ pTRD->SBHUFFRDW = Table_B14.get();
+ } else if (cSBHUFFRDW == 1) {
+ Table_B15.reset(new CJBig2_HuffmanTable(HuffmanTable_B15,
+ FX_ArraySize(HuffmanTable_B15),
+ HuffmanTable_HTOOB_B15));
+ pTRD->SBHUFFRDW = Table_B15.get();
+ } else {
+ CJBig2_Segment* pSeg =
+ findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
+ if (!pSeg)
+ return JBIG2_ERROR_FATAL;
+ pTRD->SBHUFFRDW = pSeg->m_Result.ht;
+ }
+ if (cSBHUFFRDH == 0) {
+ if (!Table_B14) {
+ Table_B14.reset(new CJBig2_HuffmanTable(HuffmanTable_B14,
+ FX_ArraySize(HuffmanTable_B14),
+ HuffmanTable_HTOOB_B14));
+ }
+ pTRD->SBHUFFRDH = Table_B14.get();
+ } else if (cSBHUFFRDH == 1) {
+ if (!Table_B15) {
+ Table_B15.reset(new CJBig2_HuffmanTable(HuffmanTable_B15,
+ FX_ArraySize(HuffmanTable_B15),
+ HuffmanTable_HTOOB_B15));
+ }
+ pTRD->SBHUFFRDH = Table_B15.get();
+ } else {
+ CJBig2_Segment* pSeg =
+ findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
+ if (!pSeg)
+ return JBIG2_ERROR_FATAL;
+ pTRD->SBHUFFRDH = pSeg->m_Result.ht;
+ }
+ if (cSBHUFFRDX == 0) {
+ if (!Table_B14) {
+ Table_B14.reset(new CJBig2_HuffmanTable(HuffmanTable_B14,
+ FX_ArraySize(HuffmanTable_B14),
+ HuffmanTable_HTOOB_B14));
+ }
+ pTRD->SBHUFFRDX = Table_B14.get();
+ } else if (cSBHUFFRDX == 1) {
+ if (!Table_B15) {
+ Table_B15.reset(new CJBig2_HuffmanTable(HuffmanTable_B15,
+ FX_ArraySize(HuffmanTable_B15),
+ HuffmanTable_HTOOB_B15));
+ }
+ pTRD->SBHUFFRDX = Table_B15.get();
+ } else {
+ CJBig2_Segment* pSeg =
+ findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
+ if (!pSeg)
+ return JBIG2_ERROR_FATAL;
+ pTRD->SBHUFFRDX = pSeg->m_Result.ht;
+ }
+ if (cSBHUFFRDY == 0) {
+ if (!Table_B14) {
+ Table_B14.reset(new CJBig2_HuffmanTable(HuffmanTable_B14,
+ FX_ArraySize(HuffmanTable_B14),
+ HuffmanTable_HTOOB_B14));
+ }
+ pTRD->SBHUFFRDY = Table_B14.get();
+ } else if (cSBHUFFRDY == 1) {
+ if (!Table_B15) {
+ Table_B15.reset(new CJBig2_HuffmanTable(HuffmanTable_B15,
+ FX_ArraySize(HuffmanTable_B15),
+ HuffmanTable_HTOOB_B15));
+ }
+ pTRD->SBHUFFRDY = Table_B15.get();
+ } else {
+ CJBig2_Segment* pSeg =
+ findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
+ if (!pSeg)
+ return JBIG2_ERROR_FATAL;
+ pTRD->SBHUFFRDY = pSeg->m_Result.ht;
+ }
+ if (cSBHUFFRSIZE == 0) {
+ Table_B1.reset(new CJBig2_HuffmanTable(HuffmanTable_B1,
+ FX_ArraySize(HuffmanTable_B1),
+ HuffmanTable_HTOOB_B1));
+ pTRD->SBHUFFRSIZE = Table_B1.get();
+ } else {
+ CJBig2_Segment* pSeg =
+ findReferredSegmentByTypeAndIndex(pSegment, 53, nIndex++);
+ if (!pSeg)
+ return JBIG2_ERROR_FATAL;
+ pTRD->SBHUFFRSIZE = pSeg->m_Result.ht;
+ }
+ }
+ std::unique_ptr<JBig2ArithCtx, FxFreeDeleter> grContext;
+ if (pTRD->SBREFINE == 1) {
+ const size_t size = GetRefAggContextSize(pTRD->SBRTEMPLATE);
+ grContext.reset(FX_Alloc(JBig2ArithCtx, size));
+ JBIG2_memset(grContext.get(), 0, sizeof(JBig2ArithCtx) * size);
+ }
+ if (pTRD->SBHUFF == 0) {
+ std::unique_ptr<CJBig2_ArithDecoder> pArithDecoder(
+ new CJBig2_ArithDecoder(m_pStream.get()));
+ pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
+ pSegment->m_Result.im =
+ pTRD->decode_Arith(pArithDecoder.get(), grContext.get(), nullptr);
+ if (!pSegment->m_Result.im)
+ return JBIG2_ERROR_FATAL;
+ m_pStream->alignByte();
+ m_pStream->offset(2);
+ } else {
+ pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
+ pSegment->m_Result.im =
+ pTRD->decode_Huffman(m_pStream.get(), grContext.get());
+ if (!pSegment->m_Result.im)
+ return JBIG2_ERROR_FATAL;
+ m_pStream->alignByte();
+ }
+ if (pSegment->m_cFlags.s.type != 4) {
+ if (!m_bBufSpecified) {
+ JBig2PageInfo* pPageInfo = m_PageInfoList.back();
+ if ((pPageInfo->m_bIsStriped == 1) &&
+ (ri.y + ri.height > m_pPage->m_nHeight)) {
+ m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0);
+ }
+ }
+ m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Result.im,
+ (JBig2ComposeOp)(ri.flags & 0x03));
+ delete pSegment->m_Result.im;
+ pSegment->m_Result.im = NULL;
+ }
+ return JBIG2_SUCCESS;
+}
+
+int32_t CJBig2_Context::parsePatternDict(CJBig2_Segment* pSegment,
+ IFX_Pause* pPause) {
+ uint8_t cFlags;
+ std::unique_ptr<CJBig2_PDDProc> pPDD(new CJBig2_PDDProc);
+ if (m_pStream->read1Byte(&cFlags) != 0 ||
+ m_pStream->read1Byte(&pPDD->HDPW) != 0 ||
+ m_pStream->read1Byte(&pPDD->HDPH) != 0 ||
+ m_pStream->readInteger(&pPDD->GRAYMAX) != 0) {
+ return JBIG2_ERROR_TOO_SHORT;
+ }
+ if (pPDD->GRAYMAX > JBIG2_MAX_PATTERN_INDEX)
+ return JBIG2_ERROR_LIMIT;
+
+ pPDD->HDMMR = cFlags & 0x01;
+ pPDD->HDTEMPLATE = (cFlags >> 1) & 0x03;
+ pSegment->m_nResultType = JBIG2_PATTERN_DICT_POINTER;
+ if (pPDD->HDMMR == 0) {
+ const size_t size = GetHuffContextSize(pPDD->HDTEMPLATE);
+ std::unique_ptr<JBig2ArithCtx, FxFreeDeleter> gbContext(
+ FX_Alloc(JBig2ArithCtx, size));
+ JBIG2_memset(gbContext.get(), 0, sizeof(JBig2ArithCtx) * size);
+ std::unique_ptr<CJBig2_ArithDecoder> pArithDecoder(
+ new CJBig2_ArithDecoder(m_pStream.get()));
+ pSegment->m_Result.pd =
+ pPDD->decode_Arith(pArithDecoder.get(), gbContext.get(), pPause);
+ if (!pSegment->m_Result.pd)
+ return JBIG2_ERROR_FATAL;
+
+ m_pStream->alignByte();
+ m_pStream->offset(2);
+ } else {
+ pSegment->m_Result.pd = pPDD->decode_MMR(m_pStream.get(), pPause);
+ if (!pSegment->m_Result.pd)
+ return JBIG2_ERROR_FATAL;
+ m_pStream->alignByte();
+ }
+ return JBIG2_SUCCESS;
+}
+
+int32_t CJBig2_Context::parseHalftoneRegion(CJBig2_Segment* pSegment,
+ IFX_Pause* pPause) {
+ uint8_t cFlags;
+ JBig2RegionInfo ri;
+ std::unique_ptr<CJBig2_HTRDProc> pHRD(new CJBig2_HTRDProc);
+ if (parseRegionInfo(&ri) != JBIG2_SUCCESS ||
+ m_pStream->read1Byte(&cFlags) != 0 ||
+ m_pStream->readInteger(&pHRD->HGW) != 0 ||
+ m_pStream->readInteger(&pHRD->HGH) != 0 ||
+ m_pStream->readInteger((FX_DWORD*)&pHRD->HGX) != 0 ||
+ m_pStream->readInteger((FX_DWORD*)&pHRD->HGY) != 0 ||
+ m_pStream->readShortInteger(&pHRD->HRX) != 0 ||
+ m_pStream->readShortInteger(&pHRD->HRY) != 0) {
+ return JBIG2_ERROR_TOO_SHORT;
+ }
+
+ if (pHRD->HGW == 0 || pHRD->HGH == 0)
+ return JBIG2_ERROR_FATAL;
+
+ pHRD->HBW = ri.width;
+ pHRD->HBH = ri.height;
+ pHRD->HMMR = cFlags & 0x01;
+ pHRD->HTEMPLATE = (cFlags >> 1) & 0x03;
+ pHRD->HENABLESKIP = (cFlags >> 3) & 0x01;
+ pHRD->HCOMBOP = (JBig2ComposeOp)((cFlags >> 4) & 0x07);
+ pHRD->HDEFPIXEL = (cFlags >> 7) & 0x01;
+ if (pSegment->m_nReferred_to_segment_count != 1)
+ return JBIG2_ERROR_FATAL;
+
+ CJBig2_Segment* pSeg =
+ findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[0]);
+ if (!pSeg || (pSeg->m_cFlags.s.type != 16))
+ return JBIG2_ERROR_FATAL;
+
+ CJBig2_PatternDict* pPatternDict = pSeg->m_Result.pd;
+ if (!pPatternDict || (pPatternDict->NUMPATS == 0))
+ return JBIG2_ERROR_FATAL;
+
+ pHRD->HNUMPATS = pPatternDict->NUMPATS;
+ pHRD->HPATS = pPatternDict->HDPATS;
+ pHRD->HPW = pPatternDict->HDPATS[0]->m_nWidth;
+ pHRD->HPH = pPatternDict->HDPATS[0]->m_nHeight;
+ pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
+ if (pHRD->HMMR == 0) {
+ const size_t size = GetHuffContextSize(pHRD->HTEMPLATE);
+ std::unique_ptr<JBig2ArithCtx, FxFreeDeleter> gbContext(
+ FX_Alloc(JBig2ArithCtx, size));
+ JBIG2_memset(gbContext.get(), 0, sizeof(JBig2ArithCtx) * size);
+ std::unique_ptr<CJBig2_ArithDecoder> pArithDecoder(
+ new CJBig2_ArithDecoder(m_pStream.get()));
+ pSegment->m_Result.im =
+ pHRD->decode_Arith(pArithDecoder.get(), gbContext.get(), pPause);
+ if (!pSegment->m_Result.im)
+ return JBIG2_ERROR_FATAL;
+
+ m_pStream->alignByte();
+ m_pStream->offset(2);
+ } else {
+ pSegment->m_Result.im = pHRD->decode_MMR(m_pStream.get(), pPause);
+ if (!pSegment->m_Result.im)
+ return JBIG2_ERROR_FATAL;
+ m_pStream->alignByte();
+ }
+ if (pSegment->m_cFlags.s.type != 20) {
+ if (!m_bBufSpecified) {
+ JBig2PageInfo* pPageInfo = m_PageInfoList.back();
+ if (pPageInfo->m_bIsStriped == 1 &&
+ ri.y + ri.height > m_pPage->m_nHeight) {
+ m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0);
+ }
+ }
+ m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Result.im,
+ (JBig2ComposeOp)(ri.flags & 0x03));
+ delete pSegment->m_Result.im;
+ pSegment->m_Result.im = NULL;
+ }
+ return JBIG2_SUCCESS;
+}
+
+int32_t CJBig2_Context::parseGenericRegion(CJBig2_Segment* pSegment,
+ IFX_Pause* pPause) {
+ if (!m_pGRD) {
+ std::unique_ptr<CJBig2_GRDProc> pGRD(new CJBig2_GRDProc);
+ uint8_t cFlags;
+ if (parseRegionInfo(&m_ri) != JBIG2_SUCCESS ||
+ m_pStream->read1Byte(&cFlags) != 0) {
+ return JBIG2_ERROR_TOO_SHORT;
+ }
+ if (m_ri.height < 0 || m_ri.width < 0)
+ return JBIG2_FAILED;
+
+ pGRD->GBW = m_ri.width;
+ pGRD->GBH = m_ri.height;
+ pGRD->MMR = cFlags & 0x01;
+ pGRD->GBTEMPLATE = (cFlags >> 1) & 0x03;
+ pGRD->TPGDON = (cFlags >> 3) & 0x01;
+ if (pGRD->MMR == 0) {
+ if (pGRD->GBTEMPLATE == 0) {
+ for (int32_t i = 0; i < 8; ++i) {
+ if (m_pStream->read1Byte((uint8_t*)&pGRD->GBAT[i]) != 0) {
+ return JBIG2_ERROR_TOO_SHORT;
+ }
+ }
+ } else {
+ for (int32_t i = 0; i < 2; ++i) {
+ if (m_pStream->read1Byte((uint8_t*)&pGRD->GBAT[i]) != 0) {
+ return JBIG2_ERROR_TOO_SHORT;
+ }
+ }
+ }
+ }
+ pGRD->USESKIP = 0;
+ m_pGRD = std::move(pGRD);
+ }
+ pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
+ if (m_pGRD->MMR == 0) {
+ if (!m_gbContext) {
+ const size_t size = GetHuffContextSize(m_pGRD->GBTEMPLATE);
+ m_gbContext = FX_Alloc(JBig2ArithCtx, size);
+ JBIG2_memset(m_gbContext, 0, sizeof(JBig2ArithCtx) * size);
+ }
+ if (!m_pArithDecoder) {
+ m_pArithDecoder.reset(new CJBig2_ArithDecoder(m_pStream.get()));
+ m_ProcessingStatus = m_pGRD->Start_decode_Arith(
+ &pSegment->m_Result.im, m_pArithDecoder.get(), m_gbContext, pPause);
+ } else {
+ m_ProcessingStatus = m_pGRD->Continue_decode(pPause);
+ }
+ if (m_ProcessingStatus == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
+ if (pSegment->m_cFlags.s.type != 36) {
+ if (!m_bBufSpecified) {
+ JBig2PageInfo* pPageInfo = m_PageInfoList.back();
+ if ((pPageInfo->m_bIsStriped == 1) &&
+ (m_ri.y + m_ri.height > m_pPage->m_nHeight)) {
+ m_pPage->expand(m_ri.y + m_ri.height,
+ (pPageInfo->m_cFlags & 4) ? 1 : 0);
+ }
+ }
+ FX_RECT Rect = m_pGRD->GetReplaceRect();
+ m_pPage->composeFrom(m_ri.x + Rect.left, m_ri.y + Rect.top,
+ pSegment->m_Result.im,
+ (JBig2ComposeOp)(m_ri.flags & 0x03), &Rect);
+ }
+ return JBIG2_SUCCESS;
+ } else {
+ m_pArithDecoder.reset();
+ FX_Free(m_gbContext);
+ m_gbContext = NULL;
+ if (!pSegment->m_Result.im) {
+ m_ProcessingStatus = FXCODEC_STATUS_ERROR;
+ m_pGRD.reset();
+ return JBIG2_ERROR_FATAL;
+ }
+ m_pStream->alignByte();
+ m_pStream->offset(2);
+ }
+ } else {
+ FXCODEC_STATUS status = m_pGRD->Start_decode_MMR(&pSegment->m_Result.im,
+ m_pStream.get(), pPause);
+ while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
+ m_pGRD->Continue_decode(pPause);
+ }
+ if (!pSegment->m_Result.im) {
+ m_pGRD.reset();
+ return JBIG2_ERROR_FATAL;
+ }
+ m_pStream->alignByte();
+ }
+ if (pSegment->m_cFlags.s.type != 36) {
+ if (!m_bBufSpecified) {
+ JBig2PageInfo* pPageInfo = m_PageInfoList.back();
+ if ((pPageInfo->m_bIsStriped == 1) &&
+ (m_ri.y + m_ri.height > m_pPage->m_nHeight)) {
+ m_pPage->expand(m_ri.y + m_ri.height,
+ (pPageInfo->m_cFlags & 4) ? 1 : 0);
+ }
+ }
+ FX_RECT Rect = m_pGRD->GetReplaceRect();
+ m_pPage->composeFrom(m_ri.x + Rect.left, m_ri.y + Rect.top,
+ pSegment->m_Result.im,
+ (JBig2ComposeOp)(m_ri.flags & 0x03), &Rect);
+ delete pSegment->m_Result.im;
+ pSegment->m_Result.im = NULL;
+ }
+ m_pGRD.reset();
+ return JBIG2_SUCCESS;
+}
+
+int32_t CJBig2_Context::parseGenericRefinementRegion(CJBig2_Segment* pSegment) {
+ JBig2RegionInfo ri;
+ uint8_t cFlags;
+ if (parseRegionInfo(&ri) != JBIG2_SUCCESS ||
+ m_pStream->read1Byte(&cFlags) != 0) {
+ return JBIG2_ERROR_TOO_SHORT;
+ }
+ std::unique_ptr<CJBig2_GRRDProc> pGRRD(new CJBig2_GRRDProc);
+ pGRRD->GRW = ri.width;
+ pGRRD->GRH = ri.height;
+ pGRRD->GRTEMPLATE = cFlags & 0x01;
+ pGRRD->TPGRON = (cFlags >> 1) & 0x01;
+ if (pGRRD->GRTEMPLATE == 0) {
+ for (int32_t i = 0; i < 4; ++i) {
+ if (m_pStream->read1Byte((uint8_t*)&pGRRD->GRAT[i]) != 0)
+ return JBIG2_ERROR_TOO_SHORT;
+ }
+ }
+ CJBig2_Segment* pSeg = nullptr;
+ if (pSegment->m_nReferred_to_segment_count > 0) {
+ int32_t i;
+ for (i = 0; i < pSegment->m_nReferred_to_segment_count; ++i) {
+ pSeg = findSegmentByNumber(pSegment->m_pReferred_to_segment_numbers[0]);
+ if (!pSeg)
+ return JBIG2_ERROR_FATAL;
+
+ if (pSeg->m_cFlags.s.type == 4 || pSeg->m_cFlags.s.type == 20 ||
+ pSeg->m_cFlags.s.type == 36 || pSeg->m_cFlags.s.type == 40) {
+ break;
+ }
+ }
+ if (i >= pSegment->m_nReferred_to_segment_count)
+ return JBIG2_ERROR_FATAL;
+
+ pGRRD->GRREFERENCE = pSeg->m_Result.im;
+ } else {
+ pGRRD->GRREFERENCE = m_pPage.get();
+ }
+ pGRRD->GRREFERENCEDX = 0;
+ pGRRD->GRREFERENCEDY = 0;
+ const size_t size = GetRefAggContextSize(pGRRD->GRTEMPLATE);
+ std::unique_ptr<JBig2ArithCtx, FxFreeDeleter> grContext(
+ FX_Alloc(JBig2ArithCtx, size));
+ JBIG2_memset(grContext.get(), 0, sizeof(JBig2ArithCtx) * size);
+ std::unique_ptr<CJBig2_ArithDecoder> pArithDecoder(
+ new CJBig2_ArithDecoder(m_pStream.get()));
+ pSegment->m_nResultType = JBIG2_IMAGE_POINTER;
+ pSegment->m_Result.im = pGRRD->decode(pArithDecoder.get(), grContext.get());
+ if (!pSegment->m_Result.im)
+ return JBIG2_ERROR_FATAL;
+
+ m_pStream->alignByte();
+ m_pStream->offset(2);
+ if (pSegment->m_cFlags.s.type != 40) {
+ if (!m_bBufSpecified) {
+ JBig2PageInfo* pPageInfo = m_PageInfoList.back();
+ if ((pPageInfo->m_bIsStriped == 1) &&
+ (ri.y + ri.height > m_pPage->m_nHeight)) {
+ m_pPage->expand(ri.y + ri.height, (pPageInfo->m_cFlags & 4) ? 1 : 0);
+ }
+ }
+ m_pPage->composeFrom(ri.x, ri.y, pSegment->m_Result.im,
+ (JBig2ComposeOp)(ri.flags & 0x03));
+ delete pSegment->m_Result.im;
+ pSegment->m_Result.im = NULL;
+ }
+ return JBIG2_SUCCESS;
+}
+
+int32_t CJBig2_Context::parseTable(CJBig2_Segment* pSegment) {
+ pSegment->m_nResultType = JBIG2_HUFFMAN_TABLE_POINTER;
+ pSegment->m_Result.ht = nullptr;
+ std::unique_ptr<CJBig2_HuffmanTable> pHuff(
+ new CJBig2_HuffmanTable(m_pStream.get()));
+ if (!pHuff->IsOK())
+ return JBIG2_ERROR_FATAL;
+
+ pSegment->m_Result.ht = pHuff.release();
+ m_pStream->alignByte();
+ return JBIG2_SUCCESS;
+}
+
+int32_t CJBig2_Context::parseRegionInfo(JBig2RegionInfo* pRI) {
+ if (m_pStream->readInteger((FX_DWORD*)&pRI->width) != 0 ||
+ m_pStream->readInteger((FX_DWORD*)&pRI->height) != 0 ||
+ m_pStream->readInteger((FX_DWORD*)&pRI->x) != 0 ||
+ m_pStream->readInteger((FX_DWORD*)&pRI->y) != 0 ||
+ m_pStream->read1Byte(&pRI->flags) != 0) {
+ return JBIG2_ERROR_TOO_SHORT;
+ }
+ return JBIG2_SUCCESS;
+}
+
+JBig2HuffmanCode* CJBig2_Context::decodeSymbolIDHuffmanTable(
+ CJBig2_BitStream* pStream,
+ FX_DWORD SBNUMSYMS) {
+ const size_t kRunCodesSize = 35;
+ int32_t runcodes[kRunCodesSize];
+ int32_t runcodes_len[kRunCodesSize];
+ for (int32_t i = 0; i < kRunCodesSize; ++i) {
+ if (pStream->readNBits(4, &runcodes_len[i]) != 0)
+ return nullptr;
+ }
+ huffman_assign_code(runcodes, runcodes_len, kRunCodesSize);
+
+ std::unique_ptr<JBig2HuffmanCode, FxFreeDeleter> SBSYMCODES(
+ FX_Alloc(JBig2HuffmanCode, SBNUMSYMS));
+ int32_t run;
+ int32_t i = 0;
+ while (i < (int)SBNUMSYMS) {
+ int32_t j;
+ int32_t nVal = 0;
+ int32_t nBits = 0;
+ FX_DWORD nTemp;
+ while (true) {
+ if (pStream->read1Bit(&nTemp) != 0)
+ return nullptr;
+
+ nVal = (nVal << 1) | nTemp;
+ ++nBits;
+ for (j = 0; j < kRunCodesSize; ++j) {
+ if (nBits == runcodes_len[j] && nVal == runcodes[j]) {
+ break;
+ }
+ }
+ if (j < kRunCodesSize) {
+ break;
+ }
+ }
+ int32_t runcode = j;
+ if (runcode < 32) {
+ SBSYMCODES.get()[i].codelen = runcode;
+ run = 0;
+ } else if (runcode == 32) {
+ if (pStream->readNBits(2, &nTemp) != 0)
+ return nullptr;
+ run = nTemp + 3;
+ } else if (runcode == 33) {
+ if (pStream->readNBits(3, &nTemp) != 0)
+ return nullptr;
+ run = nTemp + 3;
+ } else if (runcode == 34) {
+ if (pStream->readNBits(7, &nTemp) != 0)
+ return nullptr;
+ run = nTemp + 11;
+ }
+ if (run > 0) {
+ if (i + run > (int)SBNUMSYMS)
+ return nullptr;
+ for (j = 0; j < run; ++j) {
+ if (runcode == 32 && i > 0) {
+ SBSYMCODES.get()[i + j].codelen = SBSYMCODES.get()[i - 1].codelen;
+ } else {
+ SBSYMCODES.get()[i + j].codelen = 0;
+ }
+ }
+ i += run;
+ } else {
+ ++i;
+ }
+ }
+ huffman_assign_code(SBSYMCODES.get(), SBNUMSYMS);
+ return SBSYMCODES.release();
+}
+
+void CJBig2_Context::huffman_assign_code(int* CODES, int* PREFLEN, int NTEMP) {
+ // TODO(thestig) CJBig2_HuffmanTable::parseFromCodedBuffer() has similar code.
+ int CURLEN, LENMAX, CURCODE, CURTEMP, i;
+ int* LENCOUNT;
+ int* FIRSTCODE;
+ LENMAX = 0;
+ for (i = 0; i < NTEMP; ++i) {
+ if (PREFLEN[i] > LENMAX) {
+ LENMAX = PREFLEN[i];
+ }
+ }
+ LENCOUNT = FX_Alloc(int, LENMAX + 1);
+ JBIG2_memset(LENCOUNT, 0, sizeof(int) * (LENMAX + 1));
+ FIRSTCODE = FX_Alloc(int, LENMAX + 1);
+ for (i = 0; i < NTEMP; ++i) {
+ ++LENCOUNT[PREFLEN[i]];
+ }
+ CURLEN = 1;
+ FIRSTCODE[0] = 0;
+ LENCOUNT[0] = 0;
+ while (CURLEN <= LENMAX) {
+ FIRSTCODE[CURLEN] = (FIRSTCODE[CURLEN - 1] + LENCOUNT[CURLEN - 1]) << 1;
+ CURCODE = FIRSTCODE[CURLEN];
+ CURTEMP = 0;
+ while (CURTEMP < NTEMP) {
+ if (PREFLEN[CURTEMP] == CURLEN) {
+ CODES[CURTEMP] = CURCODE;
+ CURCODE = CURCODE + 1;
+ }
+ CURTEMP = CURTEMP + 1;
+ }
+ CURLEN = CURLEN + 1;
+ }
+ FX_Free(LENCOUNT);
+ FX_Free(FIRSTCODE);
+}
+void CJBig2_Context::huffman_assign_code(JBig2HuffmanCode* SBSYMCODES,
+ int NTEMP) {
+ int CURLEN, LENMAX, CURCODE, CURTEMP, i;
+ int* LENCOUNT;
+ int* FIRSTCODE;
+ LENMAX = 0;
+ for (i = 0; i < NTEMP; ++i) {
+ if (SBSYMCODES[i].codelen > LENMAX) {
+ LENMAX = SBSYMCODES[i].codelen;
+ }
+ }
+ LENCOUNT = FX_Alloc(int, (LENMAX + 1));
+ JBIG2_memset(LENCOUNT, 0, sizeof(int) * (LENMAX + 1));
+ FIRSTCODE = FX_Alloc(int, (LENMAX + 1));
+ for (i = 0; i < NTEMP; ++i) {
+ ++LENCOUNT[SBSYMCODES[i].codelen];
+ }
+ CURLEN = 1;
+ FIRSTCODE[0] = 0;
+ LENCOUNT[0] = 0;
+ while (CURLEN <= LENMAX) {
+ FIRSTCODE[CURLEN] = (FIRSTCODE[CURLEN - 1] + LENCOUNT[CURLEN - 1]) << 1;
+ CURCODE = FIRSTCODE[CURLEN];
+ CURTEMP = 0;
+ while (CURTEMP < NTEMP) {
+ if (SBSYMCODES[CURTEMP].codelen == CURLEN) {
+ SBSYMCODES[CURTEMP].code = CURCODE;
+ CURCODE = CURCODE + 1;
+ }
+ CURTEMP = CURTEMP + 1;
+ }
+ CURLEN = CURLEN + 1;
+ }
+ FX_Free(LENCOUNT);
+ FX_Free(FIRSTCODE);
+}
diff --git a/core/fxcodec/jbig2/JBig2_Context.h b/core/fxcodec/jbig2/JBig2_Context.h
new file mode 100644
index 0000000000..f09b8fc1ab
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_Context.h
@@ -0,0 +1,134 @@
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_JBIG2_JBIG2_CONTEXT_H_
+#define CORE_FXCODEC_JBIG2_JBIG2_CONTEXT_H_
+
+#include <list>
+#include <memory>
+#include <utility>
+
+#include "core/fxcodec/jbig2/JBig2_List.h"
+#include "core/fxcodec/jbig2/JBig2_Page.h"
+#include "core/fxcodec/jbig2/JBig2_Segment.h"
+#include "core/include/fpdfapi/cpdf_object.h"
+#include "core/include/fxcodec/fx_codec_def.h"
+
+class CJBig2_ArithDecoder;
+class CJBig2_GRDProc;
+class CPDF_StreamAcc;
+class IFX_Pause;
+
+// Cache is keyed by the ObjNum of a stream and an index within the stream.
+using CJBig2_CacheKey = std::pair<FX_DWORD, FX_DWORD>;
+// NB: CJBig2_SymbolDict* is owned.
+using CJBig2_CachePair = std::pair<CJBig2_CacheKey, CJBig2_SymbolDict*>;
+
+#define JBIG2_SUCCESS 0
+#define JBIG2_FAILED -1
+#define JBIG2_ERROR_TOO_SHORT -2
+#define JBIG2_ERROR_FATAL -3
+#define JBIG2_END_OF_PAGE 2
+#define JBIG2_END_OF_FILE 3
+#define JBIG2_ERROR_FILE_FORMAT -4
+#define JBIG2_ERROR_STREAM_TYPE -5
+#define JBIG2_ERROR_LIMIT -6
+#define JBIG2_MIN_SEGMENT_SIZE 11
+
+class CJBig2_Context {
+ public:
+ static CJBig2_Context* CreateContext(
+ CPDF_StreamAcc* pGlobalStream,
+ CPDF_StreamAcc* pSrcStream,
+ std::list<CJBig2_CachePair>* pSymbolDictCache,
+ IFX_Pause* pPause = NULL);
+
+ static void DestroyContext(CJBig2_Context* pContext);
+
+ int32_t getFirstPage(uint8_t* pBuf,
+ int32_t width,
+ int32_t height,
+ int32_t stride,
+ IFX_Pause* pPause);
+
+ int32_t Continue(IFX_Pause* pPause);
+ FXCODEC_STATUS GetProcessingStatus() { return m_ProcessingStatus; }
+
+ private:
+ CJBig2_Context(CPDF_StreamAcc* pGlobalStream,
+ CPDF_StreamAcc* pSrcStream,
+ std::list<CJBig2_CachePair>* pSymbolDictCache,
+ IFX_Pause* pPause,
+ bool bIsGlobal);
+
+ ~CJBig2_Context();
+
+ int32_t decode_SquentialOrgnazation(IFX_Pause* pPause);
+
+ int32_t decode_EmbedOrgnazation(IFX_Pause* pPause);
+
+ int32_t decode_RandomOrgnazation_FirstPage(IFX_Pause* pPause);
+
+ int32_t decode_RandomOrgnazation(IFX_Pause* pPause);
+
+ CJBig2_Segment* findSegmentByNumber(FX_DWORD dwNumber);
+
+ CJBig2_Segment* findReferredSegmentByTypeAndIndex(CJBig2_Segment* pSegment,
+ uint8_t cType,
+ int32_t nIndex);
+
+ int32_t parseSegmentHeader(CJBig2_Segment* pSegment);
+
+ int32_t parseSegmentData(CJBig2_Segment* pSegment, IFX_Pause* pPause);
+ int32_t ProcessingParseSegmentData(CJBig2_Segment* pSegment,
+ IFX_Pause* pPause);
+
+ int32_t parseSymbolDict(CJBig2_Segment* pSegment, IFX_Pause* pPause);
+
+ int32_t parseTextRegion(CJBig2_Segment* pSegment);
+
+ int32_t parsePatternDict(CJBig2_Segment* pSegment, IFX_Pause* pPause);
+
+ int32_t parseHalftoneRegion(CJBig2_Segment* pSegment, IFX_Pause* pPause);
+
+ int32_t parseGenericRegion(CJBig2_Segment* pSegment, IFX_Pause* pPause);
+
+ int32_t parseGenericRefinementRegion(CJBig2_Segment* pSegment);
+
+ int32_t parseTable(CJBig2_Segment* pSegment);
+
+ int32_t parseRegionInfo(JBig2RegionInfo* pRI);
+
+ JBig2HuffmanCode* decodeSymbolIDHuffmanTable(CJBig2_BitStream* pStream,
+ FX_DWORD SBNUMSYMS);
+
+ void huffman_assign_code(int* CODES, int* PREFLEN, int NTEMP);
+
+ void huffman_assign_code(JBig2HuffmanCode* SBSYMCODES, int NTEMP);
+
+ private:
+ CJBig2_Context* m_pGlobalContext;
+ std::unique_ptr<CJBig2_BitStream> m_pStream;
+ CJBig2_List<CJBig2_Segment> m_SegmentList;
+ CJBig2_List<JBig2PageInfo> m_PageInfoList;
+ std::unique_ptr<CJBig2_Image> m_pPage;
+ size_t m_nSegmentDecoded;
+ bool m_bInPage;
+ bool m_bBufSpecified;
+ int32_t m_PauseStep;
+ IFX_Pause* m_pPause;
+ FXCODEC_STATUS m_ProcessingStatus;
+ std::unique_ptr<CJBig2_ArithDecoder> m_pArithDecoder;
+ std::unique_ptr<CJBig2_GRDProc> m_pGRD;
+ JBig2ArithCtx* m_gbContext;
+ std::unique_ptr<CJBig2_Segment> m_pSegment;
+ FX_DWORD m_dwOffset;
+ JBig2RegionInfo m_ri;
+ std::list<CJBig2_CachePair>* const m_pSymbolDictCache;
+ bool m_bIsGlobal;
+};
+
+#endif // CORE_FXCODEC_JBIG2_JBIG2_CONTEXT_H_
diff --git a/core/fxcodec/jbig2/JBig2_Define.h b/core/fxcodec/jbig2/JBig2_Define.h
new file mode 100644
index 0000000000..5149c19ef2
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_Define.h
@@ -0,0 +1,36 @@
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_JBIG2_JBIG2_DEFINE_H_
+#define CORE_FXCODEC_JBIG2_JBIG2_DEFINE_H_
+
+#include "core/include/fxcrt/fx_system.h"
+
+#define JBIG2_memset FXSYS_memset
+#define JBIG2_memcmp FXSYS_memcmp
+#define JBIG2_memcpy FXSYS_memcpy
+#define JBIG2_OOB 1
+
+struct JBig2RegionInfo {
+ int32_t width;
+ int32_t height;
+ int32_t x;
+ int32_t y;
+ uint8_t flags;
+};
+
+struct JBig2HuffmanCode {
+ int32_t codelen;
+ int32_t code;
+};
+
+#define JBIG2_MAX_REFERRED_SEGMENT_COUNT 64
+#define JBIG2_MAX_EXPORT_SYSMBOLS 65535
+#define JBIG2_MAX_NEW_SYSMBOLS 65535
+#define JBIG2_MAX_PATTERN_INDEX 65535
+#define JBIG2_MAX_IMAGE_SIZE 65535
+
+#endif // CORE_FXCODEC_JBIG2_JBIG2_DEFINE_H_
diff --git a/core/fxcodec/jbig2/JBig2_GrdProc.cpp b/core/fxcodec/jbig2/JBig2_GrdProc.cpp
new file mode 100644
index 0000000000..a3fc33c2be
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_GrdProc.cpp
@@ -0,0 +1,1259 @@
+// Copyright 2015 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxcodec/jbig2/JBig2_GrdProc.h"
+
+#include <memory>
+
+#include "core/fxcodec/jbig2/JBig2_ArithDecoder.h"
+#include "core/fxcodec/jbig2/JBig2_BitStream.h"
+#include "core/fxcodec/jbig2/JBig2_Image.h"
+#include "core/include/fxcodec/fx_codec.h"
+
+CJBig2_GRDProc::CJBig2_GRDProc()
+ : m_loopIndex(0),
+ m_pLine(nullptr),
+ m_pPause(nullptr),
+ m_DecodeType(0),
+ LTP(0) {
+ m_ReplaceRect.left = 0;
+ m_ReplaceRect.bottom = 0;
+ m_ReplaceRect.top = 0;
+ m_ReplaceRect.right = 0;
+}
+
+bool CJBig2_GRDProc::UseTemplate0Opt3() const {
+ return (GBAT[0] == 3) && (GBAT[1] == -1) && (GBAT[2] == -3) &&
+ (GBAT[3] == -1) && (GBAT[4] == 2) && (GBAT[5] == -2) &&
+ (GBAT[6] == -2) && (GBAT[7] == -2);
+}
+
+bool CJBig2_GRDProc::UseTemplate1Opt3() const {
+ return (GBAT[0] == 3) && (GBAT[1] == -1);
+}
+
+bool CJBig2_GRDProc::UseTemplate23Opt3() const {
+ return (GBAT[0] == 2) && (GBAT[1] == -1);
+}
+
+CJBig2_Image* CJBig2_GRDProc::decode_Arith(CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext) {
+ if (GBW == 0 || GBH == 0)
+ return new CJBig2_Image(GBW, GBH);
+
+ if (GBTEMPLATE == 0) {
+ if (UseTemplate0Opt3())
+ return decode_Arith_Template0_opt3(pArithDecoder, gbContext);
+ return decode_Arith_Template0_unopt(pArithDecoder, gbContext);
+ } else if (GBTEMPLATE == 1) {
+ if (UseTemplate1Opt3())
+ return decode_Arith_Template1_opt3(pArithDecoder, gbContext);
+ return decode_Arith_Template1_unopt(pArithDecoder, gbContext);
+ } else if (GBTEMPLATE == 2) {
+ if (UseTemplate23Opt3())
+ return decode_Arith_Template2_opt3(pArithDecoder, gbContext);
+ return decode_Arith_Template2_unopt(pArithDecoder, gbContext);
+ } else {
+ if (UseTemplate23Opt3())
+ return decode_Arith_Template3_opt3(pArithDecoder, gbContext);
+ return decode_Arith_Template3_unopt(pArithDecoder, gbContext);
+ }
+}
+CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template0_opt3(
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext) {
+ FX_BOOL LTP, SLTP, bVal;
+ FX_DWORD CONTEXT;
+ FX_DWORD line1, line2;
+ uint8_t *pLine, *pLine1, *pLine2, cVal;
+ int32_t nStride, nStride2, k;
+ int32_t nLineBytes, nBitsLeft, cc;
+ LTP = 0;
+ std::unique_ptr<CJBig2_Image> GBREG(new CJBig2_Image(GBW, GBH));
+ if (!GBREG->m_pData)
+ return nullptr;
+
+ pLine = GBREG->m_pData;
+ nStride = GBREG->m_nStride;
+ nStride2 = nStride << 1;
+ nLineBytes = ((GBW + 7) >> 3) - 1;
+ nBitsLeft = GBW - (nLineBytes << 3);
+ FX_DWORD height = GBH & 0x7fffffff;
+ for (FX_DWORD h = 0; h < height; h++) {
+ if (TPGDON) {
+ SLTP = pArithDecoder->DECODE(&gbContext[0x9b25]);
+ LTP = LTP ^ SLTP;
+ }
+ if (LTP == 1) {
+ GBREG->copyLine(h, h - 1);
+ } else {
+ if (h > 1) {
+ pLine1 = pLine - nStride2;
+ pLine2 = pLine - nStride;
+ line1 = (*pLine1++) << 6;
+ line2 = *pLine2++;
+ CONTEXT = ((line1 & 0xf800) | (line2 & 0x07f0));
+ for (cc = 0; cc < nLineBytes; cc++) {
+ line1 = (line1 << 8) | ((*pLine1++) << 6);
+ line2 = (line2 << 8) | (*pLine2++);
+ cVal = 0;
+ for (k = 7; k >= 0; k--) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << k;
+ CONTEXT = (((CONTEXT & 0x7bf7) << 1) | bVal |
+ ((line1 >> k) & 0x0800) | ((line2 >> k) & 0x0010));
+ }
+ pLine[cc] = cVal;
+ }
+ line1 <<= 8;
+ line2 <<= 8;
+ cVal = 0;
+ for (k = 0; k < nBitsLeft; k++) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << (7 - k);
+ CONTEXT =
+ (((CONTEXT & 0x7bf7) << 1) | bVal |
+ ((line1 >> (7 - k)) & 0x0800) | ((line2 >> (7 - k)) & 0x0010));
+ }
+ pLine[nLineBytes] = cVal;
+ } else {
+ pLine2 = pLine - nStride;
+ line2 = (h & 1) ? (*pLine2++) : 0;
+ CONTEXT = (line2 & 0x07f0);
+ for (cc = 0; cc < nLineBytes; cc++) {
+ if (h & 1) {
+ line2 = (line2 << 8) | (*pLine2++);
+ }
+ cVal = 0;
+ for (k = 7; k >= 0; k--) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << k;
+ CONTEXT =
+ (((CONTEXT & 0x7bf7) << 1) | bVal | ((line2 >> k) & 0x0010));
+ }
+ pLine[cc] = cVal;
+ }
+ line2 <<= 8;
+ cVal = 0;
+ for (k = 0; k < nBitsLeft; k++) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << (7 - k);
+ CONTEXT = (((CONTEXT & 0x7bf7) << 1) | bVal |
+ (((line2 >> (7 - k))) & 0x0010));
+ }
+ pLine[nLineBytes] = cVal;
+ }
+ }
+ pLine += nStride;
+ }
+ return GBREG.release();
+}
+
+CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template0_unopt(
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext) {
+ FX_BOOL LTP, SLTP, bVal;
+ FX_DWORD CONTEXT;
+ FX_DWORD line1, line2, line3;
+ LTP = 0;
+ std::unique_ptr<CJBig2_Image> GBREG(new CJBig2_Image(GBW, GBH));
+ GBREG->fill(0);
+ for (FX_DWORD h = 0; h < GBH; h++) {
+ if (TPGDON) {
+ SLTP = pArithDecoder->DECODE(&gbContext[0x9b25]);
+ LTP = LTP ^ SLTP;
+ }
+ if (LTP == 1) {
+ GBREG->copyLine(h, h - 1);
+ } else {
+ line1 = GBREG->getPixel(1, h - 2);
+ line1 |= GBREG->getPixel(0, h - 2) << 1;
+ line2 = GBREG->getPixel(2, h - 1);
+ line2 |= GBREG->getPixel(1, h - 1) << 1;
+ line2 |= GBREG->getPixel(0, h - 1) << 2;
+ line3 = 0;
+ for (FX_DWORD w = 0; w < GBW; w++) {
+ if (USESKIP && SKIP->getPixel(w, h)) {
+ bVal = 0;
+ } else {
+ CONTEXT = line3;
+ CONTEXT |= GBREG->getPixel(w + GBAT[0], h + GBAT[1]) << 4;
+ CONTEXT |= line2 << 5;
+ CONTEXT |= GBREG->getPixel(w + GBAT[2], h + GBAT[3]) << 10;
+ CONTEXT |= GBREG->getPixel(w + GBAT[4], h + GBAT[5]) << 11;
+ CONTEXT |= line1 << 12;
+ CONTEXT |= GBREG->getPixel(w + GBAT[6], h + GBAT[7]) << 15;
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ }
+ if (bVal) {
+ GBREG->setPixel(w, h, bVal);
+ }
+ line1 = ((line1 << 1) | GBREG->getPixel(w + 2, h - 2)) & 0x07;
+ line2 = ((line2 << 1) | GBREG->getPixel(w + 3, h - 1)) & 0x1f;
+ line3 = ((line3 << 1) | bVal) & 0x0f;
+ }
+ }
+ }
+ return GBREG.release();
+}
+
+CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template1_opt3(
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext) {
+ FX_BOOL LTP, SLTP, bVal;
+ FX_DWORD CONTEXT;
+ FX_DWORD line1, line2;
+ uint8_t *pLine, *pLine1, *pLine2, cVal;
+ int32_t nStride, nStride2, k;
+ int32_t nLineBytes, nBitsLeft, cc;
+ LTP = 0;
+ std::unique_ptr<CJBig2_Image> GBREG(new CJBig2_Image(GBW, GBH));
+ if (!GBREG->m_pData)
+ return nullptr;
+
+ pLine = GBREG->m_pData;
+ nStride = GBREG->m_nStride;
+ nStride2 = nStride << 1;
+ nLineBytes = ((GBW + 7) >> 3) - 1;
+ nBitsLeft = GBW - (nLineBytes << 3);
+ for (FX_DWORD h = 0; h < GBH; h++) {
+ if (TPGDON) {
+ SLTP = pArithDecoder->DECODE(&gbContext[0x0795]);
+ LTP = LTP ^ SLTP;
+ }
+ if (LTP == 1) {
+ GBREG->copyLine(h, h - 1);
+ } else {
+ if (h > 1) {
+ pLine1 = pLine - nStride2;
+ pLine2 = pLine - nStride;
+ line1 = (*pLine1++) << 4;
+ line2 = *pLine2++;
+ CONTEXT = (line1 & 0x1e00) | ((line2 >> 1) & 0x01f8);
+ for (cc = 0; cc < nLineBytes; cc++) {
+ line1 = (line1 << 8) | ((*pLine1++) << 4);
+ line2 = (line2 << 8) | (*pLine2++);
+ cVal = 0;
+ for (k = 7; k >= 0; k--) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << k;
+ CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal |
+ ((line1 >> k) & 0x0200) | ((line2 >> (k + 1)) & 0x0008);
+ }
+ pLine[cc] = cVal;
+ }
+ line1 <<= 8;
+ line2 <<= 8;
+ cVal = 0;
+ for (k = 0; k < nBitsLeft; k++) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << (7 - k);
+ CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal |
+ ((line1 >> (7 - k)) & 0x0200) |
+ ((line2 >> (8 - k)) & 0x0008);
+ }
+ pLine[nLineBytes] = cVal;
+ } else {
+ pLine2 = pLine - nStride;
+ line2 = (h & 1) ? (*pLine2++) : 0;
+ CONTEXT = (line2 >> 1) & 0x01f8;
+ for (cc = 0; cc < nLineBytes; cc++) {
+ if (h & 1) {
+ line2 = (line2 << 8) | (*pLine2++);
+ }
+ cVal = 0;
+ for (k = 7; k >= 0; k--) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << k;
+ CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal |
+ ((line2 >> (k + 1)) & 0x0008);
+ }
+ pLine[cc] = cVal;
+ }
+ line2 <<= 8;
+ cVal = 0;
+ for (k = 0; k < nBitsLeft; k++) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << (7 - k);
+ CONTEXT =
+ ((CONTEXT & 0x0efb) << 1) | bVal | ((line2 >> (8 - k)) & 0x0008);
+ }
+ pLine[nLineBytes] = cVal;
+ }
+ }
+ pLine += nStride;
+ }
+ return GBREG.release();
+}
+
+CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template1_unopt(
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext) {
+ FX_BOOL LTP, SLTP, bVal;
+ FX_DWORD CONTEXT;
+ FX_DWORD line1, line2, line3;
+ LTP = 0;
+ std::unique_ptr<CJBig2_Image> GBREG(new CJBig2_Image(GBW, GBH));
+ GBREG->fill(0);
+ for (FX_DWORD h = 0; h < GBH; h++) {
+ if (TPGDON) {
+ SLTP = pArithDecoder->DECODE(&gbContext[0x0795]);
+ LTP = LTP ^ SLTP;
+ }
+ if (LTP == 1) {
+ GBREG->copyLine(h, h - 1);
+ } else {
+ line1 = GBREG->getPixel(2, h - 2);
+ line1 |= GBREG->getPixel(1, h - 2) << 1;
+ line1 |= GBREG->getPixel(0, h - 2) << 2;
+ line2 = GBREG->getPixel(2, h - 1);
+ line2 |= GBREG->getPixel(1, h - 1) << 1;
+ line2 |= GBREG->getPixel(0, h - 1) << 2;
+ line3 = 0;
+ for (FX_DWORD w = 0; w < GBW; w++) {
+ if (USESKIP && SKIP->getPixel(w, h)) {
+ bVal = 0;
+ } else {
+ CONTEXT = line3;
+ CONTEXT |= GBREG->getPixel(w + GBAT[0], h + GBAT[1]) << 3;
+ CONTEXT |= line2 << 4;
+ CONTEXT |= line1 << 9;
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ }
+ if (bVal) {
+ GBREG->setPixel(w, h, bVal);
+ }
+ line1 = ((line1 << 1) | GBREG->getPixel(w + 3, h - 2)) & 0x0f;
+ line2 = ((line2 << 1) | GBREG->getPixel(w + 3, h - 1)) & 0x1f;
+ line3 = ((line3 << 1) | bVal) & 0x07;
+ }
+ }
+ }
+ return GBREG.release();
+}
+CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template2_opt3(
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext) {
+ FX_BOOL LTP, SLTP, bVal;
+ FX_DWORD CONTEXT;
+ FX_DWORD line1, line2;
+ uint8_t *pLine, *pLine1, *pLine2, cVal;
+ int32_t nStride, nStride2, k;
+ int32_t nLineBytes, nBitsLeft, cc;
+ LTP = 0;
+ std::unique_ptr<CJBig2_Image> GBREG(new CJBig2_Image(GBW, GBH));
+ if (!GBREG->m_pData)
+ return nullptr;
+
+ pLine = GBREG->m_pData;
+ nStride = GBREG->m_nStride;
+ nStride2 = nStride << 1;
+ nLineBytes = ((GBW + 7) >> 3) - 1;
+ nBitsLeft = GBW - (nLineBytes << 3);
+ for (FX_DWORD h = 0; h < GBH; h++) {
+ if (TPGDON) {
+ SLTP = pArithDecoder->DECODE(&gbContext[0x00e5]);
+ LTP = LTP ^ SLTP;
+ }
+ if (LTP == 1) {
+ GBREG->copyLine(h, h - 1);
+ } else {
+ if (h > 1) {
+ pLine1 = pLine - nStride2;
+ pLine2 = pLine - nStride;
+ line1 = (*pLine1++) << 1;
+ line2 = *pLine2++;
+ CONTEXT = (line1 & 0x0380) | ((line2 >> 3) & 0x007c);
+ for (cc = 0; cc < nLineBytes; cc++) {
+ line1 = (line1 << 8) | ((*pLine1++) << 1);
+ line2 = (line2 << 8) | (*pLine2++);
+ cVal = 0;
+ for (k = 7; k >= 0; k--) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << k;
+ CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
+ ((line1 >> k) & 0x0080) | ((line2 >> (k + 3)) & 0x0004);
+ }
+ pLine[cc] = cVal;
+ }
+ line1 <<= 8;
+ line2 <<= 8;
+ cVal = 0;
+ for (k = 0; k < nBitsLeft; k++) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << (7 - k);
+ CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
+ ((line1 >> (7 - k)) & 0x0080) |
+ ((line2 >> (10 - k)) & 0x0004);
+ }
+ pLine[nLineBytes] = cVal;
+ } else {
+ pLine2 = pLine - nStride;
+ line2 = (h & 1) ? (*pLine2++) : 0;
+ CONTEXT = (line2 >> 3) & 0x007c;
+ for (cc = 0; cc < nLineBytes; cc++) {
+ if (h & 1) {
+ line2 = (line2 << 8) | (*pLine2++);
+ }
+ cVal = 0;
+ for (k = 7; k >= 0; k--) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << k;
+ CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
+ ((line2 >> (k + 3)) & 0x0004);
+ }
+ pLine[cc] = cVal;
+ }
+ line2 <<= 8;
+ cVal = 0;
+ for (k = 0; k < nBitsLeft; k++) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << (7 - k);
+ CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
+ (((line2 >> (10 - k))) & 0x0004);
+ }
+ pLine[nLineBytes] = cVal;
+ }
+ }
+ pLine += nStride;
+ }
+ return GBREG.release();
+}
+
+CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template2_unopt(
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext) {
+ FX_BOOL LTP, SLTP, bVal;
+ FX_DWORD CONTEXT;
+ FX_DWORD line1, line2, line3;
+ LTP = 0;
+ std::unique_ptr<CJBig2_Image> GBREG(new CJBig2_Image(GBW, GBH));
+ GBREG->fill(0);
+ for (FX_DWORD h = 0; h < GBH; h++) {
+ if (TPGDON) {
+ SLTP = pArithDecoder->DECODE(&gbContext[0x00e5]);
+ LTP = LTP ^ SLTP;
+ }
+ if (LTP == 1) {
+ GBREG->copyLine(h, h - 1);
+ } else {
+ line1 = GBREG->getPixel(1, h - 2);
+ line1 |= GBREG->getPixel(0, h - 2) << 1;
+ line2 = GBREG->getPixel(1, h - 1);
+ line2 |= GBREG->getPixel(0, h - 1) << 1;
+ line3 = 0;
+ for (FX_DWORD w = 0; w < GBW; w++) {
+ if (USESKIP && SKIP->getPixel(w, h)) {
+ bVal = 0;
+ } else {
+ CONTEXT = line3;
+ CONTEXT |= GBREG->getPixel(w + GBAT[0], h + GBAT[1]) << 2;
+ CONTEXT |= line2 << 3;
+ CONTEXT |= line1 << 7;
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ }
+ if (bVal) {
+ GBREG->setPixel(w, h, bVal);
+ }
+ line1 = ((line1 << 1) | GBREG->getPixel(w + 2, h - 2)) & 0x07;
+ line2 = ((line2 << 1) | GBREG->getPixel(w + 2, h - 1)) & 0x0f;
+ line3 = ((line3 << 1) | bVal) & 0x03;
+ }
+ }
+ }
+ return GBREG.release();
+}
+
+CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template3_opt3(
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext) {
+ FX_BOOL LTP, SLTP, bVal;
+ FX_DWORD CONTEXT;
+ FX_DWORD line1;
+ uint8_t *pLine, *pLine1, cVal;
+ int32_t nStride, k;
+ int32_t nLineBytes, nBitsLeft, cc;
+ LTP = 0;
+ std::unique_ptr<CJBig2_Image> GBREG(new CJBig2_Image(GBW, GBH));
+ if (!GBREG->m_pData)
+ return nullptr;
+
+ pLine = GBREG->m_pData;
+ nStride = GBREG->m_nStride;
+ nLineBytes = ((GBW + 7) >> 3) - 1;
+ nBitsLeft = GBW - (nLineBytes << 3);
+ for (FX_DWORD h = 0; h < GBH; h++) {
+ if (TPGDON) {
+ SLTP = pArithDecoder->DECODE(&gbContext[0x0195]);
+ LTP = LTP ^ SLTP;
+ }
+ if (LTP == 1) {
+ GBREG->copyLine(h, h - 1);
+ } else {
+ if (h > 0) {
+ pLine1 = pLine - nStride;
+ line1 = *pLine1++;
+ CONTEXT = (line1 >> 1) & 0x03f0;
+ for (cc = 0; cc < nLineBytes; cc++) {
+ line1 = (line1 << 8) | (*pLine1++);
+ cVal = 0;
+ for (k = 7; k >= 0; k--) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << k;
+ CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal |
+ ((line1 >> (k + 1)) & 0x0010);
+ }
+ pLine[cc] = cVal;
+ }
+ line1 <<= 8;
+ cVal = 0;
+ for (k = 0; k < nBitsLeft; k++) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << (7 - k);
+ CONTEXT =
+ ((CONTEXT & 0x01f7) << 1) | bVal | ((line1 >> (8 - k)) & 0x0010);
+ }
+ pLine[nLineBytes] = cVal;
+ } else {
+ CONTEXT = 0;
+ for (cc = 0; cc < nLineBytes; cc++) {
+ cVal = 0;
+ for (k = 7; k >= 0; k--) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << k;
+ CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal;
+ }
+ pLine[cc] = cVal;
+ }
+ cVal = 0;
+ for (k = 0; k < nBitsLeft; k++) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << (7 - k);
+ CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal;
+ }
+ pLine[nLineBytes] = cVal;
+ }
+ }
+ pLine += nStride;
+ }
+ return GBREG.release();
+}
+
+CJBig2_Image* CJBig2_GRDProc::decode_Arith_Template3_unopt(
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext) {
+ FX_BOOL LTP, SLTP, bVal;
+ FX_DWORD CONTEXT;
+ FX_DWORD line1, line2;
+ LTP = 0;
+ std::unique_ptr<CJBig2_Image> GBREG(new CJBig2_Image(GBW, GBH));
+ GBREG->fill(0);
+ for (FX_DWORD h = 0; h < GBH; h++) {
+ if (TPGDON) {
+ SLTP = pArithDecoder->DECODE(&gbContext[0x0195]);
+ LTP = LTP ^ SLTP;
+ }
+ if (LTP == 1) {
+ GBREG->copyLine(h, h - 1);
+ } else {
+ line1 = GBREG->getPixel(1, h - 1);
+ line1 |= GBREG->getPixel(0, h - 1) << 1;
+ line2 = 0;
+ for (FX_DWORD w = 0; w < GBW; w++) {
+ if (USESKIP && SKIP->getPixel(w, h)) {
+ bVal = 0;
+ } else {
+ CONTEXT = line2;
+ CONTEXT |= GBREG->getPixel(w + GBAT[0], h + GBAT[1]) << 4;
+ CONTEXT |= line1 << 5;
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ }
+ if (bVal) {
+ GBREG->setPixel(w, h, bVal);
+ }
+ line1 = ((line1 << 1) | GBREG->getPixel(w + 2, h - 1)) & 0x1f;
+ line2 = ((line2 << 1) | bVal) & 0x0f;
+ }
+ }
+ }
+ return GBREG.release();
+}
+
+FXCODEC_STATUS CJBig2_GRDProc::Start_decode_Arith(
+ CJBig2_Image** pImage,
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause) {
+ if (GBW == 0 || GBH == 0) {
+ m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
+ return FXCODEC_STATUS_DECODE_FINISH;
+ }
+ m_ProssiveStatus = FXCODEC_STATUS_DECODE_READY;
+ m_pPause = pPause;
+ if (!*pImage)
+ *pImage = new CJBig2_Image(GBW, GBH);
+ if (!(*pImage)->m_pData) {
+ delete *pImage;
+ *pImage = nullptr;
+ m_ProssiveStatus = FXCODEC_STATUS_ERROR;
+ return FXCODEC_STATUS_ERROR;
+ }
+ m_DecodeType = 1;
+ m_pImage = pImage;
+ (*m_pImage)->fill(0);
+ m_pArithDecoder = pArithDecoder;
+ m_gbContext = gbContext;
+ LTP = 0;
+ m_pLine = nullptr;
+ m_loopIndex = 0;
+ return decode_Arith(pPause);
+}
+
+FXCODEC_STATUS CJBig2_GRDProc::decode_Arith(IFX_Pause* pPause) {
+ int iline = m_loopIndex;
+ CJBig2_Image* pImage = *m_pImage;
+ if (GBTEMPLATE == 0) {
+ if (UseTemplate0Opt3()) {
+ m_ProssiveStatus = decode_Arith_Template0_opt3(pImage, m_pArithDecoder,
+ m_gbContext, pPause);
+ } else {
+ m_ProssiveStatus = decode_Arith_Template0_unopt(pImage, m_pArithDecoder,
+ m_gbContext, pPause);
+ }
+ } else if (GBTEMPLATE == 1) {
+ if (UseTemplate1Opt3()) {
+ m_ProssiveStatus = decode_Arith_Template1_opt3(pImage, m_pArithDecoder,
+ m_gbContext, pPause);
+ } else {
+ m_ProssiveStatus = decode_Arith_Template1_unopt(pImage, m_pArithDecoder,
+ m_gbContext, pPause);
+ }
+ } else if (GBTEMPLATE == 2) {
+ if (UseTemplate23Opt3()) {
+ m_ProssiveStatus = decode_Arith_Template2_opt3(pImage, m_pArithDecoder,
+ m_gbContext, pPause);
+ } else {
+ m_ProssiveStatus = decode_Arith_Template2_unopt(pImage, m_pArithDecoder,
+ m_gbContext, pPause);
+ }
+ } else {
+ if (UseTemplate23Opt3()) {
+ m_ProssiveStatus = decode_Arith_Template3_opt3(pImage, m_pArithDecoder,
+ m_gbContext, pPause);
+ } else {
+ m_ProssiveStatus = decode_Arith_Template3_unopt(pImage, m_pArithDecoder,
+ m_gbContext, pPause);
+ }
+ }
+ m_ReplaceRect.left = 0;
+ m_ReplaceRect.right = pImage->m_nWidth;
+ m_ReplaceRect.top = iline;
+ m_ReplaceRect.bottom = m_loopIndex;
+ if (m_ProssiveStatus == FXCODEC_STATUS_DECODE_FINISH) {
+ m_loopIndex = 0;
+ }
+ return m_ProssiveStatus;
+}
+
+FXCODEC_STATUS CJBig2_GRDProc::Start_decode_MMR(CJBig2_Image** pImage,
+ CJBig2_BitStream* pStream,
+ IFX_Pause* pPause) {
+ int bitpos, i;
+ *pImage = new CJBig2_Image(GBW, GBH);
+ if (!(*pImage)->m_pData) {
+ delete (*pImage);
+ (*pImage) = nullptr;
+ m_ProssiveStatus = FXCODEC_STATUS_ERROR;
+ return m_ProssiveStatus;
+ }
+ bitpos = (int)pStream->getBitPos();
+ FaxG4Decode(pStream->getBuf(), pStream->getLength(), &bitpos,
+ (*pImage)->m_pData, GBW, GBH, (*pImage)->m_nStride);
+ pStream->setBitPos(bitpos);
+ for (i = 0; (FX_DWORD)i < (*pImage)->m_nStride * GBH; i++) {
+ (*pImage)->m_pData[i] = ~(*pImage)->m_pData[i];
+ }
+ m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
+ return m_ProssiveStatus;
+}
+
+FXCODEC_STATUS CJBig2_GRDProc::Continue_decode(IFX_Pause* pPause) {
+ if (m_ProssiveStatus != FXCODEC_STATUS_DECODE_TOBECONTINUE)
+ return m_ProssiveStatus;
+
+ if (m_DecodeType != 1) {
+ m_ProssiveStatus = FXCODEC_STATUS_ERROR;
+ return m_ProssiveStatus;
+ }
+
+ return decode_Arith(pPause);
+}
+
+FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template0_opt3(
+ CJBig2_Image* pImage,
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause) {
+ FX_BOOL SLTP, bVal;
+ FX_DWORD CONTEXT;
+ FX_DWORD line1, line2;
+ uint8_t *pLine1, *pLine2, cVal;
+ int32_t nStride, nStride2, k;
+ int32_t nLineBytes, nBitsLeft, cc;
+ if (!m_pLine) {
+ m_pLine = pImage->m_pData;
+ }
+ nStride = pImage->m_nStride;
+ nStride2 = nStride << 1;
+ nLineBytes = ((GBW + 7) >> 3) - 1;
+ nBitsLeft = GBW - (nLineBytes << 3);
+ FX_DWORD height = GBH & 0x7fffffff;
+ for (; m_loopIndex < height; m_loopIndex++) {
+ if (TPGDON) {
+ SLTP = pArithDecoder->DECODE(&gbContext[0x9b25]);
+ LTP = LTP ^ SLTP;
+ }
+ if (LTP == 1) {
+ pImage->copyLine(m_loopIndex, m_loopIndex - 1);
+ } else {
+ if (m_loopIndex > 1) {
+ pLine1 = m_pLine - nStride2;
+ pLine2 = m_pLine - nStride;
+ line1 = (*pLine1++) << 6;
+ line2 = *pLine2++;
+ CONTEXT = ((line1 & 0xf800) | (line2 & 0x07f0));
+ for (cc = 0; cc < nLineBytes; cc++) {
+ line1 = (line1 << 8) | ((*pLine1++) << 6);
+ line2 = (line2 << 8) | (*pLine2++);
+ cVal = 0;
+ for (k = 7; k >= 0; k--) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << k;
+ CONTEXT = (((CONTEXT & 0x7bf7) << 1) | bVal |
+ ((line1 >> k) & 0x0800) | ((line2 >> k) & 0x0010));
+ }
+ m_pLine[cc] = cVal;
+ }
+ line1 <<= 8;
+ line2 <<= 8;
+ cVal = 0;
+ for (k = 0; k < nBitsLeft; k++) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << (7 - k);
+ CONTEXT =
+ (((CONTEXT & 0x7bf7) << 1) | bVal |
+ ((line1 >> (7 - k)) & 0x0800) | ((line2 >> (7 - k)) & 0x0010));
+ }
+ m_pLine[nLineBytes] = cVal;
+ } else {
+ pLine2 = m_pLine - nStride;
+ line2 = (m_loopIndex & 1) ? (*pLine2++) : 0;
+ CONTEXT = (line2 & 0x07f0);
+ for (cc = 0; cc < nLineBytes; cc++) {
+ if (m_loopIndex & 1) {
+ line2 = (line2 << 8) | (*pLine2++);
+ }
+ cVal = 0;
+ for (k = 7; k >= 0; k--) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << k;
+ CONTEXT =
+ (((CONTEXT & 0x7bf7) << 1) | bVal | ((line2 >> k) & 0x0010));
+ }
+ m_pLine[cc] = cVal;
+ }
+ line2 <<= 8;
+ cVal = 0;
+ for (k = 0; k < nBitsLeft; k++) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << (7 - k);
+ CONTEXT = (((CONTEXT & 0x7bf7) << 1) | bVal |
+ ((line2 >> (7 - k)) & 0x0010));
+ }
+ m_pLine[nLineBytes] = cVal;
+ }
+ }
+ m_pLine += nStride;
+ if (pPause && pPause->NeedToPauseNow()) {
+ m_loopIndex++;
+ m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
+ return FXCODEC_STATUS_DECODE_TOBECONTINUE;
+ }
+ }
+ m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
+ return FXCODEC_STATUS_DECODE_FINISH;
+}
+
+FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template0_unopt(
+ CJBig2_Image* pImage,
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause) {
+ FX_BOOL SLTP, bVal;
+ FX_DWORD CONTEXT;
+ FX_DWORD line1, line2, line3;
+ for (; m_loopIndex < GBH; m_loopIndex++) {
+ if (TPGDON) {
+ SLTP = pArithDecoder->DECODE(&gbContext[0x9b25]);
+ LTP = LTP ^ SLTP;
+ }
+ if (LTP == 1) {
+ pImage->copyLine(m_loopIndex, m_loopIndex - 1);
+ } else {
+ line1 = pImage->getPixel(1, m_loopIndex - 2);
+ line1 |= pImage->getPixel(0, m_loopIndex - 2) << 1;
+ line2 = pImage->getPixel(2, m_loopIndex - 1);
+ line2 |= pImage->getPixel(1, m_loopIndex - 1) << 1;
+ line2 |= pImage->getPixel(0, m_loopIndex - 1) << 2;
+ line3 = 0;
+ for (FX_DWORD w = 0; w < GBW; w++) {
+ if (USESKIP && SKIP->getPixel(w, m_loopIndex)) {
+ bVal = 0;
+ } else {
+ CONTEXT = line3;
+ CONTEXT |= pImage->getPixel(w + GBAT[0], m_loopIndex + GBAT[1]) << 4;
+ CONTEXT |= line2 << 5;
+ CONTEXT |= pImage->getPixel(w + GBAT[2], m_loopIndex + GBAT[3]) << 10;
+ CONTEXT |= pImage->getPixel(w + GBAT[4], m_loopIndex + GBAT[5]) << 11;
+ CONTEXT |= line1 << 12;
+ CONTEXT |= pImage->getPixel(w + GBAT[6], m_loopIndex + GBAT[7]) << 15;
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ }
+ if (bVal) {
+ pImage->setPixel(w, m_loopIndex, bVal);
+ }
+ line1 =
+ ((line1 << 1) | pImage->getPixel(w + 2, m_loopIndex - 2)) & 0x07;
+ line2 =
+ ((line2 << 1) | pImage->getPixel(w + 3, m_loopIndex - 1)) & 0x1f;
+ line3 = ((line3 << 1) | bVal) & 0x0f;
+ }
+ }
+ if (pPause && pPause->NeedToPauseNow()) {
+ m_loopIndex++;
+ m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
+ return FXCODEC_STATUS_DECODE_TOBECONTINUE;
+ }
+ }
+ m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
+ return FXCODEC_STATUS_DECODE_FINISH;
+}
+
+FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template1_opt3(
+ CJBig2_Image* pImage,
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause) {
+ FX_BOOL SLTP, bVal;
+ FX_DWORD CONTEXT;
+ FX_DWORD line1, line2;
+ uint8_t *pLine1, *pLine2, cVal;
+ int32_t nStride, nStride2, k;
+ int32_t nLineBytes, nBitsLeft, cc;
+ if (!m_pLine) {
+ m_pLine = pImage->m_pData;
+ }
+ nStride = pImage->m_nStride;
+ nStride2 = nStride << 1;
+ nLineBytes = ((GBW + 7) >> 3) - 1;
+ nBitsLeft = GBW - (nLineBytes << 3);
+ for (; m_loopIndex < GBH; m_loopIndex++) {
+ if (TPGDON) {
+ SLTP = pArithDecoder->DECODE(&gbContext[0x0795]);
+ LTP = LTP ^ SLTP;
+ }
+ if (LTP == 1) {
+ pImage->copyLine(m_loopIndex, m_loopIndex - 1);
+ } else {
+ if (m_loopIndex > 1) {
+ pLine1 = m_pLine - nStride2;
+ pLine2 = m_pLine - nStride;
+ line1 = (*pLine1++) << 4;
+ line2 = *pLine2++;
+ CONTEXT = (line1 & 0x1e00) | ((line2 >> 1) & 0x01f8);
+ for (cc = 0; cc < nLineBytes; cc++) {
+ line1 = (line1 << 8) | ((*pLine1++) << 4);
+ line2 = (line2 << 8) | (*pLine2++);
+ cVal = 0;
+ for (k = 7; k >= 0; k--) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << k;
+ CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal |
+ ((line1 >> k) & 0x0200) | ((line2 >> (k + 1)) & 0x0008);
+ }
+ m_pLine[cc] = cVal;
+ }
+ line1 <<= 8;
+ line2 <<= 8;
+ cVal = 0;
+ for (k = 0; k < nBitsLeft; k++) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << (7 - k);
+ CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal |
+ ((line1 >> (7 - k)) & 0x0200) |
+ ((line2 >> (8 - k)) & 0x0008);
+ }
+ m_pLine[nLineBytes] = cVal;
+ } else {
+ pLine2 = m_pLine - nStride;
+ line2 = (m_loopIndex & 1) ? (*pLine2++) : 0;
+ CONTEXT = (line2 >> 1) & 0x01f8;
+ for (cc = 0; cc < nLineBytes; cc++) {
+ if (m_loopIndex & 1) {
+ line2 = (line2 << 8) | (*pLine2++);
+ }
+ cVal = 0;
+ for (k = 7; k >= 0; k--) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << k;
+ CONTEXT = ((CONTEXT & 0x0efb) << 1) | bVal |
+ ((line2 >> (k + 1)) & 0x0008);
+ }
+ m_pLine[cc] = cVal;
+ }
+ line2 <<= 8;
+ cVal = 0;
+ for (k = 0; k < nBitsLeft; k++) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << (7 - k);
+ CONTEXT =
+ ((CONTEXT & 0x0efb) << 1) | bVal | ((line2 >> (8 - k)) & 0x0008);
+ }
+ m_pLine[nLineBytes] = cVal;
+ }
+ }
+ m_pLine += nStride;
+ if (pPause && pPause->NeedToPauseNow()) {
+ m_loopIndex++;
+ m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
+ return FXCODEC_STATUS_DECODE_TOBECONTINUE;
+ }
+ }
+ m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
+ return FXCODEC_STATUS_DECODE_FINISH;
+}
+
+FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template1_unopt(
+ CJBig2_Image* pImage,
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause) {
+ FX_BOOL SLTP, bVal;
+ FX_DWORD CONTEXT;
+ FX_DWORD line1, line2, line3;
+ for (FX_DWORD h = 0; h < GBH; h++) {
+ if (TPGDON) {
+ SLTP = pArithDecoder->DECODE(&gbContext[0x0795]);
+ LTP = LTP ^ SLTP;
+ }
+ if (LTP == 1) {
+ pImage->copyLine(h, h - 1);
+ } else {
+ line1 = pImage->getPixel(2, h - 2);
+ line1 |= pImage->getPixel(1, h - 2) << 1;
+ line1 |= pImage->getPixel(0, h - 2) << 2;
+ line2 = pImage->getPixel(2, h - 1);
+ line2 |= pImage->getPixel(1, h - 1) << 1;
+ line2 |= pImage->getPixel(0, h - 1) << 2;
+ line3 = 0;
+ for (FX_DWORD w = 0; w < GBW; w++) {
+ if (USESKIP && SKIP->getPixel(w, h)) {
+ bVal = 0;
+ } else {
+ CONTEXT = line3;
+ CONTEXT |= pImage->getPixel(w + GBAT[0], h + GBAT[1]) << 3;
+ CONTEXT |= line2 << 4;
+ CONTEXT |= line1 << 9;
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ }
+ if (bVal) {
+ pImage->setPixel(w, h, bVal);
+ }
+ line1 = ((line1 << 1) | pImage->getPixel(w + 3, h - 2)) & 0x0f;
+ line2 = ((line2 << 1) | pImage->getPixel(w + 3, h - 1)) & 0x1f;
+ line3 = ((line3 << 1) | bVal) & 0x07;
+ }
+ }
+ if (pPause && pPause->NeedToPauseNow()) {
+ m_loopIndex++;
+ m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
+ return FXCODEC_STATUS_DECODE_TOBECONTINUE;
+ }
+ }
+ m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
+ return FXCODEC_STATUS_DECODE_FINISH;
+}
+
+FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template2_opt3(
+ CJBig2_Image* pImage,
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause) {
+ FX_BOOL SLTP, bVal;
+ FX_DWORD CONTEXT;
+ FX_DWORD line1, line2;
+ uint8_t *pLine1, *pLine2, cVal;
+ int32_t nStride, nStride2, k;
+ int32_t nLineBytes, nBitsLeft, cc;
+ if (!m_pLine) {
+ m_pLine = pImage->m_pData;
+ }
+ nStride = pImage->m_nStride;
+ nStride2 = nStride << 1;
+ nLineBytes = ((GBW + 7) >> 3) - 1;
+ nBitsLeft = GBW - (nLineBytes << 3);
+ for (; m_loopIndex < GBH; m_loopIndex++) {
+ if (TPGDON) {
+ SLTP = pArithDecoder->DECODE(&gbContext[0x00e5]);
+ LTP = LTP ^ SLTP;
+ }
+ if (LTP == 1) {
+ pImage->copyLine(m_loopIndex, m_loopIndex - 1);
+ } else {
+ if (m_loopIndex > 1) {
+ pLine1 = m_pLine - nStride2;
+ pLine2 = m_pLine - nStride;
+ line1 = (*pLine1++) << 1;
+ line2 = *pLine2++;
+ CONTEXT = (line1 & 0x0380) | ((line2 >> 3) & 0x007c);
+ for (cc = 0; cc < nLineBytes; cc++) {
+ line1 = (line1 << 8) | ((*pLine1++) << 1);
+ line2 = (line2 << 8) | (*pLine2++);
+ cVal = 0;
+ for (k = 7; k >= 0; k--) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << k;
+ CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
+ ((line1 >> k) & 0x0080) | ((line2 >> (k + 3)) & 0x0004);
+ }
+ m_pLine[cc] = cVal;
+ }
+ line1 <<= 8;
+ line2 <<= 8;
+ cVal = 0;
+ for (k = 0; k < nBitsLeft; k++) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << (7 - k);
+ CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
+ ((line1 >> (7 - k)) & 0x0080) |
+ ((line2 >> (10 - k)) & 0x0004);
+ }
+ m_pLine[nLineBytes] = cVal;
+ } else {
+ pLine2 = m_pLine - nStride;
+ line2 = (m_loopIndex & 1) ? (*pLine2++) : 0;
+ CONTEXT = (line2 >> 3) & 0x007c;
+ for (cc = 0; cc < nLineBytes; cc++) {
+ if (m_loopIndex & 1) {
+ line2 = (line2 << 8) | (*pLine2++);
+ }
+ cVal = 0;
+ for (k = 7; k >= 0; k--) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << k;
+ CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
+ ((line2 >> (k + 3)) & 0x0004);
+ }
+ m_pLine[cc] = cVal;
+ }
+ line2 <<= 8;
+ cVal = 0;
+ for (k = 0; k < nBitsLeft; k++) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << (7 - k);
+ CONTEXT = ((CONTEXT & 0x01bd) << 1) | bVal |
+ (((line2 >> (10 - k))) & 0x0004);
+ }
+ m_pLine[nLineBytes] = cVal;
+ }
+ }
+ m_pLine += nStride;
+ if (pPause && m_loopIndex % 50 == 0 && pPause->NeedToPauseNow()) {
+ m_loopIndex++;
+ m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
+ return FXCODEC_STATUS_DECODE_TOBECONTINUE;
+ }
+ }
+ m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
+ return FXCODEC_STATUS_DECODE_FINISH;
+}
+
+FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template2_unopt(
+ CJBig2_Image* pImage,
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause) {
+ FX_BOOL SLTP, bVal;
+ FX_DWORD CONTEXT;
+ FX_DWORD line1, line2, line3;
+ for (; m_loopIndex < GBH; m_loopIndex++) {
+ if (TPGDON) {
+ SLTP = pArithDecoder->DECODE(&gbContext[0x00e5]);
+ LTP = LTP ^ SLTP;
+ }
+ if (LTP == 1) {
+ pImage->copyLine(m_loopIndex, m_loopIndex - 1);
+ } else {
+ line1 = pImage->getPixel(1, m_loopIndex - 2);
+ line1 |= pImage->getPixel(0, m_loopIndex - 2) << 1;
+ line2 = pImage->getPixel(1, m_loopIndex - 1);
+ line2 |= pImage->getPixel(0, m_loopIndex - 1) << 1;
+ line3 = 0;
+ for (FX_DWORD w = 0; w < GBW; w++) {
+ if (USESKIP && SKIP->getPixel(w, m_loopIndex)) {
+ bVal = 0;
+ } else {
+ CONTEXT = line3;
+ CONTEXT |= pImage->getPixel(w + GBAT[0], m_loopIndex + GBAT[1]) << 2;
+ CONTEXT |= line2 << 3;
+ CONTEXT |= line1 << 7;
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ }
+ if (bVal) {
+ pImage->setPixel(w, m_loopIndex, bVal);
+ }
+ line1 =
+ ((line1 << 1) | pImage->getPixel(w + 2, m_loopIndex - 2)) & 0x07;
+ line2 =
+ ((line2 << 1) | pImage->getPixel(w + 2, m_loopIndex - 1)) & 0x0f;
+ line3 = ((line3 << 1) | bVal) & 0x03;
+ }
+ }
+ if (pPause && pPause->NeedToPauseNow()) {
+ m_loopIndex++;
+ m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
+ return FXCODEC_STATUS_DECODE_TOBECONTINUE;
+ }
+ }
+ m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
+ return FXCODEC_STATUS_DECODE_FINISH;
+}
+
+FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template3_opt3(
+ CJBig2_Image* pImage,
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause) {
+ FX_BOOL SLTP, bVal;
+ FX_DWORD CONTEXT;
+ FX_DWORD line1;
+ uint8_t *pLine1, cVal;
+ int32_t nStride, k;
+ int32_t nLineBytes, nBitsLeft, cc;
+ if (!m_pLine) {
+ m_pLine = pImage->m_pData;
+ }
+ nStride = pImage->m_nStride;
+ nLineBytes = ((GBW + 7) >> 3) - 1;
+ nBitsLeft = GBW - (nLineBytes << 3);
+ for (; m_loopIndex < GBH; m_loopIndex++) {
+ if (TPGDON) {
+ SLTP = pArithDecoder->DECODE(&gbContext[0x0195]);
+ LTP = LTP ^ SLTP;
+ }
+ if (LTP == 1) {
+ pImage->copyLine(m_loopIndex, m_loopIndex - 1);
+ } else {
+ if (m_loopIndex > 0) {
+ pLine1 = m_pLine - nStride;
+ line1 = *pLine1++;
+ CONTEXT = (line1 >> 1) & 0x03f0;
+ for (cc = 0; cc < nLineBytes; cc++) {
+ line1 = (line1 << 8) | (*pLine1++);
+ cVal = 0;
+ for (k = 7; k >= 0; k--) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << k;
+ CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal |
+ ((line1 >> (k + 1)) & 0x0010);
+ }
+ m_pLine[cc] = cVal;
+ }
+ line1 <<= 8;
+ cVal = 0;
+ for (k = 0; k < nBitsLeft; k++) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << (7 - k);
+ CONTEXT =
+ ((CONTEXT & 0x01f7) << 1) | bVal | ((line1 >> (8 - k)) & 0x0010);
+ }
+ m_pLine[nLineBytes] = cVal;
+ } else {
+ CONTEXT = 0;
+ for (cc = 0; cc < nLineBytes; cc++) {
+ cVal = 0;
+ for (k = 7; k >= 0; k--) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << k;
+ CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal;
+ }
+ m_pLine[cc] = cVal;
+ }
+ cVal = 0;
+ for (k = 0; k < nBitsLeft; k++) {
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ cVal |= bVal << (7 - k);
+ CONTEXT = ((CONTEXT & 0x01f7) << 1) | bVal;
+ }
+ m_pLine[nLineBytes] = cVal;
+ }
+ }
+ m_pLine += nStride;
+ if (pPause && pPause->NeedToPauseNow()) {
+ m_loopIndex++;
+ m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
+ return FXCODEC_STATUS_DECODE_TOBECONTINUE;
+ }
+ }
+ m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
+ return FXCODEC_STATUS_DECODE_FINISH;
+}
+
+FXCODEC_STATUS CJBig2_GRDProc::decode_Arith_Template3_unopt(
+ CJBig2_Image* pImage,
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause) {
+ FX_BOOL SLTP, bVal;
+ FX_DWORD CONTEXT;
+ FX_DWORD line1, line2;
+ for (; m_loopIndex < GBH; m_loopIndex++) {
+ if (TPGDON) {
+ SLTP = pArithDecoder->DECODE(&gbContext[0x0195]);
+ LTP = LTP ^ SLTP;
+ }
+ if (LTP == 1) {
+ pImage->copyLine(m_loopIndex, m_loopIndex - 1);
+ } else {
+ line1 = pImage->getPixel(1, m_loopIndex - 1);
+ line1 |= pImage->getPixel(0, m_loopIndex - 1) << 1;
+ line2 = 0;
+ for (FX_DWORD w = 0; w < GBW; w++) {
+ if (USESKIP && SKIP->getPixel(w, m_loopIndex)) {
+ bVal = 0;
+ } else {
+ CONTEXT = line2;
+ CONTEXT |= pImage->getPixel(w + GBAT[0], m_loopIndex + GBAT[1]) << 4;
+ CONTEXT |= line1 << 5;
+ bVal = pArithDecoder->DECODE(&gbContext[CONTEXT]);
+ }
+ if (bVal) {
+ pImage->setPixel(w, m_loopIndex, bVal);
+ }
+ line1 =
+ ((line1 << 1) | pImage->getPixel(w + 2, m_loopIndex - 1)) & 0x1f;
+ line2 = ((line2 << 1) | bVal) & 0x0f;
+ }
+ }
+ if (pPause && pPause->NeedToPauseNow()) {
+ m_loopIndex++;
+ m_ProssiveStatus = FXCODEC_STATUS_DECODE_TOBECONTINUE;
+ return FXCODEC_STATUS_DECODE_TOBECONTINUE;
+ }
+ }
+ m_ProssiveStatus = FXCODEC_STATUS_DECODE_FINISH;
+ return FXCODEC_STATUS_DECODE_FINISH;
+}
diff --git a/core/fxcodec/jbig2/JBig2_GrdProc.h b/core/fxcodec/jbig2/JBig2_GrdProc.h
new file mode 100644
index 0000000000..2a181b1822
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_GrdProc.h
@@ -0,0 +1,124 @@
+// Copyright 2015 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_JBIG2_JBIG2_GRDPROC_H_
+#define CORE_FXCODEC_JBIG2_JBIG2_GRDPROC_H_
+
+#include "core/include/fxcodec/fx_codec_def.h"
+#include "core/include/fxcrt/fx_coordinates.h"
+#include "core/include/fxcrt/fx_system.h"
+
+class CJBig2_ArithDecoder;
+class CJBig2_BitStream;
+class CJBig2_Image;
+class IFX_Pause;
+struct JBig2ArithCtx;
+
+class CJBig2_GRDProc {
+ public:
+ CJBig2_GRDProc();
+
+ CJBig2_Image* decode_Arith(CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext);
+
+ FXCODEC_STATUS Start_decode_Arith(CJBig2_Image** pImage,
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause);
+ FXCODEC_STATUS Start_decode_MMR(CJBig2_Image** pImage,
+ CJBig2_BitStream* pStream,
+ IFX_Pause* pPause);
+ FXCODEC_STATUS Continue_decode(IFX_Pause* pPause);
+ FX_RECT GetReplaceRect() const { return m_ReplaceRect; }
+
+ FX_BOOL MMR;
+ FX_DWORD GBW;
+ FX_DWORD GBH;
+ uint8_t GBTEMPLATE;
+ FX_BOOL TPGDON;
+ FX_BOOL USESKIP;
+ CJBig2_Image* SKIP;
+ int8_t GBAT[8];
+
+ private:
+ bool UseTemplate0Opt3() const;
+ bool UseTemplate1Opt3() const;
+ bool UseTemplate23Opt3() const;
+
+ FXCODEC_STATUS decode_Arith(IFX_Pause* pPause);
+ FXCODEC_STATUS decode_Arith_Template0_opt3(CJBig2_Image* pImage,
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause);
+ FXCODEC_STATUS decode_Arith_Template0_unopt(
+ CJBig2_Image* pImage,
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause);
+ FXCODEC_STATUS decode_Arith_Template1_opt3(CJBig2_Image* pImage,
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause);
+ FXCODEC_STATUS decode_Arith_Template1_unopt(
+ CJBig2_Image* pImage,
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause);
+ FXCODEC_STATUS decode_Arith_Template2_opt3(CJBig2_Image* pImage,
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause);
+ FXCODEC_STATUS decode_Arith_Template2_unopt(
+ CJBig2_Image* pImage,
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause);
+ FXCODEC_STATUS decode_Arith_Template3_opt3(CJBig2_Image* pImage,
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause);
+ FXCODEC_STATUS decode_Arith_Template3_unopt(
+ CJBig2_Image* pImage,
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause);
+ CJBig2_Image* decode_Arith_Template0_opt3(CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext);
+
+ CJBig2_Image* decode_Arith_Template0_unopt(CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext);
+
+ CJBig2_Image* decode_Arith_Template1_opt3(CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext);
+
+ CJBig2_Image* decode_Arith_Template1_unopt(CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext);
+
+ CJBig2_Image* decode_Arith_Template2_opt3(CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext);
+
+ CJBig2_Image* decode_Arith_Template2_unopt(CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext);
+
+ CJBig2_Image* decode_Arith_Template3_opt3(CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext);
+
+ CJBig2_Image* decode_Arith_Template3_unopt(CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext);
+
+ FX_DWORD m_loopIndex;
+ uint8_t* m_pLine;
+ IFX_Pause* m_pPause;
+ FXCODEC_STATUS m_ProssiveStatus;
+ CJBig2_Image** m_pImage;
+ CJBig2_ArithDecoder* m_pArithDecoder;
+ JBig2ArithCtx* m_gbContext;
+ FX_WORD m_DecodeType;
+ FX_BOOL LTP;
+ FX_RECT m_ReplaceRect;
+};
+
+#endif // CORE_FXCODEC_JBIG2_JBIG2_GRDPROC_H_
diff --git a/core/fxcodec/jbig2/JBig2_GrrdProc.cpp b/core/fxcodec/jbig2/JBig2_GrrdProc.cpp
new file mode 100644
index 0000000000..c6ff3dd647
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_GrrdProc.cpp
@@ -0,0 +1,516 @@
+// Copyright 2015 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxcodec/jbig2/JBig2_GrrdProc.h"
+
+#include <memory>
+
+#include "core/fxcodec/jbig2/JBig2_ArithDecoder.h"
+#include "core/fxcodec/jbig2/JBig2_BitStream.h"
+#include "core/fxcodec/jbig2/JBig2_Image.h"
+
+CJBig2_Image* CJBig2_GRRDProc::decode(CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* grContext) {
+ if (GRW == 0 || GRH == 0)
+ return new CJBig2_Image(GRW, GRH);
+
+ if (GRTEMPLATE == 0) {
+ if ((GRAT[0] == -1) && (GRAT[1] == -1) && (GRAT[2] == -1) &&
+ (GRAT[3] == -1) && (GRREFERENCEDX == 0) &&
+ (GRW == (FX_DWORD)GRREFERENCE->m_nWidth)) {
+ return decode_Template0_opt(pArithDecoder, grContext);
+ }
+ return decode_Template0_unopt(pArithDecoder, grContext);
+ }
+
+ if ((GRREFERENCEDX == 0) && (GRW == (FX_DWORD)GRREFERENCE->m_nWidth))
+ return decode_Template1_opt(pArithDecoder, grContext);
+ return decode_Template1_unopt(pArithDecoder, grContext);
+}
+
+CJBig2_Image* CJBig2_GRRDProc::decode_Template0_unopt(
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* grContext) {
+ FX_BOOL LTP, SLTP, bVal;
+ FX_DWORD CONTEXT;
+ FX_DWORD line1, line2, line3, line4, line5;
+ LTP = 0;
+ std::unique_ptr<CJBig2_Image> GRREG(new CJBig2_Image(GRW, GRH));
+ GRREG->fill(0);
+ for (FX_DWORD h = 0; h < GRH; h++) {
+ if (TPGRON) {
+ SLTP = pArithDecoder->DECODE(&grContext[0x0010]);
+ LTP = LTP ^ SLTP;
+ }
+ if (LTP == 0) {
+ line1 = GRREG->getPixel(1, h - 1);
+ line1 |= GRREG->getPixel(0, h - 1) << 1;
+ line2 = 0;
+ line3 = GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY - 1);
+ line3 |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY - 1)
+ << 1;
+ line4 = GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY);
+ line4 |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY) << 1;
+ line4 |= GRREFERENCE->getPixel(-GRREFERENCEDX - 1, h - GRREFERENCEDY)
+ << 2;
+ line5 = GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY + 1);
+ line5 |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY + 1)
+ << 1;
+ line5 |= GRREFERENCE->getPixel(-GRREFERENCEDX - 1, h - GRREFERENCEDY + 1)
+ << 2;
+ for (FX_DWORD w = 0; w < GRW; w++) {
+ CONTEXT = line5;
+ CONTEXT |= line4 << 3;
+ CONTEXT |= line3 << 6;
+ CONTEXT |= GRREFERENCE->getPixel(w - GRREFERENCEDX + GRAT[2],
+ h - GRREFERENCEDY + GRAT[3])
+ << 8;
+ CONTEXT |= line2 << 9;
+ CONTEXT |= line1 << 10;
+ CONTEXT |= GRREG->getPixel(w + GRAT[0], h + GRAT[1]) << 12;
+ bVal = pArithDecoder->DECODE(&grContext[CONTEXT]);
+ GRREG->setPixel(w, h, bVal);
+ line1 = ((line1 << 1) | GRREG->getPixel(w + 2, h - 1)) & 0x03;
+ line2 = ((line2 << 1) | bVal) & 0x01;
+ line3 = ((line3 << 1) |
+ GRREFERENCE->getPixel(w - GRREFERENCEDX + 2,
+ h - GRREFERENCEDY - 1)) &
+ 0x03;
+ line4 =
+ ((line4 << 1) |
+ GRREFERENCE->getPixel(w - GRREFERENCEDX + 2, h - GRREFERENCEDY)) &
+ 0x07;
+ line5 = ((line5 << 1) |
+ GRREFERENCE->getPixel(w - GRREFERENCEDX + 2,
+ h - GRREFERENCEDY + 1)) &
+ 0x07;
+ }
+ } else {
+ line1 = GRREG->getPixel(1, h - 1);
+ line1 |= GRREG->getPixel(0, h - 1) << 1;
+ line2 = 0;
+ line3 = GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY - 1);
+ line3 |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY - 1)
+ << 1;
+ line4 = GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY);
+ line4 |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY) << 1;
+ line4 |= GRREFERENCE->getPixel(-GRREFERENCEDX - 1, h - GRREFERENCEDY)
+ << 2;
+ line5 = GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY + 1);
+ line5 |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY + 1)
+ << 1;
+ line5 |= GRREFERENCE->getPixel(-GRREFERENCEDX - 1, h - GRREFERENCEDY + 1)
+ << 2;
+ for (FX_DWORD w = 0; w < GRW; w++) {
+ bVal = GRREFERENCE->getPixel(w, h);
+ if (!(TPGRON && (bVal == GRREFERENCE->getPixel(w - 1, h - 1)) &&
+ (bVal == GRREFERENCE->getPixel(w, h - 1)) &&
+ (bVal == GRREFERENCE->getPixel(w + 1, h - 1)) &&
+ (bVal == GRREFERENCE->getPixel(w - 1, h)) &&
+ (bVal == GRREFERENCE->getPixel(w + 1, h)) &&
+ (bVal == GRREFERENCE->getPixel(w - 1, h + 1)) &&
+ (bVal == GRREFERENCE->getPixel(w, h + 1)) &&
+ (bVal == GRREFERENCE->getPixel(w + 1, h + 1)))) {
+ CONTEXT = line5;
+ CONTEXT |= line4 << 3;
+ CONTEXT |= line3 << 6;
+ CONTEXT |= GRREFERENCE->getPixel(w - GRREFERENCEDX + GRAT[2],
+ h - GRREFERENCEDY + GRAT[3])
+ << 8;
+ CONTEXT |= line2 << 9;
+ CONTEXT |= line1 << 10;
+ CONTEXT |= GRREG->getPixel(w + GRAT[0], h + GRAT[1]) << 12;
+ bVal = pArithDecoder->DECODE(&grContext[CONTEXT]);
+ }
+ GRREG->setPixel(w, h, bVal);
+ line1 = ((line1 << 1) | GRREG->getPixel(w + 2, h - 1)) & 0x03;
+ line2 = ((line2 << 1) | bVal) & 0x01;
+ line3 = ((line3 << 1) |
+ GRREFERENCE->getPixel(w - GRREFERENCEDX + 2,
+ h - GRREFERENCEDY - 1)) &
+ 0x03;
+ line4 =
+ ((line4 << 1) |
+ GRREFERENCE->getPixel(w - GRREFERENCEDX + 2, h - GRREFERENCEDY)) &
+ 0x07;
+ line5 = ((line5 << 1) |
+ GRREFERENCE->getPixel(w - GRREFERENCEDX + 2,
+ h - GRREFERENCEDY + 1)) &
+ 0x07;
+ }
+ }
+ }
+ return GRREG.release();
+}
+
+CJBig2_Image* CJBig2_GRRDProc::decode_Template0_opt(
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* grContext) {
+ if (!GRREFERENCE->m_pData)
+ return nullptr;
+
+ FX_BOOL LTP, SLTP, bVal;
+ FX_DWORD CONTEXT;
+ FX_DWORD line1, line1_r, line2_r, line3_r;
+ uint8_t *pLine, *pLineR, cVal;
+ intptr_t nStride, nStrideR, nOffset;
+ int32_t k, nBits;
+ int32_t GRWR, GRHR;
+ int32_t GRW, GRH;
+ GRW = (int32_t)CJBig2_GRRDProc::GRW;
+ GRH = (int32_t)CJBig2_GRRDProc::GRH;
+ LTP = 0;
+ std::unique_ptr<CJBig2_Image> GRREG(new CJBig2_Image(GRW, GRH));
+ if (!GRREG->m_pData)
+ return nullptr;
+
+ pLine = GRREG->m_pData;
+ pLineR = GRREFERENCE->m_pData;
+ nStride = GRREG->m_nStride;
+ nStrideR = GRREFERENCE->m_nStride;
+ GRWR = (int32_t)GRREFERENCE->m_nWidth;
+ GRHR = (int32_t)GRREFERENCE->m_nHeight;
+ if (GRREFERENCEDY < -GRHR + 1 || GRREFERENCEDY > GRHR - 1) {
+ GRREFERENCEDY = 0;
+ }
+ nOffset = -GRREFERENCEDY * nStrideR;
+ for (int32_t h = 0; h < GRH; h++) {
+ if (TPGRON) {
+ SLTP = pArithDecoder->DECODE(&grContext[0x0010]);
+ LTP = LTP ^ SLTP;
+ }
+ line1 = (h > 0) ? pLine[-nStride] << 4 : 0;
+ int32_t reference_h = h - GRREFERENCEDY;
+ FX_BOOL line1_r_ok = (reference_h > 0 && reference_h < GRHR + 1);
+ FX_BOOL line2_r_ok = (reference_h > -1 && reference_h < GRHR);
+ FX_BOOL line3_r_ok = (reference_h > -2 && reference_h < GRHR - 1);
+ line1_r = line1_r_ok ? pLineR[nOffset - nStrideR] : 0;
+ line2_r = line2_r_ok ? pLineR[nOffset] : 0;
+ line3_r = line3_r_ok ? pLineR[nOffset + nStrideR] : 0;
+ if (LTP == 0) {
+ CONTEXT = (line1 & 0x1c00) | (line1_r & 0x01c0) |
+ ((line2_r >> 3) & 0x0038) | ((line3_r >> 6) & 0x0007);
+ for (int32_t w = 0; w < GRW; w += 8) {
+ nBits = GRW - w > 8 ? 8 : GRW - w;
+ if (h > 0)
+ line1 = (line1 << 8) |
+ (w + 8 < GRW ? pLine[-nStride + (w >> 3) + 1] << 4 : 0);
+ if (h > GRHR + GRREFERENCEDY + 1) {
+ line1_r = 0;
+ line2_r = 0;
+ line3_r = 0;
+ } else {
+ if (line1_r_ok)
+ line1_r =
+ (line1_r << 8) |
+ (w + 8 < GRWR ? pLineR[nOffset - nStrideR + (w >> 3) + 1] : 0);
+ if (line2_r_ok)
+ line2_r = (line2_r << 8) |
+ (w + 8 < GRWR ? pLineR[nOffset + (w >> 3) + 1] : 0);
+ if (line3_r_ok) {
+ line3_r =
+ (line3_r << 8) |
+ (w + 8 < GRWR ? pLineR[nOffset + nStrideR + (w >> 3) + 1] : 0);
+ } else {
+ line3_r = 0;
+ }
+ }
+ cVal = 0;
+ for (k = 0; k < nBits; k++) {
+ bVal = pArithDecoder->DECODE(&grContext[CONTEXT]);
+ cVal |= bVal << (7 - k);
+ CONTEXT = ((CONTEXT & 0x0cdb) << 1) | (bVal << 9) |
+ ((line1 >> (7 - k)) & 0x0400) |
+ ((line1_r >> (7 - k)) & 0x0040) |
+ ((line2_r >> (10 - k)) & 0x0008) |
+ ((line3_r >> (13 - k)) & 0x0001);
+ }
+ pLine[w >> 3] = cVal;
+ }
+ } else {
+ CONTEXT = (line1 & 0x1c00) | (line1_r & 0x01c0) |
+ ((line2_r >> 3) & 0x0038) | ((line3_r >> 6) & 0x0007);
+ for (int32_t w = 0; w < GRW; w += 8) {
+ nBits = GRW - w > 8 ? 8 : GRW - w;
+ if (h > 0)
+ line1 = (line1 << 8) |
+ (w + 8 < GRW ? pLine[-nStride + (w >> 3) + 1] << 4 : 0);
+ if (line1_r_ok)
+ line1_r =
+ (line1_r << 8) |
+ (w + 8 < GRWR ? pLineR[nOffset - nStrideR + (w >> 3) + 1] : 0);
+ if (line2_r_ok)
+ line2_r = (line2_r << 8) |
+ (w + 8 < GRWR ? pLineR[nOffset + (w >> 3) + 1] : 0);
+ if (line3_r_ok) {
+ line3_r =
+ (line3_r << 8) |
+ (w + 8 < GRWR ? pLineR[nOffset + nStrideR + (w >> 3) + 1] : 0);
+ } else {
+ line3_r = 0;
+ }
+ cVal = 0;
+ for (k = 0; k < nBits; k++) {
+ bVal = GRREFERENCE->getPixel(w + k, h);
+ if (!(TPGRON && (bVal == GRREFERENCE->getPixel(w + k - 1, h - 1)) &&
+ (bVal == GRREFERENCE->getPixel(w + k, h - 1)) &&
+ (bVal == GRREFERENCE->getPixel(w + k + 1, h - 1)) &&
+ (bVal == GRREFERENCE->getPixel(w + k - 1, h)) &&
+ (bVal == GRREFERENCE->getPixel(w + k + 1, h)) &&
+ (bVal == GRREFERENCE->getPixel(w + k - 1, h + 1)) &&
+ (bVal == GRREFERENCE->getPixel(w + k, h + 1)) &&
+ (bVal == GRREFERENCE->getPixel(w + k + 1, h + 1)))) {
+ bVal = pArithDecoder->DECODE(&grContext[CONTEXT]);
+ }
+ cVal |= bVal << (7 - k);
+ CONTEXT = ((CONTEXT & 0x0cdb) << 1) | (bVal << 9) |
+ ((line1 >> (7 - k)) & 0x0400) |
+ ((line1_r >> (7 - k)) & 0x0040) |
+ ((line2_r >> (10 - k)) & 0x0008) |
+ ((line3_r >> (13 - k)) & 0x0001);
+ }
+ pLine[w >> 3] = cVal;
+ }
+ }
+ pLine += nStride;
+ if (h < GRHR + GRREFERENCEDY) {
+ pLineR += nStrideR;
+ }
+ }
+ return GRREG.release();
+}
+
+CJBig2_Image* CJBig2_GRRDProc::decode_Template1_unopt(
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* grContext) {
+ FX_BOOL LTP, SLTP, bVal;
+ FX_DWORD CONTEXT;
+ FX_DWORD line1, line2, line3, line4, line5;
+ LTP = 0;
+ std::unique_ptr<CJBig2_Image> GRREG(new CJBig2_Image(GRW, GRH));
+ GRREG->fill(0);
+ for (FX_DWORD h = 0; h < GRH; h++) {
+ if (TPGRON) {
+ SLTP = pArithDecoder->DECODE(&grContext[0x0008]);
+ LTP = LTP ^ SLTP;
+ }
+ if (LTP == 0) {
+ line1 = GRREG->getPixel(1, h - 1);
+ line1 |= GRREG->getPixel(0, h - 1) << 1;
+ line1 |= GRREG->getPixel(-1, h - 1) << 2;
+ line2 = 0;
+ line3 = GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY - 1);
+ line4 = GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY);
+ line4 |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY) << 1;
+ line4 |= GRREFERENCE->getPixel(-GRREFERENCEDX - 1, h - GRREFERENCEDY)
+ << 2;
+ line5 = GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY + 1);
+ line5 |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY + 1)
+ << 1;
+ for (FX_DWORD w = 0; w < GRW; w++) {
+ CONTEXT = line5;
+ CONTEXT |= line4 << 2;
+ CONTEXT |= line3 << 5;
+ CONTEXT |= line2 << 6;
+ CONTEXT |= line1 << 7;
+ bVal = pArithDecoder->DECODE(&grContext[CONTEXT]);
+ GRREG->setPixel(w, h, bVal);
+ line1 = ((line1 << 1) | GRREG->getPixel(w + 2, h - 1)) & 0x07;
+ line2 = ((line2 << 1) | bVal) & 0x01;
+ line3 = ((line3 << 1) |
+ GRREFERENCE->getPixel(w - GRREFERENCEDX + 1,
+ h - GRREFERENCEDY - 1)) &
+ 0x01;
+ line4 =
+ ((line4 << 1) |
+ GRREFERENCE->getPixel(w - GRREFERENCEDX + 2, h - GRREFERENCEDY)) &
+ 0x07;
+ line5 = ((line5 << 1) |
+ GRREFERENCE->getPixel(w - GRREFERENCEDX + 2,
+ h - GRREFERENCEDY + 1)) &
+ 0x03;
+ }
+ } else {
+ line1 = GRREG->getPixel(1, h - 1);
+ line1 |= GRREG->getPixel(0, h - 1) << 1;
+ line1 |= GRREG->getPixel(-1, h - 1) << 2;
+ line2 = 0;
+ line3 = GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY - 1);
+ line4 = GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY);
+ line4 |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY) << 1;
+ line4 |= GRREFERENCE->getPixel(-GRREFERENCEDX - 1, h - GRREFERENCEDY)
+ << 2;
+ line5 = GRREFERENCE->getPixel(-GRREFERENCEDX + 1, h - GRREFERENCEDY + 1);
+ line5 |= GRREFERENCE->getPixel(-GRREFERENCEDX, h - GRREFERENCEDY + 1)
+ << 1;
+ for (FX_DWORD w = 0; w < GRW; w++) {
+ bVal = GRREFERENCE->getPixel(w, h);
+ if (!(TPGRON && (bVal == GRREFERENCE->getPixel(w - 1, h - 1)) &&
+ (bVal == GRREFERENCE->getPixel(w, h - 1)) &&
+ (bVal == GRREFERENCE->getPixel(w + 1, h - 1)) &&
+ (bVal == GRREFERENCE->getPixel(w - 1, h)) &&
+ (bVal == GRREFERENCE->getPixel(w + 1, h)) &&
+ (bVal == GRREFERENCE->getPixel(w - 1, h + 1)) &&
+ (bVal == GRREFERENCE->getPixel(w, h + 1)) &&
+ (bVal == GRREFERENCE->getPixel(w + 1, h + 1)))) {
+ CONTEXT = line5;
+ CONTEXT |= line4 << 2;
+ CONTEXT |= line3 << 5;
+ CONTEXT |= line2 << 6;
+ CONTEXT |= line1 << 7;
+ bVal = pArithDecoder->DECODE(&grContext[CONTEXT]);
+ }
+ GRREG->setPixel(w, h, bVal);
+ line1 = ((line1 << 1) | GRREG->getPixel(w + 2, h - 1)) & 0x07;
+ line2 = ((line2 << 1) | bVal) & 0x01;
+ line3 = ((line3 << 1) |
+ GRREFERENCE->getPixel(w - GRREFERENCEDX + 1,
+ h - GRREFERENCEDY - 1)) &
+ 0x01;
+ line4 =
+ ((line4 << 1) |
+ GRREFERENCE->getPixel(w - GRREFERENCEDX + 2, h - GRREFERENCEDY)) &
+ 0x07;
+ line5 = ((line5 << 1) |
+ GRREFERENCE->getPixel(w - GRREFERENCEDX + 2,
+ h - GRREFERENCEDY + 1)) &
+ 0x03;
+ }
+ }
+ }
+ return GRREG.release();
+}
+
+CJBig2_Image* CJBig2_GRRDProc::decode_Template1_opt(
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* grContext) {
+ if (!GRREFERENCE->m_pData)
+ return nullptr;
+
+ FX_BOOL LTP, SLTP, bVal;
+ FX_DWORD CONTEXT;
+ FX_DWORD line1, line1_r, line2_r, line3_r;
+ uint8_t *pLine, *pLineR, cVal;
+ intptr_t nStride, nStrideR, nOffset;
+ int32_t k, nBits;
+ int32_t GRWR, GRHR;
+ int32_t GRW, GRH;
+ GRW = (int32_t)CJBig2_GRRDProc::GRW;
+ GRH = (int32_t)CJBig2_GRRDProc::GRH;
+ LTP = 0;
+ std::unique_ptr<CJBig2_Image> GRREG(new CJBig2_Image(GRW, GRH));
+ if (!GRREG->m_pData)
+ return nullptr;
+
+ pLine = GRREG->m_pData;
+ pLineR = GRREFERENCE->m_pData;
+ nStride = GRREG->m_nStride;
+ nStrideR = GRREFERENCE->m_nStride;
+ GRWR = (int32_t)GRREFERENCE->m_nWidth;
+ GRHR = (int32_t)GRREFERENCE->m_nHeight;
+ if (GRREFERENCEDY < -GRHR + 1 || GRREFERENCEDY > GRHR - 1) {
+ GRREFERENCEDY = 0;
+ }
+ nOffset = -GRREFERENCEDY * nStrideR;
+ for (int32_t h = 0; h < GRH; h++) {
+ if (TPGRON) {
+ SLTP = pArithDecoder->DECODE(&grContext[0x0008]);
+ LTP = LTP ^ SLTP;
+ }
+ line1 = (h > 0) ? pLine[-nStride] << 1 : 0;
+ int32_t reference_h = h - GRREFERENCEDY;
+ FX_BOOL line1_r_ok = (reference_h > 0 && reference_h < GRHR + 1);
+ FX_BOOL line2_r_ok = (reference_h > -1 && reference_h < GRHR);
+ FX_BOOL line3_r_ok = (reference_h > -2 && reference_h < GRHR - 1);
+ line1_r = line1_r_ok ? pLineR[nOffset - nStrideR] : 0;
+ line2_r = line2_r_ok ? pLineR[nOffset] : 0;
+ line3_r = line3_r_ok ? pLineR[nOffset + nStrideR] : 0;
+ if (LTP == 0) {
+ CONTEXT = (line1 & 0x0380) | ((line1_r >> 2) & 0x0020) |
+ ((line2_r >> 4) & 0x001c) | ((line3_r >> 6) & 0x0003);
+ for (int32_t w = 0; w < GRW; w += 8) {
+ nBits = GRW - w > 8 ? 8 : GRW - w;
+ if (h > 0)
+ line1 = (line1 << 8) |
+ (w + 8 < GRW ? pLine[-nStride + (w >> 3) + 1] << 1 : 0);
+ if (line1_r_ok)
+ line1_r =
+ (line1_r << 8) |
+ (w + 8 < GRWR ? pLineR[nOffset - nStrideR + (w >> 3) + 1] : 0);
+ if (line2_r_ok)
+ line2_r = (line2_r << 8) |
+ (w + 8 < GRWR ? pLineR[nOffset + (w >> 3) + 1] : 0);
+ if (line3_r_ok) {
+ line3_r =
+ (line3_r << 8) |
+ (w + 8 < GRWR ? pLineR[nOffset + nStrideR + (w >> 3) + 1] : 0);
+ } else {
+ line3_r = 0;
+ }
+ cVal = 0;
+ for (k = 0; k < nBits; k++) {
+ bVal = pArithDecoder->DECODE(&grContext[CONTEXT]);
+ cVal |= bVal << (7 - k);
+ CONTEXT = ((CONTEXT & 0x018d) << 1) | (bVal << 6) |
+ ((line1 >> (7 - k)) & 0x0080) |
+ ((line1_r >> (9 - k)) & 0x0020) |
+ ((line2_r >> (11 - k)) & 0x0004) |
+ ((line3_r >> (13 - k)) & 0x0001);
+ }
+ pLine[w >> 3] = cVal;
+ }
+ } else {
+ CONTEXT = (line1 & 0x0380) | ((line1_r >> 2) & 0x0020) |
+ ((line2_r >> 4) & 0x001c) | ((line3_r >> 6) & 0x0003);
+ for (int32_t w = 0; w < GRW; w += 8) {
+ nBits = GRW - w > 8 ? 8 : GRW - w;
+ if (h > 0)
+ line1 = (line1 << 8) |
+ (w + 8 < GRW ? pLine[-nStride + (w >> 3) + 1] << 1 : 0);
+ if (line1_r_ok)
+ line1_r =
+ (line1_r << 8) |
+ (w + 8 < GRWR ? pLineR[nOffset - nStrideR + (w >> 3) + 1] : 0);
+ if (line2_r_ok)
+ line2_r = (line2_r << 8) |
+ (w + 8 < GRWR ? pLineR[nOffset + (w >> 3) + 1] : 0);
+ if (line3_r_ok) {
+ line3_r =
+ (line3_r << 8) |
+ (w + 8 < GRWR ? pLineR[nOffset + nStrideR + (w >> 3) + 1] : 0);
+ } else {
+ line3_r = 0;
+ }
+ cVal = 0;
+ for (k = 0; k < nBits; k++) {
+ bVal = GRREFERENCE->getPixel(w + k, h);
+ if (!(TPGRON && (bVal == GRREFERENCE->getPixel(w + k - 1, h - 1)) &&
+ (bVal == GRREFERENCE->getPixel(w + k, h - 1)) &&
+ (bVal == GRREFERENCE->getPixel(w + k + 1, h - 1)) &&
+ (bVal == GRREFERENCE->getPixel(w + k - 1, h)) &&
+ (bVal == GRREFERENCE->getPixel(w + k + 1, h)) &&
+ (bVal == GRREFERENCE->getPixel(w + k - 1, h + 1)) &&
+ (bVal == GRREFERENCE->getPixel(w + k, h + 1)) &&
+ (bVal == GRREFERENCE->getPixel(w + k + 1, h + 1)))) {
+ bVal = pArithDecoder->DECODE(&grContext[CONTEXT]);
+ }
+ cVal |= bVal << (7 - k);
+ CONTEXT = ((CONTEXT & 0x018d) << 1) | (bVal << 6) |
+ ((line1 >> (7 - k)) & 0x0080) |
+ ((line1_r >> (9 - k)) & 0x0020) |
+ ((line2_r >> (11 - k)) & 0x0004) |
+ ((line3_r >> (13 - k)) & 0x0001);
+ }
+ pLine[w >> 3] = cVal;
+ }
+ }
+ pLine += nStride;
+ if (h < GRHR + GRREFERENCEDY) {
+ pLineR += nStrideR;
+ }
+ }
+ return GRREG.release();
+}
diff --git a/core/fxcodec/jbig2/JBig2_GrrdProc.h b/core/fxcodec/jbig2/JBig2_GrrdProc.h
new file mode 100644
index 0000000000..36cfdcae3c
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_GrrdProc.h
@@ -0,0 +1,43 @@
+// Copyright 2015 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_JBIG2_JBIG2_GRRDPROC_H_
+#define CORE_FXCODEC_JBIG2_JBIG2_GRRDPROC_H_
+
+#include "core/include/fxcrt/fx_system.h"
+
+class CJBig2_ArithDecoder;
+class CJBig2_Image;
+struct JBig2ArithCtx;
+
+class CJBig2_GRRDProc {
+ public:
+ CJBig2_Image* decode(CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* grContext);
+
+ CJBig2_Image* decode_Template0_unopt(CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* grContext);
+
+ CJBig2_Image* decode_Template0_opt(CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* grContext);
+
+ CJBig2_Image* decode_Template1_unopt(CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* grContext);
+
+ CJBig2_Image* decode_Template1_opt(CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* grContext);
+
+ FX_DWORD GRW;
+ FX_DWORD GRH;
+ FX_BOOL GRTEMPLATE;
+ CJBig2_Image* GRREFERENCE;
+ int32_t GRREFERENCEDX;
+ int32_t GRREFERENCEDY;
+ FX_BOOL TPGRON;
+ int8_t GRAT[4];
+};
+
+#endif // CORE_FXCODEC_JBIG2_JBIG2_GRRDPROC_H_
diff --git a/core/fxcodec/jbig2/JBig2_GsidProc.cpp b/core/fxcodec/jbig2/JBig2_GsidProc.cpp
new file mode 100644
index 0000000000..92532d7238
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_GsidProc.cpp
@@ -0,0 +1,123 @@
+// Copyright 2015 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxcodec/jbig2/JBig2_GsidProc.h"
+
+#include <memory>
+
+#include "core/fxcodec/jbig2/JBig2_BitStream.h"
+#include "core/fxcodec/jbig2/JBig2_GrdProc.h"
+#include "core/fxcodec/jbig2/JBig2_Image.h"
+#include "core/fxcodec/jbig2/JBig2_List.h"
+#include "core/include/fxcrt/fx_basic.h"
+
+FX_DWORD* CJBig2_GSIDProc::decode_Arith(CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause) {
+ std::unique_ptr<CJBig2_GRDProc> pGRD(new CJBig2_GRDProc());
+ pGRD->MMR = GSMMR;
+ pGRD->GBW = GSW;
+ pGRD->GBH = GSH;
+ pGRD->GBTEMPLATE = GSTEMPLATE;
+ pGRD->TPGDON = 0;
+ pGRD->USESKIP = GSUSESKIP;
+ pGRD->SKIP = GSKIP;
+ if (GSTEMPLATE <= 1) {
+ pGRD->GBAT[0] = 3;
+ } else {
+ pGRD->GBAT[0] = 2;
+ }
+ pGRD->GBAT[1] = -1;
+ if (pGRD->GBTEMPLATE == 0) {
+ pGRD->GBAT[2] = -3;
+ pGRD->GBAT[3] = -1;
+ pGRD->GBAT[4] = 2;
+ pGRD->GBAT[5] = -2;
+ pGRD->GBAT[6] = -2;
+ pGRD->GBAT[7] = -2;
+ }
+
+ CJBig2_List<CJBig2_Image> GSPLANES(GSBPP);
+ for (int32_t i = GSBPP - 1; i >= 0; --i) {
+ CJBig2_Image* pImage = nullptr;
+ FXCODEC_STATUS status =
+ pGRD->Start_decode_Arith(&pImage, pArithDecoder, gbContext, nullptr);
+ while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE)
+ pGRD->Continue_decode(pPause);
+
+ if (!pImage)
+ return nullptr;
+
+ GSPLANES.set(i, pImage);
+
+ if (i < GSBPP - 1)
+ pImage->composeFrom(0, 0, GSPLANES.get(i + 1), JBIG2_COMPOSE_XOR);
+ }
+ std::unique_ptr<FX_DWORD, FxFreeDeleter> GSVALS(
+ FX_Alloc2D(FX_DWORD, GSW, GSH));
+ JBIG2_memset(GSVALS.get(), 0, sizeof(FX_DWORD) * GSW * GSH);
+ for (FX_DWORD y = 0; y < GSH; ++y) {
+ for (FX_DWORD x = 0; x < GSW; ++x) {
+ for (int32_t i = 0; i < GSBPP; ++i) {
+ GSVALS.get()[y * GSW + x] |= GSPLANES.get(i)->getPixel(x, y) << i;
+ }
+ }
+ }
+ return GSVALS.release();
+}
+
+FX_DWORD* CJBig2_GSIDProc::decode_MMR(CJBig2_BitStream* pStream,
+ IFX_Pause* pPause) {
+ std::unique_ptr<CJBig2_GRDProc> pGRD(new CJBig2_GRDProc());
+ pGRD->MMR = GSMMR;
+ pGRD->GBW = GSW;
+ pGRD->GBH = GSH;
+
+ std::unique_ptr<CJBig2_Image*> GSPLANES(FX_Alloc(CJBig2_Image*, GSBPP));
+ JBIG2_memset(GSPLANES.get(), 0, sizeof(CJBig2_Image*) * GSBPP);
+ FXCODEC_STATUS status =
+ pGRD->Start_decode_MMR(&GSPLANES.get()[GSBPP - 1], pStream, nullptr);
+ while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
+ pGRD->Continue_decode(pPause);
+ }
+ if (!GSPLANES.get()[GSBPP - 1])
+ return nullptr;
+
+ pStream->alignByte();
+ pStream->offset(3);
+ int32_t J = GSBPP - 2;
+ while (J >= 0) {
+ FXCODEC_STATUS status =
+ pGRD->Start_decode_MMR(&GSPLANES.get()[J], pStream, nullptr);
+ while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
+ pGRD->Continue_decode(pPause);
+ }
+ if (!GSPLANES.get()[J]) {
+ for (int32_t K = GSBPP - 1; K > J; --K) {
+ delete GSPLANES.get()[K];
+ return nullptr;
+ }
+ }
+ pStream->alignByte();
+ pStream->offset(3);
+ GSPLANES.get()[J]->composeFrom(0, 0, GSPLANES.get()[J + 1],
+ JBIG2_COMPOSE_XOR);
+ J = J - 1;
+ }
+ std::unique_ptr<FX_DWORD> GSVALS(FX_Alloc2D(FX_DWORD, GSW, GSH));
+ JBIG2_memset(GSVALS.get(), 0, sizeof(FX_DWORD) * GSW * GSH);
+ for (FX_DWORD y = 0; y < GSH; ++y) {
+ for (FX_DWORD x = 0; x < GSW; ++x) {
+ for (J = 0; J < GSBPP; ++J) {
+ GSVALS.get()[y * GSW + x] |= GSPLANES.get()[J]->getPixel(x, y) << J;
+ }
+ }
+ }
+ for (J = 0; J < GSBPP; ++J) {
+ delete GSPLANES.get()[J];
+ }
+ return GSVALS.release();
+}
diff --git a/core/fxcodec/jbig2/JBig2_GsidProc.h b/core/fxcodec/jbig2/JBig2_GsidProc.h
new file mode 100644
index 0000000000..50c24eaa60
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_GsidProc.h
@@ -0,0 +1,36 @@
+// Copyright 2015 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_JBIG2_JBIG2_GSIDPROC_H_
+#define CORE_FXCODEC_JBIG2_JBIG2_GSIDPROC_H_
+
+#include "core/include/fxcrt/fx_system.h"
+
+class CJBig2_ArithDecoder;
+class CJBig2_BitStream;
+class CJBig2_Image;
+class IFX_Pause;
+struct JBig2ArithCtx;
+
+class CJBig2_GSIDProc {
+ public:
+ FX_DWORD* decode_Arith(CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause);
+
+ FX_DWORD* decode_MMR(CJBig2_BitStream* pStream, IFX_Pause* pPause);
+
+ public:
+ FX_BOOL GSMMR;
+ FX_BOOL GSUSESKIP;
+ uint8_t GSBPP;
+ FX_DWORD GSW;
+ FX_DWORD GSH;
+ uint8_t GSTEMPLATE;
+ CJBig2_Image* GSKIP;
+};
+
+#endif // CORE_FXCODEC_JBIG2_JBIG2_GSIDPROC_H_
diff --git a/core/fxcodec/jbig2/JBig2_HtrdProc.cpp b/core/fxcodec/jbig2/JBig2_HtrdProc.cpp
new file mode 100644
index 0000000000..daee067d74
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_HtrdProc.cpp
@@ -0,0 +1,104 @@
+// Copyright 2015 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxcodec/jbig2/JBig2_HtrdProc.h"
+
+#include <memory>
+
+#include "core/fxcodec/jbig2/JBig2_GsidProc.h"
+#include "core/include/fxcrt/fx_basic.h"
+
+CJBig2_Image* CJBig2_HTRDProc::decode_Arith(CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause) {
+ FX_DWORD ng, mg;
+ int32_t x, y;
+ FX_DWORD HBPP;
+ FX_DWORD* GI;
+ std::unique_ptr<CJBig2_Image> HSKIP;
+ std::unique_ptr<CJBig2_Image> HTREG(new CJBig2_Image(HBW, HBH));
+ HTREG->fill(HDEFPIXEL);
+ if (HENABLESKIP == 1) {
+ HSKIP.reset(new CJBig2_Image(HGW, HGH));
+ for (mg = 0; mg < HGH; mg++) {
+ for (ng = 0; ng < HGW; ng++) {
+ x = (HGX + mg * HRY + ng * HRX) >> 8;
+ y = (HGY + mg * HRX - ng * HRY) >> 8;
+ if ((x + HPW <= 0) | (x >= (int32_t)HBW) | (y + HPH <= 0) |
+ (y >= (int32_t)HPH)) {
+ HSKIP->setPixel(ng, mg, 1);
+ } else {
+ HSKIP->setPixel(ng, mg, 0);
+ }
+ }
+ }
+ }
+ HBPP = 1;
+ while ((FX_DWORD)(1 << HBPP) < HNUMPATS) {
+ HBPP++;
+ }
+ std::unique_ptr<CJBig2_GSIDProc> pGID(new CJBig2_GSIDProc());
+ pGID->GSMMR = HMMR;
+ pGID->GSW = HGW;
+ pGID->GSH = HGH;
+ pGID->GSBPP = (uint8_t)HBPP;
+ pGID->GSUSESKIP = HENABLESKIP;
+ pGID->GSKIP = HSKIP.get();
+ pGID->GSTEMPLATE = HTEMPLATE;
+ GI = pGID->decode_Arith(pArithDecoder, gbContext, pPause);
+ if (!GI)
+ return nullptr;
+
+ for (mg = 0; mg < HGH; mg++) {
+ for (ng = 0; ng < HGW; ng++) {
+ x = (HGX + mg * HRY + ng * HRX) >> 8;
+ y = (HGY + mg * HRX - ng * HRY) >> 8;
+ FX_DWORD pat_index = GI[mg * HGW + ng];
+ if (pat_index >= HNUMPATS) {
+ pat_index = HNUMPATS - 1;
+ }
+ HTREG->composeFrom(x, y, HPATS[pat_index], HCOMBOP);
+ }
+ }
+ FX_Free(GI);
+ return HTREG.release();
+}
+
+CJBig2_Image* CJBig2_HTRDProc::decode_MMR(CJBig2_BitStream* pStream,
+ IFX_Pause* pPause) {
+ FX_DWORD ng, mg;
+ int32_t x, y;
+ FX_DWORD* GI;
+ std::unique_ptr<CJBig2_Image> HTREG(new CJBig2_Image(HBW, HBH));
+ HTREG->fill(HDEFPIXEL);
+ FX_DWORD HBPP = 1;
+ while ((FX_DWORD)(1 << HBPP) < HNUMPATS) {
+ HBPP++;
+ }
+ std::unique_ptr<CJBig2_GSIDProc> pGID(new CJBig2_GSIDProc());
+ pGID->GSMMR = HMMR;
+ pGID->GSW = HGW;
+ pGID->GSH = HGH;
+ pGID->GSBPP = (uint8_t)HBPP;
+ pGID->GSUSESKIP = 0;
+ GI = pGID->decode_MMR(pStream, pPause);
+ if (!GI)
+ return nullptr;
+
+ for (mg = 0; mg < HGH; mg++) {
+ for (ng = 0; ng < HGW; ng++) {
+ x = (HGX + mg * HRY + ng * HRX) >> 8;
+ y = (HGY + mg * HRX - ng * HRY) >> 8;
+ FX_DWORD pat_index = GI[mg * HGW + ng];
+ if (pat_index >= HNUMPATS) {
+ pat_index = HNUMPATS - 1;
+ }
+ HTREG->composeFrom(x, y, HPATS[pat_index], HCOMBOP);
+ }
+ }
+ FX_Free(GI);
+ return HTREG.release();
+}
diff --git a/core/fxcodec/jbig2/JBig2_HtrdProc.h b/core/fxcodec/jbig2/JBig2_HtrdProc.h
new file mode 100644
index 0000000000..583145b5ca
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_HtrdProc.h
@@ -0,0 +1,46 @@
+// Copyright 2015 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_JBIG2_JBIG2_HTRDPROC_H_
+#define CORE_FXCODEC_JBIG2_JBIG2_HTRDPROC_H_
+
+#include "core/fxcodec/jbig2/JBig2_Image.h"
+#include "core/include/fxcrt/fx_system.h"
+
+class CJBig2_ArithDecoder;
+class CJBig2_BitStream;
+class IFX_Pause;
+struct JBig2ArithCtx;
+
+class CJBig2_HTRDProc {
+ public:
+ CJBig2_Image* decode_Arith(CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause);
+
+ CJBig2_Image* decode_MMR(CJBig2_BitStream* pStream, IFX_Pause* pPause);
+
+ public:
+ FX_DWORD HBW;
+ FX_DWORD HBH;
+ FX_BOOL HMMR;
+ uint8_t HTEMPLATE;
+ FX_DWORD HNUMPATS;
+ CJBig2_Image** HPATS;
+ FX_BOOL HDEFPIXEL;
+ JBig2ComposeOp HCOMBOP;
+ FX_BOOL HENABLESKIP;
+ FX_DWORD HGW;
+ FX_DWORD HGH;
+ int32_t HGX;
+ int32_t HGY;
+ FX_WORD HRX;
+ FX_WORD HRY;
+ uint8_t HPW;
+ uint8_t HPH;
+};
+
+#endif // CORE_FXCODEC_JBIG2_JBIG2_HTRDPROC_H_
diff --git a/core/fxcodec/jbig2/JBig2_HuffmanDecoder.cpp b/core/fxcodec/jbig2/JBig2_HuffmanDecoder.cpp
new file mode 100644
index 0000000000..afcc17a55e
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_HuffmanDecoder.cpp
@@ -0,0 +1,45 @@
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxcodec/jbig2/JBig2_HuffmanDecoder.h"
+
+#include "core/fxcodec/jbig2/JBig2_Define.h"
+
+CJBig2_HuffmanDecoder::CJBig2_HuffmanDecoder(CJBig2_BitStream* pStream)
+ : m_pStream(pStream) {}
+
+CJBig2_HuffmanDecoder::~CJBig2_HuffmanDecoder() {}
+
+int CJBig2_HuffmanDecoder::decodeAValue(CJBig2_HuffmanTable* pTable,
+ int* nResult) {
+ int nVal = 0;
+ int nBits = 0;
+ while (1) {
+ FX_DWORD nTmp;
+ if (m_pStream->read1Bit(&nTmp) == -1)
+ break;
+
+ nVal = (nVal << 1) | nTmp;
+ ++nBits;
+ for (FX_DWORD i = 0; i < pTable->Size(); ++i) {
+ if (pTable->GetPREFLEN()[i] == nBits && pTable->GetCODES()[i] == nVal) {
+ if (pTable->IsHTOOB() && i == pTable->Size() - 1)
+ return JBIG2_OOB;
+
+ if (m_pStream->readNBits(pTable->GetRANGELEN()[i], &nTmp) == -1)
+ return -1;
+
+ FX_DWORD offset = pTable->IsHTOOB() ? 3 : 2;
+ if (i == pTable->Size() - offset)
+ *nResult = pTable->GetRANGELOW()[i] - nTmp;
+ else
+ *nResult = pTable->GetRANGELOW()[i] + nTmp;
+ return 0;
+ }
+ }
+ }
+ return -1;
+}
diff --git a/core/fxcodec/jbig2/JBig2_HuffmanDecoder.h b/core/fxcodec/jbig2/JBig2_HuffmanDecoder.h
new file mode 100644
index 0000000000..c72346ac18
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_HuffmanDecoder.h
@@ -0,0 +1,24 @@
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_JBIG2_JBIG2_HUFFMANDECODER_H_
+#define CORE_FXCODEC_JBIG2_JBIG2_HUFFMANDECODER_H_
+
+#include "core/fxcodec/jbig2/JBig2_BitStream.h"
+#include "core/fxcodec/jbig2/JBig2_HuffmanTable.h"
+class CJBig2_HuffmanDecoder {
+ public:
+ explicit CJBig2_HuffmanDecoder(CJBig2_BitStream* pStream);
+
+ ~CJBig2_HuffmanDecoder();
+
+ int decodeAValue(CJBig2_HuffmanTable* pTable, int* nResult);
+
+ private:
+ CJBig2_BitStream* const m_pStream;
+};
+
+#endif // CORE_FXCODEC_JBIG2_JBIG2_HUFFMANDECODER_H_
diff --git a/core/fxcodec/jbig2/JBig2_HuffmanTable.cpp b/core/fxcodec/jbig2/JBig2_HuffmanTable.cpp
new file mode 100644
index 0000000000..f4a838eb24
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_HuffmanTable.cpp
@@ -0,0 +1,136 @@
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxcodec/jbig2/JBig2_HuffmanTable.h"
+
+#include <algorithm>
+#include <vector>
+
+#include "core/fxcodec/jbig2/JBig2_BitStream.h"
+#include "core/fxcodec/jbig2/JBig2_Define.h"
+#include "core/fxcodec/jbig2/JBig2_HuffmanTable_Standard.h"
+#include "core/include/fxcrt/fx_memory.h"
+
+CJBig2_HuffmanTable::CJBig2_HuffmanTable(const JBig2TableLine* pTable,
+ FX_DWORD nLines,
+ bool bHTOOB)
+ : m_bOK(true), HTOOB(bHTOOB), NTEMP(nLines) {
+ ParseFromStandardTable(pTable);
+}
+
+CJBig2_HuffmanTable::CJBig2_HuffmanTable(CJBig2_BitStream* pStream)
+ : HTOOB(false), NTEMP(0) {
+ m_bOK = ParseFromCodedBuffer(pStream);
+}
+
+CJBig2_HuffmanTable::~CJBig2_HuffmanTable() {}
+
+void CJBig2_HuffmanTable::ParseFromStandardTable(const JBig2TableLine* pTable) {
+ PREFLEN.resize(NTEMP);
+ RANGELEN.resize(NTEMP);
+ RANGELOW.resize(NTEMP);
+ for (FX_DWORD i = 0; i < NTEMP; ++i) {
+ PREFLEN[i] = pTable[i].PREFLEN;
+ RANGELEN[i] = pTable[i].RANDELEN;
+ RANGELOW[i] = pTable[i].RANGELOW;
+ }
+ InitCodes();
+}
+
+bool CJBig2_HuffmanTable::ParseFromCodedBuffer(CJBig2_BitStream* pStream) {
+ unsigned char cTemp;
+ if (pStream->read1Byte(&cTemp) == -1)
+ return false;
+
+ HTOOB = !!(cTemp & 0x01);
+ unsigned char HTPS = ((cTemp >> 1) & 0x07) + 1;
+ unsigned char HTRS = ((cTemp >> 4) & 0x07) + 1;
+ FX_DWORD HTLOW;
+ FX_DWORD HTHIGH;
+ if (pStream->readInteger(&HTLOW) == -1 ||
+ pStream->readInteger(&HTHIGH) == -1) {
+ return false;
+ }
+
+ const int low = static_cast<int>(HTLOW);
+ const int high = static_cast<int>(HTHIGH);
+ if (low > high)
+ return false;
+
+ ExtendBuffers(false);
+ int cur_low = low;
+ do {
+ if ((pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1) ||
+ (pStream->readNBits(HTRS, &RANGELEN[NTEMP]) == -1)) {
+ return false;
+ }
+ RANGELOW[NTEMP] = cur_low;
+ cur_low += (1 << RANGELEN[NTEMP]);
+ ExtendBuffers(true);
+ } while (cur_low < high);
+
+ if (pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1)
+ return false;
+
+ RANGELEN[NTEMP] = 32;
+ RANGELOW[NTEMP] = low - 1;
+ ExtendBuffers(true);
+
+ if (pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1)
+ return false;
+
+ RANGELEN[NTEMP] = 32;
+ RANGELOW[NTEMP] = high;
+ ExtendBuffers(true);
+
+ if (HTOOB) {
+ if (pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1)
+ return false;
+
+ ++NTEMP;
+ }
+
+ InitCodes();
+ return true;
+}
+
+void CJBig2_HuffmanTable::InitCodes() {
+ int lenmax = 0;
+ for (FX_DWORD i = 0; i < NTEMP; ++i)
+ lenmax = std::max(PREFLEN[i], lenmax);
+
+ CODES.resize(NTEMP);
+ std::vector<int> LENCOUNT(lenmax + 1);
+ std::vector<int> FIRSTCODE(lenmax + 1);
+ for (int len : PREFLEN)
+ ++LENCOUNT[len];
+
+ FIRSTCODE[0] = 0;
+ LENCOUNT[0] = 0;
+ for (int i = 1; i <= lenmax; ++i) {
+ FIRSTCODE[i] = (FIRSTCODE[i - 1] + LENCOUNT[i - 1]) << 1;
+ int CURCODE = FIRSTCODE[i];
+ for (FX_DWORD j = 0; j < NTEMP; ++j) {
+ if (PREFLEN[j] == i)
+ CODES[j] = CURCODE++;
+ }
+ }
+}
+
+void CJBig2_HuffmanTable::ExtendBuffers(bool increment) {
+ if (increment)
+ ++NTEMP;
+
+ size_t size = PREFLEN.size();
+ if (NTEMP < size)
+ return;
+
+ size += 16;
+ ASSERT(NTEMP < size);
+ PREFLEN.resize(size);
+ RANGELEN.resize(size);
+ RANGELOW.resize(size);
+}
diff --git a/core/fxcodec/jbig2/JBig2_HuffmanTable.h b/core/fxcodec/jbig2/JBig2_HuffmanTable.h
new file mode 100644
index 0000000000..892c19e9d6
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_HuffmanTable.h
@@ -0,0 +1,50 @@
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_JBIG2_JBIG2_HUFFMANTABLE_H_
+#define CORE_FXCODEC_JBIG2_JBIG2_HUFFMANTABLE_H_
+
+#include <vector>
+
+#include "core/include/fxcrt/fx_system.h"
+
+class CJBig2_BitStream;
+struct JBig2TableLine;
+
+class CJBig2_HuffmanTable {
+ public:
+ CJBig2_HuffmanTable(const JBig2TableLine* pTable,
+ FX_DWORD nLines,
+ bool bHTOOB);
+
+ explicit CJBig2_HuffmanTable(CJBig2_BitStream* pStream);
+
+ ~CJBig2_HuffmanTable();
+
+ bool IsHTOOB() const { return HTOOB; }
+ FX_DWORD Size() const { return NTEMP; }
+ const std::vector<int>& GetCODES() const { return CODES; }
+ const std::vector<int>& GetPREFLEN() const { return PREFLEN; }
+ const std::vector<int>& GetRANGELEN() const { return RANGELEN; }
+ const std::vector<int>& GetRANGELOW() const { return RANGELOW; }
+ bool IsOK() const { return m_bOK; }
+
+ private:
+ void ParseFromStandardTable(const JBig2TableLine* pTable);
+ bool ParseFromCodedBuffer(CJBig2_BitStream* pStream);
+ void InitCodes();
+ void ExtendBuffers(bool increment);
+
+ bool m_bOK;
+ bool HTOOB;
+ FX_DWORD NTEMP;
+ std::vector<int> CODES;
+ std::vector<int> PREFLEN;
+ std::vector<int> RANGELEN;
+ std::vector<int> RANGELOW;
+};
+
+#endif // CORE_FXCODEC_JBIG2_JBIG2_HUFFMANTABLE_H_
diff --git a/core/fxcodec/jbig2/JBig2_HuffmanTable_Standard.h b/core/fxcodec/jbig2/JBig2_HuffmanTable_Standard.h
new file mode 100644
index 0000000000..0b768654f5
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_HuffmanTable_Standard.h
@@ -0,0 +1,98 @@
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_JBIG2_JBIG2_HUFFMANTABLE_STANDARD_H_
+#define CORE_FXCODEC_JBIG2_JBIG2_HUFFMANTABLE_STANDARD_H_
+
+#include "core/include/fxcrt/fx_system.h"
+
+struct JBig2TableLine {
+ int PREFLEN;
+ int RANDELEN;
+ int RANGELOW;
+};
+
+const bool HuffmanTable_HTOOB_B1 = false;
+const JBig2TableLine HuffmanTable_B1[] = {{1, 4, 0},
+ {2, 8, 16},
+ {3, 16, 272},
+ {0, 32, -1},
+ {3, 32, 65808}};
+const bool HuffmanTable_HTOOB_B2 = true;
+const JBig2TableLine HuffmanTable_B2[] = {{1, 0, 0}, {2, 0, 1}, {3, 0, 2},
+ {4, 3, 3}, {5, 6, 11}, {0, 32, -1},
+ {6, 32, 75}, {6, 0, 0}};
+const bool HuffmanTable_HTOOB_B3 = true;
+const JBig2TableLine HuffmanTable_B3[] = {
+ {8, 8, -256}, {1, 0, 0}, {2, 0, 1}, {3, 0, 2}, {4, 3, 3},
+ {5, 6, 11}, {8, 32, -257}, {7, 32, 75}, {6, 0, 0}};
+const bool HuffmanTable_HTOOB_B4 = false;
+const JBig2TableLine HuffmanTable_B4[] = {
+ {1, 0, 1}, {2, 0, 2}, {3, 0, 3}, {4, 3, 4},
+ {5, 6, 12}, {0, 32, -1}, {5, 32, 76},
+};
+const bool HuffmanTable_HTOOB_B5 = false;
+const JBig2TableLine HuffmanTable_B5[] = {{7, 8, -255}, {1, 0, 1}, {2, 0, 2},
+ {3, 0, 3}, {4, 3, 4}, {5, 6, 12},
+ {7, 32, -256}, {6, 32, 76}};
+const bool HuffmanTable_HTOOB_B6 = false;
+const JBig2TableLine HuffmanTable_B6[] = {
+ {5, 10, -2048}, {4, 9, -1024}, {4, 8, -512}, {4, 7, -256}, {5, 6, -128},
+ {5, 5, -64}, {4, 5, -32}, {2, 7, 0}, {3, 7, 128}, {3, 8, 256},
+ {4, 9, 512}, {4, 10, 1024}, {6, 32, -2049}, {6, 32, 2048}};
+const bool HuffmanTable_HTOOB_B7 = false;
+const JBig2TableLine HuffmanTable_B7[] = {
+ {4, 9, -1024}, {3, 8, -512}, {4, 7, -256}, {5, 6, -128}, {5, 5, -64},
+ {4, 5, -32}, {4, 5, 0}, {5, 5, 32}, {5, 6, 64}, {4, 7, 128},
+ {3, 8, 256}, {3, 9, 512}, {3, 10, 1024}, {5, 32, -1025}, {5, 32, 2048},
+};
+const bool HuffmanTable_HTOOB_B8 = true;
+const JBig2TableLine HuffmanTable_B8[] = {
+ {8, 3, -15}, {9, 1, -7}, {8, 1, -5}, {9, 0, -3}, {7, 0, -2},
+ {4, 0, -1}, {2, 1, 0}, {5, 0, 2}, {6, 0, 3}, {3, 4, 4},
+ {6, 1, 20}, {4, 4, 22}, {4, 5, 38}, {5, 6, 70}, {5, 7, 134},
+ {6, 7, 262}, {7, 8, 390}, {6, 10, 646}, {9, 32, -16}, {9, 32, 1670},
+ {2, 0, 0}};
+const bool HuffmanTable_HTOOB_B9 = true;
+const JBig2TableLine HuffmanTable_B9[] = {
+ {8, 4, -31}, {9, 2, -15}, {8, 2, -11}, {9, 1, -7}, {7, 1, -5},
+ {4, 1, -3}, {3, 1, -1}, {3, 1, 1}, {5, 1, 3}, {6, 1, 5},
+ {3, 5, 7}, {6, 2, 39}, {4, 5, 43}, {4, 6, 75}, {5, 7, 139},
+ {5, 8, 267}, {6, 8, 523}, {7, 9, 779}, {6, 11, 1291}, {9, 32, -32},
+ {9, 32, 3339}, {2, 0, 0}};
+const bool HuffmanTable_HTOOB_B10 = true;
+const JBig2TableLine HuffmanTable_B10[] = {
+ {7, 4, -21}, {8, 0, -5}, {7, 0, -4}, {5, 0, -3}, {2, 2, -2},
+ {5, 0, 2}, {6, 0, 3}, {7, 0, 4}, {8, 0, 5}, {2, 6, 6},
+ {5, 5, 70}, {6, 5, 102}, {6, 6, 134}, {6, 7, 198}, {6, 8, 326},
+ {6, 9, 582}, {6, 10, 1094}, {7, 11, 2118}, {8, 32, -22}, {8, 32, 4166},
+ {2, 0, 0}};
+const bool HuffmanTable_HTOOB_B11 = false;
+const JBig2TableLine HuffmanTable_B11[] = {
+ {1, 0, 1}, {2, 1, 2}, {4, 0, 4}, {4, 1, 5}, {5, 1, 7},
+ {5, 2, 9}, {6, 2, 13}, {7, 2, 17}, {7, 3, 21}, {7, 4, 29},
+ {7, 5, 45}, {7, 6, 77}, {0, 32, 0}, {7, 32, 141}};
+const bool HuffmanTable_HTOOB_B12 = false;
+const JBig2TableLine HuffmanTable_B12[] = {
+ {1, 0, 1}, {2, 0, 2}, {3, 1, 3}, {5, 0, 5}, {5, 1, 6},
+ {6, 1, 8}, {7, 0, 10}, {7, 1, 11}, {7, 2, 13}, {7, 3, 17},
+ {7, 4, 25}, {8, 5, 41}, {0, 32, 0}, {8, 32, 73}};
+const bool HuffmanTable_HTOOB_B13 = false;
+const JBig2TableLine HuffmanTable_B13[] = {
+ {1, 0, 1}, {3, 0, 2}, {4, 0, 3}, {5, 0, 4}, {4, 1, 5},
+ {3, 3, 7}, {6, 1, 15}, {6, 2, 17}, {6, 3, 21}, {6, 4, 29},
+ {6, 5, 45}, {7, 6, 77}, {0, 32, 0}, {7, 32, 141}};
+const bool HuffmanTable_HTOOB_B14 = false;
+const JBig2TableLine HuffmanTable_B14[] = {{3, 0, -2}, {3, 0, -1}, {1, 0, 0},
+ {3, 0, 1}, {3, 0, 2}, {0, 32, -3},
+ {0, 32, 3}};
+const bool HuffmanTable_HTOOB_B15 = false;
+const JBig2TableLine HuffmanTable_B15[] = {
+ {7, 4, -24}, {6, 2, -8}, {5, 1, -4}, {4, 0, -2}, {3, 0, -1},
+ {1, 0, 0}, {3, 0, 1}, {4, 0, 2}, {5, 1, 3}, {6, 2, 5},
+ {7, 4, 9}, {7, 32, -25}, {7, 32, 25}};
+
+#endif // CORE_FXCODEC_JBIG2_JBIG2_HUFFMANTABLE_STANDARD_H_
diff --git a/core/fxcodec/jbig2/JBig2_Image.cpp b/core/fxcodec/jbig2/JBig2_Image.cpp
new file mode 100644
index 0000000000..311c38270e
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_Image.cpp
@@ -0,0 +1,1099 @@
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include <limits.h>
+
+#include "core/fxcodec/jbig2/JBig2_Image.h"
+#include "core/include/fxcrt/fx_coordinates.h"
+#include "core/include/fxcrt/fx_safe_types.h"
+
+CJBig2_Image::CJBig2_Image(int32_t w, int32_t h) {
+ m_nWidth = w;
+ m_nHeight = h;
+ if (m_nWidth <= 0 || m_nHeight <= 0 || m_nWidth > INT_MAX - 31) {
+ m_pData = NULL;
+ m_bNeedFree = FALSE;
+ return;
+ }
+ m_nStride = ((w + 31) >> 5) << 2;
+ if (m_nStride * m_nHeight > 0 && 104857600 / (int)m_nStride > m_nHeight) {
+ m_pData = FX_Alloc2D(uint8_t, m_nStride, m_nHeight);
+ } else {
+ m_pData = NULL;
+ }
+ m_bNeedFree = TRUE;
+}
+CJBig2_Image::CJBig2_Image(int32_t w,
+ int32_t h,
+ int32_t stride,
+ uint8_t* pBuf) {
+ m_nWidth = w;
+ m_nHeight = h;
+ m_nStride = stride;
+ m_pData = pBuf;
+ m_bNeedFree = FALSE;
+}
+CJBig2_Image::CJBig2_Image(const CJBig2_Image& im) {
+ m_nWidth = im.m_nWidth;
+ m_nHeight = im.m_nHeight;
+ m_nStride = im.m_nStride;
+ if (im.m_pData) {
+ m_pData = FX_Alloc2D(uint8_t, m_nStride, m_nHeight);
+ JBIG2_memcpy(m_pData, im.m_pData, m_nStride * m_nHeight);
+ } else {
+ m_pData = NULL;
+ }
+ m_bNeedFree = TRUE;
+}
+CJBig2_Image::~CJBig2_Image() {
+ if (m_bNeedFree) {
+ FX_Free(m_pData);
+ }
+}
+FX_BOOL CJBig2_Image::getPixel(int32_t x, int32_t y) {
+ if (!m_pData) {
+ return 0;
+ }
+ int32_t m, n;
+ if (x < 0 || x >= m_nWidth) {
+ return 0;
+ }
+ if (y < 0 || y >= m_nHeight) {
+ return 0;
+ }
+ m = y * m_nStride + (x >> 3);
+ n = x & 7;
+ return ((m_pData[m] >> (7 - n)) & 1);
+}
+
+int32_t CJBig2_Image::setPixel(int32_t x, int32_t y, FX_BOOL v) {
+ if (!m_pData) {
+ return 0;
+ }
+ int32_t m, n;
+ if (x < 0 || x >= m_nWidth) {
+ return 0;
+ }
+ if (y < 0 || y >= m_nHeight) {
+ return 0;
+ }
+ m = y * m_nStride + (x >> 3);
+ n = x & 7;
+ if (v) {
+ m_pData[m] |= 1 << (7 - n);
+ } else {
+ m_pData[m] &= ~(1 << (7 - n));
+ }
+ return 1;
+}
+void CJBig2_Image::copyLine(int32_t hTo, int32_t hFrom) {
+ if (!m_pData) {
+ return;
+ }
+ if (hFrom < 0 || hFrom >= m_nHeight) {
+ JBIG2_memset(m_pData + hTo * m_nStride, 0, m_nStride);
+ } else {
+ JBIG2_memcpy(m_pData + hTo * m_nStride, m_pData + hFrom * m_nStride,
+ m_nStride);
+ }
+}
+void CJBig2_Image::fill(FX_BOOL v) {
+ if (!m_pData) {
+ return;
+ }
+ JBIG2_memset(m_pData, v ? 0xff : 0, m_nStride * m_nHeight);
+}
+FX_BOOL CJBig2_Image::composeTo(CJBig2_Image* pDst,
+ int32_t x,
+ int32_t y,
+ JBig2ComposeOp op) {
+ if (!m_pData) {
+ return FALSE;
+ }
+ return composeTo_opt2(pDst, x, y, op);
+}
+FX_BOOL CJBig2_Image::composeTo(CJBig2_Image* pDst,
+ int32_t x,
+ int32_t y,
+ JBig2ComposeOp op,
+ const FX_RECT* pSrcRect) {
+ if (!m_pData) {
+ return FALSE;
+ }
+ if (NULL == pSrcRect || *pSrcRect == FX_RECT(0, 0, m_nWidth, m_nHeight)) {
+ return composeTo_opt2(pDst, x, y, op);
+ }
+ return composeTo_opt2(pDst, x, y, op, pSrcRect);
+}
+
+FX_BOOL CJBig2_Image::composeFrom(int32_t x,
+ int32_t y,
+ CJBig2_Image* pSrc,
+ JBig2ComposeOp op) {
+ if (!m_pData) {
+ return FALSE;
+ }
+ return pSrc->composeTo(this, x, y, op);
+}
+FX_BOOL CJBig2_Image::composeFrom(int32_t x,
+ int32_t y,
+ CJBig2_Image* pSrc,
+ JBig2ComposeOp op,
+ const FX_RECT* pSrcRect) {
+ if (!m_pData) {
+ return FALSE;
+ }
+ return pSrc->composeTo(this, x, y, op, pSrcRect);
+}
+#define JBIG2_GETDWORD(buf) \
+ ((FX_DWORD)(((buf)[0] << 24) | ((buf)[1] << 16) | ((buf)[2] << 8) | (buf)[3]))
+CJBig2_Image* CJBig2_Image::subImage(int32_t x,
+ int32_t y,
+ int32_t w,
+ int32_t h) {
+ int32_t m, n, j;
+ uint8_t *pLineSrc, *pLineDst;
+ FX_DWORD wTmp;
+ uint8_t *pSrc, *pSrcEnd, *pDst, *pDstEnd;
+ if (w == 0 || h == 0) {
+ return NULL;
+ }
+ CJBig2_Image* pImage = new CJBig2_Image(w, h);
+ if (!m_pData) {
+ pImage->fill(0);
+ return pImage;
+ }
+ if (!pImage->m_pData) {
+ return pImage;
+ }
+ pLineSrc = m_pData + m_nStride * y;
+ pLineDst = pImage->m_pData;
+ m = (x >> 5) << 2;
+ n = x & 31;
+ if (n == 0) {
+ for (j = 0; j < h; j++) {
+ pSrc = pLineSrc + m;
+ pSrcEnd = pLineSrc + m_nStride;
+ pDst = pLineDst;
+ pDstEnd = pLineDst + pImage->m_nStride;
+ for (; pDst < pDstEnd; pSrc += 4, pDst += 4) {
+ *((FX_DWORD*)pDst) = *((FX_DWORD*)pSrc);
+ }
+ pLineSrc += m_nStride;
+ pLineDst += pImage->m_nStride;
+ }
+ } else {
+ for (j = 0; j < h; j++) {
+ pSrc = pLineSrc + m;
+ pSrcEnd = pLineSrc + m_nStride;
+ pDst = pLineDst;
+ pDstEnd = pLineDst + pImage->m_nStride;
+ for (; pDst < pDstEnd; pSrc += 4, pDst += 4) {
+ if (pSrc + 4 < pSrcEnd) {
+ wTmp = (JBIG2_GETDWORD(pSrc) << n) |
+ (JBIG2_GETDWORD(pSrc + 4) >> (32 - n));
+ } else {
+ wTmp = JBIG2_GETDWORD(pSrc) << n;
+ }
+ pDst[0] = (uint8_t)(wTmp >> 24);
+ pDst[1] = (uint8_t)(wTmp >> 16);
+ pDst[2] = (uint8_t)(wTmp >> 8);
+ pDst[3] = (uint8_t)wTmp;
+ }
+ pLineSrc += m_nStride;
+ pLineDst += pImage->m_nStride;
+ }
+ }
+ return pImage;
+}
+void CJBig2_Image::expand(int32_t h, FX_BOOL v) {
+ if (!m_pData || h <= m_nHeight) {
+ return;
+ }
+ FX_DWORD dwH = pdfium::base::checked_cast<FX_DWORD>(h);
+ FX_DWORD dwStride = pdfium::base::checked_cast<FX_DWORD>(m_nStride);
+ FX_DWORD dwHeight = pdfium::base::checked_cast<FX_DWORD>(m_nHeight);
+ FX_SAFE_DWORD safeMemSize = dwH;
+ safeMemSize *= dwStride;
+ if (!safeMemSize.IsValid()) {
+ return;
+ }
+ // The guaranteed reallocated memory is to be < 4GB (unsigned int).
+ m_pData = FX_Realloc(uint8_t, m_pData, safeMemSize.ValueOrDie());
+
+ // The result of dwHeight * dwStride doesn't overflow after the
+ // checking of safeMemSize.
+ // The same as the result of (dwH - dwHeight) * dwStride) because
+ // dwH - dwHeight is always less than dwH(h) which is checked in
+ // the calculation of dwH * dwStride.
+ JBIG2_memset(m_pData + dwHeight * dwStride, v ? 0xff : 0,
+ (dwH - dwHeight) * dwStride);
+ m_nHeight = h;
+}
+FX_BOOL CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst,
+ int32_t x,
+ int32_t y,
+ JBig2ComposeOp op) {
+ int32_t xs0 = 0, ys0 = 0, xs1 = 0, ys1 = 0, xd0 = 0, yd0 = 0, xd1 = 0,
+ yd1 = 0, xx = 0, yy = 0, w = 0, h = 0, middleDwords = 0, lineLeft = 0;
+
+ FX_DWORD s1 = 0, d1 = 0, d2 = 0, shift = 0, shift1 = 0, shift2 = 0, tmp = 0,
+ tmp1 = 0, tmp2 = 0, maskL = 0, maskR = 0, maskM = 0;
+
+ uint8_t *lineSrc = NULL, *lineDst = NULL, *sp = NULL, *dp = NULL;
+
+ if (!m_pData) {
+ return FALSE;
+ }
+ if (x < -1048576 || x > 1048576 || y < -1048576 || y > 1048576) {
+ return FALSE;
+ }
+ if (y < 0) {
+ ys0 = -y;
+ }
+ if (y + m_nHeight > pDst->m_nHeight) {
+ ys1 = pDst->m_nHeight - y;
+ } else {
+ ys1 = m_nHeight;
+ }
+ if (x < 0) {
+ xs0 = -x;
+ }
+ if (x + m_nWidth > pDst->m_nWidth) {
+ xs1 = pDst->m_nWidth - x;
+ } else {
+ xs1 = m_nWidth;
+ }
+ if ((ys0 >= ys1) || (xs0 >= xs1)) {
+ return 0;
+ }
+ w = xs1 - xs0;
+ h = ys1 - ys0;
+ if (y >= 0) {
+ yd0 = y;
+ }
+ if (x >= 0) {
+ xd0 = x;
+ }
+ xd1 = xd0 + w;
+ yd1 = yd0 + h;
+ d1 = xd0 & 31;
+ d2 = xd1 & 31;
+ s1 = xs0 & 31;
+ maskL = 0xffffffff >> d1;
+ maskR = 0xffffffff << ((32 - (xd1 & 31)) % 32);
+ maskM = maskL & maskR;
+ lineSrc = m_pData + ys0 * m_nStride + ((xs0 >> 5) << 2);
+ lineLeft = m_nStride - ((xs0 >> 5) << 2);
+ lineDst = pDst->m_pData + yd0 * pDst->m_nStride + ((xd0 >> 5) << 2);
+ if ((xd0 & ~31) == ((xd1 - 1) & ~31)) {
+ if ((xs0 & ~31) == ((xs1 - 1) & ~31)) {
+ if (s1 > d1) {
+ shift = s1 - d1;
+ for (yy = yd0; yy < yd1; yy++) {
+ tmp1 = JBIG2_GETDWORD(lineSrc) << shift;
+ tmp2 = JBIG2_GETDWORD(lineDst);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
+ break;
+ }
+ lineDst[0] = (uint8_t)(tmp >> 24);
+ lineDst[1] = (uint8_t)(tmp >> 16);
+ lineDst[2] = (uint8_t)(tmp >> 8);
+ lineDst[3] = (uint8_t)tmp;
+ lineSrc += m_nStride;
+ lineDst += pDst->m_nStride;
+ }
+ } else {
+ shift = d1 - s1;
+ for (yy = yd0; yy < yd1; yy++) {
+ tmp1 = JBIG2_GETDWORD(lineSrc) >> shift;
+ tmp2 = JBIG2_GETDWORD(lineDst);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
+ break;
+ }
+ lineDst[0] = (uint8_t)(tmp >> 24);
+ lineDst[1] = (uint8_t)(tmp >> 16);
+ lineDst[2] = (uint8_t)(tmp >> 8);
+ lineDst[3] = (uint8_t)tmp;
+ lineSrc += m_nStride;
+ lineDst += pDst->m_nStride;
+ }
+ }
+ } else {
+ shift1 = s1 - d1;
+ shift2 = 32 - shift1;
+ for (yy = yd0; yy < yd1; yy++) {
+ tmp1 = (JBIG2_GETDWORD(lineSrc) << shift1) |
+ (JBIG2_GETDWORD(lineSrc + 4) >> shift2);
+ tmp2 = JBIG2_GETDWORD(lineDst);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
+ break;
+ }
+ lineDst[0] = (uint8_t)(tmp >> 24);
+ lineDst[1] = (uint8_t)(tmp >> 16);
+ lineDst[2] = (uint8_t)(tmp >> 8);
+ lineDst[3] = (uint8_t)tmp;
+ lineSrc += m_nStride;
+ lineDst += pDst->m_nStride;
+ }
+ }
+ } else {
+ if (s1 > d1) {
+ shift1 = s1 - d1;
+ shift2 = 32 - shift1;
+ middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
+ for (yy = yd0; yy < yd1; yy++) {
+ sp = lineSrc;
+ dp = lineDst;
+ if (d1 != 0) {
+ tmp1 = (JBIG2_GETDWORD(sp) << shift1) |
+ (JBIG2_GETDWORD(sp + 4) >> shift2);
+ tmp2 = JBIG2_GETDWORD(dp);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
+ break;
+ }
+ dp[0] = (uint8_t)(tmp >> 24);
+ dp[1] = (uint8_t)(tmp >> 16);
+ dp[2] = (uint8_t)(tmp >> 8);
+ dp[3] = (uint8_t)tmp;
+ sp += 4;
+ dp += 4;
+ }
+ for (xx = 0; xx < middleDwords; xx++) {
+ tmp1 = (JBIG2_GETDWORD(sp) << shift1) |
+ (JBIG2_GETDWORD(sp + 4) >> shift2);
+ tmp2 = JBIG2_GETDWORD(dp);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = tmp1 | tmp2;
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = tmp1 & tmp2;
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = tmp1 ^ tmp2;
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = ~(tmp1 ^ tmp2);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = tmp1;
+ break;
+ }
+ dp[0] = (uint8_t)(tmp >> 24);
+ dp[1] = (uint8_t)(tmp >> 16);
+ dp[2] = (uint8_t)(tmp >> 8);
+ dp[3] = (uint8_t)tmp;
+ sp += 4;
+ dp += 4;
+ }
+ if (d2 != 0) {
+ tmp1 =
+ (JBIG2_GETDWORD(sp) << shift1) |
+ (((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >>
+ shift2);
+ tmp2 = JBIG2_GETDWORD(dp);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
+ break;
+ }
+ dp[0] = (uint8_t)(tmp >> 24);
+ dp[1] = (uint8_t)(tmp >> 16);
+ dp[2] = (uint8_t)(tmp >> 8);
+ dp[3] = (uint8_t)tmp;
+ }
+ lineSrc += m_nStride;
+ lineDst += pDst->m_nStride;
+ }
+ } else if (s1 == d1) {
+ middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
+ for (yy = yd0; yy < yd1; yy++) {
+ sp = lineSrc;
+ dp = lineDst;
+ if (d1 != 0) {
+ tmp1 = JBIG2_GETDWORD(sp);
+ tmp2 = JBIG2_GETDWORD(dp);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
+ break;
+ }
+ dp[0] = (uint8_t)(tmp >> 24);
+ dp[1] = (uint8_t)(tmp >> 16);
+ dp[2] = (uint8_t)(tmp >> 8);
+ dp[3] = (uint8_t)tmp;
+ sp += 4;
+ dp += 4;
+ }
+ for (xx = 0; xx < middleDwords; xx++) {
+ tmp1 = JBIG2_GETDWORD(sp);
+ tmp2 = JBIG2_GETDWORD(dp);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = tmp1 | tmp2;
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = tmp1 & tmp2;
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = tmp1 ^ tmp2;
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = ~(tmp1 ^ tmp2);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = tmp1;
+ break;
+ }
+ dp[0] = (uint8_t)(tmp >> 24);
+ dp[1] = (uint8_t)(tmp >> 16);
+ dp[2] = (uint8_t)(tmp >> 8);
+ dp[3] = (uint8_t)tmp;
+ sp += 4;
+ dp += 4;
+ }
+ if (d2 != 0) {
+ tmp1 = JBIG2_GETDWORD(sp);
+ tmp2 = JBIG2_GETDWORD(dp);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
+ break;
+ }
+ dp[0] = (uint8_t)(tmp >> 24);
+ dp[1] = (uint8_t)(tmp >> 16);
+ dp[2] = (uint8_t)(tmp >> 8);
+ dp[3] = (uint8_t)tmp;
+ }
+ lineSrc += m_nStride;
+ lineDst += pDst->m_nStride;
+ }
+ } else {
+ shift1 = d1 - s1;
+ shift2 = 32 - shift1;
+ middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
+ for (yy = yd0; yy < yd1; yy++) {
+ sp = lineSrc;
+ dp = lineDst;
+ if (d1 != 0) {
+ tmp1 = JBIG2_GETDWORD(sp) >> shift1;
+ tmp2 = JBIG2_GETDWORD(dp);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
+ break;
+ }
+ dp[0] = (uint8_t)(tmp >> 24);
+ dp[1] = (uint8_t)(tmp >> 16);
+ dp[2] = (uint8_t)(tmp >> 8);
+ dp[3] = (uint8_t)tmp;
+ dp += 4;
+ }
+ for (xx = 0; xx < middleDwords; xx++) {
+ tmp1 = (JBIG2_GETDWORD(sp) << shift2) |
+ ((JBIG2_GETDWORD(sp + 4)) >> shift1);
+ tmp2 = JBIG2_GETDWORD(dp);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = tmp1 | tmp2;
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = tmp1 & tmp2;
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = tmp1 ^ tmp2;
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = ~(tmp1 ^ tmp2);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = tmp1;
+ break;
+ }
+ dp[0] = (uint8_t)(tmp >> 24);
+ dp[1] = (uint8_t)(tmp >> 16);
+ dp[2] = (uint8_t)(tmp >> 8);
+ dp[3] = (uint8_t)tmp;
+ sp += 4;
+ dp += 4;
+ }
+ if (d2 != 0) {
+ tmp1 =
+ (JBIG2_GETDWORD(sp) << shift2) |
+ (((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >>
+ shift1);
+ tmp2 = JBIG2_GETDWORD(dp);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
+ break;
+ }
+ dp[0] = (uint8_t)(tmp >> 24);
+ dp[1] = (uint8_t)(tmp >> 16);
+ dp[2] = (uint8_t)(tmp >> 8);
+ dp[3] = (uint8_t)tmp;
+ }
+ lineSrc += m_nStride;
+ lineDst += pDst->m_nStride;
+ }
+ }
+ }
+ return 1;
+}
+FX_BOOL CJBig2_Image::composeTo_opt2(CJBig2_Image* pDst,
+ int32_t x,
+ int32_t y,
+ JBig2ComposeOp op,
+ const FX_RECT* pSrcRect) {
+ int32_t xs0, ys0, xs1, ys1, xd0, yd0, xd1, yd1, xx, yy, w, h, middleDwords,
+ lineLeft;
+ FX_DWORD s1, d1, d2, shift, shift1, shift2, tmp, tmp1, tmp2, maskL, maskR,
+ maskM;
+ uint8_t *lineSrc, *lineDst, *sp, *dp;
+ int32_t sw, sh;
+ if (!m_pData) {
+ return FALSE;
+ }
+ if (x < -1048576 || x > 1048576 || y < -1048576 || y > 1048576) {
+ return FALSE;
+ }
+ sw = pSrcRect->Width();
+ sh = pSrcRect->Height();
+ if (y < 0) {
+ ys0 = -y;
+ } else {
+ ys0 = 0;
+ }
+ if (y + sh > pDst->m_nHeight) {
+ ys1 = pDst->m_nHeight - y;
+ } else {
+ ys1 = sh;
+ }
+ if (x < 0) {
+ xs0 = -x;
+ } else {
+ xs0 = 0;
+ }
+ if (x + sw > pDst->m_nWidth) {
+ xs1 = pDst->m_nWidth - x;
+ } else {
+ xs1 = sw;
+ }
+ if ((ys0 >= ys1) || (xs0 >= xs1)) {
+ return 0;
+ }
+ w = xs1 - xs0;
+ h = ys1 - ys0;
+ if (y < 0) {
+ yd0 = 0;
+ } else {
+ yd0 = y;
+ }
+ if (x < 0) {
+ xd0 = 0;
+ } else {
+ xd0 = x;
+ }
+ xd1 = xd0 + w;
+ yd1 = yd0 + h;
+ d1 = xd0 & 31;
+ d2 = xd1 & 31;
+ s1 = xs0 & 31;
+ maskL = 0xffffffff >> d1;
+ maskR = 0xffffffff << ((32 - (xd1 & 31)) % 32);
+ maskM = maskL & maskR;
+ lineSrc = m_pData + (pSrcRect->top + ys0) * m_nStride +
+ (((xs0 + pSrcRect->left) >> 5) << 2);
+ lineLeft = m_nStride - ((xs0 >> 5) << 2);
+ lineDst = pDst->m_pData + yd0 * pDst->m_nStride + ((xd0 >> 5) << 2);
+ if ((xd0 & ~31) == ((xd1 - 1) & ~31)) {
+ if ((xs0 & ~31) == ((xs1 - 1) & ~31)) {
+ if (s1 > d1) {
+ shift = s1 - d1;
+ for (yy = yd0; yy < yd1; yy++) {
+ tmp1 = JBIG2_GETDWORD(lineSrc) << shift;
+ tmp2 = JBIG2_GETDWORD(lineDst);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
+ break;
+ }
+ lineDst[0] = (uint8_t)(tmp >> 24);
+ lineDst[1] = (uint8_t)(tmp >> 16);
+ lineDst[2] = (uint8_t)(tmp >> 8);
+ lineDst[3] = (uint8_t)tmp;
+ lineSrc += m_nStride;
+ lineDst += pDst->m_nStride;
+ }
+ } else {
+ shift = d1 - s1;
+ for (yy = yd0; yy < yd1; yy++) {
+ tmp1 = JBIG2_GETDWORD(lineSrc) >> shift;
+ tmp2 = JBIG2_GETDWORD(lineDst);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
+ break;
+ }
+ lineDst[0] = (uint8_t)(tmp >> 24);
+ lineDst[1] = (uint8_t)(tmp >> 16);
+ lineDst[2] = (uint8_t)(tmp >> 8);
+ lineDst[3] = (uint8_t)tmp;
+ lineSrc += m_nStride;
+ lineDst += pDst->m_nStride;
+ }
+ }
+ } else {
+ shift1 = s1 - d1;
+ shift2 = 32 - shift1;
+ for (yy = yd0; yy < yd1; yy++) {
+ tmp1 = (JBIG2_GETDWORD(lineSrc) << shift1) |
+ (JBIG2_GETDWORD(lineSrc + 4) >> shift2);
+ tmp2 = JBIG2_GETDWORD(lineDst);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = (tmp2 & ~maskM) | ((tmp1 | tmp2) & maskM);
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = (tmp2 & ~maskM) | ((tmp1 & tmp2) & maskM);
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = (tmp2 & ~maskM) | ((tmp1 ^ tmp2) & maskM);
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = (tmp2 & ~maskM) | ((~(tmp1 ^ tmp2)) & maskM);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = (tmp2 & ~maskM) | (tmp1 & maskM);
+ break;
+ }
+ lineDst[0] = (uint8_t)(tmp >> 24);
+ lineDst[1] = (uint8_t)(tmp >> 16);
+ lineDst[2] = (uint8_t)(tmp >> 8);
+ lineDst[3] = (uint8_t)tmp;
+ lineSrc += m_nStride;
+ lineDst += pDst->m_nStride;
+ }
+ }
+ } else {
+ if (s1 > d1) {
+ shift1 = s1 - d1;
+ shift2 = 32 - shift1;
+ middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
+ for (yy = yd0; yy < yd1; yy++) {
+ sp = lineSrc;
+ dp = lineDst;
+ if (d1 != 0) {
+ tmp1 = (JBIG2_GETDWORD(sp) << shift1) |
+ (JBIG2_GETDWORD(sp + 4) >> shift2);
+ tmp2 = JBIG2_GETDWORD(dp);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
+ break;
+ }
+ dp[0] = (uint8_t)(tmp >> 24);
+ dp[1] = (uint8_t)(tmp >> 16);
+ dp[2] = (uint8_t)(tmp >> 8);
+ dp[3] = (uint8_t)tmp;
+ sp += 4;
+ dp += 4;
+ }
+ for (xx = 0; xx < middleDwords; xx++) {
+ tmp1 = (JBIG2_GETDWORD(sp) << shift1) |
+ (JBIG2_GETDWORD(sp + 4) >> shift2);
+ tmp2 = JBIG2_GETDWORD(dp);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = tmp1 | tmp2;
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = tmp1 & tmp2;
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = tmp1 ^ tmp2;
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = ~(tmp1 ^ tmp2);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = tmp1;
+ break;
+ }
+ dp[0] = (uint8_t)(tmp >> 24);
+ dp[1] = (uint8_t)(tmp >> 16);
+ dp[2] = (uint8_t)(tmp >> 8);
+ dp[3] = (uint8_t)tmp;
+ sp += 4;
+ dp += 4;
+ }
+ if (d2 != 0) {
+ tmp1 =
+ (JBIG2_GETDWORD(sp) << shift1) |
+ (((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >>
+ shift2);
+ tmp2 = JBIG2_GETDWORD(dp);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
+ break;
+ }
+ dp[0] = (uint8_t)(tmp >> 24);
+ dp[1] = (uint8_t)(tmp >> 16);
+ dp[2] = (uint8_t)(tmp >> 8);
+ dp[3] = (uint8_t)tmp;
+ }
+ lineSrc += m_nStride;
+ lineDst += pDst->m_nStride;
+ }
+ } else if (s1 == d1) {
+ middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
+ for (yy = yd0; yy < yd1; yy++) {
+ sp = lineSrc;
+ dp = lineDst;
+ if (d1 != 0) {
+ tmp1 = JBIG2_GETDWORD(sp);
+ tmp2 = JBIG2_GETDWORD(dp);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
+ break;
+ }
+ dp[0] = (uint8_t)(tmp >> 24);
+ dp[1] = (uint8_t)(tmp >> 16);
+ dp[2] = (uint8_t)(tmp >> 8);
+ dp[3] = (uint8_t)tmp;
+ sp += 4;
+ dp += 4;
+ }
+ for (xx = 0; xx < middleDwords; xx++) {
+ tmp1 = JBIG2_GETDWORD(sp);
+ tmp2 = JBIG2_GETDWORD(dp);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = tmp1 | tmp2;
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = tmp1 & tmp2;
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = tmp1 ^ tmp2;
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = ~(tmp1 ^ tmp2);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = tmp1;
+ break;
+ }
+ dp[0] = (uint8_t)(tmp >> 24);
+ dp[1] = (uint8_t)(tmp >> 16);
+ dp[2] = (uint8_t)(tmp >> 8);
+ dp[3] = (uint8_t)tmp;
+ sp += 4;
+ dp += 4;
+ }
+ if (d2 != 0) {
+ tmp1 = JBIG2_GETDWORD(sp);
+ tmp2 = JBIG2_GETDWORD(dp);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
+ break;
+ }
+ dp[0] = (uint8_t)(tmp >> 24);
+ dp[1] = (uint8_t)(tmp >> 16);
+ dp[2] = (uint8_t)(tmp >> 8);
+ dp[3] = (uint8_t)tmp;
+ }
+ lineSrc += m_nStride;
+ lineDst += pDst->m_nStride;
+ }
+ } else {
+ shift1 = d1 - s1;
+ shift2 = 32 - shift1;
+ middleDwords = (xd1 >> 5) - ((xd0 + 31) >> 5);
+ for (yy = yd0; yy < yd1; yy++) {
+ sp = lineSrc;
+ dp = lineDst;
+ if (d1 != 0) {
+ tmp1 = JBIG2_GETDWORD(sp) >> shift1;
+ tmp2 = JBIG2_GETDWORD(dp);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = (tmp2 & ~maskL) | ((tmp1 | tmp2) & maskL);
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = (tmp2 & ~maskL) | ((tmp1 & tmp2) & maskL);
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = (tmp2 & ~maskL) | ((tmp1 ^ tmp2) & maskL);
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = (tmp2 & ~maskL) | ((~(tmp1 ^ tmp2)) & maskL);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = (tmp2 & ~maskL) | (tmp1 & maskL);
+ break;
+ }
+ dp[0] = (uint8_t)(tmp >> 24);
+ dp[1] = (uint8_t)(tmp >> 16);
+ dp[2] = (uint8_t)(tmp >> 8);
+ dp[3] = (uint8_t)tmp;
+ dp += 4;
+ }
+ for (xx = 0; xx < middleDwords; xx++) {
+ tmp1 = (JBIG2_GETDWORD(sp) << shift2) |
+ ((JBIG2_GETDWORD(sp + 4)) >> shift1);
+ tmp2 = JBIG2_GETDWORD(dp);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = tmp1 | tmp2;
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = tmp1 & tmp2;
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = tmp1 ^ tmp2;
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = ~(tmp1 ^ tmp2);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = tmp1;
+ break;
+ }
+ dp[0] = (uint8_t)(tmp >> 24);
+ dp[1] = (uint8_t)(tmp >> 16);
+ dp[2] = (uint8_t)(tmp >> 8);
+ dp[3] = (uint8_t)tmp;
+ sp += 4;
+ dp += 4;
+ }
+ if (d2 != 0) {
+ tmp1 =
+ (JBIG2_GETDWORD(sp) << shift2) |
+ (((sp + 4) < lineSrc + lineLeft ? JBIG2_GETDWORD(sp + 4) : 0) >>
+ shift1);
+ tmp2 = JBIG2_GETDWORD(dp);
+ switch (op) {
+ case JBIG2_COMPOSE_OR:
+ tmp = (tmp2 & ~maskR) | ((tmp1 | tmp2) & maskR);
+ break;
+ case JBIG2_COMPOSE_AND:
+ tmp = (tmp2 & ~maskR) | ((tmp1 & tmp2) & maskR);
+ break;
+ case JBIG2_COMPOSE_XOR:
+ tmp = (tmp2 & ~maskR) | ((tmp1 ^ tmp2) & maskR);
+ break;
+ case JBIG2_COMPOSE_XNOR:
+ tmp = (tmp2 & ~maskR) | ((~(tmp1 ^ tmp2)) & maskR);
+ break;
+ case JBIG2_COMPOSE_REPLACE:
+ tmp = (tmp2 & ~maskR) | (tmp1 & maskR);
+ break;
+ }
+ dp[0] = (uint8_t)(tmp >> 24);
+ dp[1] = (uint8_t)(tmp >> 16);
+ dp[2] = (uint8_t)(tmp >> 8);
+ dp[3] = (uint8_t)tmp;
+ }
+ lineSrc += m_nStride;
+ lineDst += pDst->m_nStride;
+ }
+ }
+ }
+ return 1;
+}
diff --git a/core/fxcodec/jbig2/JBig2_Image.h b/core/fxcodec/jbig2/JBig2_Image.h
new file mode 100644
index 0000000000..a18a95d596
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_Image.h
@@ -0,0 +1,85 @@
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_JBIG2_JBIG2_IMAGE_H_
+#define CORE_FXCODEC_JBIG2_JBIG2_IMAGE_H_
+
+#include "core/fxcodec/jbig2/JBig2_Define.h"
+
+enum JBig2ComposeOp {
+ JBIG2_COMPOSE_OR = 0,
+ JBIG2_COMPOSE_AND = 1,
+ JBIG2_COMPOSE_XOR = 2,
+ JBIG2_COMPOSE_XNOR = 3,
+ JBIG2_COMPOSE_REPLACE = 4
+};
+
+struct FX_RECT;
+class CJBig2_Image {
+ public:
+ CJBig2_Image(int32_t w, int32_t h);
+
+ CJBig2_Image(int32_t w, int32_t h, int32_t stride, uint8_t* pBuf);
+
+ CJBig2_Image(const CJBig2_Image& im);
+
+ ~CJBig2_Image();
+
+ FX_BOOL getPixel(int32_t x, int32_t y);
+
+ int32_t setPixel(int32_t x, int32_t y, FX_BOOL v);
+
+ void copyLine(int32_t hTo, int32_t hFrom);
+
+ void fill(FX_BOOL v);
+
+ FX_BOOL composeTo(CJBig2_Image* pDst,
+ int32_t x,
+ int32_t y,
+ JBig2ComposeOp op);
+ FX_BOOL composeTo(CJBig2_Image* pDst,
+ int32_t x,
+ int32_t y,
+ JBig2ComposeOp op,
+ const FX_RECT* pSrcRect);
+
+ FX_BOOL composeTo_opt2(CJBig2_Image* pDst,
+ int32_t x,
+ int32_t y,
+ JBig2ComposeOp op);
+ FX_BOOL composeTo_opt2(CJBig2_Image* pDst,
+ int32_t x,
+ int32_t y,
+ JBig2ComposeOp op,
+ const FX_RECT* pSrcRect);
+
+ FX_BOOL composeFrom(int32_t x,
+ int32_t y,
+ CJBig2_Image* pSrc,
+ JBig2ComposeOp op);
+ FX_BOOL composeFrom(int32_t x,
+ int32_t y,
+ CJBig2_Image* pSrc,
+ JBig2ComposeOp op,
+ const FX_RECT* pSrcRect);
+
+ CJBig2_Image* subImage(int32_t x, int32_t y, int32_t w, int32_t h);
+
+ void expand(int32_t h, FX_BOOL v);
+
+ public:
+ int32_t m_nWidth;
+
+ int32_t m_nHeight;
+
+ int32_t m_nStride;
+
+ uint8_t* m_pData;
+
+ FX_BOOL m_bNeedFree;
+};
+
+#endif // CORE_FXCODEC_JBIG2_JBIG2_IMAGE_H_
diff --git a/core/fxcodec/jbig2/JBig2_List.h b/core/fxcodec/jbig2/JBig2_List.h
new file mode 100644
index 0000000000..b021ac3375
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_List.h
@@ -0,0 +1,54 @@
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_JBIG2_JBIG2_LIST_H_
+#define CORE_FXCODEC_JBIG2_JBIG2_LIST_H_
+
+#include <stdlib.h>
+
+#include <vector>
+
+// A poor man's ScopedVector for pointers of TYPE.
+// Owns all the pointers contained within and deletes them on destruction.
+template <class TYPE>
+class CJBig2_List {
+ public:
+ CJBig2_List() {}
+ explicit CJBig2_List(size_t count) { resize(count); }
+
+ ~CJBig2_List() { clear(); }
+
+ TYPE* get(size_t index) const { return m_vector[index]; }
+ TYPE* back() const { return m_vector.back(); }
+ size_t size() const { return m_vector.size(); }
+
+ // Deletes all the pointers contained within.
+ void clear() {
+ for (size_t i = 0; i < m_vector.size(); ++i)
+ delete m_vector[i];
+ m_vector.clear();
+ }
+
+ // Takes ownership of |pItem|.
+ void push_back(TYPE* pItem) { m_vector.push_back(pItem); }
+
+ // Takes ownership of |pItem|.
+ void set(size_t index, TYPE* pItem) {
+ delete m_vector[index];
+ m_vector[index] = pItem;
+ }
+
+ void resize(size_t count) {
+ for (size_t i = count; i < size(); ++i)
+ delete m_vector[i];
+ m_vector.resize(count);
+ }
+
+ private:
+ std::vector<TYPE*> m_vector;
+};
+
+#endif // CORE_FXCODEC_JBIG2_JBIG2_LIST_H_
diff --git a/core/fxcodec/jbig2/JBig2_Page.h b/core/fxcodec/jbig2/JBig2_Page.h
new file mode 100644
index 0000000000..b3e09d8ae0
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_Page.h
@@ -0,0 +1,22 @@
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_JBIG2_JBIG2_PAGE_H_
+#define CORE_FXCODEC_JBIG2_JBIG2_PAGE_H_
+
+#include "core/include/fxcrt/fx_system.h"
+
+struct JBig2PageInfo {
+ FX_DWORD m_dwWidth;
+ FX_DWORD m_dwHeight;
+ FX_DWORD m_dwResolutionX;
+ FX_DWORD m_dwResolutionY;
+ uint8_t m_cFlags;
+ FX_BOOL m_bIsStriped;
+ FX_WORD m_wMaxStripeSize;
+};
+
+#endif // CORE_FXCODEC_JBIG2_JBIG2_PAGE_H_
diff --git a/core/fxcodec/jbig2/JBig2_PatternDict.cpp b/core/fxcodec/jbig2/JBig2_PatternDict.cpp
new file mode 100644
index 0000000000..58157ef13a
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_PatternDict.cpp
@@ -0,0 +1,23 @@
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxcodec/jbig2/JBig2_PatternDict.h"
+
+#include "core/include/fxcrt/fx_memory.h"
+
+CJBig2_PatternDict::CJBig2_PatternDict() {
+ NUMPATS = 0;
+ HDPATS = NULL;
+}
+
+CJBig2_PatternDict::~CJBig2_PatternDict() {
+ if (HDPATS) {
+ for (FX_DWORD i = 0; i < NUMPATS; i++) {
+ delete HDPATS[i];
+ }
+ FX_Free(HDPATS);
+ }
+}
diff --git a/core/fxcodec/jbig2/JBig2_PatternDict.h b/core/fxcodec/jbig2/JBig2_PatternDict.h
new file mode 100644
index 0000000000..3196fcaaf3
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_PatternDict.h
@@ -0,0 +1,23 @@
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_JBIG2_JBIG2_PATTERNDICT_H_
+#define CORE_FXCODEC_JBIG2_JBIG2_PATTERNDICT_H_
+
+#include "core/fxcodec/jbig2/JBig2_Define.h"
+#include "core/fxcodec/jbig2/JBig2_Image.h"
+
+class CJBig2_PatternDict {
+ public:
+ CJBig2_PatternDict();
+
+ ~CJBig2_PatternDict();
+
+ FX_DWORD NUMPATS;
+ CJBig2_Image** HDPATS;
+};
+
+#endif // CORE_FXCODEC_JBIG2_JBIG2_PATTERNDICT_H_
diff --git a/core/fxcodec/jbig2/JBig2_PddProc.cpp b/core/fxcodec/jbig2/JBig2_PddProc.cpp
new file mode 100644
index 0000000000..5b67aadb57
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_PddProc.cpp
@@ -0,0 +1,87 @@
+// Copyright 2015 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxcodec/jbig2/JBig2_PddProc.h"
+
+#include <memory>
+
+#include "core/fxcodec/jbig2/JBig2_GrdProc.h"
+#include "core/fxcodec/jbig2/JBig2_Image.h"
+#include "core/fxcodec/jbig2/JBig2_PatternDict.h"
+
+CJBig2_PatternDict* CJBig2_PDDProc::decode_Arith(
+ CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause) {
+ FX_DWORD GRAY;
+ CJBig2_Image* BHDC = nullptr;
+ std::unique_ptr<CJBig2_PatternDict> pDict(new CJBig2_PatternDict());
+ pDict->NUMPATS = GRAYMAX + 1;
+ pDict->HDPATS = FX_Alloc(CJBig2_Image*, pDict->NUMPATS);
+ JBIG2_memset(pDict->HDPATS, 0, sizeof(CJBig2_Image*) * pDict->NUMPATS);
+
+ std::unique_ptr<CJBig2_GRDProc> pGRD(new CJBig2_GRDProc());
+ pGRD->MMR = HDMMR;
+ pGRD->GBW = (GRAYMAX + 1) * HDPW;
+ pGRD->GBH = HDPH;
+ pGRD->GBTEMPLATE = HDTEMPLATE;
+ pGRD->TPGDON = 0;
+ pGRD->USESKIP = 0;
+ pGRD->GBAT[0] = -(int32_t)HDPW;
+ pGRD->GBAT[1] = 0;
+ if (pGRD->GBTEMPLATE == 0) {
+ pGRD->GBAT[2] = -3;
+ pGRD->GBAT[3] = -1;
+ pGRD->GBAT[4] = 2;
+ pGRD->GBAT[5] = -2;
+ pGRD->GBAT[6] = -2;
+ pGRD->GBAT[7] = -2;
+ }
+ FXCODEC_STATUS status =
+ pGRD->Start_decode_Arith(&BHDC, pArithDecoder, gbContext, nullptr);
+ while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
+ pGRD->Continue_decode(pPause);
+ }
+ if (!BHDC)
+ return nullptr;
+
+ GRAY = 0;
+ while (GRAY <= GRAYMAX) {
+ pDict->HDPATS[GRAY] = BHDC->subImage(HDPW * GRAY, 0, HDPW, HDPH);
+ GRAY = GRAY + 1;
+ }
+ delete BHDC;
+ return pDict.release();
+}
+
+CJBig2_PatternDict* CJBig2_PDDProc::decode_MMR(CJBig2_BitStream* pStream,
+ IFX_Pause* pPause) {
+ FX_DWORD GRAY;
+ CJBig2_Image* BHDC = nullptr;
+ std::unique_ptr<CJBig2_PatternDict> pDict(new CJBig2_PatternDict());
+ pDict->NUMPATS = GRAYMAX + 1;
+ pDict->HDPATS = FX_Alloc(CJBig2_Image*, pDict->NUMPATS);
+ JBIG2_memset(pDict->HDPATS, 0, sizeof(CJBig2_Image*) * pDict->NUMPATS);
+
+ std::unique_ptr<CJBig2_GRDProc> pGRD(new CJBig2_GRDProc());
+ pGRD->MMR = HDMMR;
+ pGRD->GBW = (GRAYMAX + 1) * HDPW;
+ pGRD->GBH = HDPH;
+ FXCODEC_STATUS status = pGRD->Start_decode_MMR(&BHDC, pStream, nullptr);
+ while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
+ pGRD->Continue_decode(pPause);
+ }
+ if (!BHDC)
+ return nullptr;
+
+ GRAY = 0;
+ while (GRAY <= GRAYMAX) {
+ pDict->HDPATS[GRAY] = BHDC->subImage(HDPW * GRAY, 0, HDPW, HDPH);
+ GRAY = GRAY + 1;
+ }
+ delete BHDC;
+ return pDict.release();
+}
diff --git a/core/fxcodec/jbig2/JBig2_PddProc.h b/core/fxcodec/jbig2/JBig2_PddProc.h
new file mode 100644
index 0000000000..25f941235f
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_PddProc.h
@@ -0,0 +1,34 @@
+// Copyright 2015 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_JBIG2_JBIG2_PDDPROC_H_
+#define CORE_FXCODEC_JBIG2_JBIG2_PDDPROC_H_
+
+#include "core/include/fxcrt/fx_system.h"
+
+class CJBig2_ArithDecoder;
+class CJBig2_BitStream;
+class CJBig2_PatternDict;
+class IFX_Pause;
+struct JBig2ArithCtx;
+
+class CJBig2_PDDProc {
+ public:
+ CJBig2_PatternDict* decode_Arith(CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* gbContext,
+ IFX_Pause* pPause);
+
+ CJBig2_PatternDict* decode_MMR(CJBig2_BitStream* pStream, IFX_Pause* pPause);
+
+ public:
+ FX_BOOL HDMMR;
+ uint8_t HDPW;
+ uint8_t HDPH;
+ FX_DWORD GRAYMAX;
+ uint8_t HDTEMPLATE;
+};
+
+#endif // CORE_FXCODEC_JBIG2_JBIG2_PDDPROC_H_
diff --git a/core/fxcodec/jbig2/JBig2_SddProc.cpp b/core/fxcodec/jbig2/JBig2_SddProc.cpp
new file mode 100644
index 0000000000..80079b93a5
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_SddProc.cpp
@@ -0,0 +1,624 @@
+// Copyright 2015 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxcodec/jbig2/JBig2_SddProc.h"
+
+#include <memory>
+#include <vector>
+
+#include "core/fxcodec/jbig2/JBig2_ArithIntDecoder.h"
+#include "core/fxcodec/jbig2/JBig2_GrdProc.h"
+#include "core/fxcodec/jbig2/JBig2_GrrdProc.h"
+#include "core/fxcodec/jbig2/JBig2_HuffmanDecoder.h"
+#include "core/fxcodec/jbig2/JBig2_HuffmanTable.h"
+#include "core/fxcodec/jbig2/JBig2_HuffmanTable_Standard.h"
+#include "core/fxcodec/jbig2/JBig2_SymbolDict.h"
+#include "core/fxcodec/jbig2/JBig2_TrdProc.h"
+#include "core/include/fxcrt/fx_basic.h"
+
+CJBig2_SymbolDict* CJBig2_SDDProc::decode_Arith(
+ CJBig2_ArithDecoder* pArithDecoder,
+ std::vector<JBig2ArithCtx>* gbContext,
+ std::vector<JBig2ArithCtx>* grContext) {
+ CJBig2_Image** SDNEWSYMS;
+ FX_DWORD HCHEIGHT, NSYMSDECODED;
+ int32_t HCDH;
+ FX_DWORD SYMWIDTH, TOTWIDTH;
+ int32_t DW;
+ CJBig2_Image* BS;
+ FX_DWORD I, J, REFAGGNINST;
+ FX_BOOL* EXFLAGS;
+ FX_DWORD EXINDEX;
+ FX_BOOL CUREXFLAG;
+ FX_DWORD EXRUNLENGTH;
+ FX_DWORD nTmp;
+ FX_DWORD SBNUMSYMS;
+ uint8_t SBSYMCODELEN;
+ int32_t RDXI, RDYI;
+ CJBig2_Image** SBSYMS;
+ std::unique_ptr<CJBig2_ArithIaidDecoder> IAID;
+ std::unique_ptr<CJBig2_SymbolDict> pDict;
+ std::unique_ptr<CJBig2_ArithIntDecoder> IADH(new CJBig2_ArithIntDecoder);
+ std::unique_ptr<CJBig2_ArithIntDecoder> IADW(new CJBig2_ArithIntDecoder);
+ std::unique_ptr<CJBig2_ArithIntDecoder> IAAI(new CJBig2_ArithIntDecoder);
+ std::unique_ptr<CJBig2_ArithIntDecoder> IARDX(new CJBig2_ArithIntDecoder);
+ std::unique_ptr<CJBig2_ArithIntDecoder> IARDY(new CJBig2_ArithIntDecoder);
+ std::unique_ptr<CJBig2_ArithIntDecoder> IAEX(new CJBig2_ArithIntDecoder);
+ std::unique_ptr<CJBig2_ArithIntDecoder> IADT(new CJBig2_ArithIntDecoder);
+ std::unique_ptr<CJBig2_ArithIntDecoder> IAFS(new CJBig2_ArithIntDecoder);
+ std::unique_ptr<CJBig2_ArithIntDecoder> IADS(new CJBig2_ArithIntDecoder);
+ std::unique_ptr<CJBig2_ArithIntDecoder> IAIT(new CJBig2_ArithIntDecoder);
+ std::unique_ptr<CJBig2_ArithIntDecoder> IARI(new CJBig2_ArithIntDecoder);
+ std::unique_ptr<CJBig2_ArithIntDecoder> IARDW(new CJBig2_ArithIntDecoder);
+ std::unique_ptr<CJBig2_ArithIntDecoder> IARDH(new CJBig2_ArithIntDecoder);
+ nTmp = 0;
+ while ((FX_DWORD)(1 << nTmp) < (SDNUMINSYMS + SDNUMNEWSYMS)) {
+ nTmp++;
+ }
+ IAID.reset(new CJBig2_ArithIaidDecoder((uint8_t)nTmp));
+ SDNEWSYMS = FX_Alloc(CJBig2_Image*, SDNUMNEWSYMS);
+ FXSYS_memset(SDNEWSYMS, 0, SDNUMNEWSYMS * sizeof(CJBig2_Image*));
+
+ HCHEIGHT = 0;
+ NSYMSDECODED = 0;
+ while (NSYMSDECODED < SDNUMNEWSYMS) {
+ BS = nullptr;
+ IADH->decode(pArithDecoder, &HCDH);
+ HCHEIGHT = HCHEIGHT + HCDH;
+ if ((int)HCHEIGHT < 0 || (int)HCHEIGHT > JBIG2_MAX_IMAGE_SIZE) {
+ goto failed;
+ }
+ SYMWIDTH = 0;
+ TOTWIDTH = 0;
+ for (;;) {
+ if (!IADW->decode(pArithDecoder, &DW))
+ break;
+
+ if (NSYMSDECODED >= SDNUMNEWSYMS)
+ goto failed;
+
+ SYMWIDTH = SYMWIDTH + DW;
+ if ((int)SYMWIDTH < 0 || (int)SYMWIDTH > JBIG2_MAX_IMAGE_SIZE)
+ goto failed;
+
+ if (HCHEIGHT == 0 || SYMWIDTH == 0) {
+ TOTWIDTH = TOTWIDTH + SYMWIDTH;
+ SDNEWSYMS[NSYMSDECODED] = nullptr;
+ NSYMSDECODED = NSYMSDECODED + 1;
+ continue;
+ }
+ TOTWIDTH = TOTWIDTH + SYMWIDTH;
+ if (SDREFAGG == 0) {
+ std::unique_ptr<CJBig2_GRDProc> pGRD(new CJBig2_GRDProc());
+ pGRD->MMR = 0;
+ pGRD->GBW = SYMWIDTH;
+ pGRD->GBH = HCHEIGHT;
+ pGRD->GBTEMPLATE = SDTEMPLATE;
+ pGRD->TPGDON = 0;
+ pGRD->USESKIP = 0;
+ pGRD->GBAT[0] = SDAT[0];
+ pGRD->GBAT[1] = SDAT[1];
+ pGRD->GBAT[2] = SDAT[2];
+ pGRD->GBAT[3] = SDAT[3];
+ pGRD->GBAT[4] = SDAT[4];
+ pGRD->GBAT[5] = SDAT[5];
+ pGRD->GBAT[6] = SDAT[6];
+ pGRD->GBAT[7] = SDAT[7];
+ BS = pGRD->decode_Arith(pArithDecoder, gbContext->data());
+ if (!BS) {
+ goto failed;
+ }
+ } else {
+ IAAI->decode(pArithDecoder, (int*)&REFAGGNINST);
+ if (REFAGGNINST > 1) {
+ std::unique_ptr<CJBig2_TRDProc> pDecoder(new CJBig2_TRDProc());
+ pDecoder->SBHUFF = SDHUFF;
+ pDecoder->SBREFINE = 1;
+ pDecoder->SBW = SYMWIDTH;
+ pDecoder->SBH = HCHEIGHT;
+ pDecoder->SBNUMINSTANCES = REFAGGNINST;
+ pDecoder->SBSTRIPS = 1;
+ pDecoder->SBNUMSYMS = SDNUMINSYMS + NSYMSDECODED;
+ SBNUMSYMS = pDecoder->SBNUMSYMS;
+ nTmp = 0;
+ while ((FX_DWORD)(1 << nTmp) < SBNUMSYMS) {
+ nTmp++;
+ }
+ SBSYMCODELEN = (uint8_t)nTmp;
+ pDecoder->SBSYMCODELEN = SBSYMCODELEN;
+ SBSYMS = FX_Alloc(CJBig2_Image*, SBNUMSYMS);
+ JBIG2_memcpy(SBSYMS, SDINSYMS, SDNUMINSYMS * sizeof(CJBig2_Image*));
+ JBIG2_memcpy(SBSYMS + SDNUMINSYMS, SDNEWSYMS,
+ NSYMSDECODED * sizeof(CJBig2_Image*));
+ pDecoder->SBSYMS = SBSYMS;
+ pDecoder->SBDEFPIXEL = 0;
+ pDecoder->SBCOMBOP = JBIG2_COMPOSE_OR;
+ pDecoder->TRANSPOSED = 0;
+ pDecoder->REFCORNER = JBIG2_CORNER_TOPLEFT;
+ pDecoder->SBDSOFFSET = 0;
+ std::unique_ptr<CJBig2_HuffmanTable> SBHUFFFS(new CJBig2_HuffmanTable(
+ HuffmanTable_B6, FX_ArraySize(HuffmanTable_B6),
+ HuffmanTable_HTOOB_B6));
+ std::unique_ptr<CJBig2_HuffmanTable> SBHUFFDS(new CJBig2_HuffmanTable(
+ HuffmanTable_B8, FX_ArraySize(HuffmanTable_B8),
+ HuffmanTable_HTOOB_B8));
+ std::unique_ptr<CJBig2_HuffmanTable> SBHUFFDT(new CJBig2_HuffmanTable(
+ HuffmanTable_B11, FX_ArraySize(HuffmanTable_B11),
+ HuffmanTable_HTOOB_B11));
+ std::unique_ptr<CJBig2_HuffmanTable> SBHUFFRDW(
+ new CJBig2_HuffmanTable(HuffmanTable_B15,
+ FX_ArraySize(HuffmanTable_B15),
+ HuffmanTable_HTOOB_B15));
+ std::unique_ptr<CJBig2_HuffmanTable> SBHUFFRDH(
+ new CJBig2_HuffmanTable(HuffmanTable_B15,
+ FX_ArraySize(HuffmanTable_B15),
+ HuffmanTable_HTOOB_B15));
+ std::unique_ptr<CJBig2_HuffmanTable> SBHUFFRDX(
+ new CJBig2_HuffmanTable(HuffmanTable_B15,
+ FX_ArraySize(HuffmanTable_B15),
+ HuffmanTable_HTOOB_B15));
+ std::unique_ptr<CJBig2_HuffmanTable> SBHUFFRDY(
+ new CJBig2_HuffmanTable(HuffmanTable_B15,
+ FX_ArraySize(HuffmanTable_B15),
+ HuffmanTable_HTOOB_B15));
+ std::unique_ptr<CJBig2_HuffmanTable> SBHUFFRSIZE(
+ new CJBig2_HuffmanTable(HuffmanTable_B1,
+ FX_ArraySize(HuffmanTable_B1),
+ HuffmanTable_HTOOB_B1));
+ pDecoder->SBHUFFFS = SBHUFFFS.get();
+ pDecoder->SBHUFFDS = SBHUFFDS.get();
+ pDecoder->SBHUFFDT = SBHUFFDT.get();
+ pDecoder->SBHUFFRDW = SBHUFFRDW.get();
+ pDecoder->SBHUFFRDH = SBHUFFRDH.get();
+ pDecoder->SBHUFFRDX = SBHUFFRDX.get();
+ pDecoder->SBHUFFRDY = SBHUFFRDY.get();
+ pDecoder->SBHUFFRSIZE = SBHUFFRSIZE.get();
+ pDecoder->SBRTEMPLATE = SDRTEMPLATE;
+ pDecoder->SBRAT[0] = SDRAT[0];
+ pDecoder->SBRAT[1] = SDRAT[1];
+ pDecoder->SBRAT[2] = SDRAT[2];
+ pDecoder->SBRAT[3] = SDRAT[3];
+ JBig2IntDecoderState ids;
+ ids.IADT = IADT.get();
+ ids.IAFS = IAFS.get();
+ ids.IADS = IADS.get();
+ ids.IAIT = IAIT.get();
+ ids.IARI = IARI.get();
+ ids.IARDW = IARDW.get();
+ ids.IARDH = IARDH.get();
+ ids.IARDX = IARDX.get();
+ ids.IARDY = IARDY.get();
+ ids.IAID = IAID.get();
+ BS = pDecoder->decode_Arith(pArithDecoder, grContext->data(), &ids);
+ if (!BS) {
+ FX_Free(SBSYMS);
+ goto failed;
+ }
+ FX_Free(SBSYMS);
+ } else if (REFAGGNINST == 1) {
+ SBNUMSYMS = SDNUMINSYMS + NSYMSDECODED;
+ FX_DWORD IDI;
+ IAID->decode(pArithDecoder, &IDI);
+ IARDX->decode(pArithDecoder, &RDXI);
+ IARDY->decode(pArithDecoder, &RDYI);
+ if (IDI >= SBNUMSYMS) {
+ goto failed;
+ }
+ SBSYMS = FX_Alloc(CJBig2_Image*, SBNUMSYMS);
+ JBIG2_memcpy(SBSYMS, SDINSYMS, SDNUMINSYMS * sizeof(CJBig2_Image*));
+ JBIG2_memcpy(SBSYMS + SDNUMINSYMS, SDNEWSYMS,
+ NSYMSDECODED * sizeof(CJBig2_Image*));
+ if (!SBSYMS[IDI]) {
+ FX_Free(SBSYMS);
+ goto failed;
+ }
+ std::unique_ptr<CJBig2_GRRDProc> pGRRD(new CJBig2_GRRDProc());
+ pGRRD->GRW = SYMWIDTH;
+ pGRRD->GRH = HCHEIGHT;
+ pGRRD->GRTEMPLATE = SDRTEMPLATE;
+ pGRRD->GRREFERENCE = SBSYMS[IDI];
+ pGRRD->GRREFERENCEDX = RDXI;
+ pGRRD->GRREFERENCEDY = RDYI;
+ pGRRD->TPGRON = 0;
+ pGRRD->GRAT[0] = SDRAT[0];
+ pGRRD->GRAT[1] = SDRAT[1];
+ pGRRD->GRAT[2] = SDRAT[2];
+ pGRRD->GRAT[3] = SDRAT[3];
+ BS = pGRRD->decode(pArithDecoder, grContext->data());
+ if (!BS) {
+ FX_Free(SBSYMS);
+ goto failed;
+ }
+ FX_Free(SBSYMS);
+ }
+ }
+ SDNEWSYMS[NSYMSDECODED] = BS;
+ BS = nullptr;
+ NSYMSDECODED = NSYMSDECODED + 1;
+ }
+ }
+ EXINDEX = 0;
+ CUREXFLAG = 0;
+ EXFLAGS = FX_Alloc(FX_BOOL, SDNUMINSYMS + SDNUMNEWSYMS);
+ while (EXINDEX < SDNUMINSYMS + SDNUMNEWSYMS) {
+ IAEX->decode(pArithDecoder, (int*)&EXRUNLENGTH);
+ if (EXINDEX + EXRUNLENGTH > SDNUMINSYMS + SDNUMNEWSYMS) {
+ FX_Free(EXFLAGS);
+ goto failed;
+ }
+ if (EXRUNLENGTH != 0) {
+ for (I = EXINDEX; I < EXINDEX + EXRUNLENGTH; I++) {
+ EXFLAGS[I] = CUREXFLAG;
+ }
+ }
+ EXINDEX = EXINDEX + EXRUNLENGTH;
+ CUREXFLAG = !CUREXFLAG;
+ }
+ pDict.reset(new CJBig2_SymbolDict);
+ I = J = 0;
+ for (I = 0; I < SDNUMINSYMS + SDNUMNEWSYMS; I++) {
+ if (EXFLAGS[I] && J < SDNUMEXSYMS) {
+ if (I < SDNUMINSYMS) {
+ pDict->AddImage(SDINSYMS[I] ? new CJBig2_Image(*SDINSYMS[I]) : nullptr);
+ } else {
+ pDict->AddImage(SDNEWSYMS[I - SDNUMINSYMS]);
+ }
+ ++J;
+ } else if (!EXFLAGS[I] && I >= SDNUMINSYMS) {
+ delete SDNEWSYMS[I - SDNUMINSYMS];
+ }
+ }
+ FX_Free(EXFLAGS);
+ FX_Free(SDNEWSYMS);
+ return pDict.release();
+failed:
+ for (I = 0; I < NSYMSDECODED; I++) {
+ if (SDNEWSYMS[I]) {
+ delete SDNEWSYMS[I];
+ SDNEWSYMS[I] = nullptr;
+ }
+ }
+ FX_Free(SDNEWSYMS);
+ return nullptr;
+}
+
+CJBig2_SymbolDict* CJBig2_SDDProc::decode_Huffman(
+ CJBig2_BitStream* pStream,
+ std::vector<JBig2ArithCtx>* gbContext,
+ std::vector<JBig2ArithCtx>* grContext,
+ IFX_Pause* pPause) {
+ CJBig2_Image** SDNEWSYMS;
+ FX_DWORD* SDNEWSYMWIDTHS;
+ FX_DWORD HCHEIGHT, NSYMSDECODED;
+ int32_t HCDH;
+ FX_DWORD SYMWIDTH, TOTWIDTH, HCFIRSTSYM;
+ int32_t DW;
+ CJBig2_Image *BS, *BHC;
+ FX_DWORD I, J, REFAGGNINST;
+ FX_BOOL* EXFLAGS;
+ FX_DWORD EXINDEX;
+ FX_BOOL CUREXFLAG;
+ FX_DWORD EXRUNLENGTH;
+ int32_t nVal, nBits;
+ FX_DWORD nTmp;
+ FX_DWORD SBNUMSYMS;
+ uint8_t SBSYMCODELEN;
+ JBig2HuffmanCode* SBSYMCODES;
+ FX_DWORD IDI;
+ int32_t RDXI, RDYI;
+ FX_DWORD BMSIZE;
+ FX_DWORD stride;
+ CJBig2_Image** SBSYMS;
+ std::unique_ptr<CJBig2_HuffmanDecoder> pHuffmanDecoder(
+ new CJBig2_HuffmanDecoder(pStream));
+ SDNEWSYMS = FX_Alloc(CJBig2_Image*, SDNUMNEWSYMS);
+ FXSYS_memset(SDNEWSYMS, 0, SDNUMNEWSYMS * sizeof(CJBig2_Image*));
+ SDNEWSYMWIDTHS = nullptr;
+ BHC = nullptr;
+ if (SDREFAGG == 0) {
+ SDNEWSYMWIDTHS = FX_Alloc(FX_DWORD, SDNUMNEWSYMS);
+ FXSYS_memset(SDNEWSYMWIDTHS, 0, SDNUMNEWSYMS * sizeof(FX_DWORD));
+ }
+ std::unique_ptr<CJBig2_SymbolDict> pDict(new CJBig2_SymbolDict());
+ std::unique_ptr<CJBig2_HuffmanTable> pTable;
+
+ HCHEIGHT = 0;
+ NSYMSDECODED = 0;
+ BS = nullptr;
+ while (NSYMSDECODED < SDNUMNEWSYMS) {
+ if (pHuffmanDecoder->decodeAValue(SDHUFFDH, &HCDH) != 0) {
+ goto failed;
+ }
+ HCHEIGHT = HCHEIGHT + HCDH;
+ if ((int)HCHEIGHT < 0 || (int)HCHEIGHT > JBIG2_MAX_IMAGE_SIZE) {
+ goto failed;
+ }
+ SYMWIDTH = 0;
+ TOTWIDTH = 0;
+ HCFIRSTSYM = NSYMSDECODED;
+ for (;;) {
+ nVal = pHuffmanDecoder->decodeAValue(SDHUFFDW, &DW);
+ if (nVal == JBIG2_OOB) {
+ break;
+ } else if (nVal != 0) {
+ goto failed;
+ } else {
+ if (NSYMSDECODED >= SDNUMNEWSYMS) {
+ goto failed;
+ }
+ SYMWIDTH = SYMWIDTH + DW;
+ if ((int)SYMWIDTH < 0 || (int)SYMWIDTH > JBIG2_MAX_IMAGE_SIZE) {
+ goto failed;
+ } else if (HCHEIGHT == 0 || SYMWIDTH == 0) {
+ TOTWIDTH = TOTWIDTH + SYMWIDTH;
+ SDNEWSYMS[NSYMSDECODED] = nullptr;
+ NSYMSDECODED = NSYMSDECODED + 1;
+ continue;
+ }
+ TOTWIDTH = TOTWIDTH + SYMWIDTH;
+ }
+ if (SDREFAGG == 1) {
+ if (pHuffmanDecoder->decodeAValue(SDHUFFAGGINST, (int*)&REFAGGNINST) !=
+ 0) {
+ goto failed;
+ }
+ BS = nullptr;
+ if (REFAGGNINST > 1) {
+ std::unique_ptr<CJBig2_TRDProc> pDecoder(new CJBig2_TRDProc());
+ pDecoder->SBHUFF = SDHUFF;
+ pDecoder->SBREFINE = 1;
+ pDecoder->SBW = SYMWIDTH;
+ pDecoder->SBH = HCHEIGHT;
+ pDecoder->SBNUMINSTANCES = REFAGGNINST;
+ pDecoder->SBSTRIPS = 1;
+ pDecoder->SBNUMSYMS = SDNUMINSYMS + NSYMSDECODED;
+ SBNUMSYMS = pDecoder->SBNUMSYMS;
+ SBSYMCODES = FX_Alloc(JBig2HuffmanCode, SBNUMSYMS);
+ nTmp = 1;
+ while ((FX_DWORD)(1 << nTmp) < SBNUMSYMS) {
+ nTmp++;
+ }
+ for (I = 0; I < SBNUMSYMS; I++) {
+ SBSYMCODES[I].codelen = nTmp;
+ SBSYMCODES[I].code = I;
+ }
+ pDecoder->SBSYMCODES = SBSYMCODES;
+ SBSYMS = FX_Alloc(CJBig2_Image*, SBNUMSYMS);
+ JBIG2_memcpy(SBSYMS, SDINSYMS, SDNUMINSYMS * sizeof(CJBig2_Image*));
+ JBIG2_memcpy(SBSYMS + SDNUMINSYMS, SDNEWSYMS,
+ NSYMSDECODED * sizeof(CJBig2_Image*));
+ pDecoder->SBSYMS = SBSYMS;
+ pDecoder->SBDEFPIXEL = 0;
+ pDecoder->SBCOMBOP = JBIG2_COMPOSE_OR;
+ pDecoder->TRANSPOSED = 0;
+ pDecoder->REFCORNER = JBIG2_CORNER_TOPLEFT;
+ pDecoder->SBDSOFFSET = 0;
+ std::unique_ptr<CJBig2_HuffmanTable> SBHUFFFS(new CJBig2_HuffmanTable(
+ HuffmanTable_B6, FX_ArraySize(HuffmanTable_B6),
+ HuffmanTable_HTOOB_B6));
+ std::unique_ptr<CJBig2_HuffmanTable> SBHUFFDS(new CJBig2_HuffmanTable(
+ HuffmanTable_B8, FX_ArraySize(HuffmanTable_B8),
+ HuffmanTable_HTOOB_B8));
+ std::unique_ptr<CJBig2_HuffmanTable> SBHUFFDT(new CJBig2_HuffmanTable(
+ HuffmanTable_B11, FX_ArraySize(HuffmanTable_B11),
+ HuffmanTable_HTOOB_B11));
+ std::unique_ptr<CJBig2_HuffmanTable> SBHUFFRDW(
+ new CJBig2_HuffmanTable(HuffmanTable_B15,
+ FX_ArraySize(HuffmanTable_B15),
+ HuffmanTable_HTOOB_B15));
+ std::unique_ptr<CJBig2_HuffmanTable> SBHUFFRDH(
+ new CJBig2_HuffmanTable(HuffmanTable_B15,
+ FX_ArraySize(HuffmanTable_B15),
+ HuffmanTable_HTOOB_B15));
+ std::unique_ptr<CJBig2_HuffmanTable> SBHUFFRDX(
+ new CJBig2_HuffmanTable(HuffmanTable_B15,
+ FX_ArraySize(HuffmanTable_B15),
+ HuffmanTable_HTOOB_B15));
+ std::unique_ptr<CJBig2_HuffmanTable> SBHUFFRDY(
+ new CJBig2_HuffmanTable(HuffmanTable_B15,
+ FX_ArraySize(HuffmanTable_B15),
+ HuffmanTable_HTOOB_B15));
+ std::unique_ptr<CJBig2_HuffmanTable> SBHUFFRSIZE(
+ new CJBig2_HuffmanTable(HuffmanTable_B1,
+ FX_ArraySize(HuffmanTable_B1),
+ HuffmanTable_HTOOB_B1));
+ pDecoder->SBHUFFFS = SBHUFFFS.get();
+ pDecoder->SBHUFFDS = SBHUFFDS.get();
+ pDecoder->SBHUFFDT = SBHUFFDT.get();
+ pDecoder->SBHUFFRDW = SBHUFFRDW.get();
+ pDecoder->SBHUFFRDH = SBHUFFRDH.get();
+ pDecoder->SBHUFFRDX = SBHUFFRDX.get();
+ pDecoder->SBHUFFRDY = SBHUFFRDY.get();
+ pDecoder->SBHUFFRSIZE = SBHUFFRSIZE.get();
+ pDecoder->SBRTEMPLATE = SDRTEMPLATE;
+ pDecoder->SBRAT[0] = SDRAT[0];
+ pDecoder->SBRAT[1] = SDRAT[1];
+ pDecoder->SBRAT[2] = SDRAT[2];
+ pDecoder->SBRAT[3] = SDRAT[3];
+ BS = pDecoder->decode_Huffman(pStream, grContext->data());
+ if (!BS) {
+ FX_Free(SBSYMCODES);
+ FX_Free(SBSYMS);
+ goto failed;
+ }
+ FX_Free(SBSYMCODES);
+ FX_Free(SBSYMS);
+ } else if (REFAGGNINST == 1) {
+ SBNUMSYMS = SDNUMINSYMS + SDNUMNEWSYMS;
+ nTmp = 1;
+ while ((FX_DWORD)(1 << nTmp) < SBNUMSYMS) {
+ nTmp++;
+ }
+ SBSYMCODELEN = (uint8_t)nTmp;
+ SBSYMCODES = FX_Alloc(JBig2HuffmanCode, SBNUMSYMS);
+ for (I = 0; I < SBNUMSYMS; I++) {
+ SBSYMCODES[I].codelen = SBSYMCODELEN;
+ SBSYMCODES[I].code = I;
+ }
+ nVal = 0;
+ nBits = 0;
+ for (;;) {
+ if (pStream->read1Bit(&nTmp) != 0) {
+ FX_Free(SBSYMCODES);
+ goto failed;
+ }
+ nVal = (nVal << 1) | nTmp;
+ for (IDI = 0; IDI < SBNUMSYMS; IDI++) {
+ if ((nVal == SBSYMCODES[IDI].code) &&
+ (nBits == SBSYMCODES[IDI].codelen)) {
+ break;
+ }
+ }
+ if (IDI < SBNUMSYMS) {
+ break;
+ }
+ }
+ FX_Free(SBSYMCODES);
+ std::unique_ptr<CJBig2_HuffmanTable> SBHUFFRDX(
+ new CJBig2_HuffmanTable(HuffmanTable_B15,
+ FX_ArraySize(HuffmanTable_B15),
+ HuffmanTable_HTOOB_B15));
+ std::unique_ptr<CJBig2_HuffmanTable> SBHUFFRSIZE(
+ new CJBig2_HuffmanTable(HuffmanTable_B1,
+ FX_ArraySize(HuffmanTable_B1),
+ HuffmanTable_HTOOB_B1));
+ if ((pHuffmanDecoder->decodeAValue(SBHUFFRDX.get(), &RDXI) != 0) ||
+ (pHuffmanDecoder->decodeAValue(SBHUFFRDX.get(), &RDYI) != 0) ||
+ (pHuffmanDecoder->decodeAValue(SBHUFFRSIZE.get(), &nVal) != 0)) {
+ goto failed;
+ }
+ pStream->alignByte();
+ nTmp = pStream->getOffset();
+ SBSYMS = FX_Alloc(CJBig2_Image*, SBNUMSYMS);
+ JBIG2_memcpy(SBSYMS, SDINSYMS, SDNUMINSYMS * sizeof(CJBig2_Image*));
+ JBIG2_memcpy(SBSYMS + SDNUMINSYMS, SDNEWSYMS,
+ NSYMSDECODED * sizeof(CJBig2_Image*));
+ std::unique_ptr<CJBig2_GRRDProc> pGRRD(new CJBig2_GRRDProc());
+ pGRRD->GRW = SYMWIDTH;
+ pGRRD->GRH = HCHEIGHT;
+ pGRRD->GRTEMPLATE = SDRTEMPLATE;
+ pGRRD->GRREFERENCE = SBSYMS[IDI];
+ pGRRD->GRREFERENCEDX = RDXI;
+ pGRRD->GRREFERENCEDY = RDYI;
+ pGRRD->TPGRON = 0;
+ pGRRD->GRAT[0] = SDRAT[0];
+ pGRRD->GRAT[1] = SDRAT[1];
+ pGRRD->GRAT[2] = SDRAT[2];
+ pGRRD->GRAT[3] = SDRAT[3];
+ std::unique_ptr<CJBig2_ArithDecoder> pArithDecoder(
+ new CJBig2_ArithDecoder(pStream));
+ BS = pGRRD->decode(pArithDecoder.get(), grContext->data());
+ if (!BS) {
+ FX_Free(SBSYMS);
+ goto failed;
+ }
+ pStream->alignByte();
+ pStream->offset(2);
+ if ((FX_DWORD)nVal != (pStream->getOffset() - nTmp)) {
+ delete BS;
+ FX_Free(SBSYMS);
+ goto failed;
+ }
+ FX_Free(SBSYMS);
+ }
+ SDNEWSYMS[NSYMSDECODED] = BS;
+ }
+ if (SDREFAGG == 0) {
+ SDNEWSYMWIDTHS[NSYMSDECODED] = SYMWIDTH;
+ }
+ NSYMSDECODED = NSYMSDECODED + 1;
+ }
+ if (SDREFAGG == 0) {
+ if (pHuffmanDecoder->decodeAValue(SDHUFFBMSIZE, (int32_t*)&BMSIZE) != 0) {
+ goto failed;
+ }
+ pStream->alignByte();
+ if (BMSIZE == 0) {
+ stride = (TOTWIDTH + 7) >> 3;
+ if (pStream->getByteLeft() >= stride * HCHEIGHT) {
+ BHC = new CJBig2_Image(TOTWIDTH, HCHEIGHT);
+ for (I = 0; I < HCHEIGHT; I++) {
+ JBIG2_memcpy(BHC->m_pData + I * BHC->m_nStride,
+ pStream->getPointer(), stride);
+ pStream->offset(stride);
+ }
+ } else {
+ goto failed;
+ }
+ } else {
+ std::unique_ptr<CJBig2_GRDProc> pGRD(new CJBig2_GRDProc());
+ pGRD->MMR = 1;
+ pGRD->GBW = TOTWIDTH;
+ pGRD->GBH = HCHEIGHT;
+ FXCODEC_STATUS status = pGRD->Start_decode_MMR(&BHC, pStream, nullptr);
+ while (status == FXCODEC_STATUS_DECODE_TOBECONTINUE) {
+ pGRD->Continue_decode(pPause);
+ }
+ pStream->alignByte();
+ }
+ nTmp = 0;
+ if (!BHC) {
+ continue;
+ }
+ for (I = HCFIRSTSYM; I < NSYMSDECODED; I++) {
+ SDNEWSYMS[I] = BHC->subImage(nTmp, 0, SDNEWSYMWIDTHS[I], HCHEIGHT);
+ nTmp += SDNEWSYMWIDTHS[I];
+ }
+ delete BHC;
+ BHC = nullptr;
+ }
+ }
+ EXINDEX = 0;
+ CUREXFLAG = 0;
+ pTable.reset(new CJBig2_HuffmanTable(
+ HuffmanTable_B1, FX_ArraySize(HuffmanTable_B1), HuffmanTable_HTOOB_B1));
+ EXFLAGS = FX_Alloc(FX_BOOL, SDNUMINSYMS + SDNUMNEWSYMS);
+ while (EXINDEX < SDNUMINSYMS + SDNUMNEWSYMS) {
+ if (pHuffmanDecoder->decodeAValue(pTable.get(), (int*)&EXRUNLENGTH) != 0) {
+ FX_Free(EXFLAGS);
+ goto failed;
+ }
+ if (EXINDEX + EXRUNLENGTH > SDNUMINSYMS + SDNUMNEWSYMS) {
+ FX_Free(EXFLAGS);
+ goto failed;
+ }
+ if (EXRUNLENGTH != 0) {
+ for (I = EXINDEX; I < EXINDEX + EXRUNLENGTH; I++) {
+ EXFLAGS[I] = CUREXFLAG;
+ }
+ }
+ EXINDEX = EXINDEX + EXRUNLENGTH;
+ CUREXFLAG = !CUREXFLAG;
+ }
+ I = J = 0;
+ for (I = 0; I < SDNUMINSYMS + SDNUMNEWSYMS; I++) {
+ if (EXFLAGS[I] && J < SDNUMEXSYMS) {
+ if (I < SDNUMINSYMS) {
+ pDict->AddImage(SDINSYMS[I] ? new CJBig2_Image(*SDINSYMS[I]) : nullptr);
+ } else {
+ pDict->AddImage(SDNEWSYMS[I - SDNUMINSYMS]);
+ }
+ ++J;
+ } else if (!EXFLAGS[I] && I >= SDNUMINSYMS) {
+ delete SDNEWSYMS[I - SDNUMINSYMS];
+ }
+ }
+ FX_Free(EXFLAGS);
+ FX_Free(SDNEWSYMS);
+ if (SDREFAGG == 0) {
+ FX_Free(SDNEWSYMWIDTHS);
+ }
+ return pDict.release();
+failed:
+ for (I = 0; I < NSYMSDECODED; I++) {
+ delete SDNEWSYMS[I];
+ }
+ FX_Free(SDNEWSYMS);
+ if (SDREFAGG == 0) {
+ FX_Free(SDNEWSYMWIDTHS);
+ }
+ return nullptr;
+}
diff --git a/core/fxcodec/jbig2/JBig2_SddProc.h b/core/fxcodec/jbig2/JBig2_SddProc.h
new file mode 100644
index 0000000000..fa1211b4b4
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_SddProc.h
@@ -0,0 +1,49 @@
+// Copyright 2015 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_JBIG2_JBIG2_SDDPROC_H_
+#define CORE_FXCODEC_JBIG2_JBIG2_SDDPROC_H_
+
+#include <vector>
+
+#include "core/fxcodec/jbig2/JBig2_ArithDecoder.h"
+#include "core/include/fxcrt/fx_system.h"
+
+class CJBig2_BitStream;
+class CJBig2_HuffmanTable;
+class CJBig2_Image;
+class CJBig2_SymbolDict;
+class IFX_Pause;
+
+class CJBig2_SDDProc {
+ public:
+ CJBig2_SymbolDict* decode_Arith(CJBig2_ArithDecoder* pArithDecoder,
+ std::vector<JBig2ArithCtx>* gbContext,
+ std::vector<JBig2ArithCtx>* grContext);
+
+ CJBig2_SymbolDict* decode_Huffman(CJBig2_BitStream* pStream,
+ std::vector<JBig2ArithCtx>* gbContext,
+ std::vector<JBig2ArithCtx>* grContext,
+ IFX_Pause* pPause);
+
+ public:
+ FX_BOOL SDHUFF;
+ FX_BOOL SDREFAGG;
+ FX_DWORD SDNUMINSYMS;
+ CJBig2_Image** SDINSYMS;
+ FX_DWORD SDNUMNEWSYMS;
+ FX_DWORD SDNUMEXSYMS;
+ CJBig2_HuffmanTable* SDHUFFDH;
+ CJBig2_HuffmanTable* SDHUFFDW;
+ CJBig2_HuffmanTable* SDHUFFBMSIZE;
+ CJBig2_HuffmanTable* SDHUFFAGGINST;
+ uint8_t SDTEMPLATE;
+ int8_t SDAT[8];
+ FX_BOOL SDRTEMPLATE;
+ int8_t SDRAT[4];
+};
+
+#endif // CORE_FXCODEC_JBIG2_JBIG2_SDDPROC_H_
diff --git a/core/fxcodec/jbig2/JBig2_Segment.cpp b/core/fxcodec/jbig2/JBig2_Segment.cpp
new file mode 100644
index 0000000000..a6bac36141
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_Segment.cpp
@@ -0,0 +1,44 @@
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxcodec/jbig2/JBig2_Segment.h"
+
+#include "core/include/fxcrt/fx_memory.h"
+
+CJBig2_Segment::CJBig2_Segment() {
+ m_dwNumber = 0;
+ m_cFlags.c = 0;
+ m_nReferred_to_segment_count = 0;
+ m_pReferred_to_segment_numbers = NULL;
+ m_dwPage_association = 0;
+ m_dwData_length = 0;
+ m_dwHeader_Length = 0;
+ m_dwObjNum = 0;
+ m_dwDataOffset = 0;
+ m_State = JBIG2_SEGMENT_HEADER_UNPARSED;
+ m_nResultType = JBIG2_VOID_POINTER;
+ m_Result.vd = NULL;
+}
+CJBig2_Segment::~CJBig2_Segment() {
+ FX_Free(m_pReferred_to_segment_numbers);
+
+ switch (m_nResultType) {
+ case JBIG2_IMAGE_POINTER:
+ delete m_Result.im;
+ break;
+ case JBIG2_SYMBOL_DICT_POINTER:
+ delete m_Result.sd;
+ break;
+ case JBIG2_PATTERN_DICT_POINTER:
+ delete m_Result.pd;
+ break;
+ case JBIG2_HUFFMAN_TABLE_POINTER:
+ delete m_Result.ht;
+ break;
+ default:
+ FX_Free(m_Result.vd);
+ }
+}
diff --git a/core/fxcodec/jbig2/JBig2_Segment.h b/core/fxcodec/jbig2/JBig2_Segment.h
new file mode 100644
index 0000000000..61550ada09
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_Segment.h
@@ -0,0 +1,66 @@
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_JBIG2_JBIG2_SEGMENT_H_
+#define CORE_FXCODEC_JBIG2_JBIG2_SEGMENT_H_
+
+#include "core/fxcodec/jbig2/JBig2_Define.h"
+#include "core/fxcodec/jbig2/JBig2_HuffmanTable.h"
+#include "core/fxcodec/jbig2/JBig2_PatternDict.h"
+#include "core/fxcodec/jbig2/JBig2_SymbolDict.h"
+
+#define JBIG2_GET_INT32(buf) \
+ (((buf)[0] << 24) | ((buf)[1] << 16) | ((buf)[2] << 8) | (buf)[3])
+#define JBIG2_GET_INT16(buf) (((buf)[0] << 8) | (buf)[1])
+typedef enum {
+ JBIG2_SEGMENT_HEADER_UNPARSED,
+ JBIG2_SEGMENT_DATA_UNPARSED,
+ JBIG2_SEGMENT_PARSE_COMPLETE,
+ JBIG2_SEGMENT_PAUSED,
+ JBIG2_SEGMENT_ERROR
+} JBig2_SegmentState;
+typedef enum {
+ JBIG2_VOID_POINTER = 0,
+ JBIG2_IMAGE_POINTER,
+ JBIG2_SYMBOL_DICT_POINTER,
+ JBIG2_PATTERN_DICT_POINTER,
+ JBIG2_HUFFMAN_TABLE_POINTER
+} JBig2_ResultType;
+class CJBig2_Segment {
+ public:
+ CJBig2_Segment();
+
+ ~CJBig2_Segment();
+
+ FX_DWORD m_dwNumber;
+ union {
+ struct {
+ uint8_t type : 6;
+ uint8_t page_association_size : 1;
+ uint8_t deferred_non_retain : 1;
+ } s;
+ uint8_t c;
+ } m_cFlags;
+ int32_t m_nReferred_to_segment_count;
+ FX_DWORD* m_pReferred_to_segment_numbers;
+ FX_DWORD m_dwPage_association;
+ FX_DWORD m_dwData_length;
+
+ FX_DWORD m_dwHeader_Length;
+ FX_DWORD m_dwObjNum;
+ FX_DWORD m_dwDataOffset;
+ JBig2_SegmentState m_State;
+ JBig2_ResultType m_nResultType;
+ union {
+ CJBig2_SymbolDict* sd;
+ CJBig2_PatternDict* pd;
+ CJBig2_Image* im;
+ CJBig2_HuffmanTable* ht;
+ void* vd;
+ } m_Result;
+};
+
+#endif // CORE_FXCODEC_JBIG2_JBIG2_SEGMENT_H_
diff --git a/core/fxcodec/jbig2/JBig2_SymbolDict.cpp b/core/fxcodec/jbig2/JBig2_SymbolDict.cpp
new file mode 100644
index 0000000000..9fe3d54a0c
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_SymbolDict.cpp
@@ -0,0 +1,26 @@
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxcodec/jbig2/JBig2_SymbolDict.h"
+
+#include "core/fxcodec/jbig2/JBig2_Image.h"
+#include "core/include/fxcrt/fx_memory.h"
+
+CJBig2_SymbolDict::CJBig2_SymbolDict() {}
+
+CJBig2_SymbolDict::~CJBig2_SymbolDict() {}
+
+std::unique_ptr<CJBig2_SymbolDict> CJBig2_SymbolDict::DeepCopy() const {
+ const CJBig2_SymbolDict* src = this;
+ std::unique_ptr<CJBig2_SymbolDict> dst(new CJBig2_SymbolDict);
+ for (size_t i = 0; i < src->m_SDEXSYMS.size(); ++i) {
+ CJBig2_Image* image = src->m_SDEXSYMS.get(i);
+ dst->m_SDEXSYMS.push_back(image ? new CJBig2_Image(*image) : nullptr);
+ }
+ dst->m_gbContext = src->m_gbContext;
+ dst->m_grContext = src->m_grContext;
+ return dst;
+}
diff --git a/core/fxcodec/jbig2/JBig2_SymbolDict.h b/core/fxcodec/jbig2/JBig2_SymbolDict.h
new file mode 100644
index 0000000000..64ab881596
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_SymbolDict.h
@@ -0,0 +1,48 @@
+// Copyright 2014 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_JBIG2_JBIG2_SYMBOLDICT_H_
+#define CORE_FXCODEC_JBIG2_JBIG2_SYMBOLDICT_H_
+
+#include <memory>
+#include <vector>
+
+#include "core/fxcodec/jbig2/JBig2_ArithDecoder.h"
+#include "core/fxcodec/jbig2/JBig2_List.h"
+#include "core/include/fxcrt/fx_basic.h"
+
+class CJBig2_Image;
+
+class CJBig2_SymbolDict {
+ public:
+ CJBig2_SymbolDict();
+ ~CJBig2_SymbolDict();
+
+ std::unique_ptr<CJBig2_SymbolDict> DeepCopy() const;
+
+ // Takes ownership of |image|.
+ void AddImage(CJBig2_Image* image) { m_SDEXSYMS.push_back(image); }
+
+ size_t NumImages() const { return m_SDEXSYMS.size(); }
+ CJBig2_Image* GetImage(size_t index) const { return m_SDEXSYMS.get(index); }
+
+ const std::vector<JBig2ArithCtx>& GbContext() const { return m_gbContext; }
+ const std::vector<JBig2ArithCtx>& GrContext() const { return m_grContext; }
+
+ void SetGbContext(const std::vector<JBig2ArithCtx>& gbContext) {
+ m_gbContext = gbContext;
+ }
+ void SetGrContext(const std::vector<JBig2ArithCtx>& grContext) {
+ m_grContext = grContext;
+ }
+
+ private:
+ std::vector<JBig2ArithCtx> m_gbContext;
+ std::vector<JBig2ArithCtx> m_grContext;
+ CJBig2_List<CJBig2_Image> m_SDEXSYMS;
+};
+
+#endif // CORE_FXCODEC_JBIG2_JBIG2_SYMBOLDICT_H_
diff --git a/core/fxcodec/jbig2/JBig2_TrdProc.cpp b/core/fxcodec/jbig2/JBig2_TrdProc.cpp
new file mode 100644
index 0000000000..401249e3f2
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_TrdProc.cpp
@@ -0,0 +1,407 @@
+// Copyright 2015 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "core/fxcodec/jbig2/JBig2_TrdProc.h"
+
+#include <memory>
+
+#include "core/fxcodec/jbig2/JBig2_ArithDecoder.h"
+#include "core/fxcodec/jbig2/JBig2_ArithIntDecoder.h"
+#include "core/fxcodec/jbig2/JBig2_GrrdProc.h"
+#include "core/fxcodec/jbig2/JBig2_HuffmanDecoder.h"
+
+CJBig2_Image* CJBig2_TRDProc::decode_Huffman(CJBig2_BitStream* pStream,
+ JBig2ArithCtx* grContext) {
+ int32_t STRIPT, FIRSTS;
+ FX_DWORD NINSTANCES;
+ int32_t DT, DFS, CURS;
+ int32_t SI, TI;
+ CJBig2_Image* IBI;
+ FX_DWORD WI, HI;
+ int32_t IDS;
+ FX_BOOL RI;
+ int32_t RDWI, RDHI, RDXI, RDYI;
+ CJBig2_Image* IBOI;
+ FX_DWORD WOI, HOI;
+ FX_BOOL bFirst;
+ FX_DWORD nTmp;
+ int32_t nVal, nBits;
+ std::unique_ptr<CJBig2_HuffmanDecoder> pHuffmanDecoder(
+ new CJBig2_HuffmanDecoder(pStream));
+ std::unique_ptr<CJBig2_Image> SBREG(new CJBig2_Image(SBW, SBH));
+ SBREG->fill(SBDEFPIXEL);
+ if (pHuffmanDecoder->decodeAValue(SBHUFFDT, &STRIPT) != 0)
+ return nullptr;
+
+ STRIPT *= SBSTRIPS;
+ STRIPT = -STRIPT;
+ FIRSTS = 0;
+ NINSTANCES = 0;
+ while (NINSTANCES < SBNUMINSTANCES) {
+ if (pHuffmanDecoder->decodeAValue(SBHUFFDT, &DT) != 0)
+ return nullptr;
+
+ DT *= SBSTRIPS;
+ STRIPT = STRIPT + DT;
+ bFirst = TRUE;
+ for (;;) {
+ if (bFirst) {
+ if (pHuffmanDecoder->decodeAValue(SBHUFFFS, &DFS) != 0)
+ return nullptr;
+
+ FIRSTS = FIRSTS + DFS;
+ CURS = FIRSTS;
+ bFirst = FALSE;
+ } else {
+ nVal = pHuffmanDecoder->decodeAValue(SBHUFFDS, &IDS);
+ if (nVal == JBIG2_OOB) {
+ break;
+ } else if (nVal != 0) {
+ return nullptr;
+ } else {
+ CURS = CURS + IDS + SBDSOFFSET;
+ }
+ }
+ uint8_t CURT = 0;
+ if (SBSTRIPS != 1) {
+ nTmp = 1;
+ while ((FX_DWORD)(1 << nTmp) < SBSTRIPS) {
+ nTmp++;
+ }
+ if (pStream->readNBits(nTmp, &nVal) != 0)
+ return nullptr;
+
+ CURT = nVal;
+ }
+ TI = STRIPT + CURT;
+ nVal = 0;
+ nBits = 0;
+ FX_DWORD IDI;
+ for (;;) {
+ if (pStream->read1Bit(&nTmp) != 0)
+ return nullptr;
+
+ nVal = (nVal << 1) | nTmp;
+ nBits++;
+ for (IDI = 0; IDI < SBNUMSYMS; IDI++) {
+ if ((nBits == SBSYMCODES[IDI].codelen) &&
+ (nVal == SBSYMCODES[IDI].code)) {
+ break;
+ }
+ }
+ if (IDI < SBNUMSYMS) {
+ break;
+ }
+ }
+ if (SBREFINE == 0) {
+ RI = 0;
+ } else {
+ if (pStream->read1Bit(&RI) != 0) {
+ return nullptr;
+ }
+ }
+ if (RI == 0) {
+ IBI = SBSYMS[IDI];
+ } else {
+ if ((pHuffmanDecoder->decodeAValue(SBHUFFRDW, &RDWI) != 0) ||
+ (pHuffmanDecoder->decodeAValue(SBHUFFRDH, &RDHI) != 0) ||
+ (pHuffmanDecoder->decodeAValue(SBHUFFRDX, &RDXI) != 0) ||
+ (pHuffmanDecoder->decodeAValue(SBHUFFRDY, &RDYI) != 0) ||
+ (pHuffmanDecoder->decodeAValue(SBHUFFRSIZE, &nVal) != 0)) {
+ return nullptr;
+ }
+ pStream->alignByte();
+ nTmp = pStream->getOffset();
+ IBOI = SBSYMS[IDI];
+ if (!IBOI)
+ return nullptr;
+
+ WOI = IBOI->m_nWidth;
+ HOI = IBOI->m_nHeight;
+ if ((int)(WOI + RDWI) < 0 || (int)(HOI + RDHI) < 0)
+ return nullptr;
+
+ std::unique_ptr<CJBig2_GRRDProc> pGRRD(new CJBig2_GRRDProc());
+ pGRRD->GRW = WOI + RDWI;
+ pGRRD->GRH = HOI + RDHI;
+ pGRRD->GRTEMPLATE = SBRTEMPLATE;
+ pGRRD->GRREFERENCE = IBOI;
+ pGRRD->GRREFERENCEDX = (RDWI >> 2) + RDXI;
+ pGRRD->GRREFERENCEDY = (RDHI >> 2) + RDYI;
+ pGRRD->TPGRON = 0;
+ pGRRD->GRAT[0] = SBRAT[0];
+ pGRRD->GRAT[1] = SBRAT[1];
+ pGRRD->GRAT[2] = SBRAT[2];
+ pGRRD->GRAT[3] = SBRAT[3];
+
+ {
+ std::unique_ptr<CJBig2_ArithDecoder> pArithDecoder(
+ new CJBig2_ArithDecoder(pStream));
+ IBI = pGRRD->decode(pArithDecoder.get(), grContext);
+ if (!IBI)
+ return nullptr;
+ }
+
+ pStream->alignByte();
+ pStream->offset(2);
+ if ((FX_DWORD)nVal != (pStream->getOffset() - nTmp)) {
+ delete IBI;
+ return nullptr;
+ }
+ }
+ if (!IBI) {
+ continue;
+ }
+ WI = IBI->m_nWidth;
+ HI = IBI->m_nHeight;
+ if (TRANSPOSED == 0 && ((REFCORNER == JBIG2_CORNER_TOPRIGHT) ||
+ (REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) {
+ CURS = CURS + WI - 1;
+ } else if (TRANSPOSED == 1 && ((REFCORNER == JBIG2_CORNER_BOTTOMLEFT) ||
+ (REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) {
+ CURS = CURS + HI - 1;
+ }
+ SI = CURS;
+ if (TRANSPOSED == 0) {
+ switch (REFCORNER) {
+ case JBIG2_CORNER_TOPLEFT:
+ SBREG->composeFrom(SI, TI, IBI, SBCOMBOP);
+ break;
+ case JBIG2_CORNER_TOPRIGHT:
+ SBREG->composeFrom(SI - WI + 1, TI, IBI, SBCOMBOP);
+ break;
+ case JBIG2_CORNER_BOTTOMLEFT:
+ SBREG->composeFrom(SI, TI - HI + 1, IBI, SBCOMBOP);
+ break;
+ case JBIG2_CORNER_BOTTOMRIGHT:
+ SBREG->composeFrom(SI - WI + 1, TI - HI + 1, IBI, SBCOMBOP);
+ break;
+ }
+ } else {
+ switch (REFCORNER) {
+ case JBIG2_CORNER_TOPLEFT:
+ SBREG->composeFrom(TI, SI, IBI, SBCOMBOP);
+ break;
+ case JBIG2_CORNER_TOPRIGHT:
+ SBREG->composeFrom(TI - WI + 1, SI, IBI, SBCOMBOP);
+ break;
+ case JBIG2_CORNER_BOTTOMLEFT:
+ SBREG->composeFrom(TI, SI - HI + 1, IBI, SBCOMBOP);
+ break;
+ case JBIG2_CORNER_BOTTOMRIGHT:
+ SBREG->composeFrom(TI - WI + 1, SI - HI + 1, IBI, SBCOMBOP);
+ break;
+ }
+ }
+ if (RI != 0) {
+ delete IBI;
+ }
+ if (TRANSPOSED == 0 && ((REFCORNER == JBIG2_CORNER_TOPLEFT) ||
+ (REFCORNER == JBIG2_CORNER_BOTTOMLEFT))) {
+ CURS = CURS + WI - 1;
+ } else if (TRANSPOSED == 1 && ((REFCORNER == JBIG2_CORNER_TOPLEFT) ||
+ (REFCORNER == JBIG2_CORNER_TOPRIGHT))) {
+ CURS = CURS + HI - 1;
+ }
+ NINSTANCES = NINSTANCES + 1;
+ }
+ }
+ return SBREG.release();
+}
+
+CJBig2_Image* CJBig2_TRDProc::decode_Arith(CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* grContext,
+ JBig2IntDecoderState* pIDS) {
+ std::unique_ptr<CJBig2_ArithIntDecoder> IADT;
+ std::unique_ptr<CJBig2_ArithIntDecoder> IAFS;
+ std::unique_ptr<CJBig2_ArithIntDecoder> IADS;
+ std::unique_ptr<CJBig2_ArithIntDecoder> IAIT;
+ std::unique_ptr<CJBig2_ArithIntDecoder> IARI;
+ std::unique_ptr<CJBig2_ArithIntDecoder> IARDW;
+ std::unique_ptr<CJBig2_ArithIntDecoder> IARDH;
+ std::unique_ptr<CJBig2_ArithIntDecoder> IARDX;
+ std::unique_ptr<CJBig2_ArithIntDecoder> IARDY;
+ std::unique_ptr<CJBig2_ArithIaidDecoder> IAID;
+ CJBig2_ArithIntDecoder* pIADT;
+ CJBig2_ArithIntDecoder* pIAFS;
+ CJBig2_ArithIntDecoder* pIADS;
+ CJBig2_ArithIntDecoder* pIAIT;
+ CJBig2_ArithIntDecoder* pIARI;
+ CJBig2_ArithIntDecoder* pIARDW;
+ CJBig2_ArithIntDecoder* pIARDH;
+ CJBig2_ArithIntDecoder* pIARDX;
+ CJBig2_ArithIntDecoder* pIARDY;
+ CJBig2_ArithIaidDecoder* pIAID;
+ if (pIDS) {
+ pIADT = pIDS->IADT;
+ pIAFS = pIDS->IAFS;
+ pIADS = pIDS->IADS;
+ pIAIT = pIDS->IAIT;
+ pIARI = pIDS->IARI;
+ pIARDW = pIDS->IARDW;
+ pIARDH = pIDS->IARDH;
+ pIARDX = pIDS->IARDX;
+ pIARDY = pIDS->IARDY;
+ pIAID = pIDS->IAID;
+ } else {
+ IADT.reset(new CJBig2_ArithIntDecoder());
+ IAFS.reset(new CJBig2_ArithIntDecoder());
+ IADS.reset(new CJBig2_ArithIntDecoder());
+ IAIT.reset(new CJBig2_ArithIntDecoder());
+ IARI.reset(new CJBig2_ArithIntDecoder());
+ IARDW.reset(new CJBig2_ArithIntDecoder());
+ IARDH.reset(new CJBig2_ArithIntDecoder());
+ IARDX.reset(new CJBig2_ArithIntDecoder());
+ IARDY.reset(new CJBig2_ArithIntDecoder());
+ IAID.reset(new CJBig2_ArithIaidDecoder(SBSYMCODELEN));
+ pIADT = IADT.get();
+ pIAFS = IAFS.get();
+ pIADS = IADS.get();
+ pIAIT = IAIT.get();
+ pIARI = IARI.get();
+ pIARDW = IARDW.get();
+ pIARDH = IARDH.get();
+ pIARDX = IARDX.get();
+ pIARDY = IARDY.get();
+ pIAID = IAID.get();
+ }
+ std::unique_ptr<CJBig2_Image> SBREG(new CJBig2_Image(SBW, SBH));
+ SBREG->fill(SBDEFPIXEL);
+ int32_t STRIPT;
+ pIADT->decode(pArithDecoder, &STRIPT);
+ STRIPT *= SBSTRIPS;
+ STRIPT = -STRIPT;
+ int32_t FIRSTS = 0;
+ FX_DWORD NINSTANCES = 0;
+ while (NINSTANCES < SBNUMINSTANCES) {
+ int32_t CURS;
+ int32_t DT;
+ pIADT->decode(pArithDecoder, &DT);
+ DT *= SBSTRIPS;
+ STRIPT += DT;
+ bool bFirst = true;
+ for (;;) {
+ if (bFirst) {
+ int32_t DFS;
+ pIAFS->decode(pArithDecoder, &DFS);
+ FIRSTS += DFS;
+ CURS = FIRSTS;
+ bFirst = false;
+ } else {
+ int32_t IDS;
+ if (!pIADS->decode(pArithDecoder, &IDS))
+ break;
+ CURS += IDS + SBDSOFFSET;
+ }
+ if (NINSTANCES >= SBNUMINSTANCES) {
+ break;
+ }
+ int CURT = 0;
+ if (SBSTRIPS != 1)
+ pIAIT->decode(pArithDecoder, &CURT);
+
+ int32_t TI = STRIPT + CURT;
+ FX_DWORD IDI;
+ pIAID->decode(pArithDecoder, &IDI);
+ if (IDI >= SBNUMSYMS)
+ return nullptr;
+
+ int RI;
+ if (SBREFINE == 0)
+ RI = 0;
+ else
+ pIARI->decode(pArithDecoder, &RI);
+
+ std::unique_ptr<CJBig2_Image> IBI;
+ CJBig2_Image* pIBI;
+ if (RI == 0) {
+ pIBI = SBSYMS[IDI];
+ } else {
+ int32_t RDWI;
+ int32_t RDHI;
+ int32_t RDXI;
+ int32_t RDYI;
+ pIARDW->decode(pArithDecoder, &RDWI);
+ pIARDH->decode(pArithDecoder, &RDHI);
+ pIARDX->decode(pArithDecoder, &RDXI);
+ pIARDY->decode(pArithDecoder, &RDYI);
+ CJBig2_Image* IBOI = SBSYMS[IDI];
+ FX_DWORD WOI = IBOI->m_nWidth;
+ FX_DWORD HOI = IBOI->m_nHeight;
+ if ((int)(WOI + RDWI) < 0 || (int)(HOI + RDHI) < 0) {
+ return nullptr;
+ }
+ std::unique_ptr<CJBig2_GRRDProc> pGRRD(new CJBig2_GRRDProc());
+ pGRRD->GRW = WOI + RDWI;
+ pGRRD->GRH = HOI + RDHI;
+ pGRRD->GRTEMPLATE = SBRTEMPLATE;
+ pGRRD->GRREFERENCE = IBOI;
+ pGRRD->GRREFERENCEDX = (RDWI >> 1) + RDXI;
+ pGRRD->GRREFERENCEDY = (RDHI >> 1) + RDYI;
+ pGRRD->TPGRON = 0;
+ pGRRD->GRAT[0] = SBRAT[0];
+ pGRRD->GRAT[1] = SBRAT[1];
+ pGRRD->GRAT[2] = SBRAT[2];
+ pGRRD->GRAT[3] = SBRAT[3];
+ IBI.reset(pGRRD->decode(pArithDecoder, grContext));
+ pIBI = IBI.get();
+ }
+ if (!pIBI)
+ return nullptr;
+
+ FX_DWORD WI = pIBI->m_nWidth;
+ FX_DWORD HI = pIBI->m_nHeight;
+ if (TRANSPOSED == 0 && ((REFCORNER == JBIG2_CORNER_TOPRIGHT) ||
+ (REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) {
+ CURS += WI - 1;
+ } else if (TRANSPOSED == 1 && ((REFCORNER == JBIG2_CORNER_BOTTOMLEFT) ||
+ (REFCORNER == JBIG2_CORNER_BOTTOMRIGHT))) {
+ CURS += HI - 1;
+ }
+ int32_t SI = CURS;
+ if (TRANSPOSED == 0) {
+ switch (REFCORNER) {
+ case JBIG2_CORNER_TOPLEFT:
+ SBREG->composeFrom(SI, TI, pIBI, SBCOMBOP);
+ break;
+ case JBIG2_CORNER_TOPRIGHT:
+ SBREG->composeFrom(SI - WI + 1, TI, pIBI, SBCOMBOP);
+ break;
+ case JBIG2_CORNER_BOTTOMLEFT:
+ SBREG->composeFrom(SI, TI - HI + 1, pIBI, SBCOMBOP);
+ break;
+ case JBIG2_CORNER_BOTTOMRIGHT:
+ SBREG->composeFrom(SI - WI + 1, TI - HI + 1, pIBI, SBCOMBOP);
+ break;
+ }
+ } else {
+ switch (REFCORNER) {
+ case JBIG2_CORNER_TOPLEFT:
+ SBREG->composeFrom(TI, SI, pIBI, SBCOMBOP);
+ break;
+ case JBIG2_CORNER_TOPRIGHT:
+ SBREG->composeFrom(TI - WI + 1, SI, pIBI, SBCOMBOP);
+ break;
+ case JBIG2_CORNER_BOTTOMLEFT:
+ SBREG->composeFrom(TI, SI - HI + 1, pIBI, SBCOMBOP);
+ break;
+ case JBIG2_CORNER_BOTTOMRIGHT:
+ SBREG->composeFrom(TI - WI + 1, SI - HI + 1, pIBI, SBCOMBOP);
+ break;
+ }
+ }
+ if (TRANSPOSED == 0 && ((REFCORNER == JBIG2_CORNER_TOPLEFT) ||
+ (REFCORNER == JBIG2_CORNER_BOTTOMLEFT))) {
+ CURS += WI - 1;
+ } else if (TRANSPOSED == 1 && ((REFCORNER == JBIG2_CORNER_TOPLEFT) ||
+ (REFCORNER == JBIG2_CORNER_TOPRIGHT))) {
+ CURS += HI - 1;
+ }
+ ++NINSTANCES;
+ }
+ }
+ return SBREG.release();
+}
diff --git a/core/fxcodec/jbig2/JBig2_TrdProc.h b/core/fxcodec/jbig2/JBig2_TrdProc.h
new file mode 100644
index 0000000000..090e564726
--- /dev/null
+++ b/core/fxcodec/jbig2/JBig2_TrdProc.h
@@ -0,0 +1,82 @@
+// Copyright 2015 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.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef CORE_FXCODEC_JBIG2_JBIG2_TRDPROC_H_
+#define CORE_FXCODEC_JBIG2_JBIG2_TRDPROC_H_
+
+#include "core/fxcodec/jbig2/JBig2_Image.h"
+#include "core/include/fxcrt/fx_system.h"
+
+class CJBig2_ArithDecoder;
+class CJBig2_ArithIaidDecoder;
+class CJBig2_ArithIntDecoder;
+class CJBig2_BitStream;
+class CJBig2_HuffmanTable;
+struct JBig2ArithCtx;
+struct JBig2HuffmanCode;
+
+struct JBig2IntDecoderState {
+ CJBig2_ArithIntDecoder* IADT;
+ CJBig2_ArithIntDecoder* IAFS;
+ CJBig2_ArithIntDecoder* IADS;
+ CJBig2_ArithIntDecoder* IAIT;
+ CJBig2_ArithIntDecoder* IARI;
+ CJBig2_ArithIntDecoder* IARDW;
+ CJBig2_ArithIntDecoder* IARDH;
+ CJBig2_ArithIntDecoder* IARDX;
+ CJBig2_ArithIntDecoder* IARDY;
+ CJBig2_ArithIaidDecoder* IAID;
+};
+
+enum JBig2Corner {
+ JBIG2_CORNER_BOTTOMLEFT = 0,
+ JBIG2_CORNER_TOPLEFT = 1,
+ JBIG2_CORNER_BOTTOMRIGHT = 2,
+ JBIG2_CORNER_TOPRIGHT = 3
+};
+
+class CJBig2_TRDProc {
+ public:
+ CJBig2_Image* decode_Huffman(CJBig2_BitStream* pStream,
+ JBig2ArithCtx* grContext);
+
+ CJBig2_Image* decode_Arith(CJBig2_ArithDecoder* pArithDecoder,
+ JBig2ArithCtx* grContext,
+ JBig2IntDecoderState* pIDS);
+
+ public:
+ FX_BOOL SBHUFF;
+ FX_BOOL SBREFINE;
+ FX_DWORD SBW;
+ FX_DWORD SBH;
+ FX_DWORD SBNUMINSTANCES;
+ FX_DWORD SBSTRIPS;
+ FX_DWORD SBNUMSYMS;
+
+ JBig2HuffmanCode* SBSYMCODES;
+ uint8_t SBSYMCODELEN;
+
+ CJBig2_Image** SBSYMS;
+ FX_BOOL SBDEFPIXEL;
+
+ JBig2ComposeOp SBCOMBOP;
+ FX_BOOL TRANSPOSED;
+
+ JBig2Corner REFCORNER;
+ int8_t SBDSOFFSET;
+ CJBig2_HuffmanTable* SBHUFFFS;
+ CJBig2_HuffmanTable* SBHUFFDS;
+ CJBig2_HuffmanTable* SBHUFFDT;
+ CJBig2_HuffmanTable* SBHUFFRDW;
+ CJBig2_HuffmanTable* SBHUFFRDH;
+ CJBig2_HuffmanTable* SBHUFFRDX;
+ CJBig2_HuffmanTable* SBHUFFRDY;
+ CJBig2_HuffmanTable* SBHUFFRSIZE;
+ FX_BOOL SBRTEMPLATE;
+ int8_t SBRAT[4];
+};
+
+#endif // CORE_FXCODEC_JBIG2_JBIG2_TRDPROC_H_