paperless-asn-qr-codes/paperless_asn_qr_codes/avery_labels.py

128 lines
3.9 KiB
Python
Raw Normal View History

2023-11-18 17:59:00 +01:00
import os
from collections.abc import Iterator
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import LETTER, landscape
from reportlab.lib.units import inch
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.lib.units import mm, cm
# Usage:
# label = AveryLabels.AveryLabel(5160)
# label.open( "labels5160.pdf" )
# label.render( RenderAddress, 30 )
# label.close()
#
# 'render' can either pass a callable, which receives the canvas object
# (with X,Y=0,0 at the lower right) or a string "form" name of a form
# previously created with canv.beginForm().
# labels across
# labels down
# label size w/h
# label gutter across/down
# page margins left/top
labelInfo = {
4731: ( 7, 27, (25.4*mm, 10*mm), (0.25*cm, 0), (1.22*cm, 0.48*cm)),
# 2.6 x 1 address labels
5160: ( 3, 10, (187, 72), (11, 0), (14, 36)),
5161: ( 2, 10, (288, 72), (0, 0), (18, 36)),
# 4 x 2 address labels
5163: ( 2, 5, (288, 144), (0, 0), (18, 36)),
# 1.75 x 0.5 return address labels
5167: ( 4, 20, (126, 36), (0, 0), (54, 36)),
# 3.5 x 2 business cards
5371: ( 2, 5, (252, 144), (0, 0), (54, 36)),
}
RETURN_ADDRESS = 5167
BUSINESS_CARDS = 5371
class AveryLabel:
def __init__(self, label, **kwargs):
data = labelInfo[label]
self.across = data[0]
self.down = data[1]
self.size = data[2]
self.labelsep = self.size[0]+data[3][0], self.size[1]+data[3][1]
self.margins = data[4]
self.topDown = True
self.debug = False
self.pagesize = LETTER
self.position = 0
self.__dict__.update(kwargs)
def open(self, filename):
self.canvas = canvas.Canvas( filename, pagesize=self.pagesize )
if self.debug:
self.canvas.setPageCompression( 0 )
self.canvas.setLineJoin(1)
self.canvas.setLineCap(1)
def topLeft(self, x=None, y=None):
if x == None:
x = self.position
if y == None:
if self.topDown:
x,y = divmod(x, self.down)
else:
y,x = divmod(x, self.across)
return (
self.margins[0]+x*self.labelsep[0],
self.pagesize[1] - self.margins[1] - (y+1)*self.labelsep[1]
)
def advance(self):
self.position += 1
if self.position == self.across * self.down:
self.canvas.showPage()
self.position = 0
def close(self):
if self.position:
self.canvas.showPage()
self.canvas.save()
self.canvas = None
# To render, you can either create a template and tell me
# "go draw N of these templates" or provide a callback.
# Callback receives canvas, width, height.
#
# Or, pass a callable and an iterator. We'll do one label
# per iteration of the iterator.
def render( self, thing, count, *args ):
assert callable(thing) or isinstance(thing, str)
if isinstance(count, Iterator):
return self.render_iterator( thing, count )
canv = self.canvas
for i in range(count):
canv.saveState()
canv.translate( *self.topLeft() )
if self.debug:
canv.setLineWidth( 0.25 )
canv.rect( 0, 0, self.size[0], self.size[1] )
if callable(thing):
thing( canv, self.size[0], self.size[1], *args )
elif isinstance(thing, str):
canv.doForm(thing)
canv.restoreState()
self.advance()
def render_iterator( self, func, iterator ):
canv = self.canvas
for chunk in iterator:
canv.saveState()
canv.translate( *self.topLeft() )
if self.debug:
canv.setLineWidth( 0.25 )
canv.rect( 0, 0, self.size[0], self.size[1] )
func( canv, self.size[0], self.size[1], chunk )
canv.restoreState()
self.advance()