Java Code Examples for org.apache.pdfbox.io.IOUtils#closeQuietly()

The following examples show how to use org.apache.pdfbox.io.IOUtils#closeQuietly() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: ASCII85Filter.java    From gcs with Mozilla Public License 2.0 6 votes vote down vote up
@Override
public DecodeResult decode(InputStream encoded, OutputStream decoded,
                                     COSDictionary parameters, int index) throws IOException
{
    ASCII85InputStream is = null;
    try
    {
        is = new ASCII85InputStream(encoded);
        IOUtils.copy(is, decoded);
        decoded.flush();
    }
    finally
    {
        IOUtils.closeQuietly(is);
    }
    return new DecodeResult(parameters);
}
 
Example 2
Source File: Version.java    From gcs with Mozilla Public License 2.0 6 votes vote down vote up
/**
 * Returns the version of PDFBox.
 */
public static String getVersion()
{
    InputStream is = null;
    try
    {
        is = Version.class.getResourceAsStream(PDFBOX_VERSION_PROPERTIES);
        if (is == null)
        {
            return null;
        }
        Properties properties = new Properties();
        properties.load(is);
        return properties.getProperty("pdfbox.version", null);
    }
    catch (IOException io)
    {
        return null;
    }
    finally
    {
        IOUtils.closeQuietly(is);
    }
}
 
Example 3
Source File: PDCIDFont.java    From gcs with Mozilla Public License 2.0 6 votes vote down vote up
final int[] readCIDToGIDMap() throws IOException
{
    int[] cid2gid = null;
    COSBase map = dict.getDictionaryObject(COSName.CID_TO_GID_MAP);
    if (map instanceof COSStream)
    {
        COSStream stream = (COSStream) map;

        InputStream is = stream.createInputStream();
        byte[] mapAsBytes = IOUtils.toByteArray(is);
        IOUtils.closeQuietly(is);
        int numberOfInts = mapAsBytes.length / 2;
        cid2gid = new int[numberOfInts];
        int offset = 0;
        for (int index = 0; index < numberOfInts; index++)
        {
            int gid = (mapAsBytes[offset] & 0xff) << 8 | mapAsBytes[offset + 1] & 0xff;
            cid2gid[index] = gid;
            offset += 2;
        }
    }
    return cid2gid;
}
 
Example 4
Source File: PDDocument.java    From gcs with Mozilla Public License 2.0 6 votes vote down vote up
private static PDDocument load(RandomAccessBufferedFileInputStream raFile, String password,
                               InputStream keyStore, String alias,
                               MemoryUsageSetting memUsageSetting) throws IOException
{
    ScratchFile scratchFile = new ScratchFile(memUsageSetting);
    try
    {
        PDFParser parser = new PDFParser(raFile, password, keyStore, alias, scratchFile);
        parser.parse();
        return parser.getPDDocument();
    }
    catch (IOException ioe)
    {
        IOUtils.closeQuietly(scratchFile);
        throw ioe;
    }
}
 
Example 5
Source File: PDDocument.java    From gcs with Mozilla Public License 2.0 6 votes vote down vote up
/**
 * Parses a PDF.
 * 
 * @param file file to be loaded
 * @param password password to be used for decryption
 * @param keyStore key store to be used for decryption when using public key security 
 * @param alias alias to be used for decryption when using public key security
 * @param memUsageSetting defines how memory is used for buffering PDF streams 
 * 
 * @return loaded document
 * 
 * @throws IOException in case of a file reading or parsing error
 */
public static PDDocument load(File file, String password, InputStream keyStore, String alias,
                              MemoryUsageSetting memUsageSetting) throws IOException
{
    @SuppressWarnings({"squid:S2095"}) // raFile not closed here, may be needed for signing
    RandomAccessBufferedFileInputStream raFile = new RandomAccessBufferedFileInputStream(file);
    try
    {
        return load(raFile, password, keyStore, alias, memUsageSetting);
    }
    catch (IOException ioe)
    {
        IOUtils.closeQuietly(raFile);
        throw ioe;
    }
}
 
