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 2014/10/22 09:41:26 UTC

svn commit: r1633548 - in /pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox: pdmodel/interactive/form/PDAppearanceString.java pdmodel/interactive/form/PDField.java util/appearance/AppearanceGenerator.java

Author: msahyoun
Date: Wed Oct 22 07:41:26 2014
New Revision: 1633548

URL: http://svn.apache.org/r1633548
Log:
PDFBOX-2333 code cleanup

Modified:
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PDAppearanceString.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PDField.java
    pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/appearance/AppearanceGenerator.java

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PDAppearanceString.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PDAppearanceString.java?rev=1633548&r1=1633547&r2=1633548&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PDAppearanceString.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PDAppearanceString.java Wed Oct 22 07:41:26 2014
@@ -46,22 +46,21 @@ import org.apache.pdfbox.pdmodel.interac
 import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceDictionary;
 import org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream;
 import org.apache.pdfbox.pdmodel.interactive.annotation.PDAnnotationWidget;
-import org.apache.pdfbox.util.appearance.AppearanceGenerator;
 import org.apache.pdfbox.contentstream.operator.Operator;
 
 /**
- * A default appearance string contains any graphics state or text state operators needed to
- * establish the graphics state parameters, such as text size and colour, for displaying the field?s
- * variable text. Only operators that are allowed within text objects shall occur in this string.
+ * A default appearance string contains any graphics state or text state operators needed to establish the graphics
+ * state parameters, such as text size and colour, for displaying the field?s variable text. Only operators that are
+ * allowed within text objects shall occur in this string.
  *
  * @author Stephan Gerhard
  * @author Ben Litchfield
  */
 public final class PDAppearanceString
 {
-	
-	private static final Log LOG = LogFactory.getLog(AppearanceGenerator.class);
-		
+
+    private static final Log LOG = LogFactory.getLog(PDAppearanceString.class);
+
     private final PDVariableText parent;
 
     private String value;
@@ -70,13 +69,11 @@ public final class PDAppearanceString
     private final PDAcroForm acroForm;
     private List<COSObjectable> widgets = new ArrayList<COSObjectable>();
 
-
     /**
-     * Constructs a COSAppearnce from the given field.
+     * Constructs a COSAppearance from the given field.
      *
-     * @param theAcroForm the acro form that this field is part of.
+     * @param theAcroForm the AcroForm that this field is part of.
      * @param field the field which you wish to control the appearance of
-     * @throws IOException If there is an error creating the appearance.
      */
     public PDAppearanceString(PDAcroForm theAcroForm, PDVariableText field)
     {
@@ -84,17 +81,18 @@ public final class PDAppearanceString
         parent = field;
 
         widgets = field.getKids();
-        if( widgets == null )
+        if (widgets == null)
         {
             widgets = new ArrayList<COSObjectable>();
-            widgets.add( field.getWidget() );
+            widgets.add(field.getWidget());
         }
         defaultAppearance = getDefaultAppearance();
     }
 
     /**
-     * Returns the default apperance of a textbox. If the textbox
-     * does not have one, then it will be taken from the AcroForm.
+     * Returns the default appearance of a textbox. If the textbox does not have one,
+     * then it will be taken from the AcroForm.
+     * 
      * @return The DA element
      */
     private COSString getDefaultAppearance()
@@ -103,13 +101,13 @@ public final class PDAppearanceString
         COSString dap = parent.getDefaultAppearance();
         if (dap == null)
         {
-            COSArray kids = (COSArray)parent.getDictionary().getDictionaryObject( COSName.KIDS );
-            if( kids != null && kids.size() > 0 )
+            COSArray kids = (COSArray) parent.getDictionary().getDictionaryObject(COSName.KIDS);
+            if (kids != null && kids.size() > 0)
             {
-                COSDictionary firstKid = (COSDictionary)kids.getObject( 0 );
-                dap = (COSString)firstKid.getDictionaryObject( COSName.DA );
+                COSDictionary firstKid = (COSDictionary) kids.getObject(0);
+                dap = (COSString) firstKid.getDictionaryObject(COSName.DA);
             }
-            if( dap == null )
+            if (dap == null)
             {
                 dap = (COSString) acroForm.getDictionary().getDictionaryObject(COSName.DA);
             }
@@ -120,14 +118,14 @@ public final class PDAppearanceString
     private int getQ()
     {
         int q = parent.getQ();
-        if( parent.getDictionary().getDictionaryObject( COSName.Q ) == null )
+        if (parent.getDictionary().getDictionaryObject(COSName.Q) == null)
         {
-            COSArray kids = (COSArray)parent.getDictionary().getDictionaryObject( COSName.KIDS );
-            if( kids != null && kids.size() > 0 )
+            COSArray kids = (COSArray) parent.getDictionary().getDictionaryObject(COSName.KIDS);
+            if (kids != null && kids.size() > 0)
             {
-                COSDictionary firstKid = (COSDictionary)kids.getObject( 0 );
-                COSNumber qNum = (COSNumber)firstKid.getDictionaryObject( COSName.Q );
-                if( qNum != null )
+                COSDictionary firstKid = (COSDictionary) kids.getObject(0);
+                COSNumber qNum = (COSNumber) firstKid.getDictionaryObject(COSName.Q);
+                if (qNum != null)
                 {
                     q = qNum.intValue();
                 }
@@ -141,39 +139,39 @@ public final class PDAppearanceString
      *
      * @return The tokens in the original appearance stream
      */
-    private List<Object> getStreamTokens( PDAppearanceStream appearanceStream ) throws IOException
+    private List<Object> getStreamTokens(PDAppearanceStream appearanceStream) throws IOException
     {
         List<Object> tokens = new ArrayList<Object>();
-        if( appearanceStream != null )
+        if (appearanceStream != null)
         {
-            tokens = getStreamTokens( appearanceStream.getStream() );
+            tokens = getStreamTokens(appearanceStream.getStream());
         }
         return tokens;
     }
 
-    private List<Object> getStreamTokens( COSString string ) throws IOException
+    private List<Object> getStreamTokens(COSString string) throws IOException
     {
         PDFStreamParser parser;
 
-        List<Object> tokens =  new ArrayList<Object>();
-        if( string != null )
+        List<Object> tokens = new ArrayList<Object>();
+        if (string != null)
         {
-            ByteArrayInputStream stream = new ByteArrayInputStream( string.getBytes() );
-            parser = new PDFStreamParser( stream );
+            ByteArrayInputStream stream = new ByteArrayInputStream(string.getBytes());
+            parser = new PDFStreamParser(stream);
             parser.parse();
             tokens = parser.getTokens();
         }
         return tokens;
     }
 
-    private List<Object> getStreamTokens( COSStream stream ) throws IOException
+    private List<Object> getStreamTokens(COSStream stream) throws IOException
     {
         PDFStreamParser parser;
 
         List<Object> tokens = new ArrayList<Object>();
-        if( stream != null )
+        if (stream != null)
         {
-            parser = new PDFStreamParser( stream );
+            parser = new PDFStreamParser(stream);
             parser.parse();
             tokens = parser.getTokens();
         }
@@ -181,15 +179,15 @@ public final class PDAppearanceString
     }
 
     /**
-     * Tests if the apperance stream already contains content.
+     * Tests if the appearance stream already contains content.
      * 
      * @param streamTokens individual tokens within the appearance stream
      *
      * @return true if it contains any content
      */
-    private boolean containsMarkedContent( List<Object> streamTokens )
+    private boolean containsMarkedContent(List<Object> streamTokens)
     {
-        return streamTokens.contains( Operator.getOperator("BMC") );
+        return streamTokens.contains(Operator.getOperator("BMC"));
     }
 
     /**
@@ -203,90 +201,90 @@ public final class PDAppearanceString
     {
         value = apValue;
         Iterator<COSObjectable> widgetIter = widgets.iterator();
-        while( widgetIter.hasNext() )
+        while (widgetIter.hasNext())
         {
             COSObjectable next = widgetIter.next();
             PDField field = null;
             PDAnnotationWidget widget;
-            if( next instanceof PDField )
+            if (next instanceof PDField)
             {
-                field = (PDField)next;
+                field = (PDField) next;
                 widget = field.getWidget();
             }
             else
             {
-                widget = (PDAnnotationWidget)next;
+                widget = (PDAnnotationWidget) next;
             }
             PDFormFieldAdditionalActions actions = null;
-            if( field != null )
+            if (field != null)
             {
                 actions = field.getActions();
             }
-            if( actions != null &&
-                actions.getF() != null &&
-                widget.getDictionary().getDictionaryObject( COSName.AP ) ==null)
+            if (actions != null && actions.getF() != null
+                    && widget.getDictionary().getDictionaryObject(COSName.AP) == null)
             {
-                //do nothing because the field will be formatted by acrobat
-                //when it is opened.  See FreedomExpressions.pdf for an example of this.
+                // do nothing because the field will be formatted by acrobat
+                // when it is opened. See FreedomExpressions.pdf for an example of this.
             }
             else
             {
 
                 PDAppearanceDictionary appearance = widget.getAppearance();
-                if( appearance == null )
+                if (appearance == null)
                 {
                     appearance = new PDAppearanceDictionary();
-                    widget.setAppearance( appearance );
+                    widget.setAppearance(appearance);
                 }
 
-                Map<String,PDAppearanceStream> normalAppearance = appearance.getNormalAppearance();
-                PDAppearanceStream appearanceStream = normalAppearance.get( "default" );
-                if( appearanceStream == null )
+                Map<String, PDAppearanceStream> normalAppearance = appearance.getNormalAppearance();
+                PDAppearanceStream appearanceStream = normalAppearance.get("default");
+                if (appearanceStream == null)
                 {
                     COSStream cosStream = acroForm.getDocument().getDocument().createCOSStream();
-                    appearanceStream = new PDAppearanceStream( cosStream );
-                    appearanceStream.setBoundingBox( widget.getRectangle().createRetranslatedRectangle() );
-                    appearance.setNormalAppearance( appearanceStream );
+                    appearanceStream = new PDAppearanceStream(cosStream);
+                    appearanceStream.setBoundingBox(widget.getRectangle()
+                            .createRetranslatedRectangle());
+                    appearance.setNormalAppearance(appearanceStream);
                 }
 
-                List<Object> tokens = getStreamTokens( appearanceStream );
-                List<Object> daTokens = getStreamTokens( getDefaultAppearance() );
-                PDFont pdFont = getFontAndUpdateResources( tokens, appearanceStream );
+                List<Object> tokens = getStreamTokens(appearanceStream);
+                List<Object> daTokens = getStreamTokens(getDefaultAppearance());
+                PDFont pdFont = getFontAndUpdateResources(tokens, appearanceStream);
 
-                if (!containsMarkedContent( tokens ))
+                if (!containsMarkedContent(tokens))
                 {
                     ByteArrayOutputStream output = new ByteArrayOutputStream();
 
-                    //BJL 9/25/2004 Must prepend existing stream
-                    //because it might have operators to draw things like
-                    //rectangles and such
-                    ContentStreamWriter writer = new ContentStreamWriter( output );
-                    writer.writeTokens( tokens );
-
-                    output.write( " /Tx BMC\n".getBytes("ISO-8859-1") );
-                    insertGeneratedAppearance( widget, output, pdFont, tokens, appearanceStream );
-                    output.write( " EMC".getBytes("ISO-8859-1") );
-                    writeToStream( output.toByteArray(), appearanceStream );
+                    // BJL 9/25/2004 Must prepend existing stream
+                    // because it might have operators to draw things like
+                    // rectangles and such
+                    ContentStreamWriter writer = new ContentStreamWriter(output);
+                    writer.writeTokens(tokens);
+
+                    output.write(" /Tx BMC\n".getBytes("ISO-8859-1"));
+                    insertGeneratedAppearance(widget, output, pdFont, tokens, appearanceStream);
+                    output.write(" EMC".getBytes("ISO-8859-1"));
+                    writeToStream(output.toByteArray(), appearanceStream);
                 }
                 else
                 {
-                    if( tokens != null )
+                    if (tokens != null)
                     {
-                        if( daTokens != null )
+                        if (daTokens != null)
                         {
-                            int bmcIndex = tokens.indexOf( Operator.getOperator("BMC"));
-                            int emcIndex = tokens.indexOf( Operator.getOperator("EMC"));
-                            if( bmcIndex != -1 && emcIndex != -1 &&
-                                emcIndex == bmcIndex+1 )
+                            int bmcIndex = tokens.indexOf(Operator.getOperator("BMC"));
+                            int emcIndex = tokens.indexOf(Operator.getOperator("EMC"));
+                            if (bmcIndex != -1 && emcIndex != -1 && emcIndex == bmcIndex + 1)
                             {
-                                //if the EMC immediately follows the BMC index then should
-                                //insert the daTokens inbetween the two markers.
-                                tokens.addAll( emcIndex, daTokens );
+                                // if the EMC immediately follows the BMC index then should
+                                // insert the daTokens inbetween the two markers.
+                                tokens.addAll(emcIndex, daTokens);
                             }
                         }
                         ByteArrayOutputStream output = new ByteArrayOutputStream();
-                        ContentStreamWriter writer = new ContentStreamWriter( output );
-                        float fontSize = calculateFontSize( pdFont, appearanceStream.getBoundingBox(), tokens, null );
+                        ContentStreamWriter writer = new ContentStreamWriter(output);
+                        float fontSize = calculateFontSize(pdFont,
+                                appearanceStream.getBoundingBox(), tokens, null);
                         boolean foundString = false;
                         for (Object token : tokens)
                         {
@@ -295,117 +293,128 @@ public final class PDAppearanceString
                                 foundString = true;
                                 COSString drawnString = (COSString) token;
                                 drawnString.reset();
-                                drawnString.append( apValue.getBytes("ISO-8859-1") );
+                                drawnString.append(apValue.getBytes("ISO-8859-1"));
                             }
                         }
-                        int setFontIndex = tokens.indexOf( Operator.getOperator("Tf"));
-                        tokens.set( setFontIndex-1, new COSFloat( fontSize ) );
-                        if( foundString )
+                        int setFontIndex = tokens.indexOf(Operator.getOperator("Tf"));
+                        tokens.set(setFontIndex - 1, new COSFloat(fontSize));
+                        if (foundString)
                         {
-                            writer.writeTokens( tokens );
+                            writer.writeTokens(tokens);
                         }
                         else
                         {
-                            int bmcIndex = tokens.indexOf( Operator.getOperator("BMC") );
-                            int emcIndex = tokens.indexOf( Operator.getOperator("EMC") );
+                            int bmcIndex = tokens.indexOf(Operator.getOperator("BMC"));
+                            int emcIndex = tokens.indexOf(Operator.getOperator("EMC"));
 
-                            if( bmcIndex != -1 )
+                            if (bmcIndex != -1)
                             {
-                                writer.writeTokens( tokens, 0, bmcIndex+1 );
+                                writer.writeTokens(tokens, 0, bmcIndex + 1);
                             }
                             else
                             {
-                                writer.writeTokens( tokens );
+                                writer.writeTokens(tokens);
                             }
-                            output.write( "\n".getBytes("ISO-8859-1") );
-                            insertGeneratedAppearance( widget, output,
-                                pdFont, tokens, appearanceStream );
-                            if( emcIndex != -1 )
+                            output.write("\n".getBytes("ISO-8859-1"));
+                            insertGeneratedAppearance(widget, output, pdFont, tokens,
+                                    appearanceStream);
+                            if (emcIndex != -1)
                             {
-                                writer.writeTokens( tokens, emcIndex, tokens.size() );
+                                writer.writeTokens(tokens, emcIndex, tokens.size());
                             }
                         }
-                        writeToStream( output.toByteArray(), appearanceStream );
+                        writeToStream(output.toByteArray(), appearanceStream);
                     }
                     else
                     {
-                        //hmm?
+                        // hmm?
                     }
                 }
             }
         }
     }
 
-    private void insertGeneratedAppearance( PDAnnotationWidget fieldWidget, OutputStream output,
-        PDFont pdFont, List<Object> tokens, PDAppearanceStream appearanceStream ) throws IOException
+    private void insertGeneratedAppearance(PDAnnotationWidget fieldWidget, OutputStream output,
+            PDFont pdFont, List<Object> tokens, PDAppearanceStream appearanceStream)
+            throws IOException
     {
-        PrintWriter printWriter = new PrintWriter( output, true );
+        PrintWriter printWriter = new PrintWriter(output, true);
         float fontSize = 0.0f;
         PDRectangle boundingBox = appearanceStream.getBoundingBox();
-        if( boundingBox == null )
+        if (boundingBox == null)
         {
             boundingBox = fieldWidget.getRectangle().createRetranslatedRectangle();
         }
-        printWriter.println( "BT" );
-        if( defaultAppearance != null )
+        printWriter.println("BT");
+        if (defaultAppearance != null)
         {
             String daString = defaultAppearance.getString();
-            PDFStreamParser daParser = new PDFStreamParser(new ByteArrayInputStream( daString.getBytes("ISO-8859-1") ) );
+            PDFStreamParser daParser = new PDFStreamParser(new ByteArrayInputStream(
+                    daString.getBytes("ISO-8859-1")));
             daParser.parse();
             List<Object> daTokens = daParser.getTokens();
-            fontSize = calculateFontSize( pdFont, boundingBox, tokens, daTokens );
-            int fontIndex = daTokens.indexOf( Operator.getOperator("Tf") );
-            if(fontIndex != -1 )
+            fontSize = calculateFontSize(pdFont, boundingBox, tokens, daTokens);
+            int fontIndex = daTokens.indexOf(Operator.getOperator("Tf"));
+            if (fontIndex != -1)
             {
-                daTokens.set( fontIndex-1, new COSFloat( fontSize ) );
+                daTokens.set(fontIndex - 1, new COSFloat(fontSize));
             }
             ContentStreamWriter daWriter = new ContentStreamWriter(output);
-            daWriter.writeTokens( daTokens );
+            daWriter.writeTokens(daTokens);
         }
-          
+
         PDRectangle borderEdge = getSmallestDrawnRectangle(boundingBox, tokens);
-        
+
         // Acrobat calculates the left and right padding dependent on the offset of the border edge
-        // TODO: verify the vertical alignment calculation
+        // This calculation works for forms having been generated by Acrobat.
+        // Need to revisit this for forms being generated with other software.
         float paddingLeft = Math.max(2, Math.round(4 * borderEdge.getLowerLeftX()));
-        float paddingRight = Math.max(2, Math.round(4 * (boundingBox.getUpperRightX() - borderEdge.getUpperRightX())));
+        float paddingRight = Math.max(2,
+                Math.round(4 * (boundingBox.getUpperRightX() - borderEdge.getUpperRightX())));
         float verticalOffset = getVerticalOffset(boundingBox, pdFont, fontSize, tokens);
-        
-        // Acrobat shifts the value so it aligns to the bottom if 
+
+        // Acrobat shifts the value so it aligns to the bottom if
         // the font's caps are larger than the height of the borderEdge
-        // TODO: verify this with more samples
-        //       verify fontHeight calculation which was taken from getVerticalOffset()
+        //
+        // This is based on a small sample of test files and might not be generally the case.
+        // The fontHeight calculation has been taken from getVerticalOffset().
+        // We potentially need to revisit that calculation
         float fontHeight = boundingBox.getHeight() - verticalOffset * 2;
-        
-        if (fontHeight + 2 * borderEdge.getLowerLeftX() > borderEdge.getHeight()) {
-        	verticalOffset = pdFont.getBoundingBox().getHeight()/1000 * fontSize - borderEdge.getHeight();
+
+        if (fontHeight + 2 * borderEdge.getLowerLeftX() > borderEdge.getHeight())
+        {
+            verticalOffset = pdFont.getBoundingBox().getHeight() / 1000 * fontSize
+                    - borderEdge.getHeight();
         }
-        
+
         float leftOffset = 0f;
-        
-        // Acrobat aligns left regardless of the quadding if the text is wider then the remaining width
-        float stringWidth = (pdFont.getStringWidth( value )/1000)*fontSize;
+
+        // Acrobat aligns left regardless of the quadding if the text is wider than the remaining width
+        float stringWidth = (pdFont.getStringWidth(value) / 1000) * fontSize;
         int q = getQ();
-        if (q == PDTextField.QUADDING_LEFT || stringWidth > borderEdge.getWidth() - paddingLeft - paddingRight)
+        if (q == PDTextField.QUADDING_LEFT
+                || stringWidth > borderEdge.getWidth() - paddingLeft - paddingRight)
         {
-        	leftOffset = paddingLeft;
-        } 
+            leftOffset = paddingLeft;
+        }
         else if (q == PDTextField.QUADDING_CENTERED)
         {
-        	leftOffset = (boundingBox.getWidth() - stringWidth) / 2; 
-        } else if (q == PDTextField.QUADDING_RIGHT)
+            leftOffset = (boundingBox.getWidth() - stringWidth) / 2;
+        }
+        else if (q == PDTextField.QUADDING_RIGHT)
+        {
+            leftOffset = boundingBox.getWidth() - stringWidth - paddingRight;
+
+        }
+        else
         {
-        	leftOffset = boundingBox.getWidth() - stringWidth - paddingRight;
-        	
-        } else 
-        {
-        	// Unknown quadding value - default to left
-        	printWriter.println(paddingLeft + " " + verticalOffset + " Td");
-        	LOG.info("Unknown justification value, defaulting to left: " + q);
+            // Unknown quadding value - default to left
+            printWriter.println(paddingLeft + " " + verticalOffset + " Td");
+            LOG.debug("Unknown justification value, defaulting to left: " + q);
         }
-        
+
         printWriter.println(leftOffset + " " + verticalOffset + " Td");
-        
+
         // add the value as hex string to deal with non ISO-8859-1 data values
         if (!isMultiLineValue(value))
         {
@@ -420,40 +429,41 @@ public final class PDAppearanceString
                 String endingTag = lastLine ? "> Tj\n" : "> Tj 0 -13 Td";
                 printWriter.print("<" + new COSString(lines[i]).getHexString() + endingTag);
             }
-        }        
-        printWriter.println("ET" );
+        }
+        printWriter.println("ET");
         printWriter.flush();
     }
 
-    private PDFont getFontAndUpdateResources( List<Object> tokens, PDAppearanceStream appearanceStream ) throws IOException
+    private PDFont getFontAndUpdateResources(List<Object> tokens,
+            PDAppearanceStream appearanceStream) throws IOException
     {
         PDFont retval = null;
         PDResources streamResources = appearanceStream.getResources();
         PDResources formResources = acroForm.getDefaultResources();
-        if( formResources != null )
+        if (formResources != null)
         {
-            if( streamResources == null )
+            if (streamResources == null)
             {
                 streamResources = new PDResources();
-                appearanceStream.setResources( streamResources );
+                appearanceStream.setResources(streamResources);
             }
 
             COSString da = getDefaultAppearance();
-            if( da != null )
+            if (da != null)
             {
                 String data = da.getString();
-                PDFStreamParser streamParser = new PDFStreamParser(
-                        new ByteArrayInputStream( data.getBytes("ISO-8859-1") ) );
+                PDFStreamParser streamParser = new PDFStreamParser(new ByteArrayInputStream(
+                        data.getBytes("ISO-8859-1")));
                 streamParser.parse();
                 tokens = streamParser.getTokens();
             }
 
-            int setFontIndex = tokens.indexOf( Operator.getOperator("Tf"));
-            COSName cosFontName = (COSName)tokens.get( setFontIndex-2 );
-            retval = streamResources.getFont( cosFontName );
-            if( retval == null )
+            int setFontIndex = tokens.indexOf(Operator.getOperator("Tf"));
+            COSName cosFontName = (COSName) tokens.get(setFontIndex - 2);
+            retval = streamResources.getFont(cosFontName);
+            if (retval == null)
             {
-                retval = formResources.getFont( cosFontName );
+                retval = formResources.getFont(cosFontName);
                 streamResources.put(cosFontName, retval);
             }
         }
@@ -464,61 +474,61 @@ public final class PDAppearanceString
     {
         return (parent.isMultiline() && value.contains("\n"));
     }
-    
+
     /**
      * Writes the stream to the actual stream in the COSStream.
      *
      * @throws IOException If there is an error writing to the stream
      */
-    private void writeToStream( byte[] data, PDAppearanceStream appearanceStream ) throws IOException
+    private void writeToStream(byte[] data, PDAppearanceStream appearanceStream) throws IOException
     {
         OutputStream out = appearanceStream.getStream().createUnfilteredStream();
-        out.write( data );
+        out.write(data);
         out.flush();
     }
 
-
     /**
      * w in an appearance stream represents the lineWidth.
+     * 
      * @return the linewidth
      */
-    private float getLineWidth( List<Object> tokens )
+    private float getLineWidth(List<Object> tokens)
     {
 
         float retval = 1;
-        if( tokens != null )
+        if (tokens != null)
         {
             int btIndex = tokens.indexOf(Operator.getOperator("BT"));
             int wIndex = tokens.indexOf(Operator.getOperator("w"));
-            //the w should only be used if it is before the first BT.
-            if( (wIndex > 0) && (wIndex < btIndex) )
+            // the w should only be used if it is before the first BT.
+            if ((wIndex > 0) && (wIndex < btIndex))
             {
-                retval = ((COSNumber)tokens.get(wIndex-1)).floatValue();
+                retval = ((COSNumber) tokens.get(wIndex - 1)).floatValue();
             }
         }
         return retval;
     }
 
-    private PDRectangle getSmallestDrawnRectangle( PDRectangle boundingBox, List<Object> tokens )
+    private PDRectangle getSmallestDrawnRectangle(PDRectangle boundingBox, List<Object> tokens)
     {
         PDRectangle smallest = boundingBox;
-        for( int i=0; i<tokens.size(); i++ )
+        for (int i = 0; i < tokens.size(); i++)
         {
-            Object next = tokens.get( i );
-            if( next == Operator.getOperator("re") )
+            Object next = tokens.get(i);
+            if (next == Operator.getOperator("re"))
             {
-                COSNumber x = (COSNumber)tokens.get( i-4 );
-                COSNumber y = (COSNumber)tokens.get( i-3 );
-                COSNumber width = (COSNumber)tokens.get( i-2 );
-                COSNumber height = (COSNumber)tokens.get( i-1 );
+                COSNumber x = (COSNumber) tokens.get(i - 4);
+                COSNumber y = (COSNumber) tokens.get(i - 3);
+                COSNumber width = (COSNumber) tokens.get(i - 2);
+                COSNumber height = (COSNumber) tokens.get(i - 1);
                 PDRectangle potentialSmallest = new PDRectangle();
-                potentialSmallest.setLowerLeftX( x.floatValue() );
-                potentialSmallest.setLowerLeftY( y.floatValue() );
-                potentialSmallest.setUpperRightX( x.floatValue() + width.floatValue() );
-                potentialSmallest.setUpperRightY( y.floatValue() + height.floatValue() );
-                if( smallest == null ||
-                    smallest.getLowerLeftX() < potentialSmallest.getLowerLeftX() ||
-                    smallest.getUpperRightY() > potentialSmallest.getUpperRightY() )
+                potentialSmallest.setLowerLeftX(x.floatValue());
+                potentialSmallest.setLowerLeftY(y.floatValue());
+                potentialSmallest.setUpperRightX(x.floatValue() + width.floatValue());
+                potentialSmallest.setUpperRightY(y.floatValue() + height.floatValue());
+                if (smallest == null
+                        || smallest.getLowerLeftX() < potentialSmallest.getLowerLeftX()
+                        || smallest.getUpperRightY() > potentialSmallest.getUpperRightY())
                 {
                     smallest = potentialSmallest;
                 }
@@ -529,97 +539,95 @@ public final class PDAppearanceString
     }
 
     /**
-     * My "not so great" method for calculating the fontsize.
-     * It does not work superb, but it handles ok.
+     * My "not so great" method for calculating the fontsize. It does not work superb, but it handles ok.
+     * 
      * @return the calculated font-size
      *
      * @throws IOException If there is an error getting the font height.
      */
-    private float calculateFontSize( PDFont pdFont, PDRectangle boundingBox, List<Object> tokens, List<Object> daTokens )
-        throws IOException
+    private float calculateFontSize(PDFont pdFont, PDRectangle boundingBox, List<Object> tokens,
+            List<Object> daTokens) throws IOException
     {
         float fontSize = 0;
-        if( daTokens != null )
+        if (daTokens != null)
         {
-            //daString looks like   "BMC /Helv 3.4 Tf EMC"
-            int fontIndex = daTokens.indexOf( Operator.getOperator("Tf") );
-            if(fontIndex != -1 )
+            // daString looks like "BMC /Helv 3.4 Tf EMC"
+            int fontIndex = daTokens.indexOf(Operator.getOperator("Tf"));
+            if (fontIndex != -1)
             {
-                fontSize = ((COSNumber)daTokens.get(fontIndex-1)).floatValue();
+                fontSize = ((COSNumber) daTokens.get(fontIndex - 1)).floatValue();
             }
         }
-        
+
         float widthBasedFontSize = Float.MAX_VALUE;
-        
-        if( parent.doNotScroll() )
+
+        if (parent.doNotScroll())
         {
-            //if we don't scroll then we will shrink the font to fit into the text area.
-            float widthAtFontSize1 = pdFont.getStringWidth( value )/1000.f;
+            // if we don't scroll then we will shrink the font to fit into the text area.
+            float widthAtFontSize1 = pdFont.getStringWidth(value) / 1000.f;
             float availableWidth = getAvailableWidth(boundingBox, getLineWidth(tokens));
             widthBasedFontSize = availableWidth / widthAtFontSize1;
         }
-        else if( fontSize == 0 )
+        else if (fontSize == 0)
         {
-            float lineWidth = getLineWidth( tokens );
+            float lineWidth = getLineWidth(tokens);
             float height = 0;
-            if( pdFont instanceof PDFont )
+            if (pdFont instanceof PDFont)
             {
-                height = ((PDFont)pdFont).getFontDescriptor().getFontBoundingBox().getHeight();
+                height = ((PDFont) pdFont).getFontDescriptor().getFontBoundingBox().getHeight();
             }
             else
             {
-                //now much we can do, so lets assume font is square and use width
-                //as the height
+                // now much we can do, so lets assume font is square and use width
+                // as the height
                 height = pdFont.getAverageFontWidth();
             }
-            height = height/1000f;
+            height = height / 1000f;
 
-            float availHeight = getAvailableHeight( boundingBox, lineWidth );
-            fontSize = Math.min((availHeight/height), widthBasedFontSize);
+            float availHeight = getAvailableHeight(boundingBox, lineWidth);
+            fontSize = Math.min((availHeight / height), widthBasedFontSize);
         }
         return fontSize;
     }
-    
-    
+
     /**
-     * Calculates where to start putting the text in the box.
-     * The positioning is not quite as accurate as when Acrobat
+     * Calculates where to start putting the text in the box. The positioning is not quite as accurate as when Acrobat
      * places the elements, but it works though.
      *
      * @return the sting for representing the start position of the text
      *
      * @throws IOException If there is an error calculating the text position.
      */
-    private float getVerticalOffset( PDRectangle boundingBox, PDFont pdFont, float fontSize, List<Object> tokens )
-        throws IOException
+    private float getVerticalOffset(PDRectangle boundingBox, PDFont pdFont, float fontSize,
+            List<Object> tokens) throws IOException
     {
-        float lineWidth = getLineWidth( tokens );
+        float lineWidth = getLineWidth(tokens);
         float verticalOffset = 0.0f;
-        if(parent.isMultiline())
+        if (parent.isMultiline())
         {
-            int rows = (int) (getAvailableHeight( boundingBox, lineWidth ) / ((int) fontSize));
-            verticalOffset = ((rows)*fontSize)-fontSize;
+            int rows = (int) (getAvailableHeight(boundingBox, lineWidth) / ((int) fontSize));
+            verticalOffset = ((rows) * fontSize) - fontSize;
         }
         else
         {
-            if( pdFont instanceof PDFont )
+            if (pdFont instanceof PDFont)
             {
-                //BJL 9/25/2004
-                //This algorithm is a little bit of black magic.  It does
-                //not appear to be documented anywhere.  Through examining a few
-                //PDF documents and the value that Acrobat places in there I
-                //have determined that the below method of computing the position
-                //is correct for certain documents, but maybe not all.  It does
-                //work f1040ez.pdf and Form_1.pdf
-                PDFontDescriptor fd = ((PDFont)pdFont).getFontDescriptor();
+                // BJL 9/25/2004
+                // This algorithm is a little bit of black magic. It does
+                // not appear to be documented anywhere. Through examining a few
+                // PDF documents and the value that Acrobat places in there I
+                // have determined that the below method of computing the position
+                // is correct for certain documents, but maybe not all. It does
+                // work f1040ez.pdf and Form_1.pdf
+                PDFontDescriptor fd = ((PDFont) pdFont).getFontDescriptor();
                 float bBoxHeight = boundingBox.getHeight();
                 float fontHeight = fd.getFontBoundingBox().getHeight() + 2 * fd.getDescent();
-                fontHeight = (fontHeight/1000) * fontSize;
-                verticalOffset = (bBoxHeight - fontHeight)/2;
+                fontHeight = (fontHeight / 1000) * fontSize;
+                verticalOffset = (bBoxHeight - fontHeight) / 2;
             }
             else
             {
-                LOG.info( "Unable to calculate the vertical offset for non-simple fonts - using 0 instead" );
+                LOG.debug("Unable to calculate the vertical offset for non-simple fonts - using 0 instead");
             }
         }
         return verticalOffset;
@@ -627,18 +635,20 @@ public final class PDAppearanceString
 
     /**
      * calculates the available width of the box.
+     * 
      * @return the calculated available width of the box
      */
-    private float getAvailableWidth( PDRectangle boundingBox, float lineWidth )
+    private float getAvailableWidth(PDRectangle boundingBox, float lineWidth)
     {
         return boundingBox.getWidth() - 2 * lineWidth;
     }
 
     /**
      * calculates the available height of the box.
+     * 
      * @return the calculated available height of the box
      */
-    private float getAvailableHeight( PDRectangle boundingBox, float lineWidth )
+    private float getAvailableHeight(PDRectangle boundingBox, float lineWidth)
     {
         return boundingBox.getHeight() - 2 * lineWidth;
     }

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PDField.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PDField.java?rev=1633548&r1=1633547&r2=1633548&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PDField.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/form/PDField.java Wed Oct 22 07:41:26 2014
@@ -123,10 +123,18 @@ public abstract class PDField extends PD
         return fieldType;
     }
     
-    protected void updateFieldAppearances() {
-    	if (!getAcroForm().isNeedAppearances()) {
-    		AppearanceGenerator.generateFieldAppearances(this);
-    	}
+    /**
+     * Update the fields appearance stream.
+     * 
+     * The fields appearance stream needs to be updated to reflect the new field
+     * value. This will be done only if the NeedAppearances flag has not been set.
+     */
+    protected void updateFieldAppearances()
+    {
+        if (!getAcroForm().isNeedAppearances())
+        {
+            AppearanceGenerator.generateFieldAppearances(this);
+        }
     }
 
 

Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/appearance/AppearanceGenerator.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/appearance/AppearanceGenerator.java?rev=1633548&r1=1633547&r2=1633548&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/appearance/AppearanceGenerator.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/util/appearance/AppearanceGenerator.java Wed Oct 22 07:41:26 2014
@@ -28,48 +28,59 @@ import org.apache.pdfbox.pdmodel.interac
 /**
  * (Re-) Generate the appearance for a field.
  * 
- * The fields appearance defines the 'look' the field has when it's rendered
- * for display or printing.
+ * The fields appearance defines the 'look' the field has when it's rendered for display or printing.
  * 
  */
 
-public class AppearanceGenerator {
-	
-	private static final Log LOG = LogFactory.getLog(AppearanceGenerator.class);
-	
-	private AppearanceGenerator() {
-	}
-	
-	
-	/**
-	 * Generate the appearances for a single field.
-	 * 
-	 * @param field The field which appearances need to be generated.
-	 */
-	public static void generateFieldAppearances(PDField field) {
-		// TODO: handle appearance generation for other field types
-		if (field instanceof PDVariableText) {
-			
-			PDAppearanceString pdAppearance = new PDAppearanceString(field.getAcroForm(), (PDVariableText) field);
-			
-			Object fieldValue = field.getValue();
-			
-			// in case there is no value being set generate the visual 
-			// appearance with an empty String
-			if (fieldValue == null) {
-				fieldValue = "";
-			}
-			
-			// TODO: implement the handling for additional values.
-			if (fieldValue instanceof COSString) {
-				try {
-					pdAppearance.setAppearanceValue(((COSString) fieldValue).getString());
-				} catch (IOException e) {
-					LOG.error("Unable to generate the field appearance.", e);
-				}
-			} else {
-				LOG.warn("Can't generate the appearance for values typed " + fieldValue.getClass().getName() + ".");
-			}
-		}
-	}
+public class AppearanceGenerator
+{
+
+    private static final Log LOG = LogFactory.getLog(AppearanceGenerator.class);
+
+    private AppearanceGenerator()
+    {
+    }
+
+    /**
+     * Generate the appearances for a single field.
+     * 
+     * @param field The field which appearances need to be generated.
+     */
+    public static void generateFieldAppearances(PDField field)
+    {
+        // TODO: handle appearance generation for other field types
+        if (field instanceof PDVariableText)
+        {
+
+            PDAppearanceString pdAppearance = new PDAppearanceString(field.getAcroForm(),
+                    (PDVariableText) field);
+
+            Object fieldValue = field.getValue();
+
+            // in case there is no value being set generate the visual
+            // appearance with an empty String
+            if (fieldValue == null)
+            {
+                fieldValue = "";
+            }
+
+            // TODO: implement the handling for additional values.
+            if (fieldValue instanceof COSString)
+            {
+                try
+                {
+                    pdAppearance.setAppearanceValue(((COSString) fieldValue).getString());
+                }
+                catch (IOException e)
+                {
+                    LOG.debug("Unable to generate the field appearance.", e);
+                }
+            }
+            else
+            {
+                LOG.debug("Can't generate the appearance for values typed "
+                        + fieldValue.getClass().getName() + ".");
+            }
+        }
+    }
 }