BodyBalanceEvaluation/backend/venv/Lib/site-packages/reportlab/graphics/barcode/dmtx.py

274 lines
7.7 KiB
Python
Raw Normal View History

2025-07-31 17:23:05 +08:00
try:
from pylibdmtx import pylibdmtx
except ImportError:
pylibdmtx = None
__all__ = ()
else:
__all__=('DataMatrix',)
from reportlab.graphics.barcode.common import Barcode
from reportlab.lib.utils import asBytes
from reportlab.platypus.paraparser import _num as paraparser_num
from reportlab.graphics.widgetbase import Widget
from reportlab.lib.validators import isColor, isString, isColorOrNone, isNumber, isBoxAnchor
from reportlab.lib.attrmap import AttrMap, AttrMapValue
from reportlab.lib.colors import toColor
from reportlab.graphics.shapes import Group, Rect
def _numConv(x):
return x if isinstance(x,(int,float)) else paraparser_num(x)
class _DMTXCheck:
@classmethod
def pylibdmtx_check(cls):
if not pylibdmtx:
raise ValueError('The %s class requires package pylibdmtx' % cls.__name__)
class DataMatrix(Barcode,_DMTXCheck):
def __init__(self, value='', **kwds):
self.pylibdmtx_check()
self._recalc = True
self.value = value
self.cellSize = kwds.pop('cellSize','5x5')
self.size = kwds.pop('size','SquareAuto')
self.encoding = kwds.pop('encoding','Ascii')
self.anchor = kwds.pop('anchor','sw')
self.color = kwds.pop('color',(0,0,0))
self.bgColor = kwds.pop('bgColor',None)
self.x = kwds.pop('x',0)
self.y = kwds.pop('y',0)
self.border = kwds.pop('border',5)
@property
def value(self):
return self._value
@value.setter
def value(self,v):
self._value = asBytes(v)
self._recalc = True
@property
def size(self):
return self._size
@size.setter
def size(self,v):
self._size = self._checkVal('size', v, pylibdmtx.ENCODING_SIZE_NAMES)
self._recalc = True
@property
def border(self):
return self._border
@border.setter
def border(self,v):
self._border = _numConv(v)
self._recalc = True
@property
def x(self):
return self._x
@x.setter
def x(self,v):
self._x = _numConv(v)
self._recalc = True
@property
def y(self):
return self._y
@y.setter
def y(self,v):
self._y = _numConv(v)
self._recalc = True
@property
def cellSize(self):
return self._cellSize
@size.setter
def cellSize(self,v):
self._cellSize = v
self._recalc = True
@property
def encoding(self):
return self._encoding
@encoding.setter
def encoding(self,v):
self._encoding = self._checkVal('encoding', v, pylibdmtx.ENCODING_SCHEME_NAMES)
self._recalc = True
@property
def anchor(self):
return self._anchor
@anchor.setter
def anchor(self,v):
self._anchor = self._checkVal('anchor', v, ('n','ne','e','se','s','sw','w','nw','c'))
self._recalc = True
def recalc(self):
if not self._recalc: return
data = self._value
size = self._size
encoding = self._encoding
e = pylibdmtx.encode(data, size=size, scheme=encoding)
iW = e.width
iH = e.height
p = e.pixels
iCellSize = 5
bpp = 3 #bytes per pixel
rowLen = iW*bpp
cellLen = iCellSize*bpp
assert len(p)//rowLen == iH
matrix = list(filter(None,
(''.join(
(('x' if p[j:j+bpp] != b'\xff\xff\xff' else ' ')
for j in range(i,i+rowLen,cellLen))).strip()
for i in range(0,iH*rowLen,rowLen*iCellSize))))
self._nRows = len(matrix)
self._nCols = len(matrix[-1])
self._matrix = '\n'.join(matrix)
cellWidth = self._cellSize
if cellWidth:
cellWidth = cellWidth.split('x')
if len(cellWidth)>2:
raise ValueError('cellSize needs to be distance x distance not %r' % self._cellSize)
elif len(cellWidth)==2:
cellWidth, cellHeight = cellWidth
else:
cellWidth = cellHeight = cellWidth[0]
cellWidth = _numConv(cellWidth)
cellHeight = _numConv(cellHeight)
else:
cellWidth = cellHeight = iCellSize
self._cellWidth = cellWidth
self._cellHeight = cellHeight
self._recalc = False
self._bord = max(self.border,cellWidth,cellHeight)
self._width = cellWidth*self._nCols + 2*self._bord
self._height = cellHeight*self._nRows + 2*self._bord
@property
def matrix(self):
self.recalc()
return self._matrix
@property
def width(self):
self.recalc()
return self._width
@property
def height(self):
self.recalc()
return self._height
@property
def cellWidth(self):
self.recalc()
return self._cellWidth
@property
def cellHeight(self):
self.recalc()
return self._cellHeight
def draw(self):
self.recalc()
canv = self.canv
w = self.width
h = self.height
x = self.x
y = self.y
b = self._bord
anchor = self.anchor
if anchor in ('nw','n','ne'):
y -= h
elif anchor in ('c','e','w'):
y -= h//2
if anchor in ('ne','e','se'):
x -= w
elif anchor in ('n','c','s'):
x -= w//2
canv.saveState()
if self.bgColor:
canv.setFillColor(toColor(self.bgColor))
canv.rect(x, y-h, w, h, fill=1, stroke=0)
canv.setFillColor(toColor(self.color))
canv.setStrokeColor(None)
cellWidth = self.cellWidth
cellHeight = self.cellHeight
yr = y - b - cellHeight
x += b
for row in self.matrix.split('\n'):
xr = x
for c in row:
if c=='x':
canv.rect(xr, yr, cellWidth, cellHeight, fill=1, stroke=0)
xr += cellWidth
yr -= cellHeight
canv.restoreState()
class DataMatrixWidget(Widget,_DMTXCheck):
codeName = "DataMatrix"
_attrMap = AttrMap(
BASE = Widget,
value = AttrMapValue(isString, desc='Datamatrix data'),
x = AttrMapValue(isNumber, desc='x-coord'),
y = AttrMapValue(isNumber, desc='y-coord'),
color = AttrMapValue(isColor, desc='foreground color'),
bgColor = AttrMapValue(isColorOrNone, desc='background color'),
encoding = AttrMapValue(isString, desc='encoding'),
size = AttrMapValue(isString, desc='size'),
cellSize = AttrMapValue(isString, desc='cellSize'),
anchor = AttrMapValue(isBoxAnchor, desc='anchor pooint for x,y'),
)
_defaults = dict(
x = ('0',_numConv),
y = ('0',_numConv),
color = ('black',toColor),
bgColor = (None,lambda _: toColor(_) if _ is not None else _),
encoding = ('Ascii',None),
size = ('SquareAuto',None),
cellSize = ('5x5',None),
anchor = ('sw', None),
)
def __init__(self,value='Hello Cruel World!', **kwds):
self.pylibdmtx_check()
self.value = value
for k,(d,c) in self._defaults.items():
v = kwds.pop(k,d)
if c: v = c(v)
setattr(self,k,v)
def rect(self, x, y, w, h, fill=1, stroke=0):
self._gadd(Rect(x,y,w,h,strokeColor=None,fillColor=self._fillColor))
def saveState(self,*args,**kwds):
pass
restoreState = setStrokeColor = saveState
def setFillColor(self,c):
self._fillColor = c
def draw(self):
m = DataMatrix(value=self.value,**{k: getattr(self,k) for k in self._defaults})
m.canv = self
m.y += m.height
g = Group()
self._gadd = g.add
m.draw()
return g