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 {
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,17 +211,17 @@ 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++;
}
},
}
mapBfRange(low, high, dstLow) {
var lastByte = dstLow.length - 1;
@ -231,28 +231,28 @@ var CMap = (function CMapClosure() {
dstLow = dstLow.substr(0, lastByte) +
String.fromCharCode(dstLow.charCodeAt(lastByte) + 1);
}
},
}
mapBfRangeToArray(low, high, array) {
var i = 0, ii = array.length;
let i = 0, ii = array.length;
while (low <= high && i < ii) {
this._map[low] = array[i++];
++low;
}
},
}
// This is used for both bf and cid chars.
mapOne(src, dst) {
this._map[src] = dst;
},
}
lookup(code) {
return this._map[code];
},
}
contains(code) {
return this._map[code] !== undefined;
},
}
forEach(callback) {
// Most maps have fewer than 65536 entries, and for those we use normal
@ -273,12 +273,12 @@ var CMap = (function CMapClosure() {
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;
const map = this._map;
if (map.length <= 0x10000) {
return map.indexOf(value);
}
@ -288,25 +288,24 @@ var CMap = (function CMapClosure() {
}
}
return -1;
},
}
getMap() {
return this._map;
},
}
readCharCode(str, offset, out) {
var c = 0;
var codespaceRanges = this.codespaceRanges;
var codespaceRangesLen = this.codespaceRanges.length;
let c = 0;
const codespaceRanges = this.codespaceRanges;
// 9.7.6.2 CMap Mapping
// The code length is at most 4.
for (var n = 0; n < codespaceRangesLen; n++) {
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.
var codespaceRange = codespaceRanges[n];
for (var k = 0, kk = codespaceRange.length; k < kk;) {
var low = codespaceRange[k++];
var high = codespaceRange[k++];
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;
@ -316,11 +315,11 @@ var CMap = (function CMapClosure() {
}
out.charcode = 0;
out.length = 1;
},
}
get length() {
return this._map.length;
},
}
get isIdentityCMap() {
if (!(this.name === 'Identity-H' || this.name === 'Identity-V')) {
@ -329,86 +328,76 @@ var CMap = (function CMapClosure() {
if (this._map.length !== 0x10000) {
return false;
}
for (var i = 0; i < 0x10000; i++) {
for (let 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
// 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');
},
}
mapBfRange(low, high, dstLow) {
unreachable('should not call mapBfRange');
},
}
mapBfRangeToArray(low, high, array) {
unreachable('should not call mapBfRangeToArray');
},
}
mapOne(src, dst) {
unreachable('should not call mapCidOne');
},
}
lookup(code) {
return (Number.isInteger(code) && code <= 0xffff) ? code : undefined;
},
}
contains(code) {
return Number.isInteger(code) && code <= 0xffff;
},
}
forEach(callback) {
for (var i = 0; i <= 0xffff; i++) {
for (let i = 0; i <= 0xffff; i++) {
callback(i, i);
}
},
}
charCodeOf(value) {
return (Number.isInteger(value) && value <= 0xffff) ? value : -1;
},
}
getMap() {
// Sometimes identity maps must be instantiated, but it's rare.
var map = new Array(0x10000);
for (var i = 0; i <= 0xffff; i++) {
const map = new Array(0x10000);
for (let i = 0; i <= 0xffff; i++) {
map[i] = i;
}
return map;
},
readCharCode: CMap.prototype.readCharCode,
}
get length() {
return 0x10000;
},
}
get isIdentityCMap() {
unreachable('should not access .isIdentityCMap');
},
};
return IdentityCMap;
})();
}
}
var BinaryCMapReader = (function BinaryCMapReaderClosure() {
function hexToInt(a, size) {

View File

@ -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;
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,36 +670,35 @@ 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);
class TrueTypeCompiled extends CompiledFont {
constructor(glyphs, cmap, fontMatrix) {
super(fontMatrix || [0.000488, 0, 0, 0.000488, 0, 0]);
this.glyphs = glyphs;
this.cmap = cmap;
}
Util.inherit(TrueTypeCompiled, CompiledFont, {
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);
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 || [];
@ -712,11 +716,10 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
this.fdArray = cffInfo.fdArray;
}
Util.inherit(Type2Compiled, CompiledFont, {
compileGlyphImpl(code, cmds, glyphId) {
compileCharString(code, cmds, this, glyphId);
},
});
}
}
return {
create: function FontRendererFactory_create(font, seacAnalysisEnabled) {

View File

@ -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,32 +1573,35 @@ 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) {
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);
getAll() {
const dict = Object.create(null);
if (!this.root) {
return dict;
}
var xref = this.xref;
const xref = this.xref;
// Reading Name/Number tree.
var processed = new RefSet();
const processed = new RefSet();
processed.put(this.root);
var queue = [this.root];
const queue = [this.root];
while (queue.length > 0) {
var i, n;
var obj = xref.fetchIfRef(queue.shift());
const 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];
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.`);
}
@ -1607,26 +1610,24 @@ var NameOrNumberTree = (function NameOrNumberTreeClosure() {
}
continue;
}
var entries = obj.get(this._type);
const entries = obj.get(this._type);
if (Array.isArray(entries)) {
for (i = 0, n = entries.length; i < n; i += 2) {
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) {
return null;
}
var xref = this.xref;
var kidsOrEntries = xref.fetchIfRef(this.root);
var loopCount = 0;
var MAX_LEVELS = 10;
var l, r, m;
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.
@ -1636,17 +1637,16 @@ var NameOrNumberTree = (function NameOrNumberTreeClosure() {
return null;
}
var kids = kidsOrEntries.get('Kids');
const kids = kidsOrEntries.get('Kids');
if (!Array.isArray(kids)) {
return null;
}
l = 0;
r = kids.length - 1;
let l = 0, r = kids.length - 1;
while (l <= r) {
m = (l + r) >> 1;
var kid = xref.fetchIfRef(kids[m]);
var limits = kid.get('Limits');
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;
@ -1664,16 +1664,15 @@ var NameOrNumberTree = (function NameOrNumberTreeClosure() {
// 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);
const entries = kidsOrEntries.get(this._type);
if (Array.isArray(entries)) {
// Perform a binary search to reduce the lookup time.
l = 0;
r = entries.length - 2;
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.
m = (l + r) & ~1;
var currentKey = xref.fetchIfRef(entries[m]);
const m = (l + r) & ~1;
const currentKey = xref.fetchIfRef(entries[m]);
if (key < currentKey) {
r = m - 2;
} else if (key > currentKey) {
@ -1684,34 +1683,20 @@ var NameOrNumberTree = (function NameOrNumberTreeClosure() {
}
}
return null;
},
};
return NameOrNumberTree;
})();
var NameTree = (function NameTreeClosure() {
function NameTree(root, xref) {
this.root = root;
this.xref = xref;
this._type = 'Names';
}
}
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

View File

@ -839,22 +839,26 @@ var Util = (function UtilClosure() {
return result;
};
var ROMAN_NUMBER_MAP = [
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 is false.
* to lower case letters. The default value is `false`.
* @return {string} The resulting Roman number.
*/
Util.toRoman = function Util_toRoman(number, lowerCase) {
function toRomanNumerals(number, lowerCase = false) {
assert(Number.isInteger(number) && number > 0,
'The number should be a positive integer.');
var pos, romanBuf = [];
let pos, romanBuf = [];
// Thousands
while (number >= 1000) {
number -= 1000;
@ -871,20 +875,9 @@ var Util = (function UtilClosure() {
// Ones
romanBuf.push(ROMAN_NUMBER_MAP[20 + number]);
var romanStr = romanBuf.join('');
const 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;
})();
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,
@ -1033,6 +1026,7 @@ export {
UnexpectedResponseException,
UnknownErrorException,
Util,
toRomanNumerals,
XRefParseException,
FormatError,
arrayByteLength,