diff --git a/src/fonts.js b/src/fonts.js index 3cfdba094..330210b28 100644 --- a/src/fonts.js +++ b/src/fonts.js @@ -17,7 +17,7 @@ /* globals assert, bytesToString, CIDToUnicodeMaps, error, ExpertCharset, ExpertSubsetCharset, FileReaderSync, globalScope, GlyphsUnicode, info, isArray, isNum, ISOAdobeCharset, isWorker, PDFJS, Stream, - stringToBytes, TextDecoder, TODO, warn, Lexer */ + stringToBytes, TextDecoder, TODO, warn, Lexer, Util */ 'use strict'; @@ -6696,6 +6696,33 @@ var CFFCompiler = (function CFFCompilerClosure() { var nameIndex = this.compileNameIndex(cff.names); output.add(nameIndex); + if (cff.isCIDFont) { + // The spec is unclear on how font matrices should relate to each other + // when there is one in the main top dict and the sub top dicts. + // Windows handles this differently than linux and osx so we have to + // normalize to work on all. + // Rules based off of some mailing list discussions: + // - If main font has a matrix and subfont doesn't, use the main matrix. + // - If no main font matrix and there is a subfont matrix, use the + // subfont matrix. + // - If both have matrices, concat together. + // - If neither have matrices, use default. + // To make this work on all platforms we move the top matrix into each + // sub top dict and concat if necessary. + if (cff.topDict.hasName('FontMatrix')) { + var base = cff.topDict.getByName('FontMatrix'); + cff.topDict.removeByName('FontMatrix'); + for (var i = 0, ii = cff.fdArray.length; i < ii; i++) { + var subDict = cff.fdArray[i]; + var matrix = base.slice(0); + if (subDict.hasName('FontMatrix')) { + matrix = Util.transform(matrix, subDict.getByName('FontMatrix')); + } + subDict.setByName('FontMatrix', matrix); + } + } + } + var compiled = this.compileTopDicts([cff.topDict], output.length, cff.isCIDFont); diff --git a/src/util.js b/src/util.js index c29699f7d..8706b27fb 100644 --- a/src/util.js +++ b/src/util.js @@ -223,6 +223,18 @@ var Util = PDFJS.Util = (function UtilClosure() { return Util.makeCssCmyk(cmyk); }; + // Concatenates two transformation matrices together and returns the result. + Util.transform = function Util_transform(m1, m2) { + return [ + m1[0] * m2[0] + m1[2] * m2[1], + m1[1] * m2[0] + m1[3] * m2[1], + m1[0] * m2[2] + m1[2] * m2[3], + m1[1] * m2[2] + m1[3] * m2[3], + m1[0] * m2[4] + m1[2] * m2[5] + m1[4], + m1[1] * m2[4] + m1[3] * m2[5] + m1[5] + ]; + }; + // For 2d affine transforms Util.applyTransform = function Util_applyTransform(p, m) { var xt = p[0] * m[0] + p[1] * m[2] + m[4]; diff --git a/test/pdfs/issue3061.pdf b/test/pdfs/issue3061.pdf new file mode 100644 index 000000000..4c16f7c58 Binary files /dev/null and b/test/pdfs/issue3061.pdf differ diff --git a/test/test_manifest.json b/test/test_manifest.json index 68fbc7009..a1ce04f51 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -883,6 +883,13 @@ "lastPage": 4, "type": "load" }, + { "id": "issue3061", + "file": "pdfs/issue3061.pdf", + "md5": "696a7cb1b194d095ca3f7861779a606b", + "rounds": 1, + "type": "eq", + "about": "CFF CID font with font matrices in main top dict and sub top dict." + }, { "id": "issue1878", "file": "pdfs/issue1878.pdf", "md5": "b4fb0ce7c19368e7104dce3d0d34bcb3",