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:
Tim van der Meij 2018-07-14 23:58:38 +02:00 committed by GitHub
commit b56081c5f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 358 additions and 387 deletions

View File

@ -14,8 +14,8 @@
*/ */
import { import {
CMapCompressionType, FormatError, isString, MissingDataException, CMapCompressionType, FormatError, isString, MissingDataException, unreachable,
unreachable, Util, warn warn
} from '../shared/util'; } from '../shared/util';
import { isCmd, isEOF, isName, isStream } from './primitives'; import { isCmd, isEOF, isName, isStream } from './primitives';
import { Lexer } from './parser'; import { Lexer } from './parser';
@ -194,8 +194,8 @@ var BUILT_IN_CMAPS = [
'WP-Symbol']; 'WP-Symbol'];
// CMap, not to be confused with TrueType's cmap. // CMap, not to be confused with TrueType's cmap.
var CMap = (function CMapClosure() { class CMap {
function CMap(builtInCMap) { constructor(builtInCMap = false) {
// Codespace ranges are stored as follows: // Codespace ranges are stored as follows:
// [[1BytePairs], [2BytePairs], [3BytePairs], [4BytePairs]] // [[1BytePairs], [2BytePairs], [3BytePairs], [4BytePairs]]
// where nBytePairs are ranges e.g. [low1, high1, low2, high2, ...] // where nBytePairs are ranges e.g. [low1, high1, low2, high2, ...]
@ -211,204 +211,193 @@ var CMap = (function CMapClosure() {
this.useCMap = null; this.useCMap = null;
this.builtInCMap = builtInCMap; this.builtInCMap = builtInCMap;
} }
CMap.prototype = {
addCodespaceRange(n, low, high) {
this.codespaceRanges[n - 1].push(low, high);
this.numCodespaceRanges++;
},
mapCidRange(low, high, dstLow) { addCodespaceRange(n, low, high) {
while (low <= high) { this.codespaceRanges[n - 1].push(low, high);
this._map[low++] = dstLow++; this.numCodespaceRanges++;
} }
},
mapBfRange(low, high, dstLow) { mapCidRange(low, high, dstLow) {
var lastByte = dstLow.length - 1; while (low <= high) {
while (low <= high) { this._map[low++] = dstLow++;
this._map[low++] = dstLow; }
// Only the last byte has to be incremented. }
dstLow = dstLow.substr(0, lastByte) +
String.fromCharCode(dstLow.charCodeAt(lastByte) + 1);
}
},
mapBfRangeToArray(low, high, array) { mapBfRange(low, high, dstLow) {
var i = 0, ii = array.length; var lastByte = dstLow.length - 1;
while (low <= high && i < ii) { while (low <= high) {
this._map[low] = array[i++]; this._map[low++] = dstLow;
++low; // 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. mapBfRangeToArray(low, high, array) {
mapOne(src, dst) { let i = 0, ii = array.length;
this._map[src] = dst; while (low <= high && i < ii) {
}, this._map[low] = array[i++];
++low;
}
}
lookup(code) { // This is used for both bf and cid chars.
return this._map[code]; mapOne(src, dst) {
}, this._map[src] = dst;
}
contains(code) { lookup(code) {
return this._map[code] !== undefined; return this._map[code];
}, }
forEach(callback) { contains(code) {
// Most maps have fewer than 65536 entries, and for those we use normal return this._map[code] !== undefined;
// 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 forEach(callback) {
// it does avoid iterating over every undefined entry. // Most maps have fewer than 65536 entries, and for those we use normal
let map = this._map; // array iteration. But really sparse tables are possible -- e.g. with
let length = map.length; // indices in the *billions*. For such tables we use for..in, which isn't
if (length <= 0x10000) { // ideal because it stringifies the indices for all present elements, but
for (let i = 0; i < length; i++) { // it does avoid iterating over every undefined entry.
if (map[i] !== undefined) { let map = this._map;
callback(i, map[i]); let length = map.length;
} if (length <= 0x10000) {
} for (let i = 0; i < length; i++) {
} else { if (map[i] !== undefined) {
for (let i in map) {
callback(i, map[i]); callback(i, map[i]);
} }
} }
}, } else {
for (let i in map) {
charCodeOf(value) { callback(i, map[i]);
// `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);
} }
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() { get length() {
return this._map; return this._map.length;
}, }
readCharCode(str, offset, out) { get isIdentityCMap() {
var c = 0; if (!(this.name === 'Identity-H' || this.name === 'Identity-V')) {
var codespaceRanges = this.codespaceRanges; return false;
var codespaceRangesLen = this.codespaceRanges.length; }
// 9.7.6.2 CMap Mapping if (this._map.length !== 0x10000) {
// The code length is at most 4. return false;
for (var n = 0; n < codespaceRangesLen; n++) { }
c = ((c << 8) | str.charCodeAt(offset + n)) >>> 0; for (let i = 0; i < 0x10000; i++) {
// Check each codespace range to see if it falls within. if (this._map[i] !== i) {
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')) {
return false; return false;
} }
if (this._map.length !== 0x10000) { }
return false; return true;
} }
for (var i = 0; i < 0x10000; i++) { }
if (this._map[i] !== i) {
return false;
}
}
return true;
},
};
return CMap;
})();
// A special case of CMap, where the _map array implicitly has a length of // A special case of CMap, where the _map array implicitly has a length of
// 65536 and each element is equal to its index. // 65536 and each element is equal to its index.
var IdentityCMap = (function IdentityCMapClosure() { class IdentityCMap extends CMap {
function IdentityCMap(vertical, n) { constructor(vertical, n) {
CMap.call(this); super();
this.vertical = vertical; this.vertical = vertical;
this.addCodespaceRange(n, 0, 0xffff); this.addCodespaceRange(n, 0, 0xffff);
} }
Util.inherit(IdentityCMap, CMap, {});
IdentityCMap.prototype = { mapCidRange(low, high, dstLow) {
addCodespaceRange: CMap.prototype.addCodespaceRange, unreachable('should not call mapCidRange');
}
mapCidRange(low, high, dstLow) { mapBfRange(low, high, dstLow) {
unreachable('should not call mapCidRange'); unreachable('should not call mapBfRange');
}, }
mapBfRange(low, high, dstLow) { mapBfRangeToArray(low, high, array) {
unreachable('should not call mapBfRange'); unreachable('should not call mapBfRangeToArray');
}, }
mapBfRangeToArray(low, high, array) { mapOne(src, dst) {
unreachable('should not call mapBfRangeToArray'); unreachable('should not call mapCidOne');
}, }
mapOne(src, dst) { lookup(code) {
unreachable('should not call mapCidOne'); return (Number.isInteger(code) && code <= 0xffff) ? code : undefined;
}, }
lookup(code) { contains(code) {
return (Number.isInteger(code) && code <= 0xffff) ? code : undefined; return Number.isInteger(code) && code <= 0xffff;
}, }
contains(code) { forEach(callback) {
return Number.isInteger(code) && code <= 0xffff; for (let i = 0; i <= 0xffff; i++) {
}, callback(i, i);
}
}
forEach(callback) { charCodeOf(value) {
for (var i = 0; i <= 0xffff; i++) { return (Number.isInteger(value) && value <= 0xffff) ? value : -1;
callback(i, i); }
}
},
charCodeOf(value) { getMap() {
return (Number.isInteger(value) && value <= 0xffff) ? value : -1; // 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() { get length() {
// Sometimes identity maps must be instantiated, but it's rare. return 0x10000;
var map = new Array(0x10000); }
for (var i = 0; i <= 0xffff; i++) {
map[i] = i;
}
return map;
},
readCharCode: CMap.prototype.readCharCode, get isIdentityCMap() {
unreachable('should not access .isIdentityCMap');
get length() { }
return 0x10000; }
},
get isIdentityCMap() {
unreachable('should not access .isIdentityCMap');
},
};
return IdentityCMap;
})();
var BinaryCMapReader = (function BinaryCMapReaderClosure() { var BinaryCMapReader = (function BinaryCMapReaderClosure() {
function hexToInt(a, size) { function hexToInt(a, size) {

View File

@ -14,7 +14,7 @@
*/ */
import { import {
bytesToString, FONT_IDENTITY_MATRIX, FormatError, unreachable, Util, warn bytesToString, FONT_IDENTITY_MATRIX, FormatError, unreachable, warn
} from '../shared/util'; } from '../shared/util';
import { CFFParser } from './cff_parser'; import { CFFParser } from './cff_parser';
import { getGlyphsUnicode } from './glyphlist'; import { getGlyphsUnicode } from './glyphlist';
@ -616,17 +616,22 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
parse(code); 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) { getPathJs(unicode) {
var cmap = lookupCmap(this.cmap, unicode); const cmap = lookupCmap(this.cmap, unicode);
var fn = this.compiledGlyphs[cmap.glyphId]; let fn = this.compiledGlyphs[cmap.glyphId];
if (!fn) { if (!fn) {
fn = this.compileGlyph(this.glyphs[cmap.glyphId], cmap.glyphId); fn = this.compileGlyph(this.glyphs[cmap.glyphId], cmap.glyphId);
this.compiledGlyphs[cmap.glyphId] = fn; this.compiledGlyphs[cmap.glyphId] = fn;
@ -635,11 +640,11 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
this.compiledCharCodeToGlyphId[cmap.charCode] = cmap.glyphId; this.compiledCharCodeToGlyphId[cmap.charCode] = cmap.glyphId;
} }
return fn; return fn;
}, }
compileGlyph(code, glyphId) { compileGlyph(code, glyphId) {
if (!code || code.length === 0 || code[0] === 14) { if (!code || code.length === 0 || code[0] === 14) {
return noop; return NOOP;
} }
let fontMatrix = this.fontMatrix; let fontMatrix = this.fontMatrix;
@ -655,7 +660,7 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
} }
} }
var cmds = []; const cmds = [];
cmds.push({ cmd: 'save', }); cmds.push({ cmd: 'save', });
cmds.push({ cmd: 'transform', args: fontMatrix.slice(), }); cmds.push({ cmd: 'transform', args: fontMatrix.slice(), });
cmds.push({ cmd: 'scale', args: ['size', '-size'], }); cmds.push({ cmd: 'scale', args: ['size', '-size'], });
@ -665,58 +670,56 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
cmds.push({ cmd: 'restore', }); cmds.push({ cmd: 'restore', });
return cmds; return cmds;
}, }
compileGlyphImpl() { compileGlyphImpl() {
unreachable('Children classes should implement this.'); unreachable('Children classes should implement this.');
}, }
hasBuiltPath(unicode) { hasBuiltPath(unicode) {
var cmap = lookupCmap(this.cmap, unicode); const cmap = lookupCmap(this.cmap, unicode);
return (this.compiledGlyphs[cmap.glyphId] !== undefined && return (this.compiledGlyphs[cmap.glyphId] !== undefined &&
this.compiledCharCodeToGlyphId[cmap.charCode] !== 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) { compileGlyphImpl(code, cmds) {
compileGlyf(code, cmds, this); 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) { compileGlyphImpl(code, cmds, glyphId) {
compileCharString(code, cmds, this, glyphId); compileCharString(code, cmds, this, glyphId);
}, }
}); }
return { return {
create: function FontRendererFactory_create(font, seacAnalysisEnabled) { create: function FontRendererFactory_create(font, seacAnalysisEnabled) {

View File

@ -16,7 +16,7 @@
import { import {
bytesToString, createPromiseCapability, createValidAbsoluteUrl, FormatError, bytesToString, createPromiseCapability, createValidAbsoluteUrl, FormatError,
info, InvalidPDFException, isBool, isString, MissingDataException, shadow, info, InvalidPDFException, isBool, isString, MissingDataException, shadow,
stringToPDFString, stringToUTF8String, unreachable, Util, warn, stringToPDFString, stringToUTF8String, toRomanNumerals, unreachable, warn,
XRefParseException XRefParseException
} from '../shared/util'; } from '../shared/util';
import { import {
@ -310,7 +310,7 @@ var Catalog = (function CatalogClosure() {
break; break;
case 'R': case 'R':
case 'r': case 'r':
currentLabel = Util.toRoman(currentIndex, style === 'r'); currentLabel = toRomanNumerals(currentIndex, style === 'r');
break; break;
case 'A': case 'A':
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. * see the specification (7.9.6 and 7.9.7) for additional details.
* TODO: implement all the Dict functions and make this more efficient. * TODO: implement all the Dict functions and make this more efficient.
*/ */
var NameOrNumberTree = (function NameOrNumberTreeClosure() { class NameOrNumberTree {
function NameOrNumberTree(root, xref) { constructor(root, xref, type) {
unreachable('Cannot initialize NameOrNumberTree.'); if (this.constructor === NameOrNumberTree) {
unreachable('Cannot initialize NameOrNumberTree.');
}
this.root = root;
this.xref = xref;
this._type = type;
} }
NameOrNumberTree.prototype = { getAll() {
getAll: function NameOrNumberTree_getAll() { const dict = Object.create(null);
var dict = Object.create(null); if (!this.root) {
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]);
}
}
}
return dict; 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) { get(key) {
if (!this.root) { 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; return null;
} }
var xref = this.xref; const kids = kidsOrEntries.get('Kids');
var kidsOrEntries = xref.fetchIfRef(this.root); if (!Array.isArray(kids)) {
var loopCount = 0; return null;
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;
}
} }
// If we get here, then we have found the right entry. Now go through the let l = 0, r = kids.length - 1;
// entries in the dictionary until we find the key we're looking for. while (l <= r) {
var entries = kidsOrEntries.get(this._type); const m = (l + r) >> 1;
if (Array.isArray(entries)) { const kid = xref.fetchIfRef(kids[m]);
// Perform a binary search to reduce the lookup time. const limits = kid.get('Limits');
l = 0;
r = entries.length - 2; if (key < xref.fetchIfRef(limits[0])) {
while (l <= r) { r = m - 1;
// Check only even indices (0, 2, 4, ...) because the } else if (key > xref.fetchIfRef(limits[1])) {
// odd indices contain the actual data. l = m + 1;
m = (l + r) & ~1; } else {
var currentKey = xref.fetchIfRef(entries[m]); kidsOrEntries = xref.fetchIfRef(kids[m]);
if (key < currentKey) { break;
r = m - 2;
} else if (key > currentKey) {
l = m + 2;
} else {
return xref.fetchIfRef(entries[m + 1]);
}
} }
} }
return null; if (l > r) {
}, return null;
}; }
return NameOrNumberTree; }
})();
var NameTree = (function NameTreeClosure() { // If we get here, then we have found the right entry. Now go through the
function NameTree(root, xref) { // entries in the dictionary until we find the key we're looking for.
this.root = root; const entries = kidsOrEntries.get(this._type);
this.xref = xref; if (Array.isArray(entries)) {
this._type = 'Names'; // 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, {}); class NameTree extends NameOrNumberTree {
constructor(root, xref) {
return NameTree; super(root, xref, 'Names');
})();
var NumberTree = (function NumberTreeClosure() {
function NumberTree(root, xref) {
this.root = root;
this.xref = xref;
this._type = 'Nums';
} }
}
Util.inherit(NumberTree, NameOrNumberTree, {}); class NumberTree extends NameOrNumberTree {
constructor(root, xref) {
return NumberTree; super(root, xref, 'Nums');
})(); }
}
/** /**
* "A PDF file can refer to the contents of another file by using a File * "A PDF file can refer to the contents of another file by using a File

View File

@ -839,53 +839,46 @@ var Util = (function UtilClosure() {
return result; 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; 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 = [ 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, 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, 0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0,
@ -1033,6 +1026,7 @@ export {
UnexpectedResponseException, UnexpectedResponseException,
UnknownErrorException, UnknownErrorException,
Util, Util,
toRomanNumerals,
XRefParseException, XRefParseException,
FormatError, FormatError,
arrayByteLength, arrayByteLength,