org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream Java Examples

The following examples show how to use org.apache.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream. 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: AppearanceGeneratorHelper.java    From gcs with Mozilla Public License 2.0 6 votes vote down vote up
private PDAppearanceStream prepareNormalAppearanceStream(PDAnnotationWidget widget)
{
    PDAppearanceStream appearanceStream = new PDAppearanceStream(field.getAcroForm().getDocument());

    // Calculate the entries for the bounding box and the transformation matrix
    // settings for the appearance stream
    int rotation = resolveRotation(widget);
    PDRectangle rect = widget.getRectangle();
    Matrix matrix = Matrix.getRotateInstance(Math.toRadians(rotation), 0, 0);
    Point2D.Float point2D = matrix.transformPoint(rect.getWidth(), rect.getHeight());

    PDRectangle bbox = new PDRectangle(Math.abs((float) point2D.getX()), Math.abs((float) point2D.getY()));
    appearanceStream.setBBox(bbox);

    AffineTransform at = calculateMatrix(bbox, rotation);
    if (!at.isIdentity())
    {
        appearanceStream.setMatrix(at);
    }
    appearanceStream.setFormType(1);
    appearanceStream.setResources(new PDResources());
    return appearanceStream;
}
 
Example #2
Source File: PDAcroForm.java    From gcs with Mozilla Public License 2.0 6 votes vote down vote up
/**
 * Check if there needs to be a scaling transformation applied.
 * 
 * @param annotation
 * @param rotation 
 * @return the need for a scaling transformation.
 */    
private boolean resolveNeedsScaling(PDAnnotation annotation, int rotation)
{
    PDAppearanceStream appearanceStream = annotation.getNormalAppearanceStream();
    // Check if there is a transformation within the XObjects content
    PDResources resources = appearanceStream.getResources();
    if (resources != null && resources.getXObjectNames().iterator().hasNext())
    {
        return true;
    }
    PDRectangle bbox = appearanceStream.getBBox();
    PDRectangle fieldRect = annotation.getRectangle();
    if (rotation == 90 || rotation == 270)
    {
        return Float.compare(bbox.getWidth(),  fieldRect.getHeight()) != 0 ||
               Float.compare(bbox.getHeight(), fieldRect.getWidth()) != 0;
    }
    else
    {
        return Float.compare(bbox.getWidth(),  fieldRect.getWidth()) != 0 ||
               Float.compare(bbox.getHeight(), fieldRect.getHeight()) != 0;
    }
}
 
Example #3
Source File: PDPageContentStream.java    From gcs with Mozilla Public License 2.0 5 votes vote down vote up
/**
 * Create a new appearance stream. Note that this is not actually a "page" content stream.
 *
 * @param doc The document the appearance is part of.
 * @param appearance The appearance stream to add to.
 * @param outputStream The appearances output stream to write to.
 * @throws IOException If there is an error writing to the page contents.
 */
public PDPageContentStream(PDDocument doc, PDAppearanceStream appearance, OutputStream outputStream)
        throws IOException
{
    this.document = doc;
    
    output = outputStream;
    this.resources = appearance.getResources();
    
    formatDecimal.setMaximumFractionDigits(4);
    formatDecimal.setGroupingUsed(false);
}
 
Example #4
Source File: ExtractAppearanceText.java    From testarea-pdfbox2 with Apache License 2.0 5 votes vote down vote up
/**
 * <a href="https://stackoverflow.com/questions/49427615/how-to-extract-label-text-from-push-button-using-apache-pdfbox">
 * How to extract label text from Push button using Apache PDFBox?
 * </a>
 * <p>
 * This method extracts the text from the normal appearance streams
 * of the form fields in the given PDF document.
 * </p>
 * @see #testBtn()
 * @see #testKYF211Beställning2014()
 */
