Search code examples
ghostscript

Get Ghostscript to handle portrait pages differently from landscape pages?


I am a newbie with ghostscript. I am trying to add a an additional margin to pages in a PDF. My command line works for pages in portrait mode, but messes up pages in landscape mode. I want to add 30 points width and 42 points margin all round to portrait pages (to keep the same aspect ratio), so increase the A4 page size by double that. For landscape, I reverse the numbers.

When changing the command so that it works for landscape pages, it now messes up portrait pages.

Is there a way to conditionally change the pages so that it would work on both portrait and landscape pages?

My commands were (for Windows)

  • Works for for portrait mode:

gswin64 -o c:\temp\outport.pdf -sDEVICE=pdfwrite -g6550x9270 -c "<</Install {30 42 translate}>> setpagedevice" -f "mysource.pdf"

  • Works for landscape pages

gswin64 -o c:\temp\outland.pdf -sDEVICE=pdfwrite -g9270x6550 -c "<</Install {42 30 translate}>> setpagedevice" -f "mysource.pdf"

I am doing this as originally the PDF needed a 2cm margin around text. But now I need a (roughly) 3cm margin. This way, when I print it, it will print in A4 with a cm margin and the correct aspect ratio.


Solution

  • Reluctantly I'll have to post this as an answer because it's too big for a comment.

    Create a text file with this content, call it something memorable like 'intelligent_resize.ps':

    %!
    userdict begin
    /ResetPageSize true def
    end
    
    <<
      /BeginPage
      {
        userdict /ResetPageSize known not
        {
          (Error: ResetPageSize undefined!\n) print flush
          //true
        }
        {
          userdict /ResetPageSize get
        } ifelse
    
        {
          userdict /ResetPageSize //false put
          currentpagedevice /PageSize get aload pop
          2 copy gt
          {
            60 add exch 84 add exch
            2 array astore /PageSize exch
            1 dict dup 4 2 roll put
            setpagedevice
            42 30 translate
          }
          {
            84 add exch 60 add exch
            2 array astore /PageSize exch
            1 dict dup 4 2 roll put
            setpagedevice
            30 42 translate
          } ifelse
        }
        {
          userdict /ResetPageSize //true put
        } ifelse
      }
    >> setpagedevice
    

    Then use this command line (or something similar):

    gswin64 -o c:\temp\outport.pdf -sDEVICE=pdfwrite intelligent_resize.ps "mysource.pdf"
    

    That installs a BeginPage routine which gets run at the start of every page, but with a control in userdict to determine what the routine does.

    If the control is true then it sets it to false (prevents recursion in setpagedevice) checks to see if the media is portrait or landscape, adds 60, 84 or 84,60 points to the width and height, depending on the orientation, and translates the content by 30,42 or 42,30.

    If the control is false it sets it to true.

    So we get called when the first page is begun, The control is true so we reset the control, calculate the new media size, and call setpagedevice to set that new size. That means we call BeginPage again. This time the control is false so we set the control back to true and exit back to our original BeginPage routine, which then translates the CTM of the newly created page.

    Then the content for the page gets executed. We move on to the next page and round we go again. So this 'ought' to work for PDF files containing a mixture of orientations. The code as it stands just expands all pages by the required amount and re-centers the content, it doesn't try to fit the content to a differently sized page or anything complicated.

    I don't have time to spare today to comment the program, sorry, but it shouldn't be hard to work out and modify if required. It's also not as minimal as it could be there's repeated code that could be factored out but I don't have time for that today either.

    I tried it on a Letter portrait file and a Letter landscape file and it seemed to do what you want.