Example 6
Source File: PDImageXObject.java    From gcs with Mozilla Public License 2.0 6 votes vote down vote up
/**
 * Creates an Image XObject with the given stream as its contents and current color spaces. This
 * constructor is for internal PDFBox use and is not for PDF generation. Users who want to
 * create images should look at {@link #createFromFileByExtension(File, PDDocument) }.
 *
 * @param stream the XObject stream to read
 * @param resources the current resources
 * @throws java.io.IOException if there is an error creating the XObject.
 */
public PDImageXObject(PDStream stream, PDResources resources) throws IOException
{
    super(stream, COSName.IMAGE);
    this.resources = resources;
    List<COSName> filters = stream.getFilters();
    if (filters != null && !filters.isEmpty() && COSName.JPX_DECODE.equals(filters.get(filters.size()-1)))
    {
        COSInputStream is = null;
        try
        {
            is = stream.createInputStream();
            DecodeResult decodeResult = is.getDecodeResult();
            stream.getCOSObject().addAll(decodeResult.getParameters());
            this.colorSpace = decodeResult.getJPXColorSpace();
        }
        finally
        {
            IOUtils.closeQuietly(is);
        }
    }
}
 
Example 7
Source File: FDFParser.java    From gcs with Mozilla Public License 2.0 6 votes vote down vote up
/**
 * This will parse the stream and populate the COSDocument object.
 *
 * @throws IOException If there is an error reading from the stream or corrupt data
 * is found.
 */
public void parse() throws IOException
{
     // set to false if all is processed
     boolean exceptionOccurred = true; 
     try
     {
        if (!parseFDFHeader())
        {
            throw new IOException( "Error: Header doesn't contain versioninfo" );
        }
        initialParse();
        exceptionOccurred = false;
    }
    finally
    {
        if (exceptionOccurred && document != null)
        {
            IOUtils.closeQuietly(document);
            document = null;
        }
    }
}
 
Example 8
Source File: COSStream.java    From gcs with Mozilla Public License 2.0 6 votes vote down vote up
/**
 * Returns the contents of the stream as a PDF "text string".
 * 
 * @return the text string representation of this stream.
 */
public String toTextString()
{
    ByteArrayOutputStream out = new ByteArrayOutputStream();
    InputStream input = null;
    try
    {
        input = createInputStream();
        IOUtils.copy(input, out);
    }
    catch (IOException e)
    {
        return "";
    }
    finally
    {
        IOUtils.closeQuietly(input);
    }
    COSString string = new COSString(out.toByteArray());
    return string.getString();
}
 
Example 9
Source File: PDFParser.java    From gcs with Mozilla Public License 2.0 5 votes vote down vote up
/**
 * This will parse the stream and populate the COSDocument object.  This will close
 * the keystore stream when it is done parsing.
 *
 * @throws InvalidPasswordException If the password is incorrect.
 * @throws IOException If there is an error reading from the stream or corrupt data
 * is found.
 */
public void parse() throws IOException
{
     // set to false if all is processed
     boolean exceptionOccurred = true; 
     try
     {
        // PDFBOX-1922 read the version header and rewind
        if (!parsePDFHeader() && !parseFDFHeader())
        {
            throw new IOException( "Error: Header doesn't contain versioninfo" );
        }

        if (!initialParseDone)
        {
            initialParse();
        }
        exceptionOccurred = false;
    }
    finally
    {
        if (exceptionOccurred && document != null)
        {
            IOUtils.closeQuietly(document);
            document = null;
        }
    }
}
 
Example 10
Source File: COSStream.java    From gcs with Mozilla Public License 2.0 5 votes vote down vote up
/**
 * Returns a new OutputStream for writing stream data, using and the given filters.
 * 
 * @param filters COSArray or COSName of filters to be used.
 * @return OutputStream for un-encoded stream data.
 * @throws IOException If the output stream could not be created.
 */
