📄 pdappearance.java
字号:
if( foundString )
{
writer.writeTokens( tokens );
}
else
{
int bmcIndex = tokens.indexOf( PDFOperator.getOperator( "BMC" ) );
int emcIndex = tokens.indexOf( PDFOperator.getOperator( "EMC" ) );
if( bmcIndex != -1 )
{
writer.writeTokens( tokens, 0, bmcIndex+1 );
}
else
{
writer.writeTokens( tokens );
}
output.write( "\n".getBytes() );
insertGeneratedAppearance( widget, output,
pdFont, tokens, appearanceStream );
if( emcIndex != -1 )
{
writer.writeTokens( tokens, emcIndex, tokens.size() );
}
}
writeToStream( output.toByteArray(), appearanceStream );
}
else
{
//hmm?
}
}
}
}
}
private void insertGeneratedAppearance( PDAnnotationWidget fieldWidget, OutputStream output,
PDFont pdFont, List tokens, PDAppearanceStream appearanceStream ) throws IOException
{
PrintWriter printWriter = new PrintWriter( output, true );
float fontSize = 0.0f;
PDRectangle boundingBox = null;
boundingBox = appearanceStream.getBoundingBox();
if( boundingBox == null )
{
boundingBox = fieldWidget.getRectangle().createRetranslatedRectangle();
}
printWriter.println( "BT" );
if( defaultAppearance != null )
{
String daString = defaultAppearance.getString();
PDFStreamParser daParser = new PDFStreamParser(new ByteArrayInputStream( daString.getBytes() ), null );
daParser.parse();
List daTokens = daParser.getTokens();
fontSize = calculateFontSize( pdFont, boundingBox, tokens, daTokens );
int fontIndex = daTokens.indexOf( PDFOperator.getOperator( "Tf" ) );
if(fontIndex != -1 )
{
daTokens.set( fontIndex-1, new COSFloat( fontSize ) );
}
ContentStreamWriter daWriter = new ContentStreamWriter(output);
daWriter.writeTokens( daTokens );
}
printWriter.println( getTextPosition( boundingBox, pdFont, fontSize, tokens ) );
int q = getQ();
if( q == PDTextbox.QUADDING_LEFT )
{
//do nothing because left is default
}
else if( q == PDTextbox.QUADDING_CENTERED ||
q == PDTextbox.QUADDING_RIGHT )
{
float fieldWidth = boundingBox.getWidth();
float stringWidth = (pdFont.getStringWidth( value )/1000)*fontSize;
float adjustAmount = fieldWidth - stringWidth - 4;
if( q == PDTextbox.QUADDING_CENTERED )
{
adjustAmount = adjustAmount/2.0f;
}
printWriter.println( adjustAmount + " 0 Td" );
}
else
{
throw new IOException( "Error: Unknown justification value:" + q );
}
printWriter.println("(" + value + ") Tj");
printWriter.println("ET" );
printWriter.flush();
}
private PDFont getFontAndUpdateResources( List tokens, PDAppearanceStream appearanceStream ) throws IOException
{
PDFont retval = null;
PDResources streamResources = appearanceStream.getResources();
PDResources formResources = acroForm.getDefaultResources();
if( formResources != null )
{
if( streamResources == null )
{
streamResources = new PDResources();
appearanceStream.setResources( streamResources );
}
COSString da = getDefaultAppearance();
if( da != null )
{
String data = da.getString();
PDFStreamParser streamParser = new PDFStreamParser(
new ByteArrayInputStream( data.getBytes() ), null );
streamParser.parse();
tokens = streamParser.getTokens();
}
int setFontIndex = tokens.indexOf( PDFOperator.getOperator( "Tf" ));
COSName cosFontName = (COSName)tokens.get( setFontIndex-2 );
String fontName = cosFontName.getName();
retval = (PDFont)streamResources.getFonts().get( fontName );
if( retval == null )
{
retval = (PDFont)formResources.getFonts().get( fontName );
streamResources.getFonts().put( fontName, retval );
}
}
return retval;
}
private String convertToMultiLine( String line )
{
int currIdx = 0;
int lastIdx = 0;
StringBuffer result = new StringBuffer(line.length() + 64);
while( (currIdx = line.indexOf('\n',lastIdx )) > -1 )
{
result.append(line.substring(lastIdx,currIdx));
result.append(" ) Tj\n0 -13 Td\n(");
lastIdx = currIdx + 1;
}
result.append(line.substring(lastIdx));
return result.toString();
}
/**
* 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
{
OutputStream out = appearanceStream.getStream().createUnfilteredStream();
out.write( data );
out.flush();
}
/**
* w in an appearance stream represents the lineWidth.
* @return the linewidth
*/
private float getLineWidth( List tokens )
{
float retval = 1;
if( tokens != null )
{
int btIndex = tokens.indexOf(PDFOperator.getOperator( "BT" ));
int wIndex = tokens.indexOf(PDFOperator.getOperator( "w" ));
//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();
}
}
return retval;
}
private PDRectangle getSmallestDrawnRectangle( PDRectangle boundingBox, List tokens )
{
PDRectangle smallest = boundingBox;
for( int i=0; i<tokens.size(); i++ )
{
Object next = tokens.get( i );
if( next == PDFOperator.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 );
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() )
{
smallest = potentialSmallest;
}
}
}
return smallest;
}
/**
* 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 tokens, List daTokens )
throws IOException
{
float fontSize = 0;
if( daTokens != null )
{
//daString looks like "BMC /Helv 3.4 Tf EMC"
int fontIndex = daTokens.indexOf( PDFOperator.getOperator( "Tf" ) );
if(fontIndex != -1 )
{
fontSize = ((COSNumber)daTokens.get(fontIndex-1)).floatValue();
}
}
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 );
float availableWidth = boundingBox.getWidth();
float perfectFitFontSize = availableWidth / widthAtFontSize1;
}
else if( fontSize == 0 )
{
float lineWidth = getLineWidth( tokens );
float stringWidth = pdFont.getStringWidth( value );
float height = 0;
if( pdFont instanceof PDSimpleFont )
{
height = ((PDSimpleFont)pdFont).getFontDescriptor().getFontBoundingBox().getHeight();
}
else
{
//now much we can do, so lets assume font is square and use width
//as the height
height = pdFont.getAverageFontWidth();
}
height = height/1000f;
float availHeight = getAvailableHeight( boundingBox, lineWidth );
fontSize =(availHeight/height);
}
return fontSize;
}
/**
* 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 String getTextPosition( PDRectangle boundingBox, PDFont pdFont, float fontSize, List tokens )
throws IOException
{
float lineWidth = getLineWidth( tokens );
float pos = 0.0f;
if(parent.isMultiline())
{
int rows = (int) (getAvailableHeight( boundingBox, lineWidth ) / ((int) fontSize));
pos = ((rows)*fontSize)-fontSize;
}
else
{
if( pdFont instanceof PDSimpleFont )
{
//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 = ((PDSimpleFont)pdFont).getFontDescriptor();
float bBoxHeight = boundingBox.getHeight();
float fontHeight = fd.getFontBoundingBox().getHeight() + 2 * fd.getDescent();
fontHeight = (fontHeight/1000) * fontSize;
pos = (bBoxHeight - fontHeight)/2;
}
else
{
throw new IOException( "Error: Don't know how to calculate the position for non-simple fonts" );
}
}
PDRectangle innerBox = getSmallestDrawnRectangle( boundingBox, tokens );
float xInset = 2+ 2*(boundingBox.getWidth() - innerBox.getWidth());
return Math.round(xInset) + " "+ pos + " Td";
}
/**
* calculates the available width of the box.
* @return the calculated available width of the box
*/
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 )
{
return boundingBox.getHeight() - 2 * lineWidth;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -