// 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 #include #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(HTLOW); const int high = static_cast(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 LENCOUNT(LENMAX + 1); for (FX_DWORD i = 0; i < NTEMP; ++i) LENCOUNT[PREFLEN[i]]++; LENCOUNT[0] = 0; std::vector 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; }