public OutputStream createOutputStream(COSBase filters) throws IOException
{
    checkClosed();
    if (isWriting)
    {
        throw new IllegalStateException("Cannot have more than one open stream writer.");
    }
    // apply filters, if any
    if (filters != null)
    {
        setItem(COSName.FILTER, filters);
    }
    IOUtils.closeQuietly(randomAccess);
    randomAccess = scratchFile.createBuffer();
    OutputStream randomOut = new RandomAccessOutputStream(randomAccess);
    OutputStream cosOut = new COSOutputStream(getFilterList(), this, randomOut, scratchFile);
    isWriting = true;
    return new FilterOutputStream(cosOut)
    {
        @Override
        public void write(byte[] b, int off, int len) throws IOException
        {
            this.out.write(b, off, len);
        }
        
        @Override
        public void close() throws IOException
        {
            super.close();
            setInt(COSName.LENGTH, (int)randomAccess.length());
            isWriting = false;
        }
    };
}
 
Example 11
Source File: PDFont.java    From gcs with Mozilla Public License 2.0 5 votes vote down vote up
/**
 * Reads a CMap given a COS Stream or Name. May return null if a predefined CMap does not exist.
 *
 * @param base COSName or COSStream
 */
protected final CMap readCMap(COSBase base) throws IOException
{
    if (base instanceof COSName)
    {
        // predefined CMap
        String name = ((COSName)base).getName();
        return CMapManager.getPredefinedCMap(name);
    }
    else if (base instanceof COSStream)
    {
        // embedded CMap
        InputStream input = null;
        try
        {
            input = ((COSStream)base).createInputStream();
            return CMapManager.parseCMap(input);
        }
        finally
        {
            IOUtils.closeQuietly(input);
        }
    }
    else
    {
        throw new IOException("Expected Name or Stream");
    }
}
 
Example 12
Source File: PDStream.java    From gcs with Mozilla Public License 2.0 5 votes vote down vote up
/**
 * If there are not compression filters on the current stream then this will
 * add a compression filter, flate compression for example.
 * 
 * @deprecated This method is inefficient. To copying an existing InputStream, use
 *             {@link #PDStream(PDDocument, InputStream, COSName)} instead, with
 *             COSName.FLATE_DECODE as the final argument.
 *             
 *             Otherwise, to write new compressed data, use {@link #createOutputStream(COSName)},
 *             with COSName.FLATE_DECODE as the argument.
 */
@Deprecated
public void addCompression()
{
    List<COSName> filters = getFilters();
    if (filters == null)
    {
        if (stream.getLength() > 0)
        {
            OutputStream out = null;
            try
            {
                byte[] bytes = IOUtils.toByteArray(stream.createInputStream());
                out = stream.createOutputStream(COSName.FLATE_DECODE);
                out.write(bytes);
            }
            catch (IOException e)
            {
                // not much else we can do here without breaking the existing API, sorry.
                throw new RuntimeException(e);
            }
            finally
            {
                IOUtils.closeQuietly(out);
            }
        }
        else
        {
            filters = new ArrayList<COSName>();
            filters.add(COSName.FLATE_DECODE);
            setFilters(filters);
        }
    }
}
 
Example 13
Source File: COSStream.java    From gcs with Mozilla Public License 2.0 5 votes vote down vote up
/**
 * Returns a new OutputStream for writing encoded PDF data. Experts only!
 * 
 * @return OutputStream for raw PDF stream data.
 * @throws IOException If the output stream could not be created.
 */
public OutputStream createRawOutputStream() throws IOException
{
    checkClosed();
    if (isWriting)
    {
        throw new IllegalStateException("Cannot have more than one open stream writer.");
    }
    IOUtils.closeQuietly(randomAccess);
    randomAccess = scratchFile.createBuffer();
    OutputStream out = new RandomAccessOutputStream(randomAccess);
    isWriting = true;
    return new FilterOutputStream(out)
    {
        @Override
        public void write(byte[] b, int off, int len) throws IOException
        {
            this.out.write(b, off, len);
        }
        
        @Override
        public void close() throws IOException
        {
            super.close();
            setInt(COSName.LENGTH, (int)randomAccess.length());
            isWriting = false;
        }
    };
}
 
