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() + ".");
+ }
+ }
+ }
}