blob: 8aaebf46a211ec06a963eef200a15479b93dbd40 [file] [log] [blame]
// 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;
}