eb32cc96f2
Dia doesn't seem to support complex SVG in the .shape? Or is the problem elsewhere? Anyway, just xlinking to the SVG file yields better results, and avoids parsing the SVG ourselves, so it may be better. Rely on ImageMagick to get the aspect ratio and dimensions then. Dia supports abstract coordinates (we'll max them to 64x64).
138 lines
3.9 KiB
Python
Executable File
138 lines
3.9 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# This is free and unencumbered software released into the public domain.
|
|
|
|
from argparse import ArgumentParser
|
|
import xml.etree.ElementTree as ET
|
|
from dataclasses import dataclass
|
|
from pathlib import Path
|
|
import getpass
|
|
import subprocess
|
|
|
|
|
|
@dataclass
|
|
class Sheet:
|
|
name: str
|
|
author: str
|
|
description: str
|
|
objects: dict
|
|
|
|
|
|
def build_sheet(sheet):
|
|
xsheet = ET.Element(
|
|
'sheet',
|
|
attrib={'xmlns': 'http://www.lysator.liu.se/~alla/dia/dia-sheet-ns'}
|
|
)
|
|
if sheet.name:
|
|
ET.SubElement(xsheet, 'name').text = sheet.name
|
|
if sheet.author:
|
|
ET.SubElement(xsheet, 'created_by').text = sheet.author
|
|
if sheet.description:
|
|
ET.SubElement(xsheet, 'description').text = sheet.description
|
|
|
|
xcontents = ET.SubElement(xsheet, 'contents')
|
|
for oname, odescription in sheet.objects.items():
|
|
xobj = ET.SubElement(xcontents, 'object')
|
|
xobj.attrib['name'] = oname
|
|
ET.SubElement(xobj, 'description').text = odescription
|
|
return xsheet
|
|
|
|
|
|
def build_shape(svg_path, width, height):
|
|
attrib = {
|
|
'xmlns:svg': "http://www.w3.org/2000/svg",
|
|
'xmlns:xlink': "http://www.w3.org/1999/xlink",
|
|
'xmlns': 'http://www.daa.com.au/~james/dia-shape-ns',
|
|
}
|
|
xshape = ET.Element('shape', attrib=attrib)
|
|
ET.SubElement(xshape, 'name').text = svg_path.stem
|
|
ET.SubElement(xshape, 'icon').text = f"{svg_path.stem}.png"
|
|
|
|
xconns = ET.SubElement(xshape, 'connections')
|
|
points = [
|
|
(0, 0),
|
|
(0, width // 2),
|
|
(0, width),
|
|
(height // 2, 0),
|
|
(height, 0),
|
|
(width // 2, height),
|
|
(width, height // 2),
|
|
(width, height),
|
|
]
|
|
for x, y in points:
|
|
ET.SubElement(xconns, 'point', attrib={'x': str(x), 'y': str(y)})
|
|
|
|
ET.SubElement(xshape, 'aspectratio', attrib={'type': 'fixed'})
|
|
|
|
xsvg = ET.SubElement(xshape, 'svg:svg')
|
|
ET.SubElement(xsvg, 'svg:image', attrib={'xlink:href': str(svg_path), 'x': '0', 'y': '0', 'width': str(width), 'height': str(height)})
|
|
|
|
return xshape
|
|
|
|
|
|
def main():
|
|
aparser = ArgumentParser()
|
|
aparser.add_argument('--name', default='TODO')
|
|
aparser.add_argument('svg_file', nargs='+')
|
|
args = aparser.parse_args()
|
|
|
|
psheets = Path('sheets')
|
|
psheets.mkdir(exist_ok=True)
|
|
pshapes = Path('shapes')
|
|
pshapes.mkdir(exist_ok=True)
|
|
|
|
sheet = Sheet(
|
|
name=args.name,
|
|
author=getpass.getuser(),
|
|
description=f"TODO: fill {args.name} description",
|
|
objects={}
|
|
)
|
|
|
|
seen = set()
|
|
for svg_file in args.svg_file:
|
|
svg_file = Path(svg_file)
|
|
if svg_file.stem in seen:
|
|
print(f"ignoring duplicate {svg_file.stem}")
|
|
continue
|
|
seen.add(svg_file.stem)
|
|
|
|
png_file = f'{pshapes}/{svg_file.stem}.png'
|
|
subprocess.check_call([
|
|
'convert',
|
|
str(svg_file),
|
|
'-resize',
|
|
'64x64',
|
|
png_file,
|
|
])
|
|
print(f"wrote {png_file}")
|
|
|
|
width, height = map(int, subprocess.check_output([
|
|
'identify',
|
|
'-format',
|
|
'%w %h',
|
|
png_file,
|
|
]).decode().split())
|
|
|
|
new_path = pshapes.joinpath(f"{svg_file.stem}.svg")
|
|
new_path.write_text(svg_file.read_text())
|
|
print(f"wrote {new_path}")
|
|
|
|
xshape = build_shape(svg_file, width, height)
|
|
# ET.indent(xshape)
|
|
tshape = ET.tostring(xshape, encoding='unicode')
|
|
shape_path = pshapes.joinpath(f"{svg_file.stem}.shape")
|
|
shape_path.write_text(tshape)
|
|
print(f"wrote {shape_path}")
|
|
|
|
sheet.objects[svg_file.stem] = f"TODO: fill description for {svg_file.stem}"
|
|
|
|
xsheet = build_sheet(sheet)
|
|
# ET.indent(xsheet)
|
|
tsheet = ET.tostring(xsheet, encoding="unicode")
|
|
sheet_path = psheets.joinpath(f"{args.name}.sheet")
|
|
sheet_path.write_text(tsheet)
|
|
print(f"wrote {sheet_path}")
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|