Merge pull request #6141 from skalnik/fix-font-csp-issues
Provide a fallback for font rendering when not allowed to use `eval`
This commit is contained in:
commit
c56dc9a093
@ -134,16 +134,15 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function compileGlyf(code, js, font) {
|
function compileGlyf(code, cmds, font) {
|
||||||
function moveTo(x, y) {
|
function moveTo(x, y) {
|
||||||
js.push('c.moveTo(' + x + ',' + y + ');');
|
cmds.push({cmd: 'moveTo', args: [x, y]});
|
||||||
}
|
}
|
||||||
function lineTo(x, y) {
|
function lineTo(x, y) {
|
||||||
js.push('c.lineTo(' + x + ',' + y + ');');
|
cmds.push({cmd: 'lineTo', args: [x, y]});
|
||||||
}
|
}
|
||||||
function quadraticCurveTo(xa, ya, x, y) {
|
function quadraticCurveTo(xa, ya, x, y) {
|
||||||
js.push('c.quadraticCurveTo(' + xa + ',' + ya + ',' +
|
cmds.push({cmd: 'quadraticCurveTo', args: [xa, ya, x, y]});
|
||||||
x + ',' + y + ');');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var i = 0;
|
var i = 0;
|
||||||
@ -189,11 +188,11 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
}
|
}
|
||||||
var subglyph = font.glyphs[glyphIndex];
|
var subglyph = font.glyphs[glyphIndex];
|
||||||
if (subglyph) {
|
if (subglyph) {
|
||||||
js.push('c.save();');
|
cmds.push({cmd: 'save'});
|
||||||
js.push('c.transform(' + scaleX + ',' + scale01 + ',' +
|
cmds.push({cmd: 'transform',
|
||||||
scale10 + ',' + scaleY + ',' + x + ',' + y + ');');
|
args: [scaleX, scale01, scale10, scaleY, x, y]});
|
||||||
compileGlyf(subglyph, js, font);
|
compileGlyf(subglyph, cmds, font);
|
||||||
js.push('c.restore();');
|
cmds.push({cmd: 'restore'});
|
||||||
}
|
}
|
||||||
} while ((flags & 0x20));
|
} while ((flags & 0x20));
|
||||||
} else {
|
} else {
|
||||||
@ -289,20 +288,19 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function compileCharString(code, js, font) {
|
function compileCharString(code, cmds, font) {
|
||||||
var stack = [];
|
var stack = [];
|
||||||
var x = 0, y = 0;
|
var x = 0, y = 0;
|
||||||
var stems = 0;
|
var stems = 0;
|
||||||
|
|
||||||
function moveTo(x, y) {
|
function moveTo(x, y) {
|
||||||
js.push('c.moveTo(' + x + ',' + y + ');');
|
cmds.push({cmd: 'moveTo', args: [x, y]});
|
||||||
}
|
}
|
||||||
function lineTo(x, y) {
|
function lineTo(x, y) {
|
||||||
js.push('c.lineTo(' + x + ',' + y + ');');
|
cmds.push({cmd: 'lineTo', args: [x, y]});
|
||||||
}
|
}
|
||||||
function bezierCurveTo(x1, y1, x2, y2, x, y) {
|
function bezierCurveTo(x1, y1, x2, y2, x, y) {
|
||||||
js.push('c.bezierCurveTo(' + x1 + ',' + y1 + ',' + x2 + ',' + y2 + ',' +
|
cmds.push({cmd: 'bezierCurveTo', args: [x1, y1, x2, y2, x, y]});
|
||||||
x + ',' + y + ');');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function parse(code) {
|
function parse(code) {
|
||||||
@ -431,16 +429,16 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
var bchar = stack.pop();
|
var bchar = stack.pop();
|
||||||
y = stack.pop();
|
y = stack.pop();
|
||||||
x = stack.pop();
|
x = stack.pop();
|
||||||
js.push('c.save();');
|
cmds.push({cmd: 'save'});
|
||||||
js.push('c.translate('+ x + ',' + y + ');');
|
cmds.push({cmd: 'translate', args: [x, y]});
|
||||||
var gid = lookupCmap(font.cmap, String.fromCharCode(
|
var gid = lookupCmap(font.cmap, String.fromCharCode(
|
||||||
font.glyphNameMap[Encodings.StandardEncoding[achar]]));
|
font.glyphNameMap[Encodings.StandardEncoding[achar]]));
|
||||||
compileCharString(font.glyphs[gid], js, font);
|
compileCharString(font.glyphs[gid], cmds, font);
|
||||||
js.push('c.restore();');
|
cmds.push({cmd: 'restore'});
|
||||||
|
|
||||||
gid = lookupCmap(font.cmap, String.fromCharCode(
|
gid = lookupCmap(font.cmap, String.fromCharCode(
|
||||||
font.glyphNameMap[Encodings.StandardEncoding[bchar]]));
|
font.glyphNameMap[Encodings.StandardEncoding[bchar]]));
|
||||||
compileCharString(font.glyphs[gid], js, font);
|
compileCharString(font.glyphs[gid], cmds, font);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case 18: // hstemhm
|
case 18: // hstemhm
|
||||||
@ -609,16 +607,16 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
return noop;
|
return noop;
|
||||||
}
|
}
|
||||||
|
|
||||||
var js = [];
|
var cmds = [];
|
||||||
js.push('c.save();');
|
cmds.push({cmd: 'save'});
|
||||||
js.push('c.transform(' + this.fontMatrix.join(',') + ');');
|
cmds.push({cmd: 'transform', args: this.fontMatrix.slice()});
|
||||||
js.push('c.scale(size, -size);');
|
cmds.push({cmd: 'scale', args: ['size', '-size']});
|
||||||
|
|
||||||
this.compileGlyphImpl(code, js);
|
this.compileGlyphImpl(code, cmds);
|
||||||
|
|
||||||
js.push('c.restore();');
|
cmds.push({cmd: 'restore'});
|
||||||
|
|
||||||
return js.join('\n');
|
return cmds;
|
||||||
},
|
},
|
||||||
|
|
||||||
compileGlyphImpl: function () {
|
compileGlyphImpl: function () {
|
||||||
@ -642,8 +640,8 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Util.inherit(TrueTypeCompiled, CompiledFont, {
|
Util.inherit(TrueTypeCompiled, CompiledFont, {
|
||||||
compileGlyphImpl: function (code, js) {
|
compileGlyphImpl: function (code, cmds) {
|
||||||
compileGlyf(code, js, this);
|
compileGlyf(code, cmds, this);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -664,8 +662,8 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Util.inherit(Type2Compiled, CompiledFont, {
|
Util.inherit(Type2Compiled, CompiledFont, {
|
||||||
compileGlyphImpl: function (code, js) {
|
compileGlyphImpl: function (code, cmds) {
|
||||||
compileCharString(code, js, this);
|
compileCharString(code, cmds, this);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -177,6 +177,14 @@ PDFJS.openExternalLinksInNewWindow = (
|
|||||||
PDFJS.openExternalLinksInNewWindow === undefined ?
|
PDFJS.openExternalLinksInNewWindow === undefined ?
|
||||||
false : PDFJS.openExternalLinksInNewWindow);
|
false : PDFJS.openExternalLinksInNewWindow);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if we can eval strings as JS. Primarily used to improve
|
||||||
|
* performance for font rendering.
|
||||||
|
* @var {boolean}
|
||||||
|
*/
|
||||||
|
PDFJS.isEvalSupported = (PDFJS.isEvalSupported === undefined ?
|
||||||
|
true : PDFJS.isEvalSupported);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Document initialization / loading parameters object.
|
* Document initialization / loading parameters object.
|
||||||
*
|
*
|
||||||
|
@ -77,6 +77,18 @@ var FontLoader = {
|
|||||||
));
|
));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
get isEvalSupported() {
|
||||||
|
var evalSupport = false;
|
||||||
|
if (PDFJS.isEvalSupported) {
|
||||||
|
try {
|
||||||
|
/* jshint evil: true */
|
||||||
|
new Function('');
|
||||||
|
evalSupport = true;
|
||||||
|
} catch (e) {}
|
||||||
|
}
|
||||||
|
return shadow(this, 'isEvalSupported', evalSupport);
|
||||||
|
},
|
||||||
|
|
||||||
loadTestFontId: 0,
|
loadTestFontId: 0,
|
||||||
|
|
||||||
loadingContext: {
|
loadingContext: {
|
||||||
@ -372,9 +384,40 @@ var FontFaceObject = (function FontFaceObjectClosure() {
|
|||||||
|
|
||||||
getPathGenerator: function FontLoader_getPathGenerator(objs, character) {
|
getPathGenerator: function FontLoader_getPathGenerator(objs, character) {
|
||||||
if (!(character in this.compiledGlyphs)) {
|
if (!(character in this.compiledGlyphs)) {
|
||||||
var js = objs.get(this.loadedName + '_path_' + character);
|
var cmds = objs.get(this.loadedName + '_path_' + character);
|
||||||
/*jshint -W054 */
|
var current, i, len;
|
||||||
this.compiledGlyphs[character] = new Function('c', 'size', js);
|
|
||||||
|
// If we can, compile cmds into JS for MAXIMUM SPEED
|
||||||
|
if (FontLoader.isEvalSupported) {
|
||||||
|
var args, js = '';
|
||||||
|
for (i = 0, len = cmds.length; i < len; i++) {
|
||||||
|
current = cmds[i];
|
||||||
|
|
||||||
|
if (current.args !== undefined) {
|
||||||
|
args = current.args.join(',');
|
||||||
|
} else {
|
||||||
|
args = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
js += 'c.' + current.cmd + '(' + args + ');\n';
|
||||||
|
}
|
||||||
|
/* jshint -W054 */
|
||||||
|
this.compiledGlyphs[character] = new Function('c', 'size', js);
|
||||||
|
} else {
|
||||||
|
// But fall back on using Function.prototype.apply() if we're
|
||||||
|
// blocked from using eval() for whatever reason (like CSP policies)
|
||||||
|
this.compiledGlyphs[character] = function(c, size) {
|
||||||
|
for (i = 0, len = cmds.length; i < len; i++) {
|
||||||
|
current = cmds[i];
|
||||||
|
|
||||||
|
if (current.cmd === 'scale') {
|
||||||
|
current.args = [size, -size];
|
||||||
|
}
|
||||||
|
|
||||||
|
c[current.cmd].apply(c, current.args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return this.compiledGlyphs[character];
|
return this.compiledGlyphs[character];
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user