circuit-to-svg 0.0.65 → 0.0.67

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -972,6 +972,7 @@ var colorMap = {
972
972
  sheet_name: "rgb(0, 100, 100)",
973
973
  value: "rgb(0, 100, 100)",
974
974
  wire: "rgb(0, 150, 0)",
975
+ wire_crossing: "rgb(30, 180, 30)",
975
976
  worksheet: "rgb(132, 0, 0)"
976
977
  }
977
978
  };
@@ -1259,8 +1260,11 @@ function pointPairsToMatrix(a1, a2, b1, b2) {
1259
1260
 
1260
1261
  // lib/utils/get-sch-font-size.ts
1261
1262
  import "transformation-matrix";
1262
- var getSchFontSize = (transform, textType) => {
1263
- return Math.abs(transform.a) * (textType === "pin_number" ? 0.15 : 0.18);
1263
+ var getSchMmFontSize = (textType) => {
1264
+ return textType === "pin_number" ? 0.15 : 0.18;
1265
+ };
1266
+ var getSchScreenFontSize = (transform, textType) => {
1267
+ return Math.abs(transform.a) * getSchMmFontSize(textType);
1264
1268
  };
1265
1269
 
1266
1270
  // lib/sch/svg-object-fns/create-svg-objects-from-sch-component-with-symbol.ts
@@ -1357,7 +1361,7 @@ var createSvgObjectsFromSchematicComponentWithSymbol = ({
1357
1361
  "dominant-baseline": ninePointAnchorToDominantBaseline[text.anchor],
1358
1362
  "text-anchor": ninePointAnchorToTextAnchor[text.anchor],
1359
1363
  "font-family": "sans-serif",
1360
- "font-size": `${getSchFontSize(realToScreenTransform, "reference_designator")}px`
1364
+ "font-size": `${getSchScreenFontSize(realToScreenTransform, "reference_designator")}px`
1361
1365
  },
1362
1366
  value: "",
1363
1367
  children: [
@@ -1551,7 +1555,7 @@ var createSvgObjectsForSchPortPinNumberText = (params) => {
1551
1555
  fill: colorMap.schematic.pin_number,
1552
1556
  "text-anchor": "middle",
1553
1557
  "dominant-baseline": "auto",
1554
- "font-size": `${getSchFontSize(transform, "pin_number")}px`,
1558
+ "font-size": `${getSchScreenFontSize(transform, "pin_number")}px`,
1555
1559
  transform: schPort.side_of_component === "top" || schPort.side_of_component === "bottom" ? `rotate(-90 ${screenPinNumberTextPos.x} ${screenPinNumberTextPos.y})` : ""
1556
1560
  },
1557
1561
  children: [
@@ -1597,7 +1601,7 @@ var createSvgObjectsForSchPortPinLabel = (params) => {
1597
1601
  fill: colorMap.schematic.pin_number,
1598
1602
  "text-anchor": schPort.side_of_component === "left" || schPort.side_of_component === "bottom" ? "start" : "end",
1599
1603
  "dominant-baseline": "middle",
1600
- "font-size": `${getSchFontSize(transform, "pin_number")}px`,
1604
+ "font-size": `${getSchScreenFontSize(transform, "pin_number")}px`,
1601
1605
  transform: schPort.side_of_component === "top" || schPort.side_of_component === "bottom" ? `rotate(-90 ${screenPinNumberTextPos.x} ${screenPinNumberTextPos.y})` : ""
1602
1606
  },
1603
1607
  children: [
@@ -1663,7 +1667,7 @@ var createSvgObjectsFromSchematicComponentWithBox = ({
1663
1667
  y: schComponent.center.y + schComponent.size.height / 2 + 0.5
1664
1668
  // Above the component top edge
1665
1669
  });
1666
- const fontSizePx = getSchFontSize(transform, "manufacturer_number");
1670
+ const fontSizePx = getSchScreenFontSize(transform, "manufacturer_number");
1667
1671
  if (srcComponent?.manufacturer_part_number) {
1668
1672
  svgObjects.push({
1669
1673
  name: "text",
@@ -1863,9 +1867,11 @@ import { applyToPoint as applyToPoint22 } from "transformation-matrix";
1863
1867
  function createSchematicTrace(trace, transform) {
1864
1868
  const edges = trace.edges;
1865
1869
  if (edges.length === 0) return [];
1870
+ const svgObjects = [];
1866
1871
  let path = "";
1867
1872
  for (let edgeIndex = 0; edgeIndex < edges.length; edgeIndex++) {
1868
1873
  const edge = edges[edgeIndex];
1874
+ if (edge.is_crossing) continue;
1869
1875
  const [screenFromX, screenFromY] = applyToPoint22(transform, [
1870
1876
  edge.from.x,
1871
1877
  edge.from.y
@@ -1874,31 +1880,61 @@ function createSchematicTrace(trace, transform) {
1874
1880
  edge.to.x,
1875
1881
  edge.to.y
1876
1882
  ]);
1877
- if (edge.is_crossing) {
1878
- const midX = (screenFromX + screenToX) / 2;
1879
- const midY = (screenFromY + screenToY) / 2;
1880
- const dx = screenToX - screenFromX;
1881
- const dy = screenToY - screenFromY;
1882
- const len = Math.sqrt(dx * dx + dy * dy);
1883
- const hopHeight = len * 0.7;
1884
- const perpX = -dy / len * hopHeight;
1885
- const perpY = dx / len * hopHeight;
1886
- const controlX = midX + perpX;
1887
- const controlY = midY - Math.abs(perpY);
1888
- if (edgeIndex === 0) {
1889
- path += `M ${screenFromX} ${screenFromY} Q ${controlX} ${controlY} ${screenToX} ${screenToY}`;
1890
- } else {
1891
- path += ` Q ${controlX} ${controlY} ${screenToX} ${screenToY}`;
1892
- }
1893
- }
1894
- if (edgeIndex === 0) {
1883
+ if (edgeIndex === 0 || edges[edgeIndex - 1]?.is_crossing) {
1895
1884
  path += `M ${screenFromX} ${screenFromY} L ${screenToX} ${screenToY}`;
1896
1885
  } else {
1897
1886
  path += ` L ${screenToX} ${screenToY}`;
1898
1887
  }
1899
1888
  }
1900
- return path ? [
1901
- {
1889
+ for (const edge of edges) {
1890
+ if (!edge.is_crossing) continue;
1891
+ const [screenFromX, screenFromY] = applyToPoint22(transform, [
1892
+ edge.from.x,
1893
+ edge.from.y
1894
+ ]);
1895
+ const [screenToX, screenToY] = applyToPoint22(transform, [
1896
+ edge.to.x,
1897
+ edge.to.y
1898
+ ]);
1899
+ const midX = (screenFromX + screenToX) / 2;
1900
+ const midY = (screenFromY + screenToY) / 2;
1901
+ const dx = screenToX - screenFromX;
1902
+ const dy = screenToY - screenFromY;
1903
+ const len = Math.sqrt(dx * dx + dy * dy);
1904
+ const hopHeight = len * 0.7;
1905
+ const perpX = -dy / len * hopHeight;
1906
+ const perpY = dx / len * hopHeight;
1907
+ const controlX = midX + perpX;
1908
+ const controlY = midY - Math.abs(perpY);
1909
+ svgObjects.push({
1910
+ name: "path",
1911
+ type: "element",
1912
+ attributes: {
1913
+ d: `M ${screenFromX} ${screenFromY} Q ${controlX} ${controlY} ${screenToX} ${screenToY}`,
1914
+ stroke: colorMap.schematic.background,
1915
+ fill: "none",
1916
+ "stroke-width": `${getSchStrokeSize(transform) + 1.5}px`,
1917
+ "stroke-linecap": "round"
1918
+ },
1919
+ value: "",
1920
+ children: []
1921
+ });
1922
+ svgObjects.push({
1923
+ name: "path",
1924
+ type: "element",
1925
+ attributes: {
1926
+ d: `M ${screenFromX} ${screenFromY} Q ${controlX} ${controlY} ${screenToX} ${screenToY}`,
1927
+ stroke: colorMap.schematic.wire,
1928
+ fill: "none",
1929
+ "stroke-width": `${getSchStrokeSize(transform)}px`,
1930
+ "stroke-linecap": "round"
1931
+ },
1932
+ value: "",
1933
+ children: []
1934
+ });
1935
+ }
1936
+ if (path) {
1937
+ svgObjects.push({
1902
1938
  name: "path",
1903
1939
  type: "element",
1904
1940
  attributes: {
@@ -1906,71 +1942,898 @@ function createSchematicTrace(trace, transform) {
1906
1942
  d: path,
1907
1943
  stroke: colorMap.schematic.wire,
1908
1944
  fill: "none",
1909
- "stroke-width": `${getSchStrokeSize(transform)}px`
1945
+ "stroke-width": `${getSchStrokeSize(transform)}px`,
1946
+ "stroke-linecap": "round"
1910
1947
  },
1911
1948
  value: "",
1912
1949
  children: []
1950
+ });
1951
+ }
1952
+ if (trace.junctions) {
1953
+ for (const junction of trace.junctions) {
1954
+ const [screenX, screenY] = applyToPoint22(transform, [
1955
+ junction.x,
1956
+ junction.y
1957
+ ]);
1958
+ svgObjects.push({
1959
+ name: "circle",
1960
+ type: "element",
1961
+ attributes: {
1962
+ cx: screenX.toString(),
1963
+ cy: screenY.toString(),
1964
+ r: (Math.abs(transform.a) * 0.03).toString(),
1965
+ fill: colorMap.schematic.junction
1966
+ },
1967
+ value: "",
1968
+ children: []
1969
+ });
1913
1970
  }
1914
- ] : [];
1971
+ }
1972
+ return svgObjects;
1915
1973
  }
1916
1974
 
1917
1975
  // lib/sch/svg-object-fns/create-svg-objects-for-sch-net-label.ts
1918
- import { applyToPoint as applyToPoint23 } from "transformation-matrix";
1919
- var createSvgObjectsForSchNetLabel = (schNetLabel, transform) => {
1920
- const svgObjects = [];
1921
- const screenPos = applyToPoint23(transform, schNetLabel.center);
1922
- const fontSize = getSchFontSize(transform, "net_label");
1923
- const textWidth = (schNetLabel.text?.length || 0) * fontSize * 0.7;
1924
- const padding = fontSize * 0.5;
1925
- const screenLabelHeight = fontSize * 1.2;
1926
- const screenArrowPoint = fontSize * 0.3;
1927
- const screenLabelWidth = textWidth + padding * 2 + screenArrowPoint;
1928
- let rotation = 0;
1929
- let baseX = screenPos.x;
1930
- let baseY = screenPos.y;
1931
- switch (schNetLabel.anchor_side) {
1932
- case "left":
1933
- rotation = 0;
1934
- break;
1935
- case "right":
1936
- rotation = 180;
1937
- baseX -= screenLabelWidth;
1938
- break;
1939
- case "top":
1940
- rotation = -90;
1941
- baseX -= screenLabelHeight / 2;
1942
- baseY += screenLabelWidth / 2;
1943
- break;
1944
- case "bottom":
1945
- rotation = 90;
1946
- baseX -= screenLabelHeight / 2;
1947
- baseY -= screenLabelWidth / 2;
1948
- break;
1949
- default:
1950
- rotation = 0;
1976
+ import {
1977
+ applyToPoint as applyToPoint23,
1978
+ compose as compose6,
1979
+ rotate as rotate3,
1980
+ scale as scale3,
1981
+ translate as translate6
1982
+ } from "transformation-matrix";
1983
+
1984
+ // lib/sch/arial-text-metrics.ts
1985
+ var arialTextMetrics = {
1986
+ "0": {
1987
+ width: 13,
1988
+ height: 27,
1989
+ ascent: 22,
1990
+ descent: 5,
1991
+ left: -1,
1992
+ right: 12
1993
+ },
1994
+ "1": {
1995
+ width: 13,
1996
+ height: 27,
1997
+ ascent: 22,
1998
+ descent: 5,
1999
+ left: -3,
2000
+ right: 9
2001
+ },
2002
+ "2": {
2003
+ width: 13,
2004
+ height: 27,
2005
+ ascent: 22,
2006
+ descent: 5,
2007
+ left: -1,
2008
+ right: 12
2009
+ },
2010
+ "3": {
2011
+ width: 13,
2012
+ height: 27,
2013
+ ascent: 22,
2014
+ descent: 5,
2015
+ left: -1,
2016
+ right: 12
2017
+ },
2018
+ "4": {
2019
+ width: 13,
2020
+ height: 27,
2021
+ ascent: 22,
2022
+ descent: 5,
2023
+ left: 0,
2024
+ right: 12
2025
+ },
2026
+ "5": {
2027
+ width: 13,
2028
+ height: 27,
2029
+ ascent: 22,
2030
+ descent: 5,
2031
+ left: -1,
2032
+ right: 12
2033
+ },
2034
+ "6": {
2035
+ width: 13,
2036
+ height: 27,
2037
+ ascent: 22,
2038
+ descent: 5,
2039
+ left: -1,
2040
+ right: 12
2041
+ },
2042
+ "7": {
2043
+ width: 13,
2044
+ height: 27,
2045
+ ascent: 22,
2046
+ descent: 5,
2047
+ left: -1,
2048
+ right: 12
2049
+ },
2050
+ "8": {
2051
+ width: 13,
2052
+ height: 27,
2053
+ ascent: 22,
2054
+ descent: 5,
2055
+ left: -1,
2056
+ right: 12
2057
+ },
2058
+ "9": {
2059
+ width: 13,
2060
+ height: 27,
2061
+ ascent: 22,
2062
+ descent: 5,
2063
+ left: -1,
2064
+ right: 12
2065
+ },
2066
+ " ": {
2067
+ width: 7,
2068
+ height: 27,
2069
+ ascent: 22,
2070
+ descent: 5,
2071
+ left: 0,
2072
+ right: 0
2073
+ },
2074
+ "!": {
2075
+ width: 7,
2076
+ height: 27,
2077
+ ascent: 22,
2078
+ descent: 5,
2079
+ left: -2,
2080
+ right: 5
2081
+ },
2082
+ '"': {
2083
+ width: 9,
2084
+ height: 27,
2085
+ ascent: 22,
2086
+ descent: 5,
2087
+ left: -1,
2088
+ right: 7
2089
+ },
2090
+ "#": {
2091
+ width: 13,
2092
+ height: 27,
2093
+ ascent: 22,
2094
+ descent: 5,
2095
+ left: 0,
2096
+ right: 13
2097
+ },
2098
+ $: {
2099
+ width: 13,
2100
+ height: 27,
2101
+ ascent: 22,
2102
+ descent: 5,
2103
+ left: -1,
2104
+ right: 12
2105
+ },
2106
+ "%": {
2107
+ width: 21,
2108
+ height: 27,
2109
+ ascent: 22,
2110
+ descent: 5,
2111
+ left: -1,
2112
+ right: 20
2113
+ },
2114
+ "&": {
2115
+ width: 16,
2116
+ height: 27,
2117
+ ascent: 22,
2118
+ descent: 5,
2119
+ left: -1,
2120
+ right: 15
2121
+ },
2122
+ "'": {
2123
+ width: 5,
2124
+ height: 27,
2125
+ ascent: 22,
2126
+ descent: 5,
2127
+ left: -1,
2128
+ right: 3
2129
+ },
2130
+ "(": {
2131
+ width: 8,
2132
+ height: 27,
2133
+ ascent: 22,
2134
+ descent: 5,
2135
+ left: -1,
2136
+ right: 7
2137
+ },
2138
+ ")": {
2139
+ width: 8,
2140
+ height: 27,
2141
+ ascent: 22,
2142
+ descent: 5,
2143
+ left: -1,
2144
+ right: 7
2145
+ },
2146
+ "*": {
2147
+ width: 9,
2148
+ height: 27,
2149
+ ascent: 22,
2150
+ descent: 5,
2151
+ left: -1,
2152
+ right: 8
2153
+ },
2154
+ "+": {
2155
+ width: 14,
2156
+ height: 27,
2157
+ ascent: 22,
2158
+ descent: 5,
2159
+ left: -1,
2160
+ right: 13
2161
+ },
2162
+ ",": {
2163
+ width: 7,
2164
+ height: 27,
2165
+ ascent: 22,
2166
+ descent: 5,
2167
+ left: -2,
2168
+ right: 5
2169
+ },
2170
+ "-": {
2171
+ width: 8,
2172
+ height: 27,
2173
+ ascent: 22,
2174
+ descent: 5,
2175
+ left: -1,
2176
+ right: 7
2177
+ },
2178
+ ".": {
2179
+ width: 7,
2180
+ height: 27,
2181
+ ascent: 22,
2182
+ descent: 5,
2183
+ left: -2,
2184
+ right: 5
2185
+ },
2186
+ "/": {
2187
+ width: 7,
2188
+ height: 27,
2189
+ ascent: 22,
2190
+ descent: 5,
2191
+ left: 0,
2192
+ right: 7
2193
+ },
2194
+ ":": {
2195
+ width: 7,
2196
+ height: 27,
2197
+ ascent: 22,
2198
+ descent: 5,
2199
+ left: -2,
2200
+ right: 5
2201
+ },
2202
+ ";": {
2203
+ width: 7,
2204
+ height: 27,
2205
+ ascent: 22,
2206
+ descent: 5,
2207
+ left: -2,
2208
+ right: 5
2209
+ },
2210
+ "<": {
2211
+ width: 14,
2212
+ height: 27,
2213
+ ascent: 22,
2214
+ descent: 5,
2215
+ left: -1,
2216
+ right: 13
2217
+ },
2218
+ "=": {
2219
+ width: 14,
2220
+ height: 27,
2221
+ ascent: 22,
2222
+ descent: 5,
2223
+ left: -1,
2224
+ right: 13
2225
+ },
2226
+ ">": {
2227
+ width: 14,
2228
+ height: 27,
2229
+ ascent: 22,
2230
+ descent: 5,
2231
+ left: -1,
2232
+ right: 13
2233
+ },
2234
+ "?": {
2235
+ width: 13,
2236
+ height: 27,
2237
+ ascent: 22,
2238
+ descent: 5,
2239
+ left: -1,
2240
+ right: 12
2241
+ },
2242
+ "@": {
2243
+ width: 24,
2244
+ height: 27,
2245
+ ascent: 22,
2246
+ descent: 5,
2247
+ left: -1,
2248
+ right: 23
2249
+ },
2250
+ A: {
2251
+ width: 16,
2252
+ height: 27,
2253
+ ascent: 22,
2254
+ descent: 5,
2255
+ left: 0,
2256
+ right: 16
2257
+ },
2258
+ B: {
2259
+ width: 16,
2260
+ height: 27,
2261
+ ascent: 22,
2262
+ descent: 5,
2263
+ left: -2,
2264
+ right: 15
2265
+ },
2266
+ C: {
2267
+ width: 17,
2268
+ height: 27,
2269
+ ascent: 22,
2270
+ descent: 5,
2271
+ left: -1,
2272
+ right: 16
2273
+ },
2274
+ D: {
2275
+ width: 17,
2276
+ height: 27,
2277
+ ascent: 22,
2278
+ descent: 5,
2279
+ left: -2,
2280
+ right: 16
2281
+ },
2282
+ E: {
2283
+ width: 16,
2284
+ height: 27,
2285
+ ascent: 22,
2286
+ descent: 5,
2287
+ left: -2,
2288
+ right: 15
2289
+ },
2290
+ F: {
2291
+ width: 15,
2292
+ height: 27,
2293
+ ascent: 22,
2294
+ descent: 5,
2295
+ left: -2,
2296
+ right: 14
2297
+ },
2298
+ G: {
2299
+ width: 19,
2300
+ height: 27,
2301
+ ascent: 22,
2302
+ descent: 5,
2303
+ left: -1,
2304
+ right: 17
2305
+ },
2306
+ H: {
2307
+ width: 17,
2308
+ height: 27,
2309
+ ascent: 22,
2310
+ descent: 5,
2311
+ left: -2,
2312
+ right: 15
2313
+ },
2314
+ I: {
2315
+ width: 7,
2316
+ height: 27,
2317
+ ascent: 22,
2318
+ descent: 5,
2319
+ left: -2,
2320
+ right: 5
2321
+ },
2322
+ J: {
2323
+ width: 12,
2324
+ height: 27,
2325
+ ascent: 22,
2326
+ descent: 5,
2327
+ left: -1,
2328
+ right: 10
2329
+ },
2330
+ K: {
2331
+ width: 16,
2332
+ height: 27,
2333
+ ascent: 22,
2334
+ descent: 5,
2335
+ left: -2,
2336
+ right: 16
2337
+ },
2338
+ L: {
2339
+ width: 13,
2340
+ height: 27,
2341
+ ascent: 22,
2342
+ descent: 5,
2343
+ left: -2,
2344
+ right: 12
2345
+ },
2346
+ M: {
2347
+ width: 20,
2348
+ height: 27,
2349
+ ascent: 22,
2350
+ descent: 5,
2351
+ left: -2,
2352
+ right: 18
2353
+ },
2354
+ N: {
2355
+ width: 17,
2356
+ height: 27,
2357
+ ascent: 22,
2358
+ descent: 5,
2359
+ left: -2,
2360
+ right: 15
2361
+ },
2362
+ O: {
2363
+ width: 19,
2364
+ height: 27,
2365
+ ascent: 22,
2366
+ descent: 5,
2367
+ left: -1,
2368
+ right: 18
2369
+ },
2370
+ P: {
2371
+ width: 16,
2372
+ height: 27,
2373
+ ascent: 22,
2374
+ descent: 5,
2375
+ left: -2,
2376
+ right: 15
2377
+ },
2378
+ Q: {
2379
+ width: 19,
2380
+ height: 27,
2381
+ ascent: 22,
2382
+ descent: 5,
2383
+ left: -1,
2384
+ right: 18
2385
+ },
2386
+ R: {
2387
+ width: 17,
2388
+ height: 27,
2389
+ ascent: 22,
2390
+ descent: 5,
2391
+ left: -2,
2392
+ right: 17
2393
+ },
2394
+ S: {
2395
+ width: 16,
2396
+ height: 27,
2397
+ ascent: 22,
2398
+ descent: 5,
2399
+ left: -1,
2400
+ right: 15
2401
+ },
2402
+ T: {
2403
+ width: 15,
2404
+ height: 27,
2405
+ ascent: 22,
2406
+ descent: 5,
2407
+ left: -1,
2408
+ right: 14
2409
+ },
2410
+ U: {
2411
+ width: 17,
2412
+ height: 27,
2413
+ ascent: 22,
2414
+ descent: 5,
2415
+ left: -2,
2416
+ right: 15
2417
+ },
2418
+ V: {
2419
+ width: 16,
2420
+ height: 27,
2421
+ ascent: 22,
2422
+ descent: 5,
2423
+ left: 0,
2424
+ right: 16
2425
+ },
2426
+ W: {
2427
+ width: 23,
2428
+ height: 27,
2429
+ ascent: 22,
2430
+ descent: 5,
2431
+ left: 0,
2432
+ right: 22
2433
+ },
2434
+ X: {
2435
+ width: 16,
2436
+ height: 27,
2437
+ ascent: 22,
2438
+ descent: 5,
2439
+ left: 0,
2440
+ right: 16
2441
+ },
2442
+ Y: {
2443
+ width: 16,
2444
+ height: 27,
2445
+ ascent: 22,
2446
+ descent: 5,
2447
+ left: 0,
2448
+ right: 16
2449
+ },
2450
+ Z: {
2451
+ width: 15,
2452
+ height: 27,
2453
+ ascent: 22,
2454
+ descent: 5,
2455
+ left: 0,
2456
+ right: 14
2457
+ },
2458
+ "[": {
2459
+ width: 7,
2460
+ height: 27,
2461
+ ascent: 22,
2462
+ descent: 5,
2463
+ left: -2,
2464
+ right: 6
2465
+ },
2466
+ "\\": {
2467
+ width: 7,
2468
+ height: 27,
2469
+ ascent: 22,
2470
+ descent: 5,
2471
+ left: 0,
2472
+ right: 7
2473
+ },
2474
+ "]": {
2475
+ width: 7,
2476
+ height: 27,
2477
+ ascent: 22,
2478
+ descent: 5,
2479
+ left: 0,
2480
+ right: 5
2481
+ },
2482
+ "^": {
2483
+ width: 11,
2484
+ height: 27,
2485
+ ascent: 22,
2486
+ descent: 5,
2487
+ left: -1,
2488
+ right: 11
2489
+ },
2490
+ _: {
2491
+ width: 13,
2492
+ height: 27,
2493
+ ascent: 22,
2494
+ descent: 5,
2495
+ left: 0,
2496
+ right: 14
2497
+ },
2498
+ "`": {
2499
+ width: 8,
2500
+ height: 27,
2501
+ ascent: 22,
2502
+ descent: 5,
2503
+ left: -1,
2504
+ right: 5
2505
+ },
2506
+ a: {
2507
+ width: 13,
2508
+ height: 27,
2509
+ ascent: 22,
2510
+ descent: 5,
2511
+ left: -1,
2512
+ right: 12
2513
+ },
2514
+ b: {
2515
+ width: 13,
2516
+ height: 27,
2517
+ ascent: 22,
2518
+ descent: 5,
2519
+ left: -2,
2520
+ right: 12
2521
+ },
2522
+ c: {
2523
+ width: 12,
2524
+ height: 27,
2525
+ ascent: 22,
2526
+ descent: 5,
2527
+ left: -1,
2528
+ right: 12
2529
+ },
2530
+ d: {
2531
+ width: 13,
2532
+ height: 27,
2533
+ ascent: 22,
2534
+ descent: 5,
2535
+ left: -1,
2536
+ right: 12
2537
+ },
2538
+ e: {
2539
+ width: 13,
2540
+ height: 27,
2541
+ ascent: 22,
2542
+ descent: 5,
2543
+ left: -1,
2544
+ right: 12
2545
+ },
2546
+ f: {
2547
+ width: 7,
2548
+ height: 27,
2549
+ ascent: 22,
2550
+ descent: 5,
2551
+ left: 0,
2552
+ right: 8
2553
+ },
2554
+ g: {
2555
+ width: 13,
2556
+ height: 27,
2557
+ ascent: 22,
2558
+ descent: 5,
2559
+ left: -1,
2560
+ right: 12
2561
+ },
2562
+ h: {
2563
+ width: 13,
2564
+ height: 27,
2565
+ ascent: 22,
2566
+ descent: 5,
2567
+ left: -2,
2568
+ right: 12
2569
+ },
2570
+ i: {
2571
+ width: 5,
2572
+ height: 27,
2573
+ ascent: 22,
2574
+ descent: 5,
2575
+ left: -2,
2576
+ right: 4
2577
+ },
2578
+ j: {
2579
+ width: 5,
2580
+ height: 27,
2581
+ ascent: 22,
2582
+ descent: 5,
2583
+ left: 1,
2584
+ right: 4
2585
+ },
2586
+ k: {
2587
+ width: 12,
2588
+ height: 27,
2589
+ ascent: 22,
2590
+ descent: 5,
2591
+ left: -2,
2592
+ right: 12
2593
+ },
2594
+ l: {
2595
+ width: 5,
2596
+ height: 27,
2597
+ ascent: 22,
2598
+ descent: 5,
2599
+ left: -2,
2600
+ right: 4
2601
+ },
2602
+ m: {
2603
+ width: 20,
2604
+ height: 27,
2605
+ ascent: 22,
2606
+ descent: 5,
2607
+ left: -2,
2608
+ right: 18
2609
+ },
2610
+ n: {
2611
+ width: 13,
2612
+ height: 27,
2613
+ ascent: 22,
2614
+ descent: 5,
2615
+ left: -2,
2616
+ right: 12
2617
+ },
2618
+ o: {
2619
+ width: 13,
2620
+ height: 27,
2621
+ ascent: 22,
2622
+ descent: 5,
2623
+ left: -1,
2624
+ right: 12
2625
+ },
2626
+ p: {
2627
+ width: 13,
2628
+ height: 27,
2629
+ ascent: 22,
2630
+ descent: 5,
2631
+ left: -2,
2632
+ right: 12
2633
+ },
2634
+ q: {
2635
+ width: 13,
2636
+ height: 27,
2637
+ ascent: 22,
2638
+ descent: 5,
2639
+ left: -1,
2640
+ right: 12
2641
+ },
2642
+ r: {
2643
+ width: 8,
2644
+ height: 27,
2645
+ ascent: 22,
2646
+ descent: 5,
2647
+ left: -2,
2648
+ right: 8
2649
+ },
2650
+ s: {
2651
+ width: 12,
2652
+ height: 27,
2653
+ ascent: 22,
2654
+ descent: 5,
2655
+ left: -1,
2656
+ right: 11
2657
+ },
2658
+ t: {
2659
+ width: 7,
2660
+ height: 27,
2661
+ ascent: 22,
2662
+ descent: 5,
2663
+ left: 0,
2664
+ right: 6
2665
+ },
2666
+ u: {
2667
+ width: 13,
2668
+ height: 27,
2669
+ ascent: 22,
2670
+ descent: 5,
2671
+ left: -2,
2672
+ right: 12
2673
+ },
2674
+ v: {
2675
+ width: 12,
2676
+ height: 27,
2677
+ ascent: 22,
2678
+ descent: 5,
2679
+ left: 0,
2680
+ right: 12
2681
+ },
2682
+ w: {
2683
+ width: 17,
2684
+ height: 27,
2685
+ ascent: 22,
2686
+ descent: 5,
2687
+ left: 0,
2688
+ right: 17
2689
+ },
2690
+ x: {
2691
+ width: 12,
2692
+ height: 27,
2693
+ ascent: 22,
2694
+ descent: 5,
2695
+ left: 0,
2696
+ right: 12
2697
+ },
2698
+ y: {
2699
+ width: 12,
2700
+ height: 27,
2701
+ ascent: 22,
2702
+ descent: 5,
2703
+ left: 0,
2704
+ right: 12
2705
+ },
2706
+ z: {
2707
+ width: 12,
2708
+ height: 27,
2709
+ ascent: 22,
2710
+ descent: 5,
2711
+ left: 0,
2712
+ right: 11
2713
+ },
2714
+ "{": {
2715
+ width: 8,
2716
+ height: 27,
2717
+ ascent: 22,
2718
+ descent: 5,
2719
+ left: -1,
2720
+ right: 7
2721
+ },
2722
+ "|": {
2723
+ width: 6,
2724
+ height: 27,
2725
+ ascent: 22,
2726
+ descent: 5,
2727
+ left: -2,
2728
+ right: 4
2729
+ },
2730
+ "}": {
2731
+ width: 8,
2732
+ height: 27,
2733
+ ascent: 22,
2734
+ descent: 5,
2735
+ left: -1,
2736
+ right: 7
2737
+ },
2738
+ "~": {
2739
+ width: 14,
2740
+ height: 27,
2741
+ ascent: 22,
2742
+ descent: 5,
2743
+ left: -1,
2744
+ right: 13
1951
2745
  }
1952
- const transformString = `rotate(${rotation} ${screenPos.x} ${screenPos.y})`;
1953
- const points = [
1954
- { x: baseX, y: baseY },
1955
- // Left edge
1956
- { x: baseX + screenLabelWidth - screenArrowPoint, y: baseY },
1957
- // Top edge
1958
- { x: baseX + screenLabelWidth, y: baseY + screenLabelHeight / 2 },
1959
- // Arrow point
2746
+ };
2747
+
2748
+ // lib/sch/estimate-text-width.ts
2749
+ var estimateTextWidth = (text) => {
2750
+ if (!text) return 0;
2751
+ let totalWidth = 0;
2752
+ for (const char of text) {
2753
+ const metrics = arialTextMetrics[char];
2754
+ if (metrics) {
2755
+ totalWidth += metrics.width;
2756
+ } else {
2757
+ totalWidth += arialTextMetrics["?"].width;
2758
+ }
2759
+ }
2760
+ return totalWidth / 27;
2761
+ };
2762
+
2763
+ // lib/sch/svg-object-fns/create-svg-objects-for-sch-net-label.ts
2764
+ var ARROW_POINT_WIDTH_FSR = 0.3;
2765
+ var END_PADDING_FSR = 0.3;
2766
+ var END_PADDING_EXTRA_PER_CHARACTER_FSR = 0.06;
2767
+ var createSvgObjectsForSchNetLabel = (schNetLabel, realToScreenTransform) => {
2768
+ if (!schNetLabel.text) return [];
2769
+ const svgObjects = [];
2770
+ const fontSizePx = getSchScreenFontSize(realToScreenTransform, "net_label");
2771
+ const fontSizeMm = getSchMmFontSize("net_label");
2772
+ const textWidthFSR = estimateTextWidth(schNetLabel.text || "");
2773
+ const screenCenter = applyToPoint23(realToScreenTransform, schNetLabel.center);
2774
+ const realTextGrowthVec = getUnitVectorFromOutsideToEdge(
2775
+ schNetLabel.anchor_side
2776
+ );
2777
+ const screenTextGrowthVec = { ...realTextGrowthVec };
2778
+ screenTextGrowthVec.y *= -1;
2779
+ const fullWidthFsr = textWidthFSR + ARROW_POINT_WIDTH_FSR * 2 + END_PADDING_EXTRA_PER_CHARACTER_FSR * schNetLabel.text.length + END_PADDING_FSR;
2780
+ const screenAnchorPosition = schNetLabel.anchor_position ? applyToPoint23(realToScreenTransform, schNetLabel.anchor_position) : {
2781
+ x: screenCenter.x - screenTextGrowthVec.x * fullWidthFsr * fontSizePx / 2,
2782
+ y: screenCenter.y - screenTextGrowthVec.y * fullWidthFsr * fontSizePx / 2
2783
+ };
2784
+ const realAnchorPosition = schNetLabel.anchor_position ?? {
2785
+ x: schNetLabel.center.x - realTextGrowthVec.x * fullWidthFsr * fontSizeMm / 2,
2786
+ y: schNetLabel.center.y - realTextGrowthVec.y * fullWidthFsr * fontSizeMm / 2
2787
+ };
2788
+ const pathRotation = {
2789
+ left: 0,
2790
+ top: -90,
2791
+ bottom: 90,
2792
+ right: 180
2793
+ }[schNetLabel.anchor_side];
2794
+ const screenOutlinePoints = [
2795
+ // Arrow point in font-relative coordinates
1960
2796
  {
1961
- x: baseX + screenLabelWidth - screenArrowPoint,
1962
- y: baseY + screenLabelHeight
2797
+ x: 0,
2798
+ y: 0
1963
2799
  },
1964
- // Bottom after arrow
1965
- { x: baseX, y: baseY + screenLabelHeight }
1966
- // Bottom left corner
1967
- ];
2800
+ // Top left corner in font-relative coordinates
2801
+ {
2802
+ x: ARROW_POINT_WIDTH_FSR,
2803
+ y: 0.6
2804
+ },
2805
+ // Top right corner in font-relative coordinates
2806
+ {
2807
+ x: ARROW_POINT_WIDTH_FSR * 2 + END_PADDING_FSR + END_PADDING_EXTRA_PER_CHARACTER_FSR * schNetLabel.text.length + textWidthFSR,
2808
+ y: 0.6
2809
+ },
2810
+ // Bottom right corner in font-relative coordinates
2811
+ {
2812
+ x: ARROW_POINT_WIDTH_FSR * 2 + END_PADDING_FSR + END_PADDING_EXTRA_PER_CHARACTER_FSR * schNetLabel.text.length + textWidthFSR,
2813
+ y: -0.6
2814
+ },
2815
+ // Bottom left corner in font-relative coordinates
2816
+ {
2817
+ x: ARROW_POINT_WIDTH_FSR,
2818
+ y: -0.6
2819
+ }
2820
+ ].map(
2821
+ (fontRelativePoint) => applyToPoint23(
2822
+ compose6(
2823
+ realToScreenTransform,
2824
+ translate6(realAnchorPosition.x, realAnchorPosition.y),
2825
+ scale3(fontSizeMm),
2826
+ rotate3(pathRotation / 180 * Math.PI)
2827
+ ),
2828
+ fontRelativePoint
2829
+ )
2830
+ );
1968
2831
  const pathD = `
1969
- M ${points[0]?.x},${points[0]?.y}
1970
- L ${points[1]?.x},${points[1]?.y}
1971
- L ${points[2]?.x},${points[2]?.y}
1972
- L ${points[3]?.x},${points[3]?.y}
1973
- L ${points[4]?.x},${points[4]?.y}
2832
+ M ${screenOutlinePoints[0].x},${screenOutlinePoints[0].y}
2833
+ L ${screenOutlinePoints[1].x},${screenOutlinePoints[1].y}
2834
+ L ${screenOutlinePoints[2].x},${screenOutlinePoints[2].y}
2835
+ L ${screenOutlinePoints[3].x},${screenOutlinePoints[3].y}
2836
+ L ${screenOutlinePoints[4].x},${screenOutlinePoints[4].y}
1974
2837
  Z
1975
2838
  `;
1976
2839
  svgObjects.push({
@@ -1981,28 +2844,41 @@ var createSvgObjectsForSchNetLabel = (schNetLabel, transform) => {
1981
2844
  d: pathD,
1982
2845
  fill: "white",
1983
2846
  stroke: colorMap.schematic.label_global,
1984
- "stroke-width": `${getSchStrokeSize(transform)}px`,
1985
- transform: transformString
2847
+ "stroke-width": `${getSchStrokeSize(realToScreenTransform)}px`
1986
2848
  },
1987
2849
  value: "",
1988
2850
  children: []
1989
2851
  });
1990
- const screenTextX = baseX + (screenLabelWidth - screenArrowPoint) / 2;
1991
- const screenTextY = baseY + screenLabelHeight / 2 + fontSize * 0.05;
2852
+ const screenTextPos = {
2853
+ x: screenAnchorPosition.x + screenTextGrowthVec.x * fontSizePx * 0.5,
2854
+ y: screenAnchorPosition.y + screenTextGrowthVec.y * fontSizePx * 0.5
2855
+ };
2856
+ const textAnchor = {
2857
+ left: "start",
2858
+ top: "start",
2859
+ bottom: "start",
2860
+ right: "end"
2861
+ }[schNetLabel.anchor_side];
2862
+ const textTransformString = {
2863
+ left: "",
2864
+ right: "",
2865
+ top: `rotate(90 ${screenTextPos.x} ${screenTextPos.y})`,
2866
+ bottom: `rotate(-90 ${screenTextPos.x} ${screenTextPos.y})`
2867
+ }[schNetLabel.anchor_side];
1992
2868
  svgObjects.push({
1993
2869
  name: "text",
1994
2870
  type: "element",
1995
2871
  attributes: {
1996
2872
  class: "net-label-text",
1997
- x: screenTextX.toString(),
1998
- y: screenTextY.toString(),
2873
+ x: screenTextPos.x.toString(),
2874
+ y: screenTextPos.y.toString(),
1999
2875
  fill: colorMap.schematic.label_global,
2000
- "text-anchor": "middle",
2876
+ "text-anchor": textAnchor,
2001
2877
  "dominant-baseline": "central",
2002
- // Changed to central for better vertical alignment
2003
2878
  "font-family": "sans-serif",
2004
- "font-size": `${fontSize}px`,
2005
- transform: transformString
2879
+ "font-variant-numeric": "tabular-nums",
2880
+ "font-size": `${fontSizePx}px`,
2881
+ transform: textTransformString
2006
2882
  },
2007
2883
  children: [
2008
2884
  {
@@ -2073,14 +2949,6 @@ function convertCircuitJsonToSchematicSvg(circuitJson, options) {
2073
2949
  drawSchematicGrid({ bounds: realBounds, transform, ...gridConfig })
2074
2950
  );
2075
2951
  }
2076
- if (options?.labeledPoints) {
2077
- svgChildren.push(
2078
- drawSchematicLabeledPoints({
2079
- points: options.labeledPoints,
2080
- transform
2081
- })
2082
- );
2083
- }
2084
2952
  const schDebugObjectSvgs = [];
2085
2953
  const schComponentSvgs = [];
2086
2954
  const schTraceSvgs = [];
@@ -2110,6 +2978,14 @@ function convertCircuitJsonToSchematicSvg(circuitJson, options) {
2110
2978
  ...schTraceSvgs,
2111
2979
  ...schNetLabel
2112
2980
  );
2981
+ if (options?.labeledPoints) {
2982
+ svgChildren.push(
2983
+ drawSchematicLabeledPoints({
2984
+ points: options.labeledPoints,
2985
+ transform
2986
+ })
2987
+ );
2988
+ }
2113
2989
  const svgObject = {
2114
2990
  name: "svg",
2115
2991
  type: "element",