Add tmtheme support

This commit is contained in:
jaseg 2023-07-22 14:25:18 +02:00
parent 2f0a21abf9
commit ba4cafa3a4
5 changed files with 82 additions and 9 deletions

View file

@ -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()))))

View file

@ -9,4 +9,5 @@ class Colorscheme:
values = 'black'
labels = 'black'
fill = '#cccccc'
background = 'white'

View file

@ -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),

View 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()))

View file

@ -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)