You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ti...@apache.org on 2024/12/16 16:57:04 UTC
svn commit: r1922535 - in /pdfbox/trunk/pdfbox/src: main/java/org/apache/pdfbox/text/PDFTextStripper.java test/java/org/apache/pdfbox/text/TestTextStripper.java
Author: tilman
Date: Mon Dec 16 16:57:04 2024
New Revision: 1922535
URL: http://svn.apache.org/viewvc?rev=1922535&view=rev
Log:
PDFBOX-3774: conditionally ignore spaces from the content stream; add setting + getter/setter + test + code simplification by Kevin Day
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/text/PDFTextStripper.java
pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/text/TestTextStripper.java
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/text/PDFTextStripper.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/text/PDFTextStripper.java?rev=1922535&r1=1922534&r2=1922535&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/text/PDFTextStripper.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/text/PDFTextStripper.java Mon Dec 16 16:57:04 2024
@@ -146,6 +146,7 @@ public class PDFTextStripper extends Leg
private boolean shouldSeparateByBeads = true;
private boolean sortByPosition = false;
private boolean addMoreFormatting = false;
+ private boolean ignoreContentStreamSpaceGlyphs = false;
private float indentThreshold = defaultIndentThreshold;
private float dropThreshold = defaultDropThreshold;
@@ -523,11 +524,8 @@ public class PDFTextStripper extends Leg
{
IterativeMergeSort.sort(textList, comparator);
}
- finally
- {
- // PDFBOX-5487: Remove all space characters if contained within the adjacent letters
- removeContainedSpaces(textList);
- }
+ // PDFBOX-5487: Remove all space characters if contained within the adjacent letters
+ removeContainedSpaces(textList);
}
startArticle();
@@ -555,6 +553,12 @@ public class PDFTextStripper extends Leg
PositionWrapper current = new PositionWrapper(position);
String characterValue = position.getUnicode();
+ // PDFBOX-3774: conditionally ignore spaces from the content stream
+ if (" ".equals(characterValue) && getIgnoreContentStreamSpaceGlyphs())
+ {
+ continue;
+ }
+
// Resets the average character width when we see a change in font
// or a change in the font size
if (lastPosition != null &&
@@ -1277,6 +1281,32 @@ public class PDFTextStripper extends Leg
}
/**
+ * Determines whether spaces in the content stream text rendering instructions will be ignored
+ * during text extraction.
+ *
+ * @return true is space glyphs in the content stream text rendering instructions will be
+ * ignored - default is false
+ */
+ public boolean getIgnoreContentStreamSpaceGlyphs()
+ {
+ return ignoreContentStreamSpaceGlyphs;
+ }
+
+ /**
+ * Instruct the algorithm to ignore any spaces in the text rendering instructions in the content
+ * stream, and instead rely purely on the algorithm to determine where word breaks are.
+ *
+ * This can improve text extraction results where the content stream is sorted by position and
+ * has text overlapping spaces, but could cause some word breaks to not be added to the output
+ *
+ * @param newIgnoreContentStreamSpaceGlyphs whether PDF Box should ignore context stream spaces
+ */
+ public void setIgnoreContentStreamSpaceGlyphs(boolean newIgnoreContentStreamSpaceGlyphs)
+ {
+ ignoreContentStreamSpaceGlyphs = newIgnoreContentStreamSpaceGlyphs;
+ }
+
+ /**
* Get the current space width-based tolerance value that is being used to estimate where spaces in text should be
* added. Note that the default value for this has been determined from trial and error.
*
Modified: pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/text/TestTextStripper.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/text/TestTextStripper.java?rev=1922535&r1=1922534&r2=1922535&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/text/TestTextStripper.java (original)
+++ pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/text/TestTextStripper.java Mon Dec 16 16:57:04 2024
@@ -54,9 +54,13 @@ import org.apache.logging.log4j.LogManag
import org.apache.fontbox.util.BoundingBox;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.PDPage;
+import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDFontDescriptor;
+import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.pdfbox.pdmodel.font.PDType3Font;
+import org.apache.pdfbox.pdmodel.font.Standard14Fonts;
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.destination.PDPageDestination;
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDDocumentOutline;
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem;
@@ -688,4 +692,51 @@ class TestTextStripper
assertEquals(1378, text.replaceAll("\r", "").length());
}
}
+
+ /**
+ * PDFBOX-3774: test the IgnoreContentStreamSpaceGlyphs option.
+ *
+ * @throws Exception
+ */
+ @Test
+ void testIgnoreContentStreamSpaceGlyphs() throws Exception
+ {
+ try (PDDocument doc = new PDDocument())
+ {
+ PDPage page = new PDPage();
+ try (PDPageContentStream cs = new PDPageContentStream(doc, page))
+ {
+ float fontHeight = 8;
+ float x = 50;
+ float y = page.getMediaBox().getHeight() - 50;
+ PDFont font = new PDType1Font(Standard14Fonts.FontName.HELVETICA);
+ cs.beginText();
+ cs.setFont(font, fontHeight);
+ cs.newLineAtOffset(x, y);
+ cs.showText("( )");
+ cs.endText();
+
+ int indent = 6;
+ float overlapX = x + indent * font.getAverageFontWidth() / 1000f * fontHeight;
+ PDFont overlapFont = new PDType1Font(Standard14Fonts.FontName.TIMES_ROMAN);
+ cs.beginText();
+ cs.setFont(overlapFont, fontHeight * 2f);
+ cs.newLineAtOffset(overlapX, y);
+ cs.showText("overlap");
+ cs.endText();
+ }
+ doc.addPage(page);
+
+ PDFTextStripper localStripper = new PDFTextStripper();
+ localStripper.setLineSeparator("\n");
+ localStripper.setPageEnd("\n");
+ localStripper.setStartPage(1);
+ localStripper.setEndPage(1);
+ localStripper.setSortByPosition(true);
+
+ localStripper.setIgnoreContentStreamSpaceGlyphs(true);
+ String text = localStripper.getText(doc);
+ assertEquals("( overlap )\n", text);
+ }
+ }
}