From 21ca5f7f5c2e5425f9a142961bf86b39af825bf7 Mon Sep 17 00:00:00 2001 From: jaseg Date: Fri, 21 Jul 2023 14:38:09 +0200 Subject: WIP --- gerbonara/cad/kicad/base_types.py | 79 +++++++++++++++++++-------------------- gerbonara/cad/kicad/schematic.py | 48 +++++++++++++++++++++++- gerbonara/newstroke.py | 8 ++-- 3 files changed, 89 insertions(+), 46 deletions(-) diff --git a/gerbonara/cad/kicad/base_types.py b/gerbonara/cad/kicad/base_types.py index 3d0b0c4..8243c07 100644 --- a/gerbonara/cad/kicad/base_types.py +++ b/gerbonara/cad/kicad/base_types.py @@ -325,9 +325,33 @@ class TextMixin: for line in self.render(): yield f'M {line.x1:.3f} {line.y1:.3f} L {line.x2:.3f} {line.y2:.3f}' - def to_svg(self, color='black'): - d = ' '.join(self.svg_path_data()) - yield Tag('path', d=d, fill='none', stroke=color, stroke_width=f'{self.line_width:.3f}', stroke_linecap='round') + @property + def default_v_align(self): + return 'bottom' + + @property + def h_align(self): + return 'left' if self.effects.justify.h else 'center' + + def to_svg(self, color='black', variables={}): + if not self.effects or self.effects.hide or not self.effects.font: + return + + font = Newstroke.load() + text = string.Template(self.text).safe_substitute(variables) + aperture = ap.CircleAperture(self.line_width or 0.2, unit=MM) + if text == 'H3LIS100DL': + print(text, self.rotation, self.at, self.effects) + yield font.render_svg(text, + size=self.size or 1.27, + rotation=self.rotation, + h_align=self.h_align, + v_align=self.effects.justify.v or self.default_v_align, + stroke=color, + stroke_width=f'{self.line_width:.3f}', + scale=(1,1), + transform=f'translate({self.at.x:.3f} {self.at.y:.3f})', + ) @property def _text_offset(self): @@ -343,50 +367,23 @@ class TextMixin: font = Newstroke.load() text = string.Template(self.text).safe_substitute(variables) - strokes = list(font.render(text, size=self.size)) - min_x = min(x for st in strokes for x, y in st) - min_y = min(y for st in strokes for x, y in st) - max_x = max(x for st in strokes for x, y in st) - max_y = max(y for st in strokes for x, y in st) - w = max_x - min_x - h = max_y - min_y - - h_just = self.effects.justify.h if self.effects.justify else None - v_just = self.effects.justify.v if self.effects.justify else None - - rot = self.rotation - # KiCad already flips h_just in these cases, making the rotation param redundant. - if rot == 180: - rot = 0 - - if rot == 270 and self.at.rotation != 270: - h_just = {Atom.right: Atom.left, Atom.left: Atom.right}.get(h_just, h_just) - - offx, offy = self._text_offset - - offx += -min_x + { - None: -w/2, - Atom.right: -w, - Atom.left: 0 - }[h_just] - - offy += { - None: self.size/2, - Atom.top: self.size, - Atom.bottom: 0 - }[v_just] - aperture = ap.CircleAperture(self.line_width or 0.2, unit=MM) - for stroke in strokes: - out = [] - + for stroke in font.render(text, + x0=self.at.x, y=self.at.y, + size=self.size or 1.27, + h_align=self.effects.justify.h_str, + v_align=self.effects.justify.v_str, + rotation=self.at.rotation, + ): + + points = [] for x, y in stroke: x, y = x+offx, y+offy x, y = rotate_point(x, y, math.radians(-rot or 0)) x, y = x+self.at.x, y+self.at.y - out.append((x, y)) + points.append((x, y)) - for p1, p2 in zip(out[:-1], out[1:]): + for p1, p2 in zip(points[:-1], points[1:]): yield go.Line(*p1, *p2, aperture=aperture, unit=MM) diff --git a/gerbonara/cad/kicad/schematic.py b/gerbonara/cad/kicad/schematic.py index 00272dd..cb945a2 100644 --- a/gerbonara/cad/kicad/schematic.py +++ b/gerbonara/cad/kicad/schematic.py @@ -302,9 +302,26 @@ class DrawnProperty(TextMixin): def text(self, value): self.value = value + @property + def default_v_align(self): + return 'middle' + + @property + def h_align(self): + return self.effects.justify.h_str + @property def rotation(self): - return self.parent.rotation + self.at.rotation + rot = -self.at.rotation + rot += getattr(self.parent.at, 'rotation', 0) + if getattr(self.parent, 'reference', None) == 'C13': + print(self.value, self.at, self.parent.at, self.parent.mirror) + if hasattr(self.parent, 'mirror'): + if self.parent.mirror.y and rot in (90, 270): + rot = (rot+180)%360 + if self.parent.mirror.x and rot in (0, 180): + rot = (rot+180)%360 + return rot%360 def to_svg(self, colorscheme=Colorscheme.KiCad): if not self.hide: @@ -336,6 +353,35 @@ class SymbolInstance: def __after_parse__(self, parent): self.schematic = parent + @property + def reference(self): + return self['Reference'].value + + @reference.setter + def reference(self, value): + self['Reference'].value = value + + @property + def value(self): + return self['Value'].value + + @value.setter + def value(self, value): + self['Value'].value = value + + @property + def footprint(self): + return self['Footprint'].value + + @footprint.setter + def footprint(self, value): + self['Footprint'].value = value + + def __getitem__(self, key): + for prop in self.properties: + if prop.key == key: + return prop + @property def rotation(self): return self.at.rotation diff --git a/gerbonara/newstroke.py b/gerbonara/newstroke.py index 247b674..d0ed951 100644 --- a/gerbonara/newstroke.py +++ b/gerbonara/newstroke.py @@ -58,9 +58,9 @@ class Newstroke: raise ValueError(f'Invalid h_align value "{h_align}"') if v_align == 'top': - aly = -1.2*size + aly = sy*1.2*size elif v_align == 'middle': - aly = -1.2*size/2 + aly = sy*1.2*size/2 elif v_align != 'bottom': raise ValueError(f'Invalid v_align value "{v_align}"') @@ -77,7 +77,7 @@ class Newstroke: x += glyph_w*size - def render_svg(self, text, size=1.0, x0=0, y0=0, rotation=0, h_align='left', v_align='bottom', space_width=DEFAULT_SPACE_WIDTH, char_gap=DEFAULT_CHAR_GAP, **svg_attrs): + def render_svg(self, text, size=1.0, x0=0, y0=0, rotation=0, h_align='left', v_align='bottom', space_width=DEFAULT_SPACE_WIDTH, char_gap=DEFAULT_CHAR_GAP, scale=(1, -1), **svg_attrs): if 'stroke_linecap' not in svg_attrs: svg_attrs['stroke_linecap'] = 'round' if 'stroke_linejoin' not in svg_attrs: @@ -89,7 +89,7 @@ class Newstroke: strokes = ['M ' + ' L '.join(f'{x:.3f} {y:.3f}' for x, y in stroke) for stroke in self.render(text, size=size, x0=x0, y0=y0, rotation=rotation, h_align=h_align, v_align=v_align, space_width=space_width, char_gap=char_gap, - scale=(1, -1))] + scale=scale)] return Tag('path', d=' '.join(strokes), **svg_attrs) def bounding_box(self, text, size=1.0, space_width=DEFAULT_SPACE_WIDTH, char_gap=DEFAULT_CHAR_GAP): -- cgit