| // 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 "JBig2_HuffmanTable.h" |
| |
| #include <string.h> |
| |
| #include <vector> |
| |
| #include "JBig2_BitStream.h" |
| #include "JBig2_Define.h" |
| #include "core/include/fxcrt/fx_memory.h" |
| |
| CJBig2_HuffmanTable::CJBig2_HuffmanTable(const JBig2TableLine* pTable, |
| int nLines, |
| FX_BOOL bHTOOB) { |
| init(); |
| m_bOK = parseFromStandardTable(pTable, nLines, bHTOOB); |
| } |
| |
| CJBig2_HuffmanTable::CJBig2_HuffmanTable(CJBig2_BitStream* pStream) { |
| init(); |
| m_bOK = parseFromCodedBuffer(pStream); |
| } |
| |
| CJBig2_HuffmanTable::~CJBig2_HuffmanTable() { |
| FX_Free(CODES); |
| FX_Free(PREFLEN); |
| FX_Free(RANGELEN); |
| FX_Free(RANGELOW); |
| } |
| void CJBig2_HuffmanTable::init() { |
| HTOOB = FALSE; |
| NTEMP = 0; |
| CODES = nullptr; |
| PREFLEN = nullptr; |
| RANGELEN = nullptr; |
| RANGELOW = nullptr; |
| } |
| int CJBig2_HuffmanTable::parseFromStandardTable(const JBig2TableLine* pTable, |
| int nLines, |
| FX_BOOL bHTOOB) { |
| HTOOB = bHTOOB; |
| NTEMP = nLines; |
| CODES = FX_Alloc(int, NTEMP); |
| PREFLEN = FX_Alloc(int, NTEMP); |
| RANGELEN = FX_Alloc(int, NTEMP); |
| RANGELOW = FX_Alloc(int, NTEMP); |
| int LENMAX = 0; |
| for (FX_DWORD i = 0; i < NTEMP; ++i) { |
| PREFLEN[i] = pTable[i].PREFLEN; |
| RANGELEN[i] = pTable[i].RANDELEN; |
| RANGELOW[i] = pTable[i].RANGELOW; |
| if (PREFLEN[i] > LENMAX) { |
| LENMAX = PREFLEN[i]; |
| } |
| } |
| int* LENCOUNT = FX_Alloc(int, LENMAX + 1); |
| JBIG2_memset(LENCOUNT, 0, sizeof(int) * (LENMAX + 1)); |
| int* FIRSTCODE = FX_Alloc(int, LENMAX + 1); |
| for (FX_DWORD i = 0; i < NTEMP; ++i) |
| ++LENCOUNT[PREFLEN[i]]; |
| |
| int CURLEN = 1; |
| FIRSTCODE[0] = 0; |
| LENCOUNT[0] = 0; |
| while (CURLEN <= LENMAX) { |
| FIRSTCODE[CURLEN] = (FIRSTCODE[CURLEN - 1] + LENCOUNT[CURLEN - 1]) << 1; |
| int CURCODE = FIRSTCODE[CURLEN]; |
| FX_DWORD 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); |
| return 1; |
| } |
| |
| #define HT_CHECK_MEMORY_ADJUST \ |
| if (NTEMP >= nSize) { \ |
| nSize += 16; \ |
| PREFLEN = FX_Realloc(int, PREFLEN, nSize); \ |
| RANGELEN = FX_Realloc(int, RANGELEN, nSize); \ |
| RANGELOW = FX_Realloc(int, RANGELOW, nSize); \ |
| } |
| int 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; |
| |
| FX_DWORD nSize = 16; |
| PREFLEN = FX_Alloc(int, nSize); |
| RANGELEN = FX_Alloc(int, nSize); |
| RANGELOW = FX_Alloc(int, nSize); |
| int cur_low = low; |
| NTEMP = 0; |
| do { |
| HT_CHECK_MEMORY_ADJUST |
| if ((pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1) || |
| (pStream->readNBits(HTRS, &RANGELEN[NTEMP]) == -1)) { |
| return FALSE; |
| } |
| RANGELOW[NTEMP] = cur_low; |
| cur_low += (1 << RANGELEN[NTEMP]); |
| NTEMP = NTEMP + 1; |
| } while (cur_low < high); |
| HT_CHECK_MEMORY_ADJUST |
| if (pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1) |
| return FALSE; |
| |
| RANGELEN[NTEMP] = 32; |
| RANGELOW[NTEMP] = low - 1; |
| ++NTEMP; |
| HT_CHECK_MEMORY_ADJUST |
| if (pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1) |
| return FALSE; |
| |
| RANGELEN[NTEMP] = 32; |
| RANGELOW[NTEMP] = high; |
| NTEMP = NTEMP + 1; |
| if (HTOOB) { |
| HT_CHECK_MEMORY_ADJUST |
| if (pStream->readNBits(HTPS, &PREFLEN[NTEMP]) == -1) |
| return FALSE; |
| |
| ++NTEMP; |
| } |
| CODES = FX_Alloc(int, NTEMP); |
| int LENMAX = 0; |
| for (FX_DWORD i = 0; i < NTEMP; ++i) |
| LENMAX = std::max(PREFLEN[i], LENMAX); |
| |
| std::vector<int> LENCOUNT(LENMAX + 1); |
| for (FX_DWORD i = 0; i < NTEMP; ++i) |
| LENCOUNT[PREFLEN[i]]++; |
| LENCOUNT[0] = 0; |
| |
| std::vector<int> FIRSTCODE(LENMAX + 1); |
| FIRSTCODE[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++; |
| } |
| } |
| return TRUE; |
| } |