public void showNormalFieldAppearanceTexts(PDDocument document) throws IOException {
    PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();

    if (acroForm != null) {
        SimpleXObjectTextStripper stripper = new SimpleXObjectTextStripper();

        for (PDField field : acroForm.getFieldTree()) {
            if (field instanceof PDTerminalField) {
                PDTerminalField terminalField = (PDTerminalField) field;
                System.out.println();
                System.out.println("* " + terminalField.getFullyQualifiedName());
                for (PDAnnotationWidget widget : terminalField.getWidgets()) {
                    PDAppearanceDictionary appearance = widget.getAppearance();
                    if (appearance != null) {
                        PDAppearanceEntry normal = appearance.getNormalAppearance();
                        if (normal != null) {
                            Map<COSName, PDAppearanceStream> streams = normal.isSubDictionary() ? normal.getSubDictionary() :
                                Collections.singletonMap(COSName.DEFAULT, normal.getAppearanceStream());
                            for (Map.Entry<COSName, PDAppearanceStream> entry : streams.entrySet()) {
                                String text = stripper.getText(entry.getValue());
                                System.out.printf("  * %s: %s\n", entry.getKey().getName(), text);
                            }
                        }
                    }
                }
            }
        }
    }
}
 
Example #5
Source File: PDFStreamEngine.java    From gcs with Mozilla Public License 2.0 5 votes vote down vote up
/**
 * Shows the given annotation.
 *
 * @param annotation An annotation on the current page.
 * @throws IOException If an error occurred reading the annotation
 */
public void showAnnotation(PDAnnotation annotation) throws IOException
{
    PDAppearanceStream appearanceStream = getAppearance(annotation);
    if (appearanceStream != null)
    {
        processAnnotation(annotation, appearanceStream);
    }
}
 
Example #6
Source File: PDVisibleSigBuilder.java    From gcs with Mozilla Public License 2.0 5 votes vote down vote up
@Override
public void createAppearanceDictionary(PDFormXObject holderForml,
                                       PDSignatureField signatureField) throws IOException
{
    PDAppearanceDictionary appearance = new PDAppearanceDictionary();
    appearance.getCOSObject().setDirect(true);

    PDAppearanceStream appearanceStream = new PDAppearanceStream(holderForml.getCOSObject());

    appearance.setNormalAppearance(appearanceStream);
    signatureField.getWidgets().get(0).setAppearance(appearance);

    pdfStructure.setAppearanceDictionary(appearance);
    LOG.info("PDF appearance dictionary has been created");
}
 
Example #7
Source File: PDAbstractAppearanceHandler.java    From gcs with Mozilla Public License 2.0 5 votes vote down vote up
private void setTransformationMatrix(PDAppearanceStream appearanceStream)
{
    PDRectangle bbox = getRectangle();
    appearanceStream.setBBox(bbox);
    AffineTransform transform = AffineTransform.getTranslateInstance(-bbox.getLowerLeftX(),
            -bbox.getLowerLeftY());
    appearanceStream.setMatrix(transform);
}
 
Example #8
Source File: PDAcroForm.java    From gcs with Mozilla Public License 2.0 5 votes vote down vote up
/**
 * Check if there is a translation needed to place the annotations content.
 * 
 * @param appearanceStream
 * @return the need for a translation transformation.
 */
private boolean resolveNeedsTranslation(PDAppearanceStream appearanceStream)
{
    boolean needsTranslation = true;

    PDResources resources = appearanceStream.getResources();
    if (resources != null && resources.getXObjectNames().iterator().hasNext())
    {
        Iterator<COSName> xObjectNames = resources.getXObjectNames().iterator();

        while (xObjectNames.hasNext())
        {
            try
            {
                // if the BBox of the PDFormXObject does not start at 0,0
                // there is no need do translate as this is done by the BBox definition.
                PDXObject xObject = resources.getXObject(xObjectNames.next());
                if (xObject instanceof PDFormXObject)
                {
                    PDRectangle bbox = ((PDFormXObject)xObject).getBBox();
                    float llX = bbox.getLowerLeftX();
                    float llY = bbox.getLowerLeftY();
                    if (Float.compare(llX, 0) != 0 && Float.compare(llY, 0) != 0)
                    {
                        needsTranslation = false;
                    }
                }
            }
            catch (IOException e)
            {
                // we can safely ignore the exception here
                // as this might only cause a misplacement
            }
        }
        return needsTranslation;
    }
    
    return true;
}
 
Example #9
Source File: AppearanceGeneratorHelper.java    From gcs with Mozilla Public License 2.0 5 votes vote down vote up
/**
 * Resolve the bounding box.
 * 
 * @param fieldWidget the annotation widget.
 * @param appearanceStream the annotations appearance stream.
 * @return the resolved boundingBox.
 */
