⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pdappearance.java

📁 非常有用的操作pdf文件的java源码
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
                        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 + -