'Merging 2 PDF forms via layering

I have 2 acro-forms I'd like to merge.

One contains only text fields, the other contains an image field with hyperlink (QR code). Both are dynamically populated.

I'd like to merge the second one onto the first one (like an overlay, but not really).

Second form (first one is proprietary - so can't post it):

form2

Here's what I've tried:

private fun prepareQrForm(qrTemplate: PDDocument, url: String): PDDocument {
    val qrCode = encodeQr(url)
    val acroForm = qrTemplate.documentCatalog.acroForm
    val pdPushButton = acroForm.getField("qr")

    val widget = pdPushButton.widgets.first()

    val qrPdImageXObject = PDImageXObject.createFromByteArray(qrTemplate, qrCode, "qr")
    val scaleRatio = qrPdImageXObject.height.toFloat() / qrPdImageXObject.width

    val imageBoundingBox = widget.rectangle

    val height = imageBoundingBox.height
    val width = height / scaleRatio
    val x = imageBoundingBox.lowerLeftX
    val y = imageBoundingBox.lowerLeftY


    val pdAppearanceStream = PDAppearanceStream(qrTemplate).apply {
      resources = PDResources()
    }

    PDAppearanceContentStream(pdAppearanceStream).use {
      it.drawImage(qrPdImageXObject, x, y, width, height)
    }

    if(widget.appearance == null) {
      widget.appearance = PDAppearanceDictionary()
    }

    widget.appearance.setNormalAppearance(pdAppearanceStream)

//    PDPageContentStream(qrTemplate, pdAppearanceStream).use {
//      it.drawImage(qrPdImageXObject, x, y, width, height)
//    }

    pdAppearanceStream.bBox = PDRectangle(x, y, width, height)


    val annotationLink = PDAnnotationLink().apply {
      action = PDActionURI().apply {
        uri = url
      }
      rectangle = imageBoundingBox
    }

    //the clickable area
    qrTemplate.getPage(0).annotations.add(annotationLink)

    return ByteArrayOutputStream().let { bos ->
      qrTemplate.save(bos)
      File("populated_qr_template.pdf").outputStream().use { it.write(bos.toByteArray()) }
      PDDocument.load(bos.toByteArray())
    }
  }

The merger:

fun overlayPdf(
      source: PDDocument,
      sourcePage: PDPage = source.getPage(0),
      target: PDDocument,
      targetPage: PDPage
  ) {
    val formObject = LayerUtility(target).importPageAsForm(source, sourcePage)
    PDPageContentStream(target, targetPage, PDPageContentStream.AppendMode.APPEND, false, true).use {
      it.drawForm(formObject)
    }
  }

The problem:

The resulting file does not contain the populated QR code, nor is clickable.

Expected:

The merged file should contain all content from both populated forms.



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source