private PDRectangle resolveBoundingBox(PDAnnotationWidget fieldWidget,
                                       PDAppearanceStream appearanceStream)
{
    PDRectangle boundingBox = appearanceStream.getBBox();
    if (boundingBox == null)
    {
        boundingBox = fieldWidget.getRectangle().createRetranslatedRectangle();
    }
    return boundingBox;
}
 
Example #10
Source File: AppearanceGeneratorHelper.java    From gcs with Mozilla Public License 2.0 5 votes vote down vote up
/**
 * 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.getCOSObject().createOutputStream();
    out.write(data);
    out.close();
}
 
Example #11
Source File: AppearanceGeneratorHelper.java    From gcs with Mozilla Public License 2.0 5 votes vote down vote up
private void insertGeneratedListboxSelectionHighlight(PDPageContentStream contents, PDAppearanceStream appearanceStream,
        PDFont font, float fontSize) throws IOException
{
    List<Integer> indexEntries = ((PDListBox) field).getSelectedOptionsIndex();
    List<String> values = ((PDListBox) field).getValue();
    List<String> options = ((PDListBox) field).getOptionsExportValues();
    
    if (!values.isEmpty() && !options.isEmpty() && indexEntries.isEmpty())
    {
        // create indexEntries from options
        indexEntries = new ArrayList<Integer>();
        for (String v : values)
        {
            indexEntries.add(options.indexOf(v));
        }
    }

    // The first entry which shall be presented might be adjusted by the optional TI key
    // If this entry is present the first entry to be displayed is the keys value otherwise
    // display starts with the first entry in Opt.
    int topIndex = ((PDListBox) field).getTopIndex();
    
    float highlightBoxHeight = font.getBoundingBox().getHeight() * fontSize / FONTSCALE;       

    // the padding area 
    PDRectangle paddingEdge = applyPadding(appearanceStream.getBBox(), 1);

    for (int selectedIndex : indexEntries)
    {
        contents.setNonStrokingColor(HIGHLIGHT_COLOR[0], HIGHLIGHT_COLOR[1], HIGHLIGHT_COLOR[2]);

        contents.addRect(paddingEdge.getLowerLeftX(),
                paddingEdge.getUpperRightY() - highlightBoxHeight * (selectedIndex - topIndex + 1) + 2,
                paddingEdge.getWidth(),
                highlightBoxHeight);
        contents.fill();
    }
    contents.setNonStrokingColor(0);
}
 
Example #12
Source File: AppearanceGeneratorHelper.java    From gcs with Mozilla Public License 2.0 5 votes vote down vote up
/**
 * Generate the appearance for comb fields.
 * 
 * @param contents the content stream to write to
 * @param appearanceStream the appearance stream used
 * @param font the font to be used
 * @param fontSize the font size to be used
 * @throws IOException
 */
private void insertGeneratedCombAppearance(PDPageContentStream contents, PDAppearanceStream appearanceStream,
        PDFont font, float fontSize) throws IOException
{
    
    // TODO:    Currently the quadding is not taken into account
    //          so the comb is always filled from left to right.
    
    int maxLen = ((PDTextField) field).getMaxLen();
    int numChars = Math.min(value.length(), maxLen);
    
    PDRectangle paddingEdge = applyPadding(appearanceStream.getBBox(), 1);
    
    float combWidth = appearanceStream.getBBox().getWidth() / maxLen;
    float ascentAtFontSize = font.getFontDescriptor().getAscent() / FONTSCALE * fontSize;
    float baselineOffset = paddingEdge.getLowerLeftY() +  
            (appearanceStream.getBBox().getHeight() - ascentAtFontSize)/2;
    
    float prevCharWidth = 0f;
    
    float xOffset = combWidth / 2;

    for (int i = 0; i < numChars; i++) 
    {
        String combString = value.substring(i, i+1);
        float currCharWidth = font.getStringWidth(combString) / FONTSCALE * fontSize/2;
        
        xOffset = xOffset + prevCharWidth/2 - currCharWidth/2;
        
        contents.newLineAtOffset(xOffset, baselineOffset);
        contents.showText(combString);
        
        baselineOffset = 0;
        prevCharWidth = currCharWidth;
        xOffset = combWidth;
    }
}
 
Example #13
Source File: AppearanceGeneratorHelper.java    From gcs with Mozilla Public License 2.0 5 votes vote down vote up
/**
 * Parses an appearance stream into tokens.
 */
