@codehz/draw-call 0.2.1 → 0.4.0

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.
@@ -1,7 +1,9 @@
1
- import { createRequire } from "node:module";
1
+ import { DOMMatrix, Path2D, createCanvas as createCanvas$1 } from "@napi-rs/canvas";
2
2
 
3
- //#region rolldown:runtime
4
- var __require = /* @__PURE__ */ createRequire(import.meta.url);
3
+ //#region src/compat/index.ts
4
+ function createRawCanvas(width, height) {
5
+ return createCanvas$1(width, height);
6
+ }
5
7
 
6
8
  //#endregion
7
9
  //#region src/types/base.ts
@@ -1111,17 +1113,6 @@ function renderBox(ctx, node) {
1111
1113
  if (element.opacity !== void 0 && element.opacity < 1) ctx.globalAlpha = 1;
1112
1114
  }
1113
1115
 
1114
- //#endregion
1115
- //#region src/compat/DOMMatrix.ts
1116
- const DOMMatrixCompat = (() => {
1117
- if (typeof DOMMatrix !== "undefined") return DOMMatrix;
1118
- try {
1119
- return __require("@napi-rs/canvas").DOMMatrix;
1120
- } catch {
1121
- throw new Error("DOMMatrix is not available. In Node.js, install @napi-rs/canvas.");
1122
- }
1123
- })();
1124
-
1125
1116
  //#endregion
1126
1117
  //#region src/render/components/ProxiedCanvasContext.ts
1127
1118
  /**
@@ -1158,7 +1149,7 @@ var ProxiedCanvasContext = class {
1158
1149
  constructor(ctx, baseTransform) {
1159
1150
  this.ctx = ctx;
1160
1151
  this.baseTransform = baseTransform;
1161
- this.relativeTransform = new DOMMatrixCompat();
1152
+ this.relativeTransform = new DOMMatrix();
1162
1153
  }
1163
1154
  /**
1164
1155
  * save() - 保存当前状态并增加计数
@@ -1181,8 +1172,8 @@ var ProxiedCanvasContext = class {
1181
1172
  */
