Skip to content

Instantly share code, notes, and snippets.

@stefanv
Created August 7, 2013 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save stefanv/6174296 to your computer and use it in GitHub Desktop.
Save stefanv/6174296 to your computer and use it in GitHub Desktop.
Conference badge generator
# Original version is
# Copyright (c) 2008 Richard Wall <richard (at) the-moon.net>
# License: "Yes, by all means use and modify the code."
"""
Classes and functions concerned with the creation of delegate badges
"""
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.units import cm, mm
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.platypus import Frame, Image, ImageAndFlowables, Paragraph, \
Spacer, Flowable
from StringIO import StringIO
COLS = 2
ROWS = 4
ZOOM = 0.95
INDENT = 0.25*cm
class Line(Flowable):
"""Draw a separating line."""
def __init__(self, width, thickness=1):
Flowable.__init__(self)
self.width = width
self.thickness = thickness
def __repr__(self):
return "Line(w=%s, h=%s, t=%s)" % (self.width, self.height, self.text)
def draw(self):
self.canv.saveState()
self.canv.setLineWidth(self.thickness)
self.canv.line(0, 0, self.width, 0)
self.canv.restoreState()
class DelegateBadge(object):
"""
An object capable of rendering a delegate badge to a badge sheet canvas
"""
width = A4[0]/COLS*ZOOM
height = A4[1]/ROWS*ZOOM
def __init__(self, delegate, logoPath):
"""
delegate has delegate.full_name, delegate.institution and
delegate.country.
"""
self.delegate = delegate
self.logoPath = logoPath
self.foldPoints = (2*self.height/5, 4*self.height/5)
def rend(self, canvas):
"""
Render the badge text and graphics
@param canvas: A Canvas instance to which the badge should be rendered
"""
canvas.setLineWidth(0.1)
canvas.rect(0, 0, 9*cm, -5.5*cm)
canvas.setLineWidth(0.5)
canvas.rect(INDENT, -INDENT, 9*cm - 2*INDENT, -5.5*cm + 2*INDENT)
canvas.translate(INDENT, -INDENT)
#self._drawFoldLines(canvas)
styles = getSampleStyleSheet()
for s in ('Heading1', 'Heading2', 'Heading3', 'Normal'):
styles[s].fontName = "Helvetica"
styles['Heading3'].spaceAfter = 0
styles['Heading3'].spaceBefore = 0
styles['Heading2'].fontSize = 17
styles['Normal'].fontSize = 12
logo = Image(self.logoPath, width=39, height=39, kind='%')
body = [
ImageAndFlowables(
logo, [], imageSide='left', imageLeftPadding=0.0*cm),
Spacer(width=self.width, height=0.1*cm),
Line(width=self.width - 8*INDENT, thickness=0.1),
Spacer(width=self.width, height=1.5*mm),
Paragraph(u'SANUM 2011 \u00b7 Stellenbosch \u00b7 South Africa',
styles['Heading3']),
Line(width=self.width - 8*INDENT, thickness=0.1),
Spacer(width=self.width, height=0.2*cm),
Paragraph(self.delegate.full_name, styles['Heading2']),
Paragraph(self.delegate.institution, styles['Normal']),
Paragraph(self.delegate.country, styles['Normal']),]
f1 = Frame(0, -self.height, self.width, self.height)
[f1.add(x, canvas) for x in body]
return canvas
def _drawFoldLines(self, canvas):
"""
Draw fold lines
"""
for height in (self.foldPoints):
canvas.line(5, height, 10, height)
canvas.line(self.width-5, height, self.width-10, height)
class BadgeSheet(object):
"""
A class for creating a PDF file with a list of badges
"""
# sheet margins
bottom_margin = 0.5*cm
left_margin = 0.5*cm
def __init__(self, badges, pageSize):
"""
@param badges: a generator of Badge instances
@param pageSize: a list of the x and y dimensions of the badge sheet
"""
self.badges = badges
self.pageSize = pageSize
# Label dimensions
self.height = pageSize[1]/ROWS*ZOOM
self.width = pageSize[0]/COLS*ZOOM
def save(self, pdfPath):
self._pageCount = 0
self.canvas = canvas.Canvas(pdfPath, pagesize=self.pageSize)
for i, badge in enumerate(self.badges):
# After the ROWth label, move to the next column
# and restore state, cursor moves back to the bottom
remainder = i % (ROWS*2)
if remainder == ROWS:
self.canvas.restoreState()
self.canvas.translate(self.width, 0)
elif remainder == 0:
self._newPage()
# move up by one label height
self.canvas.translate(0, self.height)
# render one label
self.canvas.saveState()
badge.rend(self.canvas)
self.canvas.restoreState()
self.canvas.save()
def _newPage(self):
if self._pageCount > 0:
self.canvas.showPage()
# self._grid()
# Start at the margin edge left, bottom
self.canvas.translate(self.left_margin, self.bottom_margin)
self.canvas.saveState()
self._pageCount += 1
def _grid(self):
"""
Draw the grid onto the edge of the badge sheet
"""
# vertical marks
for i in range(0, 6):
# y offset
y = self.bottom_margin + i * self.height
# left edge
self.canvas.line(5, y, 20, y)
# right edge
self.canvas.line(self.pageSize[0] - 5, y, self.pageSize[0] - 20, y)
# horizontal marks
for i in range(0, 3):
# x offset
x = self.left_margin + i * self.width
# bottom edge
self.canvas.line(x, 5, x, 20)
# top edge
self.canvas.line(x, self.pageSize[1] - 5, x, self.pageSize[1] - 20)
def generate_labels(delegates, logo_path, output_file):
def badgeGenerator():
for d in delegates:
yield DelegateBadge(d, logo_path)
bs = BadgeSheet(badgeGenerator(), A4)
bs.save(output_file)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment