Make IdentityCMaps more compact.

IdentityCMap uses an array to represent a 16-bit unsigned identity
function. This is very space-inefficient, and some files cause multiple
IdentityCMaps to be instantiated (e.g. the one from #4580 has 74).

This patch make the representation implicit.

When loading the PDF from issue #4580, this change reduces peak RSS from
~370 to ~280 MiB. It also improves overall speed on that PDF by ~30%,
going from 522 ms to 366 ms.
This commit is contained in:
Nicholas Nethercote 2014-08-04 23:38:43 -07:00
parent 6865c284a7
commit 51055e5836

View File

@ -302,20 +302,69 @@ var CMap = (function CMapClosure() {
return [0, 1];
}
};
return CMap;
})();
// A special case of CMap, where the _map array implicitly has a length of
// 65535 and each element is equal to its index.
var IdentityCMap = (function IdentityCMapClosure() {
function IdentityCMap(vertical, n) {
CMap.call(this);
this.vertical = vertical;
this.addCodespaceRange(n, 0, 0xffff);
this.mapCidRange(0, 0xffff, 0);
}
Util.inherit(IdentityCMap, CMap, {});
IdentityCMap.prototype = {
addCodespaceRange: CMap.prototype.addCodespaceRange,
mapCidRange: function(low, high, dstLow) {
error('should not call mapCidRange');
},
mapBfRange: function(low, high, dstLow) {
error('should not call mapBfRange');
},
mapBfRangeToArray: function(low, high, array) {
error('should not call mapBfRangeToArray');
},
mapOne: function(src, dst) {
error('should not call mapCidOne');
},
lookup: function(code) {
return (isInt(code) && code <= 0xffff) ? code : undefined;
},
contains: function(code) {
return isInt(code) && code <= 0xffff;
},
forEach: function(callback) {
for (var i = 0; i <= 0xffff; i++) {
callback(i, i);
}
},
charCodeOf: function(value) {
return (isInt(value) && value <= 0xffff) ? value : -1;
},
getMap: function() {
// 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;
},
readCharCode: CMap.prototype.readCharCode
};
return IdentityCMap;
})();