From 88f9e633dde47fda1daf22a94e93357a67bc0095 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Fri, 8 Mar 2019 12:55:44 +0100 Subject: [PATCH] Try to improve text-selection for Type3 fonts that utilize a non-default /FontMatrix (bug 1513120) For Type3 fonts text-selection is often not that great, and there's a couple of heuristics used to try and improve things. This patch simple extends those heuristics a bit, and fixes a pre-existing "naive" array comparison, but this all feels a bit brittle to say the least. The existing Type3 test-coverage isn't that great in general, and in particular Type3 `text` tests are few and far between, hence why this patch adds *two* different new `text` tests. --- src/core/evaluator.js | 14 ++++++-------- src/shared/util.js | 10 ++++++++++ test/pdfs/.gitignore | 1 + test/pdfs/bug1513120_reduced.pdf | Bin 0 -> 30014 bytes test/test_manifest.json | 14 ++++++++++++++ 5 files changed, 31 insertions(+), 8 deletions(-) create mode 100644 test/pdfs/bug1513120_reduced.pdf diff --git a/src/core/evaluator.js b/src/core/evaluator.js index c512c952e..dd13aeb64 100644 --- a/src/core/evaluator.js +++ b/src/core/evaluator.js @@ -15,8 +15,8 @@ import { AbortException, assert, CMapCompressionType, createPromiseCapability, - FONT_IDENTITY_MATRIX, FormatError, IDENTITY_MATRIX, info, isNum, isString, - NativeImageDecoding, OPS, stringToPDFString, TextRenderingMode, + FONT_IDENTITY_MATRIX, FormatError, IDENTITY_MATRIX, info, isArrayEqual, isNum, + isString, NativeImageDecoding, OPS, stringToPDFString, TextRenderingMode, UNSUPPORTED_FEATURES, Util, warn } from '../shared/util'; import { CMapFactory, IdentityCMap } from './cmap'; @@ -1264,13 +1264,11 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { 0, textState.fontSize, 0, textState.textRise]; - if (font.isType3Font && - textState.fontMatrix !== FONT_IDENTITY_MATRIX && - textState.fontSize === 1) { - var glyphHeight = font.bbox[3] - font.bbox[1]; + if (font.isType3Font && textState.fontSize <= 1 && + !isArrayEqual(textState.fontMatrix, FONT_IDENTITY_MATRIX)) { + const glyphHeight = font.bbox[3] - font.bbox[1]; if (glyphHeight > 0) { - glyphHeight = glyphHeight * textState.fontMatrix[3]; - tsm[3] *= glyphHeight; + tsm[3] *= (glyphHeight * textState.fontMatrix[3]); } } diff --git a/src/shared/util.js b/src/shared/util.js index 8a9902b82..35685921f 100644 --- a/src/shared/util.js +++ b/src/shared/util.js @@ -824,6 +824,15 @@ function isArrayBuffer(v) { return typeof v === 'object' && v !== null && v.byteLength !== undefined; } +function isArrayEqual(arr1, arr2) { + if (arr1.length !== arr2.length) { + return false; + } + return arr1.every(function(element, index) { + return element === arr2[index]; + }); +} + // Checks if ch is one of the following characters: SPACE, TAB, CR or LF. function isSpace(ch) { return (ch === 0x20 || ch === 0x09 || ch === 0x0D || ch === 0x0A); @@ -927,6 +936,7 @@ export { getVerbosityLevel, info, isArrayBuffer, + isArrayEqual, isBool, isEmptyObj, isNum, diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index 2d21b3fff..259a95710 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -93,6 +93,7 @@ !bug1146106.pdf !bug1245391_reduced.pdf !bug1252420.pdf +!bug1513120_reduced.pdf !issue9949.pdf !bug1308536.pdf !bug1337429.pdf diff --git a/test/pdfs/bug1513120_reduced.pdf b/test/pdfs/bug1513120_reduced.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f41ef4af96d79e1622987ca3d27073579f2ea393 GIT binary patch literal 30014 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