Merge pull request #9887 from Snuffleupagus/rm-Util-inherit
Convert more code in the `/src` folder to use ES6 classes, such that `Util.inherit` can be removed
This commit is contained in:
commit
b56081c5f8
325
src/core/cmap.js
325
src/core/cmap.js
@ -14,8 +14,8 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
CMapCompressionType, FormatError, isString, MissingDataException,
|
||||
unreachable, Util, warn
|
||||
CMapCompressionType, FormatError, isString, MissingDataException, unreachable,
|
||||
warn
|
||||
} from '../shared/util';
|
||||
import { isCmd, isEOF, isName, isStream } from './primitives';
|
||||
import { Lexer } from './parser';
|
||||
@ -194,8 +194,8 @@ var BUILT_IN_CMAPS = [
|
||||
'WP-Symbol'];
|
||||
|
||||
// CMap, not to be confused with TrueType's cmap.
|
||||
var CMap = (function CMapClosure() {
|
||||
function CMap(builtInCMap) {
|
||||
class CMap {
|
||||
constructor(builtInCMap = false) {
|
||||
// Codespace ranges are stored as follows:
|
||||
// [[1BytePairs], [2BytePairs], [3BytePairs], [4BytePairs]]
|
||||
// where nBytePairs are ranges e.g. [low1, high1, low2, high2, ...]
|
||||
@ -211,204 +211,193 @@ var CMap = (function CMapClosure() {
|
||||
this.useCMap = null;
|
||||
this.builtInCMap = builtInCMap;
|
||||
}
|
||||
CMap.prototype = {
|
||||
addCodespaceRange(n, low, high) {
|
||||
this.codespaceRanges[n - 1].push(low, high);
|
||||
this.numCodespaceRanges++;
|
||||
},
|
||||
|
||||
mapCidRange(low, high, dstLow) {
|
||||
while (low <= high) {
|
||||
this._map[low++] = dstLow++;
|
||||
}
|
||||
},
|
||||
addCodespaceRange(n, low, high) {
|
||||
this.codespaceRanges[n - 1].push(low, high);
|
||||
this.numCodespaceRanges++;
|
||||
}
|
||||
|
||||
mapBfRange(low, high, dstLow) {
|
||||
var lastByte = dstLow.length - 1;
|
||||
while (low <= high) {
|
||||
this._map[low++] = dstLow;
|
||||
// Only the last byte has to be incremented.
|
||||
dstLow = dstLow.substr(0, lastByte) +
|
||||
String.fromCharCode(dstLow.charCodeAt(lastByte) + 1);
|
||||
}
|
||||
},
|
||||
mapCidRange(low, high, dstLow) {
|
||||
while (low <= high) {
|
||||
this._map[low++] = dstLow++;
|
||||
}
|
||||
}
|
||||
|
||||
mapBfRangeToArray(low, high, array) {
|
||||
var i = 0, ii = array.length;
|
||||
while (low <= high && i < ii) {
|
||||
this._map[low] = array[i++];
|
||||
++low;
|
||||
}
|
||||
},
|
||||
mapBfRange(low, high, dstLow) {
|
||||
var lastByte = dstLow.length - 1;
|
||||
while (low <= high) {
|
||||
this._map[low++] = dstLow;
|
||||
// Only the last byte has to be incremented.
|
||||
dstLow = dstLow.substr(0, lastByte) +
|
||||
String.fromCharCode(dstLow.charCodeAt(lastByte) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// This is used for both bf and cid chars.
|
||||
mapOne(src, dst) {
|
||||
this._map[src] = dst;
|
||||
},
|
||||
mapBfRangeToArray(low, high, array) {
|
||||
let i = 0, ii = array.length;
|
||||
while (low <= high && i < ii) {
|
||||
this._map[low] = array[i++];
|
||||
++low;
|
||||
}
|
||||
}
|
||||
|
||||
lookup(code) {
|
||||
return this._map[code];
|
||||
},
|
||||
// This is used for both bf and cid chars.
|
||||
mapOne(src, dst) {
|
||||
this._map[src] = dst;
|
||||
}
|
||||
|
||||
contains(code) {
|
||||
return this._map[code] !== undefined;
|
||||
},
|
||||
lookup(code) {
|
||||
return this._map[code];
|
||||
}
|
||||
|
||||
forEach(callback) {
|
||||
// Most maps have fewer than 65536 entries, and for those we use normal
|
||||
// array iteration. But really sparse tables are possible -- e.g. with
|
||||
// indices in the *billions*. For such tables we use for..in, which isn't
|
||||
// ideal because it stringifies the indices for all present elements, but
|
||||
// it does avoid iterating over every undefined entry.
|
||||
let map = this._map;
|
||||
let length = map.length;
|
||||
if (length <= 0x10000) {
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (map[i] !== undefined) {
|
||||
callback(i, map[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (let i in map) {
|
||||
contains(code) {
|
||||
return this._map[code] !== undefined;
|
||||
}
|
||||
|
||||
forEach(callback) {
|
||||
// Most maps have fewer than 65536 entries, and for those we use normal
|
||||
// array iteration. But really sparse tables are possible -- e.g. with
|
||||
// indices in the *billions*. For such tables we use for..in, which isn't
|
||||
// ideal because it stringifies the indices for all present elements, but
|
||||
// it does avoid iterating over every undefined entry.
|
||||
let map = this._map;
|
||||
let length = map.length;
|
||||
if (length <= 0x10000) {
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (map[i] !== undefined) {
|
||||
callback(i, map[i]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
charCodeOf(value) {
|
||||
// `Array.prototype.indexOf` is *extremely* inefficient for arrays which
|
||||
// are both very sparse and very large (see issue8372.pdf).
|
||||
let map = this._map;
|
||||
if (map.length <= 0x10000) {
|
||||
return map.indexOf(value);
|
||||
} else {
|
||||
for (let i in map) {
|
||||
callback(i, map[i]);
|
||||
}
|
||||
for (let charCode in map) {
|
||||
if (map[charCode] === value) {
|
||||
return (charCode | 0);
|
||||
}
|
||||
}
|
||||
|
||||
charCodeOf(value) {
|
||||
// `Array.prototype.indexOf` is *extremely* inefficient for arrays which
|
||||
// are both very sparse and very large (see issue8372.pdf).
|
||||
const map = this._map;
|
||||
if (map.length <= 0x10000) {
|
||||
return map.indexOf(value);
|
||||
}
|
||||
for (let charCode in map) {
|
||||
if (map[charCode] === value) {
|
||||
return (charCode | 0);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
getMap() {
|
||||
return this._map;
|
||||
}
|
||||
|
||||
readCharCode(str, offset, out) {
|
||||
let c = 0;
|
||||
const codespaceRanges = this.codespaceRanges;
|
||||
// 9.7.6.2 CMap Mapping
|
||||
// The code length is at most 4.
|
||||
for (let n = 0, nn = codespaceRanges.length; n < nn; n++) {
|
||||
c = ((c << 8) | str.charCodeAt(offset + n)) >>> 0;
|
||||
// Check each codespace range to see if it falls within.
|
||||
const codespaceRange = codespaceRanges[n];
|
||||
for (let k = 0, kk = codespaceRange.length; k < kk;) {
|
||||
const low = codespaceRange[k++];
|
||||
const high = codespaceRange[k++];
|
||||
if (c >= low && c <= high) {
|
||||
out.charcode = c;
|
||||
out.length = n + 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
},
|
||||
}
|
||||
out.charcode = 0;
|
||||
out.length = 1;
|
||||
}
|
||||
|
||||
getMap() {
|
||||
return this._map;
|
||||
},
|
||||
get length() {
|
||||
return this._map.length;
|
||||
}
|
||||
|
||||
readCharCode(str, offset, out) {
|
||||
var c = 0;
|
||||
var codespaceRanges = this.codespaceRanges;
|
||||
var codespaceRangesLen = this.codespaceRanges.length;
|
||||
// 9.7.6.2 CMap Mapping
|
||||
// The code length is at most 4.
|
||||
for (var n = 0; n < codespaceRangesLen; n++) {
|
||||
c = ((c << 8) | str.charCodeAt(offset + n)) >>> 0;
|
||||
// Check each codespace range to see if it falls within.
|
||||
var codespaceRange = codespaceRanges[n];
|
||||
for (var k = 0, kk = codespaceRange.length; k < kk;) {
|
||||
var low = codespaceRange[k++];
|
||||
var high = codespaceRange[k++];
|
||||
if (c >= low && c <= high) {
|
||||
out.charcode = c;
|
||||
out.length = n + 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
out.charcode = 0;
|
||||
out.length = 1;
|
||||
},
|
||||
|
||||
get length() {
|
||||
return this._map.length;
|
||||
},
|
||||
|
||||
get isIdentityCMap() {
|
||||
if (!(this.name === 'Identity-H' || this.name === 'Identity-V')) {
|
||||
get isIdentityCMap() {
|
||||
if (!(this.name === 'Identity-H' || this.name === 'Identity-V')) {
|
||||
return false;
|
||||
}
|
||||
if (this._map.length !== 0x10000) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0; i < 0x10000; i++) {
|
||||
if (this._map[i] !== i) {
|
||||
return false;
|
||||
}
|
||||
if (this._map.length !== 0x10000) {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0; i < 0x10000; i++) {
|
||||
if (this._map[i] !== i) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
};
|
||||
return CMap;
|
||||
})();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// A special case of CMap, where the _map array implicitly has a length of
|
||||
// 65536 and each element is equal to its index.
|
||||
var IdentityCMap = (function IdentityCMapClosure() {
|
||||
function IdentityCMap(vertical, n) {
|
||||
CMap.call(this);
|
||||
class IdentityCMap extends CMap {
|
||||
constructor(vertical, n) {
|
||||
super();
|
||||
|
||||
this.vertical = vertical;
|
||||
this.addCodespaceRange(n, 0, 0xffff);
|
||||
}
|
||||
Util.inherit(IdentityCMap, CMap, {});
|
||||
|
||||
IdentityCMap.prototype = {
|
||||
addCodespaceRange: CMap.prototype.addCodespaceRange,
|
||||
mapCidRange(low, high, dstLow) {
|
||||
unreachable('should not call mapCidRange');
|
||||
}
|
||||
|
||||
mapCidRange(low, high, dstLow) {
|
||||
unreachable('should not call mapCidRange');
|
||||
},
|
||||
mapBfRange(low, high, dstLow) {
|
||||
unreachable('should not call mapBfRange');
|
||||
}
|
||||
|
||||
mapBfRange(low, high, dstLow) {
|
||||
unreachable('should not call mapBfRange');
|
||||
},
|
||||
mapBfRangeToArray(low, high, array) {
|
||||
unreachable('should not call mapBfRangeToArray');
|
||||
}
|
||||
|
||||
mapBfRangeToArray(low, high, array) {
|
||||
unreachable('should not call mapBfRangeToArray');
|
||||
},
|
||||
mapOne(src, dst) {
|
||||
unreachable('should not call mapCidOne');
|
||||
}
|
||||
|
||||
mapOne(src, dst) {
|
||||
unreachable('should not call mapCidOne');
|
||||
},
|
||||
lookup(code) {
|
||||
return (Number.isInteger(code) && code <= 0xffff) ? code : undefined;
|
||||
}
|
||||
|
||||
lookup(code) {
|
||||
return (Number.isInteger(code) && code <= 0xffff) ? code : undefined;
|
||||
},
|
||||
contains(code) {
|
||||
return Number.isInteger(code) && code <= 0xffff;
|
||||
}
|
||||
|
||||
contains(code) {
|
||||
return Number.isInteger(code) && code <= 0xffff;
|
||||
},
|
||||
forEach(callback) {
|
||||
for (let i = 0; i <= 0xffff; i++) {
|
||||
callback(i, i);
|
||||
}
|
||||
}
|
||||
|
||||
forEach(callback) {
|
||||
for (var i = 0; i <= 0xffff; i++) {
|
||||
callback(i, i);
|
||||
}
|
||||
},
|
||||
charCodeOf(value) {
|
||||
return (Number.isInteger(value) && value <= 0xffff) ? value : -1;
|
||||
}
|
||||
|
||||
charCodeOf(value) {
|
||||
return (Number.isInteger(value) && value <= 0xffff) ? value : -1;
|
||||
},
|
||||
getMap() {
|
||||
// Sometimes identity maps must be instantiated, but it's rare.
|
||||
const map = new Array(0x10000);
|
||||
for (let i = 0; i <= 0xffff; i++) {
|
||||
map[i] = i;
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
getMap() {
|
||||
// Sometimes identity maps must be instantiated, but it's rare.
|
||||
var map = new Array(0x10000);
|
||||
for (var i = 0; i <= 0xffff; i++) {
|
||||
map[i] = i;
|
||||
}
|
||||
return map;
|
||||
},
|
||||
get length() {
|
||||
return 0x10000;
|
||||
}
|
||||
|
||||
readCharCode: CMap.prototype.readCharCode,
|
||||
|
||||
get length() {
|
||||
return 0x10000;
|
||||
},
|
||||
|
||||
get isIdentityCMap() {
|
||||
unreachable('should not access .isIdentityCMap');
|
||||
},
|
||||
};
|
||||
|
||||
return IdentityCMap;
|
||||
})();
|
||||
get isIdentityCMap() {
|
||||
unreachable('should not access .isIdentityCMap');
|
||||
}
|
||||
}
|
||||
|
||||
var BinaryCMapReader = (function BinaryCMapReaderClosure() {
|
||||
function hexToInt(a, size) {
|
||||
|
@ -14,7 +14,7 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
bytesToString, FONT_IDENTITY_MATRIX, FormatError, unreachable, Util, warn
|
||||
bytesToString, FONT_IDENTITY_MATRIX, FormatError, unreachable, warn
|
||||
} from '../shared/util';
|
||||
import { CFFParser } from './cff_parser';
|
||||
import { getGlyphsUnicode } from './glyphlist';
|
||||
@ -616,17 +616,22 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
parse(code);
|
||||
}
|
||||
|
||||
var noop = '';
|
||||
const NOOP = [];
|
||||
|
||||
class CompiledFont {
|
||||
constructor(fontMatrix) {
|
||||
if (this.constructor === CompiledFont) {
|
||||
unreachable('Cannot initialize CompiledFont.');
|
||||
}
|
||||
this.fontMatrix = fontMatrix;
|
||||
|
||||
this.compiledGlyphs = Object.create(null);
|
||||
this.compiledCharCodeToGlyphId = Object.create(null);
|
||||
}
|
||||
|
||||
function CompiledFont(fontMatrix) {
|
||||
this.compiledGlyphs = Object.create(null);
|
||||
this.compiledCharCodeToGlyphId = Object.create(null);
|
||||
this.fontMatrix = fontMatrix;
|
||||
}
|
||||
CompiledFont.prototype = {
|
||||
getPathJs(unicode) {
|
||||
var cmap = lookupCmap(this.cmap, unicode);
|
||||
var fn = this.compiledGlyphs[cmap.glyphId];
|
||||
const cmap = lookupCmap(this.cmap, unicode);
|
||||
let fn = this.compiledGlyphs[cmap.glyphId];
|
||||
if (!fn) {
|
||||
fn = this.compileGlyph(this.glyphs[cmap.glyphId], cmap.glyphId);
|
||||
this.compiledGlyphs[cmap.glyphId] = fn;
|
||||
@ -635,11 +640,11 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
this.compiledCharCodeToGlyphId[cmap.charCode] = cmap.glyphId;
|
||||
}
|
||||
return fn;
|
||||
},
|
||||
}
|
||||
|
||||
compileGlyph(code, glyphId) {
|
||||
if (!code || code.length === 0 || code[0] === 14) {
|
||||
return noop;
|
||||
return NOOP;
|
||||
}
|
||||
|
||||
let fontMatrix = this.fontMatrix;
|
||||
@ -655,7 +660,7 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
}
|
||||
}
|
||||
|
||||
var cmds = [];
|
||||
const cmds = [];
|
||||
cmds.push({ cmd: 'save', });
|
||||
cmds.push({ cmd: 'transform', args: fontMatrix.slice(), });
|
||||
cmds.push({ cmd: 'scale', args: ['size', '-size'], });
|
||||
@ -665,58 +670,56 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
||||
cmds.push({ cmd: 'restore', });
|
||||
|
||||
return cmds;
|
||||
},
|
||||
}
|
||||
|
||||
compileGlyphImpl() {
|
||||
unreachable('Children classes should implement this.');
|
||||
},
|
||||
}
|
||||
|
||||
hasBuiltPath(unicode) {
|
||||
var cmap = lookupCmap(this.cmap, unicode);
|
||||
const cmap = lookupCmap(this.cmap, unicode);
|
||||
return (this.compiledGlyphs[cmap.glyphId] !== undefined &&
|
||||
this.compiledCharCodeToGlyphId[cmap.charCode] !== undefined);
|
||||
},
|
||||
};
|
||||
|
||||
function TrueTypeCompiled(glyphs, cmap, fontMatrix) {
|
||||
fontMatrix = fontMatrix || [0.000488, 0, 0, 0.000488, 0, 0];
|
||||
CompiledFont.call(this, fontMatrix);
|
||||
|
||||
this.glyphs = glyphs;
|
||||
this.cmap = cmap;
|
||||
}
|
||||
}
|
||||
|
||||
Util.inherit(TrueTypeCompiled, CompiledFont, {
|
||||
class TrueTypeCompiled extends CompiledFont {
|
||||
constructor(glyphs, cmap, fontMatrix) {
|
||||
super(fontMatrix || [0.000488, 0, 0, 0.000488, 0, 0]);
|
||||
|
||||
this.glyphs = glyphs;
|
||||
this.cmap = cmap;
|
||||
}
|
||||
|
||||
compileGlyphImpl(code, cmds) {
|
||||
compileGlyf(code, cmds, this);
|
||||
},
|
||||
});
|
||||
|
||||
function Type2Compiled(cffInfo, cmap, fontMatrix, glyphNameMap) {
|
||||
fontMatrix = fontMatrix || [0.001, 0, 0, 0.001, 0, 0];
|
||||
CompiledFont.call(this, fontMatrix);
|
||||
|
||||
this.glyphs = cffInfo.glyphs;
|
||||
this.gsubrs = cffInfo.gsubrs || [];
|
||||
this.subrs = cffInfo.subrs || [];
|
||||
this.cmap = cmap;
|
||||
this.glyphNameMap = glyphNameMap || getGlyphsUnicode();
|
||||
|
||||
this.gsubrsBias = (this.gsubrs.length < 1240 ?
|
||||
107 : (this.gsubrs.length < 33900 ? 1131 : 32768));
|
||||
this.subrsBias = (this.subrs.length < 1240 ?
|
||||
107 : (this.subrs.length < 33900 ? 1131 : 32768));
|
||||
|
||||
this.isCFFCIDFont = cffInfo.isCFFCIDFont;
|
||||
this.fdSelect = cffInfo.fdSelect;
|
||||
this.fdArray = cffInfo.fdArray;
|
||||
}
|
||||
}
|
||||
|
||||
Util.inherit(Type2Compiled, CompiledFont, {
|
||||
class Type2Compiled extends CompiledFont {
|
||||
constructor(cffInfo, cmap, fontMatrix, glyphNameMap) {
|
||||
super(fontMatrix || [0.001, 0, 0, 0.001, 0, 0]);
|
||||
|
||||
this.glyphs = cffInfo.glyphs;
|
||||
this.gsubrs = cffInfo.gsubrs || [];
|
||||
this.subrs = cffInfo.subrs || [];
|
||||
this.cmap = cmap;
|
||||
this.glyphNameMap = glyphNameMap || getGlyphsUnicode();
|
||||
|
||||
this.gsubrsBias = (this.gsubrs.length < 1240 ?
|
||||
107 : (this.gsubrs.length < 33900 ? 1131 : 32768));
|
||||
this.subrsBias = (this.subrs.length < 1240 ?
|
||||
107 : (this.subrs.length < 33900 ? 1131 : 32768));
|
||||
|
||||
this.isCFFCIDFont = cffInfo.isCFFCIDFont;
|
||||
this.fdSelect = cffInfo.fdSelect;
|
||||
this.fdArray = cffInfo.fdArray;
|
||||
}
|
||||
|
||||
compileGlyphImpl(code, cmds, glyphId) {
|
||||
compileCharString(code, cmds, this, glyphId);
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
create: function FontRendererFactory_create(font, seacAnalysisEnabled) {
|
||||
|
235
src/core/obj.js
235
src/core/obj.js
@ -16,7 +16,7 @@
|
||||
import {
|
||||
bytesToString, createPromiseCapability, createValidAbsoluteUrl, FormatError,
|
||||
info, InvalidPDFException, isBool, isString, MissingDataException, shadow,
|
||||
stringToPDFString, stringToUTF8String, unreachable, Util, warn,
|
||||
stringToPDFString, stringToUTF8String, toRomanNumerals, unreachable, warn,
|
||||
XRefParseException
|
||||
} from '../shared/util';
|
||||
import {
|
||||
@ -310,7 +310,7 @@ var Catalog = (function CatalogClosure() {
|
||||
break;
|
||||
case 'R':
|
||||
case 'r':
|
||||
currentLabel = Util.toRoman(currentIndex, style === 'r');
|
||||
currentLabel = toRomanNumerals(currentIndex, style === 'r');
|
||||
break;
|
||||
case 'A':
|
||||
case 'a':
|
||||
@ -1573,145 +1573,130 @@ var XRef = (function XRefClosure() {
|
||||
* see the specification (7.9.6 and 7.9.7) for additional details.
|
||||
* TODO: implement all the Dict functions and make this more efficient.
|
||||
*/
|
||||
var NameOrNumberTree = (function NameOrNumberTreeClosure() {
|
||||
function NameOrNumberTree(root, xref) {
|
||||
unreachable('Cannot initialize NameOrNumberTree.');
|
||||
class NameOrNumberTree {
|
||||
constructor(root, xref, type) {
|
||||
if (this.constructor === NameOrNumberTree) {
|
||||
unreachable('Cannot initialize NameOrNumberTree.');
|
||||
}
|
||||
this.root = root;
|
||||
this.xref = xref;
|
||||
this._type = type;
|
||||
}
|
||||
|
||||
NameOrNumberTree.prototype = {
|
||||
getAll: function NameOrNumberTree_getAll() {
|
||||
var dict = Object.create(null);
|
||||
if (!this.root) {
|
||||
return dict;
|
||||
}
|
||||
var xref = this.xref;
|
||||
// Reading Name/Number tree.
|
||||
var processed = new RefSet();
|
||||
processed.put(this.root);
|
||||
var queue = [this.root];
|
||||
while (queue.length > 0) {
|
||||
var i, n;
|
||||
var obj = xref.fetchIfRef(queue.shift());
|
||||
if (!isDict(obj)) {
|
||||
continue;
|
||||
}
|
||||
if (obj.has('Kids')) {
|
||||
var kids = obj.get('Kids');
|
||||
for (i = 0, n = kids.length; i < n; i++) {
|
||||
var kid = kids[i];
|
||||
if (processed.has(kid)) {
|
||||
throw new FormatError(`Duplicate entry in "${this._type}" tree.`);
|
||||
}
|
||||
queue.push(kid);
|
||||
processed.put(kid);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
var entries = obj.get(this._type);
|
||||
if (Array.isArray(entries)) {
|
||||
for (i = 0, n = entries.length; i < n; i += 2) {
|
||||
dict[xref.fetchIfRef(entries[i])] = xref.fetchIfRef(entries[i + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
getAll() {
|
||||
const dict = Object.create(null);
|
||||
if (!this.root) {
|
||||
return dict;
|
||||
},
|
||||
}
|
||||
const xref = this.xref;
|
||||
// Reading Name/Number tree.
|
||||
const processed = new RefSet();
|
||||
processed.put(this.root);
|
||||
const queue = [this.root];
|
||||
while (queue.length > 0) {
|
||||
const obj = xref.fetchIfRef(queue.shift());
|
||||
if (!isDict(obj)) {
|
||||
continue;
|
||||
}
|
||||
if (obj.has('Kids')) {
|
||||
const kids = obj.get('Kids');
|
||||
for (let i = 0, ii = kids.length; i < ii; i++) {
|
||||
const kid = kids[i];
|
||||
if (processed.has(kid)) {
|
||||
throw new FormatError(`Duplicate entry in "${this._type}" tree.`);
|
||||
}
|
||||
queue.push(kid);
|
||||
processed.put(kid);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
const entries = obj.get(this._type);
|
||||
if (Array.isArray(entries)) {
|
||||
for (let i = 0, ii = entries.length; i < ii; i += 2) {
|
||||
dict[xref.fetchIfRef(entries[i])] = xref.fetchIfRef(entries[i + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
|
||||
get: function NameOrNumberTree_get(key) {
|
||||
if (!this.root) {
|
||||
get(key) {
|
||||
if (!this.root) {
|
||||
return null;
|
||||
}
|
||||
const xref = this.xref;
|
||||
let kidsOrEntries = xref.fetchIfRef(this.root);
|
||||
let loopCount = 0;
|
||||
const MAX_LEVELS = 10;
|
||||
|
||||
// Perform a binary search to quickly find the entry that
|
||||
// contains the key we are looking for.
|
||||
while (kidsOrEntries.has('Kids')) {
|
||||
if (++loopCount > MAX_LEVELS) {
|
||||
warn('Search depth limit reached for "' + this._type + '" tree.');
|
||||
return null;
|
||||
}
|
||||
|
||||
var xref = this.xref;
|
||||
var kidsOrEntries = xref.fetchIfRef(this.root);
|
||||
var loopCount = 0;
|
||||
var MAX_LEVELS = 10;
|
||||
var l, r, m;
|
||||
|
||||
// Perform a binary search to quickly find the entry that
|
||||
// contains the key we are looking for.
|
||||
while (kidsOrEntries.has('Kids')) {
|
||||
if (++loopCount > MAX_LEVELS) {
|
||||
warn('Search depth limit reached for "' + this._type + '" tree.');
|
||||
return null;
|
||||
}
|
||||
|
||||
var kids = kidsOrEntries.get('Kids');
|
||||
if (!Array.isArray(kids)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
l = 0;
|
||||
r = kids.length - 1;
|
||||
while (l <= r) {
|
||||
m = (l + r) >> 1;
|
||||
var kid = xref.fetchIfRef(kids[m]);
|
||||
var limits = kid.get('Limits');
|
||||
|
||||
if (key < xref.fetchIfRef(limits[0])) {
|
||||
r = m - 1;
|
||||
} else if (key > xref.fetchIfRef(limits[1])) {
|
||||
l = m + 1;
|
||||
} else {
|
||||
kidsOrEntries = xref.fetchIfRef(kids[m]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (l > r) {
|
||||
return null;
|
||||
}
|
||||
const kids = kidsOrEntries.get('Kids');
|
||||
if (!Array.isArray(kids)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// If we get here, then we have found the right entry. Now go through the
|
||||
// entries in the dictionary until we find the key we're looking for.
|
||||
var entries = kidsOrEntries.get(this._type);
|
||||
if (Array.isArray(entries)) {
|
||||
// Perform a binary search to reduce the lookup time.
|
||||
l = 0;
|
||||
r = entries.length - 2;
|
||||
while (l <= r) {
|
||||
// Check only even indices (0, 2, 4, ...) because the
|
||||
// odd indices contain the actual data.
|
||||
m = (l + r) & ~1;
|
||||
var currentKey = xref.fetchIfRef(entries[m]);
|
||||
if (key < currentKey) {
|
||||
r = m - 2;
|
||||
} else if (key > currentKey) {
|
||||
l = m + 2;
|
||||
} else {
|
||||
return xref.fetchIfRef(entries[m + 1]);
|
||||
}
|
||||
let l = 0, r = kids.length - 1;
|
||||
while (l <= r) {
|
||||
const m = (l + r) >> 1;
|
||||
const kid = xref.fetchIfRef(kids[m]);
|
||||
const limits = kid.get('Limits');
|
||||
|
||||
if (key < xref.fetchIfRef(limits[0])) {
|
||||
r = m - 1;
|
||||
} else if (key > xref.fetchIfRef(limits[1])) {
|
||||
l = m + 1;
|
||||
} else {
|
||||
kidsOrEntries = xref.fetchIfRef(kids[m]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
};
|
||||
return NameOrNumberTree;
|
||||
})();
|
||||
if (l > r) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
var NameTree = (function NameTreeClosure() {
|
||||
function NameTree(root, xref) {
|
||||
this.root = root;
|
||||
this.xref = xref;
|
||||
this._type = 'Names';
|
||||
// If we get here, then we have found the right entry. Now go through the
|
||||
// entries in the dictionary until we find the key we're looking for.
|
||||
const entries = kidsOrEntries.get(this._type);
|
||||
if (Array.isArray(entries)) {
|
||||
// Perform a binary search to reduce the lookup time.
|
||||
let l = 0, r = entries.length - 2;
|
||||
while (l <= r) {
|
||||
// Check only even indices (0, 2, 4, ...) because the
|
||||
// odd indices contain the actual data.
|
||||
const m = (l + r) & ~1;
|
||||
const currentKey = xref.fetchIfRef(entries[m]);
|
||||
if (key < currentKey) {
|
||||
r = m - 2;
|
||||
} else if (key > currentKey) {
|
||||
l = m + 2;
|
||||
} else {
|
||||
return xref.fetchIfRef(entries[m + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Util.inherit(NameTree, NameOrNumberTree, {});
|
||||
|
||||
return NameTree;
|
||||
})();
|
||||
|
||||
var NumberTree = (function NumberTreeClosure() {
|
||||
function NumberTree(root, xref) {
|
||||
this.root = root;
|
||||
this.xref = xref;
|
||||
this._type = 'Nums';
|
||||
class NameTree extends NameOrNumberTree {
|
||||
constructor(root, xref) {
|
||||
super(root, xref, 'Names');
|
||||
}
|
||||
}
|
||||
|
||||
Util.inherit(NumberTree, NameOrNumberTree, {});
|
||||
|
||||
return NumberTree;
|
||||
})();
|
||||
class NumberTree extends NameOrNumberTree {
|
||||
constructor(root, xref) {
|
||||
super(root, xref, 'Nums');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* "A PDF file can refer to the contents of another file by using a File
|
||||
|
@ -839,53 +839,46 @@ var Util = (function UtilClosure() {
|
||||
return result;
|
||||
};
|
||||
|
||||
var ROMAN_NUMBER_MAP = [
|
||||
'', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM',
|
||||
'', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC',
|
||||
'', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'
|
||||
];
|
||||
/**
|
||||
* Converts positive integers to (upper case) Roman numerals.
|
||||
* @param {integer} number - The number that should be converted.
|
||||
* @param {boolean} lowerCase - Indicates if the result should be converted
|
||||
* to lower case letters. The default is false.
|
||||
* @return {string} The resulting Roman number.
|
||||
*/
|
||||
Util.toRoman = function Util_toRoman(number, lowerCase) {
|
||||
assert(Number.isInteger(number) && number > 0,
|
||||
'The number should be a positive integer.');
|
||||
var pos, romanBuf = [];
|
||||
// Thousands
|
||||
while (number >= 1000) {
|
||||
number -= 1000;
|
||||
romanBuf.push('M');
|
||||
}
|
||||
// Hundreds
|
||||
pos = (number / 100) | 0;
|
||||
number %= 100;
|
||||
romanBuf.push(ROMAN_NUMBER_MAP[pos]);
|
||||
// Tens
|
||||
pos = (number / 10) | 0;
|
||||
number %= 10;
|
||||
romanBuf.push(ROMAN_NUMBER_MAP[10 + pos]);
|
||||
// Ones
|
||||
romanBuf.push(ROMAN_NUMBER_MAP[20 + number]);
|
||||
|
||||
var romanStr = romanBuf.join('');
|
||||
return (lowerCase ? romanStr.toLowerCase() : romanStr);
|
||||
};
|
||||
|
||||
Util.inherit = function Util_inherit(sub, base, prototype) {
|
||||
sub.prototype = Object.create(base.prototype);
|
||||
sub.prototype.constructor = sub;
|
||||
for (var prop in prototype) {
|
||||
sub.prototype[prop] = prototype[prop];
|
||||
}
|
||||
};
|
||||
|
||||
return Util;
|
||||
})();
|
||||
|
||||
const ROMAN_NUMBER_MAP = [
|
||||
'', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM',
|
||||
'', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC',
|
||||
'', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'
|
||||
];
|
||||
|
||||
/**
|
||||
* Converts positive integers to (upper case) Roman numerals.
|
||||
* @param {integer} number - The number that should be converted.
|
||||
* @param {boolean} lowerCase - Indicates if the result should be converted
|
||||
* to lower case letters. The default value is `false`.
|
||||
* @return {string} The resulting Roman number.
|
||||
*/
|
||||
function toRomanNumerals(number, lowerCase = false) {
|
||||
assert(Number.isInteger(number) && number > 0,
|
||||
'The number should be a positive integer.');
|
||||
let pos, romanBuf = [];
|
||||
// Thousands
|
||||
while (number >= 1000) {
|
||||
number -= 1000;
|
||||
romanBuf.push('M');
|
||||
}
|
||||
// Hundreds
|
||||
pos = (number / 100) | 0;
|
||||
number %= 100;
|
||||
romanBuf.push(ROMAN_NUMBER_MAP[pos]);
|
||||
// Tens
|
||||
pos = (number / 10) | 0;
|
||||
number %= 10;
|
||||
romanBuf.push(ROMAN_NUMBER_MAP[10 + pos]);
|
||||
// Ones
|
||||
romanBuf.push(ROMAN_NUMBER_MAP[20 + number]);
|
||||
|
||||
const romanStr = romanBuf.join('');
|
||||
return (lowerCase ? romanStr.toLowerCase() : romanStr);
|
||||
}
|
||||
|
||||
var PDFStringTranslateTable = [
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0,
|
||||
@ -1033,6 +1026,7 @@ export {
|
||||
UnexpectedResponseException,
|
||||
UnknownErrorException,
|
||||
Util,
|
||||
toRomanNumerals,
|
||||
XRefParseException,
|
||||
FormatError,
|
||||
arrayByteLength,
|
||||
|
Loading…
Reference in New Issue
Block a user