diff --git a/backend/src/spicebook/engine/schematic.py b/backend/src/spicebook/engine/schematic.py index b72caee..460e646 100644 --- a/backend/src/spicebook/engine/schematic.py +++ b/backend/src/spicebook/engine/schematic.py @@ -76,9 +76,9 @@ SUPPLY_NAMES = {"vcc", "vdd", "vee", "vss"} _LABEL_OFST = 0.5 # general label offset from component body _LABEL_OFST_TIGHT = 0.2 # horizontal single-component paths _NET_LABEL_FONTSIZE = 10 # net/node labels (was 8-9) -_DEVICE_LABEL_OFST = 0.4 # active device body label offset +_DEVICE_LABEL_OFST = 0.6 # active device body label offset (clear junction wires) _PARALLEL_PATH_SPACING = 4.0 # between parallel vertical paths (was 2.5) -_LEAD_STUB_LENGTH = 1.0 # clearance from transistor pin (was 0.75) +_LEAD_STUB_LENGTH = 2.0 # clearance from transistor pin to first component _INPUT_JUNCTION_LENGTH = 1.5 # base/gate junction wire (was 1.0) _VERT_CHAIN_MIN_LEN = 4.0 # minimum component length in vertical chains @@ -1555,6 +1555,33 @@ def _add_graph_paper_bg(svg_str: str, pad: float = 15.0) -> str: return ET.tostring(root, encoding="unicode") +def _add_text_halos(svg_str: str) -> str: + """Add a white halo behind all text elements so labels stay readable + over crossing wires. + + Uses paint-order: stroke first, then fill — a thick white stroke + behind the text acts as a knockout mask without adding extra elements. + """ + ET.register_namespace("", _SVG_NS) + try: + root = ET.fromstring(svg_str) + except ET.ParseError: + return svg_str + + ns = {"svg": _SVG_NS} + for text_el in root.findall(".//svg:text", ns): + style = text_el.get("style", "") + # Skip if already styled (shouldn't happen with SchemDraw output) + if "paint-order" in style: + continue + text_el.set("paint-order", "stroke fill") + text_el.set("stroke", _GRID_BG) + text_el.set("stroke-width", "4") + text_el.set("stroke-linejoin", "round") + + return ET.tostring(root, encoding="unicode") + + def annotate_svg(svg_str: str, parsed: ParsedNetlist) -> str: """Add data attributes to SVG text elements for interactive editing. @@ -1680,8 +1707,9 @@ def netlist_to_svg(netlist_text: str) -> SchematicResult: if svg is None: svg = _render_grid(parsed) - # Post-process: graph paper background, then data attributes + # Post-process: graph paper background, text halos, then data attributes svg = _add_graph_paper_bg(svg) + svg = _add_text_halos(svg) svg = annotate_svg(svg, parsed) component_map = build_component_map(parsed)