' 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
'

Imports System
Imports System.Text
Imports PDFlib_dotnet

Class starter_pdfimpose
    Public Shared Sub Main()
        Dim p As PDFlib_dotnet.PDFlib = Nothing

        ' This is where the data files are. Adjust as necessary.
        Const searchpath As String = "../../../data"
        ' By default annotations are also imported. In some cases this
        ' requires the Noto fonts for creating annotation appearance streams.
        ' We therefore set the searchpath to also point to the font directory.
        '
        Const fontpath = "../../../../resource/font"
        Const outfile As String = "starter_pdfimpose.pdf"
        Const title As String = "PDF Impose"

        Dim pdffiles() As String = { _
            "markup_annotations.pdf", _
            "pCOS-datasheet.pdf" _
        }
        Dim pdffile As String
        Dim col, row As Integer

        Dim scale As Double               ' scaling factor of a page
        Dim rowheight As Double           ' row height for the page to be placed
        Dim colwidth As Double            ' column width for the page to be placed

        Const sheetwidth As Double = 595  ' width of the sheet
        Const sheetheight As Double = 842 ' height of the sheet
        Dim maxcol As Integer = 2         ' maxcol x maxrow pages will be placed on one sheet
        Dim maxrow As Integer = 2

        Dim optlist As String

        Dim pageopen As Boolean = False ' is a page open that must be closed?
        Try
            p = New 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 Then
                Console.WriteLine("Error: " & p.get_errmsg())
                Return
            End If

            p.set_info("Creator", "PDFlib starter sample")
            p.set_info("Title", title)

            ' ---------------------------------------------------------------------
            ' Define the sheet width and height,  the number of rows and columns
            ' and calculate the scaling factor and cell dimensions for the 
            ' multi-page imposition.
            ' ---------------------------------------------------------------------

            If maxrow > maxcol Then
                scale = 1.0 / maxrow
            Else
                scale = 1.0 / maxcol
            End If

            rowheight = sheetheight * scale
            colwidth = sheetwidth * scale


            ' Loop over all input documents 
            For Each pdffile In pdffiles
                Dim indoc, maxpage, pageno, page As Integer

                ' Open the input PDF 
                indoc = p.open_pdi_document(pdffile, "")
                If indoc = -1 Then
                    Console.WriteLine("Error: " & p.get_errmsg())
                    Continue For
                End If

                maxpage = p.pcos_get_number(indoc, "length:pages")

                ' Loop over all pages of the input document 
                For pageno = 1 To maxpage
                    page = p.open_pdi_page(indoc, pageno, "")

                    If page = -1 Then
                        Console.WriteLine("Error: " & p.get_errmsg())
                        Continue For
                    End If

                    ' Start a new page 
                    If pageopen = False Then
                        p.begin_page_ext(sheetwidth, sheetheight, "")
                        pageopen = True
                    End If

                    ' 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 & " " & rowheight & "} fitmethod=meet"

                    ' Fit the imported page in the box
                    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()

                    col = col + 1

                    ' Start a new row if the current row is full
                    If col = maxcol Then
                        col = 0
                        row = row + 1
                    End If

                    ' Close the page if it is full
                    If row = maxrow Then
                        row = 0
                        p.end_page_ext("")
                        pageopen = False
                    End If
                Next
                p.close_pdi_document(indoc)
            Next

            If pageopen = True Then
                p.end_page_ext("")
            End If

            p.end_document("")

        Catch e As PDFlibException
            ' caught exception thrown by PDFlib
            Console.WriteLine("PDFlib exception occurred in starter_pdfimpose sample:")
            Console.WriteLine("[{0}] {1}: {2}", e.get_errnum(), e.get_apiname(), e.get_errmsg)

        Finally
            If Not p Is Nothing Then
                p.Dispose()
            End If
        End Try

    End Sub
End Class