Example 14
Source File: SampledImageReader.java    From gcs with Mozilla Public License 2.0 4 votes vote down vote up
private static BufferedImage from8bit(PDImage pdImage, WritableRaster raster, Rectangle clipped, final int subsampling,
                                      final int width, final int height) throws IOException
{
    int currentSubsampling = subsampling;
    DecodeOptions options = new DecodeOptions(currentSubsampling);
    options.setSourceRegion(clipped);
    InputStream input = pdImage.createInputStream(options);
    try
    {
        final int inputWidth;
        final int startx;
        final int starty;
        final int scanWidth;
        final int scanHeight;
        if (options.isFilterSubsampled())
        {
            // Decode options were honored, and so there is no need for additional clipping or subsampling
            inputWidth = width;
            startx = 0;
            starty = 0;
            scanWidth = width;
            scanHeight = height;
            currentSubsampling = 1;
        }
        else
        {
            // Decode options not honored, so we need to clip and subsample ourselves.
            inputWidth = pdImage.getWidth();
            startx = clipped.x;
            starty = clipped.y;
            scanWidth = clipped.width;
            scanHeight = clipped.height;
        }
        final int numComponents = pdImage.getColorSpace().getNumberOfComponents();
        // get the raster's underlying byte buffer
        byte[] bank = ((DataBufferByte) raster.getDataBuffer()).getData();
        if (startx == 0 && starty == 0 && scanWidth == width && scanHeight == height && currentSubsampling == 1)
        {
            // we just need to copy all sample data, then convert to RGB image.
            long inputResult = input.read(bank);
            if (inputResult != width * height * (long) numComponents)
            {
                LOG.debug("Tried reading " + width * height * (long) numComponents + " bytes but only " + inputResult + " bytes read");
            }
            return pdImage.getColorSpace().toRGBImage(raster);
        }

        // either subsampling is required, or reading only part of the image, so its
        // not possible to blindly copy all data.
        byte[] tempBytes = new byte[numComponents * inputWidth];
        // compromise between memory and time usage:
        // reading the whole image consumes too much memory
        // reading one pixel at a time makes it slow in our buffering infrastructure 
        int i = 0;
        for (int y = 0; y < starty + scanHeight; ++y)
        {
            input.read(tempBytes);
            if (y < starty || y % currentSubsampling > 0)
            {
                continue;
            }

            if (currentSubsampling == 1)
            {
                // Not the entire region was requested, but if no subsampling should
                // be performed, we can still copy the entire part of this row
                System.arraycopy(tempBytes, startx * numComponents, bank, y * inputWidth * numComponents, scanWidth * numComponents);
            }
            else
            {
                for (int x = startx; x < startx + scanWidth; x += currentSubsampling)
                {
                    for (int c = 0; c < numComponents; c++)
                    {
                        bank[i] = tempBytes[x * numComponents + c];
                        ++i;
                    }
                }
            }
        }
        // use the color space to convert the image to RGB
        return pdImage.getColorSpace().toRGBImage(raster);
    }
    finally
    {
        IOUtils.closeQuietly(input);
    }
}
 
