Use positive dimensions for text chunks in the text layer (issue #14415).

This commit is contained in:
Calixte Denizet 2022-01-04 21:36:25 +01:00
parent 2ca432d318
commit 6cdae5ac4d
4 changed files with 38 additions and 16 deletions

View File

@ -2367,8 +2367,8 @@ class PartialEvaluator {
return { return {
str, str,
dir: bidiResult.dir, dir: bidiResult.dir,
width: textChunk.totalWidth, width: Math.abs(textChunk.totalWidth),
height: textChunk.totalHeight, height: Math.abs(textChunk.totalHeight),
transform: textChunk.transform, transform: textChunk.transform,
fontName: textChunk.fontName, fontName: textChunk.fontName,
hasEOL: textChunk.hasEOL, hasEOL: textChunk.hasEOL,
@ -2459,7 +2459,11 @@ class PartialEvaluator {
if (textState.font.vertical) { if (textState.font.vertical) {
const advanceY = (lastPosY - posY) / textContentItem.textAdvanceScale; const advanceY = (lastPosY - posY) / textContentItem.textAdvanceScale;
const advanceX = posX - lastPosX; 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 ( if (
Math.abs(advanceX) > Math.abs(advanceX) >
0.5 * textContentItem.width /* not the same column */ 0.5 * textContentItem.width /* not the same column */
@ -2476,15 +2480,21 @@ class PartialEvaluator {
appendEOL(); appendEOL();
return; return;
} }
if (advanceY <= textContentItem.trackingSpaceMin) { if (advanceY <= textOrientation * textContentItem.trackingSpaceMin) {
textContentItem.height += advanceY; textContentItem.height += advanceY;
} else if (!addFakeSpaces(advanceY, textContentItem.prevTransform)) { } else if (
!addFakeSpaces(
advanceY,
textContentItem.prevTransform,
textOrientation
)
) {
if (textContentItem.str.length === 0) { if (textContentItem.str.length === 0) {
textContent.items.push({ textContent.items.push({
str: " ", str: " ",
dir: "ltr", dir: "ltr",
width: 0, width: 0,
height: advanceY, height: Math.abs(advanceY),
transform: textContentItem.prevTransform, transform: textContentItem.prevTransform,
fontName: textContentItem.fontName, fontName: textContentItem.fontName,
hasEOL: false, hasEOL: false,
@ -2499,7 +2509,11 @@ class PartialEvaluator {
const advanceX = (posX - lastPosX) / textContentItem.textAdvanceScale; const advanceX = (posX - lastPosX) / textContentItem.textAdvanceScale;
const advanceY = posY - lastPosY; 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 ( if (
Math.abs(advanceY) > Math.abs(advanceY) >
0.5 * textContentItem.height /* not the same line */ 0.5 * textContentItem.height /* not the same line */
@ -2516,14 +2530,16 @@ class PartialEvaluator {
return; return;
} }
if (advanceX <= textContentItem.trackingSpaceMin) { if (advanceX <= textOrientation * textContentItem.trackingSpaceMin) {
textContentItem.width += advanceX; textContentItem.width += advanceX;
} else if (!addFakeSpaces(advanceX, textContentItem.prevTransform)) { } else if (
!addFakeSpaces(advanceX, textContentItem.prevTransform, textOrientation)
) {
if (textContentItem.str.length === 0) { if (textContentItem.str.length === 0) {
textContent.items.push({ textContent.items.push({
str: " ", str: " ",
dir: "ltr", dir: "ltr",
width: advanceX, width: Math.abs(advanceX),
height: 0, height: 0,
transform: textContentItem.prevTransform, transform: textContentItem.prevTransform,
fontName: textContentItem.fontName, fontName: textContentItem.fontName,
@ -2652,10 +2668,10 @@ class PartialEvaluator {
} }
} }
function addFakeSpaces(width, transf) { function addFakeSpaces(width, transf, textOrientation) {
if ( if (
textContentItem.spaceInFlowMin <= width && textOrientation * textContentItem.spaceInFlowMin <= width &&
width <= textContentItem.spaceInFlowMax width <= textOrientation * textContentItem.spaceInFlowMax
) { ) {
if (textContentItem.initialized) { if (textContentItem.initialized) {
textContentItem.str.push(" "); textContentItem.str.push(" ");
@ -2677,8 +2693,8 @@ class PartialEvaluator {
// TODO: check if using the orientation from last chunk is // TODO: check if using the orientation from last chunk is
// better or not. // better or not.
dir: "ltr", dir: "ltr",
width, width: Math.abs(width),
height, height: Math.abs(height),
transform: transf || getCurrentTextTransform(), transform: transf || getCurrentTextTransform(),
fontName, fontName,
hasEOL: false, hasEOL: false,

View File

@ -500,3 +500,4 @@
!poppler-937-0-fuzzed.pdf !poppler-937-0-fuzzed.pdf
!PDFBOX-3148-2-fuzzed.pdf !PDFBOX-3148-2-fuzzed.pdf
!poppler-90-0-fuzzed.pdf !poppler-90-0-fuzzed.pdf
!issue14415.pdf

BIN
test/pdfs/issue14415.pdf Normal file

Binary file not shown.

View File

@ -6191,5 +6191,10 @@
"link": true, "link": true,
"rounds": 1, "rounds": 1,
"type": "eq" "type": "eq"
},
{ "id": "issue14415",
"file": "pdfs/issue14415.pdf",
"md5": "fa306a250a3d37fe0e7a4b3bba51c91e",
"type": "text"
} }
] ]