use of com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotation in project PdfBox-Android by TomRoush.
the class COSArrayListTest method removeFromListByIndex.
/**
* Test removing a PDModel element by index is in sync with underlying COSArray
*/
@Test
public void removeFromListByIndex() throws Exception {
COSArrayList<PDAnnotation> cosArrayList = new COSArrayList<PDAnnotation>(annotationsList, annotationsArray);
int positionToRemove = 1;
cosArrayList.remove(positionToRemove);
assertTrue("List size shall be 2", cosArrayList.size() == 2);
assertTrue("COSArray size shall be 2", annotationsArray.size() == 2);
PDAnnotation annot = (PDAnnotation) cosArrayList.get(1);
assertTrue("Object at original position 2 shall now be at position 1 in underlying COSArray", annotationsArray.indexOf(annot.getCOSObject()) == 1);
// compare with Java List/Array to ensure correct object at position
assertTrue("List object at 2 is at position 1 in COSArrayList now", cosArrayList.indexOf(tbcAnnotationsList.get(2)) == 1);
assertTrue("COSObject of List object at 2 is at position 1 in COSArray now", annotationsArray.indexOf(tbcAnnotationsList.get(2).getCOSObject()) == 1);
assertTrue("Array object at 2 is at position 1 in underlying COSArray now", annotationsArray.indexOf(tbcAnnotationsArray[2]) == 1);
assertTrue("PDAnnotation shall no longer exist in List", cosArrayList.indexOf(tbcAnnotationsList.get(positionToRemove)) == -1);
assertTrue("COSObject shall no longer exist in COSArray", annotationsArray.indexOf(tbcAnnotationsArray[positionToRemove]) == -1);
}
use of com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotation in project PdfBox-Android by TomRoush.
the class COSArrayListTest method addToList.
/**
* Test adding a PDModel element is in sync with underlying COSArray
*/
@Test
public void addToList() throws Exception {
COSArrayList<PDAnnotation> cosArrayList = new COSArrayList<PDAnnotation>(annotationsList, annotationsArray);
// add new annotation
PDAnnotationSquareCircle aSquare = new PDAnnotationSquareCircle(PDAnnotationSquareCircle.SUB_TYPE_SQUARE);
cosArrayList.add(aSquare);
assertTrue("List size shall be 4", annotationsList.size() == 4);
assertTrue("COSArray size shall be 4", annotationsArray.size() == 4);
PDAnnotation annot = (PDAnnotation) annotationsList.get(3);
assertTrue("Added annotation shall be 4th entry in COSArray", annotationsArray.indexOf(annot.getCOSObject()) == 3);
assertEquals("Provided COSArray and underlying COSArray shall be equal", annotationsArray, cosArrayList.toList());
}
use of com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotation in project PdfBox-Android by TomRoush.
the class PDFMergerUtilityTest method checkWithNumberTree.
/**
* PDFBOX-4408: Check that /StructParents values from pages and /StructParent values from
* annotations are found in the /ParentTree.
*
* @param document
*/
void checkWithNumberTree(PDDocument document) throws IOException {
PDDocumentCatalog documentCatalog = document.getDocumentCatalog();
PDNumberTreeNode parentTree = documentCatalog.getStructureTreeRoot().getParentTree();
Map<Integer, COSObjectable> numberTreeAsMap = PDFMergerUtility.getNumberTreeAsMap(parentTree);
Set<Integer> keySet = numberTreeAsMap.keySet();
PDAcroForm acroForm = documentCatalog.getAcroForm();
if (acroForm != null) {
for (PDField field : acroForm.getFieldTree()) {
for (PDAnnotationWidget widget : field.getWidgets()) {
if (widget.getStructParent() >= 0) {
assertTrue("field '" + field.getFullyQualifiedName() + "' /StructParent " + widget.getStructParent() + " missing in /ParentTree", keySet.contains(widget.getStructParent()));
}
}
}
}
for (PDPage page : document.getPages()) {
if (page.getStructParents() >= 0) {
assertTrue(keySet.contains(page.getStructParents()));
}
for (PDAnnotation ann : page.getAnnotations()) {
if (ann.getStructParent() >= 0) {
assertTrue("/StructParent " + ann.getStructParent() + " missing in /ParentTree", keySet.contains(ann.getStructParent()));
}
}
}
// might also test image and form dictionaries...
}
use of com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotation in project PdfBox-Android by TomRoush.
the class MergeAnnotationsTest method testAnnotationsMatch.
/*
* Source and target annotations are lĂnked by name with the target annotation's name
* being the source annotation's name prepended with 'annoRef_'
*/
private boolean testAnnotationsMatch(List<PDAnnotation> sourceAnnots, List<PDAnnotation> targetAnnots) {
Map<String, PDAnnotation> targetAnnotsByName = new HashMap<String, PDAnnotation>();
COSName destinationName;
// fill the map with the annotations destination name
for (PDAnnotation targetAnnot : targetAnnots) {
destinationName = (COSName) targetAnnot.getCOSObject().getDictionaryObject(COSName.DEST);
targetAnnotsByName.put(destinationName.getName(), targetAnnot);
}
// try to lookup the target annotation for the source annotation by destination name
for (PDAnnotation sourceAnnot : sourceAnnots) {
destinationName = (COSName) sourceAnnot.getCOSObject().getDictionaryObject(COSName.DEST);
if (targetAnnotsByName.get("annoRef_" + destinationName.getName()) == null) {
return false;
}
}
return true;
}
use of com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAnnotation in project PdfBox-Android by TomRoush.
the class PDAcroForm method flatten.
/**
* This will flatten the specified form fields.
*
* <p>Flattening a form field will take the current appearance and make that part
* of the pages content stream. All form fields and annotations associated are removed.</p>
*
* <p>Invisible and hidden fields will be skipped and will not become part of the
* page content stream</p>
*
* @param fields
* @param refreshAppearances if set to true the appearances for the form field widgets will be updated
* @throws IOException
*/
public void flatten(List<PDField> fields, boolean refreshAppearances) throws IOException {
// Nothing to flatten if there are no fields provided
if (fields.isEmpty()) {
return;
}
if (!refreshAppearances && getNeedAppearances()) {
Log.w("PdfBox-Android", "acroForm.getNeedAppearances() returns true, " + "visual field appearances may not have been set");
Log.w("PdfBox-Android", "call acroForm.refreshAppearances() or " + "use the flatten() method with refreshAppearances parameter");
}
// from the XFA content into a static PDF.
if (xfaIsDynamic()) {
Log.w("PdfBox-Android", "Flatten for a dynamix XFA form is not supported");
return;
}
// refresh the appearances if set
if (refreshAppearances) {
refreshAppearances(fields);
}
// the content stream to write to
PDPageContentStream contentStream;
// get the widgets per page
Map<COSDictionary, Set<COSDictionary>> pagesWidgetsMap = buildPagesWidgetsMap(fields);
// preserve all non widget annotations
for (PDPage page : document.getPages()) {
Set<COSDictionary> widgetsForPageMap = pagesWidgetsMap.get(page.getCOSObject());
// indicates if the original content stream
// has been wrapped in a q...Q pair.
boolean isContentStreamWrapped = false;
List<PDAnnotation> annotations = new ArrayList<PDAnnotation>();
for (PDAnnotation annotation : page.getAnnotations()) {
if (widgetsForPageMap != null && !widgetsForPageMap.contains(annotation.getCOSObject())) {
annotations.add(annotation);
} else if (!annotation.isInvisible() && !annotation.isHidden() && annotation.getNormalAppearanceStream() != null && annotation.getNormalAppearanceStream().getBBox() != null) {
contentStream = new PDPageContentStream(document, page, AppendMode.APPEND, true, !isContentStreamWrapped);
isContentStreamWrapped = true;
PDAppearanceStream appearanceStream = annotation.getNormalAppearanceStream();
PDFormXObject fieldObject = new PDFormXObject(appearanceStream.getCOSObject());
contentStream.saveGraphicsState();
// translate the appearance stream to the widget location if there is
// not already a transformation in place
boolean needsTranslation = resolveNeedsTranslation(appearanceStream);
// scale the appearance stream - mainly needed for images
// in buttons and signatures
boolean needsScaling = resolveNeedsScaling(annotation, page.getRotation());
Matrix transformationMatrix = new Matrix();
boolean transformed = false;
if (needsTranslation) {
transformationMatrix.translate(annotation.getRectangle().getLowerLeftX(), annotation.getRectangle().getLowerLeftY());
transformed = true;
}
// PDFBOX-4693: field could have a rotation matrix
Matrix m = appearanceStream.getMatrix();
int angle = (int) Math.round(Math.toDegrees(Math.atan2(m.getShearY(), m.getScaleY())));
int rotation = (angle + 360) % 360;
if (needsScaling) {
PDRectangle bbox = appearanceStream.getBBox();
PDRectangle fieldRect = annotation.getRectangle();
float xScale;
float yScale;
if (rotation == 90 || rotation == 270) {
xScale = fieldRect.getWidth() / bbox.getHeight();
yScale = fieldRect.getHeight() / bbox.getWidth();
} else {
xScale = fieldRect.getWidth() / bbox.getWidth();
yScale = fieldRect.getHeight() / bbox.getHeight();
}
Matrix scalingMatrix = Matrix.getScaleInstance(xScale, yScale);
transformationMatrix.concatenate(scalingMatrix);
transformed = true;
}
if (transformed) {
contentStream.transform(transformationMatrix);
}
contentStream.drawForm(fieldObject);
contentStream.restoreGraphicsState();
contentStream.close();
}
}
page.setAnnotations(annotations);
}
// remove the fields
removeFields(fields);
// remove XFA for hybrid forms
dictionary.removeItem(COSName.XFA);
}
Aggregations