summaryrefslogtreecommitdiff
path: root/gerbonara/cad
diff options
context:
space:
mode:
authorjaseg <git@jaseg.de>2023-07-22 14:25:18 +0200
committerjaseg <git@jaseg.de>2023-07-22 14:25:18 +0200
commitba4cafa3a43f3b6655e2cbfbc35d2505f0efccb1 (patch)
tree02a9314496f8a90d3e5a9d83fe86bbc2281c5c5f /gerbonara/cad
parent2f0a21abf937f97c4b1fd10a6574e53ddcd4d7cf (diff)
downloadgerbonara-ba4cafa3a43f3b6655e2cbfbc35d2505f0efccb1.tar.gz
gerbonara-ba4cafa3a43f3b6655e2cbfbc35d2505f0efccb1.tar.bz2
gerbonara-ba4cafa3a43f3b6655e2cbfbc35d2505f0efccb1.zip
Add tmtheme support
Diffstat (limited to 'gerbonara/cad')
-rw-r--r--gerbonara/cad/kicad/schematic.py15
-rw-r--r--gerbonara/cad/kicad/schematic_colors.py1
-rw-r--r--gerbonara/cad/kicad/symbols.py4
-rw-r--r--gerbonara/cad/kicad/tmtheme.py70
4 files changed, 81 insertions, 9 deletions
diff --git a/gerbonara/cad/kicad/schematic.py b/gerbonara/cad/kicad/schematic.py
index 0fce9ad..b267743 100644
--- a/gerbonara/cad/kicad/schematic.py
+++ b/gerbonara/cad/kicad/schematic.py
@@ -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()))))
diff --git a/gerbonara/cad/kicad/schematic_colors.py b/gerbonara/cad/kicad/schematic_colors.py
index 4bcbe7b..d38a88d 100644
--- a/gerbonara/cad/kicad/schematic_colors.py
+++ b/gerbonara/cad/kicad/schematic_colors.py
@@ -9,4 +9,5 @@ class Colorscheme:
values = 'black'
labels = 'black'
fill = '#cccccc'
+ background = 'white'
diff --git a/gerbonara/cad/kicad/symbols.py b/gerbonara/cad/kicad/symbols.py
index 5130b29..45f8ec0 100644
--- a/gerbonara/cad/kicad/symbols.py
+++ b/gerbonara/cad/kicad/symbols.py
@@ -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),
diff --git a/gerbonara/cad/kicad/tmtheme.py b/gerbonara/cad/kicad/tmtheme.py
new file mode 100644
index 0000000..52d9afd
--- /dev/null
+++ b/gerbonara/cad/kicad/tmtheme.py
@@ -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()))
+