def draw_label(self, c: Canvas, col: int, row: int, redemption_code: str): x = self.left_margin + ( col + 0.5) * self.label_width + col * self.inner_margin y = self.page_height - self.top_margin - (row + 0.5) * self.label_height # Drawing label bounds helps when adjusting layout. Not for production. # self.draw_label_bounds(c, x, y) c.setFont("Courier-Bold", 13) c.drawString(x - 80, y + 14, redemption_code) c.setFont("Helvetica", 10) # Space to enter redemption month and day. p = c.beginPath() p.moveTo(x + 20, y + 12) p.lineTo(x + 45, y + 12) p.moveTo(x + 55, y + 12) p.lineTo(x + 80, y + 12) p.close() c.drawPath(p) c.drawCentredString(x + 15, y + 16, 'm:') c.drawCentredString(x + 50, y + 16, 'd:') # Space to enter redeemer's email address. p = c.beginPath() p.moveTo(x - 80, y - 14) p.lineTo(x + 80, y - 14) p.close() c.drawPath(p) c.drawCentredString(x, y - 24, 'email address')
def marker_spiral( canvas: Canvas, position: Point[float], size: Size[float], repititions: int, ): p = canvas.beginPath() spacing = (size.y - size.x) / repititions inner_radius_x = size.x / 1.3 inner_radius_y = size.x / 2 p.moveTo(position.x, position.y + inner_radius_y) for round in range(repititions): multiplier = lambda frac: spacing * (round + float(frac)) p.curveTo( position.x + inner_radius_x + multiplier(0), position.y + inner_radius_y + multiplier(0), position.x + inner_radius_x + multiplier(0.25), position.y - inner_radius_y - multiplier(0.25), position.x, position.y - inner_radius_y - multiplier(0.5), ) p.curveTo( position.x - inner_radius_x - multiplier(0.5), position.y - inner_radius_y - multiplier(0.75), position.x - inner_radius_x - multiplier(0.75), position.y + inner_radius_y + multiplier(1), position.x, position.y + inner_radius_y + multiplier(1), ) canvas.drawPath(p, stroke=1)
def draw_crop_mark_h(x, y, c:canvas.Canvas, color): c.setLineWidth(.1) c.setStrokeColor(color) p = c.beginPath() p.moveTo(x - CROP_MARK_LENGTH / 2, y) p.lineTo(x + CROP_MARK_LENGTH / 2, y) c.drawPath(p, stroke=1, fill=0)
def draw_bg(c:canvas.Canvas, color): path = c.beginPath() path.moveTo(0, 0) path.lineTo(0, 30 * cm) path.lineTo(25 * cm, 30 * cm) path.lineTo(25 * cm, 0) c.setFillColor(color) c.drawPath(path, True, True)
def draw_tab_bounds(self, c: Canvas, x: float, y: float, tab_width: float): p = c.beginPath() p.moveTo(x, y) p.lineTo(x, y + self.tab_height) p.lineTo(x + tab_width, y + self.tab_height) p.lineTo(x + tab_width, y) p.lineTo(x, y) p.close() c.drawPath(p)
def draw_label_bounds(self, c: Canvas, x, y): p = c.beginPath() x -= 0.5*self.label_width y -= 0.5*self.label_height p.moveTo(x, y) p.lineTo(x, y + self.label_height) p.lineTo(x + self.label_width, y + self.label_height) p.lineTo(x + self.label_width, y) p.lineTo(x, y) p.close() c.drawPath(p)
def draw_label_bounds(self, c: Canvas, x, y): p = c.beginPath() x -= 0.5 * self.label_width y -= 0.5 * self.label_height p.moveTo(x, y) p.lineTo(x, y + self.label_height) p.lineTo(x + self.label_width, y + self.label_height) p.lineTo(x + self.label_width, y) p.lineTo(x, y) p.close() c.drawPath(p)
def draw_tab(self, c: Canvas, tab_num: int, redemption_code: str) -> None: tab_width = (self.page_width - self.left_margin - self.right_margin) / self.num_tabs # (x,y) is bottom left corner of the tab: x = self.left_margin + (tab_num * tab_width) y = self.bottom_margin # Drawing tab bounds helps when adjusting layout. Not for production. #self.draw_tab_bounds(c, x, y, tab_width) self.draw_tab_guides(c, x, y, tab_width) c.saveState() c.translate(x + 0.5 * tab_width, y + 0.5 * self.tab_height) c.rotate(90) c.setFont("Helvetica", 13) c.drawString(-0.47 * self.tab_height, 0.1 * tab_width, "Free Membership!") c.setFont("Courier-Bold", 16) c.drawString(-0.47 * self.tab_height, -0.25 * tab_width, redemption_code) c.restoreState() return None c.setFont("Helvetica", 10) # Space to enter redemption month and day. p = c.beginPath() p.moveTo(x + 20, y + 12) p.lineTo(x + 45, y + 12) p.moveTo(x + 55, y + 12) p.lineTo(x + 80, y + 12) p.close() c.drawPath(p) c.drawCentredString(x + 15, y + 16, 'm:') c.drawCentredString(x + 50, y + 16, 'd:') # Space to enter redeemer's email address. p = c.beginPath() p.moveTo(x - 80, y - 14) p.lineTo(x + 80, y - 14) p.close() c.drawPath(p) c.drawCentredString(x, y - 24, 'email address')
def marker_diamond( canvas: Canvas, position: Point[float], size: Size[float], repititions: int, ): p = canvas.beginPath() spacing = (size.y - size.x) / repititions for round in range(repititions): offset = size.x + spacing * round p.moveTo(position.x, position.y + offset) p.lineTo(position.x + offset, position.y) p.lineTo(position.x, position.y - offset) p.lineTo(position.x - offset, position.y) p.lineTo(position.x, position.y + offset) canvas.drawPath(p, stroke=1)
def draw(self, work_canvas: canvas.Canvas): if self.text and self.font: work_canvas.saveState() work_canvas.setFillColor(COLOR_WHITE) work_canvas.setStrokeColor(COLOR_WHITE) canvas_path = work_canvas.beginPath() for type_op, points in self.path: if type_op == cairo.PATH_MOVE_TO: x, y = points canvas_path.moveTo(x, y) elif type_op == cairo.PATH_LINE_TO: x, y = points canvas_path.lineTo(x, y) elif type_op == cairo.PATH_CURVE_TO: x1, y1, x2, y2, x3, y3 = points canvas_path.curveTo(x1, y1, x2, y2, x3, y3) elif type_op == cairo.PATH_CLOSE_PATH: canvas_path.close() work_canvas.drawPath(canvas_path, fill=1, stroke=0) work_canvas.restoreState()
class YearlyPdf: client = Address() provider = Address() items = [] title = "Faktura" vs = "00000000" creator = "" sign_image = None payment_days = 14 paytype = "Převodem" pdffile = None def __init__(self): self.p = inflect.engine() #self.TIN = "123121414" #self.CAN = "13123123123" self.TIN = "23102404783" self.CAN = "20/13/31/2009 21/14/31/2009" self.TOP = 260 self.LEFT = 20 pdfmetrics.registerFont(TTFont('DejaVu', '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf')) self.pdffile = NamedTemporaryFile(delete=False) self.pdf = Canvas(self.pdffile.name, pagesize = A4) self.pdf.setFont("DejaVu", 15) self.pdf.setStrokeColorRGB(0, 0, 0) def __del__(self): if os.path.isfile(self.pdffile.name): os.unlink(self.pdffile.name) ############################################################# ## Setters ############################################################# def setClient(self, address): self.client = address def setProvider(self, address): self.provider = address def setTitle(self, value): self.title = value def setVS(self, value): self.vs = value def setCreator(self, value): self.creator = value def setPaytype(self, value): self.paytype = value def setPaymentDays(self, value): self.payment_days = int(value) def addItem(self, item): self.items.append(item) ############################################################# ## Getters ############################################################# def getContent(self): # Texty self.drawMain() self.drawProvider(self.TOP-8,self.LEFT+3) # self.drawClient(self.TOP-30,self.LEFT+91) #self.drawPayment(self.TOP-26,self.LEFT+3) self.pdf.setFont("DejaVu", 18) self.drawDates(self.TOP-10,self.LEFT+91) p = self.drawsItems(self.TOP-35,self.LEFT) #self.pdf.setFillColorRGB(0, 0, 0) self.pdf.showPage() self.pdf.save() f = open(self.pdffile.name) data = f.read() f.close() os.unlink(self.pdffile.name) return data ############################################################# ## Draw methods ############################################################# def drawMain(self): # Horní lajna self.pdf.drawString(self.LEFT*mm, self.TOP*mm, self.title) self.pdf.drawString((self.LEFT+65)*mm, self.TOP*mm, "Balance Sheet") self.pdf.setFont("DejaVu", 8) self.pdf.drawString((self.LEFT+120)*mm, (self.TOP)*mm, "Dated to: %s" % self.todate) self.pdf.drawString((self.LEFT+120)*mm, (self.TOP+3)*mm, "Dated from: %s" % self.fromdate) # Rámečky #self.pdf.rect((self.LEFT)*mm, (self.TOP-38)*mm, (self.LEFT+156)*mm, 35*mm, stroke=True, fill=False) path = self.pdf.beginPath() path.moveTo((self.LEFT+88)*mm, (self.TOP-3)*mm) path.lineTo((self.LEFT+88)*mm, (self.TOP-20)*mm) self.pdf.drawPath(path, True, True) path = self.pdf.beginPath() path.moveTo((self.LEFT)*mm, (self.TOP-20)*mm) path.lineTo((self.LEFT+88)*mm, (self.TOP-20)*mm) self.pdf.drawPath(path, True, True) path = self.pdf.beginPath() path.moveTo((self.LEFT+88)*mm, (self.TOP-26)*mm) path.lineTo((self.LEFT+176)*mm, (self.TOP-26)*mm) self.pdf.drawPath(path, True, True) path = self.pdf.beginPath() path.moveTo((self.LEFT+88)*mm, (self.TOP-26)*mm) path.lineTo((self.LEFT+88)*mm, (self.TOP-20)*mm) self.pdf.drawPath(path, True, True) def drawClient(self,TOP,LEFT): self.pdf.setFont("DejaVu", 12) self.pdf.drawString((LEFT)*mm, (TOP)*mm, "Odběratel") self.pdf.setFont("DejaVu", 8) text = self.pdf.beginText((LEFT+2)*mm, (TOP-6)*mm) text.textLines("\n".join(self.client.getAddressLines())) self.pdf.drawText(text) text = self.pdf.beginText((LEFT+2)*mm, (TOP-28)*mm) text.textLines("\n".join(self.client.getContactLines())) self.pdf.drawText(text) def drawProvider(self,TOP,LEFT): LEFT += 90 self.pdf.setFont("DejaVu", 12) self.pdf.drawString((LEFT)*mm, (TOP)*mm, "Address") self.pdf.setFont("DejaVu", 9) text = self.pdf.beginText((LEFT+2)*mm, (TOP-6)*mm) text.textLines("\n".join(self.provider.getAddressLines())) self.pdf.drawText(text) text = self.pdf.beginText((LEFT+40)*mm, (TOP-6)*mm) text.textLines("\n".join(self.provider.getContactLines())) self.pdf.drawText(text) if self.provider.note: self.pdf.drawString((LEFT+2)*mm, (TOP-26)*mm, self.provider.note) def drawPayment(self,TOP,LEFT): self.pdf.setFont("DejaVu", 11) self.pdf.drawString((LEFT)*mm, (TOP)*mm, "Patient Name") self.pdf.drawString((LEFT+50)*mm, (TOP)*mm, "Date") self.pdf.setFont("DejaVu", 9) text = self.pdf.beginText((LEFT+50)*mm, (TOP-6)*mm) text.textLines(self.date) self.pdf.drawText(text) text = self.pdf.beginText((LEFT+2)*mm, (TOP-6)*mm) text.textLines("\n".join(self.client.getAddressLines())) self.pdf.drawText(text) text = self.pdf.beginText((LEFT+2)*mm, (TOP-28)*mm) text.textLines("\n".join(self.client.getContactLines())) self.pdf.drawText(text) self.pdf.drawText(text) def drawsItems(self,TOP,LEFT): LEFT += 10 # Items #path = self.pdf.beginPath() #path.moveTo((LEFT)*mm, (TOP-4)*mm) #path.lineTo((LEFT+176)*mm, (TOP-4)*mm) #self.pdf.drawPath(path, True, True) self.pdf.setFont("DejaVu", 11) i=1 self.pdf.drawString((LEFT+1)*mm, (TOP-i)*mm, "Date") self.pdf.drawString((LEFT+40)*mm, (TOP-i)*mm, "Sale") self.pdf.drawString((LEFT+75)*mm, (TOP-i)*mm, "Purchase") self.pdf.drawString((LEFT+120)*mm, (TOP-i)*mm, "Credit") i+= 2 path = self.pdf.beginPath() path.moveTo((LEFT)*mm, (TOP-i)*mm) path.lineTo((LEFT+160)*mm, (TOP-i)*mm) self.pdf.drawPath(path, True, True) i+=7 self.pdf.setFont("DejaVu", 9) # List purchase = 0.0 sale = 0.0 credit = 0.0 for x in self.sitems: if TOP - i < 30: self.pdf.showPage() self.pdf.setFont("DejaVu", 9) i = TOP - 270 self.pdf.drawString((LEFT+1)*mm, (TOP-i)*mm, x.date) i+=0 self.pdf.drawString((LEFT+41)*mm, (TOP-i)*mm,"Rs. " + str(x.sale)) self.pdf.drawString((LEFT+76)*mm, (TOP-i)*mm,"Rs. " + str(x.purchase)) self.pdf.drawString((LEFT+121)*mm, (TOP-i)*mm,"Rs. " +str(x.credit)) i+=5 purchase += x.purchase sale += x.sale credit += x.credit path = self.pdf.beginPath() path.moveTo((LEFT)*mm, (TOP-i)*mm) path.lineTo((LEFT+160)*mm, (TOP-i)*mm) self.pdf.drawPath(path, True, True) i+= 10 path = self.pdf.beginPath() path.moveTo((LEFT)*mm, (TOP-i)*mm) path.lineTo((LEFT+160)*mm, (TOP-i)*mm) self.pdf.drawPath(path, True, True) sale = round(sale,2) purchase = round(purchase,2) credit = round(credit,2) self.pdf.setFont("DejaVu", 10) self.pdf.setFont("DejaVu", 11) self.pdf.drawString((LEFT+2)*mm, (TOP-i+3)*mm, "Total Sale: ") self.pdf.drawString((LEFT+25)*mm, (TOP-i+3)*mm, "Rs. " + str(sale)) self.pdf.drawString((LEFT+52)*mm, (TOP-i+3)*mm, "Purchase: ") self.pdf.drawString((LEFT+73)*mm, (TOP-i+3)*mm, "Rs. " + str(purchase)) self.pdf.drawString((LEFT+97)*mm, (TOP-i+3)*mm, "Credit: ") self.pdf.drawString((LEFT+112)*mm, (TOP-i+3)*mm, "Rs. " + str(credit)) # self.pdf.rect((LEFT)*mm, (TOP-i-12)*mm, (LEFT+156)*mm, (i+19)*mm, stroke=True, fill=False) #140,142 if self.sign_image: self.pdf.drawImage(self.sign_image, (LEFT+98)*mm, (TOP-i-72)*mm) return TOP - i # if self.creator: # path = self.pdf.beginPath() # path.moveTo((LEFT+110)*mm, (TOP-i-70)*mm) # path.lineTo((LEFT+164)*mm, (TOP-i-70)*mm) # self.pdf.drawPath(path, True, True) # self.pdf.drawString((LEFT+112)*mm, (TOP-i-75)*mm, "Authorized Signatory") # self.pdf.rect((LEFT)*mm, (TOP-i-12)*mm, (LEFT+156)*mm, (i+19)*mm, stroke=True, fill=False) #140,142 def drawDates(self,TOP,LEFT): LEFT -= 90 today = datetime.datetime.today() payback = today+datetime.timedelta(self.payment_days) self.pdf.setFont("DejaVu", 10) self.pdf.drawString((LEFT)*mm, (TOP+1)*mm, "TIN: %s" % self.TIN) self.pdf.drawString((LEFT)*mm, (TOP-4)*mm, "DL: %s" % self.CAN)
class PDFWriter(): def __init__(self): ## Page size ## self.stock = A4 self._stockHeight = self.stock[1] self._stockWidth = self.stock[0] ## base font ## self.baseFontFamily = "Times-Roman" self.baseFontSize = 12 self.currentFontFamily = self.baseFontFamily self.currentFontSize = self.baseFontSize ## block sizing ## self.c = Canvas("test.pdf", pagesize=self.stock) self.marginTop = mm * 20 self.marginRight = mm * 20 self.marginBottom = mm * 40 self.marginLeft = mm * 20 self.c.translate(self.marginLeft, self.marginBottom) self.blockHeight = self._stockHeight - self.marginTop - self.marginBottom self.blockWidth = self._stockWidth - self.marginLeft - self.marginRight self.blockXCenter = self.blockWidth / 2 self.blockYCenter = self.blockHeight / 2 ## font ## self.resetFont() def startVerticalTextEnvironment(self): self.c.saveState() # translate back to corner self.c.translate(-self.marginLeft, -self.marginBottom) # rotate self.c.rotate(270) # translate to bottom corner self.c.translate(-self._stockHeight + self.marginTop, self.marginLeft) def endVerticalTextEnvironment(self): self.c.restoreState() def verticalString(self, x, y, s): ''' Only to be called in the vertical environment. Places at xy as if nothing moved. ''' self.c.drawString(self.blockHeight - y, x, s) def setFont(self, family, size): self.currentFontFamily = family self.c.setFont(self.currentFontFamily, size) def setFontSize(self, size): self.currentFontSize = size self.c.setFont(self.currentFontFamily, size) def setFontFamily(self, family): self.c.setFont(family, self.currentFontSize) def resetFont(self): self.c.setFont(self.baseFontFamily, self.baseFontSize) def save(self): self.c.save() def vLine(self, x, y, toY): self.c.line(x, y, x, toY) def hLine(self, x, toX, y): self.c.line(x, y, toX, y) def string(self, x, y, s): return self.c.drawString(x, y, s) def centeredString(self, x, y, s): return self.c.drawCentredString(x, y, s) def stencil(self, points, close): self.c.setLineWidth(5) p = self.c.beginPath() xs, ys = points.pop(0) p.moveTo(xs, ys) for x1, y1 in points: p.lineTo(x1, y1) if (close): p.close() self.c.drawPath(p) def invertY(self, y): ''' Y coorinates relative to top left corner ''' return self.blockHeight - y def test(self): self.hLine(0, self.blockWidth, self.blockHeight) self.vLine(0, 0, self.blockHeight) self.hLine(0, self.blockWidth, 0) self.vLine(self.blockWidth, 0, self.blockHeight) #self.hLine(self._centerPage, self._blockWidth, self._blockHeight/2) self.setFontSize(32) self.setFontFamily('LiberationSF') self.centeredString(self.blockXCenter, self.blockYCenter, 'doya?') self.resetFont() self.startVerticalTextEnvironment() self.verticalString(self.blockXCenter, self.invertY(0), 'hangin...') self.endVerticalTextEnvironment() self.string(self.blockXCenter, self.blockYCenter - 40, 'teh ah') self.stencil([(30, 30), (100, 30), (100, 25)], False) self.save()
class PDFBase(object): logo = None headertext = None sendertext = settings.ORG_NAME def __init__(self, recipient): self.pdfdata = BytesIO() self.canvas = Canvas(self.pdfdata) self.recipient = recipient self.preview = False def prepare(self): self.canvas.setTitle(self.title) self.canvas.setSubject(self.title) self.canvas.setAuthor(settings.ORG_NAME) self.canvas._doc.info.producer = "{0} Invoicing System".format(settings.ORG_NAME) registerFont(TTFont('DejaVu Serif', "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSerif.ttf")) registerFont(TTFont('DejaVu Serif Italic', "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSerif-Italic.ttf")) registerFont(TTFont('DejaVu Serif Bold', "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSerif-Bold.ttf")) def trimstring(self, s, maxlen, fontname, fontsize): while len(s) > 5: if self.canvas.stringWidth(s, fontname, fontsize) <= maxlen: return s s = s[:len(s) - 2] return s def fontheight(self, fontname, size): face = getFont(fontname).face return face.ascent * size / 1000.0 - face.descent * size / 1000.0 def textlines(self, t, lines): for l in lines.splitlines(): t.textLine(l) def _draw_multiline_aligned(self, txt, left, top, width, height): t = txt.replace("\n", "<br/>") style = ParagraphStyle('temp') style.fontName = 'DejaVu Serif' style.fontSize = 9 style.leading = 9 * 1.2 p = Paragraph(t, style) (actualwidth, actualheight) = p.wrap(width, height) p.drawOn(self.canvas, left, top - actualheight) def draw_header(self): if self.preview: t = self.canvas.beginText() t.setTextOrigin(cm(6), cm(4)) t.setFont("DejaVu Serif Italic", 70) t.setFillColorRGB(0.9, 0.9, 0.9) t.textLine("PREVIEW PREVIEW") self.canvas.rotate(45) self.canvas.drawText(t) self.canvas.rotate(-45) if self.logo: im = Image(self.logo, width=cm(3), height=cm(3)) im.drawOn(self.canvas, cm(2), cm(25)) if self.headertext: t = self.canvas.beginText() t.setFillColor(colors.black) t.setFont("DejaVu Serif", 9) t.setTextOrigin(cm(6), cm(27.5)) self.textlines(t, self.headertext) self.canvas.drawText(t) if self.sendertext: self._draw_multiline_aligned(self.sendertext, cm(2), cm(23.5), cm(9), cm(4)) self._draw_multiline_aligned("To:\n%s" % self.recipient, cm(11), cm(23.5), cm(9), cm(4)) p = self.canvas.beginPath() p.moveTo(cm(2), cm(18.9)) p.lineTo(cm(19), cm(18.9)) self.canvas.drawPath(p)
def make_page(c: Canvas, year_and_month: date, image: Image): months = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ] points, triangles = get_triangles(50, 25) centroids = get_centroids(points, triangles.simplices) dominants = get_dominant_colour(image, 12) seeds = numpy.random.uniform(0.0, 100000.0, [7]) values = numpy.zeros([centroids.shape[1]]) for p in range(centroids.shape[1]): values[p] = perlin_noise(seeds, centroids[0, p], centroids[1, p]) bright_seeds = numpy.random.uniform(-16, 16, [centroids.shape[1]]) colours = get_colour(values, dominants) + numpy.transpose( numpy.array([bright_seeds, bright_seeds, bright_seeds])) colours = numpy.clip(colours, 0, 255) width, height = A4 c.translate(0.5 * inch, 0.5 * inch + height * 2 / 3) pw, ph = width - 1 * inch, height / 3 - 1 * inch for i, t in enumerate(triangles.simplices): vertices = points[t] colour = colours[i] c.setStrokeColorRGB(colour[0] / 255, colour[1] / 255, colour[2] / 255) c.setFillColorRGB(colour[0] / 255, colour[1] / 255, colour[2] / 255) c.setLineJoin(1) path = c.beginPath() path.moveTo(vertices[0, 0] * pw, vertices[0, 1] * ph) path.lineTo(vertices[1, 0] * pw, vertices[1, 1] * ph) path.lineTo(vertices[2, 0] * pw, vertices[2, 1] * ph) path.close() c.drawPath(path, stroke=1, fill=1) c.translate(0, -1 * inch) c.setFont("Helvetica-Bold", 24) c.setFillColorRGB(0, 0, 0) c.drawString(0, 0, months[year_and_month.month - 1]) c.translate(0, -0.5 * inch) data = [(d[0], d[1], "") for d in get_days_and_dow(year_and_month)] if len(data) < 32: for _ in range(32 - len(data)): data.append(("", "", "")) data = zip_longest(data[:16], data[16:], fillvalue="") data = [[dt[0][0], dt[0][1], dt[0][2], dt[1][0], dt[1][1], dt[1][2]] for dt in data] table = Table(data, 2 * [0.5 * inch, 0.5 * inch, 2.63 * inch], 16 * [0.32 * inch]) style = [('ALIGN', (0, 0), (-1, -1), 'CENTER'), ('VALIGN', (0, 0), (-1, -1), 'MIDDLE'), ('GRID', (0, 0), (-1, -1), 1, colors.black), ('BOX', (0, 0), (-1, -1), 2, colors.black)] for row_no, row in enumerate(data): if row[0] == 'Sun' or row[0] == 'Sat': style.append(('TEXTCOLOR', (0, row_no), (2, row_no), colors.green)) else: style.append(('TEXTCOLOR', (0, row_no), (2, row_no), colors.black)) if row[3] == 'Sun' or row[3] == 'Sat': style.append( ('TEXTCOLOR', (3, row_no), (-1, row_no), colors.green)) else: style.append( ('TEXTCOLOR', (3, row_no), (-1, row_no), colors.black)) table.setStyle(style) aw, ah = width - 1 * inch, height * 2 / 3 - 1.5 * inch w, h = table.wrap(aw, ah) c.translate(0, -h) table.drawOn(c, 0, 0) c.showPage()
from reportlab.lib.colors import HexColor from reportlab.pdfgen.canvas import Canvas from reportlab.lib.units import cm pdf = Canvas("bgColour.pdf") pdf.setFillColor(HexColor("#99b0e7")) path = pdf.beginPath() path.moveTo(0*cm,0*cm) path.lineTo(0*cm,30*cm) path.lineTo(25*cm,30*cm) path.lineTo(25*cm,0*cm) #this creates a rectangle the size of the sheet pdf.drawPath(path,True,True) pdf.showPage() pdf.save()
class PDFInvoice(object): def __init__(self, recipient, invoicedate, duedate, invoicenum=None, imagedir=None, currency='€', preview=False, receipt=False, bankinfo=True): self.pdfdata = StringIO.StringIO() self.canvas = Canvas(self.pdfdata) self.recipient = recipient self.invoicenum = invoicenum self.invoicedate = invoicedate self.duedate = duedate self.imagedir = imagedir or '.' self.currency = currency or '€' self.preview = preview self.receipt = receipt self.bankinfo = bankinfo self.rows = [] if self.receipt: # Never include bank info on receipts self.bankinfo = False self.canvas.setTitle("PostgreSQL Europe Invoice #%s" % self.invoicenum) self.canvas.setSubject("PostgreSQL Europe Invoice #%s" % self.invoicenum) self.canvas.setAuthor("PostgreSQL Europe") self.canvas._doc.info.producer = "PostgreSQL Europe Invoicing System" def addrow(self, title, cost, count=1): self.rows.append((title, cost, count,)) def trimstring(self, s, maxlen, fontname, fontsize): while len(s) > 5: if self.canvas.stringWidth(s, fontname, fontsize) <= maxlen: return s s = s[:len(s)-2] return s def _pageheader(self): if self.preview: t = self.canvas.beginText() t.setTextOrigin(6*cm, 4*cm) t.setFont("Times-Italic", 70) t.setFillColorRGB(0.9,0.9,0.9) t.textLines("PREVIEW PREVIEW") self.canvas.rotate(45) self.canvas.drawText(t) self.canvas.rotate(-45) im = Image("%s/PostgreSQL_logo.1color_blue.300x300.png" % self.imagedir, width=3*cm, height=3*cm) im.drawOn(self.canvas, 2*cm, 25*cm) t = self.canvas.beginText() t.setFillColorRGB(0,0,0,0) t.setFont("Times-Roman", 10) t.setTextOrigin(6*cm, 27.5*cm) t.textLines("""PostgreSQL Europe Carpeaux Diem 13, rue du Square Carpeaux 75018 PARIS France """) self.canvas.drawText(t) t = self.canvas.beginText() t.setTextOrigin(2*cm, 23*cm) t.setFont("Times-Roman", 10) t.textLine("") t.textLines(""" Your contact: Guillaume Lelarge Function: PostgreSQL Europe Treasurer E-mail: [email protected] """) self.canvas.drawText(t) t = self.canvas.beginText() t.setTextOrigin(11*cm, 23*cm) t.setFont("Times-Italic", 11) t.textLine("To:") t.setFont("Times-Roman", 11) t.textLines(self.recipient) self.canvas.drawText(t) p = self.canvas.beginPath() p.moveTo(2*cm, 18.9*cm) p.lineTo(19*cm, 18.9*cm) self.canvas.drawPath(p) def save(self): # We can fit 15 rows on one page. We might want to do something # cute to avoid a single row on it's own page in the future, but # for now, just split it evenly. for pagenum in range(0, (len(self.rows)-1)/15+1): self._pageheader() islastpage = (pagenum == (len(self.rows)-1)/15) if len(self.rows) > 15: suffix = " (page %s/%s)" % (pagenum+1, len(self.rows)/15+1) else: suffix = '' # Center between 2 and 19 is 10.5 if self.invoicenum: if self.receipt: self.canvas.drawCentredString(10.5*cm,19*cm, "RECEIPT FOR INVOICE NUMBER %s%s" % (self.invoicenum, suffix)) else: self.canvas.drawCentredString(10.5*cm,19*cm, "INVOICE NUMBER %s - %s%s" % (self.invoicenum, self.invoicedate.strftime("%B %d, %Y"),suffix)) else: self.canvas.drawCentredString(10.5*cm,19*cm, "RECEIPT - %s%s" % (self.invoicedate.strftime("%B %d, %Y"), suffix)) if pagenum == 0: tbldata = [["Item", "Price", "Count", "Amount"], ] else: tbldata = [["Item - continued from page %s" % pagenum, "Price", "count", "amount"], ] tbldata.extend([(self.trimstring(title, 10.5*cm, "Times-Roman", 10), "%.2f %s" % (cost, self.currency), count, "%.2f %s" % ((cost * count), self.currency)) for title,cost, count in self.rows[pagenum*15:(pagenum+1)*15]]) style = [ ('BACKGROUND',(0,0),(3,0),colors.lightgrey), ('ALIGN',(1,0),(3,-1),'RIGHT'), ('LINEBELOW',(0,0),(-1,0), 2, colors.black), ('OUTLINE', (0,0), (-1, -1), 1, colors.black), ] if islastpage: tbldata.append(['','','Total',"%.2f %s" % (sum([cost*count for title,cost,count in self.rows]),self.currency)]) style.append(('LINEABOVE', (-2,-1), (-1, -1), 2, colors.black)) else: tbldata.append([' Continued on page %s' % (pagenum + 2), '', '', '']) style.append(('ALIGN', (0, -1), (-1, -1), 'CENTER')) style.append(('FONT', (0, -1), (-1, -1), 'Times-Italic')) t = Table(tbldata, [10.5*cm, 2.5*cm, 1.5*cm, 2.5*cm]) t.setStyle(TableStyle(style)) w,h = t.wrapOn(self.canvas,10*cm,10*cm) t.drawOn(self.canvas, 2*cm, 18*cm-h) if self.receipt: self.canvas.drawCentredString(10.5*cm,17.3*cm-h, "This invoice was paid %s" % self.duedate.strftime("%B %d, %Y")) else: self.canvas.drawCentredString(10.5*cm,17.3*cm-h, "This invoice is due: %s" % self.duedate.strftime("%B %d, %Y")) t = self.canvas.beginText() t.setTextOrigin(2*cm, 5*cm) t.setFont("Times-Italic", 10) t.textLine("PostgreSQL Europe is a French non-profit under the French 1901 Law. The association is not VAT registered.") t.textLine("") if islastpage and self.bankinfo: t.setFont("Times-Bold", 10) t.textLine("Bank references / Références bancaires / Bankverbindungen / Referencias bancarias") t.setFont("Times-Roman", 8) t.textLines("""CCM PARIS 1-2 LOUVRE MONTORGUEIL 28 RUE ETIENNE MARCEL 75002 PARIS FRANCE IBAN: FR76 1027 8060 3100 0205 2290 114 BIC: CMCIFR2A """) self.canvas.drawText(t) # Finish this page off, and optionally loop to another one self.canvas.showPage() # Last page is finished, flush the PDF output self.canvas.save() return self.pdfdata
class Invoice: client = Address() provider = Address() items = [] title = "Faktura" vs = "00000000" creator = "" sign_image = None payment_days = 14 paytype = "Převodem" pdffile = None def __init__(self): self.p = inflect.engine() self.TIN = "23102404783" self.CAN = "20/13/31/2009 21/14/31/2009" self.TOP = 260 self.LEFT = 20 pdfmetrics.registerFont(TTFont('DejaVu', '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf')) self.pdffile = NamedTemporaryFile(delete=False) self.pdf = Canvas(self.pdffile.name, pagesize = letter) self.pdf.setFont("DejaVu", 15) self.pdf.setStrokeColorRGB(0, 0, 0) def __del__(self): if os.path.isfile(self.pdffile.name): os.unlink(self.pdffile.name) ############################################################# ## Setters ############################################################# def setClient(self, address): self.client = address def setProvider(self, address): self.provider = address def setTitle(self, value): self.title = value def setVS(self, value): self.vs = value def setCreator(self, value): self.creator = value def setPaytype(self, value): self.paytype = value def setPaymentDays(self, value): self.payment_days = int(value) def addItem(self, item): self.items.append(item) ############################################################# ## Getters ############################################################# def getContent(self): # Texty self.drawMain() # barcode=code39.Extended39("inv"+str(int(self.vs)),barWidth=0.5*mm,barHeight=5*mm) # barcode.drawOn(self.pdf,self.TOP+45,(self.LEFT+735)) #qrw = QrCodeWidget('hello cruel world!') #self.pdf.add(qrw) # qrw = QrCodeWidget(value = "Invoice" + str(int(self.vs)), barLevel = "Q") # b = qrw.getBounds() # w=b[2]-b[0] # h=b[3]-b[1] # qr_size = 60 # drawing = Drawing(qr_size,qr_size,transform=[float(qr_size)/w,0,0,float(qr_size)/h,0,0]) # drawing.add(qrw) # renderPDF.draw(drawing, self.pdf, self.TOP+25, self.LEFT+710) # qrw.drawOn(self.pdf,self.TOP+45,(self.LEFT+735)) self.drawProvider(self.TOP-8,self.LEFT+3) # self.drawClient(self.TOP-30,self.LEFT+91) self.drawPayment(self.TOP-26,self.LEFT+3) self.drawItems(self.TOP-45,self.LEFT) self.drawDates(self.TOP-10,self.LEFT+91) self.drawWatermark() #self.pdf.setFillColorRGB(0, 0, 0) self.pdf.showPage() self.pdf.save() f = open(self.pdffile.name) data = f.read() f.close() os.unlink(self.pdffile.name) return data ############################################################# ## Draw methods ############################################################# def drawMain(self): # Horní lajna self.pdf.drawString(self.LEFT*mm, self.TOP*mm, self.title) self.pdf.drawString((self.LEFT+100)*mm, self.TOP*mm, "Invoice No.: %s" % self.vs) # Rámečky self.pdf.rect((self.LEFT)*mm, (self.TOP-38)*mm, (self.LEFT+156)*mm, 35*mm, stroke=True, fill=False) path = self.pdf.beginPath() path.moveTo((self.LEFT+88)*mm, (self.TOP-3)*mm) path.lineTo((self.LEFT+88)*mm, (self.TOP-20)*mm) self.pdf.drawPath(path, True, True) path = self.pdf.beginPath() path.moveTo((self.LEFT)*mm, (self.TOP-20)*mm) path.lineTo((self.LEFT+88)*mm, (self.TOP-20)*mm) self.pdf.drawPath(path, True, True) path = self.pdf.beginPath() path.moveTo((self.LEFT+88)*mm, (self.TOP-26)*mm) path.lineTo((self.LEFT+176)*mm, (self.TOP-26)*mm) self.pdf.drawPath(path, True, True) path = self.pdf.beginPath() path.moveTo((self.LEFT+88)*mm, (self.TOP-26)*mm) path.lineTo((self.LEFT+88)*mm, (self.TOP-20)*mm) self.pdf.drawPath(path, True, True) def drawWatermark(self): pass def drawClient(self,TOP,LEFT): self.pdf.setFont("DejaVu", 12) self.pdf.drawString((LEFT)*mm, (TOP)*mm, "Odběratel") self.pdf.setFont("DejaVu", 8) text = self.pdf.beginText((LEFT+2)*mm, (TOP-6)*mm) text.textLines("\n".join(self.client.getAddressLines())) self.pdf.drawText(text) text = self.pdf.beginText((LEFT+2)*mm, (TOP-28)*mm) text.textLines("\n".join(self.client.getContactLines())) self.pdf.drawText(text) def drawProvider(self,TOP,LEFT): LEFT += 90 self.pdf.setFont("DejaVu", 12) self.pdf.drawString((LEFT)*mm, (TOP)*mm, "Address") self.pdf.setFont("DejaVu", 9) text = self.pdf.beginText((LEFT+2)*mm, (TOP-6)*mm) text.textLines("\n".join(self.provider.getAddressLines())) self.pdf.drawText(text) text = self.pdf.beginText((LEFT+40)*mm, (TOP-6)*mm) text.textLines("\n".join(self.provider.getContactLines())) self.pdf.drawText(text) if self.provider.note: self.pdf.drawString((LEFT+2)*mm, (TOP-26)*mm, self.provider.note) def drawPayment(self,TOP,LEFT): self.pdf.setFont("DejaVu", 11) self.pdf.drawString((LEFT)*mm, (TOP)*mm, "Patient Name") self.pdf.drawString((LEFT+50)*mm, (TOP)*mm, "Date") self.pdf.setFont("DejaVu", 9) text = self.pdf.beginText((LEFT+50)*mm, (TOP-6)*mm) text.textLines(self.date) self.pdf.drawText(text) text = self.pdf.beginText((LEFT+2)*mm, (TOP-6)*mm) text.textLines("\n".join(self.client.getAddressLines())) self.pdf.drawText(text) text = self.pdf.beginText((LEFT+2)*mm, (TOP-28)*mm) text.textLines("\n".join(self.client.getContactLines())) self.pdf.drawText(text) self.pdf.drawText(text) def drawItems(self,TOP,LEFT): # Items #path = self.pdf.beginPath() #path.moveTo((LEFT)*mm, (TOP-4)*mm) #path.lineTo((LEFT+176)*mm, (TOP-4)*mm) #self.pdf.drawPath(path, True, True) self.pdf.setFont("DejaVu", 11) i=1 self.pdf.drawString((LEFT+1)*mm, (TOP-i)*mm, "Description") self.pdf.drawString((LEFT+98)*mm, (TOP-i)*mm, "Quantity") self.pdf.drawString((LEFT+121)*mm, (TOP-i)*mm, "Unit Price") self.pdf.drawString((LEFT+149)*mm, (TOP-i)*mm, "Amount") i+=7 self.pdf.setFont("DejaVu", 9) # List total=0.0 for x in self.items: self.pdf.drawString((LEFT+1)*mm, (TOP-i)*mm, x.name) i+=0 self.pdf.drawString((LEFT+100)*mm, (TOP-i)*mm, "%d" % x.count) self.pdf.drawString((LEFT+122)*mm, (TOP-i)*mm, "Rs. %.2f" % x.price) self.pdf.drawString((LEFT+150)*mm, (TOP-i)*mm, "Rs. %.2f" % (x.total())) i+=5 total += x.total() self.items = [] path = self.pdf.beginPath() path.moveTo((LEFT)*mm, (TOP-i)*mm) path.lineTo((LEFT+176)*mm, (TOP-i)*mm) self.pdf.drawPath(path, True, True) total = round(total,2) self.pdf.setFont("DejaVu", 10) self.pdf.drawString((LEFT+1)*mm, (TOP-i-8)*mm, self.p.number_to_words(total).title() + " Rupees Only.") self.pdf.setFont("DejaVu", 12) self.pdf.drawString((LEFT+130)*mm, (TOP-i-8)*mm, "Total: Rs. %s" % total) self.pdf.setFont("Helvetica-Bold", 40) self.pdf.setStrokeGray(0.25) self.pdf.setFillColorRGB(0.95, 0.95, 0.95) self.pdf.drawString((LEFT+60)*mm, (TOP-i)*mm, 'PAID') self.pdf.setFillColorRGB(0, 0, 0) self.pdf.rect((LEFT)*mm, (TOP-i-12)*mm, (LEFT+156)*mm, (i+19)*mm, stroke=True, fill=False) #140,142 if self.sign_image: self.pdf.drawImage(self.sign_image, (LEFT+98)*mm, (TOP-i-72)*mm) # if self.creator: # path = self.pdf.beginPath() # path.moveTo((LEFT+110)*mm, (TOP-i-70)*mm) # path.lineTo((LEFT+164)*mm, (TOP-i-70)*mm) # self.pdf.drawPath(path, True, True) # self.pdf.drawString((LEFT+112)*mm, (TOP-i-75)*mm, "Authorized Signatory") def drawDates(self,TOP,LEFT): LEFT -= 90 today = datetime.datetime.today() payback = today+datetime.timedelta(self.payment_days) self.pdf.setFont("DejaVu", 10) self.pdf.drawString((LEFT)*mm, (TOP+1)*mm, "TIN: %s" % self.TIN) self.pdf.drawString((LEFT)*mm, (TOP-4)*mm, "DL: %s" % self.CAN)
class PDFGenerator(object): canvas = None colorspace = None use_spot = True num_pages = 0 page_count = 0 prgs_msg = _('Saving in process...') def __init__(self, fileptr, cms, version=PDF_VERSION_DEFAULT): self.cms = cms self.canvas = Canvas(fileptr, pdfVersion=version[0]) self.info = UC_PDFInfo(self.canvas._doc) self.info.pdfxversion = version[1] self.info.subject = '---' self.canvas.setPageCompression(1) #---PDF doc data def set_creator(self, name): self.info.creator = name def set_producer(self, name): self.info.producer = name def set_title(self, title): self.info.title = title def set_author(self, author): self.info.author = author def set_subject(self, subj): self.info.subject = subj def set_keywords(self, keywords): self.info.keywords = keywords #---Rendering options def set_compression(self, val=True): self.canvas.setPageCompression(int(val)) def set_colorspace(self, cs=None): self.colorspace = cs def set_spot_usage(self, val=True): self.use_spot = val #---Page processing def set_num_pages(self, num=1): self.num_pages = num def set_progress_message(self, msg): self.prgs_msg = msg def start_page(self, w, h, left_margin=0.0, top_margin=0.0): self.canvas.translate(w / 2.0 - left_margin, h / 2.0 - top_margin) self.canvas.setPageSize((w, h)) position = 0.0 if self.num_pages: position = float(self.page_count) / float(self.num_pages) events.emit(events.FILTER_INFO, self.prgs_msg, position) def end_page(self): self.canvas.showPage() self.page_count += 1 position = 1.0 if self.num_pages: position = float(self.page_count) / float(self.num_pages) events.emit(events.FILTER_INFO, self.prgs_msg, position) def save(self): self.canvas.save() #--- Rendering def render(self, objs, toplevel=False): obj_count = 0 for obj in objs: if obj.is_pixmap(): self.draw_pixmap(obj) elif obj.is_primitive(): curve_obj = obj.to_curve() if curve_obj.is_primitive(): self.draw_curve(curve_obj) else: self.render(curve_obj.childs) elif obj.is_container(): self.draw_container(obj) else: self.render(obj.childs) #---Progress obj_count += 1 shift = 0.0 page_size = 1.0 if self.num_pages: shift = float(self.page_count) / float(self.num_pages) page_size = 1.0 / float(self.num_pages) position = shift + obj_count / len(objs) * page_size events.emit(events.FILTER_INFO, self.prgs_msg, position) def draw_curve(self, curve_obj): paths = libgeom.apply_trafo_to_paths(curve_obj.paths, curve_obj.trafo) pdfpath, closed = self.make_pdfpath(paths) fill_style = curve_obj.style[0] stroke_style = curve_obj.style[1] if stroke_style and stroke_style[7]: self.stroke_pdfpath(pdfpath, stroke_style, curve_obj.stroke_trafo) if fill_style and fill_style[0] & sk2_const.FILL_CLOSED_ONLY and closed: self.fill_pdfpath(curve_obj, pdfpath, fill_style, curve_obj.fill_trafo) elif fill_style and not fill_style[0] & sk2_const.FILL_CLOSED_ONLY: self.fill_pdfpath(curve_obj, pdfpath, fill_style, curve_obj.fill_trafo) if stroke_style and not stroke_style[7]: self.stroke_pdfpath(pdfpath, stroke_style, curve_obj.stroke_trafo) def draw_container(self, obj): container = obj.childs[0].to_curve() paths = libgeom.apply_trafo_to_paths(container.paths, container.trafo) pdfpath, closed = self.make_pdfpath(paths) fill_style = container.style[0] stroke_style = container.style[1] if stroke_style and stroke_style[7]: self.stroke_pdfpath(pdfpath, stroke_style, container.stroke_trafo) self.canvas.saveState() self.canvas.clipPath(pdfpath, 0, 0) if fill_style and fill_style[0] & sk2_const.FILL_CLOSED_ONLY and closed: self.fill_pdfpath(container, pdfpath, fill_style, container.fill_trafo) elif fill_style and not fill_style[0] & sk2_const.FILL_CLOSED_ONLY: self.fill_pdfpath(container, pdfpath, fill_style, container.fill_trafo) self.render(obj.childs[1:]) self.canvas.restoreState() if stroke_style and not stroke_style[7]: self.stroke_pdfpath(pdfpath, stroke_style, container.stroke_trafo) def make_pdfpath(self, paths): closed = False pdfpath = self.canvas.beginPath() for path in paths: pdfpath.moveTo(*path[0]) for point in path[1]: if len(point) > 2: pdfpath.curveTo(point[0][0], point[0][1], point[1][0], point[1][1], point[2][0], point[2][1]) else: pdfpath.lineTo(*point) if path[2]: pdfpath.close() closed = True return pdfpath, closed def set_fill_rule(self, fillrule): if fillrule in (sk2_const.FILL_EVENODD, sk2_const.FILL_EVENODD_CLOSED_ONLY): fillrule = FILL_EVEN_ODD else:fillrule = FILL_NON_ZERO self.canvas._fillMode = fillrule def set_rgb_values(self, color, pdfcolor): r, g, b = self.cms.get_rgb_color(color)[1] density = pdfcolor.density if density < 1: r = density * (r - 1) + 1 g = density * (g - 1) + 1 b = density * (b - 1) + 1 pdfcolor.red, pdfcolor.green, pdfcolor.blue = (r, g, b) def get_pdfcolor(self, color): pdfcolor = None alpha = color[2] if self.use_spot and color[0] == uc2const.COLOR_SPOT: c, m, y, k = self.cms.get_cmyk_color(color)[1] spotname = color[3] if spotname == uc2const.COLOR_REG: spotname = 'All' pdfcolor = CMYKColorSep(c, m, y, k, spotName=spotname, alpha=alpha) elif self.colorspace == uc2const.COLOR_CMYK: c, m, y, k = self.cms.get_cmyk_color(color)[1] pdfcolor = CMYKColor(c, m, y, k, alpha=alpha) elif self.colorspace == uc2const.COLOR_RGB: r, g, b = self.cms.get_rgb_color(color)[1] return Color(r, g, b, alpha) elif self.colorspace == uc2const.COLOR_GRAY: gray = self.cms.get_grayscale_color(color) k = 1.0 - gray[1][0] c = m = y = 0.0 pdfcolor = CMYKColor(c, m, y, k, alpha=alpha) else: if color[0] == uc2const.COLOR_RGB: r, g, b = color[1] return Color(r, g, b, alpha) elif color[0] == uc2const.COLOR_GRAY: k = 1.0 - color[1][0] c = m = y = 0.0 pdfcolor = CMYKColor(c, m, y, k, alpha=alpha) else: c, m, y, k = self.cms.get_cmyk_color(color)[1] pdfcolor = CMYKColor(c, m, y, k, alpha=alpha) self.set_rgb_values(color, pdfcolor) return pdfcolor def stroke_pdfpath(self, pdfpath, stroke_style, stroke_trafo=[]): width = stroke_style[1] if not stroke_style[8]: width = stroke_style[1] else: if not stroke_trafo: stroke_trafo = [] + sk2_const.NORMAL_TRAFO points = [[0.0, 0.0], [1.0, 0.0]] points = libgeom.apply_trafo_to_points(points, stroke_trafo) coef = libgeom.distance(*points) width = stroke_style[1] * coef self.canvas.setStrokeColor(self.get_pdfcolor(stroke_style[2])) dash = stroke_style[3] caps = stroke_style[4] joint = stroke_style[5] miter = stroke_style[6] self.canvas.setLineWidth(width) self.canvas.setLineCap(caps - 1) self.canvas.setLineJoin(joint) dashes = [] if dash: dashes = list(dash) w = width if w < 1.0: w = 1.0 for i in range(len(dashes)): dashes[i] = w * dashes[i] self.canvas.setDash(dashes) self.canvas.setMiterLimit(miter) self.canvas.drawPath(pdfpath, 1, 0) self.canvas.setStrokeAlpha(1.0) def fill_pdfpath(self, obj, pdfpath, fill_style, fill_trafo=None): self.set_fill_rule(fill_style[0]) if fill_style[1] == sk2_const.FILL_SOLID: self.canvas.setFillColor(self.get_pdfcolor(fill_style[2])) self.canvas.drawPath(pdfpath, 0, 1) elif fill_style[1] == sk2_const.FILL_GRADIENT: gradient = fill_style[2] stops = gradient[2] transparency = False for stop in stops: if stop[1][2] < 1.0: transparency = True break if transparency: self.fill_tr_gradient(obj, pdfpath, fill_trafo, gradient) else: self.fill_gradient(pdfpath, fill_trafo, gradient) elif fill_style[1] == sk2_const.FILL_PATTERN: pattern = fill_style[2] self.fill_pattern(obj, pdfpath, fill_trafo, pattern) def fill_gradient(self, pdfpath, fill_trafo, gradient): self.canvas.saveState() self.canvas.clipPath(pdfpath, 0, 0) if fill_trafo: self.canvas.transform(*fill_trafo) grad_type = gradient[0] sp, ep = gradient[1] stops = gradient[2] colors = [] positions = [] for offset, color in stops: positions.append(offset) colors.append(self.get_pdfcolor(color)) if grad_type == sk2_const.GRADIENT_RADIAL: radius = libgeom.distance(sp, ep) self.canvas.radialGradient(sp[0], sp[1], radius, colors, positions, True) else: x0, y0 = sp x1, y1 = ep self.canvas.linearGradient(x0, y0, x1, y1, colors, positions, True) self.canvas.restoreState() def fill_tr_gradient(self, obj, pdfpath, fill_trafo, gradient): grad_type = gradient[0] if grad_type == sk2_const.GRADIENT_RADIAL: self.fill_radial_tr_gradient(obj, pdfpath, fill_trafo, gradient) else: self.fill_linear_tr_gradient(obj, pdfpath, fill_trafo, gradient) def get_grcolor_at_point(self, stops, point=0.0): if not point:return self.get_pdfcolor(stops[0][1]) if point == 1.0:return self.get_pdfcolor(stops[-1][1]) stop0 = stops[0] stop1 = None for item in stops: if item[0] < point:stop0 = item if item[0] >= point: stop1 = item break size = stop1[0] - stop0[0] if not size: color = stop1[1] else: coef = (point - stop0[0]) / size color = self.cms.mix_colors(stop0[1], stop1[1], coef) return self.get_pdfcolor(color) def fill_linear_tr_gradient(self, obj, pdfpath, fill_trafo, gradient): if not fill_trafo: fill_trafo = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0] stops = gradient[2] sp, ep = gradient[1] dx, dy = sp l = libgeom.distance(sp, ep) angle = libgeom.get_point_angle(ep, sp) m21 = math.sin(angle) m11 = m22 = math.cos(angle) m12 = -m21 trafo = [m11, m21, m12, m22, dx, dy] inv_trafo = libgeom.multiply_trafo(libgeom.invert_trafo(fill_trafo), libgeom.invert_trafo(trafo)) cv_trafo = libgeom.multiply_trafo(trafo, fill_trafo) paths = libgeom.apply_trafo_to_paths(obj.paths, obj.trafo) paths = libgeom.apply_trafo_to_paths(paths, inv_trafo) bbox = libgeom.sum_bbox(libgeom.get_paths_bbox(paths), [0.0, 0.0, l, 0.0]) bbox = libgeom.normalize_bbox(bbox) y = bbox[1] d = libgeom.distance(*libgeom.apply_trafo_to_points([[0.0, 0.0], [0.0, 1.0]], inv_trafo)) height = bbox[3] - bbox[1] self.canvas.saveState() self.canvas.clipPath(pdfpath, 0, 0) self.canvas.transform(*cv_trafo) self.canvas.setFillColor(self.get_grcolor_at_point(stops, 0.0)) self.canvas.rect(bbox[0], y, 0.0 - bbox[0], height, stroke=0, fill=1) x = 0.0 while x < l: point = x / l self.canvas.setFillColor(self.get_grcolor_at_point(stops, point)) if x + d < l: width = d else: width = l - x self.canvas.rect(x, y, width, height, stroke=0, fill=1) x += d self.canvas.setFillColor(self.get_grcolor_at_point(stops, 1.0)) self.canvas.rect(l, y, bbox[2] - l, height, stroke=0, fill=1) self.canvas.restoreState() def fill_radial_tr_gradient(self, obj, pdfpath, fill_trafo, gradient): if not fill_trafo: fill_trafo = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0] stops = gradient[2] sp, ep = gradient[1] dx, dy = sp l = libgeom.distance(sp, ep) trafo = [1.0, 0.0, 0.0, 1.0, dx, dy] inv_trafo = libgeom.multiply_trafo(libgeom.invert_trafo(fill_trafo), libgeom.invert_trafo(trafo)) cv_trafo = libgeom.multiply_trafo(trafo, fill_trafo) paths = libgeom.apply_trafo_to_paths(obj.paths, obj.trafo) paths = libgeom.apply_trafo_to_paths(paths, inv_trafo) bbox = libgeom.sum_bbox(libgeom.get_paths_bbox(paths), [0.0, 0.0, l, 0.0]) bbox = libgeom.normalize_bbox(bbox) d = libgeom.distance(*libgeom.apply_trafo_to_points([[0.0, 0.0], [0.0, 1.0]], inv_trafo)) circle_paths = libgeom.get_circle_paths(0.0, 0.0, sk2_const.ARC_CHORD) trafo = [2.0, 0.0, 0.0, 2.0, -1.0, -1.0] circle_paths = libgeom.apply_trafo_to_paths(circle_paths, trafo) inner_paths = [] r = 0.0 self.canvas.saveState() self.canvas.clipPath(pdfpath, 0, 0) self.canvas.transform(*cv_trafo) while r < l: point = r / l self.canvas.setFillColor(self.get_grcolor_at_point(stops, point)) if r + d < l: coef = (r + d) else: coef = l trafo = [coef, 0.0, 0.0, coef, 0.0, 0.0] paths = libgeom.apply_trafo_to_paths(circle_paths, trafo) ring = self.make_pdfpath(inner_paths + paths)[0] inner_paths = paths self.canvas.drawPath(ring, stroke=0, fill=1) r += d self.canvas.setFillColor(self.get_grcolor_at_point(stops, 1.0)) r = max(bbox[2] - bbox[0], bbox[3] - bbox[1]) trafo = [2.0 * r, 0.0, 0.0, 2.0 * r, 0.0, 0.0] paths = libgeom.apply_trafo_to_paths(circle_paths, trafo) ring = self.make_pdfpath(inner_paths + paths)[0] self.canvas.drawPath(ring, stroke=0, fill=1) self.canvas.restoreState() def draw_image(self, image, alpha_channel=None): if not image: return if self.colorspace == uc2const.COLOR_CMYK: image = self.cms.convert_image(image, uc2const.IMAGE_CMYK) elif self.colorspace == uc2const.COLOR_RGB: image = self.cms.convert_image(image, uc2const.IMAGE_RGB) elif self.colorspace == uc2const.COLOR_GRAY: image = self.cms.convert_image(image, uc2const.IMAGE_GRAY) img = ImageReader(image) img.getRGBData() if alpha_channel: img._dataA = ImageReader(alpha_channel) self.canvas.drawImage(img, 0, 0, mask='auto') def draw_pixmap_obj(self, obj): if obj.colorspace in uc2const.DUOTONES: fg, bg = libimg.convert_duotone_to_image(self.cms, obj) self.draw_image(*bg) self.draw_image(*fg) else: raw_image = Image.open(StringIO(b64decode(obj.bitmap))) raw_image.load() alpha_chnl = None if obj.alpha_channel: alpha_chnl = Image.open(StringIO(b64decode(obj.alpha_channel))) alpha_chnl.load() self.draw_image(raw_image, alpha_chnl) def draw_pixmap(self, obj): self.canvas.saveState() self.canvas.transform(*obj.trafo) self.canvas.setFillColorCMYK(0, 0, 0, 1, 1) self.canvas.setStrokeColorCMYK(0, 0, 0, 1, 1) self.draw_pixmap_obj(obj) self.canvas.restoreState() def fill_pattern(self, obj, pdfpath, fill_trafo, pattern): if not fill_trafo: fill_trafo = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0] inv_ptrn_trafo = libgeom.invert_trafo(pattern[3]) inv_trafo = libgeom.multiply_trafo(libgeom.invert_trafo(fill_trafo), libgeom.invert_trafo(inv_ptrn_trafo)) paths = libgeom.apply_trafo_to_paths(obj.paths, obj.trafo) paths = libgeom.apply_trafo_to_paths(paths, inv_trafo) bbox = libgeom.get_paths_bbox(paths) cv_trafo = libgeom.multiply_trafo(pattern[3], fill_trafo) bmpstr = b64decode(pattern[1]) image_obj = sk2_model.Pixmap(obj.config) libimg.set_image_data(self.cms, image_obj, bmpstr) if pattern[0] == sk2_const.PATTERN_IMG and \ len(pattern) > 2: image_obj.style[3] = deepcopy(pattern[2]) libimg.update_image(self.cms, image_obj) self.canvas.saveState() self.canvas.clipPath(pdfpath, 0, 0) self.canvas.transform(*cv_trafo) w, h = image_obj.get_size() x = bbox[0] y = bbox[3] while y > bbox[1] - h: while x < bbox[2]: self.canvas.saveState() self.canvas.transform(1.0, 0.0, 0.0, 1.0, x, y) self.draw_pixmap_obj(image_obj) self.canvas.restoreState() x += w y -= h x = bbox[0] self.canvas.restoreState()
def render(grid, options): draw_with_curves = options['draw_with_curves'] filename = options['filename'] use_A4 = options['use_A4'] width = options['width'] height = options['height'] def s_shape_00(p): p.moveTo(a, 0) if draw_with_curves: p.arcTo(-a, -a, a, a, 0, 90) else: p.lineTo(a, a) p.lineTo(0, a) def s_shape_01(p): p.moveTo(0, b) if draw_with_curves: p.arcTo(-a, b, a, s + a, 270, 90) else: p.lineTo(a, b) p.lineTo(a, s) def s_shape_10(p): p.moveTo(s, a) if draw_with_curves: p.arcTo(b, -a, s + a, a, 90, 90) else: p.lineTo(b, a) p.lineTo(b, 0) def s_shape_11(p): p.moveTo(s, b) if draw_with_curves: p.arcTo(b, b, s + a, s + a, 270, -90) else: p.lineTo(b, b) p.lineTo(b, s) buffer = StringIO() if filename: c = Canvas(filename) else: c = Canvas(buffer) c.setTitle('Maze') c.setSubject("") c.setAuthor("Dale O'Brien") if use_A4: page_width = 8.3 * 72 page_height = 11.7 * 72 else: page_width = 8.5 * 72 page_height = 11.0 * 72 c.setPageSize((page_width, page_height)) # 0=butt,1=draw_with_curves,2=square c.setLineCap(1) left_margin = 15 top_margin = 15 # cells must be square, it's the math!, I'm not doing it again. # so scale the width if the height will go over the page org_width = width ratio = (page_height - 2 * top_margin) / (page_width - 2 * left_margin) if (float(height) / width > ratio): width = ceil(height / ratio) s = (page_width - 2 * left_margin) / width # center the maze, looks better for mazes that don't fit the page nicely left_margin -= (org_width - width) * s / 2.0 top_margin -= (s * height - (page_height - 2.0 * top_margin)) / 2.0 g = s * 0.2 stroke = s / 7.0 c.setLineWidth(stroke) k = 0.5 n = -(g / k) + 0.5 * (s - sqrt((g * (4.0 * g - 3.0 * g * k + 2 * k * s)) / k)) r = g / k q = n + r v = (g * (-1 + k)) / k theta = asin((2.0 * g - 2.0 * g * k + k * s) / (2.0 * g - g * k + k * s)) * 180 / pi delta = theta - 90 for j, row in enumerate(grid): # upper/lower rows for i, cell in enumerate(row): x_offset = left_margin + i * s y_offset = top_margin + j * s c.translate(x_offset, y_offset) p = c.beginPath() a = g b = s - g # mark start and end start = False end = False if (i == 0 and j == height - 1): start = True if (i == width - 1 and j == 0): end = True if start or end: c.setStrokeColorRGB(0.9, 0.1, 0.1) c.setFillColorRGB(0.9, 0.1, 0.1) p.circle(s / 2.0, s / 2.0, g / 1.5) c.drawPath(p, fill=True) p = c.beginPath() c.setStrokeColorRGB(0.0, 0.0, 0.0) if cell == 3: '│ │' '│ │' p.moveTo(a, s) p.lineTo(a, 0) p.moveTo(b, s) p.lineTo(b, 0) if cell == 1: '│ │' '└─┘' p.moveTo(b, 0) if draw_with_curves: p.lineTo(b, q) x = s - v - r y = n p.arcTo(x, y, x + 2 * r, y + 2 * r, 180, delta) p.arcTo(g / 2, g / 2, s - g / 2, s - g / 2, theta - 90, 360 - 2 * theta) x = v - r p.arcTo(x, y, x + 2 * r, y + 2 * r, 90 - theta, delta) else: p.lineTo(b, b) p.lineTo(a, b) p.lineTo(g, 0) if cell == 2: '┌─┐' '│ │' p.moveTo(b, s) if draw_with_curves: x = s - v - r y = s - n - 2 * r p.arcTo(x, y, x + 2 * r, y + 2 * r, 180, -delta) p.arcTo(g / 2, g / 2, s - g / 2, s - g / 2, 90 - theta, -360 + 2 * theta) x = v - r p.arcTo(x, y, x + 2 * r, y + 2 * r, 270 + theta, -delta) else: p.lineTo(b, a) p.lineTo(a, a) p.lineTo(a, s) if cell == 4: '┌──' '└──' p.moveTo(s, b) if draw_with_curves: x = s - n - 2 * r y = s - v - r p.arcTo(x, y, x + 2 * r, y + 2 * r, 270, delta) p.arcTo(g / 2, g / 2, s - g / 2, s - g / 2, 90 + delta, 360 - 2 * theta) y = v - r p.arcTo(x, y, x + 2 * r, y + 2 * r, 180 - theta, delta) else: p.lineTo(g, b) p.lineTo(a, a) p.lineTo(s, a) if cell == 8: '──┐' '──┘' p.moveTo(0, b) if draw_with_curves: x = n y = s - v - r p.arcTo(x, y, x + 2 * r, y + 2 * r, 270, -delta) p.arcTo(g / 2, g / 2, s - g / 2, s - g / 2, 90 - delta, -360 + 2 * theta) y = v - r p.arcTo(x, y, x + 2 * r, y + 2 * r, theta, -delta) else: p.lineTo(b, b) p.lineTo(b, a) p.lineTo(0, a) if cell == 5: '│ └' '└──' s_shape_10(p) p.moveTo(s, b) if draw_with_curves: if start: p.arcTo(a, a, b, b, 90, 90) else: p.arcTo(a, 2 * a - b, 2 * b - a, b, 90, 90) else: p.lineTo(a, b) p.lineTo(a, 0) if cell == 6: '┌──' '│ ┌' s_shape_11(p) p.moveTo(s, a) if draw_with_curves: p.arcTo(a, a, 2 * b + a, 2 * b + a, 270, -90) else: p.lineTo(a, a) p.lineTo(a, s) if cell == 7: '│ └' '│ ┌' p.moveTo(a, s) p.lineTo(a, 0) s_shape_10(p) s_shape_11(p) if cell == 9: '┘ │' '──┘' s_shape_00(p) p.moveTo(b, 0) if draw_with_curves: p.arcTo(2 * a - b, 2 * a - b, b, b, 0, 90) else: p.lineTo(b, b) p.lineTo(0, b) if cell == 10: '──┐' '┐ │' s_shape_01(p) p.moveTo(0, a) if draw_with_curves: if end: p.arcTo(a, a, b, b, 270, 90) else: p.arcTo(2 * a - b, a, b, 2 * b + a, 270, 90) else: p.lineTo(b, a) p.lineTo(b, s) if cell == 11: '┘ │' '┐ │' p.moveTo(b, s) p.lineTo(b, 0) s_shape_00(p) s_shape_01(p) if cell == 12: '───' '───' p.moveTo(0, b) p.lineTo(s, b) p.moveTo(0, a) p.lineTo(s, a) if cell == 13: '┘ └' '───' p.moveTo(0, b) p.lineTo(s, b) s_shape_00(p) s_shape_10(p) if cell == 14: '───' '┐ ┌' p.moveTo(0, a) p.lineTo(s, a) s_shape_01(p) s_shape_11(p) if cell == 15: '┘ └' '┐ ┌' s_shape_00(p) s_shape_10(p) s_shape_01(p) s_shape_11(p) if cell == 19: '┤ ├' '┤ ├' p.moveTo(a, s) p.lineTo(a, 0) p.moveTo(b, s) p.lineTo(b, 0) p.moveTo(0, a) p.lineTo(a, a) p.moveTo(0, b) p.lineTo(a, b) p.moveTo(s, a) p.lineTo(b, a) p.moveTo(s, b) p.lineTo(b, b) if cell == 28: '┴─┴' '┬─┬' p.moveTo(0, b) p.lineTo(s, b) p.moveTo(0, a) p.lineTo(s, a) p.moveTo(a, a) p.lineTo(a, 0) p.moveTo(a, b) p.lineTo(a, s) p.moveTo(b, a) p.lineTo(b, 0) p.moveTo(b, b) p.lineTo(b, s) c.drawPath(p) c.translate(-x_offset, -y_offset) c.save() pdf = "" if not filename: pdf = buffer.getvalue() buffer.close() return pdf
def render(grid, options): draw_with_curves = options['draw_with_curves'] filename = options['filename'] use_A4 = options['use_A4'] width = options['width'] height = options['height'] def s_shape_00(p): p.moveTo(a, 0) if draw_with_curves: p.arcTo(-a, -a, a, a, 0, 90) else: p.lineTo(a, a) p.lineTo(0, a) def s_shape_01(p): p.moveTo(0, b) if draw_with_curves: p.arcTo(-a, b, a, s + a, 270, 90) else: p.lineTo(a, b) p.lineTo(a, s) def s_shape_10(p): p.moveTo(s, a) if draw_with_curves: p.arcTo(b, -a, s + a, a, 90, 90) else: p.lineTo(b, a) p.lineTo(b, 0) def s_shape_11(p): p.moveTo(s, b) if draw_with_curves: p.arcTo(b, b, s + a, s + a, 270, -90) else: p.lineTo(b, b) p.lineTo(b, s) buffer = StringIO() if filename: c = Canvas(filename) else: c = Canvas(buffer) c.setTitle('Maze') c.setSubject("") c.setAuthor("Dale O'Brien") if use_A4: page_width = 8.3 * 72 page_height = 11.7 * 72 else: page_width = 8.5 * 72 page_height = 11.0 * 72 c.setPageSize((page_width, page_height)) # 0=butt,1=draw_with_curves,2=square c.setLineCap(1) left_margin = 15 top_margin = 15 # cells must be square, it's the math!, I'm not doing it again. # so scale the width if the height will go over the page org_width = width ratio = (page_height - 2 * top_margin) / (page_width - 2 * left_margin) if (float(height) / width > ratio): width = ceil(height / ratio) s = (page_width - 2 * left_margin) / width # center the maze, looks better for mazes that don't fit the page nicely left_margin -= (org_width - width) * s / 2.0 top_margin -= (s * height - (page_height - 2.0 * top_margin)) / 2.0 g = s * 0.2 stroke = s / 7.0 c.setLineWidth(stroke) k = 0.5 n = -(g / k) + 0.5 * (s - sqrt( (g * (4.0 * g - 3.0 * g * k + 2 * k * s)) / k)) r = g / k q = n + r v = (g * (-1 + k)) / k theta = asin( (2.0 * g - 2.0 * g * k + k * s) / (2.0 * g - g * k + k * s)) * 180 / pi delta = theta - 90 for j, row in enumerate(grid): # upper/lower rows for i, cell in enumerate(row): x_offset = left_margin + i * s y_offset = top_margin + j * s c.translate(x_offset, y_offset) p = c.beginPath() a = g b = s - g # mark start and end start = False end = False if (i == 0 and j == height - 1): start = True if (i == width - 1 and j == 0): end = True if start or end: c.setStrokeColorRGB(0.9, 0.1, 0.1) c.setFillColorRGB(0.9, 0.1, 0.1) p.circle(s / 2.0, s / 2.0, g / 1.5) c.drawPath(p, fill=True) p = c.beginPath() c.setStrokeColorRGB(0.0, 0.0, 0.0) if cell == 3: '│ │' '│ │' p.moveTo(a, s) p.lineTo(a, 0) p.moveTo(b, s) p.lineTo(b, 0) if cell == 1: '│ │' '└─┘' p.moveTo(b, 0) if draw_with_curves: p.lineTo(b, q) x = s - v - r y = n p.arcTo(x, y, x + 2 * r, y + 2 * r, 180, delta) p.arcTo(g / 2, g / 2, s - g / 2, s - g / 2, theta - 90, 360 - 2 * theta) x = v - r p.arcTo(x, y, x + 2 * r, y + 2 * r, 90 - theta, delta) else: p.lineTo(b, b) p.lineTo(a, b) p.lineTo(g, 0) if cell == 2: '┌─┐' '│ │' p.moveTo(b, s) if draw_with_curves: x = s - v - r y = s - n - 2 * r p.arcTo(x, y, x + 2 * r, y + 2 * r, 180, -delta) p.arcTo(g / 2, g / 2, s - g / 2, s - g / 2, 90 - theta, -360 + 2 * theta) x = v - r p.arcTo(x, y, x + 2 * r, y + 2 * r, 270 + theta, -delta) else: p.lineTo(b, a) p.lineTo(a, a) p.lineTo(a, s) if cell == 4: '┌──' '└──' p.moveTo(s, b) if draw_with_curves: x = s - n - 2 * r y = s - v - r p.arcTo(x, y, x + 2 * r, y + 2 * r, 270, delta) p.arcTo(g / 2, g / 2, s - g / 2, s - g / 2, 90 + delta, 360 - 2 * theta) y = v - r p.arcTo(x, y, x + 2 * r, y + 2 * r, 180 - theta, delta) else: p.lineTo(g, b) p.lineTo(a, a) p.lineTo(s, a) if cell == 8: '──┐' '──┘' p.moveTo(0, b) if draw_with_curves: x = n y = s - v - r p.arcTo(x, y, x + 2 * r, y + 2 * r, 270, -delta) p.arcTo(g / 2, g / 2, s - g / 2, s - g / 2, 90 - delta, -360 + 2 * theta) y = v - r p.arcTo(x, y, x + 2 * r, y + 2 * r, theta, -delta) else: p.lineTo(b, b) p.lineTo(b, a) p.lineTo(0, a) if cell == 5: '│ └' '└──' s_shape_10(p) p.moveTo(s, b) if draw_with_curves: if start: p.arcTo(a, a, b, b, 90, 90) else: p.arcTo(a, 2 * a - b, 2 * b - a, b, 90, 90) else: p.lineTo(a, b) p.lineTo(a, 0) if cell == 6: '┌──' '│ ┌' s_shape_11(p) p.moveTo(s, a) if draw_with_curves: p.arcTo(a, a, 2 * b + a, 2 * b + a, 270, -90) else: p.lineTo(a, a) p.lineTo(a, s) if cell == 7: '│ └' '│ ┌' p.moveTo(a, s) p.lineTo(a, 0) s_shape_10(p) s_shape_11(p) if cell == 9: '┘ │' '──┘' s_shape_00(p) p.moveTo(b, 0) if draw_with_curves: p.arcTo(2 * a - b, 2 * a - b, b, b, 0, 90) else: p.lineTo(b, b) p.lineTo(0, b) if cell == 10: '──┐' '┐ │' s_shape_01(p) p.moveTo(0, a) if draw_with_curves: if end: p.arcTo(a, a, b, b, 270, 90) else: p.arcTo(2 * a - b, a, b, 2 * b + a, 270, 90) else: p.lineTo(b, a) p.lineTo(b, s) if cell == 11: '┘ │' '┐ │' p.moveTo(b, s) p.lineTo(b, 0) s_shape_00(p) s_shape_01(p) if cell == 12: '───' '───' p.moveTo(0, b) p.lineTo(s, b) p.moveTo(0, a) p.lineTo(s, a) if cell == 13: '┘ └' '───' p.moveTo(0, b) p.lineTo(s, b) s_shape_00(p) s_shape_10(p) if cell == 14: '───' '┐ ┌' p.moveTo(0, a) p.lineTo(s, a) s_shape_01(p) s_shape_11(p) if cell == 15: '┘ └' '┐ ┌' s_shape_00(p) s_shape_10(p) s_shape_01(p) s_shape_11(p) if cell == 19: '┤ ├' '┤ ├' p.moveTo(a, s) p.lineTo(a, 0) p.moveTo(b, s) p.lineTo(b, 0) p.moveTo(0, a) p.lineTo(a, a) p.moveTo(0, b) p.lineTo(a, b) p.moveTo(s, a) p.lineTo(b, a) p.moveTo(s, b) p.lineTo(b, b) if cell == 28: '┴─┴' '┬─┬' p.moveTo(0, b) p.lineTo(s, b) p.moveTo(0, a) p.lineTo(s, a) p.moveTo(a, a) p.lineTo(a, 0) p.moveTo(a, b) p.lineTo(a, s) p.moveTo(b, a) p.lineTo(b, 0) p.moveTo(b, b) p.lineTo(b, s) c.drawPath(p) c.translate(-x_offset, -y_offset) c.save() pdf = "" if not filename: pdf = buffer.getvalue() buffer.close() return pdf
class Invoice: client = Address() provider = Address() items = [] title = "Faktura" vs = "00000000" creator = "" sign_image = None payment_days = 14 paytype = "Převodem" pdffile = None def __init__(self): self.TOP = 260 self.LEFT = 20 pdfmetrics.registerFont(TTFont('DejaVu', '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf')) self.pdffile = NamedTemporaryFile(delete=False) self.pdf = Canvas(self.pdffile.name, pagesize=letter) self.pdf.setFont("DejaVu", 15) self.pdf.setStrokeColorRGB(0, 0, 0) def __del__(self): if os.path.isfile(self.pdffile.name): os.unlink(self.pdffile.name) ############################################################# # Setters ############################################################# def setClient(self, address): self.client = address def setProvider(self, address): self.provider = address def setTitle(self, value): self.title = value def setVS(self, value): self.vs = value def setCreator(self, value): self.creator = value def setPaytype(self, value): self.paytype = value def setPaymentDays(self, value): self.payment_days = int(value) def addItem(self, item): self.items.append(item) ############################################################# # Getters ############################################################# def getContent(self): # Texty self.drawMain() self.drawProvider(self.TOP-10, self.LEFT+3) self.drawClient(self.TOP-30, self.LEFT+91) self.drawPayment(self.TOP-47, self.LEFT+3) self.drawItems(self.TOP-80, self.LEFT) self.drawDates(self.TOP-10, self.LEFT+91) # self.pdf.setFillColorRGB(0, 0, 0) self.pdf.showPage() self.pdf.save() f = open(self.pdffile.name) data = f.read() f.close() os.unlink(self.pdffile.name) return data ############################################################# # Draw methods ############################################################# def drawMain(self): # Horní lajna self.pdf.drawString(self.LEFT*mm, self.TOP*mm, self.title) self.pdf.drawString((self.LEFT+100)*mm, self.TOP*mm, "Variabilní symbol: %s" % self.vs) # Rámečky self.pdf.rect((self.LEFT)*mm, (self.TOP-68)*mm, (self.LEFT+156)*mm, 65*mm, stroke=True, fill=False) path = self.pdf.beginPath() path.moveTo((self.LEFT+88)*mm, (self.TOP-3)*mm) path.lineTo((self.LEFT+88)*mm, (self.TOP-68)*mm) self.pdf.drawPath(path) path = self.pdf.beginPath() path.moveTo((self.LEFT)*mm, (self.TOP-39)*mm) path.lineTo((self.LEFT+88)*mm, (self.TOP-39)*mm) self.pdf.drawPath(path) path = self.pdf.beginPath() path.moveTo((self.LEFT+88)*mm, (self.TOP-23)*mm) path.lineTo((self.LEFT+176)*mm, (self.TOP-23)*mm) self.pdf.drawPath(path) def _drawAddress(self, TOP, LEFT, header_string, address): self.pdf.setFont("DejaVu", 12) self.pdf.drawString((LEFT)*mm, (TOP)*mm, header_string) self.pdf.setFont("DejaVu", 8) text = self.pdf.beginText((LEFT+2)*mm, (TOP-6)*mm) text.textLines("\n".join(address.getAddressLines())) self.pdf.drawText(text) text = self.pdf.beginText((LEFT+40)*mm, (TOP-6)*mm) text.textLines("\n".join(address.getContactLines())) self.pdf.drawText(text) def drawClient(self, TOP, LEFT): self._drawAddress(TOP, LEFT, "Odběratel", self.client) # self.pdf.setFont("DejaVu", 12) # self.pdf.drawString((LEFT)*mm, (TOP)*mm, "Odběratel") # self.pdf.setFont("DejaVu", 8) # text = self.pdf.beginText((LEFT+2)*mm, (TOP-6)*mm) # text.textLines("\n".join(self.client.getAddressLines())) # self.pdf.drawText(text) # text = self.pdf.beginText((LEFT+2)*mm, (TOP-28)*mm) # text.textLines("\n".join(self.client.getContactLines())) # self.pdf.drawText(text) def drawProvider(self, TOP, LEFT): self._drawAddress(TOP, LEFT, "Dodavatel", self.provider) if self.provider.note: self.pdf.drawString((LEFT+2)*mm, (TOP-26)*mm, self.provider.note) def drawPayment(self, TOP, LEFT): self.pdf.setFont("DejaVu", 11) self.pdf.drawString((LEFT)*mm, (TOP)*mm, "Údaje pro platbu") # self.pdf.setFillColorRGB(255, 0, 0) text = self.pdf.beginText((LEFT+2)*mm, (TOP-6)*mm) text.textLines( """%s Číslo účtu: %s Variabilní symbol: %s""" % (self.provider.bank_name, self.provider.bank_account, self.vs), ) self.pdf.drawText(text) def drawItems(self, TOP, LEFT): # Items path = self.pdf.beginPath() path.moveTo((LEFT)*mm, (TOP-4)*mm) path.lineTo((LEFT+176)*mm, (TOP-4)*mm) self.pdf.drawPath(path) self.pdf.setFont("DejaVu", 9) self.pdf.drawString((LEFT+1)*mm, (TOP-2)*mm, "Fakturuji vám:") i = 9 self.pdf.drawString((LEFT+100)*mm, (TOP-i)*mm, "Množství") self.pdf.drawString((LEFT+122)*mm, (TOP-i)*mm, "Cena za jedn.") self.pdf.drawString((LEFT+150)*mm, (TOP-i)*mm, "Cena celkem") i += 5 # List total = 0.0 for x in self.items: self.pdf.drawString((LEFT+1)*mm, (TOP-i)*mm, x.name) i += 5 self.pdf.drawString((LEFT+100)*mm, (TOP-i)*mm, "%d ks" % x.count) self.pdf.drawString((LEFT+122)*mm, (TOP-i)*mm, "%.2f,- kč" % x.price) self.pdf.drawString((LEFT+150)*mm, (TOP-i)*mm, "%.2f,- kč" % (x.total())) i += 5 total += x.total() path = self.pdf.beginPath() path.moveTo((LEFT)*mm, (TOP-i)*mm) path.lineTo((LEFT+176)*mm, (TOP-i)*mm) self.pdf.drawPath(path) self.pdf.setFont("DejaVu", 12) self.pdf.drawString((LEFT+130)*mm, (TOP-i-10)*mm, "Celkem: %d ,- kč" % total) self.pdf.rect((LEFT)*mm, (TOP-i-17)*mm, (LEFT+156)*mm, (i+19)*mm, stroke=True, fill=False) # 140,142 if self.sign_image: self.pdf.drawImage(self.sign_image, (LEFT+98)*mm, (TOP-i-72)*mm) path = self.pdf.beginPath() path.moveTo((LEFT+110)*mm, (TOP-i-70)*mm) path.lineTo((LEFT+164)*mm, (TOP-i-70)*mm) self.pdf.drawPath(path) self.pdf.drawString((LEFT+112)*mm, (TOP-i-75)*mm, "Vystavil: %s" % self.creator) def drawDates(self, TOP, LEFT): today = datetime.datetime.today() payback = today+datetime.timedelta(self.payment_days) self.pdf.setFont("DejaVu", 10) self.pdf.drawString((LEFT)*mm, (TOP+1)*mm, "Datum vystavení: %s" % today.strftime("%d.%m.%Y")) self.pdf.drawString((LEFT)*mm, (TOP-4)*mm, "Datum splatnosti: %s" % payback.strftime("%d.%m.%Y")) self.pdf.drawString((LEFT)*mm, (TOP-9)*mm, "Forma úhrady: " + self.paytype)
class SimpleInvoice(BaseInvoice): def gen(self, filename): self.TOP = 260 self.LEFT = 20 self.filename = filename pdfmetrics.registerFont(TTFont('DejaVu', FONT_PATH)) pdfmetrics.registerFont(TTFont('DejaVu-Bold', FONT_BOLD_PATH)) self.pdf = Canvas(self.filename, pagesize = letter) self.addMetaInformation(self.pdf) self.pdf.setFont('DejaVu', 15) self.pdf.setStrokeColorRGB(0, 0, 0) # Texty self.drawMain() self.drawTitle() self.drawProvider(self.TOP - 10,self.LEFT + 3) self.drawClient(self.TOP - 35,self.LEFT + 91) self.drawPayment(self.TOP - 47,self.LEFT + 3) self.drawItems(self.TOP - 80,self.LEFT) self.drawDates(self.TOP - 10,self.LEFT + 91) #self.pdf.setFillColorRGB(0, 0, 0) self.pdf.showPage() self.pdf.save() ############################################################# ## Draw methods ############################################################# def addMetaInformation(self, pdf): pdf.setCreator(self.invoice.provider.summary) pdf.setTitle(self.invoice.title) pdf.setAuthor(self.invoice.creator.name) def drawTitle(self): # Up line self.pdf.drawString(self.LEFT*mm, self.TOP*mm, self.invoice.title) self.pdf.drawString((self.LEFT + 90) * mm, self.TOP*mm, _(u'Variable symbol: %s') % self.invoice.variable_symbol) def drawMain(self): # Borders self.pdf.rect(self.LEFT * mm, (self.TOP - 68) * mm, (self.LEFT + 156) * mm, 65 * mm, stroke=True, fill=False) path = self.pdf.beginPath() path.moveTo((self.LEFT + 88) * mm, (self.TOP - 3) * mm) path.lineTo((self.LEFT + 88) * mm, (self.TOP - 68) * mm) self.pdf.drawPath(path, True, True) path = self.pdf.beginPath() path.moveTo(self.LEFT * mm, (self.TOP - 39) * mm) path.lineTo((self.LEFT + 88) * mm, (self.TOP - 39) * mm) self.pdf.drawPath(path, True, True) path = self.pdf.beginPath() path.moveTo((self.LEFT + 88) * mm, (self.TOP - 27) * mm) path.lineTo((self.LEFT + 176) * mm, (self.TOP - 27) * mm) self.pdf.drawPath(path, True, True) def drawClient(self,TOP,LEFT): self.pdf.setFont('DejaVu', 12) self.pdf.drawString(LEFT * mm, TOP * mm, _(u'Customer')) self.pdf.setFont('DejaVu', 8) text = self.pdf.beginText((LEFT + 2) * mm, (TOP - 4) * mm) text.textLines('\n'.join(self.invoice.client.get_address_lines())) self.pdf.drawText(text) text = self.pdf.beginText((LEFT + 2) * mm, (TOP - 23) * mm) text.textLines('\n'.join(self.invoice.client.get_contact_lines())) self.pdf.drawText(text) if self.invoice.client.note: self.pdf.setFont('DejaVu', 6) text = self.pdf.beginText((LEFT + 2) * mm, (TOP - 28) * mm) text.textLines(self.invoice.client.note) self.pdf.drawText(text) def drawProvider(self,TOP,LEFT): self.pdf.setFont('DejaVu', 12) self.pdf.drawString(LEFT * mm, TOP * mm, _(u'Provider')) self.pdf.setFont('DejaVu', 8) text = self.pdf.beginText((LEFT + 2) * mm, (TOP - 6) * mm) text.textLines('\n'.join(self.invoice.provider.get_address_lines())) self.pdf.drawText(text) text = self.pdf.beginText((LEFT + 40) * mm, (TOP - 6) * mm) text.textLines('\n'.join(self.invoice.provider.get_contact_lines())) self.pdf.drawText(text) if self.invoice.provider.note: self.pdf.setFont('DejaVu', 6) text = self.pdf.beginText((LEFT + 2) * mm, (TOP - 23) * mm) text.textLines(self.invoice.provider.note) self.pdf.drawText(text) def drawPayment(self,TOP,LEFT): self.pdf.setFont('DejaVu-Bold', 9) self.pdf.drawString(LEFT * mm, TOP * mm, _(u'Payment information')) text = self.pdf.beginText((LEFT + 2) * mm, (TOP - 6) * mm) lines = [ self.invoice.provider.bank_name, '%s: %s' % (_(u'Bank account'), self.invoice.provider.bank_account), '%s: %s' % (_(u'Variable symbol'), self.invoice.variable_symbol) ] if self.invoice.specific_symbol: lines.append( '%s: %s' % (_(u'Specific symbol'), self.invoice.specific_symbol)) text.textLines('\n'.join(lines)) self.pdf.drawText(text) def drawItems(self,TOP,LEFT): # Items path = self.pdf.beginPath() path.moveTo(LEFT * mm, (TOP - 4) * mm) path.lineTo((LEFT + 176) * mm, (TOP - 4) * mm) self.pdf.drawPath(path, True, True) self.pdf.setFont('DejaVu-Bold', 7) self.pdf.drawString((LEFT + 1) * mm, (TOP - 2) * mm, _(u'List of items')) self.pdf.drawString((LEFT + 1) * mm, (TOP - 9) * mm, _(u'Description')) items_are_with_tax = self.invoice.use_tax if items_are_with_tax: i=9 self.pdf.drawString((LEFT + 68) * mm, (TOP - i) * mm, _(u'Units')) self.pdf.drawString((LEFT + 88) * mm, (TOP - i) * mm, _(u'Price per one')) self.pdf.drawString((LEFT + 115) * mm, (TOP - i) * mm, _(u'Total price')) self.pdf.drawString((LEFT + 137) * mm, (TOP - i) * mm, _(u'Tax')) self.pdf.drawString((LEFT + 146) * mm, (TOP - i) * mm, _(u'Total price with tax')) i+=5 else: i=9 self.pdf.drawString((LEFT + 104) * mm, (TOP - i) * mm, _(u'Units')) self.pdf.drawString((LEFT + 123) * mm, (TOP - i) * mm, _(u'Price per one')) self.pdf.drawString((LEFT + 150) * mm, (TOP - i) * mm, _(u'Total price')) i+=5 self.pdf.setFont('DejaVu', 7) # List for item in self.invoice.items: self.pdf.drawString((LEFT + 1) * mm, (TOP - i) * mm, item.description) if item.tax or items_are_with_tax: items_are_with_tax = True if len(item.description) > 52: i+=5 if float(int(item.count)) == item.count: self.pdf.drawString((LEFT + 68) * mm, (TOP - i) * mm, '%d %s' % (item.count, item.unit)) else: self.pdf.drawString((LEFT + 68) * mm, (TOP - i) * mm, '%.1f %s' % (item.count, item.unit)) self.pdf.drawString((LEFT + 88) * mm, (TOP - i) * mm, '%.2f,- %s' % (item.price, self.invoice.currency)) self.pdf.drawString((LEFT + 115) * mm, (TOP - i) * mm, '%.2f,- %s' % (item.total, self.invoice.currency)) self.pdf.drawString((LEFT + 137) * mm, (TOP - i) * mm, '%.0f %%' % item.tax) self.pdf.drawString((LEFT + 146) * mm, (TOP - i) * mm, '%.2f,- %s' % (item.total_tax, self.invoice.currency)) i+=5 else: if len(item.description) > 75: i+=5 if float(int(item.count)) == item.count: self.pdf.drawString((LEFT + 104) * mm, (TOP - i) * mm, '%d %s' % (item.count, item.unit)) else: self.pdf.drawString((LEFT + 104) * mm, (TOP - i) * mm, '%.1f %s' % (item.count, item.unit)) self.pdf.drawString((LEFT + 123) * mm, (TOP - i) * mm, '%.2f,- %s' % (item.price, self.invoice.currency)) self.pdf.drawString((LEFT + 150) * mm, (TOP - i) * mm, '%.2f,- %s' % (item.total, self.invoice.currency)) i+=5 if self.invoice.rounding_result: path = self.pdf.beginPath() path.moveTo(LEFT * mm, (TOP - i) * mm) path.lineTo((LEFT + 176) * mm, (TOP - i) * mm) i += 5 self.pdf.drawPath(path, True, True) self.pdf.drawString((LEFT + 1) * mm, (TOP - i) * mm, _(u'Rounding')) self.pdf.drawString((LEFT + 68) * mm, (TOP - i) * mm, '%.2f,- %s' % (self.invoice.difference_in_rounding, self.invoice.currency)) i += 3 path = self.pdf.beginPath() path.moveTo(LEFT * mm, (TOP - i) * mm) path.lineTo((LEFT + 176) * mm, (TOP - i) * mm) self.pdf.drawPath(path, True, True) if not items_are_with_tax: self.pdf.setFont('DejaVu-Bold', 11) self.pdf.drawString((LEFT + 100) * mm, (TOP - i - 7) * mm, _(u'Total')+': %.2f %s' % (self.invoice.price, self.invoice.currency)) else: self.pdf.setFont('DejaVu-Bold', 6) self.pdf.drawString((LEFT + 1) * mm, (TOP - i - 2) * mm, _(u'Breakdown VAT')) vat_list, tax_list, total_list, total_tax_list = [_(u'VAT rate')], [_(u'Tax')], [_(u'Without VAT')], [_(u'With VAT')] for vat, items in self.invoice.generate_breakdown_vat().iteritems(): vat_list.append('%.2f%%' % vat) tax_list.append('%.2f %s' % (items['tax'], self.invoice.currency)) total_list.append('%.2f %s' % (items['total'], self.invoice.currency)) total_tax_list.append('%.2f %s' % (items['total_tax'], self.invoice.currency)) self.pdf.setFont('DejaVu', 6) text = self.pdf.beginText((LEFT + 1) * mm, (TOP - i - 5) * mm) text.textLines('\n'.join(vat_list)) self.pdf.drawText(text) text = self.pdf.beginText((LEFT + 11) * mm, (TOP - i - 5) * mm) text.textLines('\n'.join(tax_list)) self.pdf.drawText(text) text = self.pdf.beginText((LEFT + 27) * mm, (TOP - i - 5) * mm) text.textLines('\n'.join(total_list)) self.pdf.drawText(text) text = self.pdf.beginText((LEFT + 45) * mm, (TOP - i - 5) * mm) text.textLines('\n'.join(total_tax_list)) self.pdf.drawText(text) self.pdf.setFont('DejaVu-Bold', 11) self.pdf.drawString((LEFT + 100) * mm, (TOP - i - 14) * mm, _(u'Total with tax')+': %.2f %s' % (self.invoice.price_tax, self.invoice.currency)) if items_are_with_tax: self.pdf.rect(LEFT * mm, (TOP - i - 17) * mm, (LEFT + 156) * mm, (i + 19) * mm, stroke=True, fill=False) #140,142 else: self.pdf.rect(LEFT * mm, (TOP - i - 11) * mm, (LEFT + 156) * mm, (i + 13) * mm, stroke=True, fill=False) #140,142 if self.invoice.creator.stamp_filename: im = Image.open(self.invoice.creator.stamp_filename) height = float(im.size[1]) / (float(im.size[0])/200.0) self.pdf.drawImage(self.invoice.creator.stamp_filename, (LEFT + 98) * mm, (TOP - i - 72) * mm, 200, height) path = self.pdf.beginPath() path.moveTo((LEFT + 110) * mm, (TOP - i - 70) * mm) path.lineTo((LEFT + 164) * mm, (TOP - i - 70) * mm) self.pdf.drawPath(path, True, True) self.pdf.drawString((LEFT + 112) * mm, (TOP - i - 75) * mm, '%s: %s' % (_(u'Creator'), self.invoice.creator.name)) def drawDates(self,TOP,LEFT): self.pdf.setFont('DejaVu', 10) top = TOP + 1 items = [ (LEFT * mm, '%s: %s' % (_(u'Date'), self.invoice.date)), (LEFT * mm, '%s: %s' % (_(u'Payback'), self.invoice.payback)) ] if self.invoice.taxable_date: items.append((LEFT * mm, '%s: %s' % (_(u'Taxable date'), self.invoice.taxable_date))) items.append((LEFT * mm, '%s: %s' % (_(u'Paytype'), self.invoice.paytype))) for item in items: self.pdf.drawString(item[0], top * mm, item[1]) top += -5
class PDFGenerator(object): canvas = None colorspace = None use_spot = True num_pages = 0 page_count = 0 prgs_msg = _('Saving in process...') def __init__(self, fileptr, cms, version=PDF_VERSION_DEFAULT): self.cms = cms self.canvas = Canvas(fileptr, pdfVersion=version[0]) self.info = UC_PDFInfo(self.canvas._doc) self.info.pdfxversion = version[1] self.info.subject = '---' self.canvas.setPageCompression(1) # ---PDF doc data def set_creator(self, name): self.info.creator = name def set_producer(self, name): self.info.producer = name def set_title(self, title): self.info.title = title def set_author(self, author): self.info.author = author def set_subject(self, subj): self.info.subject = subj def set_keywords(self, keywords): self.info.keywords = keywords # ---Rendering options def set_compression(self, val=True): self.canvas.setPageCompression(int(val)) def set_colorspace(self, cs=None): self.colorspace = cs def set_spot_usage(self, val=True): self.use_spot = val # ---Page processing def set_num_pages(self, num=1): self.num_pages = num def set_progress_message(self, msg): self.prgs_msg = msg def start_page(self, w, h, left_margin=0.0, top_margin=0.0): self.canvas.translate(w / 2.0 - left_margin, h / 2.0 - top_margin) self.canvas.setPageSize((w, h)) position = 0.0 if self.num_pages: position = float(self.page_count) / float(self.num_pages) events.emit(events.FILTER_INFO, self.prgs_msg, position) def end_page(self): self.canvas.showPage() self.page_count += 1 position = 1.0 if self.num_pages: position = float(self.page_count) / float(self.num_pages) events.emit(events.FILTER_INFO, self.prgs_msg, position) def save(self): self.canvas.save() # --- Rendering def render(self, objs, toplevel=False): obj_count = 0 for obj in objs: if obj.is_pixmap(): self.draw_pixmap(obj) elif obj.is_primitive(): curve_obj = obj.to_curve() if curve_obj.is_primitive(): self.draw_curve(curve_obj) else: self.render(curve_obj.childs) elif obj.is_container(): self.draw_container(obj) else: self.render(obj.childs) # ---Progress obj_count += 1 shift = 0.0 page_size = 1.0 if self.num_pages: shift = float(self.page_count) / float(self.num_pages) page_size = 1.0 / float(self.num_pages) position = shift + obj_count / len(objs) * page_size events.emit(events.FILTER_INFO, self.prgs_msg, position) def draw_curve(self, curve_obj): paths = libgeom.apply_trafo_to_paths(curve_obj.paths, curve_obj.trafo) pdfpath, closed = self.make_pdfpath(paths) fill_style = curve_obj.style[0] stroke_style = curve_obj.style[1] if stroke_style and stroke_style[7]: self.stroke_pdfpath(pdfpath, stroke_style, curve_obj.stroke_trafo) if fill_style and fill_style[0] & sk2const.FILL_CLOSED_ONLY and closed: self.fill_pdfpath(curve_obj, pdfpath, fill_style, curve_obj.fill_trafo) elif fill_style and not fill_style[0] & sk2const.FILL_CLOSED_ONLY: self.fill_pdfpath(curve_obj, pdfpath, fill_style, curve_obj.fill_trafo) if stroke_style and not stroke_style[7]: self.stroke_pdfpath(pdfpath, stroke_style, curve_obj.stroke_trafo) def draw_container(self, obj): container = obj.childs[0].to_curve() paths = libgeom.apply_trafo_to_paths(container.paths, container.trafo) pdfpath, closed = self.make_pdfpath(paths) fill_style = container.style[0] stroke_style = container.style[1] if stroke_style and stroke_style[7]: self.stroke_pdfpath(pdfpath, stroke_style, container.stroke_trafo) self.canvas.saveState() self.canvas.clipPath(pdfpath, 0, 0) if fill_style and fill_style[0] & sk2const.FILL_CLOSED_ONLY and closed: self.fill_pdfpath(container, pdfpath, fill_style, container.fill_trafo) elif fill_style and not fill_style[0] & sk2const.FILL_CLOSED_ONLY: self.fill_pdfpath(container, pdfpath, fill_style, container.fill_trafo) self.render(obj.childs[1:]) self.canvas.restoreState() if stroke_style and not stroke_style[7]: self.stroke_pdfpath(pdfpath, stroke_style, container.stroke_trafo) def make_pdfpath(self, paths): closed = False pdfpath = self.canvas.beginPath() for path in paths: pdfpath.moveTo(*path[0]) for point in path[1]: if len(point) > 2: pdfpath.curveTo(point[0][0], point[0][1], point[1][0], point[1][1], point[2][0], point[2][1]) else: pdfpath.lineTo(*point) if path[2]: pdfpath.close() closed = True return pdfpath, closed def set_fill_rule(self, fillrule): if fillrule in (sk2const.FILL_EVENODD, sk2const.FILL_EVENODD_CLOSED_ONLY): fillrule = FILL_EVEN_ODD else: fillrule = FILL_NON_ZERO self.canvas._fillMode = fillrule def set_rgb_values(self, color, pdfcolor): r, g, b = self.cms.get_rgb_color(color)[1] density = pdfcolor.density if density < 1: r = density * (r - 1) + 1 g = density * (g - 1) + 1 b = density * (b - 1) + 1 pdfcolor.red, pdfcolor.green, pdfcolor.blue = (r, g, b) def get_pdfcolor(self, color): pdfcolor = None alpha = color[2] if self.use_spot and color[0] == uc2const.COLOR_SPOT: c, m, y, k = self.cms.get_cmyk_color(color)[1] spotname = color[3] if spotname == uc2const.COLOR_REG: spotname = 'All' pdfcolor = CMYKColorSep(c, m, y, k, spotName=spotname, alpha=alpha) elif self.colorspace == uc2const.COLOR_CMYK: c, m, y, k = self.cms.get_cmyk_color(color)[1] pdfcolor = CMYKColor(c, m, y, k, alpha=alpha) elif self.colorspace == uc2const.COLOR_RGB: r, g, b = self.cms.get_rgb_color(color)[1] return Color(r, g, b, alpha) elif self.colorspace == uc2const.COLOR_GRAY: gray = self.cms.get_grayscale_color(color) k = 1.0 - gray[1][0] c = m = y = 0.0 pdfcolor = CMYKColor(c, m, y, k, alpha=alpha) else: if color[0] == uc2const.COLOR_RGB: r, g, b = color[1] return Color(r, g, b, alpha) elif color[0] == uc2const.COLOR_GRAY: k = 1.0 - color[1][0] c = m = y = 0.0 pdfcolor = CMYKColor(c, m, y, k, alpha=alpha) else: c, m, y, k = self.cms.get_cmyk_color(color)[1] pdfcolor = CMYKColor(c, m, y, k, alpha=alpha) self.set_rgb_values(color, pdfcolor) return pdfcolor def stroke_pdfpath(self, pdfpath, stroke_style, stroke_trafo=[]): width = stroke_style[1] if not stroke_style[8]: width = stroke_style[1] else: if not stroke_trafo: stroke_trafo = [] + sk2const.NORMAL_TRAFO points = [[0.0, 0.0], [1.0, 0.0]] points = libgeom.apply_trafo_to_points(points, stroke_trafo) coef = libgeom.distance(*points) width = stroke_style[1] * coef self.canvas.setStrokeColor(self.get_pdfcolor(stroke_style[2])) dash = stroke_style[3] caps = stroke_style[4] joint = stroke_style[5] miter = stroke_style[6] self.canvas.setLineWidth(width) self.canvas.setLineCap(caps - 1) self.canvas.setLineJoin(joint) dashes = [] if dash: dashes = list(dash) w = width if w < 1.0: w = 1.0 for i in range(len(dashes)): dashes[i] = w * dashes[i] self.canvas.setDash(dashes) self.canvas.setMiterLimit(miter) self.canvas.drawPath(pdfpath, 1, 0) self.canvas.setStrokeAlpha(1.0) def fill_pdfpath(self, obj, pdfpath, fill_style, fill_trafo=None): self.set_fill_rule(fill_style[0]) if fill_style[1] == sk2const.FILL_SOLID: self.canvas.setFillColor(self.get_pdfcolor(fill_style[2])) self.canvas.drawPath(pdfpath, 0, 1) elif fill_style[1] == sk2const.FILL_GRADIENT: gradient = fill_style[2] stops = gradient[2] transparency = False for stop in stops: if stop[1][2] < 1.0: transparency = True break if transparency: self.fill_tr_gradient(obj, pdfpath, fill_trafo, gradient) else: self.fill_gradient(pdfpath, fill_trafo, gradient) elif fill_style[1] == sk2const.FILL_PATTERN: pattern = fill_style[2] self.fill_pattern(obj, pdfpath, fill_trafo, pattern) def fill_gradient(self, pdfpath, fill_trafo, gradient): self.canvas.saveState() self.canvas.clipPath(pdfpath, 0, 0) if fill_trafo: self.canvas.transform(*fill_trafo) grad_type = gradient[0] sp, ep = gradient[1] stops = gradient[2] colors = [] positions = [] for offset, color in stops: positions.append(offset) colors.append(self.get_pdfcolor(color)) if grad_type == sk2const.GRADIENT_RADIAL: radius = libgeom.distance(sp, ep) self.canvas.radialGradient(sp[0], sp[1], radius, colors, positions, True) else: x0, y0 = sp x1, y1 = ep self.canvas.linearGradient(x0, y0, x1, y1, colors, positions, True) self.canvas.restoreState() def fill_tr_gradient(self, obj, pdfpath, fill_trafo, gradient): grad_type = gradient[0] if grad_type == sk2const.GRADIENT_RADIAL: self.fill_radial_tr_gradient(obj, pdfpath, fill_trafo, gradient) else: self.fill_linear_tr_gradient(obj, pdfpath, fill_trafo, gradient) def get_grcolor_at_point(self, stops, point=0.0): if not point: return self.get_pdfcolor(stops[0][1]) if point == 1.0: return self.get_pdfcolor(stops[-1][1]) stop0 = stops[0] stop1 = None for item in stops: if item[0] < point: stop0 = item if item[0] >= point: stop1 = item break size = stop1[0] - stop0[0] if not size: color = stop1[1] else: coef = (point - stop0[0]) / size color = self.cms.mix_colors(stop0[1], stop1[1], coef) return self.get_pdfcolor(color) def fill_linear_tr_gradient(self, obj, pdfpath, fill_trafo, gradient): if not fill_trafo: fill_trafo = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0] stops = gradient[2] sp, ep = gradient[1] dx, dy = sp l = libgeom.distance(sp, ep) angle = libgeom.get_point_angle(ep, sp) m21 = math.sin(angle) m11 = m22 = math.cos(angle) m12 = -m21 trafo = [m11, m21, m12, m22, dx, dy] inv_trafo = libgeom.multiply_trafo(libgeom.invert_trafo(fill_trafo), libgeom.invert_trafo(trafo)) cv_trafo = libgeom.multiply_trafo(trafo, fill_trafo) paths = libgeom.apply_trafo_to_paths(obj.paths, obj.trafo) paths = libgeom.apply_trafo_to_paths(paths, inv_trafo) bbox = libgeom.sum_bbox(libgeom.get_paths_bbox(paths), [0.0, 0.0, l, 0.0]) bbox = libgeom.normalize_bbox(bbox) y = bbox[1] d = libgeom.distance(*libgeom.apply_trafo_to_points( [[0.0, 0.0], [0.0, 1.0]], inv_trafo)) height = bbox[3] - bbox[1] self.canvas.saveState() self.canvas.clipPath(pdfpath, 0, 0) self.canvas.transform(*cv_trafo) self.canvas.setFillColor(self.get_grcolor_at_point(stops, 0.0)) self.canvas.rect(bbox[0], y, 0.0 - bbox[0], height, stroke=0, fill=1) x = 0.0 while x < l: point = x / l self.canvas.setFillColor(self.get_grcolor_at_point(stops, point)) if x + d < l: width = d else: width = l - x self.canvas.rect(x, y, width, height, stroke=0, fill=1) x += d self.canvas.setFillColor(self.get_grcolor_at_point(stops, 1.0)) self.canvas.rect(l, y, bbox[2] - l, height, stroke=0, fill=1) self.canvas.restoreState() def fill_radial_tr_gradient(self, obj, pdfpath, fill_trafo, gradient): if not fill_trafo: fill_trafo = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0] stops = gradient[2] sp, ep = gradient[1] dx, dy = sp l = libgeom.distance(sp, ep) trafo = [1.0, 0.0, 0.0, 1.0, dx, dy] inv_trafo = libgeom.multiply_trafo(libgeom.invert_trafo(fill_trafo), libgeom.invert_trafo(trafo)) cv_trafo = libgeom.multiply_trafo(trafo, fill_trafo) paths = libgeom.apply_trafo_to_paths(obj.paths, obj.trafo) paths = libgeom.apply_trafo_to_paths(paths, inv_trafo) bbox = libgeom.sum_bbox(libgeom.get_paths_bbox(paths), [0.0, 0.0, l, 0.0]) bbox = libgeom.normalize_bbox(bbox) d = libgeom.distance(*libgeom.apply_trafo_to_points( [[0.0, 0.0], [0.0, 1.0]], inv_trafo)) circle_paths = libgeom.get_circle_paths(0.0, 0.0, sk2const.ARC_CHORD) trafo = [2.0, 0.0, 0.0, 2.0, -1.0, -1.0] circle_paths = libgeom.apply_trafo_to_paths(circle_paths, trafo) inner_paths = [] r = 0.0 self.canvas.saveState() self.canvas.clipPath(pdfpath, 0, 0) self.canvas.transform(*cv_trafo) while r < l: point = r / l self.canvas.setFillColor(self.get_grcolor_at_point(stops, point)) if r + d < l: coef = (r + d) else: coef = l trafo = [coef, 0.0, 0.0, coef, 0.0, 0.0] paths = libgeom.apply_trafo_to_paths(circle_paths, trafo) ring = self.make_pdfpath(inner_paths + paths)[0] inner_paths = paths self.canvas.drawPath(ring, stroke=0, fill=1) r += d self.canvas.setFillColor(self.get_grcolor_at_point(stops, 1.0)) r = max(bbox[2] - bbox[0], bbox[3] - bbox[1]) trafo = [2.0 * r, 0.0, 0.0, 2.0 * r, 0.0, 0.0] paths = libgeom.apply_trafo_to_paths(circle_paths, trafo) ring = self.make_pdfpath(inner_paths + paths)[0] self.canvas.drawPath(ring, stroke=0, fill=1) self.canvas.restoreState() def draw_image(self, image, alpha_channel=None): if not image: return if self.colorspace == uc2const.COLOR_CMYK: image = self.cms.convert_image(image, uc2const.IMAGE_CMYK) elif self.colorspace == uc2const.COLOR_RGB: image = self.cms.convert_image(image, uc2const.IMAGE_RGB) elif self.colorspace == uc2const.COLOR_GRAY: image = self.cms.convert_image(image, uc2const.IMAGE_GRAY) img = ImageReader(image) img.getRGBData() if alpha_channel: img._dataA = ImageReader(alpha_channel) self.canvas.drawImage(img, 0, 0, mask='auto') def draw_pixmap_obj(self, obj): if obj.colorspace in uc2const.DUOTONES: fg, bg = libimg.convert_duotone_to_image(self.cms, obj) self.draw_image(*bg) self.draw_image(*fg) else: raw_image = Image.open(StringIO(b64decode(obj.bitmap))) raw_image.load() alpha_chnl = None if obj.alpha_channel: alpha_chnl = Image.open(StringIO(b64decode(obj.alpha_channel))) alpha_chnl.load() self.draw_image(raw_image, alpha_chnl) def draw_pixmap(self, obj): self.canvas.saveState() self.canvas.transform(*obj.trafo) self.canvas.setFillColorCMYK(0, 0, 0, 1, 1) self.canvas.setStrokeColorCMYK(0, 0, 0, 1, 1) self.draw_pixmap_obj(obj) self.canvas.restoreState() def fill_pattern(self, obj, pdfpath, fill_trafo, pattern): if not fill_trafo: fill_trafo = [1.0, 0.0, 0.0, 1.0, 0.0, 0.0] inv_ptrn_trafo = libgeom.invert_trafo(pattern[3]) inv_trafo = libgeom.multiply_trafo( libgeom.invert_trafo(fill_trafo), libgeom.invert_trafo(inv_ptrn_trafo)) paths = libgeom.apply_trafo_to_paths(obj.paths, obj.trafo) paths = libgeom.apply_trafo_to_paths(paths, inv_trafo) bbox = libgeom.get_paths_bbox(paths) cv_trafo = libgeom.multiply_trafo(pattern[3], fill_trafo) bmpstr = b64decode(pattern[1]) image_obj = sk2_model.Pixmap(obj.config) libimg.set_image_data(self.cms, image_obj, bmpstr) if pattern[0] == sk2const.PATTERN_IMG and \ len(pattern) > 2: image_obj.style[3] = deepcopy(pattern[2]) libimg.update_image(self.cms, image_obj) self.canvas.saveState() self.canvas.clipPath(pdfpath, 0, 0) self.canvas.transform(*cv_trafo) w, h = image_obj.get_size() x = bbox[0] y = bbox[3] while y > bbox[1] - h: while x < bbox[2]: self.canvas.saveState() self.canvas.transform(1.0, 0.0, 0.0, 1.0, x, y) self.draw_pixmap_obj(image_obj) self.canvas.restoreState() x += w y -= h x = bbox[0] self.canvas.restoreState()
class Invoice: client = Address() provider = Address() items = [] title = "Faktura" vs = "00000000" creator = "" sign_image = None payment_days = 14 paytype = "Převodem" pdffile = None def __init__(self): self.TOP = 260 self.LEFT = 20 pdfmetrics.registerFont(TTFont('DejaVu', '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf')) self.pdffile = NamedTemporaryFile(delete=False) self.pdf = Canvas(self.pdffile.name, pagesize = letter) self.pdf.setFont("DejaVu", 15) self.pdf.setStrokeColorRGB(0, 0, 0) def __del__(self): if os.path.isfile(self.pdffile.name): os.unlink(self.pdffile.name) ############################################################# ## Setters ############################################################# def setClient(self, address): self.client = address def setProvider(self, address): self.provider = address def setTitle(self, value): self.title = value def setVS(self, value): self.vs = value def setCreator(self, value): self.creator = value def setPaytype(self, value): self.paytype = value def setPaymentDays(self, value): self.payment_days = int(value) def addItem(self, item): self.items.append(item) ############################################################# ## Getters ############################################################# def getContent(self): # Texty self.drawMain() self.drawProvider(self.TOP-10,self.LEFT+3) self.drawClient(self.TOP-30,self.LEFT+91) self.drawPayment(self.TOP-47,self.LEFT+3) self.drawItems(self.TOP-80,self.LEFT) self.drawDates(self.TOP-10,self.LEFT+91) #self.pdf.setFillColorRGB(0, 0, 0) self.pdf.showPage() self.pdf.save() f = open(self.pdffile.name) data = f.read() f.close() os.unlink(self.pdffile.name) return data ############################################################# ## Draw methods ############################################################# def drawMain(self): # Horní lajna self.pdf.drawString(self.LEFT*mm, self.TOP*mm, self.title) self.pdf.drawString((self.LEFT+100)*mm, self.TOP*mm, "Variabilní symbol: %s" % self.vs) # Rámečky self.pdf.rect((self.LEFT)*mm, (self.TOP-68)*mm, (self.LEFT+156)*mm, 65*mm, stroke=True, fill=False) path = self.pdf.beginPath() path.moveTo((self.LEFT+88)*mm, (self.TOP-3)*mm) path.lineTo((self.LEFT+88)*mm, (self.TOP-68)*mm) self.pdf.drawPath(path, True, True) path = self.pdf.beginPath() path.moveTo((self.LEFT)*mm, (self.TOP-39)*mm) path.lineTo((self.LEFT+88)*mm, (self.TOP-39)*mm) self.pdf.drawPath(path, True, True) path = self.pdf.beginPath() path.moveTo((self.LEFT+88)*mm, (self.TOP-23)*mm) path.lineTo((self.LEFT+176)*mm, (self.TOP-23)*mm) self.pdf.drawPath(path, True, True) def drawClient(self,TOP,LEFT): self.pdf.setFont("DejaVu", 12) self.pdf.drawString((LEFT)*mm, (TOP)*mm, "Odběratel") self.pdf.setFont("DejaVu", 8) text = self.pdf.beginText((LEFT+2)*mm, (TOP-6)*mm) text.textLines("\n".join(self.client.getAddressLines())) self.pdf.drawText(text) text = self.pdf.beginText((LEFT+2)*mm, (TOP-28)*mm) text.textLines("\n".join(self.client.getContactLines())) self.pdf.drawText(text) def drawProvider(self,TOP,LEFT): self.pdf.setFont("DejaVu", 12) self.pdf.drawString((LEFT)*mm, (TOP)*mm, "Dodavatel") self.pdf.setFont("DejaVu", 8) text = self.pdf.beginText((LEFT+2)*mm, (TOP-6)*mm) text.textLines("\n".join(self.provider.getAddressLines())) self.pdf.drawText(text) text = self.pdf.beginText((LEFT+40)*mm, (TOP-6)*mm) text.textLines("\n".join(self.provider.getContactLines())) self.pdf.drawText(text) if self.provider.note: self.pdf.drawString((LEFT+2)*mm, (TOP-26)*mm, self.provider.note) def drawPayment(self,TOP,LEFT): self.pdf.setFont("DejaVu", 11) self.pdf.drawString((LEFT)*mm, (TOP)*mm, "Údaje pro platbu") #self.pdf.setFillColorRGB(255, 0, 0) text = self.pdf.beginText((LEFT+2)*mm, (TOP-6)*mm) text.textLines("""%s Číslo účtu: %s Variabilní symbol: %s"""%(self.provider.bank_name ,self.provider.bank_account, self.vs)) self.pdf.drawText(text) def drawItems(self,TOP,LEFT): # Items path = self.pdf.beginPath() path.moveTo((LEFT)*mm, (TOP-4)*mm) path.lineTo((LEFT+176)*mm, (TOP-4)*mm) self.pdf.drawPath(path, True, True) self.pdf.setFont("DejaVu", 9) self.pdf.drawString((LEFT+1)*mm, (TOP-2)*mm, "Fakturuji vám:") i=9 self.pdf.drawString((LEFT+100)*mm, (TOP-i)*mm, "Množství") self.pdf.drawString((LEFT+122)*mm, (TOP-i)*mm, "Cena za jedn.") self.pdf.drawString((LEFT+150)*mm, (TOP-i)*mm, "Cena celkem") i+=5 # List total=0.0 for x in self.items: self.pdf.drawString((LEFT+1)*mm, (TOP-i)*mm, x.name) i+=5 self.pdf.drawString((LEFT+100)*mm, (TOP-i)*mm, "%d ks" % x.count) self.pdf.drawString((LEFT+122)*mm, (TOP-i)*mm, "%.2f,- kč" % x.price) self.pdf.drawString((LEFT+150)*mm, (TOP-i)*mm, "%.2f,- kč" % (x.total())) i+=5 total += x.total() path = self.pdf.beginPath() path.moveTo((LEFT)*mm, (TOP-i)*mm) path.lineTo((LEFT+176)*mm, (TOP-i)*mm) self.pdf.drawPath(path, True, True) self.pdf.setFont("DejaVu", 12) self.pdf.drawString((LEFT+130)*mm, (TOP-i-10)*mm, "Celkem: %d ,- kč" % total) self.pdf.rect((LEFT)*mm, (TOP-i-17)*mm, (LEFT+156)*mm, (i+19)*mm, stroke=True, fill=False) #140,142 if self.sign_image: self.pdf.drawImage(self.sign_image, (LEFT+98)*mm, (TOP-i-72)*mm) path = self.pdf.beginPath() path.moveTo((LEFT+110)*mm, (TOP-i-70)*mm) path.lineTo((LEFT+164)*mm, (TOP-i-70)*mm) self.pdf.drawPath(path, True, True) self.pdf.drawString((LEFT+112)*mm, (TOP-i-75)*mm, "Vystavil: %s" % self.creator) def drawDates(self,TOP,LEFT): today = datetime.datetime.today() payback = today+datetime.timedelta(self.payment_days) self.pdf.setFont("DejaVu", 10) self.pdf.drawString((LEFT)*mm, (TOP+1)*mm, "Datum vystavení: %s" % today.strftime("%d.%m.%Y")) self.pdf.drawString((LEFT)*mm, (TOP-4)*mm, "Datum splatnosti: %s" % payback.strftime("%d.%m.%Y")) self.pdf.drawString((LEFT)*mm, (TOP-9)*mm, "Forma úhrady: " + self.paytype)
class SimpleInvoice(BaseInvoice): def gen(self, filename, generate_qr_code=False): self.TOP = 260 self.LEFT = 20 self.filename = filename if generate_qr_code: qr_builder = QrCodeBuilder(self.invoice) else: qr_builder = None self.qr_builder = qr_builder pdfmetrics.registerFont(TTFont('DejaVu', FONT_PATH)) pdfmetrics.registerFont(TTFont('DejaVu-Bold', FONT_BOLD_PATH)) self.pdf = Canvas(self.filename, pagesize=letter) self.addMetaInformation(self.pdf) self.pdf.setFont('DejaVu', 15) self.pdf.setStrokeColorRGB(0, 0, 0) # Texty self.drawMain() self.drawTitle() self.drawProvider(self.TOP - 10, self.LEFT + 3) self.drawClient(self.TOP - 35, self.LEFT + 91) self.drawPayment(self.TOP - 47, self.LEFT + 3) self.drawItems(self.TOP - 80, self.LEFT) self.drawDates(self.TOP - 10, self.LEFT + 91) #self.pdf.setFillColorRGB(0, 0, 0) self.pdf.showPage() self.pdf.save() if self.qr_builder: self.qr_builder.destroy() ############################################################# ## Draw methods ############################################################# def addMetaInformation(self, pdf): pdf.setCreator(self.invoice.provider.summary) pdf.setTitle(self.invoice.title) pdf.setAuthor(self.invoice.creator.name) def drawTitle(self): # Up line self.pdf.drawString(self.LEFT * mm, self.TOP * mm, self.invoice.title) self.pdf.drawString( (self.LEFT + 90) * mm, self.TOP * mm, _(u'Variable symbol: %s') % self.invoice.variable_symbol) def drawMain(self): # Borders self.pdf.rect(self.LEFT * mm, (self.TOP - 68) * mm, (self.LEFT + 156) * mm, 65 * mm, stroke=True, fill=False) path = self.pdf.beginPath() path.moveTo((self.LEFT + 88) * mm, (self.TOP - 3) * mm) path.lineTo((self.LEFT + 88) * mm, (self.TOP - 68) * mm) self.pdf.drawPath(path, True, True) path = self.pdf.beginPath() path.moveTo(self.LEFT * mm, (self.TOP - 39) * mm) path.lineTo((self.LEFT + 88) * mm, (self.TOP - 39) * mm) self.pdf.drawPath(path, True, True) path = self.pdf.beginPath() path.moveTo((self.LEFT + 88) * mm, (self.TOP - 27) * mm) path.lineTo((self.LEFT + 176) * mm, (self.TOP - 27) * mm) self.pdf.drawPath(path, True, True) def drawClient(self, TOP, LEFT): self.pdf.setFont('DejaVu', 12) self.pdf.drawString(LEFT * mm, TOP * mm, _(u'Customer')) self.pdf.setFont('DejaVu', 8) text = self.pdf.beginText((LEFT + 2) * mm, (TOP - 4) * mm) text.textLines('\n'.join(self.invoice.client.get_address_lines())) self.pdf.drawText(text) text = self.pdf.beginText((LEFT + 2) * mm, (TOP - 23) * mm) text.textLines('\n'.join(self.invoice.client.get_contact_lines())) self.pdf.drawText(text) if self.invoice.client.note: self.pdf.setFont('DejaVu', 6) text = self.pdf.beginText((LEFT + 2) * mm, (TOP - 28) * mm) text.textLines(self.invoice.client.note) self.pdf.drawText(text) def drawProvider(self, TOP, LEFT): self.pdf.setFont('DejaVu', 12) self.pdf.drawString(LEFT * mm, TOP * mm, _(u'Provider')) self.pdf.setFont('DejaVu', 8) text = self.pdf.beginText((LEFT + 2) * mm, (TOP - 6) * mm) text.textLines('\n'.join(self.invoice.provider.get_address_lines())) self.pdf.drawText(text) text = self.pdf.beginText((LEFT + 40) * mm, (TOP - 6) * mm) text.textLines('\n'.join(self.invoice.provider.get_contact_lines())) self.pdf.drawText(text) if self.invoice.provider.note: self.pdf.setFont('DejaVu', 6) text = self.pdf.beginText((LEFT + 2) * mm, (TOP - 23) * mm) text.textLines(self.invoice.provider.note) self.pdf.drawText(text) def drawPayment(self, TOP, LEFT): self.pdf.setFont('DejaVu-Bold', 9) self.pdf.drawString(LEFT * mm, TOP * mm, _(u'Payment information')) text = self.pdf.beginText((LEFT + 2) * mm, (TOP - 6) * mm) lines = [ self.invoice.provider.bank_name, '%s: %s' % (_(u'Bank account'), self.invoice.provider.bank_account), '%s: %s' % (_(u'Variable symbol'), self.invoice.variable_symbol) ] if self.invoice.specific_symbol: lines.append('%s: %s' % (_(u'Specific symbol'), self.invoice.specific_symbol)) text.textLines('\n'.join(lines)) self.pdf.drawText(text) def drawItems(self, TOP, LEFT): # Items path = self.pdf.beginPath() path.moveTo(LEFT * mm, (TOP - 4) * mm) path.lineTo((LEFT + 176) * mm, (TOP - 4) * mm) self.pdf.drawPath(path, True, True) self.pdf.setFont('DejaVu-Bold', 7) self.pdf.drawString((LEFT + 1) * mm, (TOP - 2) * mm, _(u'List of items')) self.pdf.drawString((LEFT + 1) * mm, (TOP - 9) * mm, _(u'Description')) items_are_with_tax = self.invoice.use_tax if items_are_with_tax: i = 9 self.pdf.drawString((LEFT + 68) * mm, (TOP - i) * mm, _(u'Units')) self.pdf.drawString((LEFT + 88) * mm, (TOP - i) * mm, _(u'Price per one')) self.pdf.drawString((LEFT + 115) * mm, (TOP - i) * mm, _(u'Total price')) self.pdf.drawString((LEFT + 137) * mm, (TOP - i) * mm, _(u'Tax')) self.pdf.drawString((LEFT + 146) * mm, (TOP - i) * mm, _(u'Total price with tax')) i += 5 else: i = 9 self.pdf.drawString((LEFT + 104) * mm, (TOP - i) * mm, _(u'Units')) self.pdf.drawString((LEFT + 123) * mm, (TOP - i) * mm, _(u'Price per one')) self.pdf.drawString((LEFT + 150) * mm, (TOP - i) * mm, _(u'Total price')) i += 5 self.pdf.setFont('DejaVu', 7) # List for item in self.invoice.items: self.pdf.drawString((LEFT + 1) * mm, (TOP - i) * mm, item.description) if item.tax or items_are_with_tax: items_are_with_tax = True if len(item.description) > 52: i += 5 if float(int(item.count)) == item.count: self.pdf.drawString((LEFT + 68) * mm, (TOP - i) * mm, '%.2f %s' % (item.count, item.unit)) else: self.pdf.drawString((LEFT + 68) * mm, (TOP - i) * mm, '%.2f %s' % (item.count, item.unit)) self.pdf.drawString( (LEFT + 88) * mm, (TOP - i) * mm, '%.2f,- %s' % (item.price, self.invoice.currency)) self.pdf.drawString( (LEFT + 115) * mm, (TOP - i) * mm, '%.2f,- %s' % (item.total, self.invoice.currency)) self.pdf.drawString((LEFT + 137) * mm, (TOP - i) * mm, '%.0f %%' % item.tax) self.pdf.drawString( (LEFT + 146) * mm, (TOP - i) * mm, '%.2f,- %s' % (item.total_tax, self.invoice.currency)) i += 5 else: if len(item.description) > 75: i += 5 if float(int(item.count)) == item.count: self.pdf.drawString((LEFT + 104) * mm, (TOP - i) * mm, '%.2f %s' % (item.count, item.unit)) else: self.pdf.drawString((LEFT + 104) * mm, (TOP - i) * mm, '%.2f %s' % (item.count, item.unit)) self.pdf.drawString( (LEFT + 123) * mm, (TOP - i) * mm, '%.2f,- %s' % (item.price, self.invoice.currency)) self.pdf.drawString( (LEFT + 150) * mm, (TOP - i) * mm, '%.2f,- %s' % (item.total, self.invoice.currency)) i += 5 if self.invoice.rounding_result: path = self.pdf.beginPath() path.moveTo(LEFT * mm, (TOP - i) * mm) path.lineTo((LEFT + 176) * mm, (TOP - i) * mm) i += 5 self.pdf.drawPath(path, True, True) self.pdf.drawString((LEFT + 1) * mm, (TOP - i) * mm, _(u'Rounding')) self.pdf.drawString( (LEFT + 68) * mm, (TOP - i) * mm, '%.2f,- %s' % (self.invoice.difference_in_rounding, self.invoice.currency)) i += 3 path = self.pdf.beginPath() path.moveTo(LEFT * mm, (TOP - i) * mm) path.lineTo((LEFT + 176) * mm, (TOP - i) * mm) self.pdf.drawPath(path, True, True) if not items_are_with_tax: self.pdf.setFont('DejaVu-Bold', 11) self.pdf.drawString((LEFT + 100) * mm, (TOP - i - 7) * mm, _(u'Total') + ': %.2f %s' % (self.invoice.price, self.invoice.currency)) else: self.pdf.setFont('DejaVu-Bold', 6) self.pdf.drawString((LEFT + 1) * mm, (TOP - i - 2) * mm, _(u'Breakdown VAT')) vat_list, tax_list, total_list, total_tax_list = [ _(u'VAT rate') ], [_(u'Tax')], [_(u'Without VAT')], [_(u'With VAT')] for vat, items in self.invoice.generate_breakdown_vat().iteritems( ): vat_list.append('%.2f%%' % vat) tax_list.append('%.2f %s' % (items['tax'], self.invoice.currency)) total_list.append('%.2f %s' % (items['total'], self.invoice.currency)) total_tax_list.append( '%.2f %s' % (items['total_tax'], self.invoice.currency)) self.pdf.setFont('DejaVu', 6) text = self.pdf.beginText((LEFT + 1) * mm, (TOP - i - 5) * mm) text.textLines('\n'.join(vat_list)) self.pdf.drawText(text) text = self.pdf.beginText((LEFT + 11) * mm, (TOP - i - 5) * mm) text.textLines('\n'.join(tax_list)) self.pdf.drawText(text) text = self.pdf.beginText((LEFT + 27) * mm, (TOP - i - 5) * mm) text.textLines('\n'.join(total_list)) self.pdf.drawText(text) text = self.pdf.beginText((LEFT + 45) * mm, (TOP - i - 5) * mm) text.textLines('\n'.join(total_tax_list)) self.pdf.drawText(text) self.pdf.setFont('DejaVu-Bold', 11) self.pdf.drawString( (LEFT + 100) * mm, (TOP - i - 14) * mm, _(u'Total with tax') + ': %.2f %s' % (self.invoice.price_tax, self.invoice.currency)) if items_are_with_tax: self.pdf.rect(LEFT * mm, (TOP - i - 17) * mm, (LEFT + 156) * mm, (i + 19) * mm, stroke=True, fill=False) #140,142 else: self.pdf.rect(LEFT * mm, (TOP - i - 11) * mm, (LEFT + 156) * mm, (i + 13) * mm, stroke=True, fill=False) #140,142 if self.invoice.creator.stamp_filename: im = Image.open(self.invoice.creator.stamp_filename) height = float(im.size[1]) / (float(im.size[0]) / 200.0) self.pdf.drawImage(self.invoice.creator.stamp_filename, (LEFT + 98) * mm, (TOP - i - 72) * mm, 200, height) if self.qr_builder: qr_filename = self.qr_builder.filename im = Image.open(qr_filename) height = float(im.size[1]) / (float(im.size[0]) / 200.0) self.pdf.drawImage(qr_filename, LEFT * mm, (TOP - i - 100) * mm, 200, height) path = self.pdf.beginPath() path.moveTo((LEFT + 110) * mm, (TOP - i - 70) * mm) path.lineTo((LEFT + 164) * mm, (TOP - i - 70) * mm) self.pdf.drawPath(path, True, True) self.pdf.drawString( (LEFT + 112) * mm, (TOP - i - 75) * mm, '%s: %s' % (_(u'Creator'), self.invoice.creator.name)) def drawDates(self, TOP, LEFT): self.pdf.setFont('DejaVu', 10) top = TOP + 1 items = [(LEFT * mm, '%s: %s' % (_(u'Date'), self.invoice.date)), (LEFT * mm, '%s: %s' % (_(u'Payback'), self.invoice.payback))] if self.invoice.taxable_date: items.append( (LEFT * mm, '%s: %s' % (_(u'Taxable date'), self.invoice.taxable_date))) items.append( (LEFT * mm, '%s: %s' % (_(u'Paytype'), self.invoice.paytype))) for item in items: self.pdf.drawString(item[0], top * mm, item[1]) top += -5
def draw_card(canvas: RLC.Canvas, X, Y, character): canvas.saveState() canvas.translate(X, Y) font_size_title = 16 font_size_content = 8 font_size_annotation = 5 font_size_furigana = 6 font_size_words = 9 font_to_mm = 0.5 * mm margin_drawing = 6 * mm margin_left = 2 * mm margin_bottom = 2 * mm margin_text = 48 * mm margin_top = -font_size_furigana * font_to_mm len_vertical_text_bound = 12 max_words_count = 6 paths, hints = extract_drawings(character.char) canvas.translate(margin_drawing, -margin_drawing) canvas.setLineWidth(7) canvas.setLineCap(1) canvas.setLineJoin(1) for i, path in enumerate(paths): canvas.setStrokeColorRGB(*palette["strokes"][i]) canvas.drawPath(convert_path(path, canvas)) canvas.setLineWidth(1) canvas.setLineCap(0) canvas.setLineJoin(0) canvas.setFont('Helvetica', 5) canvas.setFillColorRGB(*palette["default"]) for i, hint in enumerate(hints): canvas.drawString(*hint) canvas.translate(-margin_drawing, margin_drawing) canvas.setFont(font_jp, font_size_title) canvas.setFillColorRGB(*palette["default"]) canvas.drawString(margin_left, -font_size_title * font_to_mm, character.char) x_ = margin_text canvas.setFont(font_jp_v, font_size_annotation) canvas.setFillColorRGB(*palette["readings_kun"]) canvas.drawString(x_, margin_top, "kun") x_ = margin_text + font_size_annotation * 0.5 * mm canvas.setFont(font_jp_v, font_size_content) canvas.setFillColorRGB(*palette["readings_kun"]) rest = character.readings_kun while rest: if len(rest) <= len_vertical_text_bound: text, rest = rest.strip(), '' else: dlm = len_vertical_text_bound while rest[dlm] != ' ': dlm -= 1 text, rest = rest[:dlm], rest[dlm:].lstrip() canvas.drawString(x_, margin_top, text) x_ += font_size_content * 0.4 * mm x_ += 1 * mm canvas.setFont(font_jp_v, font_size_annotation) canvas.setFillColorRGB(*palette["readings_on"]) canvas.drawString(x_, margin_top, "on") x_ += font_size_annotation * font_to_mm canvas.setFont(font_jp_v, font_size_content) canvas.setFillColorRGB(*palette["readings_on"]) canvas.drawString(x_, margin_top, character.readings_on) x_ += font_size_words * font_to_mm + 2 * mm canvas.setFont(font_jp_v, font_size_annotation) canvas.setFillColorRGB(*palette["default"]) canvas.drawString(x_, margin_top, "words") x_ += font_size_annotation * font_to_mm words = character.words.split('<br/>')[:max_words_count] y_ = -margin_top - (font_size_words + font_size_furigana * 2.5) * font_to_mm rightmost = 0 for word in words: xl = x_ wparts = re.split(r'[{}]', word) for wpart in wparts: if wpart and ':' in wpart: part, furi_part = wpart.split(':') else: part, furi_part = wpart, '' width_part = fontH.stringWidth(part, font_size_words) width_furi = fontH.stringWidth(furi_part, font_size_furigana) width = max(width_furi, width_part) canvas.setFont(font_jp, font_size_words) canvas.drawString(xl + width / 2 - width_part / 2, y_, part) canvas.setFont(font_jp, font_size_furigana) canvas.drawString(xl + width / 2 - width_furi / 2, y_ + font_size_furigana * font_to_mm + 1 * mm, furi_part) xl += width rightmost = max(rightmost, xl) y_ -= font_size_words * font_to_mm + font_size_furigana * font_to_mm x_ += rightmost x_ = margin_left canvas.setFillColorRGB(*palette["secondary"]) canvas.setFont(font_jp, font_size_annotation) canvas.drawString(x_, -card_height + margin_bottom, "components") canvas.setFont(font_jp, font_size_content) canvas.drawString( x_, -card_height + margin_bottom + font_size_annotation * font_to_mm, character.parts) x_ += margin_left + 12 * mm + fontH.stringWidth(character.parts, font_size_content) canvas.setFont(font_jp, font_size_annotation) canvas.drawString(x_, -card_height + margin_bottom, "radical") canvas.setFont(font_jp, font_size_content) canvas.drawString( x_, -card_height + margin_bottom + font_size_annotation * font_to_mm, character.radicals) canvas.setFont(font_jp, font_size_annotation) text = f"JLPT {character.jlpt or '-'} #{character.frequency}" canvas.drawString( card_width - 5 * mm - fontH.stringWidth(text, font_size_annotation), -card_height + margin_bottom, text) draw_marks(canvas) canvas.restoreState() print(character.char)
def draw_label(self, c: Canvas, col: int, row: int, redemption_code: str): x = self.left_margin + (col + 0.5) * self.label_width + col * self.inner_margin y = self.page_height - self.top_margin - (row + 0.5) * self.label_height # Drawing label bounds helps when adjusting layout. Not for production. # self.draw_label_bounds(c, x, y) c.setFont("Courier-Bold", 13) c.drawString(x - 80, y + 14, redemption_code) c.setFont("Helvetica", 10) # Space to enter redemption month and day. p = c.beginPath() p.moveTo(x + 20, y + 12) p.lineTo(x + 45, y + 12) p.moveTo(x + 55, y + 12) p.lineTo(x + 80, y + 12) p.close() c.drawPath(p) c.drawCentredString(x + 15, y + 16, 'm:') c.drawCentredString(x + 50, y + 16, 'd:') # Space to enter redeemer's email address. p = c.beginPath() p.moveTo(x - 80, y - 14) p.lineTo(x + 80, y - 14) p.close() c.drawPath(p) c.drawCentredString(x, y - 24, 'email address')