Placing PDF pages: Form XObject import vs. Element by Element copy

Q:

I would like to copy page content from one PDF page to another.

I based my code on you ImpositionTest sample proejct and it works fine
but the resulting PDF gives one XObject par page. This is preventing
some Acrobat plugins we use to verify/modify PDF documents to function
properly.

Is there a way to place page content from one PDF page to another by
copying element by element (instead of creating a Form XObject)?
-----
A:

Using the approach shown in ImpositionTest sample project you are
essentially converting an existing PDF page to a Form XObject and are
then placing the resulting form on the target page. This is generally
recommended approach when placing one page to another.

If you would like to avoid creating form XObjects you can also import
the page by copying element by element from the source page to the
target page. As a starting point you may want to take a look at
ElementEdit sample project. Since you are interested in plain 'content
copy' you can comment out the lines that skip image elements and that
are modifying text element. You may also want to take a look at the
following variant of ImpositionTest which is not using
element.CreateForm() method.

static void PlacePage(Page dest_page, Page src_page, Matrix2D
pos_mtx,
  ElementBuilder builder, ElementWriter writer, ElementReader reader)
{
  // Save the graphics state
  writer.WriteElement(builder.CreateGroupBegin());

  // Copy all page elements from the source page to the destination
page
  reader.Begin(src_page);
  Element element = reader.Next();
  for (int cnt=1; element!=null; ++cnt, element=reader.Next())
  {
    if (cnt == 1) element.GetGState().Concat(pos_mtx);
    writer.WriteElement(element);
  }

  reader.End();

  writer.WriteString("%Page End\n"); // Place a comment in the output
stream

  // Restore the graphics state
  writer.WriteElement(builder.CreateGroupEnd());
}

static void Main(string[] args)
{
  PDFNet.Initialize();
  PDFNet.SetResourcesPath("../../../../../resources");

  // Relative path to the folder containing test files.
  string input_path = "../../../../TestFiles/";
  string output_path = "../../../../TestFiles/Output/";

  try
  {
  
Console.WriteLine("_______________________________________________");
    Console.WriteLine("Opening the input pdf...");
    PDFDoc in_doc = new PDFDoc(input_path + "newsletter.pdf");
    in_doc.InitSecurityHandler();

    PDFDoc new_doc = new PDFDoc();

    // Import the pages that should be merged in the destination
document.
    ArrayList copy_pages = new ArrayList();
    PageIterator end = in_doc.PageEnd();
    for (PageIterator itr = in_doc.PageBegin(); itr!=end; itr.Next())
      copy_pages.Add(itr.Current());

    ArrayList imported_pages = new_doc.ImportPages(copy_pages);

    ElementBuilder builder = new ElementBuilder();
    ElementWriter writer = new ElementWriter();
    ElementReader reader = new ElementReader();

    // A3 paper width 11.69 inch * 1/72 = 841.69 points
    Rect A3_media_box = new Rect(0, 0, 1190.88, 841.69);
    Matrix2D pos_mtx = new Matrix2D(0.665, 0, 0, 0.665, 10, 0);
    for (int i=0; i<imported_pages.Count; i+=2)
    {
      // Create a blank new A3 page and place on it two pages from
      // the import list.
      Page new_page = new_doc.PageCreate(A3_media_box);
      writer.Begin(new_page);

      pos_mtx.Set(0.9, 0, 0, 0.9, 20, 20);
      PlacePage(new_page, (Page) imported_pages[i], pos_mtx, builder,
writer, reader);

      if (i+1 < imported_pages.Count) // place the second page
      {
        pos_mtx.Set(0.9, 0, 0, 0.9, 550, 20);
        PlacePage(new_page, (Page) imported_pages[i+1], pos_mtx, builder,
writer, reader);
      }

      writer.End();
      new_doc.PagePushBack(new_page);
    }

    // new_doc.Save(output_path + "newsletter_booklet.pdf", 0);
    new_doc.Save(output_path + "newsletter_booklet.pdf",
Doc.SaveOptions.e_linearized);
    new_doc.Close();
    in_doc.Close();
    Console.WriteLine("Done.");
  }
  catch (Exception e)
  {
    Console.WriteLine("Exception caught:\n{0}", e);
  }

  PDFNet.Terminate();
}