diff --git a/src/core/evaluator.js b/src/core/evaluator.js index 4382b2215..3e0dd8492 100644 --- a/src/core/evaluator.js +++ b/src/core/evaluator.js @@ -2367,8 +2367,8 @@ class PartialEvaluator { return { str, dir: bidiResult.dir, - width: textChunk.totalWidth, - height: textChunk.totalHeight, + width: Math.abs(textChunk.totalWidth), + height: Math.abs(textChunk.totalHeight), transform: textChunk.transform, fontName: textChunk.fontName, hasEOL: textChunk.hasEOL, @@ -2459,7 +2459,11 @@ class PartialEvaluator { if (textState.font.vertical) { const advanceY = (lastPosY - posY) / textContentItem.textAdvanceScale; const advanceX = posX - lastPosX; - if (advanceY < textContentItem.negativeSpaceMax) { + + // When the total height of the current chunk is negative + // then we're writing from bottom to top. + const textOrientation = Math.sign(textContentItem.height); + if (advanceY < textOrientation * textContentItem.negativeSpaceMax) { if ( Math.abs(advanceX) > 0.5 * textContentItem.width /* not the same column */ @@ -2476,15 +2480,21 @@ class PartialEvaluator { appendEOL(); return; } - if (advanceY <= textContentItem.trackingSpaceMin) { + if (advanceY <= textOrientation * textContentItem.trackingSpaceMin) { textContentItem.height += advanceY; - } else if (!addFakeSpaces(advanceY, textContentItem.prevTransform)) { + } else if ( + !addFakeSpaces( + advanceY, + textContentItem.prevTransform, + textOrientation + ) + ) { if (textContentItem.str.length === 0) { textContent.items.push({ str: " ", dir: "ltr", width: 0, - height: advanceY, + height: Math.abs(advanceY), transform: textContentItem.prevTransform, fontName: textContentItem.fontName, hasEOL: false, @@ -2499,7 +2509,11 @@ class PartialEvaluator { const advanceX = (posX - lastPosX) / textContentItem.textAdvanceScale; const advanceY = posY - lastPosY; - if (advanceX < textContentItem.negativeSpaceMax) { + + // When the total width of the current chunk is negative + // then we're writing from right to left. + const textOrientation = Math.sign(textContentItem.width); + if (advanceX < textOrientation * textContentItem.negativeSpaceMax) { if ( Math.abs(advanceY) > 0.5 * textContentItem.height /* not the same line */ @@ -2516,14 +2530,16 @@ class PartialEvaluator { return; } - if (advanceX <= textContentItem.trackingSpaceMin) { + if (advanceX <= textOrientation * textContentItem.trackingSpaceMin) { textContentItem.width += advanceX; - } else if (!addFakeSpaces(advanceX, textContentItem.prevTransform)) { + } else if ( + !addFakeSpaces(advanceX, textContentItem.prevTransform, textOrientation) + ) { if (textContentItem.str.length === 0) { textContent.items.push({ str: " ", dir: "ltr", - width: advanceX, + width: Math.abs(advanceX), height: 0, transform: textContentItem.prevTransform, fontName: textContentItem.fontName, @@ -2652,10 +2668,10 @@ class PartialEvaluator { } } - function addFakeSpaces(width, transf) { + function addFakeSpaces(width, transf, textOrientation) { if ( - textContentItem.spaceInFlowMin <= width && - width <= textContentItem.spaceInFlowMax + textOrientation * textContentItem.spaceInFlowMin <= width && + width <= textOrientation * textContentItem.spaceInFlowMax ) { if (textContentItem.initialized) { textContentItem.str.push(" "); @@ -2677,8 +2693,8 @@ class PartialEvaluator { // TODO: check if using the orientation from last chunk is // better or not. dir: "ltr", - width, - height, + width: Math.abs(width), + height: Math.abs(height), transform: transf || getCurrentTextTransform(), fontName, hasEOL: false, diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index fd13f10da..e9067c31c 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -500,3 +500,4 @@ !poppler-937-0-fuzzed.pdf !PDFBOX-3148-2-fuzzed.pdf !poppler-90-0-fuzzed.pdf +!issue14415.pdf \ No newline at end of file diff --git a/test/pdfs/issue14415.pdf b/test/pdfs/issue14415.pdf new file mode 100644 index 000000000..0e12655b4 Binary files /dev/null and b/test/pdfs/issue14415.pdf differ diff --git a/test/test_manifest.json b/test/test_manifest.json index 884c7b666..f95c0eb3a 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -6191,5 +6191,10 @@ "link": true, "rounds": 1, "type": "eq" - } + }, + { "id": "issue14415", + "file": "pdfs/issue14415.pdf", + "md5": "fa306a250a3d37fe0e7a4b3bba51c91e", + "type": "text" + } ]