diff --git a/src/core/evaluator.js b/src/core/evaluator.js index 4bbd2aa0c..e71905134 100644 --- a/src/core/evaluator.js +++ b/src/core/evaluator.js @@ -1396,7 +1396,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { textState = stateManager.state; var fn = operation.fn; args = operation.args; - var advance; + var advance, diff; switch (fn | 0) { case OPS.setFont: @@ -1429,8 +1429,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { (args[0] - textContentItem.lastAdvanceWidth); textContentItem.height += (args[1] - textContentItem.lastAdvanceHeight); - var diff = (args[0] - textContentItem.lastAdvanceWidth) - - (args[1] - textContentItem.lastAdvanceHeight); + diff = (args[0] - textContentItem.lastAdvanceWidth) - + (args[1] - textContentItem.lastAdvanceHeight); addFakeSpaces(diff, textContentItem.str); break; } @@ -1450,6 +1450,24 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { textState.carriageReturn(); break; case OPS.setTextMatrix: + // Optimization to treat same line movement as advance. + advance = textState.calcTextLineMatrixAdvance( + args[0], args[1], args[2], args[3], args[4], args[5]); + if (advance !== null && textContentItem.initialized && + advance.value > 0 && + advance.value <= textContentItem.fakeMultiSpaceMax) { + textState.translateTextLineMatrix(advance.width, + advance.height); + textContentItem.width += + (advance.width - textContentItem.lastAdvanceWidth); + textContentItem.height += + (advance.height - textContentItem.lastAdvanceHeight); + diff = (advance.width - textContentItem.lastAdvanceWidth) - + (advance.height - textContentItem.lastAdvanceHeight); + addFakeSpaces(diff, textContentItem.str); + break; + } + flushTextContentItem(); textState.setTextMatrix(args[0], args[1], args[2], args[3], args[4], args[5]); @@ -2547,6 +2565,30 @@ var TextState = (function TextStateClosure() { m[4] = m[0] * x + m[2] * y + m[4]; m[5] = m[1] * x + m[3] * y + m[5]; }, + calcTextLineMatrixAdvance: + function TextState_calcTextLineMatrixAdvance(a, b, c, d, e, f) { + var font = this.font; + if (!font) { + return null; + } + var m = this.textLineMatrix; + if (!(a === m[0] && b === m[1] && c === m[2] && d === m[3])) { + return null; + } + var txDiff = e - m[4], tyDiff = f - m[5]; + if ((font.vertical && txDiff !== 0) || (!font.vertical && tyDiff !== 0)) { + return null; + } + var tx, ty, denominator = a * d - b * c; + if (font.vertical) { + tx = -tyDiff * c / denominator; + ty = tyDiff * a / denominator; + } else { + tx = txDiff * d / denominator; + ty = -txDiff * b / denominator; + } + return { width: tx, height: ty, value: (font.vertical ? ty : tx), }; + }, calcRenderMatrix: function TextState_calcRendeMatrix(ctm) { // 9.4.4 Text Space Details var tsm = [this.fontSize * this.textHScale, 0, diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index 82bc7d131..ba364de32 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -20,6 +20,7 @@ !issue6204.pdf !issue6782.pdf !issue6961.pdf +!issue6962.pdf !issue7020.pdf !issue7101.pdf !issue7115.pdf diff --git a/test/pdfs/issue6962.pdf b/test/pdfs/issue6962.pdf new file mode 100644 index 000000000..110279c4e Binary files /dev/null and b/test/pdfs/issue6962.pdf differ diff --git a/test/test_manifest.json b/test/test_manifest.json index 452355414..372db8416 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -1111,6 +1111,13 @@ "type": "eq", "about": "Please note that this file currently renders incorrectly." }, + { "id": "issue6962", + "file": "pdfs/issue6962.pdf", + "md5": "d40e871ecca68baf93114bd28c782148", + "rounds": 1, + "link": false, + "type": "text" + }, { "id": "issue5644", "file": "pdfs/issue5644.pdf", "md5": "6f9313c5043b3ecb0ab2df321d3e1847",