use of com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream in project PdfBox-Android by TomRoush.
the class PDAbstractAppearanceHandler method getAppearanceEntryAsContentStream.
private PDAppearanceContentStream getAppearanceEntryAsContentStream(PDAppearanceEntry appearanceEntry, boolean compress) throws IOException {
PDAppearanceStream appearanceStream = appearanceEntry.getAppearanceStream();
setTransformationMatrix(appearanceStream);
// ensure there are resources
PDResources resources = appearanceStream.getResources();
if (resources == null) {
resources = new PDResources();
appearanceStream.setResources(resources);
}
return new PDAppearanceContentStream(appearanceStream, compress);
}
use of com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream in project PdfBox-Android by TomRoush.
the class PDPolygonAppearanceHandler method generateNormalAppearance.
@Override
public void generateNormalAppearance() {
PDAnnotationMarkup annotation = (PDAnnotationMarkup) getAnnotation();
float lineWidth = getLineWidth();
PDRectangle rect = annotation.getRectangle();
// Adjust rectangle even if not empty
// CTAN-example-Annotations.pdf p2
float minX = Float.MAX_VALUE;
float minY = Float.MAX_VALUE;
float maxX = Float.MIN_VALUE;
float maxY = Float.MIN_VALUE;
float[][] pathArray = getPathArray(annotation);
if (pathArray == null) {
return;
}
for (int i = 0; i < pathArray.length; ++i) {
for (int j = 0; j < pathArray[i].length / 2; ++j) {
float x = pathArray[i][j * 2];
float y = pathArray[i][j * 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 - lineWidth, rect.getLowerLeftX()));
rect.setLowerLeftY(Math.min(minY - lineWidth, rect.getLowerLeftY()));
rect.setUpperRightX(Math.max(maxX + lineWidth, rect.getUpperRightX()));
rect.setUpperRightY(Math.max(maxY + lineWidth, rect.getUpperRightY()));
annotation.setRectangle(rect);
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.createCloudyPolygon(pathArray);
annotation.setRectangle(cloudyBorder.getRectangle());
PDAppearanceStream appearanceStream = annotation.getNormalAppearanceStream();
appearanceStream.setBBox(cloudyBorder.getBBox());
appearanceStream.setMatrix(cloudyBorder.getMatrix());
} else {
for (int i = 0; i < pathArray.length; i++) {
float[] pointsArray = pathArray[i];
// first array shall be of size 2 and specify the moveto operator
if (i == 0 && pointsArray.length == 2) {
contentStream.moveTo(pointsArray[0], pointsArray[1]);
} else {
// entries of length 2 shall be treated as lineto operator
if (pointsArray.length == 2) {
contentStream.lineTo(pointsArray[0], pointsArray[1]);
} else if (pointsArray.length == 6) {
contentStream.curveTo(pointsArray[0], pointsArray[1], pointsArray[2], pointsArray[3], pointsArray[4], pointsArray[5]);
}
}
}
contentStream.closePath();
}
contentStream.drawShape(lineWidth, hasStroke, hasBackground);
} catch (IOException e) {
Log.e("PdfBox-Android", e.getMessage(), e);
} finally {
IOUtils.closeQuietly(contentStream);
}
}
use of com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream 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);
}
use of com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream in project PdfBox-Android by TomRoush.
the class PDVisibleSigBuilder method createAppearanceDictionary.
@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.i("PdfBox-Android", "PDF appearance dictionary has been created");
}
use of com.tom_roush.pdfbox.pdmodel.interactive.annotation.PDAppearanceStream in project PdfBox-Android by TomRoush.
the class PDAcroForm method resolveNeedsScaling.
/**
* 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;
}
}
Aggregations