#!/usr/bin/perl
#
# 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
#
use PDFlib::PDFlib;
use strict;

# This is where the data files are. Adjust as necessary. 
my $searchpath = "../data";

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

my $outfile = "starter_pdfimpose.pdf";
my $title = "PDF Impose";

my @pdffiles = (
    "markup_annotations.pdf",
    "pCOS-datasheet.pdf"
);
my $col = 0;
my $row = 0;
my $scale = 1;          # scaling factor of a page
my $rowheight;          # row height for the page to be placed
my $colwidth;           # column width for the page to be placed
my $sheetwidth = 595;   # width of the sheet
my $sheetheight = 842;  # height of the sheet
my $maxcols = 2;        # maxcols x maxrows pages will be placed on one sheet
my $maxrows = 2;

eval {
    my $p = new PDFlib::PDFlib;

    $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){
        die("Error: " . $p->get_errmsg());
    }

    $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;
    }

    $rowheight = $sheetheight * $scale;
    $colwidth = $sheetwidth * $scale;

    my $pageopen = 0; # is a page open that must be closed?
    
    # Loop over all input documents 
    foreach my $pdffile (@pdffiles) { 

        # Open the input PDF 
        my $indoc = $p->open_pdi_document($pdffile, "");
        if ($indoc == -1){
            printf("Error: %s\n", $p->get_errmsg());
            next;
        }

        my $endpage = $p->pcos_get_number($indoc, "length:pages");
        
        # Loop over all pages of the input document 
        for (my $pageno = 1; $pageno <= $endpage; $pageno++) {
            my $page = $p->open_pdi_page($indoc, $pageno, "");

            if ($page == -1) {
                printf("Error: %s\n", $p->get_errmsg());
                next;
            }
            
            # Start a new page 
            if (!$pageopen) {
                $p->begin_page_ext($sheetwidth, $sheetheight, "");
                $pageopen = 1;
            }
        
            #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();

            my $optlist = "boxsize {" . $colwidth . " " . $rowheight . "} 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);
            $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++;
            if ($col == $maxcols) {
                $col = 0;
                $row++;
            }
            # Close the page if it is full
            if ($row == $maxrows) {
                $row = 0;
                $p->end_page_ext("");
                $pageopen = 0;
            }
        }
        $p->close_pdi_document($indoc);
    }
    
    if ($pageopen) {
        $p->end_page_ext("");
    }
    
    $p->end_document("");

};

if ($@) {
    die("$0: PDFlib Exception occurred:\n$@");
}