private List<Object> tokenize(PDAppearanceStream appearanceStream) throws IOException
{
    PDFStreamParser parser = new PDFStreamParser(appearanceStream);
    parser.parse();
    return parser.getTokens();
}
 
Example #14
Source File: AppearanceGeneratorHelper.java    From gcs with Mozilla Public License 2.0 4 votes vote down vote up
private void insertGeneratedListboxAppearance(PDPageContentStream contents, PDAppearanceStream appearanceStream,
        PDRectangle contentRect, PDFont font, float fontSize) throws IOException
{
    contents.setNonStrokingColor(0);
    
    int q = field.getQ();

    if (q == PDVariableText.QUADDING_CENTERED || q == PDVariableText.QUADDING_RIGHT)
    {
        float fieldWidth = appearanceStream.getBBox().getWidth();
        float stringWidth = (font.getStringWidth(value) / FONTSCALE) * fontSize;
        float adjustAmount = fieldWidth - stringWidth - 4;

        if (q == PDVariableText.QUADDING_CENTERED)
        {
            adjustAmount = adjustAmount / 2.0f;
        }

        contents.newLineAtOffset(adjustAmount, 0);
    }
    else if (q != PDVariableText.QUADDING_LEFT)
    {
        throw new IOException("Error: Unknown justification value:" + q);
    }

    List<String> options = ((PDListBox) field).getOptionsDisplayValues();
    int numOptions = options.size();

    float yTextPos = contentRect.getUpperRightY();

    int topIndex = ((PDListBox) field).getTopIndex();
    
    for (int i = topIndex; i < numOptions; i++)
    {
       
        if (i == topIndex)
        {
            yTextPos = yTextPos - font.getFontDescriptor().getAscent() / FONTSCALE * fontSize;
        }
        else
        {
            yTextPos = yTextPos - font.getBoundingBox().getHeight() / FONTSCALE * fontSize;
            contents.beginText();
        }

        contents.newLineAtOffset(contentRect.getLowerLeftX(), yTextPos);
        contents.showText(options.get(i));

        if (i != (numOptions - 1))
        {
            contents.endText();
        }
    }
}
 
Example #15
Source File: PDFObjectExtractor.java    From pdfxtk with Apache License 2.0 4 votes vote down vote up
/**
 * This will draw the page to the requested context.
 *
 * @param g The graphics context to draw onto.
 * @param p The page to draw.
 * @param pageDimension The size of the page to draw.
 *
 * @throws IOException If there is an IO error while drawing the page.
 */
public void drawPage( Graphics g, PDPage p, Dimension pageDimension ) throws IOException
{
    graphics = (Graphics2D)g;
    page = p;
    pageSize = pageDimension;
    
    graphics.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
    PDResources resources = page.findResources();
    processStream( page, resources, page.getContents().getStream() );
    List annotations = page.getAnnotations();
    for( int i=0; i<annotations.size(); i++ )
    {
        PDAnnotation annot = (PDAnnotation)annotations.get( i );
        PDRectangle rect = annot.getRectangle();
        String appearanceName = annot.getAppearanceStream();
        PDAppearanceDictionary appearDictionary = annot.getAppearance();
        if( appearDictionary != null )
        {
            if( appearanceName == null )
            {
                appearanceName = "default";
            }
            Map appearanceMap = appearDictionary.getNormalAppearance();
            PDAppearanceStream appearance = 
                (PDAppearanceStream)appearanceMap.get( appearanceName );
            if( appearance != null )
            {
                g.translate( (int)rect.getLowerLeftX(), (int)-rect.getLowerLeftY()  );
                //g.translate( 20, -20 );
                processSubStream( page, appearance.getResources(), appearance.getStream() );
                g.translate( (int)-rect.getLowerLeftX(), (int)+rect.getLowerLeftY()  );
            }
        }
    }
    // Transformations should be done in order
    // 1 - Translate
    // 2 - Rotate
    // 3 - Scale
    // Refer to PDFReference p176 (or 188 in xpdf)
    /*AffineTransform transform = graphics.getTransform();        
    transform.setToTranslation( 0, page.findMediaBox().getHeight()/2 );
    transform.setToRotation((double)p.getRotation());
    transform.setTransform( 1, 0, 0, 1, 0, 0 );        
    transform.setToScale( 1, 1 );
    
    AffineTransform rotation = graphics.getTransform();
    rotation.rotate( (page.findRotation() * Math.PI) / 180d );
    graphics.setTransform( rotation );*/
    
}
 
