#!/usr/bin/env ruby
#
# PDF impose:
# Import all pages from one more existing PDFs, and place col x row pages 
# on each sheet of the output PDF (imposition). If there are annotations
# on an imported page these are also imported and scaled or rotated as
# required.
# 
# Required software: PDFlib+PDI or PDFlib Personalization Server (PPS)
# Required data: PDF documents
#

require 'PDFlib'

# This is where the data files are. Adjust as necessary. 
searchpath = '../data'

# By default annotations are also imported. In some cases this
# requires the Noto fonts for creating annotation appearance streams.
fontpath =  "../../resource/font"

outfile = "starter_pdfimpose.pdf"
title = "PDF Impose"

pdffiles = [
    "markup_annotations.pdf",
    "PLOP-datasheet.pdf",
    "pCOS-datasheet.pdf"
]
col = 0
row = 0
scale = 1          # scaling factor of a page
rowheight = 0      # row height for the page to be placed
olwidth = 0        # column width for the page to be placed
sheetwidth = 595   # width of the sheet
sheetheight = 842  # height of the sheet
maxcols = 2        # maxcols x maxrows pages will be placed on one sheet
maxrows = 2

begin
  p = PDFlib.new

  p.set_option("searchpath={" + searchpath + "}")
  p.set_option("searchpath={" + fontpath + "}")

  # This means we must check return values of load_font() etc. 
  p.set_option("errorpolicy=return")

  if (p.begin_document(outfile, "") == -1)
    raise "Error: " + p.get_errmsg()
  end

  p.set_info("Creator", "PDFlib starter sample")
  p.set_info("Title", title )
  
  # ---------------------------------------------------------------------
  # Define the sheet width and height, the number of maxrows and columns
  # and calculate the scaling factor and cell dimensions for the 
  # multi-page imposition.
  # ---------------------------------------------------------------------

  if (maxrows > maxcols)
    scale = 1.0 / maxrows
  else
    scale = 1.0 / maxcols
  end

  rowheight = sheetheight * scale
  colwidth = sheetwidth * scale

  pageopen = false # is a page open that must be closed?
  
  # Loop over all input documents 
  pdffiles.each { |pdffile|

    #Open the input PDF */
    indoc = p.open_pdi_document(pdffile, "")
    if (indoc == -1)
      print "Error: " + p.get_errmsg()
      next
    end

    endpage = p.pcos_get_number(indoc, "length:pages")
  
    # Loop over all pages of the input document 
    1.step(endpage, 1) do |pageno|
      page = p.open_pdi_page(indoc, pageno, "")

      if (page == -1) 
        print("Error: " + p.get_errmsg())
        next
      end
      
      # Start a new page 
      if (!pageopen) 
        p.begin_page_ext(sheetwidth, sheetheight, "")
        pageopen = true
      end
    
      # The save/restore pair is required to get an independent
      # clipping area for each mini page. Note that clipping
      # is not required for the imported pages, but affects
      # the rectangle around each page. Without clipping we
      # would have to move the rectangle a bit inside the
      # imported page to avoid drawing outside its area.

      p.save()

      # Clipping path for the rectangle
      p.rect(col * colwidth, sheetheight - (row + 1) * rowheight,
            colwidth, rowheight)
      p.clip()

      optlist = "boxsize {" + colwidth.to_s + " " + rowheight.to_s + "} fitmethod meet"
    
      p.fit_pdi_page(page, col * colwidth, sheetheight - (row + 1) * rowheight, optlist)

      p.close_pdi_page(page)
    
      # Draw a frame around the mini page */ 
      p.set_graphics_option("linewidth=" + scale.to_s)
      p.rect(col * colwidth, sheetheight - (row + 1) * rowheight, colwidth, rowheight)
      p.stroke()
    
      p.restore()
      # Start a new row if the current row is full

      col +=1
      if (col == maxcols) 
        col = 0
        row+=1
      end

      # Close the page if it is full
      if (row == maxrows) 
        row = 0
        p.end_page_ext("")
        pageopen = false
      end
    end
    p.close_pdi_document(indoc)
  }
  
  if (pageopen) 
    p.end_page_ext("")
  end
  
  p.end_document("")

rescue  PDFlibException => pe
  print "PDFlib exception occurred in starter_pdfimpose sample:\n"
  print "[" + pe.get_errnum.to_s + "] " + pe.get_apiname + \
    ": " + pe.get_errmsg + "\n"
rescue  Exception => e
  print e.backtrace.join("\n") + "\n" + e.to_s
ensure
  p.delete() if p
end

# vim: sw=2