Example 15
Source File: JPEGFactory.java    From gcs with Mozilla Public License 2.0 4 votes vote down vote up
private static void encodeImageToJPEGStream(BufferedImage image, float quality, int dpi,
                                            OutputStream out) throws IOException
{
    // encode to JPEG
    ImageOutputStream ios = null;
    ImageWriter imageWriter = null;
    try
    {
        // find JAI writer
        imageWriter = getJPEGImageWriter();
        ios = ImageIO.createImageOutputStream(out);
        imageWriter.setOutput(ios);

        // add compression
        JPEGImageWriteParam jpegParam = (JPEGImageWriteParam)imageWriter.getDefaultWriteParam();
        jpegParam.setCompressionMode(JPEGImageWriteParam.MODE_EXPLICIT);
        jpegParam.setCompressionQuality(quality);

        // add metadata
        ImageTypeSpecifier imageTypeSpecifier = new ImageTypeSpecifier(image);
        IIOMetadata data = imageWriter.getDefaultImageMetadata(imageTypeSpecifier, jpegParam);
        Element tree = (Element)data.getAsTree("javax_imageio_jpeg_image_1.0");
        Element jfif = (Element)tree.getElementsByTagName("app0JFIF").item(0);
        jfif.setAttribute("Xdensity", Integer.toString(dpi));
        jfif.setAttribute("Ydensity", Integer.toString(dpi));
        jfif.setAttribute("resUnits", "1"); // 1 = dots/inch

        // write
        imageWriter.write(data, new IIOImage(image, null, null), jpegParam);
    }
    finally
    {
        // clean up
        IOUtils.closeQuietly(out);
        if (ios != null)
        {
            ios.close();
        }
        if (imageWriter != null)
        {
            imageWriter.dispose();
        }
    }
}
 
Example 16
Source File: VisibleSignature.java    From testarea-pdfbox2 with Apache License 2.0 4 votes vote down vote up
public static byte[] sign(PDDocument doc, String CERT_FILE, char[] ALIAS_PASS, String IMAGE_FILE) throws KeyStoreException, NoSuchAlgorithmException, CertificateException,
            IOException, UnrecoverableKeyException {
        System.out.println("Document pages ? " + doc.getNumberOfPages());
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
//        ks.load(VisibleSignature.class.getResourceAsStream(CERT_FILE), ALIAS_PASS);
        ks.load(new FileInputStream(CERT_FILE), ALIAS_PASS);
        System.out.println("KeyStore is null ? " + (ks == null));
        VisibleSignature vs = new VisibleSignature(ks, ALIAS_PASS.clone());
        InputStream is = VisibleSignature.class.getResourceAsStream(IMAGE_FILE);
        int page = 1;
        vs.setVisibleSignDesigner(doc, 0, 0, -50, is, page);
        is.close();
        vs.setVisibleSignatureProperties("Test", "Test", "Test", 0, page, true);
        PDSignature signature = new PDSignature();
        PDAcroForm acroForm = doc.getDocumentCatalog().getAcroForm();
        System.out.println("Acroform is null ? " + (acroForm == null));
        if (acroForm != null)
            System.out.println("Acroform getNeedAppearances ? " + (acroForm.getNeedAppearances()));
        if (acroForm != null && acroForm.getNeedAppearances())
            if (acroForm.getFields().isEmpty())
                acroForm.getCOSObject().removeItem(COSName.NEED_APPEARANCES);
            else
                System.out.println("/NeedAppearances is set, signature may be ignored by Adobe Reader");
        signature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
        signature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_DETACHED);
        if (vs.visibleSignatureProperties != null) {
            vs.visibleSignatureProperties.buildSignature();
            signature.setName(vs.visibleSignatureProperties.getSignerName());
            signature.setLocation(vs.visibleSignatureProperties.getSignerLocation());
            signature.setReason(vs.visibleSignatureProperties.getSignatureReason());
            System.out.println("SignerName " + vs.visibleSignatureProperties.getSignerName());
        }
        signature.setSignDate(Calendar.getInstance());
        vs.signatureOptions = new SignatureOptions();
        vs.signatureOptions.setVisualSignature(vs.visibleSignatureProperties.getVisibleSignature());
        vs.signatureOptions.setPage(vs.visibleSignatureProperties.getPage() - 1);
//        doc.addSignature(signature, vs.signatureOptions);
        // using this overload instead fixes the issue.
        doc.addSignature(signature, vs, vs.signatureOptions);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        doc.saveIncremental(baos);
        doc.close();
        IOUtils.closeQuietly(vs.signatureOptions);
        byte[] content = baos.toByteArray();
        System.out.println("Content length: >>>>>>>>>>>>>>>>>>> " + content.length);
        return content;
    }
 
