You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ms...@apache.org on 2020/06/20 20:16:25 UTC

svn commit: r1879050 - in /pdfbox/trunk/pdfbox/src: main/java/org/apache/pdfbox/pdmodel/interactive/form/ test/java/org/apache/pdfbox/pdmodel/interactive/form/ test/resources/org/apache/pdfbox/pdmodel/interactive/form/

Author: msahyoun
Date: Sat Jun 20 20:16:25 2020
New Revision: 1879050

URL: http://svn.apache.org/viewvc?rev=1879050&view=rev
Log:
PDFBOX-3835: break long word for multiline text as suggested by Sebastian Fieber

Added:
    pdfbox/trunk/pdfbox/src/test/resources/org/apache/pdfbox/pdmodel/interactive/form/PDFBOX-3835-input-acrobat-wrap.pdf   (with props)
Modified:
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PlainText.java
    pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/interactive/form/MultilineFieldsTest.java

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PlainText.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PlainText.java?rev=1879050&r1=1879049&r2=1879050&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PlainText.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PlainText.java Sat Jun 20 20:16:25 2020
@@ -172,6 +172,9 @@ class PlainText
             {
                 String word = textContent.substring(start,end);
                 float wordWidth = font.getStringWidth(word) * scale;
+
+                boolean wordNeedsSplit = false;
+                int splitOffset = end - start;
                 
                 lineWidth = lineWidth + wordWidth;
 
@@ -182,7 +185,7 @@ class PlainText
                     lineWidth = lineWidth - whitespaceWidth;
                 }
                 
-                if (lineWidth >= width)
+                if (lineWidth >= width && !textLine.getWords().isEmpty())
                 {
                     textLine.setWidth(textLine.calculateWidth(font, fontSize));
                     textLines.add(textLine);
@@ -190,13 +193,40 @@ class PlainText
                     lineWidth = font.getStringWidth(word) * scale;
                 }
                 
+                if (wordWidth > width && textLine.getWords().isEmpty())
+                {
+                    // single word does not fit into width
+                    wordNeedsSplit = true;
+                    while (true)
+                    {
+                        splitOffset--;
+                        String substring = word.trim().substring(0, splitOffset);
+                        float substringWidth = font.getStringWidth(substring) * scale;
+                        if (substringWidth < width)
+                        {
+                            word = substring;
+                            wordWidth = font.getStringWidth(word) * scale;
+                            lineWidth = wordWidth;
+                            break;
+                        }
+                    }
+                }
+
                 AttributedString as = new AttributedString(word);
                 as.addAttribute(TextAttribute.WIDTH, wordWidth);
                 Word wordInstance = new Word(word);
                 wordInstance.setAttributes(as);
                 textLine.addWord(wordInstance);
-                start = end;
-                end = iterator.next();
+
+                if (wordNeedsSplit)
+                {
+                    start = start + splitOffset;
+                }
+                else
+                {
+                    start = end;
+                    end = iterator.next();
+                }
             }
             textLine.setWidth(textLine.calculateWidth(font, fontSize));
             textLines.add(textLine);

Modified: pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/interactive/form/MultilineFieldsTest.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/interactive/form/MultilineFieldsTest.java?rev=1879050&r1=1879049&r2=1879050&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/interactive/form/MultilineFieldsTest.java (original)
+++ pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/interactive/form/MultilineFieldsTest.java Sat Jun 20 20:16:25 2020
@@ -21,10 +21,13 @@ import static org.junit.Assert.assertEqu
 
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
 
 import org.apache.pdfbox.Loader;
 import org.apache.pdfbox.cos.COSName;
 import org.apache.pdfbox.cos.COSNumber;
+import org.apache.pdfbox.cos.COSString;
 import org.apache.pdfbox.pdfparser.PDFStreamParser;
 import org.apache.pdfbox.pdmodel.PDDocument;
 import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
@@ -134,6 +137,29 @@ public class MultilineFieldsTest
         assertEquals(fontSizeSinglelineAutoscale, getFontSizeFromAppearanceStream(fieldSinglelineAutoscale), 0.025f);
     }
 
+    // Test for PDFBOX-3835
+    @Test
+    public void testMultilineBreak() throws IOException
+    {
+        final String TEST_PDF = "PDFBOX-3835-input-acrobat-wrap.pdf";
+        PDDocument document = Loader.loadPDF(new File(IN_DIR, TEST_PDF));
+        PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();
+
+        // Get and store the field sizes in the original PDF
+        PDTextField fieldInput = (PDTextField) acroForm.getField("filled");
+        String fieldValue = fieldInput.getValue();
+        List<String> acrobatLines = getTextLinesFromAppearanceStream(fieldInput);
+        fieldInput.setValue(fieldValue);
+        List<String> pdfboxLines = getTextLinesFromAppearanceStream(fieldInput);
+        assertEquals("Number of lines generated by PDFBox shall match Acrobat", acrobatLines.size(),pdfboxLines.size());
+        for (int i = 0; i < acrobatLines.size(); i++)
+        {
+            assertEquals("Number of characters per lines generated by PDFBox shall match Acrobat", acrobatLines.get(i).length(), pdfboxLines.get(i).length());
+        }
+        document.close();
+    }
+
+
     private float getFontSizeFromAppearanceStream(PDField field) throws IOException
     {
     	PDAnnotationWidget widget = field.getWidgets().get(0);
@@ -156,6 +182,26 @@ public class MultilineFieldsTest
         return 0;
     }
 
+    private List<String> getTextLinesFromAppearanceStream(PDField field) throws IOException
+    {
+    	PDAnnotationWidget widget = field.getWidgets().get(0);
+    	PDFStreamParser parser = new PDFStreamParser(widget.getNormalAppearanceStream().getContents());
+    	
+        Object token = parser.parseNextToken();
+        
+        List<String> lines = new ArrayList<String>();
+    	    	
+    	while (token != null)
+    	{
+            if (token instanceof COSString)
+    		{
+                lines.add(((COSString) token).getString());
+            }
+            token = parser.parseNextToken();
+        }
+        return lines;
+    }
+
     
     @After
     public void tearDown() throws IOException

Added: pdfbox/trunk/pdfbox/src/test/resources/org/apache/pdfbox/pdmodel/interactive/form/PDFBOX-3835-input-acrobat-wrap.pdf
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/test/resources/org/apache/pdfbox/pdmodel/interactive/form/PDFBOX-3835-input-acrobat-wrap.pdf?rev=1879050&view=auto
==============================================================================
Binary file - no diff available.

Propchange: pdfbox/trunk/pdfbox/src/test/resources/org/apache/pdfbox/pdmodel/interactive/form/PDFBOX-3835-input-acrobat-wrap.pdf
------------------------------------------------------------------------------
    svn:mime-type = application/pdf