# Mimsy Were the Borogoves

Hacks: Articles about programming in Python, Perl, Swift, BASIC, and whatever else I happen to feel like hacking at.

# Calculating true three-fold PDF in Python

I created a three-column PDF format using frames and reportlab in the article Multi-column PDFs. However, the document I used as an example was meant to be folded, and that was not a true three-fold layout. All of the columns were the same width and they were distributed evenly within the available printing area of the page. In order to make it truly foldable, the borders between each frame need to be distributed evenly across the entire paper width. This means that, unless there are only two columns, the outer frames need to be sized differently than the inner frames.

I divided this into four basic steps:

1. Add an inner margin size.
2. Set the frame width to be the first fold point, minus the inner margin size.
3. Adjust the first and last frame appropriately.
4. Draw guides for folding.

I modified the frame code to handle steps one through three:

[toggle code]

• #create the basic page
• pagesize =reportlab.lib.pagesizes.landscape(reportlab.lib.pagesizes.letter)
• pagewidth, pageheight = pagesize
• leftMargin = .25*inch
• rightMargin = .25*inch
• topMargin = .25*inch
• bottomMargin = .25*inch
• innerMargin = .25*inch
• document = platypus.BaseDocTemplate(destination, pagesize=pagesize, leftMargin=leftMargin, rightMargin=rightMargin, topMargin=topMargin, bottomMargin=bottomMargin)
• #create the frames
• frameCount = 3
• foldAt = pagewidth/frameCount
• frameWidth = foldAt-innerMargin
• #leave space for the header
• frameHeight = document.height-.25*inch
• frames = []
• #construct the column frames
• #Note that if the frame width is less than twice the document margin, this will fail
• for frame in range(frameCount):
• leftMargin = foldAt*frame
• thisWidth = frameWidth
• if frame == 0:
• leftMargin = leftMargin + document.leftMargin
• thisWidth = thisWidth - document.leftMargin + innerMargin/2
• else:
• leftMargin = leftMargin + innerMargin/2
• if frame == frameCount-1:
• thisWidth = thisWidth - document.rightMargin + innerMargin/2
• column = platypus.Frame(leftMargin, document.bottomMargin, thisWidth, frameHeight)
• frames.append(column)
• document.build(parts)

In this version, the leftmost and rightmost column are likely to be a different size than the rest of the columns, because they are also affected by the outer margins. Also, if you’re making pages with a lot of columns, you’ll want to make sure that your columns don’t start hitting negative widths after you apply the margin adjustments.

### Drawing a fold guide

We can make it easier for people to fold the sheet by adding a dashed vertical line exactly at the fold.

[toggle code]

• canvas.saveState()
• #draw lines where the paper should be folded
• foldguidestart = pageheight*.48
• foldguideend = pageheight*.52
• #set to 25% gray
• canvas.setStrokeColorRGB(.75, .75, .75)
• #set to a 3-point dotted line
• canvas.setDash(3, 3)
• for fold in range(1, frameCount):
• foldpoint = foldAt*fold
• canvas.line(foldpoint, foldguidestart, foldpoint, foldguideend)
• canvas.restoreState()

There’s nothing particularly special about this. It creates a line that is about 4% the height of the page, right in the middle of the page, and it does so at each fold point.