Example 17
Source File: PDCircleAppearanceHandler.java    From gcs with Mozilla Public License 2.0 4 votes vote down vote up
@Override
public void generateNormalAppearance()
{
    float lineWidth = getLineWidth();
    PDAnnotationSquareCircle annotation = (PDAnnotationSquareCircle) getAnnotation();
    PDAppearanceContentStream contentStream  = null;

    try
    {
        contentStream = getNormalAppearanceAsContentStream();
        boolean hasStroke = contentStream.setStrokingColorOnDemand(getColor());
        boolean hasBackground = contentStream
                .setNonStrokingColorOnDemand(annotation.getInteriorColor());

        setOpacity(contentStream, annotation.getConstantOpacity());

        contentStream.setBorderLine(lineWidth, annotation.getBorderStyle(), annotation.getBorder());
        PDBorderEffectDictionary borderEffect = annotation.getBorderEffect();

        if (borderEffect != null && borderEffect.getStyle().equals(PDBorderEffectDictionary.STYLE_CLOUDY))
        {
            CloudyBorder cloudyBorder = new CloudyBorder(contentStream,
                borderEffect.getIntensity(), lineWidth, getRectangle());
            cloudyBorder.createCloudyEllipse(annotation.getRectDifference());
            annotation.setRectangle(cloudyBorder.getRectangle());
            annotation.setRectDifference(cloudyBorder.getRectDifference());
            PDAppearanceStream appearanceStream = annotation.getNormalAppearanceStream();
            appearanceStream.setBBox(cloudyBorder.getBBox());
            appearanceStream.setMatrix(cloudyBorder.getMatrix());
        }
        else
        {
            // Acrobat applies a padding to each side of the bbox so the line is completely within
            // the bbox.

            PDRectangle borderBox = handleBorderBox(annotation, lineWidth);

            // lower left corner
            float x0 = borderBox.getLowerLeftX();
            float y0 = borderBox.getLowerLeftY();
            // upper right corner
            float x1 = borderBox.getUpperRightX();
            float y1 = borderBox.getUpperRightY();
            // mid points
            float xm = x0 + borderBox.getWidth() / 2;
            float ym = y0 + borderBox.getHeight() / 2;
            // see http://spencermortensen.com/articles/bezier-circle/
            // the below number was calculated from sampling content streams
            // generated using Adobe Reader
            float magic = 0.55555417f;
            // control point offsets
            float vOffset = borderBox.getHeight() / 2 * magic;
            float hOffset = borderBox.getWidth() / 2 * magic;

            contentStream.moveTo(xm, y1);
            contentStream.curveTo((xm + hOffset), y1, x1, (ym + vOffset), x1, ym);
            contentStream.curveTo(x1, (ym - vOffset), (xm + hOffset), y0, xm, y0);
            contentStream.curveTo((xm - hOffset), y0, x0, (ym - vOffset), x0, ym);
            contentStream.curveTo(x0, (ym + vOffset), (xm - hOffset), y1, xm, y1);
            contentStream.closePath();
        }

        contentStream.drawShape(lineWidth, hasStroke, hasBackground);
    }
    catch (IOException e)
    {
        LOG.error(e);
    }
    finally{
        IOUtils.closeQuietly(contentStream);
    }
}
 
