cmaps: Use cmap.forEach instead of Array.forEach

CMaps may be sparse. Array.prototype.forEach is terribly slow in Chrome
(and also in Firefox) when the sparse array contains a key with a high
value. E.g.

    console.time('forEach sparse')
    var a = [];
    a[0xFFFFFF] = 1;
    a.forEach(function(){});
    console.timeEnd('forEach sparse');

    // Chrome: 2890ms
    // Firefox: 1345ms

Switching to CMap.prototype.forEach, which is optimized for such
scenarios fixes the problem.
This commit is contained in:
Rob Wu 2015-08-08 01:16:05 +02:00
parent 26b9205c7e
commit b0a8c0fa40

View File

@ -1370,11 +1370,11 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
if (cmap instanceof IdentityCMap) {
return new IdentityToUnicodeMap(0, 0xFFFF);
}
cmap = cmap.getMap();
var map = [];
// Convert UTF-16BE
// NOTE: cmap can be a sparse array, so use forEach instead of for(;;)
// to iterate over all keys.
cmap.forEach(function(token, i) {
cmap.forEach(function(charCode, token) {
var str = [];
for (var k = 0; k < token.length; k += 2) {
var w1 = (token.charCodeAt(k) << 8) | token.charCodeAt(k + 1);
@ -1386,9 +1386,9 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
var w2 = (token.charCodeAt(k) << 8) | token.charCodeAt(k + 1);
str.push(((w1 & 0x3ff) << 10) + (w2 & 0x3ff) + 0x10000);
}
cmap[i] = String.fromCharCode.apply(String, str);
map[charCode] = String.fromCharCode.apply(String, str);
});
return new ToUnicodeMap(cmap);
return new ToUnicodeMap(map);
}
return null;
},