Example #16
Source File: NativePdfBoxVisibleSignatureDrawer.java    From dss with GNU Lesser General Public License v2.1 4 votes vote down vote up
@Override
public void draw() throws IOException {
	try (PDDocument doc = new PDDocument(); ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
		
		PDPage originalPage = document.getPage(parameters.getPage() - 1);
		SignatureFieldDimensionAndPositionBuilder dimensionAndPositionBuilder = 
				new SignatureFieldDimensionAndPositionBuilder(parameters, originalPage, pdFont);
		SignatureFieldDimensionAndPosition dimensionAndPosition = dimensionAndPositionBuilder.build();
		// create a new page
		PDPage page = new PDPage(originalPage.getMediaBox());
		doc.addPage(page);
		PDAcroForm acroForm = new PDAcroForm(doc);
           doc.getDocumentCatalog().setAcroForm(acroForm);
           PDSignatureField signatureField = new PDSignatureField(acroForm);
           PDAnnotationWidget widget = signatureField.getWidgets().get(0);
           List<PDField> acroFormFields = acroForm.getFields();
           acroForm.setSignaturesExist(true);
           acroForm.setAppendOnly(true);
           acroForm.getCOSObject().setDirect(true);
           acroFormFields.add(signatureField);

           PDRectangle rectangle = getPdRectangle(dimensionAndPosition, page);
           widget.setRectangle(rectangle);
           
           PDStream stream = new PDStream(doc);
           PDFormXObject form = new PDFormXObject(stream);
           PDResources res = new PDResources();
           form.setResources(res);
           form.setFormType(1);
           
           form.setBBox(new PDRectangle(rectangle.getWidth(), rectangle.getHeight()));
           
           PDAppearanceDictionary appearance = new PDAppearanceDictionary();
           appearance.getCOSObject().setDirect(true);
           PDAppearanceStream appearanceStream = new PDAppearanceStream(form.getCOSObject());
           appearance.setNormalAppearance(appearanceStream);
           widget.setAppearance(appearance);
           
           try (PDPageContentStream cs = new PDPageContentStream(doc, appearanceStream))
           {
           	rotateSignature(cs, rectangle, dimensionAndPosition);
           	setFieldBackground(cs, parameters.getBackgroundColor());
           	setText(cs, dimensionAndPosition, parameters);
           	setImage(cs, doc, dimensionAndPosition, parameters.getImage());
           }
           
           doc.save(baos);
           
           try (ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()))
           {
       		signatureOptions.setVisualSignature(bais);
       		signatureOptions.setPage(parameters.getPage() - 1);
           }
           
       }
}
 
Example #17
Source File: TestEmptySignatureField.java    From testarea-pdfbox2 with Apache License 2.0 4 votes vote down vote up
/**
 * <a href="http://stackoverflow.com/questions/37601092/pdfbox-identify-specific-pages-and-functionalities-recommendations">
 * PDFBox identify specific pages and functionalities recommendations
 * </a>
 * 
 * <p>
 * This test shows how to add an empty signature field with a custom appearance
 * to an existing PDF.
 * </p>
 */
