667importclick7importclick8fromreedmullerimportreedmuller8fromreedmullerimportreedmuller99101011classTag:11classTag:12""" Helper class to ease creation of SVG. All API functions that create SVG allow you to substitute this with your12""" Helper class to ease creation of SVG. All API functions that create SVG allow you to substitute this with your13 own implementation by passing a ``tag`` parameter. """13 own implementation by passing a ``tag`` parameter. """141415def__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']=fill17attrs['fill'],attrs['fill-opacity']=fill18if(stroke:=attrs.get('stroke'))andisinstance(stroke,tuple):18if(stroke:=attrs.get('stroke'))andisinstance(stroke,tuple):19attrs['stroke'],attrs['stroke-opacity']=stroke19attrs['stroke'],attrs['stroke-opacity']=stroke20self.name,self.attrs=name,attrs20self.name,self.attrs=name,attrs21self.children=childrenor[]21self.children=childrenor[]22self.root=root22self.root=root232324def__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)5862596360@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_colororcolor78text_color=text_colororcolor757976NUM_BITS=2680NUM_BITS=26778178data_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_bits84(a,nota)foraindata_bits81])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]838784width=len(data_encoded)*bar_width88width=len(data_encoded)*bar_width85# 1 px = 0.75 pt89# 1 px = 0.75 pt86pt_to_mm=lambdapt:pt/0.75/dpi*25.490pt_to_mm=lambdapt:pt/0.75/dpi*25.487font_size=pt_to_mm(font_size)91font_size=pt_to_mm(font_size)88total_height=height+font_size*292total_height=height+font_size*2899390tags=[]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}'))9710198iftext: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))104108