Use FDSelect and FDArray when converting CFF CID font to paths

This commit is contained in:
Jani Pehkonen 2018-04-10 16:44:42 +03:00
parent 2275485cec
commit 8ea505545a
4 changed files with 61 additions and 12 deletions

View File

@ -14,7 +14,7 @@
*/ */
import { import {
bytesToString, FormatError, unreachable, Util bytesToString, FONT_IDENTITY_MATRIX, FormatError, unreachable, Util, warn
} from '../shared/util'; } from '../shared/util';
import { CFFParser } from './cff_parser'; import { CFFParser } from './cff_parser';
import { getGlyphsUnicode } from './glyphlist'; import { getGlyphsUnicode } from './glyphlist';
@ -91,6 +91,9 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
subrs: (cff.topDict.privateDict && cff.topDict.privateDict.subrsIndex && subrs: (cff.topDict.privateDict && cff.topDict.privateDict.subrsIndex &&
cff.topDict.privateDict.subrsIndex.objects), cff.topDict.privateDict.subrsIndex.objects),
gsubrs: cff.globalSubrIndex && cff.globalSubrIndex.objects, gsubrs: cff.globalSubrIndex && cff.globalSubrIndex.objects,
isCFFCIDFont: cff.isCIDFont,
fdSelect: cff.fdSelect,
fdArray: cff.fdArray,
}; };
} }
@ -293,7 +296,7 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
} }
} }
function compileCharString(code, cmds, font) { function compileCharString(code, cmds, font, glyphId) {
var stack = []; var stack = [];
var x = 0, y = 0; var x = 0, y = 0;
var stems = 0; var stems = 0;
@ -366,8 +369,28 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
} }
break; break;
case 10: // callsubr case 10: // callsubr
n = stack.pop() + font.subrsBias; n = stack.pop();
subrCode = font.subrs[n]; subrCode = null;
if (font.isCFFCIDFont) {
let fdIndex = font.fdSelect.getFDIndex(glyphId);
if (fdIndex >= 0 && fdIndex < font.fdArray.length) {
let fontDict = font.fdArray[fdIndex], subrs;
if (fontDict.privateDict && fontDict.privateDict.subrsIndex) {
subrs = fontDict.privateDict.subrsIndex.objects;
}
if (subrs) {
let numSubrs = subrs.length;
// Add subroutine bias.
n += numSubrs < 1240 ? 107 :
(numSubrs < 33900 ? 1131 : 32768);
subrCode = subrs[n];
}
} else {
warn('Invalid fd index for glyph index.');
}
} else {
subrCode = font.subrs[n + font.subrsBias];
}
if (subrCode) { if (subrCode) {
parse(subrCode); parse(subrCode);
} }
@ -438,12 +461,14 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
cmds.push({ cmd: 'translate', args: [x, y], }); cmds.push({ cmd: 'translate', args: [x, y], });
var cmap = lookupCmap(font.cmap, String.fromCharCode( var cmap = lookupCmap(font.cmap, String.fromCharCode(
font.glyphNameMap[StandardEncoding[achar]])); font.glyphNameMap[StandardEncoding[achar]]));
compileCharString(font.glyphs[cmap.glyphId], cmds, font); compileCharString(font.glyphs[cmap.glyphId], cmds, font,
cmap.glyphId);
cmds.push({ cmd: 'restore', }); cmds.push({ cmd: 'restore', });
cmap = lookupCmap(font.cmap, String.fromCharCode( cmap = lookupCmap(font.cmap, String.fromCharCode(
font.glyphNameMap[StandardEncoding[bchar]])); font.glyphNameMap[StandardEncoding[bchar]]));
compileCharString(font.glyphs[cmap.glyphId], cmds, font); compileCharString(font.glyphs[cmap.glyphId], cmds, font,
cmap.glyphId);
} }
return; return;
case 18: // hstemhm case 18: // hstemhm
@ -603,7 +628,7 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
var cmap = lookupCmap(this.cmap, unicode); var cmap = lookupCmap(this.cmap, unicode);
var fn = this.compiledGlyphs[cmap.glyphId]; var fn = this.compiledGlyphs[cmap.glyphId];
if (!fn) { if (!fn) {
fn = this.compileGlyph(this.glyphs[cmap.glyphId]); fn = this.compileGlyph(this.glyphs[cmap.glyphId], cmap.glyphId);
this.compiledGlyphs[cmap.glyphId] = fn; this.compiledGlyphs[cmap.glyphId] = fn;
} }
if (this.compiledCharCodeToGlyphId[cmap.charCode] === undefined) { if (this.compiledCharCodeToGlyphId[cmap.charCode] === undefined) {
@ -612,17 +637,30 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
return fn; return fn;
}, },
compileGlyph(code) { compileGlyph(code, glyphId) {
if (!code || code.length === 0 || code[0] === 14) { if (!code || code.length === 0 || code[0] === 14) {
return noop; return noop;
} }
let fontMatrix = this.fontMatrix;
if (this.isCFFCIDFont) {
// Top DICT's FontMatrix can be ignored because CFFCompiler always
// removes it and copies to FDArray DICTs.
let fdIndex = this.fdSelect.getFDIndex(glyphId);
if (fdIndex >= 0 && fdIndex < this.fdArray.length) {
let fontDict = this.fdArray[fdIndex];
fontMatrix = fontDict.getByName('FontMatrix') || FONT_IDENTITY_MATRIX;
} else {
warn('Invalid fd index for glyph index.');
}
}
var cmds = []; var cmds = [];
cmds.push({ cmd: 'save', }); cmds.push({ cmd: 'save', });
cmds.push({ cmd: 'transform', args: this.fontMatrix.slice(), }); cmds.push({ cmd: 'transform', args: fontMatrix.slice(), });
cmds.push({ cmd: 'scale', args: ['size', '-size'], }); cmds.push({ cmd: 'scale', args: ['size', '-size'], });
this.compileGlyphImpl(code, cmds); this.compileGlyphImpl(code, cmds, glyphId);
cmds.push({ cmd: 'restore', }); cmds.push({ cmd: 'restore', });
@ -668,11 +706,15 @@ var FontRendererFactory = (function FontRendererFactoryClosure() {
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 ?
107 : (this.subrs.length < 33900 ? 1131 : 32768)); 107 : (this.subrs.length < 33900 ? 1131 : 32768));
this.isCFFCIDFont = cffInfo.isCFFCIDFont;
this.fdSelect = cffInfo.fdSelect;
this.fdArray = cffInfo.fdArray;
} }
Util.inherit(Type2Compiled, CompiledFont, { Util.inherit(Type2Compiled, CompiledFont, {
compileGlyphImpl(code, cmds) { compileGlyphImpl(code, cmds, glyphId) {
compileCharString(code, cmds, this); compileCharString(code, cmds, this, glyphId);
}, },
}); });

View File

@ -262,6 +262,7 @@
!issue4573.pdf !issue4573.pdf
!issue4722.pdf !issue4722.pdf
!issue4800.pdf !issue4800.pdf
!text_clip_cff_cid.pdf
!issue4801.pdf !issue4801.pdf
!issue5334.pdf !issue5334.pdf
!bug1186827.pdf !bug1186827.pdf

Binary file not shown.

View File

@ -2261,6 +2261,12 @@
"link": true, "link": true,
"type": "eq" "type": "eq"
}, },
{ "id": "text_clip_cff_cid",
"file": "pdfs/text_clip_cff_cid.pdf",
"md5": "92d4920586f177cc0e83326e5b5d2ee1",
"rounds": 1,
"type": "eq"
},
{ "id": "preistabelle", { "id": "preistabelle",
"file": "pdfs/preistabelle.pdf", "file": "pdfs/preistabelle.pdf",
"md5": "d2f0b2086160d4f3d325c79a5dc1fb4d", "md5": "d2f0b2086160d4f3d325c79a5dc1fb4d",