@Test
public void testAddEmptySignatureField() throws IOException
{
    try (   InputStream sourceStream = getClass().getResourceAsStream("test.pdf");
            OutputStream output = new FileOutputStream(new File(RESULT_FOLDER, "test-with-empty-sig-field.pdf")))
    {
        PDFont font = PDType1Font.HELVETICA;
        PDResources resources = new PDResources();
        resources.put(COSName.getPDFName("Helv"), font);

        PDDocument document = Loader.loadPDF(sourceStream);
        PDAcroForm acroForm = new PDAcroForm(document);
        acroForm.setDefaultResources(resources);
        document.getDocumentCatalog().setAcroForm(acroForm);

        PDRectangle rect = new PDRectangle(50, 750, 200, 50);

        PDAppearanceDictionary appearanceDictionary = new PDAppearanceDictionary();
        PDAppearanceStream appearanceStream = new PDAppearanceStream(document);
        appearanceStream.setBBox(rect.createRetranslatedRectangle());
        appearanceStream.setResources(resources);
        appearanceDictionary.setNormalAppearance(appearanceStream);
        PDPageContentStream contentStream = new PDPageContentStream(document, appearanceStream);
        contentStream.setStrokingColor(Color.BLACK);
        contentStream.setNonStrokingColor(Color.LIGHT_GRAY);
        contentStream.setLineWidth(2);
        contentStream.addRect(0, 0, rect.getWidth(), rect.getHeight());
        contentStream.fill();
        contentStream.moveTo(1 * rect.getHeight() / 4, 1 * rect.getHeight() / 4);
        contentStream.lineTo(2 * rect.getHeight() / 4, 3 * rect.getHeight() / 4);
        contentStream.moveTo(1 * rect.getHeight() / 4, 3 * rect.getHeight() / 4);
        contentStream.lineTo(2 * rect.getHeight() / 4, 1 * rect.getHeight() / 4);
        contentStream.moveTo(3 * rect.getHeight() / 4, 1 * rect.getHeight() / 4);
        contentStream.lineTo(rect.getWidth() - rect.getHeight() / 4, 1 * rect.getHeight() / 4);
        contentStream.stroke();
        contentStream.setNonStrokingColor(Color.DARK_GRAY);
        contentStream.beginText();
        contentStream.setFont(font, rect.getHeight() / 5);
        contentStream.newLineAtOffset(3 * rect.getHeight() / 4, -font.getBoundingBox().getLowerLeftY() * rect.getHeight() / 5000);
        contentStream.showText("Customer");
        contentStream.endText();
        contentStream.close();

        PDSignatureField signatureField = new PDSignatureField(acroForm);
        signatureField.setPartialName("SignatureField");
        PDPage page = document.getPage(0);

        PDAnnotationWidget widget = signatureField.getWidgets().get(0);
        widget.setAppearance(appearanceDictionary);
        widget.setRectangle(rect);
        widget.setPage(page);

        page.getAnnotations().add(widget);
        acroForm.getFields().add(signatureField);

        document.save(output);
        document.close();
    }
}
 
Example #18
Source File: CheckImageFieldFilled.java    From testarea-pdfbox2 with Apache License 2.0 4 votes vote down vote up
boolean hasImages() throws IOException {
    count = 0;
    PDAppearanceStream normalAppearance = widget.getNormalAppearanceStream();
    processChildStream(normalAppearance, widget.getPage());
    return count != 0;
}
 
Example #19
Source File: PDFStreamEngine.java    From gcs with Mozilla Public License 2.0 4 votes vote down vote up
/**
 * Process the given annotation with the specified appearance stream.
 *
 * @param annotation The annotation containing the appearance stream to process.
 * @param appearance The appearance stream to process.
 * @throws IOException If there is an error reading or parsing the appearance content stream.
 */
protected void processAnnotation(PDAnnotation annotation, PDAppearanceStream appearance)
        throws IOException
{
    PDResources parent = pushResources(appearance);
    Deque<PDGraphicsState> savedStack = saveGraphicsStack();

    PDRectangle bbox = appearance.getBBox();
    PDRectangle rect = annotation.getRectangle();
    Matrix matrix = appearance.getMatrix();

    // zero-sized rectangles are not valid
    if (rect != null && rect.getWidth() > 0 && rect.getHeight() > 0 && bbox != null)
    {
        // transformed appearance box  fixme: may be an arbitrary shape
        Rectangle2D transformedBox = bbox.transform(matrix).getBounds2D();

        // compute a matrix which scales and translates the transformed appearance box to align
        // with the edges of the annotation's rectangle
        Matrix a = Matrix.getTranslateInstance(rect.getLowerLeftX(), rect.getLowerLeftY());
        a.concatenate(Matrix.getScaleInstance((float)(rect.getWidth() / transformedBox.getWidth()),
                (float)(rect.getHeight() / transformedBox.getHeight())));
        a.concatenate(Matrix.getTranslateInstance((float) -transformedBox.getX(),
                (float) -transformedBox.getY()));

        // Matrix shall be concatenated with A to form a matrix AA that maps from the appearance's
        // coordinate system to the annotation's rectangle in default user space
        //
        // HOWEVER only the opposite order works for rotated pages with 
        // filled fields / annotations that have a matrix in the appearance stream, see PDFBOX-3083
        Matrix aa = Matrix.concatenate(a, matrix);

        // make matrix AA the CTM
        getGraphicsState().setCurrentTransformationMatrix(aa);

        // clip to bounding box
        clipToRect(bbox);

        // needed for patterns in appearance streams, e.g. PDFBOX-2182
        initialMatrix = aa.clone();

        processStreamOperators(appearance);
    }
    
    restoreGraphicsStack(savedStack);
    popResources(parent);
}
 
