Keep track of the character to glyph mapping in font_renderer.js, to prevent errors when different characters point to the same glyph (issue 7101)

Fixes 7101.
This commit is contained in:
Jonas Jenwald 2016-03-23 13:52:30 +01:00
parent bec4891f5d
commit 17aaa125df
4 changed files with 31 additions and 16 deletions

View File

@ -137,7 +137,7 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
} }
function lookupCmap(ranges, unicode) { function lookupCmap(ranges, unicode) {
var code = unicode.charCodeAt(0); var code = unicode.charCodeAt(0), gid = 0;
var l = 0, r = ranges.length - 1; var l = 0, r = ranges.length - 1;
while (l < r) { while (l < r) {
var c = (l + r + 1) >> 1; var c = (l + r + 1) >> 1;
@ -148,10 +148,13 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
} }
} }
if (ranges[l].start <= code && code <= ranges[l].end) { if (ranges[l].start <= code && code <= ranges[l].end) {
return (ranges[l].idDelta + (ranges[l].ids ? gid = (ranges[l].idDelta + (ranges[l].ids ?
ranges[l].ids[code - ranges[l].start] : code)) & 0xFFFF; ranges[l].ids[code - ranges[l].start] : code)) & 0xFFFF;
} }
return 0; return {
charCode: code,
glyphId: gid,
};
} }
function compileGlyf(code, cmds, font) { function compileGlyf(code, cmds, font) {
@ -451,14 +454,14 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
x = stack.pop(); x = stack.pop();
cmds.push({cmd: 'save'}); cmds.push({cmd: 'save'});
cmds.push({cmd: 'translate', args: [x, y]}); cmds.push({cmd: 'translate', args: [x, y]});
var gid = lookupCmap(font.cmap, String.fromCharCode( var cmap = lookupCmap(font.cmap, String.fromCharCode(
font.glyphNameMap[StandardEncoding[achar]])); font.glyphNameMap[StandardEncoding[achar]]));
compileCharString(font.glyphs[gid], cmds, font); compileCharString(font.glyphs[cmap.glyphId], cmds, font);
cmds.push({cmd: 'restore'}); cmds.push({cmd: 'restore'});
gid = lookupCmap(font.cmap, String.fromCharCode( cmap = lookupCmap(font.cmap, String.fromCharCode(
font.glyphNameMap[StandardEncoding[bchar]])); font.glyphNameMap[StandardEncoding[bchar]]));
compileCharString(font.glyphs[gid], cmds, font); compileCharString(font.glyphs[cmap.glyphId], cmds, font);
} }
return; return;
case 18: // hstemhm case 18: // hstemhm
@ -610,14 +613,19 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
function CompiledFont(fontMatrix) { function CompiledFont(fontMatrix) {
this.compiledGlyphs = Object.create(null); this.compiledGlyphs = Object.create(null);
this.compiledCharCodeToGlyphId = Object.create(null);
this.fontMatrix = fontMatrix; this.fontMatrix = fontMatrix;
} }
CompiledFont.prototype = { CompiledFont.prototype = {
getPathJs: function (unicode) { getPathJs: function (unicode) {
var gid = lookupCmap(this.cmap, unicode); var cmap = lookupCmap(this.cmap, unicode);
var fn = this.compiledGlyphs[gid]; var fn = this.compiledGlyphs[cmap.glyphId];
if (!fn) { if (!fn) {
this.compiledGlyphs[gid] = fn = this.compileGlyph(this.glyphs[gid]); fn = this.compileGlyph(this.glyphs[cmap.glyphId]);
this.compiledGlyphs[cmap.glyphId] = fn;
}
if (this.compiledCharCodeToGlyphId[cmap.charCode] === undefined) {
this.compiledCharCodeToGlyphId[cmap.charCode] = cmap.glyphId;
} }
return fn; return fn;
}, },
@ -644,8 +652,9 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
}, },
hasBuiltPath: function (unicode) { hasBuiltPath: function (unicode) {
var gid = lookupCmap(this.cmap, unicode); var cmap = lookupCmap(this.cmap, unicode);
return gid in this.compiledGlyphs; return (this.compiledGlyphs[cmap.glyphId] !== undefined &&
this.compiledCharCodeToGlyphId[cmap.charCode] !== undefined);
} }
}; };
@ -655,8 +664,6 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
this.glyphs = glyphs; this.glyphs = glyphs;
this.cmap = cmap; this.cmap = cmap;
this.compiledGlyphs = [];
} }
Util.inherit(TrueTypeCompiled, CompiledFont, { Util.inherit(TrueTypeCompiled, CompiledFont, {
@ -668,13 +675,13 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
function Type2Compiled(cffInfo, cmap, fontMatrix, glyphNameMap) { function Type2Compiled(cffInfo, cmap, fontMatrix, glyphNameMap) {
fontMatrix = fontMatrix || [0.001, 0, 0, 0.001, 0, 0]; fontMatrix = fontMatrix || [0.001, 0, 0, 0.001, 0, 0];
CompiledFont.call(this, fontMatrix); CompiledFont.call(this, fontMatrix);
this.glyphs = cffInfo.glyphs; this.glyphs = cffInfo.glyphs;
this.gsubrs = cffInfo.gsubrs || []; this.gsubrs = cffInfo.gsubrs || [];
this.subrs = cffInfo.subrs || []; this.subrs = cffInfo.subrs || [];
this.cmap = cmap; this.cmap = cmap;
this.glyphNameMap = glyphNameMap || getGlyphsUnicode(); this.glyphNameMap = glyphNameMap || getGlyphsUnicode();
this.compiledGlyphs = [];
this.gsubrsBias = (this.gsubrs.length < 1240 ? this.gsubrsBias = (this.gsubrs.length < 1240 ?
107 : (this.gsubrs.length < 33900 ? 1131 : 32768)); 107 : (this.gsubrs.length < 33900 ? 1131 : 32768));
this.subrsBias = (this.subrs.length < 1240 ? this.subrsBias = (this.subrs.length < 1240 ?

View File

@ -21,6 +21,7 @@
!issue6782.pdf !issue6782.pdf
!issue6961.pdf !issue6961.pdf
!issue7020.pdf !issue7020.pdf
!issue7101.pdf
!issue7115.pdf !issue7115.pdf
!filled-background.pdf !filled-background.pdf
!ArabicCIDTrueType.pdf !ArabicCIDTrueType.pdf

BIN
test/pdfs/issue7101.pdf Normal file

Binary file not shown.

View File

@ -1263,6 +1263,13 @@
"rounds": 1, "rounds": 1,
"type": "eq" "type": "eq"
}, },
{ "id": "issue7101",
"file": "pdfs/issue7101.pdf",
"md5": "cc9cabe12ac9ad49e5372ef33d10aeb4",
"link": false,
"rounds": 1,
"type": "eq"
},
{ "id": "pr4606", { "id": "pr4606",
"file": "pdfs/pr4606.pdf", "file": "pdfs/pr4606.pdf",
"md5": "6574fde2314648600056bd0e229df98c", "md5": "6574fde2314648600056bd0e229df98c",