diff --git a/src/hook/render/index.js b/src/hook/render/index.js index 417528b..0148129 100644 --- a/src/hook/render/index.js +++ b/src/hook/render/index.js @@ -20,6 +20,7 @@ export class NetlistRender { id: 'root', layoutOptions: { 'elk.algorithm': 'layered', + 'elk.progressBar': true, 'layered.nodePlacement.strategy': 'SIDE_BASED' }, children: [], diff --git a/src/hook/render/layout.js b/src/hook/render/layout.js index 23fc7e3..220d547 100644 --- a/src/hook/render/layout.js +++ b/src/hook/render/layout.js @@ -5,7 +5,8 @@ import { globalLookup } from "../global"; import { Cell, CELL_LIBS, ModuleTree } from "./yosys"; -const SKIN_SCALE = 1; +export const SKIN_SCALE = 1; +export const LINE_WIDTH = 2; export const LAYOUT_CONSTANT = { // port @@ -116,33 +117,90 @@ export class Module { const width = meta.width * SKIN_SCALE; const ports = []; - for (const connectionName of cell.nameToConnection.keys()) { - const connection = cell.nameToConnection.get(connectionName); - const portSide = connection.direction === 'input' ? ELK_DIRECTION.LEFT: ELK_DIRECTION.RIGHT; - + + // 统计分配到左右两侧的 port + const leftSideConnections = []; + const rightSideConnections = []; + + for (const conn of cell.nameToConnection.values()) { + if (conn.direction === 'input') { + leftSideConnections.push(conn); + } else { + rightSideConnections.push(conn); + } + } + + // 计算左侧的 + for (let i = 0; i < leftSideConnections.length; ++ i) { + const connection = leftSideConnections[i]; const yOffset = meta.getPortYOffset(connection.name) * SKIN_SCALE; + const targetY = yOffset; + + // 默认采用 JUSTIFIED,均分一侧的 height + // 我们绘制的 svg 的 port offset y 未必和 elk 分配得到的一样,因此需要进行修正 + const layoutY = height / (leftSideConnections.length + 1) * (i + 1); + const extraOffset = LINE_WIDTH * leftSideConnections.length; + const anchorY = layoutY - targetY; + + console.log(targetY, layoutY, targetY - layoutY); + + let gap = (targetY - layoutY).toFixed(2); + console.log('gap', gap); + ports.push({ id: connection.id, - renderName: connectionName, + renderName: connection.name, renderType: 'cellPort', - width: LAYOUT_CONSTANT.CELL_PORT_WIDTH, - height: LAYOUT_CONSTANT.CELL_PORT_HEIGHT, - y: yOffset, + width: 0, + height: 0, properties: { - 'port.side': portSide + 'port.side': ELK_DIRECTION.LEFT, + 'port.anchor': `0, ${gap}` } - }) + }); + + console.log(ports.at(-1).properties["port.anchor"]); + } + // 计算右侧的 + for (let i = 0; i < rightSideConnections.length; ++ i) { + const connection = rightSideConnections[i]; + const yOffset = meta.getPortYOffset(connection.name) * SKIN_SCALE; + const targetY = yOffset; + + // 默认采用 JUSTIFIED,均分一侧的 height + // 我们绘制的 svg 的 port offset y 未必和 elk 分配得到的一样,因此需要进行修正 + const layoutY = height / (rightSideConnections.length + 1) * (i + 1); + const extraOffset = LINE_WIDTH * rightSideConnections.length / 2; + const anchorY = targetY - layoutY + extraOffset; + + ports.push({ + id: connection.id, + renderName: connection.name, + renderType: 'cellPort', + width: 0, + height: 0, + properties: { + 'port.side': ELK_DIRECTION.RIGHT, + 'port.anchor': `0, ${anchorY}` + } + }); + } + + const node = { id: cell.id, renderName: cell.type, renderType: 'cell', width, height, - ports - } + ports, + layoutOptions: { + 'org.eclipse.elk.portConstraints': 'FIXED_SIDE', + } + }; nodes.push(node); } else { // 例化模块 @@ -172,11 +230,11 @@ export class Module { width, height, ports, - properties: { + layoutOptions: { // 强制固定 port 的方向 - 'portConstraints': 'FIXED_ORDER' - }, - } + 'org.eclipse.elk.portConstraints': 'FIXED_SIDE' + } + }; nodes.push(node); } diff --git a/src/hook/skin/index.js b/src/hook/skin/index.js index e40782d..007fcfd 100644 --- a/src/hook/skin/index.js +++ b/src/hook/skin/index.js @@ -65,8 +65,8 @@ class SkinMeta { const parser = new DOMParser(); // 颜色替换 - svgString = svgString.replace(/#279BB0/g, 'var(--main-color)'); - svgString = svgString.replace(/#000000/g, 'var(--main-dark-color)'); + svgString = svgString.replace(/#279BB0/g, 'var(--main-dark-color)'); + svgString = svgString.replace(/#000000/g, 'var(--main-color)'); const svgDoc = parser.parseFromString(svgString, 'image/svg+xml'); const element = svgDoc.documentElement; @@ -94,7 +94,7 @@ class SkinMeta { return 0; } const transform = pathElement.getAttribute('transform'); - const yOffset = transform.split(' ').at(-1); + const yOffset = parseFloat(transform.split(' ').at(-1)); this.portToYOffset.set(portName, yOffset); return yOffset; }