完成线段连接

This commit is contained in:
锦恢 2024-12-24 11:48:48 +08:00
parent 3fa8971c9b
commit 45a54eb06e
82 changed files with 583 additions and 63 deletions

333
package-lock.json generated
View File

@ -25,7 +25,9 @@
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3"
"eslint-plugin-vue": "^8.0.3",
"unplugin-auto-import": "^0.17.5",
"unplugin-vue-components": "^0.26.0"
}
},
"node_modules/@achrinza/node-ipc": {
@ -55,6 +57,15 @@
"node": ">=6.0.0"
}
},
"node_modules/@antfu/utils": {
"version": "0.7.10",
"resolved": "https://registry.npmmirror.com/@antfu/utils/-/utils-0.7.10.tgz",
"integrity": "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/@babel/code-frame": {
"version": "7.26.2",
"resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.26.2.tgz",
@ -1967,6 +1978,40 @@
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@rollup/pluginutils": {
"version": "5.1.4",
"resolved": "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-5.1.4.tgz",
"integrity": "sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ==",
"dev": true,
"dependencies": {
"@types/estree": "^1.0.0",
"estree-walker": "^2.0.2",
"picomatch": "^4.0.2"
},
"engines": {
"node": ">=14.0.0"
},
"peerDependencies": {
"rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
},
"peerDependenciesMeta": {
"rollup": {
"optional": true
}
}
},
"node_modules/@rollup/pluginutils/node_modules/picomatch": {
"version": "4.0.2",
"resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/@sideway/address": {
"version": "4.1.5",
"resolved": "https://registry.npmmirror.com/@sideway/address/-/address-4.1.5.tgz",
@ -4194,6 +4239,12 @@
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
"dev": true
},
"node_modules/confbox": {
"version": "0.1.8",
"resolved": "https://registry.npmmirror.com/confbox/-/confbox-0.1.8.tgz",
"integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==",
"dev": true
},
"node_modules/connect-history-api-fallback": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz",
@ -7648,6 +7699,22 @@
"json5": "lib/cli.js"
}
},
"node_modules/local-pkg": {
"version": "0.5.1",
"resolved": "https://registry.npmmirror.com/local-pkg/-/local-pkg-0.5.1.tgz",
"integrity": "sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==",
"dev": true,
"dependencies": {
"mlly": "^1.7.3",
"pkg-types": "^1.2.1"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-5.0.0.tgz",
@ -8190,6 +8257,18 @@
"mkdirp": "bin/cmd.js"
}
},
"node_modules/mlly": {
"version": "1.7.3",
"resolved": "https://registry.npmmirror.com/mlly/-/mlly-1.7.3.tgz",
"integrity": "sha512-xUsx5n/mN0uQf4V548PKQ+YShA4/IW0KI1dZhrNrPCLG+xizETbHTkOa1f8/xut9JRPp8kQuMnz0oqwkTiLo/A==",
"dev": true,
"dependencies": {
"acorn": "^8.14.0",
"pathe": "^1.1.2",
"pkg-types": "^1.2.1",
"ufo": "^1.5.4"
}
},
"node_modules/module-alias": {
"version": "2.2.3",
"resolved": "https://registry.npmmirror.com/module-alias/-/module-alias-2.2.3.tgz",
@ -8771,6 +8850,12 @@
"node": ">=8"
}
},
"node_modules/pathe": {
"version": "1.1.2",
"resolved": "https://registry.npmmirror.com/pathe/-/pathe-1.1.2.tgz",
"integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==",
"dev": true
},
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
@ -8800,6 +8885,17 @@
"node": ">=8"
}
},
"node_modules/pkg-types": {
"version": "1.2.1",
"resolved": "https://registry.npmmirror.com/pkg-types/-/pkg-types-1.2.1.tgz",
"integrity": "sha512-sQoqa8alT3nHjGuTjuKgOnvjo4cljkufdtLMnO2LBP/wRwuDlo1tkaEdMxCRhyGRPacv/ztlZgDPm2b7FAmEvw==",
"dev": true,
"dependencies": {
"confbox": "^0.1.8",
"mlly": "^1.7.2",
"pathe": "^1.1.2"
}
},
"node_modules/portfinder": {
"version": "1.0.32",
"resolved": "https://registry.npmmirror.com/portfinder/-/portfinder-1.0.32.tgz",
@ -9992,6 +10088,12 @@
"url": "https://opencollective.com/webpack"
}
},
"node_modules/scule": {
"version": "1.3.0",
"resolved": "https://registry.npmmirror.com/scule/-/scule-1.3.0.tgz",
"integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==",
"dev": true
},
"node_modules/select-hose": {
"version": "2.0.0",
"resolved": "https://registry.npmmirror.com/select-hose/-/select-hose-2.0.0.tgz",
@ -10570,6 +10672,24 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/strip-literal": {
"version": "2.1.1",
"resolved": "https://registry.npmmirror.com/strip-literal/-/strip-literal-2.1.1.tgz",
"integrity": "sha512-631UJ6O00eNGfMiWG78ck80dfBab8X6IVFB51jZK5Icd7XAs60Z5y7QdSd/wGIklnWvRbUNloVzhOKKmutxQ6Q==",
"dev": true,
"dependencies": {
"js-tokens": "^9.0.1"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/strip-literal/node_modules/js-tokens": {
"version": "9.0.1",
"resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-9.0.1.tgz",
"integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==",
"dev": true
},
"node_modules/stylehacks": {
"version": "5.1.1",
"resolved": "https://registry.npmmirror.com/stylehacks/-/stylehacks-5.1.1.tgz",
@ -10968,6 +11088,12 @@
"node": ">= 0.6"
}
},
"node_modules/ufo": {
"version": "1.5.4",
"resolved": "https://registry.npmmirror.com/ufo/-/ufo-1.5.4.tgz",
"integrity": "sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==",
"dev": true
},
"node_modules/undici-types": {
"version": "6.20.0",
"resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.20.0.tgz",
@ -11014,6 +11140,61 @@
"node": ">=4"
}
},
"node_modules/unimport": {
"version": "3.14.5",
"resolved": "https://registry.npmmirror.com/unimport/-/unimport-3.14.5.tgz",
"integrity": "sha512-tn890SwFFZxqaJSKQPPd+yygfKSATbM8BZWW1aCR2TJBTs1SDrmLamBueaFtYsGjHtQaRgqEbQflOjN2iW12gA==",
"dev": true,
"dependencies": {
"@rollup/pluginutils": "^5.1.3",
"acorn": "^8.14.0",
"escape-string-regexp": "^5.0.0",
"estree-walker": "^3.0.3",
"fast-glob": "^3.3.2",
"local-pkg": "^0.5.1",
"magic-string": "^0.30.14",
"mlly": "^1.7.3",
"pathe": "^1.1.2",
"picomatch": "^4.0.2",
"pkg-types": "^1.2.1",
"scule": "^1.3.0",
"strip-literal": "^2.1.1",
"unplugin": "^1.16.0"
}
},
"node_modules/unimport/node_modules/escape-string-regexp": {
"version": "5.0.0",
"resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
"integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/unimport/node_modules/estree-walker": {
"version": "3.0.3",
"resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-3.0.3.tgz",
"integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
"dev": true,
"dependencies": {
"@types/estree": "^1.0.0"
}
},
"node_modules/unimport/node_modules/picomatch": {
"version": "4.0.2",
"resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/universalify": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/universalify/-/universalify-2.0.1.tgz",
@ -11032,6 +11213,156 @@
"node": ">= 0.8"
}
},
"node_modules/unplugin": {
"version": "1.16.0",
"resolved": "https://registry.npmmirror.com/unplugin/-/unplugin-1.16.0.tgz",
"integrity": "sha512-5liCNPuJW8dqh3+DM6uNM2EI3MLLpCKp/KY+9pB5M2S2SR2qvvDHhKgBOaTWEbZTAws3CXfB0rKTIolWKL05VQ==",
"dev": true,
"dependencies": {
"acorn": "^8.14.0",
"webpack-virtual-modules": "^0.6.2"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/unplugin-auto-import": {
"version": "0.17.8",
"resolved": "https://registry.npmmirror.com/unplugin-auto-import/-/unplugin-auto-import-0.17.8.tgz",
"integrity": "sha512-CHryj6HzJ+n4ASjzwHruD8arhbdl+UXvhuAIlHDs15Y/IMecG3wrf7FVg4pVH/DIysbq/n0phIjNHAjl7TG7Iw==",
"dev": true,
"dependencies": {
"@antfu/utils": "^0.7.10",
"@rollup/pluginutils": "^5.1.0",
"fast-glob": "^3.3.2",
"local-pkg": "^0.5.0",
"magic-string": "^0.30.10",
"minimatch": "^9.0.4",
"unimport": "^3.7.2",
"unplugin": "^1.11.0"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@nuxt/kit": "^3.2.2",
"@vueuse/core": "*"
},
"peerDependenciesMeta": {
"@nuxt/kit": {
"optional": true
},
"@vueuse/core": {
"optional": true
}
}
},
"node_modules/unplugin-auto-import/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/unplugin-auto-import/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true,
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/unplugin-vue-components": {
"version": "0.26.0",
"resolved": "https://registry.npmmirror.com/unplugin-vue-components/-/unplugin-vue-components-0.26.0.tgz",
"integrity": "sha512-s7IdPDlnOvPamjunVxw8kNgKNK8A5KM1YpK5j/p97jEKTjlPNrA0nZBiSfAKKlK1gWZuyWXlKL5dk3EDw874LQ==",
"dev": true,
"dependencies": {
"@antfu/utils": "^0.7.6",
"@rollup/pluginutils": "^5.0.4",
"chokidar": "^3.5.3",
"debug": "^4.3.4",
"fast-glob": "^3.3.1",
"local-pkg": "^0.4.3",
"magic-string": "^0.30.3",
"minimatch": "^9.0.3",
"resolve": "^1.22.4",
"unplugin": "^1.4.0"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
},
"peerDependencies": {
"@babel/parser": "^7.15.8",
"@nuxt/kit": "^3.2.2",
"vue": "2 || 3"
},
"peerDependenciesMeta": {
"@babel/parser": {
"optional": true
},
"@nuxt/kit": {
"optional": true
}
}
},
"node_modules/unplugin-vue-components/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/unplugin-vue-components/node_modules/local-pkg": {
"version": "0.4.3",
"resolved": "https://registry.npmmirror.com/local-pkg/-/local-pkg-0.4.3.tgz",
"integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==",
"dev": true,
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/antfu"
}
},
"node_modules/unplugin-vue-components/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true,
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/unplugin/node_modules/webpack-virtual-modules": {
"version": "0.6.2",
"resolved": "https://registry.npmmirror.com/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz",
"integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==",
"dev": true
},
"node_modules/update-browserslist-db": {
"version": "1.1.1",
"resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",

View File

@ -25,7 +25,9 @@
"@vue/cli-plugin-eslint": "~5.0.0",
"@vue/cli-service": "~5.0.0",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^8.0.3"
"eslint-plugin-vue": "^8.0.3",
"unplugin-auto-import": "^0.17.5",
"unplugin-vue-components": "^0.26.0"
},
"eslintConfig": {
"root": true,

Binary file not shown.

21
scripts/modify_name.py Normal file
View File

@ -0,0 +1,21 @@
import os
gate_home = './src/static/Gate'
word_home = './src/static/Word'
for folder in os.listdir(gate_home):
folder_path = os.path.join(gate_home, folder)
for file in os.listdir(folder_path):
file_path = os.path.join(folder_path, file)
if '$' not in file:
name = file.split('.')[0]
rename_path = f'{folder_path}/$_{name}_.svg'
os.rename(file_path, rename_path)
for folder in os.listdir(word_home):
folder_path = os.path.join(word_home, folder)
for file in os.listdir(folder_path):
file_path = os.path.join(folder_path, file)
if '$' not in file:
name = file.split('.')[0]
rename_path = f'{folder_path}/${name}.svg'
os.rename(file_path, rename_path)

View File

@ -3,6 +3,7 @@ import ELK from 'elkjs';
import { Module } from './layout';
import { globalLookup } from '../global';
export class NetlistRender {
/**
@ -112,18 +113,34 @@ export class NetlistRender {
// - 器件的 port
// 生成用于绘制的 d3 数据结构
// 默认需要渲染成矩形的(缺失样式的器件、例化模块等等)
const squares = [];
for (const node of computedLayout.children) {
squares.push({
x: node.x,
y: node.y,
width: node.width,
height: node.height,
fill: '#2D323B',
text: node.renderName,
rx: 3,
ry: 3
});
const svgElements = [];
const skinManager = globalLookup.skinManager;
for (const node of computedLayout.children) {
const skin = skinManager.querySkin(node.renderName);
if (skin) {
svgElements.push({
element: skin.meta.svgDoc.documentElement,
x: node.x,
y: node.y,
width: node.width,
height: node.height,
fill: 'var(--main-dark-color)',
});
} else {
squares.push({
x: node.x,
y: node.y,
width: node.width,
height: node.height,
fill: 'var(--main-dark-color)',
text: node.renderName,
rx: 3,
ry: 3
});
}
// 如果存在 port绘制 port
for (const cellPort of node.ports || []) {
@ -132,7 +149,7 @@ export class NetlistRender {
y: cellPort.y + node.y,
width: cellPort.width,
height: cellPort.height,
fill: '#CB81DA',
fill: 'var(--main-color)',
text: '',
rx: 0,
ry: 0
@ -149,11 +166,20 @@ export class NetlistRender {
.attr('width', data => data.width)
.attr('height', data => data.height)
.attr('fill', d => d.fill)
.attr('stroke', '#CB81DA')
.attr('stroke', 'var(--main-color)')
.attr('stroke-width', 2)
.attr('rx', d => d.rx)
.attr('ry', d => d.ry);
svg.selectAll('g')
.data(svgElements)
.enter()
.append(data => {
const element = data.element;
element.setAttribute('x', data.x);
element.setAttribute('y', data.y);
return element;
});
svg.selectAll('text')
.data(squares)

View File

@ -2,7 +2,10 @@
* 将各个节点转换为 elknode 的数据结构
*/
import { CELL_LIBS, ModuleTree } from "./yosys";
import { globalLookup } from "../global";
import { Cell, CELL_LIBS, ModuleTree } from "./yosys";
const SKIN_SCALE = 1;
export const LAYOUT_CONSTANT = {
// port
@ -29,18 +32,12 @@ export const ELK_DIRECTION = {
BOTTOM: 'SOUTH'
}
function getCellSize(cellType) {
if (CELL_LIBS[cellType]) {
return {
width: 50,
height: 50
};
} else {
return {
width: LAYOUT_CONSTANT.INSTANTIATION_WIDTH,
height: LAYOUT_CONSTANT.INSTANTIATION_HEIGHT
};
}
/**
*
* @param {Cell} cell
*/
function getInstanceSize(cell) {
// 根据 port 尺寸来进行计算
}
function makeEdgeId(fromId, toId) {
@ -105,42 +102,84 @@ export class Module {
const nodes = [];
const edges = [];
const skinManager = globalLookup.skinManager;
for (const name of this.moduleTree.nameToCell.keys()) {
const cell = this.moduleTree.nameToCell.get(name);
const { height, width } = getCellSize(cell.type);
const skin = skinManager.querySkin(cell.type);
// 创建器件节点的 port, port 和 connection 一一对应
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;
ports.push({
id: connection.id,
renderName: connectionName,
renderType: 'cellPort',
width: LAYOUT_CONSTANT.CELL_PORT_WIDTH,
height: LAYOUT_CONSTANT.CELL_PORT_HEIGHT,
if (skin) {
// 内置器件
// 创建器件节点的 port, port 和 connection 一一对应
const meta = skin.meta;
const height = meta.height * SKIN_SCALE;
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;
const yOffset = meta.getPortYOffset(connection.name) * SKIN_SCALE;
ports.push({
id: connection.id,
renderName: connectionName,
renderType: 'cellPort',
width: LAYOUT_CONSTANT.CELL_PORT_WIDTH,
height: LAYOUT_CONSTANT.CELL_PORT_HEIGHT,
y: yOffset,
properties: {
'port.side': portSide
}
})
}
const node = {
id: cell.id,
renderName: cell.type,
renderType: 'cell',
width,
height,
ports
}
nodes.push(node);
} else {
// 例化模块
// 创建器件节点的 port, port 和 connection 一一对应
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;
ports.push({
id: connection.id,
renderName: connectionName,
renderType: 'cellPort',
width: LAYOUT_CONSTANT.CELL_PORT_WIDTH,
height: LAYOUT_CONSTANT.CELL_PORT_HEIGHT,
properties: {
'port.side': portSide
}
})
}
const node = {
id: cell.id,
renderName: cell.type,
renderType: 'cell',
width,
height,
ports,
properties: {
'port.side': portSide
}
})
}
// 强制固定 port 的方向
'portConstraints': 'FIXED_ORDER'
},
}
const node = {
id: cell.id,
renderName: cell.type,
renderType: 'cell',
width,
height,
ports,
properties: {
// 强制固定 port 的方向
'portConstraints': 'FIXED_ORDER'
},
nodes.push(node);
}
nodes.push(node);
}
return nodes;

View File

@ -2,7 +2,10 @@ import * as fflate from 'fflate';
export class SkinManager {
constructor() {
/**
* @type {Map<string, SkinResource>}
*/
this.resources = new Map();
}
/**
@ -11,11 +14,88 @@ export class SkinManager {
*/
load(binary) {
const buffer = new Uint8Array(binary);
const folderTree = fflate.unzipSync(buffer);
const resources = fflate.unzipSync(buffer);
const decoder = new TextDecoder('utf-8');
for (const [path, buffer] of Object.entries(resources)) {
if (path.endsWith('.svg')) {
const filename = path.split('/').at(-1);
const name = filename.slice(0, -4);
const text = decoder.decode(buffer);
const meta = new SkinMeta(text);
this.resources.set(name, {
path,
filename,
text,
name,
meta
});
}
}
}
/**
* @description 查询 skin
* @param {string} name
* @returns {SkinResource | undefined}
*/
querySkin(name) {
const resource = this.resources.get(name);
return resource;
}
}
/**
* @typedef
*/
* @typedef SkinResource
* @property {string} path 压缩包中的相对定义路径比如src/static/Gate/Combinatorial cells (simple)/$_NOR_.svg
* @property {string} filename 器件文件名比如 $_OR_.svg
* @property {string} name 器件名 $_OR_
* @property {string} text svg 原文本
* @property {SkinMeta} meta 后续生成的更加格式化的器件
*/
class SkinMeta {
/**
* @param {string} svgString
*/
constructor(svgString) {
// 解析 svg string 获取关键信息
const parser = new DOMParser();
// 颜色替换
svgString = svgString.replace(/#279BB0/g, 'var(--main-color)');
svgString = svgString.replace(/#000000/g, 'var(--main-dark-color)');
const svgDoc = parser.parseFromString(svgString, 'image/svg+xml');
const element = svgDoc.documentElement;
this.width = element.getAttribute('width');
this.height = element.getAttribute('height');
this.svgDoc = svgDoc;
/**
* @type {Map<string, number>}
*/
this.portToYOffset = new Map();
}
/**
* @description 获取指定 port 在所在 svg Y 轴的相对偏移量
* @param {string} portName
*/
getPortYOffset(portName) {
if (this.portToYOffset.has(portName)) {
return this.portToYOffset.get(portName);
}
// 没有 hit尝试获取
const pathElement = this.svgDoc.getElementById(portName);
if (pathElement === null) {
return 0;
}
const transform = pathElement.getAttribute('transform');
const yOffset = transform.split(' ').at(-1);
this.portToYOffset.set(portName, yOffset);
return yOffset;
}
}

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

21
webpack.config.js Normal file
View File

@ -0,0 +1,21 @@
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
module.exports = {
plugins: [
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
new webpack.DefinePlugin({
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false,
})
],
resolve: {
fallback: {
}
},
};