How can I create signature widget appearance from PDF content stream?

Question:

We have a custom appearance in vector form and we want to use it as a custom appearance for a Signature Widget.

How do we apply the appearance for any given page rotation?

Answer:

Approach 1:

This will generate appearance in vector form:

// Adds a custom appearance to a specified Signature Widget by using RubberStamp to adjust the appearance rotation.
//
// doc - PDFDoc containing the signature widget to add custom appearance
// page - page containing the signature widget
// widget - Signature Widget to add custom appearance
// appData - custom appearance
// bbox - user specified bounding box for the appearance
static void AddAppearanceToWidget(PDFDoc doc, Page page, Widget widget, byte[] appData, Rect bbox) {
  Obj appObj = doc.CreateIndirectStream(appData);
  appObj.PutRect("BBox", bbox.x1, bbox.y1, bbox.x2, bbox.y2);
  RubberStamp tempAnnot = RubberStamp.Create(doc, new Rect(0, 0, bbox.Width(), bbox.Height()));
  tempAnnot.SetAppearance(appObj);
  int rotation = Page.RotationToDegree(page.GetRotation());
  if (rotation != 0) {
    tempAnnot.RotateAppearance(rotation);
  }
  widget.SetAppearance(appObj);
  appObj.PutName("Subtype", "Form");
  appObj.PutName("Type", "XObject");
  appObj.putDict("Resources");
}

Approach 2:

This will generate appearance in image form:

// Adds a custom appearance to a specified Signature Widget by using PDFDraw.

// R.raw.appearance is the file containing the PDF content stream
// mAnnot is the signature widget of interest
// mAnnotPageNum is page number where the signature widget is on

void addSignatureStampToWidget() {
  PDFDraw pdfDraw = null;
  InputStream is = null;
  PDFDoc tempDoc = null;
  try {
    String sigTempFilePath = mPdfViewCtrl.getContext().getFilesDir().getAbsolutePath() + "/" + SIGNATURE_TEMP_FILE;

    is = mPdfViewCtrl.getContext().getResources().openRawResource(R.raw.appearance);
    byte[] appearance = IOUtils.toByteArray(is);
    tempDoc = new PDFDoc();
    Obj contents = tempDoc.createIndirectStream(appearance);
    Page appPage = tempDoc.pageCreate();
    appPage.getSDFObj().put("Contents", contents);
    Rect bbox = appPage.getVisibleContentBox();
    appPage.setCropBox(bbox);

    Rect cropBox = appPage.getCropBox();
    int width = (int) cropBox.getWidth();
    int height = (int) cropBox.getHeight();

    pdfDraw = new PDFDraw();
    pdfDraw.setPageTransparent(true);
    pdfDraw.setImageSize(width, height, true);
    pdfDraw.export(appPage, sigTempFilePath, "jpeg");

    // Set the appearance of the signature
    SignatureWidget signatureWidget = new SignatureWidget(mAnnot);
    Image img = Image.create(mPdfViewCtrl.getDoc(), sigTempFilePath);
    signatureWidget.createSignatureAppearance(img);

    File sigTempFile = new File(sigTempFilePath);
    if (sigTempFile.exists()) {
      //noinspection ResultOfMethodCallIgnored
      sigTempFile.delete();
    }

    mPdfViewCtrl.update(mAnnot, mAnnotPageNum);
  } catch (Exception e) {
    e.printStackTrace();
  } finally {
    if (pdfDraw != null) {
      try {
        pdfDraw.destroy();
      } catch (PDFNetException ignored) {}
    }
    Utils.closeQuietly(is);
    Utils.closeQuietly(tempDoc);
  }
}