UNPKG

@syncfusion/ej2-pdf

Version:

Feature-rich JavaScript PDF library with built-in support for loading and manipulating PDF document.

238 lines (237 loc) 7.63 kB
import { _toUnsigned, _toSigned16 } from './../utils'; /** * Implements a Huffman decoding table with fast lookup and tree traversal. * * @private */ var _HuffmanTree = /** @class */ (function () { function _HuffmanTree() { } /** * Loads the code length array and builds the decoding structures. * * @private * @param {number[]} code Code length array. * @returns {void} nothing. */ _HuffmanTree.prototype._load = function (code) { this._clArray = code; this._initialize(); }; /** * Loads the predefined length or distance tree and builds the decoding structures. * * @private * @param {boolean} isLengthTree Whether the tree is a literal/length tree. * @returns {void} nothing. */ _HuffmanTree.prototype._loadTree = function (isLengthTree) { this._clArray = isLengthTree ? this._getLengthTree() : this._getDepthTree(); this._initialize(); }; /** * Initializes table size and bit mask and creates the primary decode table. * * @private * @returns {void} nothing. */ _HuffmanTree.prototype._initialize = function () { if (this._clArray.length === _HuffmanTree._maxLengthTree) { this._tBits = 9; } else { this._tBits = 7; } this._tMask = (1 << this._tBits) - 1; this._createTable(); }; /** * Returns the fixed Huffman code lengths for the literal/length alphabet. * * @private * @returns {number[]} lengthTree. */ _HuffmanTree.prototype._getLengthTree = function () { var lTree = Array(_HuffmanTree._maxLengthTree).fill(0); for (var i = 0; i <= 143; i++) { lTree[i] = _toUnsigned(8, 8); } for (var i = 144; i <= 255; i++) { lTree[i] = _toUnsigned(9, 8); } for (var i = 256; i <= 279; i++) { lTree[i] = _toUnsigned(7, 8); } for (var i = 280; i <= 287; i++) { lTree[i] = _toUnsigned(8, 8); } return lTree; }; /** * Returns the fixed Huffman code lengths for the distance alphabet. * * @private * @returns {number[]} depthTree. */ _HuffmanTree.prototype._getDepthTree = function () { return Array(_HuffmanTree._maxDepthTree).fill(5); }; /** * Computes canonical Huffman codes for symbols based on code lengths. * * @private * @returns {number[]} canonicalCodes. */ _HuffmanTree.prototype._calculateHashCode = function () { var bit = Array(17).fill(0); for (var i = 0; i < this._clArray.length; i++) { bit[this._clArray[i]]++; } bit[0] = 0; var next = Array(17).fill(0); var temp = 0; for (var bits = 1; bits <= 16; bits++) { temp = (temp + bit[bits - 1]) << 1; next[bits] = temp; } var code = Array(_HuffmanTree._maxLengthTree).fill(0); for (var i = 0; i < this._clArray.length; i++) { var len = this._clArray[i]; if (len > 0) { code[i] = this._bitReverse(next[len], len); next[len]++; } } return code; }; /** * Reverses the lowest `length` bits of the given value. * * @private * @param {number} code Code value. * @param {number} length Number of bits to reverse. * @returns {number} reversedCode. */ _HuffmanTree.prototype._bitReverse = function (code, length) { var newcode = 0; do { newcode |= code & 1; newcode <<= 1; code >>= 1; } while (--length > 0); return newcode >> 1; }; /** * Builds the fast lookup table and associated tree nodes for Huffman decoding. * * @private * @returns {void} nothing. */ _HuffmanTree.prototype._createTable = function () { var codeArray = this._calculateHashCode(); this._table = Array(1 << this._tBits).fill(0); this._left = Array(2 * this._clArray.length).fill(0); this._right = Array(2 * this._clArray.length).fill(0); var avail = _toSigned16(this._clArray.length); for (var ch = 0; ch < this._clArray.length; ch++) { var len = this._clArray[ch]; if (len > 0) { var start = codeArray[ch]; if (len <= this._tBits) { var i = 1 << len; if (start >= i) { throw new Error('Invalid Data.'); } var l = 1 << (this._tBits - len); for (var j = 0; j < l; j++) { this._table[start] = _toSigned16(ch); start += i; } } else { var ofBits = len - this._tBits; var bitMask = 1 << this._tBits; var index = start & ((1 << this._tBits) - 1); var array = this._table; do { var value = _toSigned16(array[index]); if (value === 0) { array[index] = _toSigned16(-avail); value = _toSigned16(-avail); avail++; } if (value > 0) { throw new Error('Invalid Data.'); } if ((start & bitMask) === 0) { array = this._left; } else { array = this._right; } index = -value; bitMask <<= 1; ofBits--; } while (ofBits !== 0); array[index] = _toSigned16(ch); } } } }; /** * Decodes and returns the next symbol from the input bit buffer. * * @private * @param {_InBuffer} input Bitwise input buffer. * @returns {number} symbol or -1 if insufficient bits. */ _HuffmanTree.prototype._getNextSymbol = function (input) { var bitBuffer = input._load16Bits(); if (input._bInBuffer === 0) { return -1; } var symbol = this._table[bitBuffer & this._tMask]; if (symbol < 0) { var mask = _toUnsigned((1 << this._tBits), 32); do { symbol = -symbol; if ((bitBuffer & mask) === 0) { symbol = this._left[symbol]; } else { symbol = this._right[symbol]; } mask <<= 1; } while (symbol < 0); } var codeLength = this._clArray[symbol]; if (codeLength <= 0) { throw new Error('Invalid Data.'); } if (codeLength > input._bInBuffer) { return -1; } input._skipBits(codeLength); return symbol; }; /** * Maximum number of codes in the length/literal tree. * * @private */ _HuffmanTree._maxLengthTree = 288; /** * Maximum tree depth supported. * * @private */ _HuffmanTree._maxDepthTree = 32; /** * Number of code length codes. * * @private */ _HuffmanTree._nCLength = 19; return _HuffmanTree; }()); export { _HuffmanTree };