diff --git a/package-lock.json b/package-lock.json index b23721a..93a504a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index 29fecdb..2d5178d 100644 --- a/package.json +++ b/package.json @@ -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, diff --git a/public/test.skin b/public/test.skin index 7d8080c..ef4275d 100644 Binary files a/public/test.skin and b/public/test.skin differ diff --git a/scripts/modify_name.py b/scripts/modify_name.py new file mode 100644 index 0000000..8f3ec70 --- /dev/null +++ b/scripts/modify_name.py @@ -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) \ No newline at end of file diff --git a/src/hook/render/index.js b/src/hook/render/index.js index f1c1dd7..417528b 100644 --- a/src/hook/render/index.js +++ b/src/hook/render/index.js @@ -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) diff --git a/src/hook/render/layout.js b/src/hook/render/layout.js index 0ad4c34..23fc7e3 100644 --- a/src/hook/render/layout.js +++ b/src/hook/render/layout.js @@ -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; diff --git a/src/hook/skin/index.js b/src/hook/skin/index.js index 6a72809..e40782d 100644 --- a/src/hook/skin/index.js +++ b/src/hook/skin/index.js @@ -2,7 +2,10 @@ import * as fflate from 'fflate'; export class SkinManager { constructor() { - + /** + * @type {Map} + */ + 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 - */ \ No newline at end of file + * @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} + */ + 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; + } +} \ No newline at end of file diff --git a/src/static/Gate/Combinatorial cells (combined)/ANDN.svg b/src/static/Gate/Combinatorial cells (combined)/$_ANDN_.svg similarity index 100% rename from src/static/Gate/Combinatorial cells (combined)/ANDN.svg rename to src/static/Gate/Combinatorial cells (combined)/$_ANDN_.svg diff --git a/src/static/Gate/Combinatorial cells (combined)/AOI3.svg b/src/static/Gate/Combinatorial cells (combined)/$_AOI3_.svg similarity index 100% rename from src/static/Gate/Combinatorial cells (combined)/AOI3.svg rename to src/static/Gate/Combinatorial cells (combined)/$_AOI3_.svg diff --git a/src/static/Gate/Combinatorial cells (combined)/AOI4.svg b/src/static/Gate/Combinatorial cells (combined)/$_AOI4_.svg similarity index 100% rename from src/static/Gate/Combinatorial cells (combined)/AOI4.svg rename to src/static/Gate/Combinatorial cells (combined)/$_AOI4_.svg diff --git a/src/static/Gate/Combinatorial cells (combined)/MUX4.svg b/src/static/Gate/Combinatorial cells (combined)/$_MUX4_.svg similarity index 100% rename from src/static/Gate/Combinatorial cells (combined)/MUX4.svg rename to src/static/Gate/Combinatorial cells (combined)/$_MUX4_.svg diff --git a/src/static/Gate/Combinatorial cells (combined)/MUX8.svg b/src/static/Gate/Combinatorial cells (combined)/$_MUX8_.svg similarity index 100% rename from src/static/Gate/Combinatorial cells (combined)/MUX8.svg rename to src/static/Gate/Combinatorial cells (combined)/$_MUX8_.svg diff --git a/src/static/Gate/Combinatorial cells (combined)/NMUX.svg b/src/static/Gate/Combinatorial cells (combined)/$_NMUX_.svg similarity index 100% rename from src/static/Gate/Combinatorial cells (combined)/NMUX.svg rename to src/static/Gate/Combinatorial cells (combined)/$_NMUX_.svg diff --git a/src/static/Gate/Combinatorial cells (combined)/OAI3.svg b/src/static/Gate/Combinatorial cells (combined)/$_OAI3_.svg similarity index 100% rename from src/static/Gate/Combinatorial cells (combined)/OAI3.svg rename to src/static/Gate/Combinatorial cells (combined)/$_OAI3_.svg diff --git a/src/static/Gate/Combinatorial cells (combined)/OAI4.svg b/src/static/Gate/Combinatorial cells (combined)/$_OAI4_.svg similarity index 100% rename from src/static/Gate/Combinatorial cells (combined)/OAI4.svg rename to src/static/Gate/Combinatorial cells (combined)/$_OAI4_.svg diff --git a/src/static/Gate/Combinatorial cells (combined)/ORN.svg b/src/static/Gate/Combinatorial cells (combined)/$_ORN_.svg similarity index 100% rename from src/static/Gate/Combinatorial cells (combined)/ORN.svg rename to src/static/Gate/Combinatorial cells (combined)/$_ORN_.svg diff --git a/src/static/Gate/Combinatorial cells (simple)/TBUF.svg b/src/static/Gate/Combinatorial cells (simple)/$_TBUF_.svg similarity index 100% rename from src/static/Gate/Combinatorial cells (simple)/TBUF.svg rename to src/static/Gate/Combinatorial cells (simple)/$_TBUF_.svg diff --git a/src/static/Gate/Combinatorial cells (simple)/$XOR.svg b/src/static/Gate/Combinatorial cells (simple)/$_XOR_.svg similarity index 100% rename from src/static/Gate/Combinatorial cells (simple)/$XOR.svg rename to src/static/Gate/Combinatorial cells (simple)/$_XOR_.svg diff --git a/src/static/Word/Binary operators/add.svg b/src/static/Word/Binary operators/$add.svg similarity index 100% rename from src/static/Word/Binary operators/add.svg rename to src/static/Word/Binary operators/$add.svg diff --git a/src/static/Word/Binary operators/and.svg b/src/static/Word/Binary operators/$and.svg similarity index 100% rename from src/static/Word/Binary operators/and.svg rename to src/static/Word/Binary operators/$and.svg diff --git a/src/static/Word/Binary operators/div.svg b/src/static/Word/Binary operators/$div.svg similarity index 100% rename from src/static/Word/Binary operators/div.svg rename to src/static/Word/Binary operators/$div.svg diff --git a/src/static/Word/Binary operators/eq.svg b/src/static/Word/Binary operators/$eq.svg similarity index 100% rename from src/static/Word/Binary operators/eq.svg rename to src/static/Word/Binary operators/$eq.svg diff --git a/src/static/Word/Binary operators/eqx.svg b/src/static/Word/Binary operators/$eqx.svg similarity index 100% rename from src/static/Word/Binary operators/eqx.svg rename to src/static/Word/Binary operators/$eqx.svg diff --git a/src/static/Word/Binary operators/ge.svg b/src/static/Word/Binary operators/$ge.svg similarity index 100% rename from src/static/Word/Binary operators/ge.svg rename to src/static/Word/Binary operators/$ge.svg diff --git a/src/static/Word/Binary operators/gt.svg b/src/static/Word/Binary operators/$gt.svg similarity index 100% rename from src/static/Word/Binary operators/gt.svg rename to src/static/Word/Binary operators/$gt.svg diff --git a/src/static/Word/Binary operators/le.svg b/src/static/Word/Binary operators/$le.svg similarity index 100% rename from src/static/Word/Binary operators/le.svg rename to src/static/Word/Binary operators/$le.svg diff --git a/src/static/Word/Binary operators/logic_and.svg b/src/static/Word/Binary operators/$logic_and.svg similarity index 100% rename from src/static/Word/Binary operators/logic_and.svg rename to src/static/Word/Binary operators/$logic_and.svg diff --git a/src/static/Word/Binary operators/logic_or.svg b/src/static/Word/Binary operators/$logic_or.svg similarity index 100% rename from src/static/Word/Binary operators/logic_or.svg rename to src/static/Word/Binary operators/$logic_or.svg diff --git a/src/static/Word/Binary operators/lt.svg b/src/static/Word/Binary operators/$lt.svg similarity index 100% rename from src/static/Word/Binary operators/lt.svg rename to src/static/Word/Binary operators/$lt.svg diff --git a/src/static/Word/Binary operators/mod.svg b/src/static/Word/Binary operators/$mod.svg similarity index 100% rename from src/static/Word/Binary operators/mod.svg rename to src/static/Word/Binary operators/$mod.svg diff --git a/src/static/Word/Binary operators/mul.svg b/src/static/Word/Binary operators/$mul.svg similarity index 100% rename from src/static/Word/Binary operators/mul.svg rename to src/static/Word/Binary operators/$mul.svg diff --git a/src/static/Word/Binary operators/ne.svg b/src/static/Word/Binary operators/$ne.svg similarity index 100% rename from src/static/Word/Binary operators/ne.svg rename to src/static/Word/Binary operators/$ne.svg diff --git a/src/static/Word/Binary operators/nex.svg b/src/static/Word/Binary operators/$nex.svg similarity index 100% rename from src/static/Word/Binary operators/nex.svg rename to src/static/Word/Binary operators/$nex.svg diff --git a/src/static/Word/Binary operators/or.svg b/src/static/Word/Binary operators/$or.svg similarity index 100% rename from src/static/Word/Binary operators/or.svg rename to src/static/Word/Binary operators/$or.svg diff --git a/src/static/Word/Binary operators/pow.svg b/src/static/Word/Binary operators/$pow.svg similarity index 100% rename from src/static/Word/Binary operators/pow.svg rename to src/static/Word/Binary operators/$pow.svg diff --git a/src/static/Word/Binary operators/shl.svg b/src/static/Word/Binary operators/$shl.svg similarity index 100% rename from src/static/Word/Binary operators/shl.svg rename to src/static/Word/Binary operators/$shl.svg diff --git a/src/static/Word/Binary operators/shr.svg b/src/static/Word/Binary operators/$shr.svg similarity index 100% rename from src/static/Word/Binary operators/shr.svg rename to src/static/Word/Binary operators/$shr.svg diff --git a/src/static/Word/Binary operators/sshl.svg b/src/static/Word/Binary operators/$sshl.svg similarity index 100% rename from src/static/Word/Binary operators/sshl.svg rename to src/static/Word/Binary operators/$sshl.svg diff --git a/src/static/Word/Binary operators/sshr.svg b/src/static/Word/Binary operators/$sshr.svg similarity index 100% rename from src/static/Word/Binary operators/sshr.svg rename to src/static/Word/Binary operators/$sshr.svg diff --git a/src/static/Word/Binary operators/sub.svg b/src/static/Word/Binary operators/$sub.svg similarity index 100% rename from src/static/Word/Binary operators/sub.svg rename to src/static/Word/Binary operators/$sub.svg diff --git a/src/static/Word/Binary operators/xnor.svg b/src/static/Word/Binary operators/$xnor.svg similarity index 100% rename from src/static/Word/Binary operators/xnor.svg rename to src/static/Word/Binary operators/$xnor.svg diff --git a/src/static/Word/Binary operators/xor.svg b/src/static/Word/Binary operators/$xor.svg similarity index 100% rename from src/static/Word/Binary operators/xor.svg rename to src/static/Word/Binary operators/$xor.svg diff --git a/src/static/Word/Coarse arithmetics/alu.svg b/src/static/Word/Coarse arithmetics/$alu.svg similarity index 100% rename from src/static/Word/Coarse arithmetics/alu.svg rename to src/static/Word/Coarse arithmetics/$alu.svg diff --git a/src/static/Word/Coarse arithmetics/fa.svg b/src/static/Word/Coarse arithmetics/$fa.svg similarity index 100% rename from src/static/Word/Coarse arithmetics/fa.svg rename to src/static/Word/Coarse arithmetics/$fa.svg diff --git a/src/static/Word/Finite state machines/fsm.svg b/src/static/Word/Finite state machines/$fsm.svg similarity index 100% rename from src/static/Word/Finite state machines/fsm.svg rename to src/static/Word/Finite state machines/$fsm.svg diff --git a/src/static/Word/Memories/mem.svg b/src/static/Word/Memories/$mem.svg similarity index 100% rename from src/static/Word/Memories/mem.svg rename to src/static/Word/Memories/$mem.svg diff --git a/src/static/Word/Memories/mem_v2.svg b/src/static/Word/Memories/$mem_v2.svg similarity index 100% rename from src/static/Word/Memories/mem_v2.svg rename to src/static/Word/Memories/$mem_v2.svg diff --git a/src/static/Word/Memories/memrd.svg b/src/static/Word/Memories/$memrd.svg similarity index 100% rename from src/static/Word/Memories/memrd.svg rename to src/static/Word/Memories/$memrd.svg diff --git a/src/static/Word/Memories/memrd_v2.svg b/src/static/Word/Memories/$memrd_v2.svg similarity index 100% rename from src/static/Word/Memories/memrd_v2.svg rename to src/static/Word/Memories/$memrd_v2.svg diff --git a/src/static/Word/Memories/memwr.svg b/src/static/Word/Memories/$memwr.svg similarity index 100% rename from src/static/Word/Memories/memwr.svg rename to src/static/Word/Memories/$memwr.svg diff --git a/src/static/Word/Memories/memwr_v2.svg b/src/static/Word/Memories/$memwr_v2.svg similarity index 100% rename from src/static/Word/Memories/memwr_v2.svg rename to src/static/Word/Memories/$memwr_v2.svg diff --git a/src/static/Word/Multiplexers/bmux.svg b/src/static/Word/Multiplexers/$bmux.svg similarity index 100% rename from src/static/Word/Multiplexers/bmux.svg rename to src/static/Word/Multiplexers/$bmux.svg diff --git a/src/static/Word/Multiplexers/bwmux.svg b/src/static/Word/Multiplexers/$bwmux.svg similarity index 100% rename from src/static/Word/Multiplexers/bwmux.svg rename to src/static/Word/Multiplexers/$bwmux.svg diff --git a/src/static/Word/Multiplexers/demux.svg b/src/static/Word/Multiplexers/$demux.svg similarity index 100% rename from src/static/Word/Multiplexers/demux.svg rename to src/static/Word/Multiplexers/$demux.svg diff --git a/src/static/Word/Multiplexers/mux.svg b/src/static/Word/Multiplexers/$mux.svg similarity index 100% rename from src/static/Word/Multiplexers/mux.svg rename to src/static/Word/Multiplexers/$mux.svg diff --git a/src/static/Word/Multiplexers/pmux.svg b/src/static/Word/Multiplexers/$pmux.svg similarity index 100% rename from src/static/Word/Multiplexers/pmux.svg rename to src/static/Word/Multiplexers/$pmux.svg diff --git a/src/static/Word/Multiplexers/tribuf.svg b/src/static/Word/Multiplexers/$tribuf.svg similarity index 100% rename from src/static/Word/Multiplexers/tribuf.svg rename to src/static/Word/Multiplexers/$tribuf.svg diff --git a/src/static/Word/Registers/adff.svg b/src/static/Word/Registers/$adff.svg similarity index 100% rename from src/static/Word/Registers/adff.svg rename to src/static/Word/Registers/$adff.svg diff --git a/src/static/Word/Registers/adffe.svg b/src/static/Word/Registers/$adffe.svg similarity index 100% rename from src/static/Word/Registers/adffe.svg rename to src/static/Word/Registers/$adffe.svg diff --git a/src/static/Word/Registers/adlatch.svg b/src/static/Word/Registers/$adlatch.svg similarity index 100% rename from src/static/Word/Registers/adlatch.svg rename to src/static/Word/Registers/$adlatch.svg diff --git a/src/static/Word/Registers/aldff.svg b/src/static/Word/Registers/$aldff.svg similarity index 100% rename from src/static/Word/Registers/aldff.svg rename to src/static/Word/Registers/$aldff.svg diff --git a/src/static/Word/Registers/aldffe.svg b/src/static/Word/Registers/$aldffe.svg similarity index 100% rename from src/static/Word/Registers/aldffe.svg rename to src/static/Word/Registers/$aldffe.svg diff --git a/src/static/Word/Registers/dff.svg b/src/static/Word/Registers/$dff.svg similarity index 100% rename from src/static/Word/Registers/dff.svg rename to src/static/Word/Registers/$dff.svg diff --git a/src/static/Word/Registers/dffe.svg b/src/static/Word/Registers/$dffe.svg similarity index 100% rename from src/static/Word/Registers/dffe.svg rename to src/static/Word/Registers/$dffe.svg diff --git a/src/static/Word/Registers/dffsr.svg b/src/static/Word/Registers/$dffsr.svg similarity index 100% rename from src/static/Word/Registers/dffsr.svg rename to src/static/Word/Registers/$dffsr.svg diff --git a/src/static/Word/Registers/dffsre.svg b/src/static/Word/Registers/$dffsre.svg similarity index 100% rename from src/static/Word/Registers/dffsre.svg rename to src/static/Word/Registers/$dffsre.svg diff --git a/src/static/Word/Registers/dlatch.svg b/src/static/Word/Registers/$dlatch.svg similarity index 100% rename from src/static/Word/Registers/dlatch.svg rename to src/static/Word/Registers/$dlatch.svg diff --git a/src/static/Word/Registers/dlatchsr.svg b/src/static/Word/Registers/$dlatchsr.svg similarity index 100% rename from src/static/Word/Registers/dlatchsr.svg rename to src/static/Word/Registers/$dlatchsr.svg diff --git a/src/static/Word/Registers/sdff.svg b/src/static/Word/Registers/$sdff.svg similarity index 100% rename from src/static/Word/Registers/sdff.svg rename to src/static/Word/Registers/$sdff.svg diff --git a/src/static/Word/Registers/sdffce.svg b/src/static/Word/Registers/$sdffce.svg similarity index 100% rename from src/static/Word/Registers/sdffce.svg rename to src/static/Word/Registers/$sdffce.svg diff --git a/src/static/Word/Registers/sdffe.svg b/src/static/Word/Registers/$sdffe.svg similarity index 100% rename from src/static/Word/Registers/sdffe.svg rename to src/static/Word/Registers/$sdffe.svg diff --git a/src/static/Word/Registers/sr.svg b/src/static/Word/Registers/$sr.svg similarity index 100% rename from src/static/Word/Registers/sr.svg rename to src/static/Word/Registers/$sr.svg diff --git a/src/static/Word/Unary operators/buf.svg b/src/static/Word/Unary operators/$buf.svg similarity index 100% rename from src/static/Word/Unary operators/buf.svg rename to src/static/Word/Unary operators/$buf.svg diff --git a/src/static/Word/Unary operators/logic_not.svg b/src/static/Word/Unary operators/$logic_not.svg similarity index 100% rename from src/static/Word/Unary operators/logic_not.svg rename to src/static/Word/Unary operators/$logic_not.svg diff --git a/src/static/Word/Unary operators/neg.svg b/src/static/Word/Unary operators/$neg.svg similarity index 100% rename from src/static/Word/Unary operators/neg.svg rename to src/static/Word/Unary operators/$neg.svg diff --git a/src/static/Word/Unary operators/not.svg b/src/static/Word/Unary operators/$not.svg similarity index 100% rename from src/static/Word/Unary operators/not.svg rename to src/static/Word/Unary operators/$not.svg diff --git a/src/static/Word/Unary operators/pos.svg b/src/static/Word/Unary operators/$pos.svg similarity index 100% rename from src/static/Word/Unary operators/pos.svg rename to src/static/Word/Unary operators/$pos.svg diff --git a/src/static/Word/Unary operators/reduce_and.svg b/src/static/Word/Unary operators/$reduce_and.svg similarity index 100% rename from src/static/Word/Unary operators/reduce_and.svg rename to src/static/Word/Unary operators/$reduce_and.svg diff --git a/src/static/Word/Unary operators/reduce_or.svg b/src/static/Word/Unary operators/$reduce_or.svg similarity index 100% rename from src/static/Word/Unary operators/reduce_or.svg rename to src/static/Word/Unary operators/$reduce_or.svg diff --git a/src/static/Word/Unary operators/reduce_xnor.svg b/src/static/Word/Unary operators/$reduce_xnor.svg similarity index 100% rename from src/static/Word/Unary operators/reduce_xnor.svg rename to src/static/Word/Unary operators/$reduce_xnor.svg diff --git a/src/static/Word/Unary operators/reduce_xor.svg b/src/static/Word/Unary operators/$reduce_xor.svg similarity index 100% rename from src/static/Word/Unary operators/reduce_xor.svg rename to src/static/Word/Unary operators/$reduce_xor.svg diff --git a/webpack.config.js b/webpack.config.js new file mode 100644 index 0000000..f9706da --- /dev/null +++ b/webpack.config.js @@ -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: { + } + }, +}; \ No newline at end of file