Example 18
Source File: PDInkAppearanceHandler.java    From gcs with Mozilla Public License 2.0 4 votes vote down vote up
@Override
public void generateNormalAppearance()
{
    PDAnnotationMarkup ink = (PDAnnotationMarkup) getAnnotation();
    // PDF spec does not mention /Border for ink annotations, but it is used if /BS is not available
    AnnotationBorder ab = AnnotationBorder.getAnnotationBorder(ink, ink.getBorderStyle());
    PDColor color = ink.getColor();
    if (color == null || color.getComponents().length == 0 || Float.compare(ab.width, 0) == 0)
    {
        return;
    }

    PDAppearanceContentStream cs = null;

    try
    {
        cs = getNormalAppearanceAsContentStream();

        setOpacity(cs, ink.getConstantOpacity());

        cs.setStrokingColor(color);
        if (ab.dashArray != null)
        {
            cs.setLineDashPattern(ab.dashArray, 0);
        }
        cs.setLineWidth(ab.width);

        for (float[] pathArray : ink.getInkList())
        {
            int nPoints = pathArray.length / 2;

            // "When drawn, the points shall be connected by straight lines or curves 
            // in an implementation-dependent way" - we do lines.
            for (int i = 0; i < nPoints; ++i)
            {
                float x = pathArray[i * 2];
                float y = pathArray[i * 2 + 1];

                if (i == 0)
                {
                    cs.moveTo(x, y);
                }
                else
                {
                    cs.lineTo(x, y);
                }
            }
            cs.stroke();
        }
    }
    catch (IOException ex)
    {
        LOG.error(ex);
    }
    finally
    {
        IOUtils.closeQuietly(cs);
    }
}
 
Example 19
Source File: PDUnderlineAppearanceHandler.java    From gcs with Mozilla Public License 2.0 4 votes vote down vote up
@Override
public void generateNormalAppearance()
{
    PDAnnotationTextMarkup annotation = (PDAnnotationTextMarkup) getAnnotation();
    PDRectangle rect = annotation.getRectangle();
    float[] pathsArray = annotation.getQuadPoints();
    if (pathsArray == null)
    {
        return;
    }
    AnnotationBorder ab = AnnotationBorder.getAnnotationBorder(annotation, annotation.getBorderStyle());
    PDColor color = annotation.getColor();
    if (color == null || color.getComponents().length == 0)
    {
        return;
    }
    if (Float.compare(ab.width, 0) == 0)
    {
        // value found in adobe reader
        ab.width = 1.5f;
    }

    // Adjust rectangle even if not empty, see PLPDF.com-MarkupAnnotations.pdf
    //TODO in a class structure this should be overridable
    // this is similar to polyline but different data type
    // all coordinates (unlike painting) are used because I'm lazy
    float minX = Float.MAX_VALUE;
    float minY = Float.MAX_VALUE;
    float maxX = Float.MIN_VALUE;
    float maxY = Float.MIN_VALUE;
    for (int i = 0; i < pathsArray.length / 2; ++i)
    {
        float x = pathsArray[i * 2];
        float y = pathsArray[i * 2 + 1];
        minX = Math.min(minX, x);
        minY = Math.min(minY, y);
        maxX = Math.max(maxX, x);
        maxY = Math.max(maxY, y);
    }
    rect.setLowerLeftX(Math.min(minX - ab.width / 2, rect.getLowerLeftX()));
    rect.setLowerLeftY(Math.min(minY - ab.width / 2, rect.getLowerLeftY()));
    rect.setUpperRightX(Math.max(maxX + ab.width / 2, rect.getUpperRightX()));
    rect.setUpperRightY(Math.max(maxY + ab.width / 2, rect.getUpperRightY()));
    annotation.setRectangle(rect);

    PDAppearanceContentStream cs = null;

    try
    {
        cs = getNormalAppearanceAsContentStream();

        setOpacity(cs, annotation.getConstantOpacity());

        cs.setStrokingColor(color);
        if (ab.dashArray != null)
        {
            cs.setLineDashPattern(ab.dashArray, 0);
        }
        cs.setLineWidth(ab.width);

        // spec is incorrect
        // https://stackoverflow.com/questions/9855814/pdf-spec-vs-acrobat-creation-quadpoints
        for (int i = 0; i < pathsArray.length / 8; ++i)
        {
            // Adobe doesn't use the lower coordinate for the line, it uses lower + delta / 7.
            // do the math for diagonal annotations with this weird old trick:
            // https://stackoverflow.com/questions/7740507/extend-a-line-segment-a-specific-distance
            float len0 = (float) (Math.sqrt(Math.pow(pathsArray[i * 8] - pathsArray[i * 8 + 4], 2) + 
                                  Math.pow(pathsArray[i * 8 + 1] - pathsArray[i * 8 + 5], 2)));
            float x0 = pathsArray[i * 8 + 4];
            float y0 = pathsArray[i * 8 + 5];
            if (Float.compare(len0, 0) != 0)
            {
                // only if both coordinates are not identical to avoid divide by zero
                x0 += (pathsArray[i * 8] - pathsArray[i * 8 + 4]) / len0 * len0 / 7;
                y0 += (pathsArray[i * 8 + 1] - pathsArray[i * 8 + 5]) / len0 * (len0 / 7);
            }
            float len1 = (float) (Math.sqrt(Math.pow(pathsArray[i * 8 + 2] - pathsArray[i * 8 + 6], 2) + 
                                  Math.pow(pathsArray[i * 8 + 3] - pathsArray[i * 8 + 7], 2)));
            float x1 = pathsArray[i * 8 + 6];
            float y1 = pathsArray[i * 8 + 7];
            if (Float.compare(len1, 0) != 0)
            {
                // only if both coordinates are not identical to avoid divide by zero
                x1 += (pathsArray[i * 8 + 2] - pathsArray[i * 8 + 6]) / len1 * len1 / 7;
                y1 += (pathsArray[i * 8 + 3] - pathsArray[i * 8 + 7]) / len1 * len1 / 7;
            }
            cs.moveTo(x0, y0);
            cs.lineTo(x1, y1);
        }
        cs.stroke();
    }
    catch (IOException ex)
    {
        LOG.error(ex);
    }
    finally
    {
        IOUtils.closeQuietly(cs);
    }
}
 
