-
-
Save kwa29/a7363a90e1165ebd91a1b76d7d4cfb19 to your computer and use it in GitHub Desktop.
Conference badge generator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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