1182
1173
  setTransform(...args) {
1183
1174
  let matrix;
1184
- if (args.length === 1 && args[0] instanceof DOMMatrixCompat) matrix = args[0];
1185
- else if (args.length === 6) matrix = new DOMMatrixCompat([
1175
+ if (args.length === 1 && args[0] instanceof DOMMatrix) matrix = args[0];
1176
+ else if (args.length === 6) matrix = new DOMMatrix([
1186
1177
  args[0],
1187
1178
  args[1],
1188
1179
  args[2],
@@ -1405,17 +1396,6 @@ function renderRichText(ctx, node) {
1405
1396
  }
1406
1397
  }
1407
1398
 
1408
- //#endregion
1409
- //#region src/compat/Path2D.ts
1410
- const Path2DCompat = (() => {
1411
- if (typeof Path2D !== "undefined") return Path2D;
1412
- try {
1413
- return __require("@napi-rs/canvas").Path2D;
1414
- } catch {
1415
- throw new Error("Path2D is not available. In Node.js, install @napi-rs/canvas.");
1416
- }
1417
- })();
1418
-
1419
1399
  //#endregion
1420
1400
  //#region src/render/components/svg.ts
1421
1401
  function isGradientDescriptor(color) {
@@ -1453,7 +1433,7 @@ function resolveColor(ctx, color, x, y, width, height) {
1453
1433
  }
1454
1434
  function applyTransform(base, transform) {
1455
1435
  if (!transform) return base;
1456
- let result = new DOMMatrixCompat([
1436
+ let result = new DOMMatrix([
1457
1437
  base.a,
1458
1438
  base.b,
1459
1439
  base.c,
@@ -1463,7 +1443,7 @@ function applyTransform(base, transform) {
1463
1443
  ]);
1464
1444
  if (transform.matrix) {
1465
1445
  const [a, b, c, d, e, f] = transform.matrix;
1466
- result = result.multiply(new DOMMatrixCompat([
1446
+ result = result.multiply(new DOMMatrix([
1467
1447
  a,
1468
1448
  b,
1469
1449
  c,
@@ -1552,7 +1532,7 @@ function renderSvgPolygon(ctx, polygon, bounds) {
1552
1532
  applyFillAndStroke(ctx, polygon, bounds);
1553
1533
  }
1554
1534
  function renderSvgPath(ctx, path, bounds) {
1555
- const path2d = new Path2DCompat(path.d);
1535
+ const path2d = new Path2D(path.d);
1556
1536
  if (path.fill && path.fill !== "none") {
1557
1537
  ctx.fillStyle = resolveColor(ctx, path.fill, bounds.x, bounds.y, bounds.width, bounds.height);
1558
1538
  ctx.fill(path2d);
@@ -1634,7 +1614,7 @@ function calculateViewBoxTransform(x, y, width, height, viewBox, preserveAspectR
1634
1614
  const scaleY = height / vbHeight;
1635
1615
  const align = preserveAspectRatio?.align ?? "xMidYMid";
1636
1616
  const meetOrSlice = preserveAspectRatio?.meetOrSlice ?? "meet";
1637
- if (align === "none") return new DOMMatrixCompat().translate(x, y).scale(scaleX, scaleY).translate(-vbX, -vbY);
1617
+ if (align === "none") return new DOMMatrix().translate(x, y).scale(scaleX, scaleY).translate(-vbX, -vbY);
1638
1618
  const scale = meetOrSlice === "meet" ? Math.min(scaleX, scaleY) : Math.max(scaleX, scaleY);
1639
1619
  const scaledWidth = vbWidth * scale;
1640
1620
  const scaledHeight = vbHeight * scale;
@@ -1644,7 +1624,7 @@ function calculateViewBoxTransform(x, y, width, height, viewBox, preserveAspectR
1644
1624
  else if (align.includes("xMax")) translateX += width - scaledWidth;
1645
1625
  if (align.includes("YMid")) translateY += (height - scaledHeight) / 2;
1646
1626
  else if (align.includes("YMax")) translateY += height - scaledHeight;
1647
- return new DOMMatrixCompat().translate(translateX, translateY).scale(scale, scale).translate(-vbX, -vbY);
1627
+ return new DOMMatrix().translate(translateX, translateY).scale(scale, scale).translate(-vbX, -vbY);
1648
1628
  }
1649
1629
  function applyShadow(ctx, shadow) {
1650
1630
  ctx.shadowOffsetX = shadow.offsetX ?? 0;
@@ -1733,13 +1713,13 @@ function renderText(ctx, node) {
1733
1713
  * - 简易对象: { translate, rotate, scale, skewX, skewY }
1734
1714
  */
1735
1715
  function parseTransformValue(transform) {
1736
- if (transform === void 0) return new DOMMatrixCompat();
1737
- if (Array.isArray(transform)) return new DOMMatrixCompat(transform);
1716
+ if (transform === void 0) return new DOMMatrix();
1717
+ if (Array.isArray(transform)) return new DOMMatrix(transform);
1738
1718
  const hasDOMMatrixInit = "a" in transform || "b" in transform || "c" in transform || "d" in transform || "e" in transform || "f" in transform;
1739
1719
  const hasSimpleTransform = "translate" in transform || "rotate" in transform || "scale" in transform || "skewX" in transform || "skewY" in transform;
1740
1720
  if (hasDOMMatrixInit && !hasSimpleTransform) {
1741
1721
  const init = transform;
1742
- return new DOMMatrixCompat([
1722
+ return new DOMMatrix([
1743
1723
  init.a ?? 1,
1744
1724
  init.b ?? 0,
1745
1725
  init.c ?? 0,
@@ -1749,7 +1729,7 @@ function parseTransformValue(transform) {
1749
1729
  ]);
1750
1730
  }
1751
1731
  const simpleObj = transform;
1752
- let result = new DOMMatrixCompat();
1732
+ let result = new DOMMatrix();
1753
1733
  if (simpleObj.translate) result = result.translate(simpleObj.translate[0], simpleObj.translate[1]);
1754
1734
  if (simpleObj.rotate !== void 0) if (typeof simpleObj.rotate === "number") result = result.rotate(simpleObj.rotate);
1755
1735
  else {
@@ -1791,7 +1771,7 @@ function renderTransform(ctx, node) {
1791
1771
  const ox = childNode.layout.x + relativeOx;
1792
1772
  const oy = childNode.layout.y + relativeOy;
1793
1773
  const targetMatrix = parseTransformValue(element.transform);
1794
- const finalMatrix = new DOMMatrixCompat().translate(ox, oy).multiply(targetMatrix).translate(-ox, -oy);
1774
+ const finalMatrix = new DOMMatrix().translate(ox, oy).multiply(targetMatrix).translate(-ox, -oy);
1795
1775
  ctx.save();
1796
1776
  const composedTransform = ctx.getTransform().multiply(finalMatrix);
1797
1777
  ctx.setTransform(composedTransform);
@@ -1840,4 +1820,220 @@ function renderNode(ctx, node) {
1840
1820
  }
1841
1821
 
1842
1822
  //#endregion
1843
- export { radialGradient as a, linearGradient as i, computeLayout as n, createCanvasMeasureContext as r, renderNode as t };
1823
+ //#region src/canvas.ts
1824
+ /**
1825
+ * 创建适用于浏览器环境的 Canvas
1826
+ *
1827
+ * 在浏览器环境中使用,支持传入已有的 canvas 实例
1828
+ */
1829
+ function createCanvas(options) {
1830
+ const { width, height, pixelRatio = 1 } = options;
1831
+ const canvas = options.canvas ?? createRawCanvas(width * pixelRatio, height * pixelRatio);
1832
+ const ctx = canvas.getContext("2d");
1833
+ if (!ctx) throw new Error("Failed to get 2d context");
1834
+ if (options.imageSmoothingEnabled !== void 0) ctx.imageSmoothingEnabled = options.imageSmoothingEnabled;
1835
+ if (options.imageSmoothingQuality !== void 0) ctx.imageSmoothingQuality = options.imageSmoothingQuality;
1836
+ if (pixelRatio !== 1) ctx.scale(pixelRatio, pixelRatio);
1837
+ const measureCtx = createCanvasMeasureContext(ctx);
1838
+ return {
1839
+ width,
1840
+ height,
1841
+ pixelRatio,
1842
+ canvas,
1843
+ render(element) {
1844
+ const layoutTree = computeLayout(element, measureCtx, {
1845
+ minWidth: 0,
1846
+ maxWidth: width,
1847
+ minHeight: 0,
1848
+ maxHeight: height
1849
+ });
1850
+ renderNode(ctx, layoutTree);
1851
+ return layoutTree;
1852
+ },
1853
+ clear() {
1854
+ ctx.clearRect(0, 0, width, height);
1855
+ },
1856
+ getContext() {
1857
+ return ctx;
1858
+ },
1859
+ toDataURL(type, quality) {
1860
+ if ("toDataURL" in canvas && typeof canvas.toDataURL === "function") return canvas.toDataURL(type, quality);
1861
+ throw new Error("toDataURL not supported");
1862
+ },
1863
+ toBuffer(type = "image/png") {
1864
+ if ("toBuffer" in canvas && typeof canvas.toBuffer === "function") return canvas.toBuffer(type);
1865
+ throw new Error("toBuffer not supported in this environment");
1866
+ }
1867
+ };
1868
+ }
1869
+
1870
+ //#endregion
1871
+ //#region src/components/Box.ts
1872
+ function Box(props) {
1873
+ return {
1874
+ type: "box",
1875
+ ...props
1876
+ };
1877
+ }
1878
+
1879
+ //#endregion
1880
+ //#region src/components/CustomDraw.ts
1881
+ function CustomDraw(props) {
1882
+ return {
1883
+ type: "customdraw",
1884
+ ...props
1885
+ };
1886
+ }
1887
+
1888
+ //#endregion
1889
+ //#region src/components/Image.ts
1890
+ function Image(props) {
1891
+ return {
1892
+ type: "image",
1893
+ ...props
1894
+ };
1895
+ }
1896
+
1897
+ //#endregion
1898
+ //#region src/components/RichText.ts
1899
+ function RichText(props) {
1900
+ return {
1901
+ type: "richtext",
1902
+ ...props
1903
+ };
1904
+ }
1905
+
1906
+ //#endregion
1907
+ //#region src/components/Stack.ts
1908
+ function Stack(props) {
1909
+ return {
1910
+ type: "stack",
1911
+ ...props
1912
+ };
1913
+ }
1914
+
1915
+ //#endregion
1916
+ //#region src/components/Svg.ts
1917
+ function Svg(props) {
1918
+ return {
1919
+ type: "svg",
1920
+ ...props
1921
+ };
1922
+ }
1923
+ const svg = {
1924
+ rect: (props) => ({
1925
+ type: "rect",
1926
+ ...props
1927
+ }),
1928
+ circle: (props) => ({
1929
+ type: "circle",
1930
+ ...props
1931
+ }),
1932
+ ellipse: (props) => ({
1933
+ type: "ellipse",
1934
+ ...props
1935
+ }),
1936
+ line: (props) => ({
1937
+ type: "line",
1938
+ ...props
1939
+ }),
1940
+ polyline: (props) => ({
1941
+ type: "polyline",
1942
+ ...props
1943
+ }),
1944
+ polygon: (props) => ({
1945
+ type: "polygon",
1946
+ ...props
1947
+ }),
1948
+ path: (props) => ({
1949
+ type: "path",
1950
+ ...props
1951
+ }),
1952
+ text: (props) => ({
1953
+ type: "text",
1954
+ ...props
1955
+ }),
1956
+ g: (props) => ({
1957
+ type: "g",
1958
+ ...props
1959
+ })
1960
+ };
1961
+
1962
+ //#endregion
1963
+ //#region src/components/Text.ts
1964
+ function Text(props) {
1965
+ return {
1966
+ type: "text",
1967
+ ...props
1968
+ };
1969
+ }
1970
+
1971
+ //#endregion
1972
+ //#region src/components/Transform.ts
1973
+ function Transform(props) {
1974
+ return {
1975
+ type: "transform",
1976
+ ...props
1977
+ };
1978
+ }
1979
+
1980
+ //#endregion
1981
+ //#region src/layout/utils/print.ts
1982
+ /**
1983
+ * 获取元素类型的显示名称
1984
+ */
1985
+ function getElementType(element) {
1986
+ switch (element.type) {
1987
+ case "box": return "Box";
1988
+ case "text": return `Text "${element.content.slice(0, 20)}${element.content.length > 20 ? "..." : ""}"`;
1989
+ case "stack": return "Stack";
1990
+ case "image": return "Image";
1991
+ case "svg": return "Svg";
1992
+ default: return element.type;
1993
+ }
1994
+ }
1995
+ /**
1996
+ * 递归打印布局树
1997
+ */
1998
+ function printLayoutToString(node, prefix = "", isLast = true, depth = 0) {
1999
+ const lines = [];
2000
+ const connector = isLast ? "└─ " : "├─ ";
2001
+ const type = getElementType(node.element);
2002
+ const { x, y, width, height } = node.layout;
2003
+ const childCount = node.children.length;
2004
+ lines.push(`${prefix}${connector}${type} @(${Math.round(x)},${Math.round(y)}) size:${Math.round(width)}x${Math.round(height)}`);
2005
+ if (node.element.type === "text" && node.lines) {
2006
+ const contentPrefix = prefix + (isLast ? " " : "│ ");
2007
+ for (let i = 0; i < node.lines.length; i++) {
2008
+ const lineText = node.lines[i];
2009
+ const isLastLine = i === node.lines.length - 1 && childCount === 0;
2010
+ lines.push(`${contentPrefix}${isLastLine ? "└─ " : "├─ "}${JSON.stringify(lineText)}`);
2011
+ }
2012
+ }
2013
+ for (let i = 0; i < node.children.length; i++) {
2014
+ const child = node.children[i];
2015
+ const isChildLast = i === node.children.length - 1;
2016
+ const childPrefix = prefix + (isLast ? " " : "│ ");
2017
+ lines.push(...printLayoutToString(child, childPrefix, isChildLast, depth + 1));
2018
+ }
2019
+ return lines;
2020
+ }
2021
+ /**
2022
+ * 打印 LayoutNode 树结构到控制台
2023
+ */
2024
+ function printLayout(node) {
2025
+ const lines = printLayoutToString(node, "", true);
2026
+ console.log(lines.join("\n"));
2027
+ }
2028
+ /**
2029
+ * 将 LayoutNode 转换为美观的字符串
2030
+ * @param node LayoutNode 根节点
2031
+ * @param indent 缩进字符串,默认为两个空格
2032
+ * @returns 格式化的字符串
2033
+ */
2034
+ function layoutToString(node, _indent = " ") {
2035
+ return printLayoutToString(node, "", true).join("\n");
2036
+ }
2037
+
2038
+ //#endregion
2039
+ export { Box, CustomDraw, Image, RichText, Stack, Svg, Text, Transform, computeLayout, createCanvas, createCanvasMeasureContext, layoutToString, linearGradient, printLayout, radialGradient, svg };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codehz/draw-call",
3
- "module": "./index.mjs",
3
+ "module": "./node/index.mjs",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -25,32 +25,33 @@
25
25
  "optionalDependencies": {
26
26
  "@napi-rs/canvas": "^0.1.88"
27
27
  },
28
- "version": "0.2.1",
29
- "main": "./index.cjs",
30
- "types": "./index.d.cts",
28
+ "version": "0.4.0",
29
+ "main": "./node/index.cjs",
30
+ "types": "./node/index.d.cts",
31
31
  "exports": {
32
32
  ".": {
33
- "require": {
34
- "types": "./index.d.cts",
35
- "import": "./index.cjs",
36
- "default": "./index.cjs"
33
+ "browser": {
34
+ "types": "./browser/index.d.mts",
35
+ "import": "./browser/index.mjs",
36
+ "require": "./browser/index.cjs",
37
+ "default": "./browser/index.mjs"
37
38
  },
38
- "import": {
39
- "types": "./index.d.mts",
40
- "import": "./index.mjs",
41
- "default": "./index.mjs"
42
- }
43
- },
44
- "./node": {
45
- "require": {
46
- "types": "./node.d.cts",
47
- "import": "./node.cjs",
48
- "default": "./node.cjs"
39
+ "node": {
40
+ "types": "./node/index.d.mts",
41
+ "import": "./node/index.mjs",
42
+ "require": "./node/index.cjs",
43
+ "default": "./node/index.mjs"
44
+ },
45
+ "bun": {
46
+ "types": "./node/index.d.mts",
47
+ "import": "./node/index.mjs",
48
+ "default": "./node/index.mjs"
49
49
  },
50
- "import": {
51
- "types": "./node.d.mts",
52
- "import": "./node.mjs",
53
- "default": "./node.mjs"
50
+ "default": {
51
+ "types": "./node/index.d.mts",
52
+ "import": "./node/index.mjs",
53
+ "require": "./node/index.cjs",
54
+ "default": "./node/index.mjs"
54
55
  }
55
56
  }
56
57
  }
package/index.cjs DELETED
@@ -1,239 +0,0 @@
1
- const require_render = require('./render.cjs');
2
-
3
- //#region src/canvas.ts
4
- /**
5
- * 创建适用于浏览器环境的 Canvas
6
- *
7
- * 在浏览器环境中使用,支持传入已有的 canvas 实例
8
- */
9
- function createCanvas(options) {
10
- const { width, height, pixelRatio = 1 } = options;
11
- let canvas;
12
- if (options.canvas) canvas = options.canvas;
13
- else {
14
- const el = document.createElement("canvas");
15
- el.width = width * pixelRatio;
16
- el.height = height * pixelRatio;
17
- canvas = el;
18
- }
19
- const ctx = canvas.getContext("2d");
20
- if (!ctx) throw new Error("Failed to get 2d context");
21
- if (pixelRatio !== 1) ctx.scale(pixelRatio, pixelRatio);
22
- const measureCtx = require_render.createCanvasMeasureContext(ctx);
23
- return {
24
- width,
25
- height,
26
- pixelRatio,
27
- canvas,
28
- render(element) {
29
- const layoutTree = require_render.computeLayout(element, measureCtx, {
30
- minWidth: 0,
31
- maxWidth: width,
32
- minHeight: 0,
33
- maxHeight: height
34
- });
35
- require_render.renderNode(ctx, layoutTree);
36
- return layoutTree;
37
- },
38
- clear() {
39
- ctx.clearRect(0, 0, width, height);
40
- },
41
- getContext() {
42
- return ctx;
43
- },
44
- toDataURL(type, quality) {
45
- if ("toDataURL" in canvas && typeof canvas.toDataURL === "function") return canvas.toDataURL(type, quality);
46
- throw new Error("toDataURL not supported");
47
- },
48
- toBuffer(type = "image/png") {
49
- if ("toBuffer" in canvas && typeof canvas.toBuffer === "function") return canvas.toBuffer(type);
50
- throw new Error("toBuffer not supported in this environment");
51
- }
52
- };
53
- }
54
-
55
- //#endregion
56
- //#region src/components/Box.ts
57
- function Box(props) {
58
- return {
59
- type: "box",
60
- ...props
61
- };
62
- }
63
-
64
- //#endregion
65
- //#region src/components/CustomDraw.ts
66
- function CustomDraw(props) {
67
- return {
68
- type: "customdraw",
69
- ...props
70
- };
71
- }
72
-
73
- //#endregion
74
- //#region src/components/Image.ts
75
- function Image(props) {
76
- return {
77
- type: "image",
78
- ...props
79
- };
80
- }
81
-
82
- //#endregion
83
- //#region src/components/RichText.ts
84
- function RichText(props) {
85
- return {
86
- type: "richtext",
87
- ...props
88
- };
89
- }
90
-
91
- //#endregion
92
- //#region src/components/Stack.ts
93
- function Stack(props) {
94
- return {
95
- type: "stack",
96
- ...props
97
- };
98
- }
99
-
100
- //#endregion
101
- //#region src/components/Svg.ts
102
- function Svg(props) {
103
- return {
104
- type: "svg",
105
- ...props
106
- };
107
- }
108
- const svg = {
109
- rect: (props) => ({
110
- type: "rect",
111
- ...props
112
- }),
113
- circle: (props) => ({
114
- type: "circle",
115
- ...props
116
- }),
117
- ellipse: (props) => ({
118
- type: "ellipse",
119
- ...props
120
- }),
121
- line: (props) => ({
122
- type: "line",
123
- ...props
124
- }),
125
- polyline: (props) => ({
126
- type: "polyline",
127
- ...props
128
- }),
129
- polygon: (props) => ({
130
- type: "polygon",
131
- ...props
132
- }),
133
- path: (props) => ({
134
- type: "path",
135
- ...props
136
- }),
137
- text: (props) => ({
138
- type: "text",
139
- ...props
140
- }),
141
- g: (props) => ({
142
- type: "g",
143
- ...props
144
- })
145
- };
146
-
147
- //#endregion
148
- //#region src/components/Text.ts
149
- function Text(props) {
150
- return {
151
- type: "text",
152
- ...props
153
- };
154
- }
155
-
156
- //#endregion
157
- //#region src/components/Transform.ts
158
- function Transform(props) {
159
- return {
160
- type: "transform",
161
- ...props
162
- };
163
- }
164
-
165
- //#endregion
166
- //#region src/layout/utils/print.ts
167
- /**
168
- * 获取元素类型的显示名称
169
- */
170
- function getElementType(element) {
171
- switch (element.type) {
172
- case "box": return "Box";
173
- case "text": return `Text "${element.content.slice(0, 20)}${element.content.length > 20 ? "..." : ""}"`;
174
- case "stack": return "Stack";
175
- case "image": return "Image";
176
- case "svg": return "Svg";
177
- default: return element.type;
178
- }
179
- }
180
- /**
181
- * 递归打印布局树
182
- */
183
- function printLayoutToString(node, prefix = "", isLast = true, depth = 0) {
184
- const lines = [];
185
- const connector = isLast ? "└─ " : "├─ ";
186
- const type = getElementType(node.element);
187
- const { x, y, width, height } = node.layout;
188
- const childCount = node.children.length;
189
- lines.push(`${prefix}${connector}${type} @(${Math.round(x)},${Math.round(y)}) size:${Math.round(width)}x${Math.round(height)}`);
190
- if (node.element.type === "text" && node.lines) {
191
- const contentPrefix = prefix + (isLast ? " " : "│ ");
192
- for (let i = 0; i < node.lines.length; i++) {
193
- const lineText = node.lines[i];
194
- const isLastLine = i === node.lines.length - 1 && childCount === 0;
195
- lines.push(`${contentPrefix}${isLastLine ? "└─ " : "├─ "}${JSON.stringify(lineText)}`);
196
- }
197
- }
198
- for (let i = 0; i < node.children.length; i++) {
199
- const child = node.children[i];
200
- const isChildLast = i === node.children.length - 1;
201
- const childPrefix = prefix + (isLast ? " " : "│ ");
202
- lines.push(...printLayoutToString(child, childPrefix, isChildLast, depth + 1));
203
- }
204
- return lines;
205
- }
206
- /**
207
- * 打印 LayoutNode 树结构到控制台
208
- */
209
- function printLayout(node) {
210
- const lines = printLayoutToString(node, "", true);
211
- console.log(lines.join("\n"));
212
- }
213
- /**
214
- * 将 LayoutNode 转换为美观的字符串
215
- * @param node LayoutNode 根节点
216
- * @param indent 缩进字符串,默认为两个空格
217
- * @returns 格式化的字符串
218
- */
219
- function layoutToString(node, _indent = " ") {
220
- return printLayoutToString(node, "", true).join("\n");
221
- }
222
-
223
- //#endregion
224
- exports.Box = Box;
225
- exports.CustomDraw = CustomDraw;
226
- exports.Image = Image;
227
- exports.RichText = RichText;
228
- exports.Stack = Stack;
229
- exports.Svg = Svg;
230
- exports.Text = Text;
231
- exports.Transform = Transform;
232
- exports.computeLayout = require_render.computeLayout;
233
- exports.createCanvas = createCanvas;
234
- exports.createCanvasMeasureContext = require_render.createCanvasMeasureContext;
235
- exports.layoutToString = layoutToString;
236
- exports.linearGradient = require_render.linearGradient;
237
- exports.printLayout = printLayout;
238
- exports.radialGradient = require_render.radialGradient;
239
- exports.svg = svg;