Example 20
Source File: PDSquareAppearanceHandler.java    From gcs with Mozilla Public License 2.0 4 votes vote down vote up
@Override
public void generateNormalAppearance()
{
    float lineWidth = getLineWidth();
    PDAnnotationSquareCircle annotation = (PDAnnotationSquareCircle) getAnnotation();
    PDAppearanceContentStream contentStream  = null;

    try
    {
        contentStream = getNormalAppearanceAsContentStream();
        boolean hasStroke = contentStream.setStrokingColorOnDemand(getColor());
        boolean hasBackground = contentStream
                .setNonStrokingColorOnDemand(annotation.getInteriorColor());

        setOpacity(contentStream, annotation.getConstantOpacity());

        contentStream.setBorderLine(lineWidth, annotation.getBorderStyle(), annotation.getBorder());                
        PDBorderEffectDictionary borderEffect = annotation.getBorderEffect();

        if (borderEffect != null && borderEffect.getStyle().equals(PDBorderEffectDictionary.STYLE_CLOUDY))
        {
            CloudyBorder cloudyBorder = new CloudyBorder(contentStream,
                borderEffect.getIntensity(), lineWidth, getRectangle());
            cloudyBorder.createCloudyRectangle(annotation.getRectDifference());
            annotation.setRectangle(cloudyBorder.getRectangle());
            annotation.setRectDifference(cloudyBorder.getRectDifference());
            PDAppearanceStream appearanceStream = annotation.getNormalAppearanceStream();
            appearanceStream.setBBox(cloudyBorder.getBBox());
            appearanceStream.setMatrix(cloudyBorder.getMatrix());
        }
        else
        {
            PDRectangle borderBox = handleBorderBox(annotation, lineWidth);

            contentStream.addRect(borderBox.getLowerLeftX(), borderBox.getLowerLeftY(),
                    borderBox.getWidth(), borderBox.getHeight());
        }

        contentStream.drawShape(lineWidth, hasStroke, hasBackground);
    }
    catch (IOException e)
    {
        LOG.error(e);
    }
    finally{
        IOUtils.closeQuietly(contentStream);
    }
}