blob: 5b9cae6d60f3e55810ffa35a8b38db841805909b [file] [log] [blame] [edit]
//========================================================================
//
// JArithmeticDecoder.cc
//
// Copyright 2002-2004 Glyph & Cog, LLC
//
//========================================================================
//========================================================================
//
// Modified under the Poppler project - http://poppler.freedesktop.org
//
// All changes made under the Poppler project to this file are licensed
// under GPL version 2 or later
//
// Copyright (C) 2019 Volker Krause <vkrause@kde.org>
// Copyright (C) 2020 Even Rouault <even.rouault@spatialys.com>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
//
//========================================================================
#include <config.h>
#include "Object.h"
#include "Stream.h"
#include "JArithmeticDecoder.h"
//------------------------------------------------------------------------
// JArithmeticDecoderStates
//------------------------------------------------------------------------
JArithmeticDecoderStats::JArithmeticDecoderStats(int contextSizeA)
{
contextSize = contextSizeA;
cxTab = (unsigned char *)gmallocn_checkoverflow(contextSize, sizeof(unsigned char));
if (cxTab) {
reset();
}
}
JArithmeticDecoderStats::~JArithmeticDecoderStats()
{
gfree(cxTab);
}
JArithmeticDecoderStats *JArithmeticDecoderStats::copy()
{
JArithmeticDecoderStats *stats;
stats = new JArithmeticDecoderStats(contextSize);
memcpy(stats->cxTab, cxTab, contextSize);
return stats;
}
void JArithmeticDecoderStats::reset()
{
memset(cxTab, 0, contextSize);
}
void JArithmeticDecoderStats::copyFrom(JArithmeticDecoderStats *stats)
{
memcpy(cxTab, stats->cxTab, contextSize);
}
void JArithmeticDecoderStats::setEntry(unsigned int cx, int i, int mps)
{
cxTab[cx] = (i << 1) + mps;
}
//------------------------------------------------------------------------
// JArithmeticDecoder
//------------------------------------------------------------------------
unsigned const int JArithmeticDecoder::qeTab[47] = { 0x56010000, 0x34010000, 0x18010000, 0x0AC10000, 0x05210000, 0x02210000, 0x56010000, 0x54010000, 0x48010000, 0x38010000, 0x30010000, 0x24010000,
0x1C010000, 0x16010000, 0x56010000, 0x54010000, 0x51010000, 0x48010000, 0x38010000, 0x34010000, 0x30010000, 0x28010000, 0x24010000, 0x22010000,
0x1C010000, 0x18010000, 0x16010000, 0x14010000, 0x12010000, 0x11010000, 0x0AC10000, 0x09C10000, 0x08A10000, 0x05210000, 0x04410000, 0x02A10000,
0x02210000, 0x01410000, 0x01110000, 0x00850000, 0x00490000, 0x00250000, 0x00150000, 0x00090000, 0x00050000, 0x00010000, 0x56010000 };
const int JArithmeticDecoder::nmpsTab[47] = { 1, 2, 3, 4, 5, 38, 7, 8, 9, 10, 11, 12, 13, 29, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 45, 46 };
const int JArithmeticDecoder::nlpsTab[47] = { 1, 6, 9, 12, 29, 33, 6, 14, 14, 14, 17, 18, 20, 21, 14, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 46 };
const int JArithmeticDecoder::switchTab[47] = { 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
JArithmeticDecoder::JArithmeticDecoder()
{
str = nullptr;
dataLen = 0;
limitStream = false;
nBytesRead = 0;
}
inline unsigned int JArithmeticDecoder::readByte()
{
if (limitStream) {
--dataLen;
if (dataLen < 0) {
return 0xff;
}
}
++nBytesRead;
return (unsigned int)str->getChar() & 0xff;
}
JArithmeticDecoder::~JArithmeticDecoder()
{
cleanup();
}
void JArithmeticDecoder::start()
{
buf0 = readByte();
buf1 = readByte();
// INITDEC
c = (buf0 ^ 0xff) << 16;
byteIn();
c <<= 7;
ct -= 7;
a = 0x80000000;
}
void JArithmeticDecoder::restart(int dataLenA)
{
unsigned int cAdd;
bool prevFF;
int k, nBits;
if (dataLen >= 0) {
dataLen = dataLenA;
} else if (dataLen == -1) {
dataLen = dataLenA;
buf1 = readByte();
} else {
k = (-dataLen - 1) * 8 - ct;
dataLen = dataLenA;
cAdd = 0;
prevFF = false;
while (k > 0) {
buf0 = readByte();
if (prevFF) {
cAdd += 0xfe00 - (buf0 << 9);
nBits = 7;
} else {
cAdd += 0xff00 - (buf0 << 8);
nBits = 8;
}
prevFF = buf0 == 0xff;
if (k > nBits) {
cAdd <<= nBits;
k -= nBits;
} else {
cAdd <<= k;
ct = nBits - k;
k = 0;
}
}
c += cAdd;
buf1 = readByte();
}
}
void JArithmeticDecoder::cleanup()
{
if (limitStream) {
while (dataLen > 0) {
buf0 = buf1;
buf1 = readByte();
}
}
}
int JArithmeticDecoder::decodeBit(unsigned int context, JArithmeticDecoderStats *stats)
{
int bit;
unsigned int qe;
int iCX, mpsCX;
iCX = stats->cxTab[context] >> 1;
mpsCX = stats->cxTab[context] & 1;
qe = qeTab[iCX];
a -= qe;
if (c < a) {
if (a & 0x80000000) {
bit = mpsCX;
} else {
// MPS_EXCHANGE
if (a < qe) {
bit = 1 - mpsCX;
if (switchTab[iCX]) {
stats->cxTab[context] = (nlpsTab[iCX] << 1) | (1 - mpsCX);
} else {
stats->cxTab[context] = (nlpsTab[iCX] << 1) | mpsCX;
}
} else {
bit = mpsCX;
stats->cxTab[context] = (nmpsTab[iCX] << 1) | mpsCX;
}
// RENORMD
do {
if (ct == 0) {
byteIn();
}
a <<= 1;
c <<= 1;
--ct;
} while (!(a & 0x80000000));
}
} else {
c -= a;
// LPS_EXCHANGE
if (a < qe) {
bit = mpsCX;
stats->cxTab[context] = (nmpsTab[iCX] << 1) | mpsCX;
} else {
bit = 1 - mpsCX;
if (switchTab[iCX]) {
stats->cxTab[context] = (nlpsTab[iCX] << 1) | (1 - mpsCX);
} else {
stats->cxTab[context] = (nlpsTab[iCX] << 1) | mpsCX;
}
}
a = qe;
// RENORMD
do {
if (ct == 0) {
byteIn();
}
a <<= 1;
c <<= 1;
--ct;
} while (!(a & 0x80000000));
}
return bit;
}
int JArithmeticDecoder::decodeByte(unsigned int context, JArithmeticDecoderStats *stats)
{
int byte;
int i;
byte = 0;
for (i = 0; i < 8; ++i) {
byte = (byte << 1) | decodeBit(context, stats);
}
return byte;
}
bool JArithmeticDecoder::decodeInt(int *x, JArithmeticDecoderStats *stats)
{
int s;
unsigned int v;
int i;
prev = 1;
s = decodeIntBit(stats);
if (decodeIntBit(stats)) {
if (decodeIntBit(stats)) {
if (decodeIntBit(stats)) {
if (decodeIntBit(stats)) {
if (decodeIntBit(stats)) {
v = 0;
for (i = 0; i < 32; ++i) {
v = (v << 1) | decodeIntBit(stats);
}
v += 4436;
} else {
v = 0;
for (i = 0; i < 12; ++i) {
v = (v << 1) | decodeIntBit(stats);
}
v += 340;
}
} else {
v = 0;
for (i = 0; i < 8; ++i) {
v = (v << 1) | decodeIntBit(stats);
}
v += 84;
}
} else {
v = 0;
for (i = 0; i < 6; ++i) {
v = (v << 1) | decodeIntBit(stats);
}
v += 20;
}
} else {
v = decodeIntBit(stats);
v = (v << 1) | decodeIntBit(stats);
v = (v << 1) | decodeIntBit(stats);
v = (v << 1) | decodeIntBit(stats);
v += 4;
}
} else {
v = decodeIntBit(stats);
v = (v << 1) | decodeIntBit(stats);
}
if (s) {
if (v == 0) {
return false;
}
*x = -(int)v;
} else {
*x = (int)v;
}
return true;
}
int JArithmeticDecoder::decodeIntBit(JArithmeticDecoderStats *stats)
{
int bit;
bit = decodeBit(prev, stats);
if (prev < 0x100) {
prev = (prev << 1) | bit;
} else {
prev = (((prev << 1) | bit) & 0x1ff) | 0x100;
}
return bit;
}
unsigned int JArithmeticDecoder::decodeIAID(unsigned int codeLen, JArithmeticDecoderStats *stats)
{
unsigned int i;
int bit;
prev = 1;
for (i = 0; i < codeLen; ++i) {
bit = decodeBit(prev, stats);
prev = (prev << 1) | bit;
}
return prev - (1 << codeLen);
}
void JArithmeticDecoder::byteIn()
{
if (buf0 == 0xff) {
if (buf1 > 0x8f) {
if (limitStream) {
buf0 = buf1;
buf1 = readByte();
c = c + 0xff00 - (buf0 << 8);
}
ct = 8;
} else {
buf0 = buf1;
buf1 = readByte();
c = c + 0xfe00 - (buf0 << 9);
ct = 7;
}
} else {
buf0 = buf1;
buf1 = readByte();
c = c + 0xff00 - (buf0 << 8);
ct = 8;
}
}