Add tmtheme support
This commit is contained in:
parent
2f0a21abf9
commit
ba4cafa3a4
5 changed files with 82 additions and 9 deletions
|
|
@ -194,7 +194,7 @@ class LocalLabel(TextMixin):
|
|||
return (0, -2*self.line_width)
|
||||
|
||||
def to_svg(self, colorscheme=Colorscheme.KiCad):
|
||||
yield from TextMixin.to_svg(self, colorscheme.text)
|
||||
yield from TextMixin.to_svg(self, colorscheme.labels)
|
||||
|
||||
|
||||
def label_shape_path_d(shape, w, h):
|
||||
|
|
@ -231,7 +231,7 @@ class GlobalLabel(TextMixin):
|
|||
properties: List(Property) = field(default_factory=list)
|
||||
|
||||
def to_svg(self, colorscheme=Colorscheme.KiCad):
|
||||
text = super(TextMixin, self).to_svg(colorscheme.text),
|
||||
text = super(TextMixin, self).to_svg(colorscheme.labels),
|
||||
text.attrs['transform'] = f'translate({self.size*0.6:.3f} 0)'
|
||||
(x1, y1), (x2, y2) = self.bounding_box()
|
||||
frame = Tag('path', fill='none', stroke_width=0.254, stroke=colorscheme.lines,
|
||||
|
|
@ -249,7 +249,7 @@ class HierarchicalLabel(TextMixin):
|
|||
uuid: UUID = field(default_factory=UUID)
|
||||
|
||||
def to_svg(self, colorscheme=Colorscheme.KiCad):
|
||||
text, = TextMixin.to_svg(self, colorscheme.text),
|
||||
text, = TextMixin.to_svg(self, colorscheme.labels),
|
||||
text.attrs['transform'] = f'translate({self.size*1.2:.3f} 0)'
|
||||
frame = Tag('path', fill='none', stroke_width=0.254, stroke=colorscheme.lines,
|
||||
d=label_shape_path_d(self.shape, self.size, self.size))
|
||||
|
|
@ -332,7 +332,7 @@ class DrawnProperty(TextMixin):
|
|||
|
||||
def to_svg(self, colorscheme=Colorscheme.KiCad):
|
||||
if not self.hide:
|
||||
yield from TextMixin.to_svg(self, colorscheme.text)
|
||||
yield from TextMixin.to_svg(self, colorscheme.values)
|
||||
|
||||
|
||||
@sexp_type('symbol')
|
||||
|
|
@ -418,7 +418,7 @@ class SymbolInstance:
|
|||
yield Tag('g', children=children, transform=at_xform, fill=colorscheme.fill, stroke=colorscheme.lines)
|
||||
|
||||
for prop in self.properties:
|
||||
yield from prop.to_svg()
|
||||
yield from prop.to_svg(colorscheme)
|
||||
|
||||
|
||||
@sexp_type('path')
|
||||
|
|
@ -627,12 +627,13 @@ class Schematic:
|
|||
for elem in self.elements:
|
||||
children += elem.to_svg(colorscheme)
|
||||
w, h = KICAD_PAPER_SIZES[self.page_settings.page_format]
|
||||
return setup_svg(children, ((0, 0), (w, h)))
|
||||
return setup_svg(children, ((0, 0), (w, h)), pagecolor=colorscheme.background)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
from ...layers import LayerStack
|
||||
from .tmtheme import TmThemeSchematic
|
||||
sch = Schematic.open(sys.argv[1])
|
||||
print('Loaded schematic with', len(sch.wires), 'wires and', len(sch.symbols), 'symbols.')
|
||||
for subsh in sch.subsheets:
|
||||
|
|
@ -640,5 +641,5 @@ if __name__ == '__main__':
|
|||
print('Loaded sub-sheet with', len(subsh.wires), 'wires and', len(subsh.symbols), 'symbols.')
|
||||
|
||||
sch.write('/tmp/test.kicad_sch')
|
||||
Path('/tmp/test.svg').write_text(str(sch.to_svg()))
|
||||
Path('/tmp/test.svg').write_text(str(sch.to_svg(TmThemeSchematic(Path('/tmp/witchhazelhypercolor.tmTheme').read_text()))))
|
||||
|
||||
|
|
|
|||
|
|
@ -9,4 +9,5 @@ class Colorscheme:
|
|||
values = 'black'
|
||||
labels = 'black'
|
||||
fill = '#cccccc'
|
||||
background = 'white'
|
||||
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ class Pin:
|
|||
h_align=h_align,
|
||||
v_align='middle',
|
||||
rotation=-frot,
|
||||
stroke=colorscheme.text,
|
||||
stroke=colorscheme.pin_names,
|
||||
transform=f'translate({lx:.3f} {ly:.3f})',
|
||||
scale=(sx, sy),
|
||||
mirror=(False, False),
|
||||
|
|
@ -211,7 +211,7 @@ class Pin:
|
|||
h_align={'left': 'right', 'right': 'left'}[h_align],
|
||||
v_align='bottom',
|
||||
rotation=-frot,
|
||||
stroke=colorscheme.text,
|
||||
stroke=colorscheme.pin_numbers,
|
||||
scale=(sx, sy),
|
||||
transform=f'translate({lx:.3f} {ly:.3f})',
|
||||
mirror=(False, False),
|
||||
|
|
|
|||
70
gerbonara/cad/kicad/tmtheme.py
Normal file
70
gerbonara/cad/kicad/tmtheme.py
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
|
||||
from xml.etree import ElementTree
|
||||
import base64
|
||||
from pathlib import Path
|
||||
|
||||
def _map_primitive(element):
|
||||
match element.tag:
|
||||
case 'data':
|
||||
return base64.b64decode(element.text)
|
||||
case 'date':
|
||||
return element.text
|
||||
case 'true':
|
||||
return True
|
||||
case 'false':
|
||||
return False
|
||||
case 'real':
|
||||
return float(element.text)
|
||||
case 'integer':
|
||||
return int(element.text)
|
||||
case 'string':
|
||||
return element.text
|
||||
case 'array':
|
||||
return [_map_primitive(child) for child in element]
|
||||
case 'dict':
|
||||
children = list(element)
|
||||
return {k.text: _map_primitive(v) for k, v in zip(children[0::2], children[1::2])}
|
||||
|
||||
|
||||
def parse_shitty_json(data):
|
||||
# Parse apple plist XML
|
||||
root = ElementTree.fromstring(data)
|
||||
return _map_primitive(root[0])
|
||||
|
||||
class TmThemeSchematic:
|
||||
def __init__(self, data):
|
||||
self.theme = parse_shitty_json(data)
|
||||
s = self.theme['settings'][0]['settings']
|
||||
by_scope = {}
|
||||
for elem in self.theme['settings']:
|
||||
if 'scope' not in elem:
|
||||
continue
|
||||
for scope in elem['scope'].split(','):
|
||||
by_scope[scope.strip()] = elem.get('settings', {})
|
||||
|
||||
def lookup(default, *scopes):
|
||||
for scope in scopes:
|
||||
if not (elem := by_scope.get(scope)):
|
||||
continue
|
||||
|
||||
if 'foreground' not in elem:
|
||||
continue
|
||||
|
||||
return elem['foreground']
|
||||
return default
|
||||
|
||||
self.background = s.get('background', 'white')
|
||||
self.bus = lookup('black', 'constant.other', 'storage.type')
|
||||
self.wire = self.lines = lookup('black', 'constant.other')
|
||||
self.no_connect = lookup('black', 'constant.language', 'variable')
|
||||
self.text = lookup('black', 'constant.numeric', 'constant.numeric.hex', 'storage.type.number')
|
||||
self.pin_numbers = lookup('black', 'constant.character', 'constant.other')
|
||||
self.pin_names = lookup('black', 'constant.character.format.placeholder', 'constant.other.placeholder')
|
||||
self.values = lookup('black', 'constant.character.format.placeholder', 'constant.other.placeholder')
|
||||
self.labels = lookup('black', 'constant.numeric', 'constant.numeric.hex', 'storage.type.number')
|
||||
self.fill = s.get('background')
|
||||
print(f'{self.background=} {self.wire=} {self.bus=} {self.lines=} {self.no_connect=} {self.labels=} {self.fill=}')
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(parse_shitty_json(Path('/tmp/witchhazelhypercolor.tmTheme').read_text()))
|
||||
|
||||
|
|
@ -523,6 +523,7 @@ def setup_svg(tags, bounds, margin=0, arg_unit=MM, svg_unit=MM, pagecolor='white
|
|||
return tag('svg', tags,
|
||||
width=f'{w}{svg_unit}', height=f'{h}{svg_unit}',
|
||||
viewBox=f'{min_x} {min_y} {w} {h}',
|
||||
style=f'background-color:{pagecolor}',
|
||||
**namespaces,
|
||||
root=True)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue