All checks were successful
Build & Deploy docs / build-deploy (push) Successful in 2m53s
69 lines
3.0 KiB
Python
69 lines
3.0 KiB
Python
import xml.etree.ElementTree as ET, re, glob, json, os
|
|
SVG="http://www.w3.org/2000/svg"; ETM="https://etm-powersync.fr/ns/schema"
|
|
INK="http://www.inkscape.org/namespaces/inkscape"
|
|
SODI="http://sodipodi.sourceforge.net/DTD/sodipodi-0.0"
|
|
def ln(t): return t.split('}')[-1]
|
|
def parse_tf(s):
|
|
M=[1,0,0,1,0,0]
|
|
if not s: return M
|
|
for name,args in re.findall(r'(\w+)\s*\(([^)]*)\)', s):
|
|
n=[float(x) for x in re.split(r'[,\s]+',args.strip()) if x!='']
|
|
if name=='translate': m=[1,0,0,1,n[0],n[1] if len(n)>1 else 0]
|
|
elif name=='scale': m=[n[0],0,0,(n[1] if len(n)>1 else n[0]),0,0]
|
|
elif name=='matrix': m=n
|
|
else: m=[1,0,0,1,0,0]
|
|
a,b,c,d,e,f=M; a2,b2,c2,d2,e2,f2=m
|
|
M=[a*a2+c*b2,b*a2+d*b2,a*c2+c*d2,b*c2+d*d2,a*e2+c*f2+e,b*e2+d*f2+f]
|
|
return M
|
|
def comp(M1,M2):
|
|
a,b,c,d,e,f=M1;a2,b2,c2,d2,e2,f2=M2
|
|
return [a*a2+c*b2,b*a2+d*b2,a*c2+c*d2,b*c2+d*d2,a*e2+c*f2+e,b*e2+d*f2+f]
|
|
def app(M,x,y):
|
|
a,b,c,d,e,f=M; return (round(a*x+c*y+e,1),round(b*x+d*y+f,1))
|
|
def pos(el):
|
|
if ln(el.tag) in("circle","ellipse"): return float(el.get("cx",0)),float(el.get("cy",0))
|
|
if ln(el.tag)=="text": return float(el.get("x",0) or 0),float(el.get("y",0) or 0)
|
|
if ln(el.tag)=="path" and el.get(f"{{{SODI}}}type")=="arc":
|
|
return float(el.get(f"{{{SODI}}}cx",0)),float(el.get(f"{{{SODI}}}cy",0))
|
|
return None
|
|
|
|
lib={}
|
|
for fn in sorted(glob.glob("symbol-*.svg")):
|
|
root=ET.parse(fn).getroot()
|
|
c=root.find(f".//{{{ETM}}}component")
|
|
ctype=c.get("type") if c is not None else None
|
|
if not ctype: # repli : deduire du nom de fichier
|
|
stem=os.path.basename(fn)[:-4]
|
|
for pre in ("symbol-","block-"):
|
|
if stem.startswith(pre): stem=stem[len(pre):]
|
|
ctype=stem.replace("-","_")
|
|
terms={}; labels={}
|
|
def walk(el,M):
|
|
M=comp(M,parse_tf(el.get("transform")))
|
|
lab=el.get(f"{{{INK}}}label"); p=pos(el)
|
|
# inkscape:label term:/lbl:
|
|
if lab and p:
|
|
x,y=app(M,*p)
|
|
if lab.startswith("term:"): terms[lab[5:]]={"x":x,"y":y}
|
|
elif lab.startswith("lbl:"):
|
|
anchor=(el.get("text-anchor") or "start")
|
|
labels[lab[4:]]={"x":x,"y":y,"anchor":anchor}
|
|
# repli etm:terminal / etm:label
|
|
et=el.get(f"{{{ETM}}}terminal")
|
|
if et and p and et not in terms: terms[et]=dict(zip(("x","y"),app(M,*p)))
|
|
el_lbl=el.get(f"{{{ETM}}}label")
|
|
if el_lbl and p and el_lbl not in labels:
|
|
x,y=app(M,*p); labels[el_lbl]={"x":x,"y":y,"anchor":el.get("text-anchor") or "start"}
|
|
for ch in el: walk(ch,M)
|
|
walk(root,[1,0,0,1,0,0])
|
|
lib[fn]={"type":ctype,"terminals":terms,"labels":labels}
|
|
|
|
json.dump(lib, open("library.json","w"), indent=2, ensure_ascii=False)
|
|
# rapport
|
|
print(f"{'fichier':30} {'type':14} terminaux / labels")
|
|
for fn,d in lib.items():
|
|
t=",".join(d["terminals"]) or "—"
|
|
l=",".join(d["labels"]) or "—"
|
|
miss="" if d["type"] else " [TYPE MANQUANT]"
|
|
print(f"{fn:30} {str(d['type']):14} T[{t}] L[{l}]{miss}")
|