Example #20
Source File: AppearanceGeneratorHelper.java    From gcs with Mozilla Public License 2.0 4 votes vote down vote up
/**
 * Constructs and sets new contents for given appearance stream.
 */
private void setAppearanceContent(PDAnnotationWidget widget,
                                  PDAppearanceStream appearanceStream) throws IOException
{
    // first copy any needed resources from the document’s DR dictionary into
    // the stream’s Resources dictionary
    defaultAppearance.copyNeededResourcesTo(appearanceStream);
    
    // then replace the existing contents of the appearance stream from /Tx BMC
    // to the matching EMC
    ByteArrayOutputStream output = new ByteArrayOutputStream();
    ContentStreamWriter writer = new ContentStreamWriter(output);
    
    List<Object> tokens = tokenize(appearanceStream);
    int bmcIndex = tokens.indexOf(BMC);
    if (bmcIndex == -1)
    {
        // append to existing stream
        writer.writeTokens(tokens);
        writer.writeTokens(COSName.TX, BMC);
    }
    else
    {
        // prepend content before BMC
        writer.writeTokens(tokens.subList(0, bmcIndex + 1));
    }
    
    // insert field contents
    insertGeneratedAppearance(widget, appearanceStream, output);
    
    int emcIndex = tokens.indexOf(EMC);
    if (emcIndex == -1)
    {
        // append EMC
        writer.writeTokens(EMC);
    }
    else
    {
        // append contents after EMC
        writer.writeTokens(tokens.subList(emcIndex, tokens.size()));
    }

    output.close();
    writeToStream(output.toByteArray(), appearanceStream);
}
 
Example #21
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);
    }
}
 
Example #22
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 #23
Source File: PDAppearanceContentStream.java    From gcs with Mozilla Public License 2.0 2 votes vote down vote up
/**
 * Create a new appearance stream.
 *
 * @param appearance
 *            The appearance stream to add to.
 * @param outputStream
 *            The appearances output stream to write to.
 */
public PDAppearanceContentStream(PDAppearanceStream appearance, OutputStream outputStream)
{
    super(null, outputStream, appearance.getResources());
}
 
Example #24
Source File: PDAppearanceContentStream.java    From gcs with Mozilla Public License 2.0 2 votes vote down vote up
/**
 * Create a new appearance stream.
 *
 * @param appearance The appearance stream to write to.
 * @param compress whether the content stream is to be compressed. Set this to true when
 * creating long content streams.
 * @throws IOException If there is an error writing to the content stream.
 */
public PDAppearanceContentStream(PDAppearanceStream appearance, boolean compress) throws IOException
{
    this(appearance, appearance.getStream().createOutputStream(compress ? COSName.FLATE_DECODE : null));
}
 
Example #25
Source File: PDFStreamEngine.java    From gcs with Mozilla Public License 2.0 2 votes vote down vote up
/**
 * Returns the appearance stream to process for the given annotation. May be used to render
 * a specific appearance such as "hover".
 *
 * @param annotation The current annotation.
 * @return The stream to process.
 */
public PDAppearanceStream getAppearance(PDAnnotation annotation)
{
    return annotation.getNormalAppearanceStream();
}
 
Example #26
Source File: PDAppearanceContentStream.java    From gcs with Mozilla Public License 2.0 2 votes vote down vote up
/**
 * Create a new appearance stream.
 *
 * @param appearance
 *            The appearance stream to write to.
 * @throws IOException If there is an error writing to the content stream.
 */
public PDAppearanceContentStream(PDAppearanceStream appearance) throws IOException
{
    this(appearance, appearance.getStream().createOutputStream());
}
 
Example #27
Source File: PDPageContentStream.java    From gcs with Mozilla Public License 2.0 2 votes vote down vote up
/**
 * Create a new appearance stream. Note that this is not actually a "page" content stream.
 *
 * @param doc The document the page is part of.
 * @param appearance The appearance stream to write to.
 * @throws IOException If there is an error writing to the page contents.
 */
public PDPageContentStream(PDDocument doc, PDAppearanceStream appearance) throws IOException
{
    this (doc, appearance, appearance.getStream().createOutputStream()); 
}