+6
+6
+7importclick
+7importclick
+8fromreedmullerimportreedmuller
+8fromreedmullerimportreedmuller
+9
+9
+10
+10
+11classTag:
+11classTag:
+12""" Helper class to ease creation of SVG. All API functions that create SVG allow you to substitute this with your
+12""" Helper class to ease creation of SVG. All API functions that create SVG allow you to substitute this with your
+13 own implementation by passing a ``tag`` parameter. """
+13 own implementation by passing a ``tag`` parameter. """
+14
+14
+15def__init__(self,name,children=None,root=False,**attrs):
+15def__init__(self,name,children=None,root=False,**attrs):
+16if(fill:=attrs.get('fill'))andisinstance(fill,tuple):
+16if(fill:=attrs.get('fill'))andisinstance(fill,tuple):
+17attrs['fill'],attrs['fill-opacity']=fill
+17attrs['fill'],attrs['fill-opacity']=fill
+18if(stroke:=attrs.get('stroke'))andisinstance(stroke,tuple):
+18if(stroke:=attrs.get('stroke'))andisinstance(stroke,tuple):
+19attrs['stroke'],attrs['stroke-opacity']=stroke
+19attrs['stroke'],attrs['stroke-opacity']=stroke
+20self.name,self.attrs=name,attrs
+20self.name,self.attrs=name,attrs
+21self.children=childrenor[]
+21self.children=childrenor[]
+22self.root=root
+22self.root=root
+23
+23
+24def__str__(self):
+24def__str__(self):
+25prefix='<?xml version="1.0" encoding="utf-8"?>\n'ifself.rootelse''
+25prefix='<?xml version="1.0" encoding="utf-8"?>\n'ifself.rootelse''
+26opening=''.join([self.name]+[f'{key.replace("__",":").replace("_","-")}="{value}"'forkey,valueinself.attrs.items()])
+26opening=''.join([self.name]+[f'{key.replace("__",":").replace("_","-")}="{value}"'forkey,valueinself.attrs.items()])
+27ifself.children:
+27ifself.children:
+28children='\n'.join(textwrap.indent(str(c),'')forcinself.children)
+28children='\n'.join(textwrap.indent(str(c),'')forcinself.children)
+29returnf'{prefix}<{opening}>\n{children}\n</{self.name}>'
+29returnf'{prefix}<{opening}>\n{children}\n</{self.name}>'
+
+56**namespaces,
+60**namespaces,
+57root=True)
+61root=True)
+58
+62
+59
+63
+60@click.command()
+64@click.command()
+61@click.option('-h','--height',type=float,default=20,help='Bar height in mm')
+65@click.option('-h','--height',type=float,default=20,help='Bar height in mm')
+62@click.option('-t/-n','--text/--no-text',default=True,help='Whether to add text containing the data under the bar code')
+66@click.option('-t/-n','--text/--no-text',default=True,help='Whether to add text containing the data under the bar code')
+63@click.option('-f','--font',default='sans-serif',help='Font for the text underneath the bar code')
+67@click.option('-f','--font',default='sans-serif',help='Font for the text underneath the bar code')
+64@click.option('-s','--font-size',type=float,default=12,help='Font size for the text underneath the bar code in points (pt)')
+68@click.option('-s','--font-size',type=float,default=12,help='Font size for the text underneath the bar code in points (pt)')
+65@click.option('-b','--bar-width',type=float,default=1.0,help='Bar width in mm')
+69@click.option('-b','--bar-width',type=float,default=1.0,help='Bar width in mm')
+66@click.option('-m','--margin',type=float,default=3.0,help='Margin around bar code in mm')
+70@click.option('-m','--margin',type=float,default=3.0,help='Margin around bar code in mm')
+67@click.option('-c','--color',default='black',help='SVG color for the bar code')
+71@click.option('-c','--color',default='black',help='SVG color for the bar code')
+68@click.option('--text-color',default=None,help='SVG color for the text (defaults to the bar code\'s color)')
+72@click.option('--text-color',default=None,help='SVG color for the text (defaults to the bar code\'s color)')
+69@click.option('--dpi',type=float,default=96,help='DPI value to assume for internal SVG unit conversions')
+73@click.option('--dpi',type=float,default=96,help='DPI value to assume for internal SVG unit conversions')
+70@click.argument('data')
+74@click.argument('data')
+71@click.argument('outfile',type=click.File('w'),default='-')
+75@click.argument('outfile',type=click.File('w'),default='-')
+72defcli(data,outfile,height,text,font,font_size,bar_width,margin,color,text_color,dpi):
+76defcli(data,outfile,height,text,font,font_size,bar_width,margin,color,text_color,dpi):
+73data=int(data,16)
+77data=int(data,16)
+74text_color=text_colororcolor
+78text_color=text_colororcolor
+75
+79
+76NUM_BITS=26
+80NUM_BITS=26
+77
+81
+78data_bits=[bool(data&(1<<i))foriinrange(NUM_BITS)]
+82data_bits=[bool(data&(1<<i))foriinrange(NUM_BITS)]
+79data_encoded=itertools.chain(*[
+83data_encoded=itertools.chain(*[
+80(a,nota)foraindata_bits
+84(a,nota)foraindata_bits
+81])
+85])
+82data_encoded=[True,False,True,False,*data_encoded,False,True,True,False,True]
+86data_encoded=[True,False,True,False,*data_encoded,False,True,True,False,True]
+83
+87
+84width=len(data_encoded)*bar_width
+88width=len(data_encoded)*bar_width
+85# 1 px = 0.75 pt
+89# 1 px = 0.75 pt
+86pt_to_mm=lambdapt:pt/0.75/dpi*25.4
+90pt_to_mm=lambdapt:pt/0.75/dpi*25.4
+87font_size=pt_to_mm(font_size)
+91font_size=pt_to_mm(font_size)
+88total_height=height+font_size*2
+92total_height=height+font_size*2
+89
+93
+90tags=[]
+94tags=[]
+91forkey,groupinitertools.groupby(enumerate(data_encoded),key=lambdax:x[1]):
+95forkey,groupinitertools.groupby(enumerate(data_encoded),key=lambdax:x[1]):
+92ifkey:
+96ifkey:
+93group=list(group)
+97group=list(group)
+94x0,_key=group[0]
+98x0,_key=group[0]
+95w=len(group)
+99w=len(group)
+96tags.append(Tag('path',stroke=color,stroke_width=w,d=f'M {(x0+w/2)*bar_width} 0 l 0 {height}'))
+100tags.append(Tag('path',stroke=color,stroke_width=w,d=f'M {(x0+w/2)*bar_width} 0 l 0 {height}'))
+97
+101
+98iftext:
+102iftext:
+99tags.append(Tag('text',children=[f'{data:07x}'],
+103tags.append(Tag('text',children=[f'{data:07x}'],
+100x=width/2,y=height+0.5*font_size,
+104x=width/2,y=height+0.5*font_size,
+101font_family=font,font_size=f'{font_size:.3f}px',
+105font_family=font,font_size=f'{font_size:.3f}px',
+102text_anchor='middle',dominant_baseline='hanging',
+106text_anchor='middle',dominant_baseline='hanging',
+103fill=text_color))
+107fill=text_color))
+104
+108
+